Merge "msm: iommu: Enable IO-MMU support for 8660" into msm-3.0
diff --git a/Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt b/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
similarity index 94%
rename from Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt
rename to Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
index f07d3c2..dff6a3e 100644
--- a/Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
@@ -84,10 +84,6 @@
QPNP_GPIO_DTEST3 = 6,
QPNP_GPIO_DTEST4 = 7
- @inv_int_pol: Invert polarity before feeding the line to the interrupt
- module in pmic. This feature will almost be never used
- since the pm8xxx interrupt block can detect both edges
- and both levels.
@master_en: 1 = Enable features within the GPIO block based on
configurations.
0 = Completely disable the GPIO block and let the pin
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
new file mode 100644
index 0000000..002431a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -0,0 +1,24 @@
+Qualcomm LPASS QDSP6v5 Peripheral Image Loader
+
+pil-qdsp6v5-lpass is a peripheral image loader (PIL) driver. It is used for
+loading QDSP6v5 (Hexagon) firmware images for Low Power Audio Subsystems
+into memory and preparing the subsystem's processor to execute code. It's
+also responsible for shutting down the processor when it's not needed.
+
+Required properties:
+- compatible: Must be "qcom,pil-q6v5-lpass"
+- reg: Three pairs of physical base addresses and region sizes
+ of memory mapped registers. The first region corresponds
+ to QDSP6SS_PUB, the second corresponds to LPASS_CC, and
+ the third to LPASS_HALTREQ.
+- qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
+
+Example:
+ qcom,lpass@fe200000 {
+ compatible = "qcom,pil-q6v5-lpass";
+ reg = <0xfe200000 0x00100>,
+ <0xfe000000 0x40000>,
+ <0xfd485100 0x00010>;
+
+ qcom,firmware-name = "lpass";
+ };
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 284426a..4821290 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -233,7 +233,7 @@
qcom,i2c-src-freq = <24000000>;
};
- qcom,acpuclk@0xf900000 {
+ qcom,acpuclk@f9000000 {
compatible = "qcom,acpuclk-copper";
};
@@ -243,4 +243,13 @@
interrupts = <0 131 0>;
qcom,dwc-usb3-msm-dbm-eps = <4>;
};
+
+ qcom,lpass@fe200000 {
+ compatible = "qcom,pil-q6v5-lpass";
+ reg = <0xfe200000 0x00100>,
+ <0xfe000000 0x40000>,
+ <0xfd485100 0x00010>;
+
+ qcom,firmware-name = "lpass";
+ };
};
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 667b1ec..1574a54 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -116,6 +116,7 @@
CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP=y
CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MSM is not set
# CONFIG_HWMON is not set
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index d665490..df30306 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -109,8 +109,8 @@
#define L2X0_PREFETCH_CTRL_WRAP8_SHIFT 30
#ifndef __ASSEMBLY__
-extern void l2cc_suspend(void);
-extern void l2cc_resume(int collapsed);
+extern void l2x0_suspend(void);
+extern void l2x0_resume(int collapsed);
extern void l2x0_cache_sync(void);
extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 7a5b21a..dabd390 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -152,7 +152,7 @@
bool disable_bam;
bool disable_runtime_pm;
bool disable_cmd23;
- u32 swfi_latency;
+ u32 cpu_dma_latency;
};
#endif
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index de314ea..88ad1a9 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -651,6 +651,26 @@
}
}
+static int cpu_has_active_perf(void)
+{
+ int idx;
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+ if (!armpmu)
+ return 0;
+
+ for (idx = 0; idx <= armpmu->num_events; ++idx) {
+ struct perf_event *event = cpuc->events[idx];
+
+ if (event)
+ /*Even one event's existence is good enough.*/
+ return 1;
+
+ }
+
+ return 0;
+}
+
static struct pmu pmu = {
.pmu_enable = armpmu_enable,
.pmu_disable = armpmu_disable,
@@ -676,16 +696,18 @@
{
switch (cmd) {
case CPU_PM_ENTER:
- armpmu_update_counters();
- perf_pmu_disable(&pmu);
+ if (cpu_has_active_perf()) {
+ armpmu_update_counters();
+ perf_pmu_disable(&pmu);
+ }
break;
case CPU_PM_ENTER_FAILED:
case CPU_PM_EXIT:
- if (armpmu && armpmu->reset)
+ if (cpu_has_active_perf() && armpmu->reset) {
armpmu->reset(NULL);
- perf_pmu_enable(&pmu);
-
+ perf_pmu_enable(&pmu);
+ }
break;
}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 4ea24a4..ca3e459 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -239,6 +239,7 @@
select MSM_GPIOMUX
select MULTI_IRQ_HANDLER
select MSM_MULTIMEDIA_USE_ION
+ select MSM_PIL
config ARCH_FSM9XXX
bool "FSM9XXX"
@@ -1742,7 +1743,6 @@
config MSM_PIL
bool "Peripheral image loading"
select FW_LOADER
- depends on (ARCH_MSM8X60 || ARCH_MSM8960)
default n
help
Some peripherals need to be loaded into memory before they can be
@@ -1771,6 +1771,13 @@
The QDSP6 is a low power DSP used in audio, modem firmware, and modem
software applications.
+config MSM_PIL_LPASS_QDSP6V5
+ tristate "LPASS QDSP6v5 (Hexagon) Boot Support"
+ depends on MSM_PIL
+ help
+ Support for booting and shutting down QDSP6v5 processors (Hexagon)
+ processors in low power audio subsystems.
+
config MSM_PIL_RIVA
tristate "RIVA (WCNSS) Boot Support"
depends on MSM_PIL
@@ -2190,12 +2197,12 @@
For production builds, you should probably say 'N' here.
config MSM_L1_ERR_PANIC
- bool "Panic on L1 cache / TLB errors"
+ bool "Panic on L1 cache errors"
depends on MSM_CACHE_ERP
help
- To cause the kernel to panic whenever an L1 cache or TLB error is
- detected, say 'Y' here. This may be useful as a debugging technique if
- general system instability is suspected.
+ To cause the kernel to panic whenever an L1 cache error is detected, say
+ 'Y' here. This may be useful as a debugging technique if general system
+ instability is suspected.
For production builds, you should probably say 'N' here.
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f14f1ea..84af813 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -67,6 +67,7 @@
obj-$(CONFIG_MSM_PIL) += scm-pas.o
obj-$(CONFIG_MSM_PIL_QDSP6V3) += pil-q6v3.o
obj-$(CONFIG_MSM_PIL_QDSP6V4) += pil-q6v4.o
+obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
@@ -273,6 +274,7 @@
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o board-copper-gpiomux.o
obj-$(CONFIG_ARCH_MSMCOPPER) += acpuclock-krait.o acpuclock-copper.o
+obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 3723da8..2019f9b 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -598,6 +598,11 @@
.sensor_type = BAYER_SENSOR,
};
+static struct platform_device msm_camera_server = {
+ .name = "msm_cam_server",
+ .id = 0,
+};
+
void __init apq8064_init_cam(void)
{
msm_gpiomux_install(apq8064_cam_common_configs,
@@ -609,6 +614,7 @@
} else if (machine_is_apq8064_liquid())
sensor_board_info_imx074.mount_angle = 180;
+ platform_device_register(&msm_camera_server);
platform_device_register(&msm8960_device_i2c_mux_gsbi4);
platform_device_register(&msm8960_device_csiphy0);
platform_device_register(&msm8960_device_csiphy1);
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index de6e0d2..99a3fa1 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -433,33 +433,6 @@
.drv = GPIOMUX_DRV_12MA,
.pull = GPIOMUX_PULL_NONE,
};
-
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-static struct gpiomux_setting hsic_act_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting hsic_sus_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
- .dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting cyts_resout_sus_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting cyts_resout_act_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
static struct gpiomux_setting cyts_sleep_sus_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_6MA,
@@ -499,15 +472,23 @@
[GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
},
},
- { /* TS RESOUT */
- .gpio = 7,
- .settings = {
- [GPIOMUX_ACTIVE] = &cyts_resout_act_cfg,
- [GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
- },
- },
};
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct gpiomux_setting hsic_act_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting hsic_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+
static struct msm_gpiomux_config apq8064_hsic_configs[] = {
{
.gpio = 88, /*HSIC_STROBE */
@@ -828,6 +809,71 @@
},
};
+static struct gpiomux_setting mi2s_act_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mi2s_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config mpq8064_mi2s_configs[] __initdata = {
+ {
+ .gpio = 27, /* mi2s ws */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mi2s_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+ },
+ },
+ {
+ .gpio = 28, /* mi2s sclk */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mi2s_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+ },
+ },
+ {
+ .gpio = 29, /* mi2s dout3 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mi2s_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+ },
+ },
+ {
+ .gpio = 30, /* mi2s dout2 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mi2s_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+ },
+ },
+
+ {
+ .gpio = 31, /* mi2s dout1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mi2s_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+ },
+ },
+ {
+ .gpio = 32, /* mi2s dout0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mi2s_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+ },
+ },
+
+ {
+ .gpio = 33, /* mi2s mclk */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mi2s_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+ },
+ },
+};
static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
{ /* TS INTERRUPT */
.gpio = 6,
@@ -900,6 +946,28 @@
},
};
+static struct gpiomux_setting ir_suspended_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting ir_active_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config mpq8064_ir_configs[] __initdata = {
+ {
+ .gpio = 88, /* GPIO IR */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ir_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &ir_active_cfg,
+ },
+ },
+};
+
void __init apq8064_init_gpiomux(void)
{
int rc;
@@ -947,6 +1015,11 @@
" as audio is not the primary user"
" for these GPIO Pins\n", __func__);
+ if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
+ machine_is_mpq8064_dtv())
+ msm_gpiomux_install(mpq8064_mi2s_configs,
+ ARRAY_SIZE(mpq8064_mi2s_configs));
+
msm_gpiomux_install(apq8064_ext_regulator_configs,
ARRAY_SIZE(apq8064_ext_regulator_configs));
@@ -970,4 +1043,8 @@
msm_gpiomux_install(apq8064_hdmi_configs,
ARRAY_SIZE(apq8064_hdmi_configs));
+
+ if (machine_is_mpq8064_cdp())
+ msm_gpiomux_install(mpq8064_ir_configs,
+ ARRAY_SIZE(mpq8064_ir_configs));
}
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index f8aa9c0..2cab803 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -195,7 +195,7 @@
.bus_freq = 0,
},
},
- .init_level = 0,
+ .init_level = 1,
.num_levels = 4,
.set_grp_async = NULL,
.idle_timeout = HZ/10,
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 275c893..d91408a 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -271,14 +271,11 @@
apq8064_sdc3_pdata->disable_cmd23 = true;
}
}
- if (apq8064_sdc1_pdata) {
- apq8064_sdc1_pdata->swfi_latency =
- apq8064_rpm_get_swfi_latency();
+
+ if (apq8064_sdc1_pdata)
apq8064_add_sdcc(1, apq8064_sdc1_pdata);
- }
+
if (apq8064_sdc3_pdata) {
- apq8064_sdc3_pdata->swfi_latency =
- apq8064_rpm_get_swfi_latency();
if (!machine_is_apq8064_cdp()) {
apq8064_sdc3_pdata->wpswitch_gpio = 0;
apq8064_sdc3_pdata->wpswitch_polarity = 0;
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 9e3b898..5b0b9c3 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -66,6 +66,7 @@
#include <mach/msm_xo.h>
#include <mach/msm_rtb.h>
#include <sound/cs8427.h>
+#include <media/gpio-ir-recv.h>
#include "msm_watchdog.h"
#include "board-8064.h"
@@ -76,6 +77,7 @@
#include "pm.h"
#include "pm-boot.h"
#include "devices-msm8x60.h"
+#include "smd_private.h"
#define MSM_PMEM_ADSP_SIZE 0x7800000
#define MSM_PMEM_AUDIO_SIZE 0x4CF000
@@ -375,7 +377,7 @@
};
#endif
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
apq8064_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
@@ -441,6 +443,12 @@
apq8064_reserve_info.bank_size);
}
+static int apq8064_change_memory_power(u64 start, u64 size,
+ int change_type)
+{
+ return soc_change_memory_power(start, size, change_type);
+}
+
static char prim_panel_name[PANEL_NAME_MAX_LEN];
static char ext_panel_name[PANEL_NAME_MAX_LEN];
static int __init prim_display_setup(char *param)
@@ -1122,7 +1130,6 @@
};
#endif
#define CYTTSP_TS_GPIO_IRQ 6
-#define CYTTSP_TS_GPIO_RESOUT 7
#define CYTTSP_TS_GPIO_SLEEP 33
static ssize_t tma340_vkeys_show(struct kobject *kobj,
@@ -1216,7 +1223,7 @@
*/
.lp_intrvl = CY_LP_INTRVL_DFLT,
.sleep_gpio = CYTTSP_TS_GPIO_SLEEP,
- .resout_gpio = CYTTSP_TS_GPIO_RESOUT,
+ .resout_gpio = -1,
.irq_gpio = CYTTSP_TS_GPIO_IRQ,
.regulator_info = cyttsp_regulator_data,
.num_regulators = ARRAY_SIZE(cyttsp_regulator_data),
@@ -1602,19 +1609,6 @@
},
};
-uint32_t apq8064_rpm_get_swfi_latency(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
- if (msm_rpmrs_levels[i].sleep_mode ==
- MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
- return msm_rpmrs_levels[i].latency_us;
- }
-
- return 0;
-}
-
static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
.mode = MSM_PM_BOOT_CONFIG_TZ,
};
@@ -1794,6 +1788,12 @@
},
};
+static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
+ .base_addr = MSM_ACC0_BASE + 0x08,
+ .cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
+ .mask = 1UL << 13,
+};
+
static void __init apq8064_init_buses(void)
{
msm_bus_rpm_set_mt_mask();
@@ -1854,6 +1854,18 @@
},
};
+static struct gpio_ir_recv_platform_data gpio_ir_recv_pdata = {
+ .gpio_nr = 88,
+ .active_low = 1,
+};
+
+static struct platform_device gpio_ir_recv_pdev = {
+ .name = "gpio-rc-recv",
+ .dev = {
+ .platform_data = &gpio_ir_recv_pdata,
+ },
+};
+
static struct platform_device *common_devices[] __initdata = {
&apq8064_device_dmov,
#ifndef CONFIG_MSM_VCAP
@@ -1912,6 +1924,7 @@
&apq_cpudai0,
&apq_cpudai1,
&mpq_cpudai_sec_i2s_rx,
+ &mpq_cpudai_mi2s_tx,
&apq_cpudai_hdmi_rx,
&apq_cpudai_bt_rx,
&apq_cpudai_bt_tx,
@@ -1962,6 +1975,10 @@
&msm_tpiu_device,
&msm_funnel_device,
&apq8064_etm_device,
+ &apq_cpudai_slim_4_rx,
+ &apq_cpudai_slim_4_tx,
+ &msm8960_gemini_device,
+ &apq8064_iommu_domain_device,
};
static struct platform_device *sim_devices[] __initdata = {
@@ -2052,6 +2069,7 @@
#ifdef CONFIG_MSM_ROTATOR
&msm_rotator_device,
#endif
+ &gpio_ir_recv_pdev,
&mpq8064_device_ext_5v_frc_vreg,
&mpq8064_device_ext_1p2_buck_vreg,
&mpq8064_device_ext_1p8_buck_vreg,
@@ -2105,7 +2123,7 @@
};
static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
- .clk_freq = 100000,
+ .clk_freq = 384000,
.src_clk_rate = 24000000,
};
@@ -2337,6 +2355,8 @@
},
};
+#define SX150X_EXP1_INT_N PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9)
+
struct sx150x_platform_data mpq8064_sx150x_pdata[] = {
[SX150X_EXP1] = {
.gpio_base = SX150X_EXP1_GPIO_BASE,
@@ -2345,7 +2365,8 @@
.io_pulldn_ena = 0x0,
.io_open_drain_ena = 0x0,
.io_polarity = 0,
- .irq_summary = -1,
+ .irq_summary = SX150X_EXP1_INT_N,
+ .irq_base = SX150X_EXP1_IRQ_BASE,
},
[SX150X_EXP2] = {
.gpio_base = SX150X_EXP2_GPIO_BASE,
@@ -2534,6 +2555,7 @@
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);
apq8064_epm_adc_init();
}
@@ -2562,6 +2584,8 @@
static void __init apq8064_cdp_init(void)
{
+ if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
+ pr_err("meminfo_init() failed!\n");
apq8064_common_init();
if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()) {
@@ -2583,6 +2607,8 @@
if (machine_is_apq8064_mtp())
platform_device_register(&mtp_kp_pdev);
+
+ change_memory_power = &apq8064_change_memory_power;
}
MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index f62a9fb..3729385 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -86,7 +86,6 @@
void apq8064_init_fb(void);
void apq8064_allocate_fb_region(void);
void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
-uint32_t apq8064_rpm_get_swfi_latency(void);
void __init apq8064_set_display_params(char *prim_panel, char *ext_panel);
void apq8064_init_gpu(void);
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 1a7e2e1..e7992f9 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -91,6 +91,11 @@
.drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_KEEPER,
},
+ {
+ .func = GPIOMUX_FUNC_2, /*active 9*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
};
@@ -113,7 +118,7 @@
{
.gpio = 4,
.settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_ACTIVE] = &cam_settings[9],
[GPIOMUX_SUSPENDED] = &cam_settings[0],
},
},
@@ -369,16 +374,17 @@
};
static struct gpio msm8930_common_cam_gpio[] = {
- {5, GPIOF_DIR_IN, "CAMIF_MCLK"},
{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
};
static struct gpio msm8930_front_cam_gpio[] = {
+ {4, GPIOF_DIR_IN, "CAMIF_MCLK"},
{76, GPIOF_DIR_OUT, "CAM_RESET"},
};
static struct gpio msm8930_back_cam_gpio[] = {
+ {5, GPIOF_DIR_IN, "CAMIF_MCLK"},
{107, GPIOF_DIR_OUT, "CAM_RESET"},
{54, GPIOF_DIR_OUT, "CAM_STBY_N"},
};
@@ -556,11 +562,17 @@
.sensor_type = BAYER_SENSOR,
};
+static struct platform_device msm_camera_server = {
+ .name = "msm_cam_server",
+ .id = 0,
+};
+
void __init msm8930_init_cam(void)
{
msm_gpiomux_install(msm8930_cam_common_configs,
ARRAY_SIZE(msm8930_cam_common_configs));
+ platform_device_register(&msm_camera_server);
platform_device_register(&msm8960_device_csiphy0);
platform_device_register(&msm8960_device_csiphy1);
platform_device_register(&msm8960_device_csid0);
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index 7c8c64f..5ee480a 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -115,7 +115,7 @@
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 450000000,
+ .gpu_freq = 400000000,
.bus_freq = 3,
.io_fraction = 0,
},
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index f760e7b..fc89a11 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -148,7 +148,6 @@
};
VREG_CONSUMERS(S1) = {
REGULATOR_SUPPLY("8038_s1", NULL),
- REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_otg"),
REGULATOR_SUPPLY("riva_vddcx", "wcnss_wlan.0"),
};
VREG_CONSUMERS(S2) = {
@@ -192,6 +191,7 @@
};
VREG_CONSUMERS(VDD_DIG_CORNER) = {
REGULATOR_SUPPLY("vdd_dig_corner", NULL),
+ REGULATOR_SUPPLY("hsusb_vdd_dig", "msm_otg"),
};
#define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 8bbb596..24e6a79 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -116,7 +116,7 @@
#endif
#define MSM_PMEM_ADSP_SIZE 0x7800000
-#define MSM_PMEM_AUDIO_SIZE 0x2B4000
+#define MSM_PMEM_AUDIO_SIZE 0x4CF000
#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
#define MSM_PMEM_SIZE 0x4000000 /* 64 Mbytes */
#else
@@ -125,7 +125,7 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x280000
+#define MSM_PMEM_KERNEL_EBI1_SIZE 0x65000
#define MSM_ION_SF_SIZE MSM_PMEM_SIZE
#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
#define MSM_ION_MM_SIZE MSM_PMEM_ADSP_SIZE
@@ -202,7 +202,6 @@
.id = 2,
.dev = { .platform_data = &android_pmem_adsp_pdata },
};
-#endif
static struct android_pmem_platform_data android_pmem_audio_pdata = {
.name = "pmem_audio",
@@ -216,7 +215,8 @@
.id = 4,
.dev = { .platform_data = &android_pmem_audio_pdata },
};
-#endif
+#endif /* CONFIG_MSM_MULTIMEDIA_USE_ION */
+#endif /* CONFIG_ANDROID_PMEM */
#define DSP_RAM_BASE_8960 0x8da00000
#define DSP_RAM_SIZE_8960 0x1800000
@@ -287,15 +287,19 @@
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_pdata.size = pmem_size;
-#endif
android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
}
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
{
msm8930_reserve_table[p->memory_type].size += p->size;
}
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
static void __init reserve_pmem_memory(void)
{
@@ -303,10 +307,10 @@
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
reserve_memory_for(&android_pmem_adsp_pdata);
reserve_memory_for(&android_pmem_pdata);
-#endif
reserve_memory_for(&android_pmem_audio_pdata);
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
msm8930_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-#endif
+#endif /*CONFIG_ANDROID_PMEM*/
}
static int msm8930_paddr_to_memtype(unsigned int paddr)
@@ -419,7 +423,7 @@
};
#endif
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
@@ -1747,9 +1751,9 @@
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
&android_pmem_device,
&android_pmem_adsp_device,
-#endif
&android_pmem_audio_device,
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
&msm_device_bam_dmux,
&msm_fm_platform_init,
@@ -1787,6 +1791,7 @@
&msm_bus_8930_sys_fpb,
&msm_bus_8930_cpss_fpb,
&msm8960_device_cache_erp,
+ &msm8930_iommu_domain_device,
};
static struct platform_device *cdp_devices[] __initdata = {
@@ -1938,6 +1943,12 @@
.mode = MSM_PM_BOOT_CONFIG_TZ,
};
+static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
+ .base_addr = MSM_ACC0_BASE + 0x08,
+ .cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
+ .mask = 1UL << 13,
+};
+
#ifdef CONFIG_I2C
#define I2C_SURF 1
#define I2C_FFA (1 << 1)
@@ -2097,6 +2108,7 @@
ARRAY_SIZE(msm_slim_devices));
change_memory_power = &msm8930_change_memory_power;
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+ msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
if (PLATFORM_IS_CHARM25())
platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 0d1c72d..b60519b 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -681,6 +681,11 @@
return rc;
}
+static struct platform_device msm_camera_server = {
+ .name = "msm_cam_server",
+ .id = 0,
+};
+
void __init msm8960_init_cam(void)
{
msm_gpiomux_install(msm8960_cam_common_configs,
@@ -709,6 +714,7 @@
msm_camera_8960_ext_power_ctrl;
}
+ platform_device_register(&msm_camera_server);
platform_device_register(&msm8960_device_csiphy0);
platform_device_register(&msm8960_device_csiphy1);
platform_device_register(&msm8960_device_csiphy2);
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 9bf80ed..8b5c693 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -256,6 +256,7 @@
.pull = GPIOMUX_PULL_DOWN,
};
+#if defined(CONFIG_FB_MSM_HDMI_MHL_8334) || defined(CONFIG_FB_MSM_HDMI_MHL_9244)
static struct gpiomux_setting hdmi_active_3_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -270,6 +271,7 @@
.dir = GPIOMUX_OUT_HIGH,
};
#endif
+#endif
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
static struct msm_gpiomux_config msm8960_ethernet_configs[] = {
@@ -690,6 +692,7 @@
[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
},
},
+#ifdef CONFIG_FB_MSM_HDMI_MHL_9244
{
.gpio = 15,
.settings = {
@@ -704,6 +707,23 @@
[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
},
},
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
+ {
+ .gpio = 4,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_3_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 15,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_4_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+#endif /* CONFIG_FB_MSM_HDMI_MHL */
};
#endif
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index cd53f83..f39a691 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -266,12 +266,10 @@
void __init msm8960_init_mmc(void)
{
#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
- msm8960_sdc1_data.swfi_latency = msm_rpm_get_swfi_latency();
/* SDC1 : eMMC card connected */
msm_add_sdcc(1, &msm8960_sdc1_data);
#endif
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
- msm8960_sdc3_data.swfi_latency = msm_rpm_get_swfi_latency();
/* SDC3: External card slot */
msm_add_sdcc(3, &msm8960_sdc3_data);
#endif
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 6ed174c..6328ab3 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -110,6 +110,9 @@
#define KS8851_IRQ_GPIO 90
#define HAP_SHIFT_LVL_OE_GPIO 47
+#define MHL_GPIO_INT 4
+#define MHL_GPIO_RESET 15
+
#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
struct sx150x_platform_data msm8960_sx150x_data[] = {
@@ -707,7 +710,7 @@
#endif
-static void reserve_cache_dump_memory(void)
+static void __init reserve_cache_dump_memory(void)
{
#ifdef CONFIG_MSM_CACHE_DUMP
unsigned int spare;
@@ -2273,11 +2276,76 @@
},
};
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
+static void mhl_sii_reset_gpio(int on)
+{
+ gpio_set_value(MHL_GPIO_RESET, on);
+ return;
+}
+
+/*
+ * Request for GPIO allocations
+ * Set appropriate GPIO directions
+ */
+static int mhl_sii_gpio_setup(int on)
+{
+ int ret;
+
+ if (on) {
+ ret = gpio_request(MHL_GPIO_RESET, "W_RST#");
+ if (ret < 0) {
+ pr_err("GPIO RESET request failed: %d\n", ret);
+ return -EBUSY;
+ }
+ ret = gpio_direction_output(MHL_GPIO_RESET, 1);
+ if (ret < 0) {
+ pr_err("SET GPIO RESET direction failed: %d\n", ret);
+ gpio_free(MHL_GPIO_RESET);
+ return -EBUSY;
+ }
+ ret = gpio_request(MHL_GPIO_INT, "W_INT");
+ if (ret < 0) {
+ pr_err("GPIO INT request failed: %d\n", ret);
+ gpio_free(MHL_GPIO_RESET);
+ return -EBUSY;
+ }
+ ret = gpio_direction_input(MHL_GPIO_INT);
+ if (ret < 0) {
+ pr_err("SET GPIO INTR direction failed: %d\n", ret);
+ gpio_free(MHL_GPIO_RESET);
+ gpio_free(MHL_GPIO_INT);
+ return -EBUSY;
+ }
+ } else {
+ gpio_free(MHL_GPIO_RESET);
+ gpio_free(MHL_GPIO_INT);
+ }
+
+ return 0;
+}
+
+static struct msm_mhl_platform_data mhl_platform_data = {
+ .irq = MSM_GPIO_TO_INT(4),
+ .gpio_setup = mhl_sii_gpio_setup,
+ .reset_pin = mhl_sii_reset_gpio,
+};
+#endif
+
static struct i2c_board_info sii_device_info[] __initdata = {
{
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
+ /*
+ * keeps SI 8334 as the default
+ * MHL TX
+ */
+ I2C_BOARD_INFO("sii8334", 0x39),
+ .platform_data = &mhl_platform_data,
+#endif
+#ifdef CONFIG_FB_MSM_HDMI_MHL_9244
I2C_BOARD_INFO("Sil-9244", 0x39),
- .flags = I2C_CLIENT_WAKE,
.irq = MSM_GPIO_TO_INT(15),
+#endif /* CONFIG_MSM_HDMI_MHL */
+ .flags = I2C_CLIENT_WAKE,
},
};
@@ -2427,9 +2495,7 @@
}
static struct msm_serial_hs_platform_data msm_uart_dm9_pdata = {
- .inject_rx_on_wakeup = 1,
- .rx_to_inject = 0xFD,
- .gpio_config = configure_uart_gpios,
+ .gpio_config = configure_uart_gpios,
};
#else
static struct msm_serial_hs_platform_data msm_uart_dm9_pdata;
@@ -2521,6 +2587,7 @@
#ifdef CONFIG_MSM_CACHE_DUMP
&msm_cache_dump_device,
#endif
+ &msm8960_iommu_domain_device,
};
static struct platform_device *sim_devices[] __initdata = {
@@ -2756,19 +2823,6 @@
.mode = MSM_PM_BOOT_CONFIG_TZ,
};
-uint32_t msm_rpm_get_swfi_latency(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
- if (msm_rpmrs_levels[i].sleep_mode ==
- MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
- return msm_rpmrs_levels[i].latency_us;
- }
-
- return 0;
-}
-
#ifdef CONFIG_I2C
#define I2C_SURF 1
#define I2C_FFA (1 << 1)
@@ -2902,7 +2956,7 @@
ARRAY_SIZE(mxt_device_info),
},
{
- I2C_FFA | I2C_LIQUID,
+ I2C_SURF | I2C_FFA | I2C_LIQUID,
MSM_8960_GSBI10_QUP_I2C_BUS_ID,
sii_device_info,
ARRAY_SIZE(sii_device_info),
@@ -3100,8 +3154,10 @@
platform_device_register(&msm8960_device_uart_gsbi5);
/* For 8960 Fusion 2.2 Primary IPC */
- if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
+ msm_uart_dm9_pdata.wakeup_irq = gpio_to_irq(94); /* GSBI9(2) */
msm_device_uart_dm9.dev.platform_data = &msm_uart_dm9_pdata;
+ }
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8960_pm8921_gpio_mpp_init();
diff --git a/arch/arm/mach-msm/board-8960.h b/arch/arm/mach-msm/board-8960.h
index dea957c..3824cfd 100644
--- a/arch/arm/mach-msm/board-8960.h
+++ b/arch/arm/mach-msm/board-8960.h
@@ -84,7 +84,6 @@
void msm8960_set_display_params(char *prim_panel, char *ext_panel);
void msm8960_pm8921_gpio_mpp_init(void);
void msm8960_mdp_writeback(struct memtype_reserve *reserve_table);
-uint32_t msm_rpm_get_swfi_latency(void);
#define PLATFORM_IS_CHARM25() \
(machine_is_msm8960_cdp() && \
(socinfo_get_platform_subtype() == 1) \
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index c600d53..0e18918 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -105,20 +105,6 @@
};
#endif
-static struct gpiomux_setting wlan_active_config = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- .dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting wlan_suspend_config = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- .dir = GPIOMUX_IN,
-};
-
static struct msm_gpiomux_config msm9615_audio_codec_configs[] __initdata = {
{
.gpio = 24,
@@ -320,24 +306,6 @@
};
#endif
-static struct msm_gpiomux_config msm9615_wlan_configs[] __initdata = {
- {
- .gpio = 2, /* WLAN_PM_ENABLE */
- .settings = {
- [GPIOMUX_ACTIVE] = &wlan_active_config,
- [GPIOMUX_SUSPENDED] = &wlan_suspend_config,
- },
- },
- {
- .gpio = 21, /* WLAN_RESET_N */
- .settings = {
- [GPIOMUX_ACTIVE] = &wlan_active_config,
- [GPIOMUX_SUSPENDED] = &wlan_suspend_config,
- },
- },
-};
-
-
int __init msm9615_init_gpiomux(void)
{
int rc;
@@ -364,9 +332,6 @@
msm_gpiomux_install(msm9615_audio_codec_configs,
ARRAY_SIZE(msm9615_audio_codec_configs));
- msm_gpiomux_install(msm9615_wlan_configs,
- ARRAY_SIZE(msm9615_wlan_configs));
-
#ifdef CONFIG_FB_MSM_EBI2
msm_gpiomux_install(msm9615_ebi2_lcdc_configs,
ARRAY_SIZE(msm9615_ebi2_lcdc_configs));
diff --git a/arch/arm/mach-msm/board-9615-storage.c b/arch/arm/mach-msm/board-9615-storage.c
index 6bf7c69..7580cc3 100644
--- a/arch/arm/mach-msm/board-9615-storage.c
+++ b/arch/arm/mach-msm/board-9615-storage.c
@@ -214,19 +214,13 @@
void __init msm9615_init_mmc(void)
{
- if (msm9615_sdc1_pdata) {
- msm9615_sdc1_pdata->swfi_latency =
- msm9615_rpm_get_swfi_latency();
+ if (msm9615_sdc1_pdata)
/* SDC1: External card slot for SD/MMC cards */
msm_add_sdcc(1, msm9615_sdc1_pdata);
- }
- if (msm9615_sdc2_pdata) {
- msm9615_sdc2_pdata->swfi_latency =
- msm9615_rpm_get_swfi_latency();
+ if (msm9615_sdc2_pdata)
/* SDC2: External card slot used for WLAN */
msm_add_sdcc(2, msm9615_sdc2_pdata);
- }
}
#else
void __init msm9615_init_mmc(void)
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 6c6a5c2..3389dea 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -107,7 +107,7 @@
.dev = { .platform_data = &ion_pdata },
};
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
{
msm9615_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
}
@@ -132,10 +132,16 @@
ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
{"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
- ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
- {"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV2,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ /* AMUX8 is used to read either Batt_id/Batt_therm.
+ * Current configuration is to support Batt_id. If clients
+ * want to read the Batt_therm, the scaling function needs to be
+ * updated to use ADC_SCALE_BATT_THERM instead of ADC_SCALE_DEFAULT.
+ * E.g.
+ * {"batt_therm", CHANNEL_BATT_ID_THERM, CHAN_PATH_SCALING1,
+ * AMUX_RSV2, ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
+ */
+ {"batt_id", CHANNEL_BATT_ID_THERM, CHAN_PATH_SCALING1,
+ AMUX_RSV2, ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
{"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
{"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
diff --git a/arch/arm/mach-msm/board-9615.h b/arch/arm/mach-msm/board-9615.h
index 239453f..7dd003f 100644
--- a/arch/arm/mach-msm/board-9615.h
+++ b/arch/arm/mach-msm/board-9615.h
@@ -36,7 +36,6 @@
#define GPIO_VREG_ID_EXT_2P95V 0
extern struct gpio_regulator_platform_data msm_gpio_regulator_pdata[];
-uint32_t msm9615_rpm_get_swfi_latency(void);
int msm9615_init_gpiomux(void);
void msm9615_init_mmc(void);
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index 3500448..ccfc770 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -183,7 +183,7 @@
.dev = { .platform_data = &ion_pdata },
};
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
{
msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
msm_copper_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
@@ -225,7 +225,12 @@
},
{
.name = "wcnss_smsm_in",
- .start = 32 + 144, /* RicaAppsWlanSmsmIrq */
+ .start = 32 + 144, /* RivaAppsWlanSmsmIrq */
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rpm_smd_in",
+ .start = 32 + 168, /* rpm_to_kpss_ipc_irq4 */
.flags = IORESOURCE_IRQ,
},
};
@@ -300,11 +305,43 @@
.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
.smsm_int.out_offset = 0x8,
},
+ {
+ .irq_config_id = SMD_RPM,
+ .subsys_name = NULL, /* do not use PIL to load RPM */
+ .edge = SMD_APPS_RPM,
+
+ .smd_int.irq_name = "rpm_smd_in",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 0,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = NULL, /* RPM does not support SMSM */
+ .smsm_int.flags = 0,
+ .smsm_int.irq_id = 0,
+ .smsm_int.device_name = NULL,
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 0,
+ .smsm_int.out_base = NULL,
+ .smsm_int.out_offset = 0,
+ },
+};
+
+static struct smd_smem_regions aux_smem_areas[] = {
+ {
+ .phys_addr = (void *)(0xfc428000),
+ .size = 0x4000,
+ },
};
static struct smd_platform smd_platform_data = {
.num_ss_configs = ARRAY_SIZE(smd_config_list),
.smd_ss_configs = smd_config_list,
+ .num_smem_areas = ARRAY_SIZE(aux_smem_areas),
+ .smd_smem_areas = aux_smem_areas,
};
struct platform_device msm_device_smd_copper = {
@@ -380,6 +417,7 @@
}
static struct clk_lookup msm_clocks_dummy[] = {
+ CLK_DUMMY("xo", XO_CLK, NULL, OFF),
CLK_DUMMY("core_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
CLK_DUMMY("iface_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
CLK_DUMMY("core_clk", SDC1_CLK, NULL, OFF),
@@ -414,6 +452,12 @@
"spi_qsd.1", NULL),
OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
"spmi-pmic-arb.0", NULL),
+ OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF980B000, \
+ "msm_sdcc.1", NULL),
+ OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF984B000, \
+ "msm_sdcc.3", NULL),
+ OF_DEV_AUXDATA("qcom,pil-q6v5-lpass", 0xFE200000, \
+ "pil-q6v5-lpass", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index f7333b9..9d01d90 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -276,6 +276,11 @@
};
#endif
+static struct platform_device msm_camera_server = {
+ .name = "msm_cam_server",
+ .id = 0,
+};
+
static void __init msm7x27a_init_cam(void)
{
if (!(machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
@@ -291,6 +296,7 @@
sensor_board_info_ov5647.cam_vreg = NULL;
sensor_board_info_ov5647.num_vreg = 0;
}
+ platform_device_register(&msm_camera_server);
if (machine_is_msm8625_surf() || machine_is_msm8625_evb()) {
platform_device_register(&msm8625_device_csic0);
platform_device_register(&msm8625_device_csic1);
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index 8a2f53a..e622dfe 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -394,7 +394,7 @@
#endif
static struct regulator_bulk_data regs_atmel[] = {
- { .supply = "ldo2", .min_uV = 2850000, .max_uV = 2850000 },
+ { .supply = "ldo12", .min_uV = 2700000, .max_uV = 3300000 },
{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
};
@@ -579,7 +579,7 @@
},
};
-static void ft5x06_touchpad_setup(void)
+static void __init ft5x06_touchpad_setup(void)
{
int rc;
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 11d9a21..946e109 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -374,8 +374,6 @@
if (!(machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())) {
if (mmc_regulator_init(3, "emmc", 3000000))
return;
- sdc3_plat_data.swfi_latency = msm7627a_power_collapse_latency(
- MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
msm_add_sdcc(3, &sdc3_plat_data);
}
#endif
@@ -385,8 +383,6 @@
if (mmc_regulator_init(1, "mmc", 2850000))
return;
sdc1_plat_data.status_irq = MSM_GPIO_TO_INT(gpio_sdc1_hw_det);
- sdc1_plat_data.swfi_latency = msm7627a_power_collapse_latency(
- MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
msm_add_sdcc(1, &sdc1_plat_data);
#endif
/* SDIO WLAN slot */
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index b72ecd4..5c2f801 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -285,7 +285,9 @@
gpio_fail:
gpio_free(gpio_wlan_sys_rest_en);
qrd_gpio_fail:
- gpio_free(GPIO_WLAN_3V3_EN);
+ /* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
+ if (machine_is_msm7627a_qrd1())
+ gpio_free(GPIO_WLAN_3V3_EN);
reg_disable:
wlan_switch_regulators(0);
out:
@@ -322,6 +324,7 @@
}
gpio_set_value(gpio_wlan_sys_rest_en, 0);
} else {
+ gpio_request(gpio_wlan_sys_rest_en, "WLAN_DEEP_SLEEP_N");
rc = setup_wlan_gpio(on);
if (rc) {
pr_err("%s: wlan_set_gpio = %d\n", __func__, rc);
@@ -359,7 +362,9 @@
gpio_fail:
gpio_free(gpio_wlan_sys_rest_en);
qrd_gpio_fail:
- gpio_free(GPIO_WLAN_3V3_EN);
+ /* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
+ if (machine_is_msm7627a_qrd1())
+ gpio_free(GPIO_WLAN_3V3_EN);
reg_disable:
wlan_switch_regulators(0);
pr_info("WLAN power-down failed\n");
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index 68e333f..413a28c 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -103,7 +103,6 @@
#endif
void __init msm7627a_camera_init(void);
-u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode);
void __init msm7627a_add_io_devices(void);
void __init qrd7627a_add_io_devices(void);
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index c3650fa..2ed5897 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -360,26 +360,6 @@
},
};
-u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode mode)
-{
- switch (mode) {
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
- return msm7x27a_pm_data
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE].latency;
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN:
- return msm7x27a_pm_data
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN].latency;
- case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
- return msm7x27a_pm_data
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
- case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
- return msm7x27a_pm_data
- [MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
- default:
- return 0;
- }
-}
-
static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
.mode = MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS,
.p_addr = 0,
@@ -587,8 +567,8 @@
(DEC4_FORMAT),
/* Concurrency 6 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
0, 0, 0,
/* Concurrency 7 */
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 3973bd1..7fa4968 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -993,8 +993,14 @@
.camera_type = BACK_CAMERA_2D,
};
+static struct platform_device msm_camera_server = {
+ .name = "msm_cam_server",
+ .id = 0,
+};
+
void __init msm7x30_init_cam(void)
{
+ platform_device_register(&msm_camera_server);
platform_device_register(&msm_device_csic0);
platform_device_register(&msm_device_vfe);
platform_device_register(&msm_device_vpe);
@@ -3173,26 +3179,6 @@
},
};
-u32 msm7x30_power_collapse_latency(enum msm_pm_sleep_mode mode)
-{
- switch (mode) {
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
- return msm_pm_data
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE].latency;
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN:
- return msm_pm_data
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN].latency;
- case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
- return msm_pm_data
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
- case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
- return msm_pm_data
- [MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
- default:
- return 0;
- }
-}
-
static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
.mode = MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT,
.v_addr = (uint32_t *)PAGE_OFFSET,
@@ -6401,8 +6387,6 @@
#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
if (mmc_regulator_init(1, "s3", 1800000))
goto out1;
- msm7x30_sdc1_data.swfi_latency = msm7x30_power_collapse_latency(
- MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
if (machine_is_msm7x30_fluid()) {
msm7x30_sdc1_data.ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29;
@@ -6418,8 +6402,6 @@
#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
if (mmc_regulator_init(2, "s3", 1800000))
goto out2;
- msm7x30_sdc2_data.swfi_latency = msm7x30_power_collapse_latency(
- MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
if (machine_is_msm8x55_svlte_surf())
msm7x30_sdc2_data.msmsdcc_fmax = 24576000;
@@ -6435,8 +6417,6 @@
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
if (mmc_regulator_init(3, "s3", 1800000))
goto out3;
- msm7x30_sdc3_data.swfi_latency = msm7x30_power_collapse_latency(
- MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
msm_sdcc_setup_gpio(3, 1);
msm_add_sdcc(3, &msm7x30_sdc3_data);
@@ -6445,8 +6425,6 @@
#ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
if (mmc_regulator_init(4, "mmc", 2850000))
return;
- msm7x30_sdc4_data.swfi_latency = msm7x30_power_collapse_latency(
- MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
msm_add_sdcc(4, &msm7x30_sdc4_data);
#endif
diff --git a/arch/arm/mach-msm/board-msm8x60-camera.c b/arch/arm/mach-msm/board-msm8x60-camera.c
index c12dce6..743ca4d 100644
--- a/arch/arm/mach-msm/board-msm8x60-camera.c
+++ b/arch/arm/mach-msm/board-msm8x60-camera.c
@@ -413,14 +413,14 @@
static struct i2c_board_info imx074_actuator_i2c_info = {
- I2C_BOARD_INFO("imx074_act", 0x11),
+ I2C_BOARD_INFO("msm_actuator", 0x11),
};
static struct msm_actuator_info imx074_actuator_info = {
.board_info = &imx074_actuator_i2c_info,
+ .cam_name = MSM_ACTUATOR_MAIN_CAM_0,
.bus_id = MSM_GSBI4_QUP_I2C_BUS_ID,
- .vcm_pwd = 0,
- .vcm_enable = 1,
+ .vcm_enable = 0,
};
static struct msm_camera_sensor_flash_data flash_imx074 = {
@@ -431,7 +431,7 @@
};
static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
- .mount_angle = 0,
+ .mount_angle = 180,
.cam_vreg = msm_8x60_back_cam_vreg,
.num_vreg = ARRAY_SIZE(msm_8x60_back_cam_vreg),
.gpio_conf = &msm_8x60_back_cam_gpio_conf,
@@ -448,8 +448,14 @@
.actuator_info = &imx074_actuator_info
};
+static struct platform_device msm_camera_server = {
+ .name = "msm_cam_server",
+ .id = 0,
+};
+
void __init msm8x60_init_cam(void)
{
+ platform_device_register(&msm_camera_server);
platform_device_register(&msm_device_csic0);
platform_device_register(&msm_device_csic1);
platform_device_register(&msm_device_vfe);
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index da362a0..5fc17df 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -5409,7 +5409,7 @@
},
};
-static void reserve_ion_memory(void)
+static void __init reserve_ion_memory(void)
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
unsigned int i;
@@ -7275,7 +7275,7 @@
};
#endif /* CONFIG_I2C */
-static void fixup_i2c_configs(void)
+static void __init fixup_i2c_configs(void)
{
#ifdef CONFIG_I2C
#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
@@ -7293,7 +7293,7 @@
#endif
}
-static void register_i2c_devices(void)
+static void __init register_i2c_devices(void)
{
#ifdef CONFIG_I2C
u8 mach_mask = 0;
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 3e8dd8f..86bf205 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -510,8 +510,8 @@
(DEC4_FORMAT),
/* Concurrency 6 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
0, 0, 0,
/* Concurrency 7 */
@@ -806,7 +806,7 @@
msm_num_footswitch_devices);
}
-static void add_platform_devices(void)
+static void __init add_platform_devices(void)
{
if (machine_is_msm8625_evb() || machine_is_msm8625_qrd7()) {
platform_add_devices(msm8625_evb_devices,
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index 1eb229a..97225ac 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -17,7 +17,11 @@
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/cpu.h>
+#include <linux/io.h>
#include <mach/msm-krait-l2-accessors.h>
+#include <mach/msm_iomap.h>
+#include <asm/cputype.h>
+#include "acpuclock.h"
#define CESR_DCTPE BIT(0)
#define CESR_DCDPE BIT(1)
@@ -28,6 +32,9 @@
#define CESR_TLBMH BIT(16)
#define CESR_I_MASK 0x000000CC
+/* Print a message for everything but TLB MH events */
+#define CESR_PRINT_MASK 0x000000FF
+
#define L2ESR_IND_ADDR 0x204
#define L2ESYNR0_IND_ADDR 0x208
#define L2ESYNR1_IND_ADDR 0x209
@@ -190,9 +197,26 @@
struct msm_l1_err_stats *l1_stats = dev_id;
unsigned int cesr = read_cesr();
unsigned int i_cesynr, d_cesynr;
+ unsigned int cpu = smp_processor_id();
+ int print_regs = cesr & CESR_PRINT_MASK;
- pr_alert("L1 Error detected on CPU %d!\n", smp_processor_id());
- pr_alert("\tCESR = 0x%08x\n", cesr);
+ void *const saw_bases[] = {
+ MSM_SAW0_BASE,
+ MSM_SAW1_BASE,
+ MSM_SAW2_BASE,
+ MSM_SAW3_BASE,
+ };
+
+ if (print_regs) {
+ pr_alert("L1 / TLB Error detected on CPU %d!\n", cpu);
+ pr_alert("\tCESR = 0x%08x\n", cesr);
+ pr_alert("\tCPU speed = %lu\n", acpuclk_get_rate(cpu));
+ pr_alert("\tMIDR = 0x%08x\n", read_cpuid_id());
+ pr_alert("\tPTE fuses = 0x%08x\n",
+ readl_relaxed(MSM_QFPROM_BASE + 0xC0));
+ pr_alert("\tPMIC_VREG = 0x%08x\n",
+ readl_relaxed(saw_bases[cpu] + 0x14));
+ }
if (cesr & CESR_DCTPE) {
pr_alert("D-cache tag parity error\n");
@@ -225,7 +249,7 @@
}
if (cesr & CESR_TLBMH) {
- pr_alert("TLB multi-hit error\n");
+ asm ("mcr p15, 0, r0, c8, c7, 0");
l1_stats->tlbmh++;
}
@@ -250,7 +274,8 @@
/* Clear the interrupt bits we processed */
write_cesr(cesr);
- ERP_L1_ERR("L1 cache / TLB error detected");
+ if (print_regs)
+ ERP_L1_ERR("L1 cache error detected");
return IRQ_HANDLED;
}
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 5951734..5ba3577 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -157,8 +157,6 @@
.ns_val = N8(nmsb, nlsb, m, n) | SPDIV(SRC_SEL_##s, div), \
}
-static struct clk_ops clk_ops_rcg_7x30;
-
enum vdd_dig_levels {
VDD_DIG_NONE,
VDD_DIG_LOW,
@@ -324,8 +322,6 @@
},
};
-static struct clk_ops clk_ops_branch;
-
static struct clk_freq_tbl clk_tbl_axi[] = {
F_RAW(1, &lpxo_clk.c, 0, 0, 0, NULL),
F_END,
@@ -344,7 +340,7 @@
.set_rate = set_rate_nop,
.c = {
.dbg_name = "glbl_root_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 1),
CLK_INIT(glbl_root_clk.c),
},
@@ -1011,7 +1007,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "csi0_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 384000000),
CLK_INIT(csi0_clk.c),
},
@@ -1036,7 +1032,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "i2c_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
CLK_INIT(i2c_clk.c),
},
@@ -1056,7 +1052,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "i2c_2_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
CLK_INIT(i2c_2_clk.c),
},
@@ -1076,7 +1072,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "qup_i2c_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
CLK_INIT(qup_i2c_clk.c),
},
@@ -1096,7 +1092,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "uart1_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
CLK_INIT(uart1_clk.c),
},
@@ -1116,7 +1112,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "uart2_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 19200000),
CLK_INIT(uart2_clk.c),
},
@@ -1156,7 +1152,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "uart1dm_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 64000000),
CLK_INIT(uart1dm_clk.c),
},
@@ -1180,7 +1176,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "uart2dm_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 64000000),
CLK_INIT(uart2dm_clk.c),
},
@@ -1214,7 +1210,7 @@
.c = {
.dbg_name = "emdh_clk",
.flags = CLKFLAG_MIN | CLKFLAG_MAX,
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 445500000),
CLK_INIT(emdh_clk.c),
.depends = &axi_li_adsp_a_clk.c,
@@ -1236,7 +1232,7 @@
.c = {
.dbg_name = "pmdh_clk",
.flags = CLKFLAG_MIN | CLKFLAG_MAX,
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 445500000),
CLK_INIT(pmdh_clk.c),
.depends = &axi_li_adsp_a_clk.c,
@@ -1281,7 +1277,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "grp_2d_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(NOMINAL, 192000000, HIGH, 245760000),
CLK_INIT(grp_2d_clk.c),
.depends = &axi_grp_2d_clk.c,
@@ -1301,7 +1297,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "grp_3d_src_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(NOMINAL, 192000000, HIGH, 245760000),
CLK_INIT(grp_3d_src_clk.c),
.depends = &axi_li_grp_clk.c,
@@ -1370,7 +1366,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "sdc1_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 49152000),
CLK_INIT(sdc1_clk.c),
},
@@ -1394,7 +1390,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "sdc3_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 49152000),
CLK_INIT(sdc3_clk.c),
},
@@ -1430,7 +1426,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "sdc2_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 49152000),
CLK_INIT(sdc2_clk.c),
},
@@ -1454,7 +1450,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "sdc4_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 49152000),
CLK_INIT(sdc4_clk.c),
},
@@ -1489,7 +1485,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mdp_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(NOMINAL, 153600000, HIGH, 192000000),
CLK_INIT(mdp_clk.c),
.depends = &axi_mdp_clk.c,
@@ -1524,7 +1520,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mdp_lcdc_pclk_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 73728000),
CLK_INIT(mdp_lcdc_pclk_clk.c),
},
@@ -1567,7 +1563,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mdp_vsync_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 24576000),
CLK_INIT(mdp_vsync_clk.c),
},
@@ -1598,7 +1594,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mi2s_codec_rx_m_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 12288000),
CLK_INIT(mi2s_codec_rx_m_clk.c),
},
@@ -1638,7 +1634,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mi2s_codec_tx_m_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 12288000),
CLK_INIT(mi2s_codec_tx_m_clk.c),
},
@@ -1684,7 +1680,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mi2s_m_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 12288000),
CLK_INIT(mi2s_m_clk.c),
},
@@ -1745,7 +1741,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "sdac_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 1536000),
CLK_INIT(sdac_clk.c),
},
@@ -1789,7 +1785,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "tv_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 74250000),
CLK_INIT(tv_clk.c),
},
@@ -1881,7 +1877,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "usb_hs_src_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
CLK_INIT(usb_hs_src_clk.c),
.depends = &axi_li_adsp_a_clk.c,
@@ -2018,7 +2014,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "jpeg_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(NOMINAL, 153600000, HIGH, 192000000),
CLK_INIT(jpeg_clk.c),
.depends = &axi_li_jpeg_clk.c,
@@ -2043,7 +2039,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "vfe_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(NOMINAL, 153600000, HIGH, 192000000),
CLK_INIT(vfe_clk.c),
.depends = &axi_li_vfe_clk.c,
@@ -2128,7 +2124,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "cam_m_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 64000000),
CLK_INIT(cam_m_clk.c),
},
@@ -2163,7 +2159,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "vpe_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 153600000),
CLK_INIT(vpe_clk.c),
.depends = &axi_vpe_clk.c,
@@ -2200,7 +2196,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "mfc_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 170667000),
CLK_INIT(mfc_clk.c),
.depends = &axi_mfc_clk.c,
@@ -2249,7 +2245,7 @@
.set_rate = set_rate_mnd,
.c = {
.dbg_name = "spi_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 26331429),
CLK_INIT(spi_clk.c),
},
@@ -2278,7 +2274,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "lpa_codec_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 4),
CLK_INIT(lpa_codec_clk.c),
},
@@ -2304,7 +2300,7 @@
.set_rate = set_rate_nop,
.c = {
.dbg_name = "mdc_clk",
- .ops = &clk_ops_rcg_7x30,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 1),
CLK_INIT(mdc_clk.c),
},
@@ -2800,8 +2796,8 @@
OWN(APPS1, 6, "iface_clk", grp_2d_p_clk, "kgsl-2d0.0"),
OWN(APPS1, 6, "iface_clk", grp_2d_p_clk, "footswitch-pcom.0"),
OWN(APPS1, 31, "hdmi_clk", hdmi_clk, "dtv.0"),
- OWN(APPS1, 0, "jpeg_clk", jpeg_clk, NULL),
- OWN(APPS1, 0, "jpeg_pclk", jpeg_p_clk, NULL),
+ OWN(APPS1, 0, "jpeg_clk", jpeg_clk, "msm_gemini.0"),
+ OWN(APPS1, 0, "jpeg_pclk", jpeg_p_clk, "msm_gemini.0"),
OWN(APPS1, 23, "lpa_codec_clk", lpa_codec_clk, NULL),
OWN(APPS1, 23, "lpa_core_clk", lpa_core_clk, NULL),
OWN(APPS1, 23, "lpa_pclk", lpa_p_clk, NULL),
@@ -2975,6 +2971,10 @@
int i;
uint32_t val;
+ clk_ops_branch.reset = soc_branch_clk_reset;
+ clk_ops_rcg.reset = msm7x30_clk_reset;
+ clk_ops_rcg.set_flags = soc_clk_set_flags;
+
cache_ownership();
print_ownership();
set_clock_ownership();
@@ -3015,29 +3015,3 @@
.pre_init = msm7x30_clock_pre_init,
.post_init = msm7x30_clock_post_init,
};
-
-/*
- * Clock operation handler registration
- */
-static struct clk_ops clk_ops_rcg_7x30 = {
- .enable = rcg_clk_enable,
- .disable = rcg_clk_disable,
- .auto_off = rcg_clk_disable,
- .set_rate = rcg_clk_set_rate,
- .list_rate = rcg_clk_list_rate,
- .is_enabled = rcg_clk_is_enabled,
- .round_rate = rcg_clk_round_rate,
- .reset = msm7x30_clk_reset,
- .set_flags = soc_clk_set_flags,
- .get_parent = rcg_clk_get_parent,
-};
-
-static struct clk_ops clk_ops_branch = {
- .enable = branch_clk_enable,
- .disable = branch_clk_disable,
- .auto_off = branch_clk_disable,
- .is_enabled = branch_clk_is_enabled,
- .reset = soc_branch_clk_reset,
- .set_flags = soc_clk_set_flags,
- .get_parent = branch_clk_get_parent,
-};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index aa25103..0997e8bd 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -556,41 +556,6 @@
},
};
-static struct clk_ops clk_ops_rcg_8960 = {
- .enable = rcg_clk_enable,
- .disable = rcg_clk_disable,
- .enable_hwcg = rcg_clk_enable_hwcg,
- .disable_hwcg = rcg_clk_disable_hwcg,
- .in_hwcg_mode = rcg_clk_in_hwcg_mode,
- .auto_off = rcg_clk_disable,
- .handoff = rcg_clk_handoff,
- .set_rate = rcg_clk_set_rate,
- .list_rate = rcg_clk_list_rate,
- .is_enabled = rcg_clk_is_enabled,
- .round_rate = rcg_clk_round_rate,
- .reset = rcg_clk_reset,
- .get_parent = rcg_clk_get_parent,
- .set_flags = rcg_clk_set_flags,
-};
-
-static struct clk_ops clk_ops_branch = {
- .enable = branch_clk_enable,
- .disable = branch_clk_disable,
- .enable_hwcg = branch_clk_enable_hwcg,
- .disable_hwcg = branch_clk_disable_hwcg,
- .in_hwcg_mode = branch_clk_in_hwcg_mode,
- .auto_off = branch_clk_disable,
- .is_enabled = branch_clk_is_enabled,
- .reset = branch_clk_reset,
- .get_parent = branch_clk_get_parent,
- .handoff = branch_clk_handoff,
- .set_flags = branch_clk_set_flags,
-};
-
-static struct clk_ops clk_ops_reset = {
- .reset = branch_clk_reset,
-};
-
/* AXI Interfaces */
static struct branch_clk gmem_axi_clk = {
.b = {
@@ -1238,7 +1203,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -1288,7 +1253,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -1352,7 +1317,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 24000000, NOMINAL, 52000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -1420,7 +1385,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "pdm_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 27000000),
CLK_INIT(pdm_clk.c),
},
@@ -1465,7 +1430,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "prng_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
CLK_INIT(prng_clk.c),
},
@@ -1491,7 +1456,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #name, \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, fmax_low, NOMINAL, fmax_nom), \
CLK_INIT(name.c), \
}, \
@@ -1554,7 +1519,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "tsif_ref_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 27000000, NOMINAL, 54000000),
CLK_INIT(tsif_ref_clk.c),
},
@@ -1586,7 +1551,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "tssc_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 27000000),
CLK_INIT(tssc_clk.c),
},
@@ -1612,7 +1577,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #name, \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP1(NOMINAL, 64000000), \
CLK_INIT(name.c), \
}, \
@@ -1658,7 +1623,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hsic_xcvr_fs_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 60000000),
CLK_INIT(usb_hsic_xcvr_fs_clk.c),
},
@@ -1702,7 +1667,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hsic_hsic_src_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 480000000),
CLK_INIT(usb_hsic_hsic_src_clk.c),
},
@@ -1745,7 +1710,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hsic_hsio_cal_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 10000000),
CLK_INIT(usb_hsic_hsio_cal_clk.c),
},
@@ -1779,7 +1744,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP1(NOMINAL, fmax_nom), \
CLK_INIT(i##_clk.c), \
}, \
@@ -1913,7 +1878,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "ce3_src_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
CLK_INIT(ce3_src_clk.c),
},
@@ -2504,7 +2469,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #name, \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 64000000, NOMINAL, 128000000), \
CLK_INIT(name.c), \
}, \
@@ -2569,7 +2534,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "csi0_src_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi0_src_clk.c),
},
@@ -2625,7 +2590,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "csi1_src_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi1_src_clk.c),
},
@@ -2681,7 +2646,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "csi2_src_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi2_src_clk.c),
},
@@ -3011,7 +2976,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "csiphy_timer_src_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csiphy_timer_src_clk.c),
},
@@ -3099,7 +3064,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "dsi1_byte_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
CLK_INIT(dsi1_byte_clk.c),
},
};
@@ -3123,7 +3088,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "dsi2_byte_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
CLK_INIT(dsi2_byte_clk.c),
},
};
@@ -3144,7 +3109,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "dsi1_esc_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
CLK_INIT(dsi1_esc_clk.c),
},
};
@@ -3164,7 +3129,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "dsi2_esc_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
CLK_INIT(dsi2_esc_clk.c),
},
};
@@ -3231,7 +3196,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "gfx2d0_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(gfx2d0_clk.c),
@@ -3275,7 +3240,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "gfx2d1_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(gfx2d1_clk.c),
@@ -3403,7 +3368,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "gfx3d_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 128000000, NOMINAL, 300000000,
HIGH, 400000000),
CLK_INIT(gfx3d_clk.c),
@@ -3465,7 +3430,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "vcap_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
.depends = &vcap_axi_clk.c,
VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
CLK_INIT(vcap_clk.c),
@@ -3540,7 +3505,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "ijpeg_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 266667000,
HIGH, 320000000),
CLK_INIT(ijpeg_clk.c),
@@ -3583,7 +3548,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "jpegd_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 96000000, NOMINAL, 200000000),
CLK_INIT(jpegd_clk.c),
.depends = &jpegd_axi_clk.c,
@@ -3660,7 +3625,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mdp_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 96000000, NOMINAL, 200000000),
CLK_INIT(mdp_clk.c),
.depends = &mdp_axi_clk.c,
@@ -3711,7 +3676,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mdp_vsync_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 27000000),
CLK_INIT(mdp_vsync_clk.c),
},
@@ -3772,7 +3737,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "rot_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 96000000, NOMINAL, 200000000),
CLK_INIT(rot_clk.c),
.depends = &rot_axi_clk.c,
@@ -3883,7 +3848,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "tv_src_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 27030000, NOMINAL, 149000000),
CLK_INIT(tv_src_clk.c),
},
@@ -4075,7 +4040,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "vcodec_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(vcodec_clk.c),
@@ -4121,7 +4086,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "vpe_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 76800000, NOMINAL, 160000000),
CLK_INIT(vpe_clk.c),
.depends = &vpe_axi_clk.c,
@@ -4187,7 +4152,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "vfe_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 266667000,
HIGH, 320000000),
CLK_INIT(vfe_clk.c),
@@ -4259,7 +4224,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP1(LOW, 24576000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -4285,7 +4250,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP1(LOW, 24576000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -4361,7 +4326,7 @@
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
}
static struct clk_freq_tbl clk_tbl_pcm[] = {
- F_PCM( 0, gnd, 1, 0, 0),
+ { .ns_val = BIT(10) /* external input */ },
F_PCM( 512000, pll4, 4, 1, 192),
F_PCM( 768000, pll4, 4, 1, 128),
F_PCM( 1024000, pll4, 4, 1, 96),
@@ -4389,14 +4354,14 @@
.ns_reg = LCC_PCM_NS_REG,
.md_reg = LCC_PCM_MD_REG,
.root_en_mask = BIT(9),
- .ns_mask = (BM(31, 16) | BM(6, 0)),
+ .ns_mask = BM(31, 16) | BIT(10) | BM(6, 0),
.mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_pcm,
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "pcm_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 24576000),
CLK_INIT(pcm_clk.c),
},
@@ -4422,7 +4387,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "audio_slimbus_clk",
- .ops = &clk_ops_rcg_8960,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 24576000),
CLK_INIT(audio_slimbus_clk.c),
},
@@ -5047,8 +5012,8 @@
CLK_LOOKUP("vcap_npl_clk", vcap_npl_clk.c, ""),
CLK_LOOKUP("vcap_npl_clk", vcap_npl_clk.c, "msm_vcap.0"),
CLK_LOOKUP("bus_clk", ijpeg_axi_clk.c, "footswitch-8x60.3"),
- CLK_LOOKUP("mem_clk", imem_axi_clk.c, ""),
- CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, ""),
+ CLK_LOOKUP("imem_clk", imem_axi_clk.c, "msm_gemini.0"),
+ CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, "msm_gemini.0"),
CLK_LOOKUP("core_clk", ijpeg_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("core_clk", jpegd_clk.c, ""),
CLK_LOOKUP("core_clk", mdp_clk.c, "mdp.0"),
@@ -5093,7 +5058,7 @@
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, "hdmi_msm.1"),
CLK_LOOKUP("slave_iface_clk", hdmi_s_p_clk.c, "hdmi_msm.1"),
- CLK_LOOKUP("ijpeg_pclk", ijpeg_p_clk.c, ""),
+ CLK_LOOKUP("ijpeg_pclk", ijpeg_p_clk.c, "msm_gemini.0"),
CLK_LOOKUP("iface_clk", ijpeg_p_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("iface_clk", jpegd_p_clk.c, ""),
CLK_LOOKUP("mem_iface_clk", imem_p_clk.c, "kgsl-3d0.0"),
@@ -5111,6 +5076,8 @@
CLK_LOOKUP("bit_clk", mi2s_bit_clk.c, "msm-dai-q6.6"),
CLK_LOOKUP("osr_clk", mi2s_osr_clk.c, "msm-dai-q6.6"),
+ CLK_LOOKUP("bit_clk", mi2s_bit_clk.c, "msm-dai-q6.7"),
+ CLK_LOOKUP("osr_clk", mi2s_osr_clk.c, "msm-dai-q6.7"),
CLK_LOOKUP("bit_clk", codec_i2s_mic_bit_clk.c,
"msm-dai-q6.1"),
CLK_LOOKUP("osr_clk", codec_i2s_mic_osr_clk.c,
@@ -5175,6 +5142,11 @@
CLK_LOOKUP("core_clk", gfx3d_axi_clk_8064.c, "msm_iommu.10"),
CLK_LOOKUP("core_clk", vcap_axi_clk.c, "msm_iommu.11"),
+ CLK_LOOKUP("mdp_iommu_clk", mdp_axi_clk.c, "msm_vidc.0"),
+ CLK_LOOKUP("rot_iommu_clk", rot_axi_clk.c, "msm_vidc.0"),
+ CLK_LOOKUP("vcodec_iommu0_clk", vcodec_axi_a_clk.c, "msm_vidc.0"),
+ CLK_LOOKUP("vcodec_iommu1_clk", vcodec_axi_b_clk.c, "msm_vidc.0"),
+ CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c, "msm_vidc.0"),
CLK_LOOKUP("core_clk", vcodec_axi_clk.c, "pil_vidc"),
CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c, "pil_vidc"),
@@ -5349,8 +5321,8 @@
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("bus_clk", ijpeg_axi_clk.c, "footswitch-8x60.3"),
- CLK_LOOKUP("imem_clk", imem_axi_clk.c, NULL),
- CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, NULL),
+ CLK_LOOKUP("imem_clk", imem_axi_clk.c, "msm_gemini.0"),
+ CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, "msm_gemini.0"),
CLK_LOOKUP("core_clk", ijpeg_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("core_clk", jpegd_clk.c, ""),
CLK_LOOKUP("core_clk", mdp_clk.c, "mdp.0"),
@@ -5402,7 +5374,7 @@
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, "hdmi_msm.1"),
CLK_LOOKUP("slave_iface_clk", hdmi_s_p_clk.c, "hdmi_msm.1"),
- CLK_LOOKUP("ijpeg_pclk", ijpeg_p_clk.c, NULL),
+ CLK_LOOKUP("ijpeg_pclk", ijpeg_p_clk.c, "msm_gemini.0"),
CLK_LOOKUP("iface_clk", ijpeg_p_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("iface_clk", jpegd_p_clk.c, ""),
CLK_LOOKUP("mem_iface_clk", imem_p_clk.c, "kgsl-3d0.0"),
@@ -5420,6 +5392,8 @@
CLK_LOOKUP("iface_clk", vpe_p_clk.c, "footswitch-8x60.9"),
CLK_LOOKUP("bit_clk", mi2s_bit_clk.c, "msm-dai-q6.6"),
CLK_LOOKUP("osr_clk", mi2s_osr_clk.c, "msm-dai-q6.6"),
+ CLK_LOOKUP("bit_clk", mi2s_bit_clk.c, "msm-dai-q6.7"),
+ CLK_LOOKUP("osr_clk", mi2s_osr_clk.c, "msm-dai-q6.7"),
CLK_LOOKUP("bit_clk", codec_i2s_mic_bit_clk.c,
"msm-dai-q6.1"),
CLK_LOOKUP("osr_clk", codec_i2s_mic_osr_clk.c,
@@ -5600,7 +5574,7 @@
CLK_LOOKUP("core_clk", pmic_ssbi2_clk.c, ""),
CLK_LOOKUP("mem_clk", rpm_msg_ram_p_clk.c, ""),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-001a"),
- CLK_LOOKUP("cam_clk", cam0_clk.c, "4-006c"),
+ CLK_LOOKUP("cam_clk", cam1_clk.c, "4-006c"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0048"),
CLK_LOOKUP("cam_clk", cam2_clk.c, NULL),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0020"),
@@ -5638,8 +5612,8 @@
CLK_LOOKUP("bus_clk",
gfx3d_axi_clk_8930.c, "footswitch-8x60.2"),
CLK_LOOKUP("bus_clk", ijpeg_axi_clk.c, "footswitch-8x60.3"),
- CLK_LOOKUP("imem_clk", imem_axi_clk.c, NULL),
- CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, NULL),
+ CLK_LOOKUP("imem_clk", imem_axi_clk.c, "msm_gemini.0"),
+ CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, "msm_gemini.0"),
CLK_LOOKUP("core_clk", ijpeg_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("core_clk", mdp_clk.c, "mdp.0"),
CLK_LOOKUP("core_clk", mdp_clk.c, "footswitch-8x60.4"),
@@ -5682,7 +5656,7 @@
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, "hdmi_msm.1"),
CLK_LOOKUP("slave_iface_clk", hdmi_s_p_clk.c, "hdmi_msm.1"),
- CLK_LOOKUP("ijpeg_pclk", ijpeg_p_clk.c, NULL),
+ CLK_LOOKUP("ijpeg_pclk", ijpeg_p_clk.c, "msm_gemini.0"),
CLK_LOOKUP("iface_clk", ijpeg_p_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("mem_iface_clk", imem_p_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("iface_clk", mdp_p_clk.c, "mdp.0"),
@@ -6088,10 +6062,10 @@
* The halt status bits for these clocks may be incorrect at boot.
* Toggle these clocks on and off to refresh them.
*/
- rcg_clk_enable(&pdm_clk.c);
- rcg_clk_disable(&pdm_clk.c);
- rcg_clk_enable(&tssc_clk.c);
- rcg_clk_disable(&tssc_clk.c);
+ clk_prepare_enable(&pdm_clk.c);
+ clk_disable_unprepare(&pdm_clk.c);
+ clk_prepare_enable(&tssc_clk.c);
+ clk_disable_unprepare(&tssc_clk.c);
clk_prepare_enable(&usb_hsic_hsic_clk.c);
clk_disable_unprepare(&usb_hsic_hsic_clk.c);
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 53dbebe..26ccaa3 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -431,34 +431,6 @@
writel_relaxed(pll_mode, MM_PLL2_MODE_REG);
}
-static struct clk_ops clk_ops_rcg_8x60 = {
- .enable = rcg_clk_enable,
- .disable = rcg_clk_disable,
- .auto_off = rcg_clk_disable,
- .handoff = rcg_clk_handoff,
- .set_rate = rcg_clk_set_rate,
- .list_rate = rcg_clk_list_rate,
- .is_enabled = rcg_clk_is_enabled,
- .round_rate = rcg_clk_round_rate,
- .reset = rcg_clk_reset,
- .get_parent = rcg_clk_get_parent,
- .set_flags = rcg_clk_set_flags,
-};
-
-static struct clk_ops clk_ops_branch = {
- .enable = branch_clk_enable,
- .disable = branch_clk_disable,
- .auto_off = branch_clk_disable,
- .is_enabled = branch_clk_is_enabled,
- .reset = branch_clk_reset,
- .get_parent = branch_clk_get_parent,
- .set_flags = branch_clk_set_flags,
-};
-
-static struct clk_ops clk_ops_reset = {
- .reset = branch_clk_reset,
-};
-
/*
* Clock Descriptions
*/
@@ -965,7 +937,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8x60, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP1(LOW, 27000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -1010,7 +982,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8x60, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -1074,7 +1046,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8x60, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 24000000, NOMINAL, 52000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -1142,7 +1114,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "pdm_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 27000000),
CLK_INIT(pdm_clk.c),
},
@@ -1185,7 +1157,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "prng_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
CLK_INIT(prng_clk.c),
},
@@ -1211,7 +1183,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8x60, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -1271,7 +1243,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "tsif_ref_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
CLK_INIT(tsif_ref_clk.c),
},
};
@@ -1302,7 +1274,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "tssc_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 27000000),
CLK_INIT(tssc_clk.c),
},
@@ -1340,7 +1312,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hs1_xcvr_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
CLK_INIT(usb_hs1_xcvr_clk.c),
},
@@ -1374,7 +1346,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8x60, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP1(NOMINAL, 60000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -2001,7 +1973,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "cam_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 64000000, NOMINAL, 128000000),
CLK_INIT(cam_clk.c),
},
@@ -2033,7 +2005,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "csi_src_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 192000000, NOMINAL, 384000000),
CLK_INIT(csi_src_clk.c),
},
@@ -2107,7 +2079,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "dsi_byte_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
CLK_INIT(dsi_byte_clk.c),
},
};
@@ -2188,7 +2160,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "gfx2d0_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(gfx2d0_clk.c),
@@ -2232,7 +2204,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "gfx2d1_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(gfx2d1_clk.c),
@@ -2303,7 +2275,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "gfx3d_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 96000000, NOMINAL, 200000000,
HIGH, 320000000),
CLK_INIT(gfx3d_clk.c),
@@ -2355,7 +2327,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "ijpeg_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 110000000, NOMINAL, 228571000),
CLK_INIT(ijpeg_clk.c),
.depends = &ijpeg_axi_clk.c,
@@ -2397,7 +2369,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "jpegd_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 96000000, NOMINAL, 200000000),
CLK_INIT(jpegd_clk.c),
.depends = &jpegd_axi_clk.c,
@@ -2468,7 +2440,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mdp_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 85330000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(mdp_clk.c),
@@ -2503,7 +2475,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "mdp_vsync_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 27000000),
CLK_INIT(mdp_vsync_clk.c),
},
@@ -2555,7 +2527,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "pixel_mdp_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 85333000, NOMINAL, 170000000),
CLK_INIT(pixel_mdp_clk.c),
},
@@ -2630,7 +2602,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "rot_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 80000000, NOMINAL, 160000000),
CLK_INIT(rot_clk.c),
.depends = &rot_axi_clk.c,
@@ -2682,7 +2654,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "tv_src_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 27030000, NOMINAL, 149000000),
CLK_INIT(tv_src_clk.c),
},
@@ -2813,7 +2785,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "vcodec_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(vcodec_clk.c),
@@ -2860,7 +2832,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "vpe_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 76800000, NOMINAL, 160000000,
HIGH, 200000000),
CLK_INIT(vpe_clk.c),
@@ -2919,7 +2891,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "vfe_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 228570000,
HIGH, 266667000),
CLK_INIT(vfe_clk.c),
@@ -3007,7 +2979,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8x60, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP1(LOW, 24576000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -3064,7 +3036,7 @@
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
}
static struct clk_freq_tbl clk_tbl_pcm[] = {
- F_PCM( 0, gnd, 1, 0, 0),
+ { .ns_val = BIT(10) /* external input */ },
F_PCM( 512000, pll4, 4, 1, 264),
F_PCM( 768000, pll4, 4, 1, 176),
F_PCM( 1024000, pll4, 4, 1, 132),
@@ -3092,14 +3064,14 @@
.ns_reg = LCC_PCM_NS_REG,
.md_reg = LCC_PCM_MD_REG,
.root_en_mask = BIT(9),
- .ns_mask = (BM(31, 16) | BM(6, 0)),
+ .ns_mask = BM(31, 16) | BIT(10) | BM(6, 0),
.mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_pcm,
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "pcm_clk",
- .ops = &clk_ops_rcg_8x60,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 24580000),
CLK_INIT(pcm_clk.c),
},
@@ -3613,7 +3585,7 @@
CLK_LOOKUP("core_clk", gfx2d1_clk.c, "footswitch-8x60.1"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"),
- CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, NULL),
+ CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, "msm_gemini.0"),
CLK_LOOKUP("core_clk", ijpeg_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("core_clk", jpegd_clk.c, NULL),
CLK_LOOKUP("core_clk", mdp_clk.c, "mdp.0"),
@@ -3666,7 +3638,7 @@
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, "hdmi_msm.1"),
CLK_LOOKUP("slave_iface_clk", hdmi_s_p_clk.c, "hdmi_msm.1"),
- CLK_LOOKUP("ijpeg_pclk", ijpeg_p_clk.c, NULL),
+ CLK_LOOKUP("ijpeg_pclk", ijpeg_p_clk.c, "msm_gemini.0"),
CLK_LOOKUP("iface_clk", ijpeg_p_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("iface_clk", jpegd_p_clk.c, NULL),
CLK_LOOKUP("mem_iface_clk", imem_p_clk.c, "kgsl-3d0.0"),
@@ -3843,10 +3815,10 @@
/* The halt status bits for PDM and TSSC may be incorrect at boot.
* Toggle these clocks on and off to refresh them. */
- rcg_clk_enable(&pdm_clk.c);
- rcg_clk_disable(&pdm_clk.c);
- rcg_clk_enable(&tssc_clk.c);
- rcg_clk_disable(&tssc_clk.c);
+ clk_prepare_enable(&pdm_clk.c);
+ clk_disable_unprepare(&pdm_clk.c);
+ clk_prepare_enable(&tssc_clk.c);
+ clk_disable_unprepare(&tssc_clk.c);
}
static int __init msm8660_clock_late_init(void)
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index b145278..12d37ae 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -153,6 +153,7 @@
/* MUX source input identifiers. */
#define cxo_to_bb_mux 0
#define pll8_to_bb_mux 3
+#define pll8_acpu_to_bb_mux 3
#define pll14_to_bb_mux 4
#define gnd_to_bb_mux 6
#define cxo_to_xo_mux 0
@@ -365,35 +366,6 @@
},
};
-static struct clk_ops clk_ops_rcg_9615 = {
- .enable = rcg_clk_enable,
- .disable = rcg_clk_disable,
- .auto_off = rcg_clk_disable,
- .enable_hwcg = rcg_clk_enable_hwcg,
- .disable_hwcg = rcg_clk_disable_hwcg,
- .in_hwcg_mode = rcg_clk_in_hwcg_mode,
- .handoff = rcg_clk_handoff,
- .set_rate = rcg_clk_set_rate,
- .list_rate = rcg_clk_list_rate,
- .is_enabled = rcg_clk_is_enabled,
- .round_rate = rcg_clk_round_rate,
- .reset = rcg_clk_reset,
- .get_parent = rcg_clk_get_parent,
-};
-
-static struct clk_ops clk_ops_branch = {
- .enable = branch_clk_enable,
- .disable = branch_clk_disable,
- .auto_off = branch_clk_disable,
- .enable_hwcg = branch_clk_enable_hwcg,
- .disable_hwcg = branch_clk_disable_hwcg,
- .in_hwcg_mode = branch_clk_in_hwcg_mode,
- .handoff = branch_clk_handoff,
- .is_enabled = branch_clk_is_enabled,
- .reset = branch_clk_reset,
- .get_parent = branch_clk_get_parent,
-};
-
/*
* Peripheral Clocks
*/
@@ -415,7 +387,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_9615, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP1(LOW, 27000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -458,7 +430,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_9615, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -514,7 +486,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_9615, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 24000000, NOMINAL, 52000000), \
CLK_INIT(i##_clk.c), \
}, \
@@ -574,7 +546,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "pdm_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 19200000),
CLK_INIT(pdm_clk.c),
},
@@ -619,7 +591,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "prng_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
CLK_INIT(prng_clk.c),
},
@@ -645,7 +617,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #name, \
- .ops = &clk_ops_rcg_9615, \
+ .ops = &clk_ops_rcg, \
VDD_DIG_FMAX_MAP2(LOW, 26000000, NOMINAL, 52000000), \
CLK_INIT(name.c), \
}, \
@@ -689,8 +661,8 @@
};
static struct clk_freq_tbl clk_tbl_usb_hsic_sys[] = {
- F_USB( 0, gnd, 1, 0, 0),
- F_USB(64000000, pll8, 1, 1, 6),
+ F_USB( 0, gnd, 1, 0, 0),
+ F_USB(64000000, pll8_acpu, 1, 1, 6),
F_END
};
@@ -713,7 +685,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hs1_xcvr_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
CLK_INIT(usb_hs1_xcvr_clk.c),
},
@@ -738,7 +710,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hs1_sys_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(NOMINAL, 60000000),
CLK_INIT(usb_hs1_sys_clk.c),
},
@@ -763,7 +735,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hsic_xcvr_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 60000000),
CLK_INIT(usb_hsic_xcvr_clk.c),
},
@@ -788,7 +760,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hsic_sys_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 64000000),
CLK_INIT(usb_hsic_sys_clk.c),
},
@@ -817,7 +789,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "usb_hsic_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 480000000),
CLK_INIT(usb_hsic_clk.c),
},
@@ -1154,7 +1126,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_9615, \
+ .ops = &clk_ops_rcg, \
CLK_INIT(i##_clk.c), \
}, \
}
@@ -1179,7 +1151,7 @@
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_9615, \
+ .ops = &clk_ops_rcg, \
CLK_INIT(i##_clk.c), \
}, \
}
@@ -1254,7 +1226,7 @@
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
}
static struct clk_freq_tbl clk_tbl_pcm[] = {
- F_PCM( 0, gnd, 1, 0, 0),
+ { .ns_val = BIT(10) /* external input */ },
F_PCM( 512000, pll4, 4, 1, 192),
F_PCM( 768000, pll4, 4, 1, 128),
F_PCM( 1024000, pll4, 4, 1, 96),
@@ -1282,14 +1254,14 @@
.ns_reg = LCC_PCM_NS_REG,
.md_reg = LCC_PCM_MD_REG,
.root_en_mask = BIT(9),
- .ns_mask = (BM(31, 16) | BM(6, 0)),
+ .ns_mask = BM(31, 16) | BIT(10) | BM(6, 0),
.mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_pcm,
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "pcm_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 24576000),
CLK_INIT(pcm_clk.c),
},
@@ -1315,7 +1287,7 @@
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "audio_slimbus_clk",
- .ops = &clk_ops_rcg_9615,
+ .ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP1(LOW, 24576000),
CLK_INIT(audio_slimbus_clk.c),
},
@@ -1857,8 +1829,8 @@
* The halt status bits for PDM may be incorrect at boot.
* Toggle these clocks on and off to refresh them.
*/
- rcg_clk_enable(&pdm_clk.c);
- rcg_clk_disable(&pdm_clk.c);
+ clk_prepare_enable(&pdm_clk.c);
+ clk_disable_unprepare(&pdm_clk.c);
}
static int __init msm9615_clock_late_init(void)
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index d414e44..e1b3381 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -268,7 +268,7 @@
return invert ? !status_bit : status_bit;
}
-int branch_in_hwcg_mode(const struct branch *b)
+static int branch_in_hwcg_mode(const struct branch *b)
{
if (!b->hwcg_mask)
return 0;
@@ -420,7 +420,7 @@
}
/* Enable a rate-settable clock. */
-int rcg_clk_enable(struct clk *c)
+static int rcg_clk_enable(struct clk *c)
{
unsigned long flags;
struct rcg_clk *clk = to_rcg_clk(c);
@@ -434,7 +434,7 @@
}
/* Disable a rate-settable clock. */
-void rcg_clk_disable(struct clk *c)
+static void rcg_clk_disable(struct clk *c)
{
unsigned long flags;
struct rcg_clk *clk = to_rcg_clk(c);
@@ -450,7 +450,7 @@
*/
/* Set a clock to an exact rate. */
-int rcg_clk_set_rate(struct clk *c, unsigned long rate)
+static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
{
struct rcg_clk *clk = to_rcg_clk(c);
struct clk_freq_tbl *nf, *cf;
@@ -527,13 +527,13 @@
}
/* Check if a clock is currently enabled. */
-int rcg_clk_is_enabled(struct clk *clk)
+static int rcg_clk_is_enabled(struct clk *clk)
{
return to_rcg_clk(clk)->enabled;
}
/* Return a supported rate that's at least the specified rate. */
-long rcg_clk_round_rate(struct clk *c, unsigned long rate)
+static long rcg_clk_round_rate(struct clk *c, unsigned long rate)
{
struct rcg_clk *clk = to_rcg_clk(c);
struct clk_freq_tbl *f;
@@ -546,7 +546,7 @@
}
/* Return the nth supported frequency for a given clock. */
-int rcg_clk_list_rate(struct clk *c, unsigned n)
+static int rcg_clk_list_rate(struct clk *c, unsigned n)
{
struct rcg_clk *clk = to_rcg_clk(c);
@@ -556,7 +556,7 @@
return (clk->freq_tbl + n)->freq_hz;
}
-struct clk *rcg_clk_get_parent(struct clk *clk)
+static struct clk *rcg_clk_get_parent(struct clk *clk)
{
return to_rcg_clk(clk)->current_freq->src_clk;
}
@@ -575,13 +575,13 @@
return HANDOFF_DISABLED_CLK;
}
-enum handoff branch_clk_handoff(struct clk *c)
+static enum handoff branch_clk_handoff(struct clk *c)
{
struct branch_clk *clk = to_branch_clk(c);
return branch_handoff(&clk->b, &clk->c);
}
-enum handoff rcg_clk_handoff(struct clk *c)
+static enum handoff rcg_clk_handoff(struct clk *c)
{
struct rcg_clk *clk = to_rcg_clk(c);
uint32_t ctl_val, ns_val, md_val, ns_mask;
@@ -641,7 +641,7 @@
struct clk_ops clk_ops_measure = {
};
-int branch_clk_enable(struct clk *clk)
+static int branch_clk_enable(struct clk *clk)
{
unsigned long flags;
struct branch_clk *branch = to_branch_clk(clk);
@@ -654,7 +654,7 @@
return 0;
}
-void branch_clk_disable(struct clk *clk)
+static void branch_clk_disable(struct clk *clk)
{
unsigned long flags;
struct branch_clk *branch = to_branch_clk(clk);
@@ -665,13 +665,13 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-struct clk *branch_clk_get_parent(struct clk *clk)
+static struct clk *branch_clk_get_parent(struct clk *clk)
{
struct branch_clk *branch = to_branch_clk(clk);
return branch->parent;
}
-int branch_clk_is_enabled(struct clk *clk)
+static int branch_clk_is_enabled(struct clk *clk)
{
struct branch_clk *branch = to_branch_clk(clk);
return branch->enabled;
@@ -701,13 +701,13 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-void branch_clk_enable_hwcg(struct clk *clk)
+static void branch_clk_enable_hwcg(struct clk *clk)
{
struct branch_clk *branch = to_branch_clk(clk);
branch_enable_hwcg(&branch->b);
}
-void branch_clk_disable_hwcg(struct clk *clk)
+static void branch_clk_disable_hwcg(struct clk *clk)
{
struct branch_clk *branch = to_branch_clk(clk);
branch_disable_hwcg(&branch->b);
@@ -740,36 +740,36 @@
return ret;
}
-int branch_clk_set_flags(struct clk *clk, unsigned flags)
+static int branch_clk_set_flags(struct clk *clk, unsigned flags)
{
return branch_set_flags(&to_branch_clk(clk)->b, flags);
}
-int branch_clk_in_hwcg_mode(struct clk *c)
+static int branch_clk_in_hwcg_mode(struct clk *c)
{
struct branch_clk *clk = to_branch_clk(c);
return branch_in_hwcg_mode(&clk->b);
}
-void rcg_clk_enable_hwcg(struct clk *clk)
+static void rcg_clk_enable_hwcg(struct clk *clk)
{
struct rcg_clk *rcg = to_rcg_clk(clk);
branch_enable_hwcg(&rcg->b);
}
-void rcg_clk_disable_hwcg(struct clk *clk)
+static void rcg_clk_disable_hwcg(struct clk *clk)
{
struct rcg_clk *rcg = to_rcg_clk(clk);
branch_disable_hwcg(&rcg->b);
}
-int rcg_clk_in_hwcg_mode(struct clk *c)
+static int rcg_clk_in_hwcg_mode(struct clk *c)
{
struct rcg_clk *clk = to_rcg_clk(c);
return branch_in_hwcg_mode(&clk->b);
}
-int rcg_clk_set_flags(struct clk *clk, unsigned flags)
+static int rcg_clk_set_flags(struct clk *clk, unsigned flags)
{
return branch_set_flags(&to_rcg_clk(clk)->b, flags);
}
@@ -811,16 +811,51 @@
return ret;
}
-int branch_clk_reset(struct clk *clk, enum clk_reset_action action)
+static int branch_clk_reset(struct clk *clk, enum clk_reset_action action)
{
return branch_reset(&to_branch_clk(clk)->b, action);
}
-int rcg_clk_reset(struct clk *clk, enum clk_reset_action action)
+struct clk_ops clk_ops_branch = {
+ .enable = branch_clk_enable,
+ .disable = branch_clk_disable,
+ .enable_hwcg = branch_clk_enable_hwcg,
+ .disable_hwcg = branch_clk_disable_hwcg,
+ .in_hwcg_mode = branch_clk_in_hwcg_mode,
+ .auto_off = branch_clk_disable,
+ .is_enabled = branch_clk_is_enabled,
+ .reset = branch_clk_reset,
+ .get_parent = branch_clk_get_parent,
+ .handoff = branch_clk_handoff,
+ .set_flags = branch_clk_set_flags,
+};
+
+struct clk_ops clk_ops_reset = {
+ .reset = branch_clk_reset,
+};
+
+static int rcg_clk_reset(struct clk *clk, enum clk_reset_action action)
{
return branch_reset(&to_rcg_clk(clk)->b, action);
}
+struct clk_ops clk_ops_rcg = {
+ .enable = rcg_clk_enable,
+ .disable = rcg_clk_disable,
+ .enable_hwcg = rcg_clk_enable_hwcg,
+ .disable_hwcg = rcg_clk_disable_hwcg,
+ .in_hwcg_mode = rcg_clk_in_hwcg_mode,
+ .auto_off = rcg_clk_disable,
+ .handoff = rcg_clk_handoff,
+ .set_rate = rcg_clk_set_rate,
+ .list_rate = rcg_clk_list_rate,
+ .is_enabled = rcg_clk_is_enabled,
+ .round_rate = rcg_clk_round_rate,
+ .reset = rcg_clk_reset,
+ .get_parent = rcg_clk_get_parent,
+ .set_flags = rcg_clk_set_flags,
+};
+
static int cdiv_clk_enable(struct clk *c)
{
unsigned long flags;
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 0419ede..a419d69 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -73,16 +73,6 @@
* !!(n))
/*
- * Halt/Status Checking Mode Macros
- */
-#define HALT 0 /* Bit pol: 1 = halted */
-#define NOCHECK 1 /* No bit to check, do nothing */
-#define HALT_VOTED 2 /* Bit pol: 1 = halted; delay on disable */
-#define ENABLE 3 /* Bit pol: 1 = running */
-#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */
-#define DELAY 5 /* No bit to check, just delay */
-
-/*
* Clock Definition Macros
*/
#define DEFINE_CLK_MEASURE(name) \
@@ -162,12 +152,13 @@
const u32 retain_mask;
};
+extern struct clk_ops clk_ops_branch;
+extern struct clk_ops clk_ops_reset;
+
int branch_reset(struct branch *b, enum clk_reset_action action);
void __branch_clk_enable_reg(const struct branch *clk, const char *name);
u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
-enum handoff branch_clk_handoff(struct clk *c);
enum handoff branch_handoff(struct branch *clk, struct clk *c);
-int branch_clk_set_flags(struct clk *clk, unsigned flags);
/*
* Generic clock-definition struct and macros
@@ -197,21 +188,9 @@
return container_of(clk, struct rcg_clk, c);
}
-extern struct clk_freq_tbl rcg_dummy_freq;
+extern struct clk_ops clk_ops_rcg;
-int rcg_clk_enable(struct clk *clk);
-void rcg_clk_disable(struct clk *clk);
-int rcg_clk_set_rate(struct clk *clk, unsigned long rate);
-int rcg_clk_list_rate(struct clk *clk, unsigned n);
-int rcg_clk_is_enabled(struct clk *clk);
-long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
-struct clk *rcg_clk_get_parent(struct clk *c);
-enum handoff rcg_clk_handoff(struct clk *c);
-int rcg_clk_reset(struct clk *clk, enum clk_reset_action action);
-void rcg_clk_enable_hwcg(struct clk *clk);
-void rcg_clk_disable_hwcg(struct clk *clk);
-int rcg_clk_in_hwcg_mode(struct clk *c);
-int rcg_clk_set_flags(struct clk *clk, unsigned flags);
+extern struct clk_freq_tbl rcg_dummy_freq;
/**
* struct cdiv_clk - integer divider clock with external source selection
@@ -271,15 +250,6 @@
return container_of(clk, struct branch_clk, c);
}
-int branch_clk_enable(struct clk *clk);
-void branch_clk_disable(struct clk *clk);
-struct clk *branch_clk_get_parent(struct clk *clk);
-int branch_clk_is_enabled(struct clk *clk);
-int branch_clk_reset(struct clk *c, enum clk_reset_action action);
-void branch_clk_enable_hwcg(struct clk *clk);
-void branch_clk_disable_hwcg(struct clk *clk);
-int branch_clk_in_hwcg_mode(struct clk *c);
-
/**
* struct measure_clk - for rate measurement debug use
* @sample_ticks: sample period in reference clock ticks
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
new file mode 100644
index 0000000..55282b6
--- /dev/null
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -0,0 +1,591 @@
+/* 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.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <mach/clk.h>
+
+#include "clock.h"
+#include "clock-local2.h"
+
+/*
+ * When enabling/disabling a clock, check the halt bit up to this number
+ * number of times (with a 1 us delay in between) before continuing.
+ */
+#define HALT_CHECK_MAX_LOOPS 200
+/* For clock without halt checking, wait this long after enables/disables. */
+#define HALT_CHECK_DELAY_US 10
+
+/*
+ * When updating an RCG configuration, check the update bit up to this number
+ * number of times (with a 1 us delay in between) before continuing.
+ */
+#define UPDATE_CHECK_MAX_LOOPS 200
+
+DEFINE_SPINLOCK(local_clock_reg_lock);
+struct clk_freq_tbl rcg_dummy_freq = F_END;
+
+#define CMD_RCGR_REG(x) (*(x)->base + (x)->cmd_rcgr_reg)
+#define CFG_RCGR_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0x4)
+#define M_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0x8)
+#define N_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0xC)
+#define D_REG(x) (*(x)->base + (x)->cmd_rcgr_reg + 0x10)
+#define CBCR_REG(x) (*(x)->base + (x)->cbcr_reg)
+#define BCR_REG(x) (*(x)->base + (x)->bcr_reg)
+#define VOTE_REG(x) (*(x)->base + (x)->vote_reg)
+
+/*
+ * Important clock bit positions and masks
+ */
+#define CMD_RCGR_ROOT_ENABLE_BIT BIT(1)
+#define CBCR_BRANCH_ENABLE_BIT BIT(0)
+#define CBCR_BRANCH_OFF_BIT BIT(31)
+#define CMD_RCGR_CONFIG_UPDATE_BIT BIT(0)
+#define CMD_RCGR_ROOT_STATUS_BIT BIT(31)
+#define BCR_BLK_ARES_BIT BIT(0)
+#define CBCR_HW_CTL_BIT BIT(1)
+#define CFG_RCGR_DIV_MASK BM(4, 0)
+#define CFG_RCGR_SRC_SEL_MASK BM(10, 8)
+#define MND_MODE_MASK BM(13, 12)
+#define MND_DUAL_EDGE_MODE_BVAL BVAL(13, 12, 0x2)
+#define CMD_RCGR_CONFIG_DIRTY_MASK BM(7, 4)
+#define CBCR_BRANCH_CDIV_MASK BM(24, 16)
+#define CBCR_BRANCH_CDIV_MASKED(val) BVAL(24, 16, (val));
+
+enum branch_state {
+ BRANCH_ON,
+ BRANCH_OFF,
+};
+
+/*
+ * RCG functions
+ */
+
+/*
+ * Update an RCG with a new configuration. This may include a new M, N, or D
+ * value, source selection or pre-divider value.
+ *
+ */
+static void rcg_update_config(struct rcg_clk *rcg)
+{
+ u32 cmd_rcgr_regval, count;
+
+ cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg));
+ cmd_rcgr_regval |= CMD_RCGR_CONFIG_UPDATE_BIT;
+ writel_relaxed(cmd_rcgr_regval, CMD_RCGR_REG(rcg));
+
+ /* Wait for update to take effect */
+ for (count = UPDATE_CHECK_MAX_LOOPS; count > 0; count--) {
+ if (!(readl_relaxed(CMD_RCGR_REG(rcg)) &
+ CMD_RCGR_CONFIG_UPDATE_BIT))
+ return;
+ udelay(1);
+ }
+
+ WARN(count == 0, "%s: rcg didn't update its configuration.",
+ rcg->c.dbg_name);
+}
+
+/* RCG set rate function for clocks with Half Integer Dividers. */
+void set_rate_hid(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
+{
+ u32 cfg_regval;
+
+ cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
+ cfg_regval &= ~(CFG_RCGR_DIV_MASK | CFG_RCGR_SRC_SEL_MASK);
+ cfg_regval |= nf->div_src_val;
+ writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg));
+
+ rcg_update_config(rcg);
+}
+
+/* RCG set rate function for clocks with MND & Half Integer Dividers. */
+void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
+{
+ u32 cfg_regval;
+
+ writel_relaxed(nf->m_val, M_REG(rcg));
+ writel_relaxed(nf->n_val, N_REG(rcg));
+ writel_relaxed(nf->d_val, D_REG(rcg));
+
+ cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
+ cfg_regval &= ~(CFG_RCGR_DIV_MASK | CFG_RCGR_SRC_SEL_MASK);
+ cfg_regval |= nf->div_src_val;
+
+ /* Activate or disable the M/N:D divider as necessary */
+ cfg_regval &= ~MND_MODE_MASK;
+ if (nf->n_val != 0)
+ cfg_regval |= MND_DUAL_EDGE_MODE_BVAL;
+ writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg));
+
+ rcg_update_config(rcg);
+}
+
+static int rcg_clk_enable(struct clk *c)
+{
+ struct rcg_clk *rcg = to_rcg_clk(c);
+
+ WARN(rcg->current_freq == &rcg_dummy_freq,
+ "Attempting to enable %s before setting its rate. "
+ "Set the rate first!\n", rcg->c.dbg_name);
+
+ return 0;
+}
+
+static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
+{
+ struct clk_freq_tbl *cf, *nf;
+ struct rcg_clk *rcg = to_rcg_clk(c);
+ int rc = 0;
+ unsigned long flags;
+
+ for (nf = rcg->freq_tbl; nf->freq_hz != FREQ_END
+ && nf->freq_hz != rate; nf++)
+ ;
+
+ if (nf->freq_hz == FREQ_END)
+ return -EINVAL;
+
+ /* Check if frequency is actually changed. */
+ cf = rcg->current_freq;
+ if (nf == cf)
+ return 0;
+
+ if (rcg->c.count) {
+ /* TODO: Modify to use the prepare API */
+ /* Enable source clock dependency for the new freq. */
+ rc = clk_enable(nf->src_clk);
+ if (rc)
+ goto out;
+ }
+
+ BUG_ON(!rcg->set_rate);
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+ /* Perform clock-specific frequency switch operations. */
+ rcg->set_rate(rcg, nf);
+
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ /* Release source requirements of the old freq. */
+ if (rcg->c.count)
+ clk_disable(cf->src_clk);
+
+ rcg->current_freq = nf;
+out:
+ return rc;
+}
+
+/* Return a supported rate that's at least the specified rate. */
+static long rcg_clk_round_rate(struct clk *c, unsigned long rate)
+{
+ struct rcg_clk *rcg = to_rcg_clk(c);
+ struct clk_freq_tbl *f;
+
+ for (f = rcg->freq_tbl; f->freq_hz != FREQ_END; f++)
+ if (f->freq_hz >= rate)
+ return f->freq_hz;
+
+ return -EPERM;
+}
+
+/* Return the nth supported frequency for a given clock. */
+static int rcg_clk_list_rate(struct clk *c, unsigned n)
+{
+ struct rcg_clk *rcg = to_rcg_clk(c);
+
+ if (!rcg->freq_tbl || rcg->freq_tbl->freq_hz == FREQ_END)
+ return -ENXIO;
+
+ return (rcg->freq_tbl + n)->freq_hz;
+}
+
+static struct clk *rcg_clk_get_parent(struct clk *c)
+{
+ return to_rcg_clk(c)->current_freq->src_clk;
+}
+
+static enum handoff _rcg_clk_handoff(struct rcg_clk *rcg, int has_mnd)
+{
+ u32 n_regval = 0, m_regval = 0, d_regval = 0;
+ u32 cfg_regval;
+ struct clk_freq_tbl *freq;
+ u32 cmd_rcgr_regval;
+
+ /* Is the root enabled? */
+ cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg));
+ if ((cmd_rcgr_regval & CMD_RCGR_ROOT_STATUS_BIT))
+ return HANDOFF_DISABLED_CLK;
+
+ /* Is there a pending configuration? */
+ if (cmd_rcgr_regval & CMD_RCGR_CONFIG_DIRTY_MASK)
+ return HANDOFF_UNKNOWN_RATE;
+
+ /* Get values of m, n, d, div and src_sel registers. */
+ if (has_mnd) {
+ m_regval = readl_relaxed(M_REG(rcg));
+ n_regval = readl_relaxed(N_REG(rcg));
+ d_regval = readl_relaxed(D_REG(rcg));
+
+ /*
+ * The n and d values stored in the frequency tables are sign
+ * extended to 32 bits. The n and d values in the registers are
+ * sign extended to 8 or 16 bits. Sign extend the values read
+ * from the registers so that they can be compared to the
+ * values in the frequency tables.
+ */
+ n_regval |= (n_regval >> 8) ? BM(31, 16) : BM(31, 8);
+ d_regval |= (d_regval >> 8) ? BM(31, 16) : BM(31, 8);
+ }
+
+ cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
+ cfg_regval &= CFG_RCGR_SRC_SEL_MASK | CFG_RCGR_DIV_MASK
+ | MND_MODE_MASK;
+
+ /* If mnd counter is present, check if it's in use. */
+ has_mnd = (has_mnd) &&
+ ((cfg_regval & MND_MODE_MASK) == MND_DUAL_EDGE_MODE_BVAL);
+
+ /*
+ * Clear out the mn counter mode bits since we now want to compare only
+ * the source mux selection and pre-divider values in the registers.
+ */
+ cfg_regval &= ~MND_MODE_MASK;
+
+ /* Figure out what rate the rcg is running at */
+ for (freq = rcg->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
+ if (freq->div_src_val != cfg_regval)
+ continue;
+ if (has_mnd) {
+ if (freq->m_val != m_regval)
+ continue;
+ if (freq->n_val != n_regval)
+ continue;
+ if (freq->d_val != d_regval)
+ continue;
+ }
+ pr_info("%s rate=%lu\n", rcg->c.dbg_name, freq->freq_hz);
+ break;
+ }
+
+ /* No known frequency found */
+ if (freq->freq_hz == FREQ_END)
+ return HANDOFF_UNKNOWN_RATE;
+
+ rcg->current_freq = freq;
+ rcg->c.rate = freq->freq_hz;
+
+ return HANDOFF_ENABLED_CLK;
+}
+
+static enum handoff rcg_mnd_clk_handoff(struct clk *c)
+{
+ return _rcg_clk_handoff(to_rcg_clk(c), 1);
+}
+
+static enum handoff rcg_clk_handoff(struct clk *c)
+{
+ return _rcg_clk_handoff(to_rcg_clk(c), 0);
+}
+
+/*
+ * Branch clock functions
+ */
+static void branch_clk_halt_check(u32 halt_check, const char *clk_name,
+ void __iomem *cbcr_reg,
+ enum branch_state br_status)
+{
+ char *status_str = (br_status == BRANCH_ON) ? "on" : "off";
+
+ /*
+ * Use a memory barrier since some halt status registers are
+ * not within the same 1K segment as the branch/root enable
+ * registers. It's also needed in the udelay() case to ensure
+ * the delay starts after the branch disable.
+ */
+ mb();
+
+ if (halt_check == DELAY || halt_check == HALT_VOTED) {
+ udelay(HALT_CHECK_DELAY_US);
+ } else if (halt_check == HALT) {
+ int count;
+ for (count = HALT_CHECK_MAX_LOOPS; count > 0; count--) {
+ if (br_status == BRANCH_ON
+ && !(readl_relaxed(cbcr_reg)
+ & CBCR_BRANCH_OFF_BIT))
+ return;
+ if (br_status == BRANCH_OFF
+ && (readl_relaxed(cbcr_reg)
+ & CBCR_BRANCH_OFF_BIT))
+ return;
+ udelay(1);
+ }
+ WARN(count == 0, "%s status stuck %s", clk_name, status_str);
+ }
+}
+
+static int branch_clk_enable(struct clk *c)
+{
+ unsigned long flags;
+ u32 cbcr_val;
+ struct branch_clk *branch = to_branch_clk(c);
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ cbcr_val = readl_relaxed(CBCR_REG(branch));
+ cbcr_val |= CBCR_BRANCH_ENABLE_BIT;
+ writel_relaxed(cbcr_val, CBCR_REG(branch));
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ /* Wait for clock to enable before continuing. */
+ branch_clk_halt_check(branch->halt_check, branch->c.dbg_name,
+ CBCR_REG(branch), BRANCH_ON);
+
+ return 0;
+}
+
+static void branch_clk_disable(struct clk *c)
+{
+ unsigned long flags;
+ struct branch_clk *branch = to_branch_clk(c);
+ u32 reg_val;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ reg_val = readl_relaxed(CBCR_REG(branch));
+ reg_val &= ~CBCR_BRANCH_ENABLE_BIT;
+ writel_relaxed(reg_val, CBCR_REG(branch));
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ /* Wait for clock to disable before continuing. */
+ branch_clk_halt_check(branch->halt_check, branch->c.dbg_name,
+ CBCR_REG(branch), BRANCH_OFF);
+}
+
+static int branch_cdiv_set_rate(struct branch_clk *branch, unsigned long rate)
+{
+ unsigned long flags;
+ u32 regval;
+
+ if (rate > branch->max_div)
+ return -EINVAL;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ regval = readl_relaxed(CBCR_REG(branch));
+ regval &= ~CBCR_BRANCH_CDIV_MASK;
+ regval |= CBCR_BRANCH_CDIV_MASKED(rate);
+ writel_relaxed(regval, CBCR_REG(branch));
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ return 0;
+}
+
+static int branch_clk_set_rate(struct clk *c, unsigned long rate)
+{
+ struct branch_clk *branch = to_branch_clk(c);
+
+ if (branch->max_div)
+ return branch_cdiv_set_rate(branch, rate);
+
+ if (!branch->has_sibling)
+ return clk_set_rate(branch->parent, rate);
+
+ return -EPERM;
+}
+
+static unsigned long branch_clk_get_rate(struct clk *c)
+{
+ struct branch_clk *branch = to_branch_clk(c);
+
+ if (branch->max_div)
+ return branch->c.rate;
+
+ if (!branch->has_sibling)
+ return clk_get_rate(branch->parent);
+
+ return 0;
+}
+
+static struct clk *branch_clk_get_parent(struct clk *c)
+{
+ return to_branch_clk(c)->parent;
+}
+
+static int branch_clk_list_rate(struct clk *c, unsigned n)
+{
+ struct branch_clk *branch = to_branch_clk(c);
+
+ if (branch->has_sibling == 1)
+ return -ENXIO;
+
+ if (branch->parent)
+ return rcg_clk_list_rate(branch->parent, n);
+ else
+ return 0;
+}
+
+static enum handoff branch_clk_handoff(struct clk *c)
+{
+ struct branch_clk *branch = to_branch_clk(c);
+ u32 cbcr_regval;
+
+ cbcr_regval = readl_relaxed(CBCR_REG(branch));
+ if ((cbcr_regval & CBCR_BRANCH_OFF_BIT))
+ return HANDOFF_DISABLED_CLK;
+ pr_info("%s enabled.\n", branch->c.dbg_name);
+
+ if (branch->parent) {
+ if (branch->parent->ops->handoff)
+ return branch->parent->ops->handoff(branch->parent);
+ }
+
+ return HANDOFF_ENABLED_CLK;
+}
+
+static int __branch_clk_reset(void __iomem *bcr_reg,
+ enum clk_reset_action action)
+{
+ int ret = 0;
+ unsigned long flags;
+ u32 reg_val;
+
+ if (!bcr_reg)
+ return -EPERM;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ reg_val = readl_relaxed(bcr_reg);
+ switch (action) {
+ case CLK_RESET_ASSERT:
+ reg_val |= BCR_BLK_ARES_BIT;
+ break;
+ case CLK_RESET_DEASSERT:
+ reg_val &= ~BCR_BLK_ARES_BIT;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ writel_relaxed(reg_val, bcr_reg);
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ /* Make sure write is issued before returning. */
+ mb();
+
+ return ret;
+}
+
+static int branch_clk_reset(struct clk *c, enum clk_reset_action action)
+{
+ struct branch_clk *branch = to_branch_clk(c);
+ return __branch_clk_reset(BCR_REG(branch), action);
+}
+
+/*
+ * Voteable clock functions
+ */
+static int local_vote_clk_reset(struct clk *c, enum clk_reset_action action)
+{
+ struct branch_clk *vclk = to_branch_clk(c);
+ return __branch_clk_reset(BCR_REG(vclk), action);
+}
+
+static int local_vote_clk_enable(struct clk *c)
+{
+ unsigned long flags;
+ u32 ena;
+ struct local_vote_clk *vclk = to_local_vote_clk(c);
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ ena = readl_relaxed(VOTE_REG(vclk));
+ ena |= vclk->en_mask;
+ writel_relaxed(ena, VOTE_REG(vclk));
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ branch_clk_halt_check(vclk->halt_check, c->dbg_name, CBCR_REG(vclk),
+ BRANCH_ON);
+
+ return 0;
+}
+
+static void local_vote_clk_disable(struct clk *c)
+{
+ unsigned long flags;
+ u32 ena;
+ struct local_vote_clk *vclk = to_local_vote_clk(c);
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ ena = readl_relaxed(VOTE_REG(vclk));
+ ena &= ~vclk->en_mask;
+ writel_relaxed(ena, VOTE_REG(vclk));
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+}
+
+static enum handoff local_vote_clk_handoff(struct clk *c)
+{
+ struct local_vote_clk *vclk = to_local_vote_clk(c);
+ u32 vote_regval;
+
+ /* Is the branch voted on by apps? */
+ vote_regval = readl_relaxed(VOTE_REG(vclk));
+ if (!(vote_regval & vclk->en_mask))
+ return HANDOFF_DISABLED_CLK;
+ pr_info("%s enabled.\n", vclk->c.dbg_name);
+
+ return HANDOFF_ENABLED_CLK;
+}
+
+struct clk_ops clk_ops_rcg = {
+ .enable = rcg_clk_enable,
+ .set_rate = rcg_clk_set_rate,
+ .list_rate = rcg_clk_list_rate,
+ .round_rate = rcg_clk_round_rate,
+ .get_parent = rcg_clk_get_parent,
+ .handoff = rcg_clk_handoff,
+};
+
+struct clk_ops clk_ops_rcg_mnd = {
+ .enable = rcg_clk_enable,
+ .set_rate = rcg_clk_set_rate,
+ .list_rate = rcg_clk_list_rate,
+ .round_rate = rcg_clk_round_rate,
+ .get_parent = rcg_clk_get_parent,
+ .handoff = rcg_mnd_clk_handoff,
+};
+
+struct clk_ops clk_ops_branch = {
+ .enable = branch_clk_enable,
+ .disable = branch_clk_disable,
+ .auto_off = branch_clk_disable,
+ .set_rate = branch_clk_set_rate,
+ .get_rate = branch_clk_get_rate,
+ .list_rate = branch_clk_list_rate,
+ .reset = branch_clk_reset,
+ .get_parent = branch_clk_get_parent,
+ .handoff = branch_clk_handoff,
+};
+
+struct clk_ops clk_ops_vote = {
+ .enable = local_vote_clk_enable,
+ .disable = local_vote_clk_disable,
+ .auto_off = local_vote_clk_disable,
+ .reset = local_vote_clk_reset,
+ .handoff = local_vote_clk_handoff,
+};
diff --git a/arch/arm/mach-msm/clock-local2.h b/arch/arm/mach-msm/clock-local2.h
new file mode 100644
index 0000000..c8d53cb
--- /dev/null
+++ b/arch/arm/mach-msm/clock-local2.h
@@ -0,0 +1,180 @@
+/* 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 __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_2_H
+#define __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_2_H
+
+#include <linux/spinlock.h>
+#include "clock.h"
+
+/*
+ * Generic frequency-definition structs and macros
+ */
+
+/**
+ * @freq_hz: output rate
+ * @src_clk: source clock for freq_hz
+ * @m_val: M value corresponding to freq_hz
+ * @n_val: N value corresponding to freq_hz
+ * @d_val: D value corresponding to freq_hz
+ * @div_src_val: Pre divider value and source selection mux index for freq_hz
+ * @sys_vdd: Voltage level required for freq_hz
+ */
+struct clk_freq_tbl {
+ unsigned long freq_hz;
+ struct clk *src_clk;
+ const u32 m_val;
+ const u32 n_val;
+ const u32 d_val;
+ const u32 div_src_val;
+ const unsigned sys_vdd;
+};
+
+#define FREQ_END (UINT_MAX-1)
+#define F_END { .freq_hz = FREQ_END }
+
+/*
+ * Generic clock-definition struct and macros
+ */
+/**
+ * struct rcg_clk - root clock generator
+ * @cmd_rcgr_reg: command register
+ * @set_rate: function to set frequency
+ * @freq_tbl: frequency table for this RCG
+ * @current_freq: current RCG frequency
+ * @c: generic clock data
+ * @base: pointer to base address of ioremapped registers.
+ */
+struct rcg_clk {
+ const u32 cmd_rcgr_reg;
+
+ void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
+
+ struct clk_freq_tbl *freq_tbl;
+ struct clk_freq_tbl *current_freq;
+ struct clk c;
+
+ void *const __iomem *base;
+};
+
+static inline struct rcg_clk *to_rcg_clk(struct clk *clk)
+{
+ return container_of(clk, struct rcg_clk, c);
+}
+
+extern struct clk_freq_tbl rcg_dummy_freq;
+
+/**
+ * struct fixed_clk - fixed rate clock (used for crystal oscillators)
+ * @rate: output rate
+ * @c: clk
+ */
+struct fixed_clk {
+ struct clk c;
+};
+
+/**
+ * struct branch_clk - branch clock
+ * @set_rate: Set the frequency of this branch clock.
+ * @parent: clock source
+ * @c: clk
+ * @cbcr_reg: branch control register
+ * @bcr_reg: block reset register
+ * @has_sibling: true if other branches are derived from this branch's source
+ * @cur_div: current branch divider value
+ * @max_div: maximum branch divider value (if zero, no divider exists)
+ * @halt_check: halt checking type
+ * @base: pointer to base address of ioremapped registers.
+ */
+struct branch_clk {
+ void (*set_rate)(struct branch_clk *, struct clk_freq_tbl *);
+ struct clk *parent;
+ struct clk c;
+ const u32 cbcr_reg;
+ const u32 bcr_reg;
+ int has_sibling;
+ u32 cur_div;
+ const u32 max_div;
+ const u32 halt_check;
+ void *const __iomem *base;
+};
+
+static inline struct branch_clk *to_branch_clk(struct clk *clk)
+{
+ return container_of(clk, struct branch_clk, c);
+}
+
+/**
+ * struct local_vote_clk - Voteable branch clock
+ * @c: clk
+ * @cbcr_reg: branch control register
+ * @vote_reg: voting register
+ * @en_mask: enable mask
+ * @halt_check: halt checking type
+ * @base: pointer to base address of ioremapped registers.
+ * An on/off switch with a rate derived from the parent.
+ */
+struct local_vote_clk {
+ struct clk c;
+ const u32 cbcr_reg;
+ const u32 vote_reg;
+ const u32 bcr_reg;
+ const u32 en_mask;
+ const u32 halt_check;
+ void *const __iomem *base;
+};
+
+static inline struct local_vote_clk *to_local_vote_clk(struct clk *clk)
+{
+ return container_of(clk, struct local_vote_clk, c);
+}
+
+/**
+ * struct measure_clk - for rate measurement debug use
+ * @sample_ticks: sample period in reference clock ticks
+ * @multiplier: measurement scale-up factor
+ * @divider: measurement scale-down factor
+ * @c: clk
+*/
+struct measure_clk {
+ u64 sample_ticks;
+ u32 multiplier;
+ u32 divider;
+ struct clk c;
+};
+
+extern struct clk_ops clk_ops_measure;
+
+static inline struct measure_clk *to_measure_clk(struct clk *clk)
+{
+ return container_of(clk, struct measure_clk, c);
+}
+
+/*
+ * Generic set-rate implementations
+ */
+void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
+void set_rate_hid(struct rcg_clk *clk, struct clk_freq_tbl *nf);
+
+/*
+ * Variables from the clock-local driver
+ */
+extern spinlock_t local_clock_reg_lock;
+
+extern struct clk_ops clk_ops_rcg;
+extern struct clk_ops clk_ops_rcg_mnd;
+extern struct clk_ops clk_ops_branch;
+extern struct clk_ops clk_ops_vote;
+
+#endif /* __ARCH_ARM_MACH_MSM_COPPER_CLOCK_LOCAL_H */
+
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index e83f17a..5022811 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -45,9 +45,11 @@
static DEFINE_SPINLOCK(pll_reg_lock);
+#define ENABLE_WAIT_MAX_LOOPS 200
+
int pll_vote_clk_enable(struct clk *clk)
{
- u32 ena;
+ u32 ena, count;
unsigned long flags;
struct pll_vote_clk *pll = to_pll_vote_clk(clk);
@@ -57,11 +59,22 @@
writel_relaxed(ena, PLL_EN_REG(pll));
spin_unlock_irqrestore(&pll_reg_lock, flags);
- /* Wait until PLL is enabled */
- while ((readl_relaxed(PLL_STATUS_REG(pll)) & pll->status_mask) == 0)
- cpu_relax();
+ /*
+ * Use a memory barrier since some PLL status registers are
+ * not within the same 1K segment as the voting registers.
+ */
+ mb();
- return 0;
+ /* Wait for pll to enable. */
+ for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) {
+ if (readl_relaxed(pll->status_reg) & pll->status_mask)
+ return 0;
+ udelay(1);
+ }
+
+ WARN("PLL %s didn't enable after voting for it!\n", clk->dbg_name);
+
+ return -ETIMEDOUT;
}
void pll_vote_clk_disable(struct clk *clk)
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index d5a3e8f..7ea464f 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -43,6 +43,16 @@
#define BM(msb, lsb) (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb))
+/*
+ * Halt/Status Checking Mode Macros
+ */
+#define HALT 0 /* Bit pol: 1 = halted */
+#define NOCHECK 1 /* No bit to check, do nothing */
+#define HALT_VOTED 2 /* Bit pol: 1 = halted; delay on disable */
+#define ENABLE 3 /* Bit pol: 1 = running */
+#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */
+#define DELAY 5 /* No bit to check, just delay */
+
#define MAX_VDD_LEVELS 4
/**
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index 4ba3f95..b68fdc1 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -30,28 +30,40 @@
{0, 0, "C0", "WFI",
MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
- {0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+ {0, 1, "C1", "RETENTION",
+ MSM_PM_SLEEP_MODE_RETENTION},
+
+ {0, 2, "C2", "STANDALONE_POWER_COLLAPSE",
MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
- {0, 2, "C2", "POWER_COLLAPSE",
+ {0, 3, "C3", "POWER_COLLAPSE",
MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
{1, 0, "C0", "WFI",
MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
- {1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+ {1, 1, "C1", "RETENTION",
+ MSM_PM_SLEEP_MODE_RETENTION},
+
+ {1, 2, "C2", "STANDALONE_POWER_COLLAPSE",
MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
{2, 0, "C0", "WFI",
MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
- {2, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+ {2, 1, "C1", "RETENTION",
+ MSM_PM_SLEEP_MODE_RETENTION},
+
+ {2, 2, "C2", "STANDALONE_POWER_COLLAPSE",
MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
{3, 0, "C0", "WFI",
MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
- {3, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+ {3, 1, "C1", "RETENTION",
+ MSM_PM_SLEEP_MODE_RETENTION},
+
+ {3, 2, "C2", "STANDALONE_POWER_COLLAPSE",
MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
};
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 2dc8751..aaa5bfb 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -40,6 +40,7 @@
#include "rpm_stats.h"
#include "rpm_log.h"
#include <mach/mpm.h>
+#include <mach/iommu_domains.h>
/* Address of GSBI blocks */
#define MSM_GSBI1_PHYS 0x12440000
@@ -440,6 +441,16 @@
.id = 0x3005,
};
+struct platform_device apq_cpudai_slim_4_rx = {
+ .name = "msm-dai-q6",
+ .id = 0x4008,
+};
+
+struct platform_device apq_cpudai_slim_4_tx = {
+ .name = "msm-dai-q6",
+ .id = 0x4009,
+};
+
/*
* Machine specific data for AUX PCM Interface
* which the driver will be unware of.
@@ -471,6 +482,19 @@
},
};
+struct msm_mi2s_data mpq_mi2s_tx_data = {
+ .sd_lines = MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3,
+ .capability = MSM_MI2S_CAP_TX,
+};
+
+struct platform_device mpq_cpudai_mi2s_tx = {
+ .name = "msm-dai-q6",
+ .id = 7, /*MI2S_TX */
+ .dev = {
+ .platform_data = &mpq_mi2s_tx_data,
+ },
+};
+
struct platform_device apq_cpu_fe = {
.name = "msm-dai-fe",
.id = -1,
@@ -2082,8 +2106,8 @@
{
.src = MSM_BUS_MASTER_VIDEO_CAP,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1280 * 720 * 3 * 60 / 16,
- .ib = 1280 * 720 * 3 * 60 / 16 * 1.5,
+ .ab = 1280 * 720 * 3 * 60,
+ .ib = 1280 * 720 * 3 * 60 * 1.5,
},
};
@@ -2091,8 +2115,8 @@
{
.src = MSM_BUS_MASTER_VIDEO_CAP,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1280 * 720 * 3 * 60 / 16,
- .ib = 1280 * 720 * 3 * 60 / 16 * 1.5,
+ .ab = 1280 * 720 * 3 * 60,
+ .ib = 1280 * 720 * 3 * 60 * 1.5,
},
};
@@ -2100,8 +2124,8 @@
{
.src = MSM_BUS_MASTER_VIDEO_CAP,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1920 * 1080 * 3 * 60 / 16,
- .ib = 1920 * 1080 * 3 * 60 / 16 * 1.5,
+ .ab = 1920 * 1080 * 3 * 60,
+ .ib = 1920 * 1080 * 3 * 60 * 1.5,
},
};
@@ -2226,3 +2250,161 @@
.num_resources = ARRAY_SIZE(msm_etm_resources),
.resource = msm_etm_resources,
};
+
+struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
+ /* Camera */
+ {
+ .name = "vpe_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vpe_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_imgwr",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_misc",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_src",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_dst",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_mm1",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_b_mm2",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_stream",
+ .domain = VIDEO_DOMAIN,
+ },
+};
+
+static struct mem_pool apq8064_video_pools[] = {
+ /*
+ * Video hardware has the following requirements:
+ * 1. All video addresses used by the video hardware must be at a higher
+ * address than video firmware address.
+ * 2. Video hardware can only access a range of 256MB from the base of
+ * the video firmware.
+ */
+ [VIDEO_FIRMWARE_POOL] =
+ /* Low addresses, intended for video firmware */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_16M - SZ_128K,
+ },
+ [VIDEO_MAIN_POOL] =
+ /* Main video pool */
+ {
+ .paddr = SZ_16M,
+ .size = SZ_256M - SZ_16M,
+ },
+ [GEN_POOL] =
+ /* Remaining address space up to 2G */
+ {
+ .paddr = SZ_256M,
+ .size = SZ_2G - SZ_256M,
+ },
+};
+
+static struct mem_pool apq8064_camera_pools[] = {
+ [GEN_POOL] =
+ /* One address space for camera */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool apq8064_display_pools[] = {
+ [GEN_POOL] =
+ /* One address space for display */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool apq8064_rotator_pools[] = {
+ [GEN_POOL] =
+ /* One address space for rotator */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct msm_iommu_domain apq8064_iommu_domains[] = {
+ [VIDEO_DOMAIN] = {
+ .iova_pools = apq8064_video_pools,
+ .npools = ARRAY_SIZE(apq8064_video_pools),
+ },
+ [CAMERA_DOMAIN] = {
+ .iova_pools = apq8064_camera_pools,
+ .npools = ARRAY_SIZE(apq8064_camera_pools),
+ },
+ [DISPLAY_DOMAIN] = {
+ .iova_pools = apq8064_display_pools,
+ .npools = ARRAY_SIZE(apq8064_display_pools),
+ },
+ [ROTATOR_DOMAIN] = {
+ .iova_pools = apq8064_rotator_pools,
+ .npools = ARRAY_SIZE(apq8064_rotator_pools),
+ },
+};
+
+struct iommu_domains_pdata apq8064_iommu_domain_pdata = {
+ .domains = apq8064_iommu_domains,
+ .ndomains = ARRAY_SIZE(apq8064_iommu_domains),
+ .domain_names = apq8064_iommu_ctx_names,
+ .nnames = ARRAY_SIZE(apq8064_iommu_ctx_names),
+ .domain_alloc_flags = 0,
+};
+
+struct platform_device apq8064_iommu_domain_device = {
+ .name = "iommu_domains",
+ .id = -1,
+ .dev = {
+ .platform_data = &apq8064_iommu_domain_pdata,
+ },
+};
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 85e927e..b7048db 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -22,6 +22,7 @@
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/socinfo.h>
+#include <mach/iommu_domains.h>
#include "devices.h"
#include "rpm_log.h"
@@ -628,3 +629,161 @@
}
platform_add_devices(vidc_device, ARRAY_SIZE(vidc_device));
}
+
+struct msm_iommu_domain_name msm8930_iommu_ctx_names[] = {
+ /* Camera */
+ {
+ .name = "vpe_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vpe_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_imgwr",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_misc",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_src",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_dst",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_mm1",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_b_mm2",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_stream",
+ .domain = VIDEO_DOMAIN,
+ },
+};
+
+static struct mem_pool msm8930_video_pools[] = {
+ /*
+ * Video hardware has the following requirements:
+ * 1. All video addresses used by the video hardware must be at a higher
+ * address than video firmware address.
+ * 2. Video hardware can only access a range of 256MB from the base of
+ * the video firmware.
+ */
+ [VIDEO_FIRMWARE_POOL] =
+ /* Low addresses, intended for video firmware */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_16M - SZ_128K,
+ },
+ [VIDEO_MAIN_POOL] =
+ /* Main video pool */
+ {
+ .paddr = SZ_16M,
+ .size = SZ_256M - SZ_16M,
+ },
+ [GEN_POOL] =
+ /* Remaining address space up to 2G */
+ {
+ .paddr = SZ_256M,
+ .size = SZ_2G - SZ_256M,
+ },
+};
+
+static struct mem_pool msm8930_camera_pools[] = {
+ [GEN_POOL] =
+ /* One address space for camera */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool msm8930_display_pools[] = {
+ [GEN_POOL] =
+ /* One address space for display */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool msm8930_rotator_pools[] = {
+ [GEN_POOL] =
+ /* One address space for rotator */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct msm_iommu_domain msm8930_iommu_domains[] = {
+ [VIDEO_DOMAIN] = {
+ .iova_pools = msm8930_video_pools,
+ .npools = ARRAY_SIZE(msm8930_video_pools),
+ },
+ [CAMERA_DOMAIN] = {
+ .iova_pools = msm8930_camera_pools,
+ .npools = ARRAY_SIZE(msm8930_camera_pools),
+ },
+ [DISPLAY_DOMAIN] = {
+ .iova_pools = msm8930_display_pools,
+ .npools = ARRAY_SIZE(msm8930_display_pools),
+ },
+ [ROTATOR_DOMAIN] = {
+ .iova_pools = msm8930_rotator_pools,
+ .npools = ARRAY_SIZE(msm8930_rotator_pools),
+ },
+};
+
+struct iommu_domains_pdata msm8930_iommu_domain_pdata = {
+ .domains = msm8930_iommu_domains,
+ .ndomains = ARRAY_SIZE(msm8930_iommu_domains),
+ .domain_names = msm8930_iommu_ctx_names,
+ .nnames = ARRAY_SIZE(msm8930_iommu_ctx_names),
+ .domain_alloc_flags = 0,
+};
+
+struct platform_device msm8930_iommu_domain_device = {
+ .name = "iommu_domains",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm8930_iommu_domain_pdata,
+ },
+};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 894c13f..8df1d7a 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -47,6 +47,7 @@
#include "pil-q6v4.h"
#include "scm-pas.h"
#include <mach/msm_dcvs.h>
+#include <mach/iommu_domains.h>
#ifdef CONFIG_MSM_MPM
#include <mach/mpm.h>
@@ -3343,3 +3344,161 @@
.num_resources = ARRAY_SIZE(msm_cache_erp_resources),
.resource = msm_cache_erp_resources,
};
+
+struct msm_iommu_domain_name msm8960_iommu_ctx_names[] = {
+ /* Camera */
+ {
+ .name = "vpe_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vpe_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_imgwr",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_misc",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_src",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_dst",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_mm1",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_b_mm2",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_stream",
+ .domain = VIDEO_DOMAIN,
+ },
+};
+
+static struct mem_pool msm8960_video_pools[] = {
+ /*
+ * Video hardware has the following requirements:
+ * 1. All video addresses used by the video hardware must be at a higher
+ * address than video firmware address.
+ * 2. Video hardware can only access a range of 256MB from the base of
+ * the video firmware.
+ */
+ [VIDEO_FIRMWARE_POOL] =
+ /* Low addresses, intended for video firmware */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_16M - SZ_128K,
+ },
+ [VIDEO_MAIN_POOL] =
+ /* Main video pool */
+ {
+ .paddr = SZ_16M,
+ .size = SZ_256M - SZ_16M,
+ },
+ [GEN_POOL] =
+ /* Remaining address space up to 2G */
+ {
+ .paddr = SZ_256M,
+ .size = SZ_2G - SZ_256M,
+ },
+};
+
+static struct mem_pool msm8960_camera_pools[] = {
+ [GEN_POOL] =
+ /* One address space for camera */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool msm8960_display_pools[] = {
+ [GEN_POOL] =
+ /* One address space for display */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool msm8960_rotator_pools[] = {
+ [GEN_POOL] =
+ /* One address space for rotator */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct msm_iommu_domain msm8960_iommu_domains[] = {
+ [VIDEO_DOMAIN] = {
+ .iova_pools = msm8960_video_pools,
+ .npools = ARRAY_SIZE(msm8960_video_pools),
+ },
+ [CAMERA_DOMAIN] = {
+ .iova_pools = msm8960_camera_pools,
+ .npools = ARRAY_SIZE(msm8960_camera_pools),
+ },
+ [DISPLAY_DOMAIN] = {
+ .iova_pools = msm8960_display_pools,
+ .npools = ARRAY_SIZE(msm8960_display_pools),
+ },
+ [ROTATOR_DOMAIN] = {
+ .iova_pools = msm8960_rotator_pools,
+ .npools = ARRAY_SIZE(msm8960_rotator_pools),
+ },
+};
+
+struct iommu_domains_pdata msm8960_iommu_domain_pdata = {
+ .domains = msm8960_iommu_domains,
+ .ndomains = ARRAY_SIZE(msm8960_iommu_domains),
+ .domain_names = msm8960_iommu_ctx_names,
+ .nnames = ARRAY_SIZE(msm8960_iommu_ctx_names),
+ .domain_alloc_flags = 0,
+};
+
+struct platform_device msm8960_iommu_domain_device = {
+ .name = "iommu_domains",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm8960_iommu_domain_pdata,
+ },
+};
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 60bcdce..34298c5 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1247,18 +1247,6 @@
},
};
-uint32_t __init msm9615_rpm_get_swfi_latency(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
- if (msm_rpmrs_levels[i].sleep_mode ==
- MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
- return msm_rpmrs_levels[i].latency_us;
- }
- return 0;
-}
-
void __init msm9615_device_init(void)
{
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 29e8180..9a03afd 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -376,11 +376,13 @@
static struct msm_iommu_dev gfx2d0_iommu = {
.name = "gfx2d0",
.ncb = 2,
+ .ttbr_split = 2,
};
static struct msm_iommu_dev gfx2d1_iommu = {
.name = "gfx2d1",
.ncb = 2,
+ .ttbr_split = 2,
};
static struct msm_iommu_dev vcap_iommu = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 48a38f0..5718fe0 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -238,6 +238,7 @@
extern struct platform_device apq_pcm_routing;
extern struct platform_device apq_cpudai0;
extern struct platform_device apq_cpudai1;
+extern struct platform_device mpq_cpudai_mi2s_tx;
extern struct platform_device apq_cpudai_hdmi_rx;
extern struct platform_device apq_cpudai_bt_rx;
extern struct platform_device apq_cpudai_bt_tx;
@@ -262,6 +263,8 @@
extern struct platform_device apq_cpudai_slimbus_1_rx;
extern struct platform_device apq_cpudai_slimbus_1_tx;
extern struct platform_device apq_cpudai_slimbus_2_tx;
+extern struct platform_device apq_cpudai_slim_4_rx;
+extern struct platform_device apq_cpudai_slim_4_tx;
extern struct platform_device *msm_footswitch_devices[];
extern unsigned msm_num_footswitch_devices;
@@ -370,5 +373,8 @@
extern struct platform_device msm_device_csic1;
extern struct platform_device msm_device_vfe;
extern struct platform_device msm_device_vpe;
-
extern struct platform_device mpq8064_device_qup_i2c_gsbi5;
+
+extern struct platform_device msm8960_iommu_domain_device;
+extern struct platform_device msm8930_iommu_domain_device;
+extern struct platform_device apq8064_iommu_domain_device;
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index c92c049..bde7713 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -638,6 +638,11 @@
fs->clk_data = gfx3d_8064_clks;
else
fs->clk_data = gfx3d_8660_clks;
+ } else if (pdev->id == FS_VED) {
+ if (cpu_is_apq8064()) {
+ fs->bus_port0 = MSM_BUS_MASTER_VIDEO_ENC;
+ fs->bus_port1 = MSM_BUS_MASTER_VIDEO_DEC;
+ }
}
for (clock = fs->clk_data; clock->name; clock++) {
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 36cdd86..c46c493 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -475,6 +475,12 @@
bool (*check_hdcp_hw_support)(void);
};
+struct msm_mhl_platform_data {
+ int irq;
+ int (*gpio_setup)(int on);
+ void (*reset_pin)(int on);
+};
+
struct msm_i2c_platform_data {
int clk_freq;
uint32_t rmutex;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index e6a0175..7857e69 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -365,6 +365,7 @@
struct list_head list_frame;
struct list_head list_pict;
struct list_head list_vpe_frame;
+ struct list_head list_eventdata;
enum msm_queue type;
void *command;
atomic_t on_heap;
@@ -638,8 +639,6 @@
};
int msm_camio_enable(struct platform_device *dev);
-int msm_camio_jpeg_clk_enable(void);
-int msm_camio_jpeg_clk_disable(void);
int msm_camio_vpe_clk_enable(uint32_t);
int msm_camio_vpe_clk_disable(void);
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index c17795a..52e70ec 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -13,6 +13,8 @@
#ifndef _ARCH_IOMMU_DOMAINS_H
#define _ARCH_IOMMU_DOMAINS_H
+#include <linux/memory_alloc.h>
+
enum {
VIDEO_DOMAIN,
CAMERA_DOMAIN,
@@ -27,6 +29,32 @@
GEN_POOL,
};
+struct msm_iommu_domain_name {
+ char *name;
+ int domain;
+};
+
+struct msm_iommu_domain {
+ /* iommu domain to map in */
+ struct iommu_domain *domain;
+ /* total number of allocations from this domain */
+ atomic_t allocation_cnt;
+ /* number of iova pools */
+ int npools;
+ /*
+ * array of gen_pools for allocating iovas.
+ * behavior is undefined if these overlap
+ */
+ struct mem_pool *iova_pools;
+};
+
+struct iommu_domains_pdata {
+ struct msm_iommu_domain *domains;
+ int ndomains;
+ struct msm_iommu_domain_name *domain_names;
+ int nnames;
+ unsigned int domain_alloc_flags;
+};
#if defined(CONFIG_MSM_IOMMU)
@@ -42,10 +70,6 @@
unsigned int partition_no,
unsigned long size);
-extern unsigned long msm_subsystem_get_domain_no(int subsys_id);
-
-extern unsigned long msm_subsystem_get_partition_no(int subsys_id);
-
extern int msm_use_iommu(void);
extern int msm_iommu_map_extra(struct iommu_domain *domain,
@@ -69,16 +93,6 @@
unsigned int partition_no,
unsigned long size) { return; }
-static inline unsigned long msm_subsystem_get_domain_no(int subsys_id)
-{
- return 0xFFFFFFFF;
-}
-
-static inline unsigned long msm_subsystem_get_partition_no(int subsys_id)
-{
- return 0xFFFFFFFF;
-}
-
static inline int msm_use_iommu(void)
{
return 0;
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index f7becef..51ace96 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -22,7 +22,6 @@
RESET_SOC = 1,
RESET_SUBSYS_COUPLED,
RESET_SUBSYS_INDEPENDENT,
- RESET_SUBSYS_MIXED = 25,
RESET_LEVEL_MAX
};
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 1959f5d..8f4af3b 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -13,6 +13,7 @@
#include <mach/msm_subsystem_map.h>
#include <linux/memory_alloc.h>
#include <linux/iommu.h>
+#include <linux/platform_device.h>
#include <linux/vmalloc.h>
#include <asm/sizes.h>
#include <asm/page.h>
@@ -24,166 +25,12 @@
/* dummy 4k for overmapping */
char iommu_dummy[2*PAGE_SIZE-4];
-struct msm_iommu_domain {
- /* iommu domain to map in */
- struct iommu_domain *domain;
- /* total number of allocations from this domain */
- atomic_t allocation_cnt;
- /* number of iova pools */
- int npools;
- /*
- * array of gen_pools for allocating iovas.
- * behavior is undefined if these overlap
- */
- struct mem_pool *iova_pools;
-
+struct msm_iommu_domain_state {
+ struct msm_iommu_domain *domains;
+ int ndomains;
};
-
-struct {
- char *name;
- int domain;
-} msm_iommu_ctx_names[] = {
- /* Camera */
- {
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "ijpeg_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "ijpeg_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "jpegd_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "jpegd_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Rotator */
- {
- .name = "rot_src",
- .domain = ROTATOR_DOMAIN,
- },
- /* Rotator */
- {
- .name = "rot_dst",
- .domain = ROTATOR_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_a_mm1",
- .domain = VIDEO_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_b_mm2",
- .domain = VIDEO_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_a_stream",
- .domain = VIDEO_DOMAIN,
- },
-};
-
-static struct mem_pool video_pools[] = {
- /*
- * Video hardware has the following requirements:
- * 1. All video addresses used by the video hardware must be at a higher
- * address than video firmware address.
- * 2. Video hardware can only access a range of 256MB from the base of
- * the video firmware.
- */
- [VIDEO_FIRMWARE_POOL] =
- /* Low addresses, intended for video firmware */
- {
- .paddr = SZ_128K,
- .size = SZ_16M - SZ_128K,
- },
- [VIDEO_MAIN_POOL] =
- /* Main video pool */
- {
- .paddr = SZ_16M,
- .size = SZ_256M - SZ_16M,
- },
- [GEN_POOL] =
- /* Remaining address space up to 2G */
- {
- .paddr = SZ_256M,
- .size = SZ_2G - SZ_256M,
- },
-};
-
-static struct mem_pool camera_pools[] = {
- [GEN_POOL] =
- /* One address space for camera */
- {
- .paddr = SZ_128K,
- .size = SZ_2G - SZ_128K,
- },
-};
-
-static struct mem_pool display_pools[] = {
- [GEN_POOL] =
- /* One address space for display */
- {
- .paddr = SZ_128K,
- .size = SZ_2G - SZ_128K,
- },
-};
-
-static struct mem_pool rotator_pools[] = {
- [GEN_POOL] =
- /* One address space for rotator */
- {
- .paddr = SZ_128K,
- .size = SZ_2G - SZ_128K,
- },
-};
-
-static struct msm_iommu_domain msm_iommu_domains[] = {
- [VIDEO_DOMAIN] = {
- .iova_pools = video_pools,
- .npools = ARRAY_SIZE(video_pools),
- },
- [CAMERA_DOMAIN] = {
- .iova_pools = camera_pools,
- .npools = ARRAY_SIZE(camera_pools),
- },
- [DISPLAY_DOMAIN] = {
- .iova_pools = display_pools,
- .npools = ARRAY_SIZE(display_pools),
- },
- [ROTATOR_DOMAIN] = {
- .iova_pools = rotator_pools,
- .npools = ARRAY_SIZE(rotator_pools),
- },
-};
+static struct msm_iommu_domain_state domain_state;
int msm_iommu_map_extra(struct iommu_domain *domain,
unsigned long start_iova,
@@ -221,46 +68,12 @@
struct iommu_domain *msm_get_iommu_domain(int domain_num)
{
- if (domain_num >= 0 && domain_num < MAX_DOMAINS)
- return msm_iommu_domains[domain_num].domain;
+ if (domain_num >= 0 && domain_num < domain_state.ndomains)
+ return domain_state.domains[domain_num].domain;
else
return NULL;
}
-static unsigned long subsystem_to_domain_tbl[] = {
- VIDEO_DOMAIN,
- VIDEO_DOMAIN,
- CAMERA_DOMAIN,
- DISPLAY_DOMAIN,
- ROTATOR_DOMAIN,
- 0xFFFFFFFF
-};
-
-unsigned long msm_subsystem_get_domain_no(int subsys_id)
-{
- if (subsys_id > INVALID_SUBSYS_ID && subsys_id <= MAX_SUBSYSTEM_ID &&
- subsys_id < ARRAY_SIZE(subsystem_to_domain_tbl))
- return subsystem_to_domain_tbl[subsys_id];
- else
- return subsystem_to_domain_tbl[MAX_SUBSYSTEM_ID];
-}
-
-unsigned long msm_subsystem_get_partition_no(int subsys_id)
-{
- switch (subsys_id) {
- case MSM_SUBSYSTEM_VIDEO_FWARE:
- return VIDEO_FIRMWARE_POOL;
- case MSM_SUBSYSTEM_VIDEO:
- return VIDEO_MAIN_POOL;
- case MSM_SUBSYSTEM_CAMERA:
- case MSM_SUBSYSTEM_DISPLAY:
- case MSM_SUBSYSTEM_ROTATOR:
- return GEN_POOL;
- default:
- return 0xFFFFFFFF;
- }
-}
-
unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
unsigned int partition_no,
unsigned long size,
@@ -269,13 +82,13 @@
struct mem_pool *pool;
unsigned long iova;
- if (iommu_domain >= MAX_DOMAINS)
+ if (iommu_domain >= domain_state.ndomains)
return 0;
- if (partition_no >= msm_iommu_domains[iommu_domain].npools)
+ if (partition_no >= domain_state.domains[iommu_domain].npools)
return 0;
- pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+ pool = &domain_state.domains[iommu_domain].iova_pools[partition_no];
if (!pool->gpool)
return 0;
@@ -294,18 +107,18 @@
{
struct mem_pool *pool;
- if (iommu_domain >= MAX_DOMAINS) {
+ if (iommu_domain >= domain_state.ndomains) {
WARN(1, "Invalid domain %d\n", iommu_domain);
return;
}
- if (partition_no >= msm_iommu_domains[iommu_domain].npools) {
+ if (partition_no >= domain_state.domains[iommu_domain].npools) {
WARN(1, "Invalid partition %d for domain %d\n",
partition_no, iommu_domain);
return;
}
- pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+ pool = &domain_state.domains[iommu_domain].iova_pools[partition_no];
if (!pool)
return;
@@ -316,20 +129,31 @@
int msm_use_iommu()
{
- return iommu_found();
+ /*
+ * If there are no domains, don't bother trying to use the iommu
+ */
+ return domain_state.ndomains && iommu_found();
}
-static int __init msm_subsystem_iommu_init(void)
+static int __init iommu_domain_probe(struct platform_device *pdev)
{
+ struct iommu_domains_pdata *p = pdev->dev.platform_data;
int i, j;
- for (i = 0; i < ARRAY_SIZE(msm_iommu_domains); i++) {
- msm_iommu_domains[i].domain = iommu_domain_alloc(0);
- if (!msm_iommu_domains[i].domain)
+ if (!p)
+ return -ENODEV;
+
+ domain_state.domains = p->domains;
+ domain_state.ndomains = p->ndomains;
+
+ for (i = 0; i < domain_state.ndomains; i++) {
+ domain_state.domains[i].domain = iommu_domain_alloc(
+ p->domain_alloc_flags);
+ if (!domain_state.domains[i].domain)
continue;
- for (j = 0; j < msm_iommu_domains[i].npools; j++) {
- struct mem_pool *pool = &msm_iommu_domains[i].
+ for (j = 0; j < domain_state.domains[i].npools; j++) {
+ struct mem_pool *pool = &domain_state.domains[i].
iova_pools[j];
mutex_init(&pool->pool_mutex);
if (pool->size) {
@@ -359,29 +183,41 @@
}
}
- for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
+ for (i = 0; i < p->nnames; i++) {
int domain_idx;
struct device *ctx = msm_iommu_get_ctx(
- msm_iommu_ctx_names[i].name);
+ p->domain_names[i].name);
if (!ctx)
continue;
- domain_idx = msm_iommu_ctx_names[i].domain;
+ domain_idx = p->domain_names[i].domain;
- if (!msm_iommu_domains[domain_idx].domain)
+ if (!domain_state.domains[domain_idx].domain)
continue;
- if (iommu_attach_device(msm_iommu_domains[domain_idx].domain,
+ if (iommu_attach_device(domain_state.domains[domain_idx].domain,
ctx)) {
WARN(1, "%s: could not attach domain %d to context %s."
" iommu programming will not occur.\n",
__func__, domain_idx,
- msm_iommu_ctx_names[i].name);
+ p->domain_names[i].name);
continue;
}
}
return 0;
}
+
+static struct platform_driver iommu_domain_driver = {
+ .driver = {
+ .name = "iommu_domains",
+ .owner = THIS_MODULE
+ },
+};
+
+static int __init msm_subsystem_iommu_init(void)
+{
+ return platform_driver_probe(&iommu_domain_driver, iommu_domain_probe);
+}
device_initcall(msm_subsystem_iommu_init);
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index a90be23..462543e 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -138,7 +138,7 @@
struct msm_ipc_sock {
struct sock sk;
struct msm_ipc_port *port;
- void *default_pil;
+ void *modem_pil;
};
enum write_data_type {
@@ -206,15 +206,4 @@
int msm_ipc_router_init_sockets(void);
void msm_ipc_router_exit_sockets(void);
-#if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT
-extern void *msm_ipc_load_default_node(void);
-
-extern void msm_ipc_unload_default_node(void *pil);
-#else
-static inline void *msm_ipc_load_default_node(void)
-{ return NULL; }
-
-static inline void msm_ipc_unload_default_node(void *pil) { }
-#endif
-
#endif
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index 307b6ae..0cde393 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -19,7 +19,6 @@
#include <linux/types.h>
#include <mach/msm_smd.h>
-#include <mach/peripheral-loader.h>
#include "ipc_router.h"
#include "smd_private.h"
@@ -443,31 +442,6 @@
return 0;
}
-void *msm_ipc_load_default_node(void)
-{
- void *pil = NULL;
- const char *peripheral;
-
- peripheral = smd_edge_to_subsystem(SMD_APPS_MODEM);
- if (peripheral && !strncmp(peripheral, "modem", 6)) {
- pil = pil_get(peripheral);
- if (IS_ERR(pil)) {
- pr_err("%s: Failed to load %s\n",
- __func__, peripheral);
- pil = NULL;
- }
- }
- return pil;
-}
-EXPORT_SYMBOL(msm_ipc_load_default_node);
-
-void msm_ipc_unload_default_node(void *pil)
-{
- if (pil)
- pil_put(pil);
-}
-EXPORT_SYMBOL(msm_ipc_unload_default_node);
-
static struct platform_driver msm_ipc_router_smd_remote_driver[] = {
{
.probe = msm_ipc_router_smd_remote_probe,
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index d1ed538..6e8c99e 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -26,15 +26,58 @@
#include <net/sock.h>
+#include <mach/peripheral-loader.h>
+#include <mach/socinfo.h>
+
#include "ipc_router.h"
#define msm_ipc_sk(sk) ((struct msm_ipc_sock *)(sk))
#define msm_ipc_sk_port(sk) ((struct msm_ipc_port *)(msm_ipc_sk(sk)->port))
+#define MODEM_LOAD_TIMEOUT (10 * HZ)
static int sockets_enabled;
static struct proto msm_ipc_proto;
static const struct proto_ops msm_ipc_proto_ops;
+static void msm_ipc_router_unload_modem(void *pil)
+{
+ if (pil)
+ pil_put(pil);
+}
+
+static void *msm_ipc_router_load_modem(void)
+{
+ void *pil = NULL;
+ int rc;
+
+ /* Load GNSS for Standalone 8064 but not for Fusion 3 */
+ if (cpu_is_apq8064()) {
+ if (socinfo_get_platform_subtype() == 0x0)
+ pil = pil_get("gss");
+ } else {
+ pil = pil_get("modem");
+ }
+
+ if (IS_ERR(pil) || !pil) {
+ pr_debug("%s: modem load failed\n", __func__);
+ pil = NULL;
+ } else {
+ rc = wait_for_completion_interruptible_timeout(
+ &msm_ipc_remote_router_up,
+ MODEM_LOAD_TIMEOUT);
+ if (!rc)
+ rc = -ETIMEDOUT;
+ if (rc < 0) {
+ pr_err("%s: wait for remote router failed %d\n",
+ __func__, rc);
+ msm_ipc_router_unload_modem(pil);
+ pil = NULL;
+ }
+ }
+
+ return pil;
+}
+
static struct sk_buff_head *msm_ipc_router_build_msg(unsigned int num_sect,
struct iovec const *msg_sect,
size_t total_len)
@@ -201,9 +244,9 @@
sock_init_data(sock, sk);
sk->sk_rcvtimeo = DEFAULT_RCV_TIMEO;
- pil = msm_ipc_load_default_node();
+ pil = msm_ipc_router_load_modem();
msm_ipc_sk(sk)->port = port_ptr;
- msm_ipc_sk(sk)->default_pil = pil;
+ msm_ipc_sk(sk)->modem_pil = pil;
return 0;
}
@@ -452,12 +495,12 @@
{
struct sock *sk = sock->sk;
struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
- void *pil = msm_ipc_sk(sk)->default_pil;
+ void *pil = msm_ipc_sk(sk)->modem_pil;
int ret;
lock_sock(sk);
ret = msm_ipc_router_close_port(port_ptr);
- msm_ipc_unload_default_node(pil);
+ msm_ipc_router_unload_modem(pil);
release_sock(sk);
sock_put(sk);
sock->sk = NULL;
diff --git a/arch/arm/mach-msm/lpass-8660.c b/arch/arm/mach-msm/lpass-8660.c
index ff08eff..1018360 100644
--- a/arch/arm/mach-msm/lpass-8660.c
+++ b/arch/arm/mach-msm/lpass-8660.c
@@ -79,9 +79,6 @@
pil_force_shutdown("q6");
disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
- if (get_restart_level() == RESET_SUBSYS_MIXED)
- smsm_reset_modem(SMSM_RESET);
-
return 0;
}
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 403c13d..9dbf9c1 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -74,6 +74,17 @@
module_param_named(filter, msm_rtb.filter, uint, 0644);
module_param_named(enable, msm_rtb.enabled, int, 0644);
+static int msm_rtb_panic_notifier(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ msm_rtb.enabled = 0;
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block msm_rtb_panic_blk = {
+ .notifier_call = msm_rtb_panic_notifier,
+};
+
int msm_rtb_event_should_log(enum logk_event_type log_type)
{
return msm_rtb.initialized && msm_rtb.enabled &&
@@ -258,7 +269,8 @@
msm_rtb.step_size = 1;
#endif
-
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &msm_rtb_panic_blk);
msm_rtb.initialized = 1;
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
new file mode 100644
index 0000000..60ae4d9
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/err.h>
+#include <linux/of.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+
+/* Register Offsets */
+#define QDSP6SS_RST_EVB 0x010
+#define LPASS_Q6SS_BCR 0x06000
+#define LPASS_Q6SS_AHB_LFABIF_CBCR 0x22000
+#define LPASS_Q6SS_XO_CBCR 0x26000
+#define AXI_HALTREQ 0x0
+#define AXI_HALTACK 0x4
+#define AXI_IDLE 0x8
+
+#define HALT_ACK_TIMEOUT_US 100000
+
+static void clk_reg_enable(void __iomem *reg)
+{
+ u32 val;
+ val = readl_relaxed(reg);
+ val |= BIT(0);
+ writel_relaxed(val, reg);
+}
+
+static void clk_reg_disable(void __iomem *reg)
+{
+ u32 val;
+ val = readl_relaxed(reg);
+ val &= ~BIT(0);
+ writel_relaxed(val, reg);
+}
+
+static int pil_lpass_shutdown(struct pil_desc *pil)
+{
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+ int ret;
+ u32 status;
+
+ writel_relaxed(1, drv->axi_halt_base + AXI_HALTREQ);
+ ret = readl_poll_timeout(drv->axi_halt_base + AXI_HALTACK,
+ status, status, 50, HALT_ACK_TIMEOUT_US);
+ if (ret)
+ dev_err(pil->dev, "Port halt timeout\n");
+ else if (!readl_relaxed(drv->axi_halt_base + AXI_IDLE))
+ dev_err(pil->dev, "Port halt failed\n");
+ writel_relaxed(0, drv->axi_halt_base + AXI_HALTREQ);
+
+ /* Make sure Q6 registers are accessible */
+ writel_relaxed(0, drv->clk_base + LPASS_Q6SS_BCR);
+ clk_reg_enable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+ mb();
+
+ pil_q6v5_shutdown(pil);
+
+ /* Disable clocks and assert subsystem resets. */
+ clk_reg_disable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+ clk_reg_disable(drv->clk_base + LPASS_Q6SS_XO_CBCR);
+ writel_relaxed(1, drv->clk_base + LPASS_Q6SS_BCR);
+
+ return 0;
+}
+
+static int pil_lpass_reset(struct pil_desc *pil)
+{
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+ /*
+ * Bring subsystem out of reset and enable required
+ * regulators and clocks.
+ */
+ writel_relaxed(0, drv->clk_base + LPASS_Q6SS_BCR);
+ clk_reg_enable(drv->clk_base + LPASS_Q6SS_XO_CBCR);
+ clk_reg_enable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+ mb();
+
+ /* Program Image Address */
+ writel_relaxed(((drv->start_addr >> 4) & 0x0FFFFFF0),
+ drv->reg_base + QDSP6SS_RST_EVB);
+
+ return pil_q6v5_reset(pil);
+}
+
+static struct pil_reset_ops pil_lpass_ops = {
+ .init_image = pil_q6v5_init_image,
+ .proxy_vote = pil_q6v5_make_proxy_votes,
+ .proxy_unvote = pil_q6v5_remove_proxy_votes,
+ .auth_and_reset = pil_lpass_reset,
+ .shutdown = pil_lpass_shutdown,
+};
+
+static int __devinit pil_lpass_driver_probe(struct platform_device *pdev)
+{
+ struct q6v5_data *drv;
+ struct pil_desc *desc;
+ struct resource *res;
+
+ desc = pil_q6v5_init(pdev);
+ drv = platform_get_drvdata(pdev);
+
+ desc->ops = &pil_lpass_ops;
+ desc->owner = THIS_MODULE;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ drv->axi_halt_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->axi_halt_base)
+ return -ENOMEM;
+
+ drv->pil = msm_pil_register(desc);
+ if (IS_ERR(drv->pil))
+ return PTR_ERR(drv->pil);
+
+ return 0;
+}
+
+static int __devexit pil_lpass_driver_exit(struct platform_device *pdev)
+{
+ struct q6v5_data *drv = platform_get_drvdata(pdev);
+ msm_pil_unregister(drv->pil);
+ return 0;
+}
+
+static struct of_device_id lpass_match_table[] = {
+ { .compatible = "qcom,pil-q6v5-lpass" },
+ {}
+};
+
+static struct platform_driver pil_lpass_driver = {
+ .probe = pil_lpass_driver_probe,
+ .remove = __devexit_p(pil_lpass_driver_exit),
+ .driver = {
+ .name = "pil-q6v5-lpass",
+ .of_match_table = lpass_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pil_lpass_init(void)
+{
+ return platform_driver_register(&pil_lpass_driver);
+}
+module_init(pil_lpass_init);
+
+static void __exit pil_lpass_exit(void)
+{
+ platform_driver_unregister(&pil_lpass_driver);
+}
+module_exit(pil_lpass_exit);
+
+MODULE_DESCRIPTION("Support for booting low-power audio subsystems with QDSP6v5 (Hexagon) processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
new file mode 100644
index 0000000..cd58a4c
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/elf.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+
+/* Register Offsets */
+#define QDSP6SS_RESET 0x014
+#define QDSP6SS_GFMUX_CTL 0x020
+#define QDSP6SS_PWR_CTL 0x030
+
+/* QDSP6SS_RESET */
+#define Q6SS_CORE_ARES BIT(1)
+#define Q6SS_ETM_ISDB_ARES BIT(3)
+#define Q6SS_STOP_CORE BIT(4)
+
+/* QDSP6SS_GFMUX_CTL */
+#define Q6SS_CLK_ENA BIT(1)
+
+/* QDSP6SS_PWR_CTL */
+#define Q6SS_L2DATA_SLP_NRET_N BIT(0)
+#define Q6SS_L2TAG_SLP_NRET_N BIT(16)
+#define Q6SS_ETB_SLP_NRET_N BIT(17)
+#define Q6SS_L2DATA_STBY_N BIT(18)
+#define Q6SS_SLP_RET_N BIT(19)
+#define Q6SS_CLAMP_IO BIT(20)
+#define QDSS_BHS_ON BIT(21)
+
+int pil_q6v5_make_proxy_votes(struct pil_desc *pil)
+{
+ int ret;
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+ ret = clk_prepare_enable(drv->xo);
+ if (ret) {
+ dev_err(pil->dev, "Failed to enable XO\n");
+ return ret;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(pil_q6v5_make_proxy_votes);
+
+void pil_q6v5_remove_proxy_votes(struct pil_desc *pil)
+{
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+ clk_disable_unprepare(drv->xo);
+}
+EXPORT_SYMBOL(pil_q6v5_remove_proxy_votes);
+
+int pil_q6v5_init_image(struct pil_desc *pil, const u8 *metadata,
+ size_t size)
+{
+ const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+ drv->start_addr = ehdr->e_entry;
+ return 0;
+}
+EXPORT_SYMBOL(pil_q6v5_init_image);
+
+void pil_q6v5_shutdown(struct pil_desc *pil)
+{
+ u32 val;
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+ /* Turn off core clock */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_GFMUX_CTL);
+ val &= ~Q6SS_CLK_ENA;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_GFMUX_CTL);
+
+ /* Clamp IO */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
+ val |= Q6SS_CLAMP_IO;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+
+ /* Turn off Q6 memories */
+ val &= ~(Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N |
+ Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLP_NRET_N |
+ Q6SS_L2DATA_STBY_N);
+ writel_relaxed(Q6SS_CLAMP_IO, drv->reg_base + QDSP6SS_PWR_CTL);
+
+ /* Assert Q6 resets */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
+ val = (Q6SS_CORE_ARES | Q6SS_ETM_ISDB_ARES);
+ writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+
+ /* Kill power at block headswitch (affects LPASS only) */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
+ val &= ~QDSS_BHS_ON;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+}
+EXPORT_SYMBOL(pil_q6v5_shutdown);
+
+int pil_q6v5_reset(struct pil_desc *pil)
+{
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+ u32 val;
+
+ /* Assert resets, stop core */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
+ val |= (Q6SS_CORE_ARES | Q6SS_ETM_ISDB_ARES | Q6SS_STOP_CORE);
+ writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+
+ /* Enable power block headswitch (only affects LPASS) */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
+ val |= QDSS_BHS_ON;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+
+ /* Turn on memories */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
+ val |= Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N |
+ Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLP_NRET_N |
+ Q6SS_L2DATA_STBY_N;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+
+ /* Remove IO clamp */
+ val &= ~Q6SS_CLAMP_IO;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+
+ /* Bring core out of reset */
+ val = Q6SS_STOP_CORE;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+
+ /* Turn on core clock */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_GFMUX_CTL);
+ val |= Q6SS_CLK_ENA;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_GFMUX_CTL);
+
+ /* Start core execution */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
+ val &= ~Q6SS_STOP_CORE;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+
+ return 0;
+}
+EXPORT_SYMBOL(pil_q6v5_reset);
+
+struct pil_desc __devinit *pil_q6v5_init(struct platform_device *pdev)
+{
+ struct q6v5_data *drv;
+ struct resource *res;
+ struct pil_desc *desc;
+ int ret;
+
+ drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+ if (!drv)
+ return ERR_PTR(-ENOMEM);
+ platform_set_drvdata(pdev, drv);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return ERR_PTR(-EINVAL);
+ drv->reg_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->reg_base)
+ return ERR_PTR(-ENOMEM);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ drv->clk_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->clk_base)
+ return ERR_PTR(-ENOMEM);
+
+ desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
+ &desc->name);
+ if (ret)
+ return ERR_PTR(ret);
+
+ drv->xo = devm_clk_get(&pdev->dev, "xo");
+ if (IS_ERR(drv->xo))
+ return ERR_CAST(drv->xo);
+
+ desc->dev = &pdev->dev;
+
+ return desc;
+}
+EXPORT_SYMBOL(pil_q6v5_init);
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
new file mode 100644
index 0000000..b17d4e7
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -0,0 +1,43 @@
+/*
+ * 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_PIL_Q6V5_H
+#define __MSM_PIL_Q6V5_H
+
+struct regulator;
+struct clk;
+struct pil_device;
+struct pil_desc;
+struct platform_device;
+
+struct q6v5_data {
+ void __iomem *reg_base;
+ void __iomem *clk_base;
+ void __iomem *axi_halt_base;
+ void __iomem *rmb_base;
+ unsigned long start_addr;
+ struct regulator *vreg;
+ bool vreg_enabled;
+ int self_auth;
+ struct clk *xo;
+ struct pil_device *pil;
+};
+
+int pil_q6v5_make_proxy_votes(struct pil_desc *pil);
+void pil_q6v5_remove_proxy_votes(struct pil_desc *pil);
+int pil_q6v5_init_image(struct pil_desc *pil, const u8 *metadata,
+ size_t size);
+void pil_q6v5_shutdown(struct pil_desc *pil);
+int pil_q6v5_reset(struct pil_desc *pil);
+struct pil_desc *pil_q6v5_init(struct platform_device *pdev);
+
+#endif
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 2b0cc18..c237013 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -105,6 +105,7 @@
static char *msm_pm_sleep_mode_labels[MSM_PM_SLEEP_MODE_NR] = {
[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = "power_collapse",
[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = "wfi",
+ [MSM_PM_SLEEP_MODE_RETENTION] = "retention",
[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] =
"standalone_power_collapse",
};
@@ -324,6 +325,7 @@
enum msm_pm_time_stats_id {
MSM_PM_STAT_REQUESTED_IDLE,
MSM_PM_STAT_IDLE_WFI,
+ MSM_PM_STAT_RETENTION,
MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
MSM_PM_STAT_IDLE_POWER_COLLAPSE,
MSM_PM_STAT_SUSPEND,
@@ -617,14 +619,27 @@
msm_arch_idle();
}
+
+static void msm_pm_retention(void)
+{
+ int ret = 0;
+
+ msm_pm_config_hw_before_swfi();
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_RETENTION, false);
+ WARN_ON(ret);
+ msm_arch_idle();
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
+ WARN_ON(ret);
+}
+
#ifdef CONFIG_CACHE_L2X0
static inline bool msm_pm_l2x0_power_collapse(void)
{
bool collapsed = 0;
- l2cc_suspend();
+ l2x0_suspend();
collapsed = msm_pm_collapse();
- l2cc_resume(collapsed);
+ l2x0_resume(collapsed);
return collapsed;
}
@@ -810,6 +825,11 @@
}
/* fall through */
+ case MSM_PM_SLEEP_MODE_RETENTION:
+ if (!allow)
+ break;
+ /* fall through */
+
case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
if (!allow)
break;
@@ -884,6 +904,13 @@
#endif
break;
+ case MSM_PM_SLEEP_MODE_RETENTION:
+ msm_pm_retention();
+#ifdef CONFIG_MSM_IDLE_STATS
+ exit_stat = MSM_PM_STAT_RETENTION;
+#endif
+ break;
+
case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
msm_pm_power_collapse_standalone(true);
#ifdef CONFIG_MSM_IDLE_STATS
@@ -982,6 +1009,10 @@
per_cpu(msm_pm_last_slp_mode, cpu)
= MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE;
msm_pm_power_collapse_standalone(false);
+ } else if (allow[MSM_PM_SLEEP_MODE_RETENTION]) {
+ per_cpu(msm_pm_last_slp_mode, cpu)
+ = MSM_PM_SLEEP_MODE_RETENTION;
+ msm_pm_retention();
} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
per_cpu(msm_pm_last_slp_mode, cpu)
= MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE;
@@ -1108,6 +1139,10 @@
if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
pr_info("%s: standalone power collapse\n", __func__);
msm_pm_power_collapse_standalone(false);
+ } else if (allow[MSM_PM_SLEEP_MODE_RETENTION]) {
+ if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
+ pr_info("%s: retention\n", __func__);
+ msm_pm_retention();
} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
pr_info("%s: swfi\n", __func__);
@@ -1195,6 +1230,10 @@
stats[MSM_PM_STAT_IDLE_WFI].first_bucket_time =
CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+ stats[MSM_PM_STAT_RETENTION].name = "retention";
+ stats[MSM_PM_STAT_RETENTION].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name =
"idle-standalone-power-collapse";
stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].
diff --git a/arch/arm/mach-msm/pm-data.c b/arch/arm/mach-msm/pm-data.c
index d7001d7..6f4743f 100644
--- a/arch/arm/mach-msm/pm-data.c
+++ b/arch/arm/mach-msm/pm-data.c
@@ -28,6 +28,13 @@
.suspend_enabled = 0,
},
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RETENTION)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 1,
@@ -49,6 +56,13 @@
.suspend_enabled = 0,
},
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_RETENTION)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 0,
@@ -70,6 +84,13 @@
.suspend_enabled = 0,
},
+ [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_RETENTION)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 0,
@@ -91,6 +112,13 @@
.suspend_enabled = 0,
},
+ [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_RETENTION)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 0,
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 7ef3c34..09494a0 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -44,13 +44,14 @@
};
enum msm_pm_sleep_mode {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND,
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
- MSM_PM_SLEEP_MODE_APPS_SLEEP,
- MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT,
- MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN,
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT = 0,
+ MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT = 1,
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE = 2,
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE = 3,
+ MSM_PM_SLEEP_MODE_APPS_SLEEP = 4,
+ MSM_PM_SLEEP_MODE_RETENTION = MSM_PM_SLEEP_MODE_APPS_SLEEP,
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND = 5,
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN = 6,
MSM_PM_SLEEP_MODE_NR
};
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 4518d7c..4f3c7e4 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1192,7 +1192,7 @@
#endif
#ifdef CONFIG_CACHE_L2X0
- l2cc_suspend();
+ l2x0_suspend();
#endif
collapsed = msm_pm_collapse();
@@ -1217,7 +1217,7 @@
}
#ifdef CONFIG_CACHE_L2X0
- l2cc_resume(collapsed);
+ l2x0_resume(collapsed);
#endif
msm_pm_boot_config_after_pc(smp_processor_id());
@@ -1434,14 +1434,14 @@
#ifdef CONFIG_CACHE_L2X0
if (!cpu_is_msm8625())
- l2cc_suspend();
+ l2x0_suspend();
#endif
collapsed = msm_pm_collapse();
#ifdef CONFIG_CACHE_L2X0
if (!cpu_is_msm8625())
- l2cc_resume(collapsed);
+ l2x0_resume(collapsed);
#endif
msm_pm_boot_config_after_pc(smp_processor_id());
diff --git a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
index 1dd90a7..5df976d 100644
--- a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, 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
@@ -201,8 +201,8 @@
audio->enc_cfg = kzalloc(sizeof(struct msm_audio_amrwb_enc_config),
GFP_KERNEL);
if (audio->enc_cfg == NULL) {
- pr_err("%s: Could not allocate memory for amrwb"
- "config param\n", __func__);
+ pr_err("%s:session id %d: Could not allocate memory for amrwb"
+ "config param\n", __func__, audio->ac->session);
kfree(audio);
return -ENOMEM;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
index 438909a..88189f6 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -274,10 +274,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_aac_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
index 9618adb..6768f7a 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -138,10 +138,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_amrnb_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
index a15ab28..f95e191 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -140,10 +140,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_amrwb_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
index 5a511c9..12c815d 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -144,10 +144,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_evrc_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
index eff41cc..22552c6 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -141,10 +141,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_mp3_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index 0f6b5a6..ee32b80 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -275,10 +275,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_multi_aac_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
index 8343beb..7b72c97 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -150,10 +150,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_qcelp_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 48e0135..644df2d 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -946,8 +946,15 @@
ac = audio->ac;
/* Offset with appropriate meta */
- param.paddr = buf_node->paddr + sizeof(struct dec_meta_in);
- param.len = buf_node->buf.data_len - sizeof(struct dec_meta_in);
+ if (audio->feedback) {
+ /* Non Tunnel mode */
+ param.paddr = buf_node->paddr + sizeof(struct dec_meta_in);
+ param.len = buf_node->buf.data_len - sizeof(struct dec_meta_in);
+ } else {
+ /* Tunnel mode */
+ param.paddr = buf_node->paddr;
+ param.len = buf_node->buf.data_len;
+ }
param.msw_ts = buf_node->meta_info.meta_in.ntimestamp.highpart;
param.lsw_ts = buf_node->meta_info.meta_in.ntimestamp.lowpart;
/* If no meta_info enaled, indicate no time stamp valid */
@@ -1181,19 +1188,21 @@
file->private_data = audio;
audio->codec_ioctl = audio_aio_ioctl;
- e_node = kmalloc(sizeof(struct audio_aio_event) * AUDIO_EVENT_NUM,
- GFP_KERNEL);
- if (e_node) {
- for (i = 0; i < AUDIO_EVENT_NUM; i++)
- list_add_tail(&e_node[i].list,
- &audio->free_event_queue);
- } else {
- pr_err("%s[%p]:event pkt alloc failed\n",
- __func__, audio);
- rc = -ENOMEM;
- goto fail;
+ for (i = 0; i < AUDIO_EVENT_NUM; i++) {
+ e_node = kmalloc(sizeof(struct audio_aio_event), GFP_KERNEL);
+ if (e_node)
+ list_add_tail(&e_node->list, &audio->free_event_queue);
+ else {
+ pr_err("%s[%p]:event pkt alloc failed\n",
+ __func__, audio);
+ break;
+ }
}
+ return 0;
fail:
+ q6asm_audio_client_free(audio->ac);
+ kfree(audio->codec_cfg);
+ kfree(audio);
return rc;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wma.c b/arch/arm/mach-msm/qdsp6v2/audio_wma.c
index 62d4393..bea0485 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wma.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -185,10 +185,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_wma_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
index a83fce9..98d1b30 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -245,10 +245,6 @@
goto fail;
}
rc = audio_aio_open(audio, file);
- if (IS_ERR_VALUE(rc)) {
- pr_err("%s: audio_aio_open failed\n", __func__);
- goto fail;
- }
#ifdef CONFIG_DEBUG_FS
snprintf(name, sizeof name, "msm_wmapro_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index bfd4c48..edb1e7d 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, 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
@@ -249,6 +249,8 @@
int len;
static int t_len;
+ if (count < 0)
+ return 0;
len = count > 63 ? 63 : count;
if (copy_from_user(l_buf + 20 , buf, len)) {
pr_info("Unable to copy data from user space\n");
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 4fd20d0..4ce9b030 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, 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
@@ -443,6 +443,7 @@
if (payload_size > MAX_PAYLOAD_SIZE) {
+
pr_err("%s: Invalid payload size = %d\n",
__func__, payload_size);
goto done;
@@ -487,11 +488,11 @@
payload_size);
adm_params.src_svc = APR_SVC_ADM;
adm_params.src_domain = APR_DOMAIN_APPS;
- adm_params.src_port = port_index;
+ adm_params.src_port = copp_id;
adm_params.dest_svc = APR_SVC_ADM;
adm_params.dest_domain = APR_DOMAIN_ADSP;
adm_params.dest_port = copp_id;
- adm_params.token = port_index;
+ adm_params.token = copp_id;
adm_params.opcode = opcode;
memcpy(rtac_adm_buffer, &adm_params, sizeof(adm_params));
@@ -613,6 +614,7 @@
}
if (payload_size > MAX_PAYLOAD_SIZE) {
+
pr_err("%s: Invalid payload size = %d\n",
__func__, payload_size);
goto done;
@@ -623,15 +625,17 @@
__func__);
goto done;
}
- if (session_id > SESSION_MAX) {
+ if (session_id > (SESSION_MAX + 1)) {
pr_err("%s: Invalid Session = %d\n", __func__, session_id);
goto done;
}
mutex_lock(&rtac_asm_apr_mutex);
- if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
- pr_err("%s: APR not initialized\n", __func__);
- goto err;
+ if (session_id < SESSION_MAX+1) {
+ if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
+ pr_err("%s: APR not initialized\n", __func__);
+ goto err;
+ }
}
/* Set globals for copy of returned payload */
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index c1e4118..6b42325 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -354,6 +354,7 @@
static void smd_fake_irq_handler(unsigned long arg);
static void smsm_cb_snapshot(uint32_t use_wakelock);
+static struct workqueue_struct *smsm_cb_wq;
static void notify_smsm_cb_clients_worker(struct work_struct *work);
static DECLARE_WORK(smsm_cb_work, notify_smsm_cb_clients_worker);
static DEFINE_MUTEX(smsm_lock);
@@ -2365,6 +2366,13 @@
return -ENOMEM;
}
+ smsm_cb_wq = create_singlethread_workqueue("smsm_cb_wq");
+ if (!smsm_cb_wq) {
+ pr_err("%s: smsm_cb_wq creation failed\n", __func__);
+ kfree(smsm_states);
+ return -EFAULT;
+ }
+
mutex_lock(&smsm_lock);
for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
state_info = &smsm_states[n];
@@ -2540,7 +2548,7 @@
goto restore_snapshot_count;
}
- schedule_work(&smsm_cb_work);
+ queue_work(smsm_cb_wq, &smsm_cb_work);
return;
restore_snapshot_count:
@@ -2832,7 +2840,6 @@
state_info->last_value = new_state;
}
}
- mutex_unlock(&smsm_lock);
/* read wakelock flag */
ret = kfifo_out(&smsm_snapshot_fifo, &use_wakelock,
@@ -2840,8 +2847,10 @@
if (ret != sizeof(use_wakelock)) {
pr_err("%s: snapshot underflow %d\n",
__func__, ret);
+ mutex_unlock(&smsm_lock);
return;
}
+ mutex_unlock(&smsm_lock);
if (use_wakelock) {
spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
index b5ff244..d6a17e6 100644
--- a/arch/arm/mach-msm/subsystem_map.c
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -34,6 +34,15 @@
static struct rb_root phys_root;
DEFINE_MUTEX(msm_buffer_mutex);
+static unsigned long subsystem_to_domain_tbl[] = {
+ VIDEO_DOMAIN,
+ VIDEO_DOMAIN,
+ CAMERA_DOMAIN,
+ DISPLAY_DOMAIN,
+ ROTATOR_DOMAIN,
+ 0xFFFFFFFF
+};
+
static struct msm_buffer_node *find_buffer(void *key)
{
struct rb_root *root = &buffer_root;
@@ -208,6 +217,31 @@
return 0;
}
+static unsigned long msm_subsystem_get_domain_no(int subsys_id)
+{
+ if (subsys_id > INVALID_SUBSYS_ID && subsys_id <= MAX_SUBSYSTEM_ID &&
+ subsys_id < ARRAY_SIZE(subsystem_to_domain_tbl))
+ return subsystem_to_domain_tbl[subsys_id];
+ else
+ return subsystem_to_domain_tbl[MAX_SUBSYSTEM_ID];
+}
+
+static unsigned long msm_subsystem_get_partition_no(int subsys_id)
+{
+ switch (subsys_id) {
+ case MSM_SUBSYSTEM_VIDEO_FWARE:
+ return VIDEO_FIRMWARE_POOL;
+ case MSM_SUBSYSTEM_VIDEO:
+ return VIDEO_MAIN_POOL;
+ case MSM_SUBSYSTEM_CAMERA:
+ case MSM_SUBSYSTEM_DISPLAY:
+ case MSM_SUBSYSTEM_ROTATOR:
+ return GEN_POOL;
+ default:
+ return 0xFFFFFFFF;
+ }
+}
+
phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id, unsigned long iova)
{
struct iommu_domain *subsys_domain;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index bc4bd21..027aa5b 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -48,8 +48,8 @@
struct restart_wq_data {
struct subsys_data *subsys;
struct wake_lock ssr_wake_lock;
- char wakelockname[64];
- int coupled;
+ char wlname[64];
+ int use_restart_order;
struct work_struct work;
};
@@ -120,26 +120,6 @@
}
EXPORT_SYMBOL(get_restart_level);
-static void restart_level_changed(void)
-{
- struct subsys_data *subsys;
-
- if (cpu_is_msm8x60() && restart_level == RESET_SUBSYS_COUPLED) {
- restart_orders = orders_8x60_all;
- n_restart_orders = ARRAY_SIZE(orders_8x60_all);
- }
-
- if (cpu_is_msm8x60() && restart_level == RESET_SUBSYS_MIXED) {
- restart_orders = orders_8x60_modems;
- n_restart_orders = ARRAY_SIZE(orders_8x60_modems);
- }
-
- mutex_lock(&subsystem_list_lock);
- list_for_each_entry(subsys, &subsystem_list, list)
- subsys->restart_order = _update_restart_order(subsys);
- mutex_unlock(&subsystem_list_lock);
-}
-
static int restart_level_set(const char *val, struct kernel_param *kp)
{
int ret;
@@ -162,20 +142,12 @@
pr_info("Phase %d behavior activated.\n", restart_level);
break;
- case RESET_SUBSYS_MIXED:
- pr_info("Phase 2+ behavior activated.\n");
- break;
-
default:
restart_level = old_val;
return -EINVAL;
break;
}
-
- if (restart_level != old_val)
- restart_level_changed();
-
return 0;
}
@@ -317,7 +289,7 @@
int i;
int restart_list_count = 0;
- if (r_work->coupled)
+ if (r_work->use_restart_order)
soc_restart_order = subsys->restart_order;
/* It's OK to not take the registration lock at this point.
@@ -441,11 +413,38 @@
kfree(r_work);
}
+static void __subsystem_restart(struct subsys_data *subsys)
+{
+ struct restart_wq_data *data = NULL;
+ int rc;
+
+ pr_debug("Restarting %s [level=%d]!\n", subsys->name,
+ restart_level);
+
+ data = kzalloc(sizeof(struct restart_wq_data), GFP_ATOMIC);
+ if (!data)
+ panic("%s: Unable to allocate memory to restart %s.",
+ __func__, subsys->name);
+
+ data->subsys = subsys;
+
+ if (restart_level != RESET_SUBSYS_INDEPENDENT)
+ data->use_restart_order = 1;
+
+ snprintf(data->wlname, sizeof(data->wlname), "ssr(%s)", subsys->name);
+ wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND, data->wlname);
+ wake_lock(&data->ssr_wake_lock);
+
+ INIT_WORK(&data->work, subsystem_restart_wq_func);
+ rc = queue_work(ssr_wq, &data->work);
+ if (rc < 0)
+ panic("%s: Unable to schedule work to restart %s (%d).",
+ __func__, subsys->name, rc);
+}
+
int subsystem_restart(const char *subsys_name)
{
struct subsys_data *subsys;
- struct restart_wq_data *data = NULL;
- int rc;
if (!subsys_name) {
pr_err("Invalid subsystem name.\n");
@@ -465,42 +464,11 @@
return -EINVAL;
}
- if (restart_level != RESET_SOC) {
- data = kzalloc(sizeof(struct restart_wq_data), GFP_KERNEL);
- if (!data) {
- restart_level = RESET_SOC;
- pr_warn("Failed to alloc restart data. Resetting.\n");
- } else {
- if (restart_level == RESET_SUBSYS_COUPLED ||
- restart_level == RESET_SUBSYS_MIXED)
- data->coupled = 1;
- else
- data->coupled = 0;
-
- data->subsys = subsys;
- }
- }
-
switch (restart_level) {
case RESET_SUBSYS_COUPLED:
- case RESET_SUBSYS_MIXED:
case RESET_SUBSYS_INDEPENDENT:
- pr_debug("Restarting %s [level=%d]!\n", subsys_name,
- restart_level);
-
- snprintf(data->wakelockname, sizeof(data->wakelockname),
- "ssr(%s)", subsys_name);
- wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND,
- data->wakelockname);
- wake_lock(&data->ssr_wake_lock);
-
- INIT_WORK(&data->work, subsystem_restart_wq_func);
- rc = schedule_work(&data->work);
-
- if (rc < 0)
- panic("%s: Unable to schedule work to restart %s",
- __func__, subsys->name);
+ __subsystem_restart(subsys);
break;
case RESET_SOC:
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index dee5479..db2a9b4 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -30,6 +30,8 @@
#define CACHE_LINE_SIZE 32
static void __iomem *l2x0_base;
+static uint32_t aux_ctrl_save;
+static uint32_t data_latency_ctrl;
static DEFINE_RAW_SPINLOCK(l2x0_lock);
static uint32_t l2x0_way_mask; /* Bitmask of active ways */
@@ -447,6 +449,51 @@
ways, cache_id, aux, l2x0_size);
}
+void l2x0_suspend(void)
+{
+ /* Save aux control register value */
+ aux_ctrl_save = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
+ data_latency_ctrl = readl_relaxed(l2x0_base + L2X0_DATA_LATENCY_CTRL);
+ /* Flush all cache */
+ l2x0_flush_all();
+ /* Disable the cache */
+ writel_relaxed(0, l2x0_base + L2X0_CTRL);
+
+ /* Memory barrier */
+ dmb();
+}
+
+void l2x0_resume(int collapsed)
+{
+ if (collapsed) {
+ /* Disable the cache */
+ writel_relaxed(0, l2x0_base + L2X0_CTRL);
+
+ /* Restore aux control register value */
+ writel_relaxed(aux_ctrl_save, l2x0_base + L2X0_AUX_CTRL);
+ writel_relaxed(data_latency_ctrl, l2x0_base +
+ L2X0_DATA_LATENCY_CTRL);
+
+ /* Invalidate the cache */
+ l2x0_inv_all();
+ /*
+ * TBD: make sure that l2xo_inv_all finished
+ * before actually enabling the cache. Logically this
+ * is not required as cache sync is atomic operation.
+ * but on 8x25, observed the random crashes and they go
+ * away if we add dmb or disable the L2.
+ * keeping this as temporary workaround until root
+ * cause is find out.
+ */
+ dmb();
+ }
+
+ /* Enable the cache */
+ writel_relaxed(1, l2x0_base + L2X0_CTRL);
+
+ mb();
+}
+
#ifdef CONFIG_OF
static void __init l2x0_of_setup(const struct device_node *np,
u32 *aux_val, u32 *aux_mask)
@@ -515,9 +562,8 @@
l2x0_base + L2X0_ADDR_FILTER_START);
}
}
-#endif
-static void __init pl310_save(void)
+static void pl310_save(void)
{
u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
L2X0_CACHE_ID_RTL_MASK;
@@ -591,7 +637,6 @@
l2x0_resume();
}
-#ifdef CONFIG_OF
static const struct l2x0_of_data pl310_data = {
pl310_of_setup,
pl310_save,
@@ -647,17 +692,3 @@
return 0;
}
#endif
-
-void l2cc_suspend(void)
-{
- pl310_save();
- l2x0_disable();
- dmb();
-}
-
-void l2cc_resume(int collapsed)
-{
- if (collapsed)
- pl310_resume();
- dmb();
-}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index d547121..656223b 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -262,8 +262,8 @@
int hsic_device_opened;
int hsic_suspend;
int read_len_mdm;
- int in_busy_hsic_read_on_mdm;
- int in_busy_hsic_write_on_mdm;
+ int in_busy_hsic_read_on_device;
+ int in_busy_hsic_write_on_device;
int in_busy_hsic_write;
int in_busy_hsic_read;
int usb_mdm_connected;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 0a156de..34640c3 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -233,6 +233,10 @@
if (driver->logging_process_id == current->tgid) {
driver->logging_mode = USB_MODE;
diagfwd_connect();
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ diagfwd_cancel_hsic();
+ diagfwd_connect_hsic(0);
+#endif
}
#endif /* DIAG over USB */
/* Delete the pkt response table entry for the exiting process */
@@ -476,6 +480,9 @@
#ifdef CONFIG_DIAG_SDIO_PIPE
driver->in_busy_sdio = 1;
#endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ diagfwd_disconnect_hsic(0);
+#endif
} else if (temp == NO_LOGGING_MODE && driver->logging_mode
== MEMORY_DEVICE_MODE) {
driver->in_busy_1 = 0;
@@ -501,15 +508,24 @@
queue_work(driver->diag_sdio_wq,
&(driver->diag_read_sdio_work));
#endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ diagfwd_connect_hsic(0);
+#endif
}
#ifdef CONFIG_DIAG_OVER_USB
else if (temp == USB_MODE && driver->logging_mode
- == NO_LOGGING_MODE)
+ == NO_LOGGING_MODE) {
diagfwd_disconnect();
- else if (temp == NO_LOGGING_MODE && driver->logging_mode
- == USB_MODE)
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ diagfwd_disconnect_hsic(0);
+#endif
+ } else if (temp == NO_LOGGING_MODE && driver->logging_mode
+ == USB_MODE) {
diagfwd_connect();
- else if (temp == USB_MODE && driver->logging_mode
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ diagfwd_connect_hsic(0);
+#endif
+ } else if (temp == USB_MODE && driver->logging_mode
== MEMORY_DEVICE_MODE) {
diagfwd_disconnect();
driver->in_busy_1 = 0;
@@ -535,9 +551,18 @@
queue_work(driver->diag_sdio_wq,
&(driver->diag_read_sdio_work));
#endif
- } else if (temp == MEMORY_DEVICE_MODE &&
- driver->logging_mode == USB_MODE)
- diagfwd_connect();
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ diagfwd_cancel_hsic();
+ diagfwd_connect_hsic(0);
+#endif
+ } else if (temp == MEMORY_DEVICE_MODE &&
+ driver->logging_mode == USB_MODE) {
+ diagfwd_connect();
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ diagfwd_cancel_hsic();
+ diagfwd_connect_hsic(0);
+#endif
+ }
#endif /* DIAG over USB */
success = 1;
}
@@ -565,6 +590,7 @@
if ((driver->data_ready[index] & USER_SPACE_LOG_TYPE) && (driver->
logging_mode == MEMORY_DEVICE_MODE)) {
+ pr_debug("diag: process woken up\n");
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & USER_SPACE_LOG_TYPE;
COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
@@ -693,6 +719,23 @@
driver->in_busy_sdio = 0;
}
#endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ pr_debug("diag: Copy data to user space %d\n",
+ driver->in_busy_hsic_write_on_device);
+ if (driver->in_busy_hsic_write_on_device == 1) {
+ num_data++;
+ /*Copy the length of data being passed*/
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ (driver->write_ptr_mdm->length), 4);
+ /*Copy the actual data being passed*/
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ *(driver->buf_in_hsic),
+ driver->write_ptr_mdm->length);
+ pr_debug("diag: data copied\n");
+ /* call the write complete function */
+ diagfwd_write_complete_hsic();
+ }
+#endif
/* copy number of data fields */
COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
ret -= 4;
@@ -854,7 +897,32 @@
}
}
#endif
- /* send masks to modem now */
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ /* send masks to 9k too */
+ if (driver->hsic_ch && (payload_size > 0)) {
+ /* wait sending mask updates if HSIC ch not ready */
+ if (driver->in_busy_hsic_write)
+ wait_event_interruptible(driver->wait_q,
+ (driver->in_busy_hsic_write != 1));
+ driver->in_busy_hsic_write = 1;
+ driver->in_busy_hsic_read_on_device = 0;
+ err = diag_bridge_write(driver->user_space_data,
+ payload_size);
+ if (err) {
+ pr_err("diag: err sending mask to MDM: %d\n",
+ err);
+ /*
+ * If the error is recoverable, then clear
+ * the write flag, so we will resubmit a
+ * write on the next frame. Otherwise, don't
+ * resubmit a write on the next frame.
+ */
+ if ((-ESHUTDOWN) != err)
+ driver->in_busy_hsic_write = 0;
+ }
+ }
+#endif
+ /* send masks to 8k now */
diag_process_hdlc((void *)(driver->user_space_data),
payload_size);
return 0;
@@ -1181,6 +1249,7 @@
diag_read_smd_wcnss_cntl_work_fn);
INIT_WORK(&(driver->diag_read_smd_dci_work),
diag_read_smd_dci_work_fn);
+ diag_debugfs_init();
diagfwd_init();
diagfwd_cntl_init();
driver->dci_state = diag_dci_init();
@@ -1214,6 +1283,7 @@
return 0;
fail:
+ diag_debugfs_cleanup();
diagchar_cleanup();
diagfwd_exit();
diagfwd_cntl_exit();
@@ -1232,6 +1302,7 @@
diagfwd_cntl_exit();
diag_sdio_fn(EXIT);
diag_hsic_fn(EXIT);
+ diag_debugfs_cleanup();
diagchar_cleanup();
printk(KERN_INFO "done diagchar exit\n");
}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 7066141..a63e344 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -183,7 +183,7 @@
return 0;
}
-inline int chk_polling_response(void)
+int chk_polling_response(void)
{
if (!(driver->polling_reg_flag) && chk_apps_master())
/*
@@ -273,6 +273,7 @@
break;
if (i < driver->num_clients) {
driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
+ pr_debug("diag: wake up logging process\n");
wake_up_interruptible(&driver->wait_q);
} else
return -EINVAL;
@@ -300,6 +301,15 @@
&(driver->diag_read_sdio_work));
}
#endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ else if (proc_num == HSIC_DATA) {
+ driver->in_busy_hsic_read = 0;
+ driver->in_busy_hsic_write_on_device = 0;
+ if (driver->hsic_ch)
+ queue_work(driver->diag_hsic_wq,
+ &(driver->diag_read_hsic_work));
+ }
+#endif
err = -1;
}
#ifdef CONFIG_DIAG_OVER_USB
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 0780a8e..f5de2ac 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -27,7 +27,10 @@
int diag_device_write(void *, int, struct diag_request *);
int mask_request_validate(unsigned char mask_buf[]);
void diag_clear_reg(int);
+int chk_config_get_id(void);
int chk_apps_only(void);
+int chk_apps_master(void);
+int chk_polling_response(void);
void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
int ssid_last, int proc);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 171168f..8efe10b 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -16,6 +16,9 @@
#include "diagchar.h"
#include "diagfwd.h"
#include "diagfwd_cntl.h"
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
#define HDR_SIZ 8
@@ -317,3 +320,281 @@
kfree(driver->buf_in_qdsp_cntl);
kfree(driver->buf_in_wcnss_cntl);
}
+
+#ifdef CONFIG_DEBUG_FS
+#define DEBUG_BUF_SIZE 4096
+static struct dentry *diag_dbgfs_dent;
+static int diag_dbgfs_table_index;
+
+static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ pr_err("diag: %s, Error allocating memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = scnprintf(buf, DEBUG_BUF_SIZE,
+ "modem ch: 0x%x\n"
+ "lpass ch: 0x%x\n"
+ "riva ch: 0x%x\n"
+ "dci ch: 0x%x\n"
+ "modem cntl_ch: 0x%x\n"
+ "lpass cntl_ch: 0x%x\n"
+ "riva cntl_ch: 0x%x\n"
+ "CPU Tools id: %d\n"
+ "Apps only: %d\n"
+ "Apps master: %d\n"
+ "Check Polling Response: %d\n"
+ "polling_reg_flag: %d\n"
+ "uses device tree: %d\n"
+ "in_busy_1: %d\n"
+ "in_busy_2: %d\n"
+ "in_busy_qdsp_1: %d\n"
+ "in_busy_qdsp_2: %d\n"
+ "in_busy_wcnss_1: %d\n"
+ "in_busy_wcnss_2: %d\n"
+ "in_busy_dci: %d\n",
+ (unsigned int)driver->ch,
+ (unsigned int)driver->chqdsp,
+ (unsigned int)driver->ch_wcnss,
+ (unsigned int)driver->ch_dci,
+ (unsigned int)driver->ch_cntl,
+ (unsigned int)driver->chqdsp_cntl,
+ (unsigned int)driver->ch_wcnss_cntl,
+ chk_config_get_id(),
+ chk_apps_only(),
+ chk_apps_master(),
+ chk_polling_response(),
+ driver->polling_reg_flag,
+ driver->use_device_tree,
+ driver->in_busy_1,
+ driver->in_busy_2,
+ driver->in_busy_qdsp_1,
+ driver->in_busy_qdsp_2,
+ driver->in_busy_wcnss_1,
+ driver->in_busy_wcnss_2,
+ driver->in_busy_dci);
+
+#ifdef CONFIG_DIAG_OVER_USB
+ ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+ "usb_connected: %d\n",
+ driver->usb_connected);
+#endif
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t diag_dbgfs_read_workpending(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos)
+{
+ char *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ pr_err("diag: %s, Error allocating memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = scnprintf(buf, DEBUG_BUF_SIZE,
+ "Pending status for work_stucts:\n"
+ "diag_drain_work: %d\n"
+ "diag_read_smd_work: %d\n"
+ "diag_read_smd_cntl_work: %d\n"
+ "diag_read_smd_qdsp_work: %d\n"
+ "diag_read_smd_qdsp_cntl_work: %d\n"
+ "diag_read_smd_wcnss_work: %d\n"
+ "diag_read_smd_wcnss_cntl_work: %d\n"
+ "diag_modem_mask_update_work: %d\n"
+ "diag_qdsp_mask_update_work: %d\n"
+ "diag_wcnss_mask_update_work: %d\n"
+ "diag_read_smd_dci_work: %d\n",
+ work_pending(&(driver->diag_drain_work)),
+ work_pending(&(driver->diag_read_smd_work)),
+ work_pending(&(driver->diag_read_smd_cntl_work)),
+ work_pending(&(driver->diag_read_smd_qdsp_work)),
+ work_pending(&(driver->diag_read_smd_qdsp_cntl_work)),
+ work_pending(&(driver->diag_read_smd_wcnss_work)),
+ work_pending(&(driver->diag_read_smd_wcnss_cntl_work)),
+ work_pending(&(driver->diag_modem_mask_update_work)),
+ work_pending(&(driver->diag_qdsp_mask_update_work)),
+ work_pending(&(driver->diag_wcnss_mask_update_work)),
+ work_pending(&(driver->diag_read_smd_dci_work)));
+
+#ifdef CONFIG_DIAG_OVER_USB
+ ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+ "diag_proc_hdlc_work: %d\n"
+ "diag_read_work: %d\n",
+ work_pending(&(driver->diag_proc_hdlc_work)),
+ work_pending(&(driver->diag_read_work)));
+#endif
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int ret = 0;
+ int i;
+ int bytes_remaining;
+ int bytes_in_buffer = 0;
+ int bytes_written;
+ int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+
+ if (diag_dbgfs_table_index >= diag_max_reg) {
+ /* Done. Reset to prepare for future requests */
+ diag_dbgfs_table_index = 0;
+ return 0;
+ }
+
+ buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL);
+ if (!buf) {
+ pr_err("diag: %s, Error allocating memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ bytes_remaining = buf_size;
+ for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
+ /* Do not process empty entries in the table */
+ if (driver->table[i].process_id == 0)
+ continue;
+
+ bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
+ "i: %3d, cmd_code: %4x, subsys_id: %4x, "
+ "client: %2d, cmd_code_lo: %4x, "
+ "cmd_code_hi: %4x, process_id: %5d\n",
+ i,
+ driver->table[i].cmd_code,
+ driver->table[i].subsys_id,
+ driver->table[i].client_id,
+ driver->table[i].cmd_code_lo,
+ driver->table[i].cmd_code_hi,
+ driver->table[i].process_id);
+
+ bytes_in_buffer += bytes_written;
+
+ /* Check if there is room to add another table entry */
+ bytes_remaining = buf_size - bytes_in_buffer;
+ if (bytes_remaining < bytes_written)
+ break;
+ }
+ diag_dbgfs_table_index = i;
+
+ *ppos = 0;
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
+
+ kfree(buf);
+ return ret;
+}
+
+#ifdef CONFIG_DIAG_HSIC_PIPE
+static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ pr_err("diag: %s, Error allocating memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = scnprintf(buf, DEBUG_BUF_SIZE,
+ "hsic initialized: %d\n"
+ "hsic ch: %d\n"
+ "hsic enabled: %d\n"
+ "hsic_opened: %d\n"
+ "hisc_suspend: %d\n"
+ "in_busy_hsic_read_on_mdm: %d\n"
+ "in_busy_hsic_write_on_mdm: %d\n"
+ "in_busy_hsic_write: %d\n"
+ "in_busy_hsic_read: %d\n"
+ "usb_mdm_connected: %d\n"
+ "diag_read_mdm_work: %d\n"
+ "diag_read_hsic_work: %d\n"
+ "diag_disconnect_work: %d\n"
+ "diag_usb_read_complete_work: %d\n",
+ driver->hsic_initialized,
+ driver->hsic_ch,
+ driver->hsic_device_enabled,
+ driver->hsic_device_opened,
+ driver->hsic_suspend,
+ driver->in_busy_hsic_read_on_device,
+ driver->in_busy_hsic_write_on_device,
+ driver->in_busy_hsic_write,
+ driver->in_busy_hsic_read,
+ driver->usb_mdm_connected,
+ work_pending(&(driver->diag_read_mdm_work)),
+ work_pending(&(driver->diag_read_hsic_work)),
+ work_pending(&(driver->diag_disconnect_work)),
+ work_pending(&(driver->diag_usb_read_complete_work)));
+
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+ kfree(buf);
+ return ret;
+}
+
+const struct file_operations diag_dbgfs_hsic_ops = {
+ .read = diag_dbgfs_read_hsic,
+};
+#endif
+
+const struct file_operations diag_dbgfs_status_ops = {
+ .read = diag_dbgfs_read_status,
+};
+
+const struct file_operations diag_dbgfs_table_ops = {
+ .read = diag_dbgfs_read_table,
+};
+
+const struct file_operations diag_dbgfs_workpending_ops = {
+ .read = diag_dbgfs_read_workpending,
+};
+
+void diag_debugfs_init(void)
+{
+ diag_dbgfs_dent = debugfs_create_dir("diag", 0);
+ if (IS_ERR(diag_dbgfs_dent))
+ return;
+
+ debugfs_create_file("status", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_status_ops);
+
+ debugfs_create_file("table", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_table_ops);
+
+ debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_workpending_ops);
+
+#ifdef CONFIG_DIAG_HSIC_PIPE
+ debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_hsic_ops);
+#endif
+
+ diag_dbgfs_table_index = 0;
+}
+
+void diag_debugfs_cleanup(void)
+{
+ if (diag_dbgfs_dent) {
+ debugfs_remove_recursive(diag_dbgfs_dent);
+ diag_dbgfs_dent = NULL;
+ }
+}
+#else
+void diag_debugfs_init(void) { }
+void diag_debugfs_cleanup(void) { }
+#endif
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index ad1fec9..743ddc1 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -86,4 +86,7 @@
void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event);
void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event);
+void diag_debugfs_init(void);
+void diag_debugfs_cleanup(void);
+
#endif
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index b2080b3..a3c6f26 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -36,11 +36,11 @@
return;
}
- /*
- * If there is no hsic data being read from the hsic and there
- * is no hsic data being written to the usb mdm channel
+ /* If there is no hsic data being read from the hsic and there
+ * is no hsic data being written to the device
*/
- if (!driver->in_busy_hsic_read && !driver->in_busy_hsic_write_on_mdm) {
+ if (!driver->in_busy_hsic_read &&
+ !driver->in_busy_hsic_write_on_device) {
/*
* Initiate the read from the hsic. The hsic read is
* asynchronous. Once the read is complete the read
@@ -49,6 +49,7 @@
int err;
driver->in_busy_hsic_read = 1;
APPEND_DEBUG('i');
+ pr_debug("diag: read from HSIC\n");
err = diag_bridge_read((char *)driver->buf_in_hsic,
IN_BUF_SIZE);
if (err) {
@@ -97,7 +98,8 @@
* diag_bridge_read(), so buf here should be
* driver->buf_in_hsic
*/
- driver->in_busy_hsic_write_on_mdm = 1;
+ driver->in_busy_hsic_write_on_device = 1;
+ pr_debug("diag: write to device\n");
diag_device_write((void *)buf, HSIC_DATA,
driver->write_ptr_mdm);
}
@@ -109,9 +111,9 @@
* If for some reason there was no hsic data to write to the
* mdm channel, set up another read
*/
- if (!driver->in_busy_hsic_write_on_mdm &&
- driver->usb_mdm_connected &&
- !driver->hsic_suspend)
+ if (!driver->in_busy_hsic_write_on_device && ((driver->logging_mode
+ == MEMORY_DEVICE_MODE) || (driver->usb_mdm_connected &&
+ !driver->hsic_suspend)))
queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
}
@@ -135,9 +137,14 @@
static int diag_hsic_suspend(void *ctxt)
{
+ pr_debug("diag: hsic_suspend\n");
if (driver->in_busy_hsic_write)
return -EBUSY;
+ /* Don't allow suspend if in MEMORY_DEVICE_MODE */
+ if (driver->logging_mode == MEMORY_DEVICE_MODE)
+ return -EBUSY;
+
driver->hsic_suspend = 1;
return 0;
@@ -145,9 +152,11 @@
static void diag_hsic_resume(void *ctxt)
{
+ pr_debug("diag: hsic_resume\n");
driver->hsic_suspend = 0;
- if (!driver->in_busy_hsic_write_on_mdm && driver->usb_mdm_connected)
+ if (!driver->in_busy_hsic_write_on_device && (driver->logging_mode
+ == MEMORY_DEVICE_MODE || driver->usb_mdm_connected))
queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
}
@@ -167,28 +176,59 @@
driver->hsic_device_opened = 0;
diag_bridge_close();
}
- pr_debug("DIAG in %s: closed successfully\n", __func__);
+ pr_debug("diag: in %s: closed successfully\n", __func__);
} else {
- pr_debug("DIAG in %s: already closed\n", __func__);
+ pr_debug("diag: in %s: already closed\n", __func__);
+ }
+
+ return 0;
+}
+
+/* diagfwd_cancel_hsic is called to cancel outstanding read/writes */
+int diagfwd_cancel_hsic(void)
+{
+ int err;
+
+ if (driver->hsic_device_enabled) {
+ if (driver->hsic_device_opened) {
+ driver->hsic_ch = 0;
+ driver->hsic_device_opened = 0;
+ diag_bridge_close();
+ err = diag_bridge_open(&hsic_diag_bridge_ops);
+ if (err) {
+ pr_err("DIAG: HSIC channel open error: %d\n",
+ err);
+ } else {
+ pr_debug("DIAG: opened HSIC channel\n");
+ driver->hsic_device_opened = 1;
+ driver->hsic_ch = 1;
+ }
+ }
}
return 0;
}
/* diagfwd_connect_hsic is called when the USB mdm channel is connected */
-static int diagfwd_connect_hsic(void)
+int diagfwd_connect_hsic(int process_cable)
{
int err;
pr_debug("DIAG in %s\n", __func__);
- err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE, N_MDM_READ);
- if (err)
- pr_err("DIAG: unable to alloc USB req on mdm ch err:%d\n", err);
+ /* If the usb cable is being connected */
+ if (process_cable) {
+ err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE,
+ N_MDM_READ);
+ if (err)
+ pr_err("DIAG: unable to alloc USB req on mdm"
+ " ch err:%d\n", err);
- driver->usb_mdm_connected = 1;
- driver->in_busy_hsic_write_on_mdm = 0;
- driver->in_busy_hsic_read_on_mdm = 0;
+ driver->usb_mdm_connected = 1;
+ }
+
+ driver->in_busy_hsic_write_on_device = 0;
+ driver->in_busy_hsic_read_on_device = 0;
driver->in_busy_hsic_write = 0;
driver->in_busy_hsic_read = 0;
@@ -215,7 +255,9 @@
driver->hsic_ch = 1;
/* Poll USB mdm channel to check for data */
- queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+ if (driver->logging_mode == USB_MODE)
+ queue_work(driver->diag_hsic_wq,
+ &driver->diag_read_mdm_work);
/* Poll HSIC channel to check for data */
queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
@@ -231,33 +273,38 @@
* diagfwd_disconnect_hsic is called when the USB mdm channel
* is disconnected
*/
-static int diagfwd_disconnect_hsic(void)
+int diagfwd_disconnect_hsic(int process_cable)
{
pr_debug("DIAG in %s\n", __func__);
- driver->usb_mdm_connected = 0;
- usb_diag_free_req(driver->mdm_ch);
- driver->in_busy_hsic_write_on_mdm = 1;
- driver->in_busy_hsic_read_on_mdm = 1;
- driver->in_busy_hsic_write = 1;
- driver->in_busy_hsic_read = 1;
+ /* If the usb cable is being disconnected */
+ if (process_cable) {
+ driver->usb_mdm_connected = 0;
+ usb_diag_free_req(driver->mdm_ch);
+ }
- /* Turn off communication over usb mdm and hsic */
- return diag_hsic_close();
+ if (driver->logging_mode != MEMORY_DEVICE_MODE) {
+ driver->in_busy_hsic_write_on_device = 1;
+ driver->in_busy_hsic_read_on_device = 1;
+ driver->in_busy_hsic_write = 1;
+ driver->in_busy_hsic_read = 1;
+ /* Turn off communication over usb mdm and hsic */
+ return diag_hsic_close();
+ }
+ return 0;
}
/*
* diagfwd_write_complete_hsic is called after the asynchronous
* usb_diag_write() on mdm channel is complete
*/
-static int diagfwd_write_complete_hsic(void)
+int diagfwd_write_complete_hsic(void)
{
/*
* Clear flag to denote that the write of the hsic data on the
* usb mdm channel is complete
*/
- driver->in_busy_hsic_write_on_mdm = 0;
-
+ driver->in_busy_hsic_write_on_device = 0;
if (!driver->hsic_ch) {
pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
return 0;
@@ -275,7 +322,7 @@
static int diagfwd_read_complete_hsic(struct diag_request *diag_read_ptr)
{
/* The read of the usb driver on the mdm (not hsic) has completed */
- driver->in_busy_hsic_read_on_mdm = 0;
+ driver->in_busy_hsic_read_on_device = 0;
driver->read_len_mdm = diag_read_ptr->actual;
if (!driver->hsic_ch) {
@@ -329,7 +376,7 @@
{
switch (event) {
case USB_DIAG_CONNECT:
- diagfwd_connect_hsic();
+ diagfwd_connect_hsic(1);
break;
case USB_DIAG_DISCONNECT:
queue_work(driver->diag_hsic_wq, &driver->diag_disconnect_work);
@@ -355,7 +402,7 @@
static void diag_disconnect_work_fn(struct work_struct *w)
{
- diagfwd_disconnect_hsic();
+ diagfwd_disconnect_hsic(1);
}
static void diag_read_mdm_work_fn(struct work_struct *work)
@@ -370,11 +417,12 @@
* and there is no mdm channel data currently being written
* to the hsic
*/
- if (!driver->in_busy_hsic_read_on_mdm && !driver->in_busy_hsic_write) {
+ if (!driver->in_busy_hsic_read_on_device &&
+ !driver->in_busy_hsic_write) {
APPEND_DEBUG('x');
/* Setup the next read from usb mdm channel */
- driver->in_busy_hsic_read_on_mdm = 1;
+ driver->in_busy_hsic_read_on_device = 1;
driver->usb_read_mdm_ptr->buf = driver->usb_buf_mdm_out;
driver->usb_read_mdm_ptr->length = USB_MAX_OUT_BUF;
usb_diag_read(driver->mdm_ch, driver->usb_read_mdm_ptr);
@@ -385,41 +433,77 @@
* If for some reason there was no mdm channel read initiated,
* queue up the reading of data from the mdm channel
*/
- if (!driver->in_busy_hsic_read_on_mdm)
+ if (!driver->in_busy_hsic_read_on_device)
queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
}
-int diag_hsic_enable(void)
+static int diag_hsic_probe(struct platform_device *pdev)
{
- pr_debug("DIAG in %s\n", __func__);
-
- driver->read_len_mdm = 0;
- if (driver->buf_in_hsic == NULL)
- driver->buf_in_hsic = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_hsic == NULL)
- goto err;
- if (driver->usb_buf_mdm_out == NULL)
- driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF, GFP_KERNEL);
- if (driver->usb_buf_mdm_out == NULL)
- goto err;
- if (driver->write_ptr_mdm == NULL)
- driver->write_ptr_mdm = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_mdm == NULL)
- goto err;
- if (driver->usb_read_mdm_ptr == NULL)
- driver->usb_read_mdm_ptr = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->usb_read_mdm_ptr == NULL)
- goto err;
+ int err = 0;
+ pr_debug("diag: in %s\n", __func__);
+ if (!driver->hsic_device_enabled) {
+ driver->read_len_mdm = 0;
+ if (driver->buf_in_hsic == NULL)
+ driver->buf_in_hsic = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+ if (driver->buf_in_hsic == NULL)
+ goto err;
+ if (driver->usb_buf_mdm_out == NULL)
+ driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
+ GFP_KERNEL);
+ if (driver->usb_buf_mdm_out == NULL)
+ goto err;
+ if (driver->write_ptr_mdm == NULL)
+ driver->write_ptr_mdm = kzalloc(
+ sizeof(struct diag_request), GFP_KERNEL);
+ if (driver->write_ptr_mdm == NULL)
+ goto err;
+ if (driver->usb_read_mdm_ptr == NULL)
+ driver->usb_read_mdm_ptr = kzalloc(
+ sizeof(struct diag_request), GFP_KERNEL);
+ if (driver->usb_read_mdm_ptr == NULL)
+ goto err;
#ifdef CONFIG_DIAG_OVER_USB
- INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
+ INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
#endif
- INIT_WORK(&(driver->diag_read_hsic_work), diag_read_hsic_work_fn);
+ INIT_WORK(&(driver->diag_read_hsic_work),
+ diag_read_hsic_work_fn);
+ driver->hsic_device_enabled = 1;
+ }
- driver->hsic_device_enabled = 1;
+ /*
+ * The probe function was called after the usb was connected
+ * on the legacy channel OR ODL is turned on. Communication over usb
+ * mdm and hsic needs to be turned on.
+ */
+ if (driver->usb_mdm_connected || (driver->logging_mode ==
+ MEMORY_DEVICE_MODE)) {
+ /* The hsic (diag_bridge) platform device driver is enabled */
+ err = diag_bridge_open(&hsic_diag_bridge_ops);
+ if (err) {
+ pr_err("diag: could not open HSIC, err: %d\n", err);
+ driver->hsic_device_opened = 0;
+ return err;
+ }
- return 0;
+ pr_info("diag: opened HSIC channel\n");
+ driver->hsic_device_opened = 1;
+ driver->hsic_ch = 1;
+ driver->in_busy_hsic_write_on_device = 0;
+ driver->in_busy_hsic_read_on_device = 0;
+ driver->in_busy_hsic_write = 0;
+ driver->in_busy_hsic_read = 0;
+
+ if (driver->usb_mdm_connected) {
+ /* Poll USB mdm channel to check for data */
+ queue_work(driver->diag_hsic_wq,
+ &driver->diag_read_mdm_work);
+ }
+
+ /* Poll HSIC channel to check for data */
+ queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+ }
+
+ return err;
err:
pr_err("DIAG could not initialize buf for HSIC\n");
kfree(driver->buf_in_hsic);
@@ -432,50 +516,6 @@
return -ENOMEM;
}
-static int diag_hsic_probe(struct platform_device *pdev)
-{
- int err;
-
- if (!driver->hsic_device_enabled) {
- err = diag_hsic_enable();
- if (err) {
- pr_err("DIAG could not enable HSIC, err: %d\n", err);
- return err;
- }
- }
-
- /*
- * The probe function was called after the usb was connected
- * on the legacy channel. Communication over usb mdm and hsic
- * needs to be turned on.
- */
- if (driver->usb_mdm_connected) {
- /* The hsic (diag_bridge) platform device driver is enabled */
- err = diag_bridge_open(&hsic_diag_bridge_ops);
- if (err) {
- pr_err("DIAG could not open HSIC, err: %d\n", err);
- driver->hsic_device_opened = 0;
- return err;
- }
-
- pr_debug("DIAG opened HSIC channel\n");
- driver->hsic_device_opened = 1;
- driver->hsic_ch = 1;
- driver->in_busy_hsic_write_on_mdm = 0;
- driver->in_busy_hsic_read_on_mdm = 0;
- driver->in_busy_hsic_write = 0;
- driver->in_busy_hsic_read = 0;
-
- /* Poll USB mdm channel to check for data */
- queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
-
- /* Poll HSIC channel to check for data */
- queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
- }
-
- return err;
-}
-
static int diag_hsic_remove(struct platform_device *pdev)
{
pr_debug("DIAG: %s called\n", __func__);
@@ -510,8 +550,7 @@
},
};
-
-void __init diagfwd_hsic_init(void)
+void diagfwd_hsic_init(void)
{
int ret;
@@ -540,7 +579,7 @@
pr_err("DIAG could not initialize for HSIC execution\n");
}
-void __exit diagfwd_hsic_exit(void)
+void diagfwd_hsic_exit(void)
{
pr_debug("DIAG in %s\n", __func__);
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index 6769052..8785d9f 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -17,7 +17,11 @@
#define N_MDM_WRITE 1 /* Upgrade to 2 with ping pong buffer */
#define N_MDM_READ 1
-void __init diagfwd_hsic_init(void);
-void __exit diagfwd_hsic_exit(void);
+int diagfwd_connect_hsic(int);
+int diagfwd_disconnect_hsic(int);
+int diagfwd_write_complete_hsic(void);
+int diagfwd_cancel_hsic(void);
+void diagfwd_hsic_init(void);
+void diagfwd_hsic_exit(void);
#endif
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index d1a9fe6..974b77e 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -72,7 +72,7 @@
return 0;
/* enable PRNG clock */
- ret = clk_enable(msm_rng_dev->prng_clk);
+ ret = clk_prepare_enable(msm_rng_dev->prng_clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable clock in callback\n");
return 0;
@@ -99,7 +99,7 @@
} while (currsize < maxsize);
/* vote to turn off clock */
- clk_disable(msm_rng_dev->prng_clk);
+ clk_disable_unprepare(msm_rng_dev->prng_clk);
return currsize;
}
@@ -116,7 +116,7 @@
int ret = 0;
/* Enable the PRNG CLK */
- ret = clk_enable(msm_rng_dev->prng_clk);
+ ret = clk_prepare_enable(msm_rng_dev->prng_clk);
if (ret) {
dev_err(&(msm_rng_dev->pdev)->dev,
"failed to enable clock in probe\n");
@@ -146,7 +146,7 @@
mb();
}
- clk_disable(msm_rng_dev->prng_clk);
+ clk_disable_unprepare(msm_rng_dev->prng_clk);
return 0;
}
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 47bc750..865fcc2 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -1303,15 +1303,15 @@
msm_rotator_dev->img_info[first_free_index];
*(msm_rotator_dev->img_info[first_free_index]) = info;
msm_rotator_dev->fd_info[first_free_index] = fd_info;
-
- if (copy_to_user((void __user *)arg, &info, sizeof(info)))
- rc = -EFAULT;
} else if (s == MAX_SESSIONS) {
dev_dbg(msm_rotator_dev->device, "%s: all sessions in use\n",
__func__);
rc = -EBUSY;
}
+ if (rc == 0 && copy_to_user((void __user *)arg, &info, sizeof(info)))
+ rc = -EFAULT;
+
rotator_start_exit:
mutex_unlock(&msm_rotator_dev->rotator_lock);
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index 0d3c4c3..111bc49 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -2505,7 +2505,7 @@
pce_dev->ce_clk = ce_clk;
/* Enable CE core clk */
- *rc = clk_enable(pce_dev->ce_core_clk);
+ *rc = clk_prepare_enable(pce_dev->ce_core_clk);
if (*rc) {
if (pce_dev->ce_core_src_clk != NULL)
clk_put(pce_dev->ce_core_src_clk);
@@ -2514,9 +2514,9 @@
goto err;
} else {
/* Enable CE clk */
- *rc = clk_enable(pce_dev->ce_clk);
+ *rc = clk_prepare_enable(pce_dev->ce_clk);
if (*rc) {
- clk_disable(pce_dev->ce_core_clk);
+ clk_disable_unprepare(pce_dev->ce_core_clk);
if (pce_dev->ce_core_src_clk != NULL)
clk_put(pce_dev->ce_core_src_clk);
clk_put(pce_dev->ce_core_clk);
@@ -2567,8 +2567,8 @@
if (pce_dev->coh_vmem)
dma_free_coherent(pce_dev->pdev, pce_dev->memsize,
pce_dev->coh_vmem, pce_dev->coh_pmem);
- clk_disable(pce_dev->ce_clk);
- clk_disable(pce_dev->ce_core_clk);
+ clk_disable_unprepare(pce_dev->ce_clk);
+ clk_disable_unprepare(pce_dev->ce_core_clk);
if (pce_dev->ce_core_src_clk != NULL)
clk_put(pce_dev->ce_core_src_clk);
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
index b09b040..90cc798 100644
--- a/drivers/gpio/qpnp-gpio.c
+++ b/drivers/gpio/qpnp-gpio.c
@@ -168,7 +168,7 @@
}
if (param->direction & QPNP_GPIO_DIR_OUT) {
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] = (param->inv_int_pol
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] = (param->output_value
<< Q_REG_OUT_INVERT_SHIFT) & Q_REG_OUT_INVERT_MASK;
q_spec->regs[Q_REG_I_OUTPUT_CTL2] |= (param->src_select
<< Q_REG_SRC_SEL_SHIFT) & Q_REG_SRC_SEL_MASK;
@@ -398,13 +398,11 @@
int rc;
dev_dbg(&spmi->dev, "%s: p[0]: 0x%x p[1]: 0x%x p[2]: 0x%x p[3]:"
- " 0x%x p[4]: 0x%x p[5]: 0x%x p[6]: 0x%x p[7]: 0x%x"
- " p[8]: 0x%x\n", __func__,
+ " 0x%x p[4]: 0x%x p[5]: 0x%x p[6]: 0x%x p[7]: 0x%x\n", __func__,
be32_to_cpup(&prop[0]), be32_to_cpup(&prop[1]),
be32_to_cpup(&prop[2]), be32_to_cpup(&prop[3]),
be32_to_cpup(&prop[4]), be32_to_cpup(&prop[5]),
- be32_to_cpup(&prop[6]), be32_to_cpup(&prop[7]),
- be32_to_cpup(&prop[8]));
+ be32_to_cpup(&prop[6]), be32_to_cpup(&prop[7]));
param.direction = be32_to_cpup(&prop[0]);
param.output_type = be32_to_cpup(&prop[1]);
@@ -413,8 +411,7 @@
param.vin_sel = be32_to_cpup(&prop[4]);
param.out_strength = be32_to_cpup(&prop[5]);
param.src_select = be32_to_cpup(&prop[6]);
- param.inv_int_pol = be32_to_cpup(&prop[7]);
- param.master_en = be32_to_cpup(&prop[8]);
+ param.master_en = be32_to_cpup(&prop[7]);
rc = qpnp_gpio_config(gpio, ¶m);
if (rc)
@@ -613,8 +610,8 @@
/* It's not an error to not config a default */
prop = of_get_property(spmi->dev_node[i].of_node,
"qcom,qpnp-gpio-cfg", &len);
- /* 9 data values constitute one tuple */
- if (prop && (len != (9 * sizeof(__be32)))) {
+ /* 8 data values constitute one tuple */
+ if (prop && (len != (8 * sizeof(__be32)))) {
dev_err(&spmi->dev, "%s: invalid format for"
" qcom,qpnp-gpio-cfg property\n",
__func__);
@@ -697,10 +694,8 @@
{
}
-MODULE_AUTHOR(
- "Michael Bohan <mbohan@codeaurora.org>");
MODULE_DESCRIPTION("QPNP PMIC gpio driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
module_init(qpnp_gpio_init);
module_exit(qpnp_gpio_exit);
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 0cec423..6823a5a 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -484,7 +484,7 @@
valid_handle = ion_handle_validate(client, handle);
if (!valid_handle) {
mutex_unlock(&client->lock);
- WARN("%s: invalid handle passed to free.\n", __func__);
+ WARN(1, "%s: invalid handle passed to free.\n", __func__);
return;
}
ion_handle_put(handle);
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index de9e2c4..84789ef 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -54,7 +54,7 @@
if (!offset) {
if ((carveout_heap->total_size -
- carveout_heap->allocated_bytes) > size)
+ carveout_heap->allocated_bytes) >= size)
pr_debug("%s: heap %s has enough memory (%lx) but"
" the allocation of size %lx still failed."
" Memory is probably fragmented.",
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 7d99482..b383e68 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -224,8 +224,9 @@
if (!offset) {
mutex_lock(&cp_heap->lock);
+ cp_heap->allocated_bytes -= size;
if ((cp_heap->total_size -
- cp_heap->allocated_bytes) > size)
+ cp_heap->allocated_bytes) >= size)
pr_debug("%s: heap %s has enough memory (%lx) but"
" the allocation of size %lx still failed."
" Memory is probably fragmented.\n",
@@ -233,8 +234,6 @@
cp_heap->total_size -
cp_heap->allocated_bytes, size);
- cp_heap->allocated_bytes -= size;
-
if (cp_heap->reusable && !cp_heap->allocated_bytes) {
if (fmem_set_state(FMEM_T_STATE) != 0)
pr_err("%s: unable to transition heap to T-state\n",
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 87f259d..00dba96 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -169,10 +169,9 @@
};
-static irqreturn_t adreno_isr(int irq, void *data)
+static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
{
irqreturn_t result;
- struct kgsl_device *device = data;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
result = adreno_dev->gpudev->irq_handler(adreno_dev);
@@ -490,7 +489,7 @@
if (status != 0)
goto error;
- status = kgsl_device_platform_probe(device, adreno_isr);
+ status = kgsl_device_platform_probe(device);
if (status)
goto error_close_rb;
@@ -1444,6 +1443,7 @@
.irqctrl = adreno_irqctrl,
.gpuid = adreno_gpuid,
.snapshot = adreno_snapshot,
+ .irq_handler = adreno_irq_handler,
/* Optional functions */
.setstate = adreno_setstate,
.drawctxt_create = adreno_drawctxt_create,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 491cf62..95378a1 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -181,6 +181,16 @@
return (adreno_dev->gpurev >= 300);
}
+static inline int adreno_is_a305(struct adreno_device *adreno_dev)
+{
+ return (adreno_dev->gpurev == ADRENO_REV_A305);
+}
+
+static inline int adreno_is_a320(struct adreno_device *adreno_dev)
+{
+ return (adreno_dev->gpurev == ADRENO_REV_A320);
+}
+
static inline int adreno_rb_ctxtswitch(unsigned int *cmd)
{
return (cmd[0] == cp_nop_packet(1) &&
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index d773521..0d15fb9 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -280,6 +280,6 @@
adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
/* Set the new context */
- adreno_dev->drawctxt_active = drawctxt;
adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
+ adreno_dev->drawctxt_active = drawctxt;
}
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 5f16ff7..a992059 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -339,6 +339,8 @@
if (status != 0)
return status;
+ if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev))
+ adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000F0602);
rb->rptr = 0;
rb->wptr = 0;
@@ -855,7 +857,7 @@
*cmds++ = cp_nop_packet(1);
*cmds++ = KGSL_END_OF_IB_IDENTIFIER;
- kgsl_setstate(device,
+ kgsl_setstate(&device->mmu,
kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
device->id));
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9e9bbf2..321c59e 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -122,6 +122,40 @@
}
/**
+ * kgsl_cancel_events_ctxt - Cancel all events for a context
+ * @device - KGSL device for the events to cancel
+ * @ctxt - context whose events we want to cancel
+ *
+ */
+static void kgsl_cancel_events_ctxt(struct kgsl_device *device,
+ struct kgsl_context *context)
+{
+ struct kgsl_event *event, *event_tmp;
+ unsigned int id, cur;
+
+ cur = device->ftbl->readtimestamp(device, context,
+ KGSL_TIMESTAMP_RETIRED);
+ id = context->id;
+
+ list_for_each_entry_safe(event, event_tmp, &device->events, list) {
+ if (event->context != context)
+ continue;
+
+ /*
+ * "cancel" the events by calling their callback.
+ * Currently, events are used for lock and memory
+ * management, so if the process is dying the right
+ * thing to do is release or free.
+ */
+ if (event->func)
+ event->func(device, event->priv, id, cur);
+
+ list_del(&event->list);
+ kfree(event);
+ }
+}
+
+/**
* kgsl_cancel_events - Cancel all events for a process
* @device - KGSL device for the events to cancel
* @owner - driver instance that owns the events to cancel
@@ -457,12 +491,9 @@
struct kgsl_context *context, unsigned int timestamp)
{
unsigned int ts_processed;
- unsigned int global;
ts_processed = device->ftbl->readtimestamp(device, context,
KGSL_TIMESTAMP_RETIRED);
- global = device->ftbl->readtimestamp(device, NULL,
- KGSL_TIMESTAMP_RETIRED);
return (timestamp_cmp(ts_processed, timestamp) >= 0);
}
@@ -718,6 +749,11 @@
mutex_lock(&device->mutex);
kgsl_check_suspended(device);
+ /* clean up any to-be-freed entries that belong to this
+ * process and this device
+ */
+ kgsl_cancel_events(device, dev_priv);
+
while (1) {
context = idr_get_next(&device->context_idr, &next);
if (context == NULL)
@@ -736,10 +772,6 @@
result = device->ftbl->stop(device);
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
}
- /* clean up any to-be-freed entries that belong to this
- * process and this device
- */
- kgsl_cancel_events(device, dev_priv);
mutex_unlock(&device->mutex);
kfree(dev_priv);
@@ -1239,6 +1271,8 @@
goto done;
}
+ kgsl_cancel_events_ctxt(dev_priv->device, context);
+
if (dev_priv->device->ftbl->drawctxt_destroy)
dev_priv->device->ftbl->drawctxt_destroy(dev_priv->device,
context);
@@ -2261,6 +2295,14 @@
return 0;
}
+static irqreturn_t kgsl_irq_handler(int irq, void *data)
+{
+ struct kgsl_device *device = data;
+
+ return device->ftbl->irq_handler(device);
+
+}
+
static const struct file_operations kgsl_fops = {
.owner = THIS_MODULE,
.release = kgsl_release,
@@ -2421,8 +2463,7 @@
}
EXPORT_SYMBOL(kgsl_register_device);
-int kgsl_device_platform_probe(struct kgsl_device *device,
- irqreturn_t (*dev_isr) (int, void*))
+int kgsl_device_platform_probe(struct kgsl_device *device)
{
int result;
int status = -EINVAL;
@@ -2470,7 +2511,7 @@
goto error_release_mem;
}
- status = request_irq(device->pwrctrl.interrupt_num, dev_isr,
+ status = request_irq(device->pwrctrl.interrupt_num, kgsl_irq_handler,
IRQF_TRIGGER_HIGH, device->name, device);
if (status) {
KGSL_DRV_ERR(device, "request_irq(%d) failed: %d\n",
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 5212d0f..9f80a73 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -33,7 +33,7 @@
#define KGSL_MEMSTORE_MAX (KGSL_MEMSTORE_SIZE / \
sizeof(struct kgsl_devmemstore) - 1)
-/* Timestamp window used to detect rollovers */
+/* Timestamp window used to detect rollovers (half of integer range) */
#define KGSL_TIMESTAMP_WINDOW 0x80000000
/*cache coherency ops */
@@ -229,14 +229,24 @@
return hostptr != NULL ? hostptr + (gpuaddr - memdesc->gpuaddr) : NULL;
}
-static inline int timestamp_cmp(unsigned int new, unsigned int old)
+static inline int timestamp_cmp(unsigned int a, unsigned int b)
{
- int ts_diff = new - old;
-
- if (ts_diff == 0)
+ /* check for equal */
+ if (a == b)
return 0;
- return ((ts_diff > 0) || (ts_diff < -KGSL_TIMESTAMP_WINDOW)) ? 1 : -1;
+ /* check for greater-than for non-rollover case */
+ if ((a > b) && (a - b < KGSL_TIMESTAMP_WINDOW))
+ return 1;
+
+ /* check for greater-than for rollover case
+ * note that <= is required to ensure that consistent
+ * results are returned for values whose difference is
+ * equal to the window size
+ */
+ a += KGSL_TIMESTAMP_WINDOW;
+ b += KGSL_TIMESTAMP_WINDOW;
+ return ((a > b) && (a - b <= KGSL_TIMESTAMP_WINDOW)) ? 1 : -1;
}
static inline void
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 7d3cfca..b42e606 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -94,6 +94,7 @@
unsigned int (*gpuid)(struct kgsl_device *device);
void * (*snapshot)(struct kgsl_device *device, void *snapshot,
int *remain, int hang);
+ irqreturn_t (*irq_handler)(struct kgsl_device *device);
/* Optional functions - these functions are not mandatory. The
driver will check that the function pointer is not NULL before
calling the hook */
@@ -340,8 +341,8 @@
int kgsl_unregister_ts_notifier(struct kgsl_device *device,
struct notifier_block *nb);
-int kgsl_device_platform_probe(struct kgsl_device *device,
- irqreturn_t (*dev_isr) (int, void*));
+int kgsl_device_platform_probe(struct kgsl_device *device);
+
void kgsl_device_platform_remove(struct kgsl_device *device);
const char *kgsl_pwrstate_to_str(unsigned int state);
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index bbb5d46..1d80a30 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -397,34 +397,15 @@
return baseptr[pte] & GSL_PT_PAGE_ADDR_MASK;
}
-static unsigned int kgsl_gpummu_pt_get_flags(struct kgsl_pagetable *pt,
- enum kgsl_deviceid id)
-{
- unsigned int result = 0;
- struct kgsl_gpummu_pt *gpummu_pt;
-
- if (pt == NULL)
- return 0;
- gpummu_pt = pt->priv;
-
- spin_lock(&pt->lock);
- if (gpummu_pt->tlb_flags && (1<<id)) {
- result = KGSL_MMUFLAGS_TLBFLUSH;
- gpummu_pt->tlb_flags &= ~(1<<id);
- }
- spin_unlock(&pt->lock);
- return result;
-}
-
-static void kgsl_gpummu_pagefault(struct kgsl_device *device)
+static void kgsl_gpummu_pagefault(struct kgsl_mmu *mmu)
{
unsigned int reg;
unsigned int ptbase;
- kgsl_regread(device, MH_MMU_PAGE_FAULT, ®);
- kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
+ kgsl_regread(mmu->device, MH_MMU_PAGE_FAULT, ®);
+ kgsl_regread(mmu->device, MH_MMU_PT_BASE, &ptbase);
- KGSL_MEM_CRIT(device,
+ KGSL_MEM_CRIT(mmu->device,
"mmu page fault: page=0x%lx pt=%d op=%s axi=%d\n",
reg & ~(PAGE_SIZE - 1),
kgsl_mmu_get_ptname_from_ptbase(ptbase),
@@ -440,7 +421,6 @@
if (!gpummu_pt)
return NULL;
- gpummu_pt->tlb_flags = 0;
gpummu_pt->last_superpte = 0;
gpummu_pt->tlbflushfilter.size = (CONFIG_MSM_KGSL_PAGE_TABLE_SIZE /
@@ -480,7 +460,7 @@
return NULL;
}
-static void kgsl_gpummu_default_setstate(struct kgsl_device *device,
+static void kgsl_gpummu_default_setstate(struct kgsl_mmu *mmu,
uint32_t flags)
{
struct kgsl_gpummu_pt *gpummu_pt;
@@ -488,43 +468,40 @@
return;
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
- kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
- gpummu_pt = device->mmu.hwpagetable->priv;
- kgsl_regwrite(device, MH_MMU_PT_BASE,
+ kgsl_idle(mmu->device, KGSL_TIMEOUT_DEFAULT);
+ gpummu_pt = mmu->hwpagetable->priv;
+ kgsl_regwrite(mmu->device, MH_MMU_PT_BASE,
gpummu_pt->base.gpuaddr);
}
if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
/* Invalidate all and tc */
- kgsl_regwrite(device, MH_MMU_INVALIDATE, 0x00000003);
+ kgsl_regwrite(mmu->device, MH_MMU_INVALIDATE, 0x00000003);
}
}
-static void kgsl_gpummu_setstate(struct kgsl_device *device,
+static void kgsl_gpummu_setstate(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable)
{
- struct kgsl_mmu *mmu = &device->mmu;
- struct kgsl_gpummu_pt *gpummu_pt;
-
if (mmu->flags & KGSL_FLAGS_STARTED) {
/* page table not current, then setup mmu to use new
* specified page table
*/
if (mmu->hwpagetable != pagetable) {
mmu->hwpagetable = pagetable;
- spin_lock(&mmu->hwpagetable->lock);
- gpummu_pt = mmu->hwpagetable->priv;
- gpummu_pt->tlb_flags &= ~(1<<device->id);
- spin_unlock(&mmu->hwpagetable->lock);
+ /* Since we do a TLB flush the tlb_flags should
+ * be cleared by calling kgsl_mmu_pt_get_flags
+ */
+ kgsl_mmu_pt_get_flags(pagetable, mmu->device->id);
/* call device specific set page table */
- kgsl_setstate(mmu->device, KGSL_MMUFLAGS_TLBFLUSH |
+ kgsl_setstate(mmu, KGSL_MMUFLAGS_TLBFLUSH |
KGSL_MMUFLAGS_PTUPDATE);
}
}
}
-static int kgsl_gpummu_init(struct kgsl_device *device)
+static int kgsl_gpummu_init(struct kgsl_mmu *mmu)
{
/*
* intialize device mmu
@@ -532,9 +509,6 @@
* call this with the global lock held
*/
int status = 0;
- struct kgsl_mmu *mmu = &device->mmu;
-
- mmu->device = device;
/* sub-client MMU lookups require address translation */
if ((mmu->config & ~0x1) > 0) {
@@ -554,12 +528,12 @@
mmu->setstate_memory.size);
}
- dev_info(device->dev, "|%s| MMU type set for device is GPUMMU\n",
+ dev_info(mmu->device->dev, "|%s| MMU type set for device is GPUMMU\n",
__func__);
return status;
}
-static int kgsl_gpummu_start(struct kgsl_device *device)
+static int kgsl_gpummu_start(struct kgsl_mmu *mmu)
{
/*
* intialize device mmu
@@ -567,7 +541,7 @@
* call this with the global lock held
*/
- struct kgsl_mmu *mmu = &device->mmu;
+ struct kgsl_device *device = mmu->device;
struct kgsl_gpummu_pt *gpummu_pt;
if (mmu->flags & KGSL_FLAGS_STARTED)
@@ -608,12 +582,12 @@
mmu->hwpagetable = mmu->defaultpagetable;
gpummu_pt = mmu->hwpagetable->priv;
- kgsl_regwrite(device, MH_MMU_PT_BASE,
+ kgsl_regwrite(mmu->device, MH_MMU_PT_BASE,
gpummu_pt->base.gpuaddr);
- kgsl_regwrite(device, MH_MMU_VA_RANGE,
+ kgsl_regwrite(mmu->device, MH_MMU_VA_RANGE,
(KGSL_PAGETABLE_BASE |
(CONFIG_MSM_KGSL_PAGE_TABLE_SIZE >> 16)));
- kgsl_setstate(device, KGSL_MMUFLAGS_TLBFLUSH);
+ kgsl_setstate(mmu, KGSL_MMUFLAGS_TLBFLUSH);
mmu->flags |= KGSL_FLAGS_STARTED;
return 0;
@@ -670,7 +644,8 @@
static int
kgsl_gpummu_map(void *mmu_specific_pt,
struct kgsl_memdesc *memdesc,
- unsigned int protflags)
+ unsigned int protflags,
+ unsigned int *tlb_flags)
{
unsigned int pte;
struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt;
@@ -704,32 +679,28 @@
if (flushtlb) {
/*set all devices as needing flushing*/
- gpummu_pt->tlb_flags = UINT_MAX;
+ *tlb_flags = UINT_MAX;
GSL_TLBFLUSH_FILTER_RESET();
}
return 0;
}
-static int kgsl_gpummu_stop(struct kgsl_device *device)
+static int kgsl_gpummu_stop(struct kgsl_mmu *mmu)
{
- struct kgsl_mmu *mmu = &device->mmu;
-
- kgsl_regwrite(device, MH_MMU_CONFIG, 0x00000000);
+ kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
mmu->flags &= ~KGSL_FLAGS_STARTED;
return 0;
}
-static int kgsl_gpummu_close(struct kgsl_device *device)
+static int kgsl_gpummu_close(struct kgsl_mmu *mmu)
{
/*
* close device mmu
*
* call this with the global lock held
*/
- struct kgsl_mmu *mmu = &device->mmu;
-
if (mmu->setstate_memory.gpuaddr)
kgsl_sharedmem_free(&mmu->setstate_memory);
@@ -740,10 +711,10 @@
}
static unsigned int
-kgsl_gpummu_get_current_ptbase(struct kgsl_device *device)
+kgsl_gpummu_get_current_ptbase(struct kgsl_mmu *mmu)
{
unsigned int ptbase;
- kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
+ kgsl_regread(mmu->device, MH_MMU_PT_BASE, &ptbase);
return ptbase;
}
@@ -764,5 +735,4 @@
.mmu_create_pagetable = kgsl_gpummu_create_pagetable,
.mmu_destroy_pagetable = kgsl_gpummu_destroy_pagetable,
.mmu_pt_equal = kgsl_gpummu_pt_equal,
- .mmu_pt_get_flags = kgsl_gpummu_pt_get_flags,
};
diff --git a/drivers/gpu/msm/kgsl_gpummu.h b/drivers/gpu/msm/kgsl_gpummu.h
index cac6930..c61a8b2 100644
--- a/drivers/gpu/msm/kgsl_gpummu.h
+++ b/drivers/gpu/msm/kgsl_gpummu.h
@@ -47,7 +47,6 @@
struct kgsl_gpummu_pt {
struct kgsl_memdesc base;
unsigned int last_superpte;
- unsigned int tlb_flags;
/* Maintain filter to manage tlb flushing */
struct kgsl_tlbflushfilter tlbflushfilter;
};
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 50086d2..bf2a4ee 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -166,17 +166,15 @@
return ret;
}
-static void kgsl_iommu_setstate(struct kgsl_device *device,
+static void kgsl_iommu_setstate(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable)
{
- struct kgsl_mmu *mmu = &device->mmu;
-
if (mmu->flags & KGSL_FLAGS_STARTED) {
/* page table not current, then setup mmu to use new
* specified page table
*/
if (mmu->hwpagetable != pagetable) {
- kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
+ kgsl_idle(mmu->device, KGSL_TIMEOUT_DEFAULT);
kgsl_detach_pagetable_iommu_domain(mmu);
mmu->hwpagetable = pagetable;
if (mmu->hwpagetable)
@@ -185,7 +183,7 @@
}
}
-static int kgsl_iommu_init(struct kgsl_device *device)
+static int kgsl_iommu_init(struct kgsl_mmu *mmu)
{
/*
* intialize device mmu
@@ -193,11 +191,8 @@
* call this with the global lock held
*/
int status = 0;
- struct kgsl_mmu *mmu = &device->mmu;
struct kgsl_iommu *iommu;
- mmu->device = device;
-
iommu = kzalloc(sizeof(struct kgsl_iommu), GFP_KERNEL);
if (!iommu) {
KGSL_CORE_ERR("kzalloc(%d) failed\n",
@@ -205,27 +200,26 @@
return -ENOMEM;
}
- status = kgsl_get_iommu_ctxt(iommu, device);
+ status = kgsl_get_iommu_ctxt(iommu, mmu->device);
if (status) {
kfree(iommu);
iommu = NULL;
}
mmu->priv = iommu;
- dev_info(device->dev, "|%s| MMU type set for device is IOMMU\n",
+ dev_info(mmu->device->dev, "|%s| MMU type set for device is IOMMU\n",
__func__);
return status;
}
-static int kgsl_iommu_start(struct kgsl_device *device)
+static int kgsl_iommu_start(struct kgsl_mmu *mmu)
{
int status;
- struct kgsl_mmu *mmu = &device->mmu;
if (mmu->flags & KGSL_FLAGS_STARTED)
return 0;
- kgsl_regwrite(device, MH_MMU_CONFIG, 0x00000000);
+ kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
if (mmu->defaultpagetable == NULL)
mmu->defaultpagetable =
kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
@@ -271,7 +265,8 @@
static int
kgsl_iommu_map(void *mmu_specific_pt,
struct kgsl_memdesc *memdesc,
- unsigned int protflags)
+ unsigned int protflags,
+ unsigned int *tlb_flags)
{
int ret;
unsigned int iommu_virt_addr;
@@ -292,17 +287,24 @@
return ret;
}
+#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
+ /*
+ * Flushing only required if per process pagetables are used. With
+ * global case, flushing will happen inside iommu_map function
+ */
+ if (!ret)
+ *tlb_flags = UINT_MAX;
+#endif
return ret;
}
-static int kgsl_iommu_stop(struct kgsl_device *device)
+static int kgsl_iommu_stop(struct kgsl_mmu *mmu)
{
/*
* stop device mmu
*
* call this with the global lock held
*/
- struct kgsl_mmu *mmu = &device->mmu;
if (mmu->flags & KGSL_FLAGS_STARTED) {
/* detach iommu attachment */
@@ -314,9 +316,8 @@
return 0;
}
-static int kgsl_iommu_close(struct kgsl_device *device)
+static int kgsl_iommu_close(struct kgsl_mmu *mmu)
{
- struct kgsl_mmu *mmu = &device->mmu;
if (mmu->defaultpagetable)
kgsl_mmu_putpagetable(mmu->defaultpagetable);
@@ -324,13 +325,13 @@
}
static unsigned int
-kgsl_iommu_get_current_ptbase(struct kgsl_device *device)
+kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu)
{
/* Current base is always the hwpagetables domain as we
* do not use per process pagetables right not for iommu.
* This will change when we switch to per process pagetables.
*/
- return (unsigned int)device->mmu.hwpagetable->priv;
+ return (unsigned int)mmu->hwpagetable->priv;
}
struct kgsl_mmu_ops iommu_ops = {
@@ -350,5 +351,4 @@
.mmu_create_pagetable = kgsl_iommu_create_pagetable,
.mmu_destroy_pagetable = kgsl_iommu_destroy_pagetable,
.mmu_pt_equal = kgsl_iommu_pt_equal,
- .mmu_pt_get_flags = NULL,
};
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 7eb5ee9..2b359ec 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -36,7 +36,8 @@
{
int i;
/* For IOMMU only unmap the global structures to global pt */
- if ((KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
+ if ((KGSL_MMU_TYPE_NONE != kgsl_mmu_type) &&
+ (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
(KGSL_MMU_GLOBAL_PT != pt->name))
return 0;
for (i = 0; i < KGSL_DEVICE_MAX; i++) {
@@ -47,6 +48,36 @@
return 0;
}
+
+static int kgsl_setup_pt(struct kgsl_pagetable *pt)
+{
+ int i = 0;
+ int status = 0;
+
+ /* For IOMMU only map the global structures to global pt */
+ if ((KGSL_MMU_TYPE_NONE != kgsl_mmu_type) &&
+ (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
+ (KGSL_MMU_GLOBAL_PT != pt->name))
+ return 0;
+ for (i = 0; i < KGSL_DEVICE_MAX; i++) {
+ struct kgsl_device *device = kgsl_driver.devp[i];
+ if (device) {
+ status = device->ftbl->setup_pt(device, pt);
+ if (status)
+ goto error_pt;
+ }
+ }
+ return status;
+error_pt:
+ while (i >= 0) {
+ struct kgsl_device *device = kgsl_driver.devp[i];
+ if (device)
+ device->ftbl->cleanup_pt(device, pt);
+ i--;
+ }
+ return status;
+}
+
static void kgsl_destroy_pagetable(struct kref *kref)
{
struct kgsl_pagetable *pagetable = container_of(kref,
@@ -297,7 +328,7 @@
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return 0;
else
- return mmu->mmu_ops->mmu_get_current_ptbase(device);
+ return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
}
EXPORT_SYMBOL(kgsl_mmu_get_current_ptbase);
@@ -328,7 +359,7 @@
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
else
- mmu->mmu_ops->mmu_setstate(device,
+ mmu->mmu_ops->mmu_setstate(mmu,
pagetable);
}
EXPORT_SYMBOL(kgsl_mmu_setstate);
@@ -340,15 +371,21 @@
mmu->device = device;
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) {
- dev_info(device->dev, "|%s| MMU type set for device is "
- "NOMMU\n", __func__);
- return 0;
+ int status = 0;
+ status = kgsl_allocate_contiguous(&mmu->setstate_memory, 64);
+ if (!status) {
+ kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0,
+ mmu->setstate_memory.size);
+ dev_info(device->dev, "|%s| MMU type set for device is "
+ "NOMMU\n", __func__);
+ }
+ return status;
} else if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
mmu->mmu_ops = &gpummu_ops;
else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type)
mmu->mmu_ops = &iommu_ops;
- return mmu->mmu_ops->mmu_init(device);
+ return mmu->mmu_ops->mmu_init(mmu);
}
EXPORT_SYMBOL(kgsl_mmu_init);
@@ -358,9 +395,12 @@
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
kgsl_regwrite(device, MH_MMU_CONFIG, 0);
+ /* Setup gpuaddr of global mappings */
+ if (!mmu->setstate_memory.gpuaddr)
+ kgsl_setup_pt(NULL);
return 0;
} else {
- return mmu->mmu_ops->mmu_start(device);
+ return mmu->mmu_ops->mmu_start(mmu);
}
}
EXPORT_SYMBOL(kgsl_mmu_start);
@@ -378,41 +418,13 @@
if (status & MH_INTERRUPT_MASK__AXI_WRITE_ERROR)
KGSL_MEM_CRIT(device, "axi write error interrupt: %08x\n", reg);
if (status & MH_INTERRUPT_MASK__MMU_PAGE_FAULT)
- device->mmu.mmu_ops->mmu_pagefault(device);
+ device->mmu.mmu_ops->mmu_pagefault(&device->mmu);
status &= KGSL_MMU_INT_MASK;
kgsl_regwrite(device, MH_INTERRUPT_CLEAR, status);
}
EXPORT_SYMBOL(kgsl_mh_intrcallback);
-static int kgsl_setup_pt(struct kgsl_pagetable *pt)
-{
- int i = 0;
- int status = 0;
-
- /* For IOMMU only map the global structures to global pt */
- if ((KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type) &&
- (KGSL_MMU_GLOBAL_PT != pt->name))
- return 0;
- for (i = 0; i < KGSL_DEVICE_MAX; i++) {
- struct kgsl_device *device = kgsl_driver.devp[i];
- if (device) {
- status = device->ftbl->setup_pt(device, pt);
- if (status)
- goto error_pt;
- }
- }
- return status;
-error_pt:
- while (i >= 0) {
- struct kgsl_device *device = kgsl_driver.devp[i];
- if (device)
- device->ftbl->cleanup_pt(device, pt);
- i--;
- }
- return status;
-}
-
static struct kgsl_pagetable *kgsl_mmu_createpagetableobject(
unsigned int name)
{
@@ -531,15 +543,15 @@
}
EXPORT_SYMBOL(kgsl_mmu_putpagetable);
-void kgsl_setstate(struct kgsl_device *device, uint32_t flags)
+void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags)
{
- struct kgsl_mmu *mmu = &device->mmu;
+ struct kgsl_device *device = mmu->device;
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
else if (device->ftbl->setstate)
device->ftbl->setstate(device, flags);
else if (mmu->mmu_ops->mmu_device_setstate)
- mmu->mmu_ops->mmu_device_setstate(device, flags);
+ mmu->mmu_ops->mmu_device_setstate(mmu, flags);
}
EXPORT_SYMBOL(kgsl_setstate);
@@ -549,7 +561,7 @@
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
else if (mmu->mmu_ops->mmu_device_setstate)
- mmu->mmu_ops->mmu_device_setstate(device, flags);
+ mmu->mmu_ops->mmu_device_setstate(mmu, flags);
}
EXPORT_SYMBOL(kgsl_mmu_device_setstate);
@@ -589,7 +601,14 @@
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
if (memdesc->sglen == 1) {
- memdesc->gpuaddr = sg_phys(memdesc->sg);
+ memdesc->gpuaddr = sg_dma_address(memdesc->sg);
+ if (!memdesc->gpuaddr)
+ memdesc->gpuaddr = sg_phys(memdesc->sg);
+ if (!memdesc->gpuaddr) {
+ KGSL_CORE_ERR("Unable to get a valid physical "
+ "address for memdesc\n");
+ return -EINVAL;
+ }
return 0;
} else {
KGSL_CORE_ERR("Memory is not contigious "
@@ -621,7 +640,8 @@
if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
spin_lock(&pagetable->lock);
- ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags);
+ ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags,
+ &pagetable->tlb_flags);
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
spin_lock(&pagetable->lock);
@@ -733,7 +753,7 @@
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
return 0;
else
- return mmu->mmu_ops->mmu_stop(device);
+ return mmu->mmu_ops->mmu_stop(mmu);
}
EXPORT_SYMBOL(kgsl_mmu_stop);
@@ -741,20 +761,30 @@
{
struct kgsl_mmu *mmu = &device->mmu;
- if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
+ if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
+ kgsl_sharedmem_free(&mmu->setstate_memory);
return 0;
- else
- return mmu->mmu_ops->mmu_close(device);
+ } else {
+ return mmu->mmu_ops->mmu_close(mmu);
+ }
}
EXPORT_SYMBOL(kgsl_mmu_close);
int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
enum kgsl_deviceid id)
{
- if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
- return pt->pt_ops->mmu_pt_get_flags(pt, id);
- else
+ unsigned int result = 0;
+
+ if (pt == NULL)
return 0;
+
+ spin_lock(&pt->lock);
+ if (pt->tlb_flags && (1<<id)) {
+ result = KGSL_MMUFLAGS_TLBFLUSH;
+ pt->tlb_flags &= ~(1<<id);
+ }
+ spin_unlock(&pt->lock);
+ return result;
}
EXPORT_SYMBOL(kgsl_mmu_pt_get_flags);
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index bff41bf..e35f368 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -112,35 +112,37 @@
unsigned int max_entries;
} stats;
const struct kgsl_mmu_pt_ops *pt_ops;
+ unsigned int tlb_flags;
void *priv;
};
+struct kgsl_mmu;
+
struct kgsl_mmu_ops {
- int (*mmu_init) (struct kgsl_device *device);
- int (*mmu_close) (struct kgsl_device *device);
- int (*mmu_start) (struct kgsl_device *device);
- int (*mmu_stop) (struct kgsl_device *device);
- void (*mmu_setstate) (struct kgsl_device *device,
+ int (*mmu_init) (struct kgsl_mmu *mmu);
+ int (*mmu_close) (struct kgsl_mmu *mmu);
+ int (*mmu_start) (struct kgsl_mmu *mmu);
+ int (*mmu_stop) (struct kgsl_mmu *mmu);
+ void (*mmu_setstate) (struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable);
- void (*mmu_device_setstate) (struct kgsl_device *device,
+ void (*mmu_device_setstate) (struct kgsl_mmu *mmu,
uint32_t flags);
- void (*mmu_pagefault) (struct kgsl_device *device);
+ void (*mmu_pagefault) (struct kgsl_mmu *mmu);
unsigned int (*mmu_get_current_ptbase)
- (struct kgsl_device *device);
+ (struct kgsl_mmu *mmu);
};
struct kgsl_mmu_pt_ops {
int (*mmu_map) (void *mmu_pt,
struct kgsl_memdesc *memdesc,
- unsigned int protflags);
+ unsigned int protflags,
+ unsigned int *tlb_flags);
int (*mmu_unmap) (void *mmu_pt,
struct kgsl_memdesc *memdesc);
void *(*mmu_create_pagetable) (void);
void (*mmu_destroy_pagetable) (void *pt);
int (*mmu_pt_equal) (struct kgsl_pagetable *pt,
unsigned int pt_base);
- unsigned int (*mmu_pt_get_flags) (struct kgsl_pagetable *pt,
- enum kgsl_deviceid id);
};
struct kgsl_mmu {
@@ -177,7 +179,7 @@
int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
-void kgsl_setstate(struct kgsl_device *device, uint32_t flags);
+void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags);
void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags);
void kgsl_mmu_setstate(struct kgsl_device *device,
struct kgsl_pagetable *pt);
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index b2b3071..47b6bb2 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -244,8 +244,8 @@
void kgsl_pwrscale_idle(struct kgsl_device *device)
{
if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->idle)
- if (device->requested_state !=
- (KGSL_STATE_SLUMBER | KGSL_STATE_SLEEP))
+ if (device->requested_state != KGSL_STATE_SLUMBER &&
+ device->requested_state != KGSL_STATE_SLEEP)
device->pwrscale.policy->idle(device,
&device->pwrscale);
device->pwrscale.gpu_busy = 0;
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index f77a02b..61d4b2d 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -16,6 +16,7 @@
#include "kgsl.h"
#include "kgsl_pwrscale.h"
#include "kgsl_device.h"
+#include "a2xx_reg.h"
struct msm_priv {
struct kgsl_device *device;
@@ -97,7 +98,11 @@
struct kgsl_pwrscale *pwrscale)
{
struct msm_priv *priv = pwrscale->priv;
- if (priv->enabled && pwrscale->gpu_busy)
+ unsigned int rb_rptr, rb_wptr;
+ kgsl_regread(device, REG_CP_RB_RPTR, &rb_rptr);
+ kgsl_regread(device, REG_CP_RB_WPTR, &rb_wptr);
+
+ if (priv->enabled && (rb_rptr == rb_wptr))
msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
return;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index c8db702..24ea571 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -511,6 +511,8 @@
KGSL_DRV_ERR(device, "snapshot created at va %p pa %lx size %d\n",
device->snapshot, __pa(device->snapshot),
device->snapshot_size);
+ if (hang)
+ sysfs_notify(&device->snapshot_kobj, NULL, "timestamp");
return 0;
}
EXPORT_SYMBOL(kgsl_device_snapshot);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 8c29535..3ca9e18 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -206,11 +206,10 @@
},
};
-static irqreturn_t z180_isr(int irq, void *data)
+static irqreturn_t z180_irq_handler(struct kgsl_device *device)
{
irqreturn_t result = IRQ_NONE;
unsigned int status;
- struct kgsl_device *device = (struct kgsl_device *) data;
struct z180_device *z180_dev = Z180_DEVICE(device);
z180_regread(device, ADDR_VGC_IRQSTATUS >> 2, &status);
@@ -469,8 +468,9 @@
cnt = PACKETSIZE_STATESTREAM;
ofs = 0;
}
- kgsl_setstate(device, kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
- device->id));
+ kgsl_setstate(&device->mmu,
+ kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
+ device->id));
result = wait_event_interruptible_timeout(device->wait_queue,
room_in_rb(z180_dev),
@@ -546,7 +546,7 @@
if (status != 0)
goto error;
- status = kgsl_device_platform_probe(device, z180_isr);
+ status = kgsl_device_platform_probe(device);
if (status)
goto error_close_ringbuffer;
@@ -882,7 +882,7 @@
if (z180_dev->ringbuffer.prevctx == context->id) {
z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
device->mmu.hwpagetable = device->mmu.defaultpagetable;
- kgsl_setstate(device, KGSL_MMUFLAGS_PTUPDATE);
+ kgsl_setstate(&device->mmu, KGSL_MMUFLAGS_PTUPDATE);
}
}
@@ -945,6 +945,7 @@
.power_stats = z180_power_stats,
.irqctrl = z180_irqctrl,
.gpuid = z180_gpuid,
+ .irq_handler = z180_irq_handler,
/* Optional functions */
.drawctxt_create = NULL,
.drawctxt_destroy = z180_drawctxt_destroy,
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index daa0b58..0bd9cbc 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -805,7 +805,7 @@
},
};
-static int epm_adc_probe(struct platform_device *pdev)
+static int __devinit epm_adc_probe(struct platform_device *pdev)
{
struct epm_adc_drv *epm_adc;
struct epm_adc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 0eeb338..3238d33 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2209,7 +2209,7 @@
.release = single_release,
};
-static void __init mxt_debugfs_init(struct mxt_data *data)
+static void __devinit mxt_debugfs_init(struct mxt_data *data)
{
debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
if (IS_ERR_OR_NULL(debug_base))
diff --git a/drivers/input/touchscreen/msm_ts.c b/drivers/input/touchscreen/msm_ts.c
index 122b45d..eb2e73b 100644
--- a/drivers/input/touchscreen/msm_ts.c
+++ b/drivers/input/touchscreen/msm_ts.c
@@ -1,7 +1,7 @@
/* drivers/input/touchscreen/msm_ts.c
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -207,7 +207,7 @@
#undef __dump_tssc_reg
}
-static int __devinit msm_ts_hw_init(struct msm_ts *ts)
+static int msm_ts_hw_init(struct msm_ts *ts)
{
uint32_t tmp;
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index 741c3a1..acf551e 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -2157,6 +2157,7 @@
marimba_set_fm_status(radio->marimba, false);
wait_for_completion(&radio->shutdown_done);
radio->handle_irq = 1;
+ radio->lp_mode = 1;
atomic_inc(&radio->users);
radio->marimba->mod_id = SLAVE_ID_BAHAMA;
flush_workqueue(radio->wqueue);
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 6744479..6d8cc5c 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -87,7 +87,7 @@
rcdev->input_name = GPIO_IR_DEVICE_NAME;
rcdev->input_id.bustype = BUS_HOST;
rcdev->driver_name = GPIO_IR_DRIVER_NAME;
- rcdev->map_name = RC_MAP_EMPTY;
+ rcdev->map_name = RC_MAP_RC6_PHILIPS;
gpio_dev->rcdev = rcdev;
gpio_dev->gpio_nr = pdata->gpio_nr;
@@ -115,6 +115,8 @@
if (rc < 0)
goto err_request_irq;
+ device_init_wakeup(pdata->can_wakeup);
+
return 0;
err_request_irq:
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 3dea4e9..4fd6e49 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -3,10 +3,10 @@
CFLAGS_REMOVE_msm_vfe8x.o = -Wframe-larger-than=1024
endif
+EXTRA_CFLAGS += -Idrivers/media/video/msm/io
obj-$(CONFIG_MSM_CAMERA) += io/
ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
- EXTRA_CFLAGS += -Idrivers/media/video/msm/io
EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
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) += sensors/ actuators/ csi/
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index 00828c9..b4adbaf 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -285,6 +285,7 @@
if (rc < 0) {
csic_dev->hw_version = 0;
iounmap(csic_dev->base);
+ csic_dev->base = NULL;
return rc;
}
}
@@ -427,6 +428,7 @@
}
disable_irq(new_csic_dev->irq->start);
iounmap(new_csic_dev->base);
+ new_csic_dev->base = NULL;
new_csic_dev->pdev = pdev;
return 0;
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 1ecbfca..0cd2cf0 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -224,6 +224,7 @@
ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
vreg_config_failed:
iounmap(csid_dev->base);
+ csid_dev->base = NULL;
return rc;
}
@@ -244,6 +245,7 @@
ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
iounmap(csid_dev->base);
+ csid_dev->base = NULL;
return 0;
}
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index 36385ca..aef017f 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -201,6 +201,7 @@
if (rc < 0) {
iounmap(csiphy_dev->base);
+ csiphy_dev->base = NULL;
return rc;
}
@@ -231,6 +232,7 @@
csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 0);
iounmap(csiphy_dev->base);
+ csiphy_dev->base = NULL;
return 0;
}
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.c b/drivers/media/video/msm/gemini/msm_gemini_platform.c
index ee0ff2f..fb5b035 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_platform.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_platform.c
@@ -20,6 +20,7 @@
#include <mach/msm_subsystem_map.h>
#include "msm_gemini_platform.h"
+#include "msm_gemini_sync.h"
#include "msm_gemini_common.h"
#include "msm_gemini_hw.h"
@@ -80,6 +81,20 @@
return 0;
}
+static struct msm_cam_clk_info gemini_8x_clk_info[] = {
+ {"ijpeg_clk", 228571000},
+ {"ijpeg_pclk", -1},
+};
+
+static struct msm_cam_clk_info gemini_7x_clk_info[] = {
+ {"jpeg_clk", 153600000},
+ {"jpeg_pclk", -1},
+};
+
+static struct msm_cam_clk_info gemini_imem_clk_info[] = {
+ {"imem_clk", -1},
+};
+
int msm_gemini_platform_init(struct platform_device *pdev,
struct resource **mem,
void **base,
@@ -91,6 +106,8 @@
int gemini_irq;
struct resource *gemini_mem, *gemini_io, *gemini_irq_res;
void *gemini_base;
+ struct msm_gemini_device *pgmn_dev =
+ (struct msm_gemini_device *) context;
gemini_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!gemini_mem) {
@@ -119,10 +136,43 @@
goto fail1;
}
- rc = msm_camio_jpeg_clk_enable();
- if (rc) {
- GMN_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
- goto fail2;
+ pgmn_dev->hw_version = GEMINI_8X60;
+ rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
+ pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 1);
+ if (rc < 0) {
+ pgmn_dev->hw_version = GEMINI_7X;
+ rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev,
+ gemini_7x_clk_info, pgmn_dev->gemini_clk,
+ ARRAY_SIZE(gemini_7x_clk_info), 1);
+ if (rc < 0) {
+ GMN_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
+ goto fail2;
+ }
+ } else {
+ rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev,
+ gemini_imem_clk_info, &pgmn_dev->gemini_clk[2],
+ ARRAY_SIZE(gemini_imem_clk_info), 1);
+ if (!rc)
+ pgmn_dev->hw_version = GEMINI_8960;
+ }
+
+ if (pgmn_dev->hw_version != GEMINI_7X) {
+ if (pgmn_dev->gemini_fs == NULL) {
+ pgmn_dev->gemini_fs =
+ regulator_get(&pgmn_dev->pdev->dev, "fs_ijpeg");
+ if (IS_ERR(pgmn_dev->gemini_fs)) {
+ pr_err("%s: Regulator FS_ijpeg get failed %ld\n",
+ __func__, PTR_ERR(pgmn_dev->gemini_fs));
+ pgmn_dev->gemini_fs = NULL;
+ goto gemini_fs_failed;
+ } else if (regulator_enable(pgmn_dev->gemini_fs)) {
+ pr_err("%s: Regulator FS_ijpeg enable failed\n",
+ __func__);
+ regulator_put(pgmn_dev->gemini_fs);
+ pgmn_dev->gemini_fs = NULL;
+ goto gemini_fs_failed;
+ }
+ }
}
msm_gemini_hw_init(gemini_base, resource_size(gemini_mem));
@@ -146,7 +196,21 @@
return rc;
fail3:
- msm_camio_jpeg_clk_disable();
+ if (pgmn_dev->hw_version != GEMINI_7X) {
+ regulator_disable(pgmn_dev->gemini_fs);
+ regulator_put(pgmn_dev->gemini_fs);
+ pgmn_dev->gemini_fs = NULL;
+ }
+gemini_fs_failed:
+ if (pgmn_dev->hw_version == GEMINI_8960)
+ msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_imem_clk_info,
+ &pgmn_dev->gemini_clk[2], ARRAY_SIZE(gemini_imem_clk_info), 0);
+ if (pgmn_dev->hw_version != GEMINI_7X)
+ msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
+ pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 0);
+ else
+ msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_7x_clk_info,
+ pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_7x_clk_info), 0);
fail2:
iounmap(gemini_base);
fail1:
@@ -158,10 +222,28 @@
int msm_gemini_platform_release(struct resource *mem, void *base, int irq,
void *context)
{
- int result;
+ int result = 0;
+ struct msm_gemini_device *pgmn_dev =
+ (struct msm_gemini_device *) context;
free_irq(irq, context);
- result = msm_camio_jpeg_clk_disable();
+
+ if (pgmn_dev->hw_version != GEMINI_7X) {
+ regulator_disable(pgmn_dev->gemini_fs);
+ regulator_put(pgmn_dev->gemini_fs);
+ pgmn_dev->gemini_fs = NULL;
+ }
+
+ if (pgmn_dev->hw_version == GEMINI_8960)
+ msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_imem_clk_info,
+ &pgmn_dev->gemini_clk[2], ARRAY_SIZE(gemini_imem_clk_info), 0);
+ if (pgmn_dev->hw_version != GEMINI_7X)
+ msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
+ pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 0);
+ else
+ msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_7x_clk_info,
+ pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_7x_clk_info), 0);
+
iounmap(base);
release_mem_region(mem->start, resource_size(mem));
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.h b/drivers/media/video/msm/gemini/msm_gemini_sync.h
index a47e766..1c6726d 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_sync.h
+++ b/drivers/media/video/msm/gemini/msm_gemini_sync.h
@@ -21,6 +21,10 @@
#include <media/v4l2-subdev.h>
#include "msm_gemini_core.h"
+#define GEMINI_7X 0x1
+#define GEMINI_8X60 (0x1 << 1)
+#define GEMINI_8960 (0x1 << 2)
+
struct msm_gemini_q {
char const *name;
struct list_head q;
@@ -39,6 +43,9 @@
struct resource *mem;
int irq;
void *base;
+ struct clk *gemini_clk[3];
+ struct regulator *gemini_fs;
+ uint32_t hw_version;
struct device *device;
struct cdev cdev;
diff --git a/drivers/media/video/msm/io/msm_io_8960.c b/drivers/media/video/msm/io/msm_io_8960.c
index 1ab4223..f9c454a 100644
--- a/drivers/media/video/msm/io/msm_io_8960.c
+++ b/drivers/media/video/msm/io/msm_io_8960.c
@@ -27,141 +27,11 @@
#define BUFF_SIZE_128 128
-static struct clk *camio_jpeg_clk;
-static struct clk *camio_jpeg_pclk;
-static struct clk *camio_imem_clk;
-static struct regulator *fs_ijpeg;
-
-int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
-{
- int rc = 0;
- struct clk *clk = NULL;
-
- switch (clktype) {
- case CAMIO_JPEG_CLK:
- camio_jpeg_clk =
- clk = clk_get(NULL, "ijpeg_clk");
- clk_set_rate(clk, 228571000);
- break;
-
- case CAMIO_JPEG_PCLK:
- camio_jpeg_pclk =
- clk = clk_get(NULL, "ijpeg_pclk");
- break;
-
- case CAMIO_IMEM_CLK:
- camio_imem_clk =
- clk = clk_get(NULL, "imem_clk");
- break;
-
- default:
- break;
- }
-
- if (!IS_ERR(clk))
- rc = clk_enable(clk);
- else
- rc = PTR_ERR(clk);
-
- if (rc < 0)
- pr_err("%s(%d) failed %d\n", __func__, clktype, rc);
-
- return rc;
-}
-
-int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
-{
- int rc = 0;
- struct clk *clk = NULL;
-
- switch (clktype) {
- case CAMIO_JPEG_CLK:
- clk = camio_jpeg_clk;
- break;
-
- case CAMIO_JPEG_PCLK:
- clk = camio_jpeg_pclk;
- break;
-
- case CAMIO_IMEM_CLK:
- clk = camio_imem_clk;
- break;
-
- default:
- break;
- }
-
- if (!IS_ERR(clk)) {
- clk_disable(clk);
- clk_put(clk);
- } else
- rc = PTR_ERR(clk);
-
- if (rc < 0)
- pr_err("%s(%d) failed %d\n", __func__, clktype, rc);
-
- return rc;
-}
-
void msm_camio_clk_rate_set_2(struct clk *clk, int rate)
{
clk_set_rate(clk, rate);
}
-int msm_camio_jpeg_clk_disable(void)
-{
- int rc = 0;
- rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_disable(CAMIO_IMEM_CLK);
- if (rc < 0)
- return rc;
-
- if (fs_ijpeg) {
- rc = regulator_disable(fs_ijpeg);
- if (rc < 0) {
- pr_err("%s: Regulator disable failed %d\n",
- __func__, rc);
- return rc;
- }
- regulator_put(fs_ijpeg);
- }
- CDBG("%s: exit %d\n", __func__, rc);
- return rc;
-}
-
-int msm_camio_jpeg_clk_enable(void)
-{
- int rc = 0;
- fs_ijpeg = regulator_get(NULL, "fs_ijpeg");
- if (IS_ERR(fs_ijpeg)) {
- pr_err("%s: Regulator FS_IJPEG get failed %ld\n",
- __func__, PTR_ERR(fs_ijpeg));
- fs_ijpeg = NULL;
- } else if (regulator_enable(fs_ijpeg)) {
- pr_err("%s: Regulator FS_IJPEG enable failed\n", __func__);
- regulator_put(fs_ijpeg);
- }
-
- rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
- if (rc < 0)
- return rc;
-
- rc = msm_camio_clk_enable(CAMIO_IMEM_CLK);
- if (rc < 0)
- return rc;
-
- CDBG("%s: exit %d\n", __func__, rc);
- return rc;
-}
-
void msm_camio_bus_scale_cfg(struct msm_bus_scale_pdata *cam_bus_scale_table,
enum msm_bus_perf_setting perf_setting)
{
diff --git a/drivers/media/video/msm/io/msm_io_8x60.c b/drivers/media/video/msm/io/msm_io_8x60.c
index 4e8dc25..baa1245 100644
--- a/drivers/media/video/msm/io/msm_io_8x60.c
+++ b/drivers/media/video/msm/io/msm_io_8x60.c
@@ -85,12 +85,9 @@
static struct clk *camio_csi0_pclk;
static struct clk *camio_csi1_pclk;
static struct clk *camio_vfe_pclk;
-static struct clk *camio_jpeg_clk;
-static struct clk *camio_jpeg_pclk;
static struct clk *camio_vpe_clk;
static struct clk *camio_vpe_pclk;
static struct regulator *fs_vfe;
-static struct regulator *fs_ijpeg;
static struct regulator *fs_vpe;
static struct regulator *ldo15;
static struct regulator *lvs0;
@@ -254,17 +251,6 @@
clk = clk_get(&camio_dev->dev, "csi_pclk");
break;
- case CAMIO_JPEG_CLK:
- camio_jpeg_clk =
- clk = clk_get(NULL, "ijpeg_clk");
- msm_camio_clk_rate_set_2(clk, 228571000);
- break;
-
- case CAMIO_JPEG_PCLK:
- camio_jpeg_pclk =
- clk = clk_get(NULL, "ijpeg_pclk");
- break;
-
case CAMIO_VPE_CLK:
camio_vpe_clk =
clk = clk_get(NULL, "vpe_clk");
@@ -334,14 +320,6 @@
clk = camio_csi1_pclk;
break;
- case CAMIO_JPEG_CLK:
- clk = camio_jpeg_clk;
- break;
-
- case CAMIO_JPEG_PCLK:
- clk = camio_jpeg_pclk;
- break;
-
case CAMIO_VPE_CLK:
clk = camio_vpe_clk;
break;
@@ -393,47 +371,6 @@
return IRQ_HANDLED;
}
-int msm_camio_jpeg_clk_disable(void)
-{
- int rc = 0;
- if (fs_ijpeg) {
- rc = regulator_disable(fs_ijpeg);
- if (rc < 0) {
- CDBG("%s: Regulator disable failed %d\n", __func__, rc);
- return rc;
- }
- regulator_put(fs_ijpeg);
- }
- rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
- CDBG("%s: exit %d\n", __func__, rc);
- return rc;
-}
-
-int msm_camio_jpeg_clk_enable(void)
-{
- int rc = 0;
- rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
- if (rc < 0)
- return rc;
- fs_ijpeg = regulator_get(NULL, "fs_ijpeg");
- if (IS_ERR(fs_ijpeg)) {
- CDBG("%s: Regulator FS_IJPEG get failed %ld\n", __func__,
- PTR_ERR(fs_ijpeg));
- fs_ijpeg = NULL;
- } else if (regulator_enable(fs_ijpeg)) {
- CDBG("%s: Regulator FS_IJPEG enable failed\n", __func__);
- regulator_put(fs_ijpeg);
- }
- CDBG("%s: exit %d\n", __func__, rc);
- return rc;
-}
-
int msm_camio_vpe_clk_disable(void)
{
int rc = 0;
diff --git a/drivers/media/video/msm/io/msm_io_vfe31.c b/drivers/media/video/msm/io/msm_io_vfe31.c
index 7f3b7ae..24bba59 100644
--- a/drivers/media/video/msm/io/msm_io_vfe31.c
+++ b/drivers/media/video/msm/io/msm_io_vfe31.c
@@ -108,8 +108,6 @@
static struct clk *camio_csi_clk;
static struct clk *camio_csi_pclk;
static struct clk *camio_csi_vfe_clk;
-static struct clk *camio_jpeg_clk;
-static struct clk *camio_jpeg_pclk;
static struct clk *camio_vpe_clk;
static struct regulator *fs_vpe;
static struct msm_camera_io_ext camio_ext;
@@ -117,7 +115,6 @@
static struct resource *camifpadio, *csiio;
void __iomem *camifpadbase, *csibase;
static uint32_t vpe_clk_rate;
-static uint32_t jpeg_clk_rate;
static struct regulator_bulk_data regs[] = {
{ .supply = "gp2", .min_uV = 2600000, .max_uV = 2600000 },
@@ -239,16 +236,6 @@
clk = clk_get(NULL, "csi_pclk");
break;
- case CAMIO_JPEG_CLK:
- camio_jpeg_clk =
- clk = clk_get(NULL, "jpeg_clk");
- jpeg_clk_rate = clk_round_rate(clk, 144000000);
- clk_set_rate(clk, jpeg_clk_rate);
- break;
- case CAMIO_JPEG_PCLK:
- camio_jpeg_pclk =
- clk = clk_get(NULL, "jpeg_pclk");
- break;
case CAMIO_VPE_CLK:
camio_vpe_clk =
clk = clk_get(NULL, "vpe_clk");
@@ -308,12 +295,6 @@
case CAMIO_CSI0_PCLK:
clk = camio_csi_pclk;
break;
- case CAMIO_JPEG_CLK:
- clk = camio_jpeg_clk;
- break;
- case CAMIO_JPEG_PCLK:
- clk = camio_jpeg_pclk;
- break;
case CAMIO_VPE_CLK:
clk = camio_vpe_clk;
break;
@@ -356,22 +337,6 @@
return IRQ_HANDLED;
}
-int msm_camio_jpeg_clk_disable(void)
-{
- msm_camio_clk_disable(CAMIO_JPEG_CLK);
- msm_camio_clk_disable(CAMIO_JPEG_PCLK);
- /* Need to add the code for remove PM QOS requirement */
- return 0;
-}
-
-
-int msm_camio_jpeg_clk_enable(void)
-{
- msm_camio_clk_enable(CAMIO_JPEG_CLK);
- msm_camio_clk_enable(CAMIO_JPEG_PCLK);
- return 0;
-}
-
int msm_camio_vpe_clk_disable(void)
{
msm_camio_clk_disable(CAMIO_VPE_CLK);
diff --git a/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c b/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c
index 451cb5a..a1270ea 100644
--- a/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c
+++ b/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c
@@ -33,12 +33,9 @@
#define BUFF_SIZE_128 128
-static struct clk *camio_jpeg_clk;
static struct clk *camio_vfe_clk;
-static struct clk *camio_jpeg_pclk;
static struct clk *camio_vpe_clk;
static struct clk *camio_vpe_pclk;
-static struct regulator *fs_ijpeg;
static struct regulator *fs_vpe;
static int vpe_clk_rate;
@@ -49,19 +46,6 @@
struct clk *clk = NULL;
switch (clktype) {
- case CAMIO_JPEG_CLK:
- camio_jpeg_clk =
- clk = clk_get(NULL, "ijpeg_clk");
- rc = clk_set_rate(clk, 228571000);
- if (rc < 0)
- rc = clk_set_rate(clk, 153600000);
- break;
-
- case CAMIO_JPEG_PCLK:
- camio_jpeg_pclk =
- clk = clk_get(NULL, "ijpeg_pclk");
- break;
-
case CAMIO_VPE_CLK:
camio_vpe_clk =
clk = clk_get(NULL, "vpe_clk");
@@ -93,14 +77,6 @@
struct clk *clk = NULL;
switch (clktype) {
- case CAMIO_JPEG_CLK:
- clk = camio_jpeg_clk;
- break;
-
- case CAMIO_JPEG_PCLK:
- clk = camio_jpeg_pclk;
- break;
-
case CAMIO_VPE_CLK:
clk = camio_vpe_clk;
break;
@@ -138,47 +114,6 @@
clk_set_rate(clk, rate);
}
-int msm_camio_jpeg_clk_disable(void)
-{
- int rc = 0;
- if (fs_ijpeg) {
- rc = regulator_disable(fs_ijpeg);
- if (rc < 0) {
- CDBG("%s: Regulator disable failed %d\n", __func__, rc);
- return rc;
- }
- regulator_put(fs_ijpeg);
- }
- rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
- CDBG("%s: exit %d\n", __func__, rc);
- return rc;
-}
-
-int msm_camio_jpeg_clk_enable(void)
-{
- int rc = 0;
- rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
- if (rc < 0)
- return rc;
- fs_ijpeg = regulator_get(NULL, "fs_ijpeg");
- if (IS_ERR(fs_ijpeg)) {
- CDBG("%s: Regulator FS_IJPEG get failed %ld\n", __func__,
- PTR_ERR(fs_ijpeg));
- fs_ijpeg = NULL;
- } else if (regulator_enable(fs_ijpeg)) {
- CDBG("%s: Regulator FS_IJPEG enable failed\n", __func__);
- regulator_put(fs_ijpeg);
- }
- CDBG("%s: exit %d\n", __func__, rc);
- return rc;
-}
-
int msm_camio_vpe_clk_disable(void)
{
int rc = 0;
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index da38acc..ff97fa3 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -66,6 +66,33 @@
spin_unlock_irqrestore(&queue->lock, flags);
}
+static void msm_drain_eventq(struct msm_device_queue *queue)
+{
+ unsigned long flags;
+ struct msm_queue_cmd *qcmd;
+ spin_lock_irqsave(&queue->lock, flags);
+ while (!list_empty(&queue->list)) {
+ qcmd = list_first_entry(&queue->list,
+ struct msm_queue_cmd, list_eventdata);
+ list_del_init(&qcmd->list_eventdata);
+ kfree(qcmd->command);
+ free_qcmd(qcmd);
+ }
+ spin_unlock_irqrestore(&queue->lock, flags);
+}
+
+static int32_t msm_find_free_queue(void)
+{
+ int i;
+ for (i = 0; i < NUM_SERVER_QUEUE; i++) {
+ struct msm_cam_server_queue *queue;
+ queue = &g_server_dev.server_queue[i];
+ if (!queue->queue_active)
+ return i;
+ }
+ return -EINVAL;
+}
+
/* callback function from all subdevices of a msm_cam_v4l2_device */
static void msm_cam_v4l2_subdev_notify(struct v4l2_subdev *sd,
unsigned int notification, void *arg)
@@ -86,29 +113,46 @@
}
}
-static int msm_ctrl_cmd_done(void __user *arg)
+static int msm_ctrl_cmd_done(void *arg)
{
void __user *uptr;
struct msm_queue_cmd *qcmd;
- struct msm_ctrl_cmd *command = &g_server_dev.ctrl;
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+ struct msm_ctrl_cmd *command =
+ kzalloc(sizeof(struct msm_ctrl_cmd), GFP_KERNEL);
+ if (!command) {
+ pr_err("%s Insufficient memory. return", __func__);
+ return -ENOMEM;
+ }
D("%s\n", __func__);
-
- if (copy_from_user(command, arg,
- sizeof(struct msm_ctrl_cmd)))
+ if (copy_from_user(command, (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_ctrl_cmd))) {
+ pr_err("%s: copy_from_user failed, size=%d\n",
+ __func__, sizeof(struct msm_ctrl_cmd));
return -EINVAL;
+ }
+ g_server_dev.server_queue[command->queue_idx].ctrl = command;
+ if (command->evt_id !=
+ g_server_dev.server_queue[command->queue_idx].evt_id) {
+ pr_err("Invalid event id from userspace\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&g_server_dev.server_queue_lock);
qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
atomic_set(&qcmd->on_heap, 1);
uptr = command->value;
qcmd->command = command;
if (command->length > 0) {
- command->value = g_server_dev.ctrl_data;
- if (command->length > sizeof(g_server_dev.ctrl_data)) {
+ command->value =
+ g_server_dev.server_queue[command->queue_idx].ctrl_data;
+ if (command->length > max_control_command_size) {
pr_err("%s: user data %d is too big (max %d)\n",
__func__, command->length,
- sizeof(g_server_dev.ctrl_data));
+ max_control_command_size);
free_qcmd(qcmd);
return -EINVAL;
}
@@ -117,8 +161,9 @@
return -EINVAL;
}
}
-
- msm_enqueue(&g_server_dev.ctrl_q, &qcmd->list_control);
+ msm_enqueue(&g_server_dev.server_queue
+ [command->queue_idx].ctrl_q, &qcmd->list_control);
+ mutex_unlock(&g_server_dev.server_queue_lock);
return 0;
}
@@ -129,8 +174,10 @@
int rc = 0;
void *value;
struct msm_queue_cmd *rcmd;
+ struct msm_queue_cmd *event_qcmd;
struct msm_ctrl_cmd *ctrlcmd;
- struct msm_device_queue *queue = &server_dev->ctrl_q;
+ struct msm_device_queue *queue =
+ &server_dev->server_queue[out->queue_idx].ctrl_q;
struct v4l2_event v4l2_evt;
struct msm_isp_event_ctrl *isp_event;
@@ -139,19 +186,38 @@
pr_err("%s Insufficient memory. return", __func__);
return -ENOMEM;
}
- D("%s\n", __func__);
+ event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+ if (!event_qcmd) {
+ pr_err("%s Insufficient memory. return", __func__);
+ return -ENOMEM;
+ }
+ D("%s\n", __func__);
+ mutex_lock(&server_dev->server_queue_lock);
+ if (++server_dev->server_evt_id == 0)
+ server_dev->server_evt_id++;
+
+ server_dev->server_queue[out->queue_idx].evt_id =
+ server_dev->server_evt_id;
v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_V4L2;
+ v4l2_evt.u.data[0] = out->queue_idx;
/* setup event object to transfer the command; */
- *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;
isp_event->resptype = MSM_CAM_RESP_V4L2;
isp_event->isp_data.ctrl = *out;
+ isp_event->isp_data.ctrl.evt_id = server_dev->server_evt_id;
+
+ atomic_set(&event_qcmd->on_heap, 1);
+ event_qcmd->command = isp_event;
+
+ msm_enqueue(&server_dev->server_queue[out->queue_idx].eventData_q,
+ &event_qcmd->list_eventdata);
+
/* now send command to config thread in userspace,
* and wait for results */
v4l2_event_queue(server_dev->server_command_queue.pvdev,
&v4l2_evt);
-
D("%s v4l2_event_queue: type = 0x%x\n", __func__, v4l2_evt.type);
+ mutex_unlock(&server_dev->server_queue_lock);
/* wait for config return status */
D("Waiting for config status\n");
@@ -163,9 +229,6 @@
if (!rc)
rc = -ETIMEDOUT;
if (rc < 0) {
- rcmd = msm_dequeue(queue, list_control);
- if (!rcmd)
- free_qcmd(rcmd);
kfree(isp_event);
pr_err("%s: wait_event error %d\n", __func__, rc);
return rc;
@@ -184,6 +247,9 @@
memcpy(out, ctrlcmd, sizeof(struct msm_ctrl_cmd));
out->value = value;
+ kfree(ctrlcmd);
+ server_dev->server_queue[out->queue_idx].ctrl = NULL;
+
free_qcmd(rcmd);
kfree(isp_event);
D("%s: rc %d\n", __func__, rc);
@@ -201,7 +267,7 @@
}
/*send open command to server*/
-static int msm_send_open_server(int vnode_id)
+static int msm_send_open_server(struct msm_cam_v4l2_device *pcam)
{
int rc = 0;
struct msm_ctrl_cmd ctrlcmd;
@@ -211,7 +277,8 @@
ctrlcmd.length = strnlen(g_server_dev.config_info.config_dev_name[0],
MAX_DEV_NAME_LEN)+1;
ctrlcmd.value = (char *)g_server_dev.config_info.config_dev_name[0];
- ctrlcmd.vnode_id = vnode_id;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
@@ -220,7 +287,7 @@
return rc;
}
-static int msm_send_close_server(int vnode_id)
+static int msm_send_close_server(struct msm_cam_v4l2_device *pcam)
{
int rc = 0;
struct msm_ctrl_cmd ctrlcmd;
@@ -230,7 +297,8 @@
ctrlcmd.length = strnlen(g_server_dev.config_info.config_dev_name[0],
MAX_DEV_NAME_LEN)+1;
ctrlcmd.value = (char *)g_server_dev.config_info.config_dev_name[0];
- ctrlcmd.vnode_id = vnode_id;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
@@ -275,6 +343,7 @@
ctrlcmd.value = (void *)&plane_info;
ctrlcmd.timeout_ms = 10000;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
@@ -339,6 +408,7 @@
ctrlcmd.value = (void *)&plane_info;
ctrlcmd.timeout_ms = 10000;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
/* send command to config thread in usersspace, and get return value */
rc = msm_server_control(&g_server_dev, &ctrlcmd);
@@ -367,6 +437,7 @@
ctrlcmd.value = NULL;
ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
@@ -388,6 +459,7 @@
ctrlcmd.value = NULL;
ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
@@ -446,6 +518,7 @@
ctrlcmd.value = (void *)ctrl_data;
ctrlcmd.timeout_ms = 1000;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
rc = msm_server_control(&g_server_dev, &ctrlcmd);
@@ -499,6 +572,7 @@
memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
ctrlcmd.timeout_ms = 1000;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
@@ -530,6 +604,7 @@
memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
ctrlcmd.timeout_ms = 1000;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
@@ -556,6 +631,7 @@
memcpy(ctrlcmd.value, queryctrl, ctrlcmd.length);
ctrlcmd.timeout_ms = 1000;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in userspace, and get return value */
@@ -666,6 +742,7 @@
ctrlcmd.value = (void *)crop;
ctrlcmd.timeout_ms = 1000;
ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
@@ -1429,6 +1506,7 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
int ion_client_created = 0;
#endif
+ int server_q_idx = 0;
/*struct msm_isp_ops *p_isp = 0;*/
/* get the video device */
struct msm_cam_v4l2_device *pcam = video_drvdata(f);
@@ -1449,6 +1527,11 @@
if (pcam->dev_inst[i] == NULL)
break;
}
+
+ server_q_idx = msm_find_free_queue();
+ if (server_q_idx < 0)
+ return server_q_idx;
+
/* if no instance is available, return error */
if (i == MSM_DEV_INST_MAX) {
mutex_unlock(&pcam->vid_lock);
@@ -1469,6 +1552,15 @@
pcam->vnode_id, pcam->use_count);
pcam->use_count++;
if (pcam->use_count == 1) {
+ struct msm_cam_server_queue *queue;
+ pcam->server_queue_idx = server_q_idx;
+ queue = &g_server_dev.server_queue[server_q_idx];
+ queue->ctrl = NULL;
+ queue->ctrl_data = kzalloc(sizeof(uint8_t) *
+ max_control_command_size, GFP_KERNEL);
+ msm_queue_init(&queue->ctrl_q, "control");
+ msm_queue_init(&queue->eventData_q, "eventdata");
+ queue->queue_active = 1;
rc = msm_cam_server_open_session(&g_server_dev, pcam);
if (rc < 0) {
@@ -1530,8 +1622,7 @@
if (pcam->use_count == 1) {
- msm_queue_init(&g_server_dev.ctrl_q, "control");
- rc = msm_send_open_server(pcam->vnode_id);
+ rc = msm_send_open_server(pcam);
if (rc < 0) {
mutex_unlock(&pcam->vid_lock);
pr_err("%s failed\n", __func__);
@@ -1630,6 +1721,7 @@
int rc = 0;
struct msm_cam_v4l2_device *pcam;
struct msm_cam_v4l2_dev_inst *pcam_inst;
+ struct msm_cam_server_queue *queue;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
pcam = pcam_inst->pcam;
@@ -1637,10 +1729,6 @@
pr_err("%s NULL pointer of camera device!\n", __func__);
return -EINVAL;
}
- if (!g_server_dev.use_count) {
- pr_err("%s: error, daemon not yet started.", __func__);
- return -EINVAL;
- }
mutex_lock(&pcam->vid_lock);
@@ -1679,7 +1767,7 @@
pr_err("msm_cam_server_close_session fails %d\n", rc);
if (g_server_dev.use_count > 0) {
- rc = msm_send_close_server(pcam->vnode_id);
+ rc = msm_send_close_server(pcam);
if (rc < 0)
pr_err("msm_send_close_server failed %d\n", rc);
}
@@ -1691,6 +1779,14 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
kref_put(&pcam->mctl.refcount, msm_release_ion_client);
#endif
+ queue = &g_server_dev.server_queue[pcam->server_queue_idx];
+ queue->queue_active = 0;
+ kfree(queue->ctrl);
+ queue->ctrl = NULL;
+ kfree(queue->ctrl_data);
+ queue->ctrl_data = NULL;
+ msm_queue_drain(&queue->ctrl_q, list_control);
+ msm_drain_eventq(&queue->eventData_q);
if (g_server_dev.use_count == 0)
mutex_unlock(&g_server_dev.server_lock);
}
@@ -1741,23 +1837,23 @@
return rc;
}
-static long msm_ioctl_server(struct file *fp, unsigned int cmd,
- unsigned long arg)
+static long msm_ioctl_server(struct file *file, void *fh,
+ bool valid_prio, int cmd, void *arg)
{
int rc = -EINVAL;
- struct v4l2_event ev;
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
struct msm_camera_info temp_cam_info;
struct msm_cam_config_dev_info temp_config_info;
struct msm_mctl_node_info temp_mctl_info;
- struct v4l2_event_subscription temp_sub;
int i;
D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
- case MSM_CAM_IOCTL_GET_CAMERA_INFO:
- if (copy_from_user(&temp_cam_info, (void __user *)arg,
- sizeof(struct msm_camera_info))) {
+ case MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO:
+ if (copy_from_user(&temp_cam_info,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_camera_info))) {
rc = -EINVAL;
return rc;
}
@@ -1781,18 +1877,20 @@
}
temp_cam_info.num_cameras =
g_server_dev.camera_info.num_cameras;
- if (copy_to_user((void __user *)arg,
- &temp_cam_info,
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+ &temp_cam_info,
sizeof(struct msm_camera_info))) {
- rc = -EINVAL;
- return rc;
+ rc = -EINVAL;
+ return rc;
}
rc = 0;
break;
- case MSM_CAM_IOCTL_GET_CONFIG_INFO:
- if (copy_from_user(&temp_config_info, (void __user *)arg,
- sizeof(struct msm_cam_config_dev_info))) {
+ case MSM_CAM_V4L2_IOCTL_GET_CONFIG_INFO:
+ if (copy_from_user(&temp_config_info,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_cam_config_dev_info))) {
+
rc = -EINVAL;
return rc;
}
@@ -1808,7 +1906,7 @@
}
temp_config_info.num_config_nodes =
g_server_dev.config_info.num_config_nodes;
- if (copy_to_user((void __user *)arg,
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
&temp_config_info,
sizeof(struct msm_cam_config_dev_info))) {
rc = -EINVAL;
@@ -1816,13 +1914,13 @@
}
rc = 0;
break;
- case MSM_CAM_IOCTL_GET_MCTL_INFO:
- if (copy_from_user(&temp_mctl_info, (void __user *)arg,
- sizeof(struct msm_mctl_node_info))) {
+ case MSM_CAM_V4L2_IOCTL_GET_MCTL_INFO:
+ if (copy_from_user(&temp_mctl_info,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_mctl_node_info))) {
rc = -EINVAL;
return rc;
}
-
for (i = 0; i < g_server_dev.mctl_node_info.num_mctl_nodes;
i++) {
if (copy_to_user((void __user *)
@@ -1836,7 +1934,7 @@
}
temp_mctl_info.num_mctl_nodes =
g_server_dev.mctl_node_info.num_mctl_nodes;
- if (copy_to_user((void __user *)arg,
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
&temp_mctl_info,
sizeof(struct msm_mctl_node_info))) {
rc = -EINVAL;
@@ -1845,122 +1943,79 @@
rc = 0;
break;
- case VIDIOC_SUBSCRIBE_EVENT:
- if (copy_from_user(&temp_sub, (void __user *)arg,
- sizeof(struct v4l2_event_subscription))) {
+ case MSM_CAM_V4L2_IOCTL_CTRL_CMD_DONE:
+ D("%s: MSM_CAM_IOCTL_CTRL_CMD_DONE\n", __func__);
+ rc = msm_ctrl_cmd_done(arg);
+ break;
+
+ case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: {
+ struct msm_queue_cmd *event_cmd;
+ struct msm_isp_event_ctrl u_isp_event;
+ struct msm_isp_event_ctrl *k_isp_event;
+ struct msm_device_queue *queue;
+ void __user *u_ctrl_value = NULL;
+ if (copy_from_user(&u_isp_event,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_isp_event_ctrl))) {
rc = -EINVAL;
return rc;
}
- rc = msm_server_v4l2_subscribe_event
- (&g_server_dev.server_command_queue.eventHandle,
- &temp_sub);
- if (rc < 0)
+ queue = &g_server_dev.server_queue
+ [u_isp_event.isp_data.ctrl.queue_idx].eventData_q;
+ event_cmd = msm_dequeue(queue, list_eventdata);
+ if (!event_cmd) {
+ pr_err("%s: No event payload\n", __func__);
+ rc = -EINVAL;
return rc;
-
- break;
-
- case VIDIOC_DQEVENT: {
- void __user *u_ctrl_value = NULL, *user_ptr = NULL;
- struct msm_isp_event_ctrl u_isp_event;
- struct msm_isp_event_ctrl *k_isp_event;
-
- /* First, copy the event structure from userspace */
- D("%s: VIDIOC_DQEVENT\n", __func__);
- if (copy_from_user(&ev, (void __user *)arg,
- sizeof(struct v4l2_event))) {
- break;
}
- /* Next, get the pointer to event_ctrl structure
- * embedded inside the v4l2_event.u.data array. */
- user_ptr = (void __user *)(*((uint32_t *)ev.u.data));
-
- /* Next, copy the userspace event ctrl structure */
- if (copy_from_user((void *)&u_isp_event, user_ptr,
- sizeof(struct msm_isp_event_ctrl))) {
- break;
- }
+ k_isp_event = (struct msm_isp_event_ctrl *)
+ event_cmd->command;
+ free_qcmd(event_cmd);
/* Save the pointer of the user allocated command buffer*/
u_ctrl_value = u_isp_event.isp_data.ctrl.value;
- /* Dequeue the event queued into the v4l2 queue*/
- rc = v4l2_event_dequeue(
- &g_server_dev.server_command_queue.eventHandle,
- &ev, fp->f_flags & O_NONBLOCK);
- if (rc < 0) {
- pr_err("no pending events?");
- break;
- }
-
- /* Use k_isp_event to point to the event_ctrl structure
- * embedded inside v4l2_event.u.data */
- k_isp_event = (struct msm_isp_event_ctrl *)
- (*((uint32_t *)ev.u.data));
- if (!k_isp_event) {
- pr_err("%s Invalid event ctrl structure. ", __func__);
- break;
- }
-
/* Copy the event structure into user struct*/
u_isp_event = *k_isp_event;
/* Restore the saved pointer of the user
* allocated command buffer. */
u_isp_event.isp_data.ctrl.value = u_ctrl_value;
- if (ev.type == V4L2_EVENT_PRIVATE_START+MSM_CAM_RESP_V4L2) {
- /* Copy the ctrl cmd, if present*/
- if (k_isp_event->isp_data.ctrl.length > 0) {
- void *k_ctrl_value =
- k_isp_event->isp_data.ctrl.value;
- if (copy_to_user(u_ctrl_value, k_ctrl_value,
- k_isp_event->isp_data.ctrl.length)) {
- rc = -EINVAL;
- break;
- }
- }
- /* Copy the event ctrl structure back into
- * user's structure. */
- if (copy_to_user(user_ptr, (void *)&u_isp_event,
- sizeof(struct msm_isp_event_ctrl))) {
+
+ /* Copy the ctrl cmd, if present*/
+ if (k_isp_event->isp_data.ctrl.length > 0) {
+ void *k_ctrl_value =
+ k_isp_event->isp_data.ctrl.value;
+ if (copy_to_user(u_ctrl_value, k_ctrl_value,
+ k_isp_event->isp_data.ctrl.length)) {
rc = -EINVAL;
break;
}
}
-
- /* Copy the v4l2_event structure back to the user*/
- if (copy_to_user((void __user *)arg, &ev,
- sizeof(struct v4l2_event))) {
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+ &u_isp_event,
+ sizeof(struct msm_isp_event_ctrl))) {
rc = -EINVAL;
- break;
+ return rc;
}
- }
+ rc = 0;
break;
-
- case MSM_CAM_IOCTL_CTRL_CMD_DONE:
- D("%s: MSM_CAM_IOCTL_CTRL_CMD_DONE\n", __func__);
- rc = msm_ctrl_cmd_done((void __user *)arg);
- break;
-
+ }
default:
break;
}
return rc;
}
-static int msm_open_server(struct inode *inode, struct file *fp)
+static int msm_open_server(struct file *fp)
{
- int rc;
+ int rc = 0;
D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
mutex_lock(&g_server_dev.server_lock);
- rc = nonseekable_open(inode, fp);
- if (rc < 0) {
- pr_err("%s: nonseekable_open error %d\n", __func__, rc);
- mutex_unlock(&g_server_dev.server_lock);
- return rc;
- }
g_server_dev.use_count++;
if (g_server_dev.use_count == 1)
- msm_queue_init(&g_server_dev.ctrl_q, "control");
+ fp->private_data =
+ &g_server_dev.server_command_queue.eventHandle;
mutex_unlock(&g_server_dev.server_lock);
return rc;
}
@@ -1982,8 +2037,9 @@
return rc;
}
-static int msm_close_server(struct inode *inode, struct file *fp)
+static int msm_close_server(struct file *fp)
{
+ D("%s\n", __func__);
mutex_lock(&g_server_dev.server_lock);
if (g_server_dev.use_count > 0)
g_server_dev.use_count--;
@@ -1999,7 +2055,6 @@
v4l2_event_queue(
g_server_dev.pcam_active->pvdev, &v4l2_ev);
}
- msm_queue_drain(&g_server_dev.ctrl_q, list_control);
}
return 0;
}
@@ -2269,14 +2324,19 @@
* which will create a config device (/dev/config0/ and plug in
* ISP's operation "v4l2_ioctl_ops*"
*/
-static const struct file_operations msm_fops_server = {
+static const struct v4l2_file_operations msm_fops_server = {
.owner = THIS_MODULE,
.open = msm_open_server,
.poll = msm_poll_server,
- .unlocked_ioctl = msm_ioctl_server,
+ .unlocked_ioctl = video_ioctl2,
.release = msm_close_server,
};
+static const struct v4l2_ioctl_ops msm_ioctl_ops_server = {
+ .vidioc_subscribe_event = msm_server_v4l2_subscribe_event,
+ .vidioc_default = msm_ioctl_server,
+};
+
static const struct file_operations msm_fops_config = {
.owner = THIS_MODULE,
.open = msm_open_config,
@@ -2379,53 +2439,70 @@
}
-static int msm_setup_server_dev(int node, char *device_name)
+static int msm_setup_server_dev(struct platform_device *pdev)
{
- int rc = -ENODEV;
- struct device *device_server;
- int dev_num = node;
- dev_t devno;
+ int rc = -ENODEV, i;
D("%s\n", __func__);
+ g_server_dev.server_pdev = pdev;
+ g_server_dev.v4l2_dev.dev = &pdev->dev;
- devno = MKDEV(MAJOR(msm_devno), dev_num);
- device_server = device_create(msm_class, NULL,
- devno, NULL, "%s", device_name);
+ rc = v4l2_device_register(g_server_dev.v4l2_dev.dev,
+ &g_server_dev.v4l2_dev);
+ if (rc < 0)
+ return -EINVAL;
- if (IS_ERR(device_server)) {
- rc = PTR_ERR(device_server);
- pr_err("%s: error creating device: %d\n", __func__, rc);
+ g_server_dev.video_dev = video_device_alloc();
+ if (g_server_dev.video_dev == NULL) {
+ pr_err("%s: video_device_alloc failed\n", __func__);
return rc;
}
- cdev_init(&g_server_dev.server_cdev, &msm_fops_server);
- g_server_dev.server_cdev.owner = THIS_MODULE;
+ strlcpy(g_server_dev.video_dev->name, pdev->name,
+ sizeof(g_server_dev.video_dev->name));
- rc = cdev_add(&g_server_dev.server_cdev, devno, 1);
- if (rc < 0) {
- pr_err("%s: error adding cdev: %d\n", __func__, rc);
- device_destroy(msm_class, devno);
- return rc;
- }
+ g_server_dev.video_dev->v4l2_dev = &g_server_dev.v4l2_dev;
+ g_server_dev.video_dev->fops = &msm_fops_server;
+ g_server_dev.video_dev->ioctl_ops = &msm_ioctl_ops_server;
+ g_server_dev.video_dev->release = video_device_release;
+ g_server_dev.video_dev->minor = 100;
+ g_server_dev.video_dev->vfl_type = 1;
+
+ video_set_drvdata(g_server_dev.video_dev, &g_server_dev);
+
+ strlcpy(g_server_dev.media_dev.model, "qcamera",
+ sizeof(g_server_dev.media_dev.model));
+ g_server_dev.media_dev.dev = &pdev->dev;
+ rc = media_device_register(&g_server_dev.media_dev);
+ g_server_dev.v4l2_dev.mdev = &g_server_dev.media_dev;
+
+ rc = video_register_device(g_server_dev.video_dev,
+ VFL_TYPE_GRABBER, 100);
mutex_init(&g_server_dev.server_lock);
+ mutex_init(&g_server_dev.server_queue_lock);
g_server_dev.pcam_active = NULL;
g_server_dev.camera_info.num_cameras = 0;
atomic_set(&g_server_dev.number_pcam_active, 0);
+ g_server_dev.server_evt_id = 0;
/*initialize fake video device and event queue*/
- g_server_dev.server_command_queue.pvdev = video_device_alloc();
- if (g_server_dev.server_command_queue.pvdev == NULL) {
- pr_err("%s: video_device_alloc failed\n", __func__);
- return -ENOMEM;
- }
+ g_server_dev.server_command_queue.pvdev = g_server_dev.video_dev;
rc = msm_setup_v4l2_event_queue(
&g_server_dev.server_command_queue.eventHandle,
g_server_dev.server_command_queue.pvdev);
+
if (rc < 0)
pr_err("%s failed to initialize event queue\n", __func__);
+ for (i = 0; i < NUM_SERVER_QUEUE; i++) {
+ struct msm_cam_server_queue *queue;
+ queue = &g_server_dev.server_queue[i];
+ queue->queue_active = 0;
+ msm_queue_init(&queue->ctrl_q, "control");
+ msm_queue_init(&queue->eventData_q, "eventdata");
+ }
return rc;
}
@@ -2717,7 +2794,7 @@
}
EXPORT_SYMBOL(msm_sensor_register);
-static int __init msm_camera_init(void)
+static int __devinit msm_camera_probe(struct platform_device *pdev)
{
int rc = 0, i;
/*for now just create a config 0 node
@@ -2749,7 +2826,7 @@
}
D("creating server and config nodes\n");
- rc = msm_setup_server_dev(0, "video_msm");
+ rc = msm_setup_server_dev(pdev);
if (rc < 0) {
pr_err("%s: failed to create server dev: %d\n", __func__,
rc);
@@ -2769,10 +2846,31 @@
return rc;
}
-static void __exit msm_camera_exit(void)
+static int __exit msm_camera_exit(struct platform_device *pdev)
{
msm_isp_unregister(&g_server_dev);
+ return 0;
+}
+
+
+static struct platform_driver msm_cam_server_driver = {
+ .probe = msm_camera_probe,
+ .remove = msm_camera_exit,
+ .driver = {
+ .name = "msm_cam_server",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_camera_init(void)
+{
+ return platform_driver_register(&msm_cam_server_driver);
+}
+
+static void __exit msm_cam_server_exit(void)
+{
+ platform_driver_unregister(&msm_cam_server_driver);
}
module_init(msm_camera_init);
-module_exit(msm_camera_exit);
+module_exit(msm_cam_server_exit);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index dd65c01..c4373a7 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -356,6 +356,7 @@
* control thread. It is accessed only from a process context.
* TO BE REMOVED
*/
+ uint32_t server_queue_idx;
struct msm_device_queue ctrl_q;
struct mutex lock;
@@ -387,11 +388,27 @@
struct msm_mem_map_info mem_map;
};
+#define NUM_SERVER_QUEUE 5
+
+struct msm_cam_server_queue {
+ uint32_t queue_active;
+ struct msm_device_queue ctrl_q;
+ struct msm_device_queue eventData_q;
+ struct msm_ctrl_cmd *ctrl;
+ uint8_t *ctrl_data;
+ uint32_t evt_id;
+};
+
/* abstract camera server device for all sensor successfully probed*/
struct msm_cam_server_dev {
/* config node device*/
- struct cdev server_cdev;
+ struct platform_device *server_pdev;
+ /* server node v4l2 device */
+ struct v4l2_device v4l2_dev;
+ struct video_device *video_dev;
+ struct media_device media_dev;
+
/* info of sensors successfully probed*/
struct msm_camera_info camera_info;
/* info of configs successfully created*/
@@ -401,18 +418,20 @@
/* number of camera devices opened*/
atomic_t number_pcam_active;
struct v4l2_queue_util server_command_queue;
+
/* This queue used by the config thread to send responses back to the
* control thread. It is accessed only from a process context.
*/
- struct msm_device_queue ctrl_q;
- uint8_t ctrl_data[max_control_command_size];
- struct msm_ctrl_cmd ctrl;
+ struct msm_cam_server_queue server_queue[NUM_SERVER_QUEUE];
+ uint32_t server_evt_id;
+
int use_count;
/* all the registered ISP subdevice*/
struct msm_isp_ops *isp_subdev[MSM_MAX_CAMERA_CONFIGS];
/* info of MCTL nodes successfully probed*/
struct msm_mctl_node_info mctl_node_info;
struct mutex server_lock;
+ struct mutex server_queue_lock;
};
/* camera server related functions */
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 3e2ddee..59e37dd 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -296,6 +296,7 @@
isp_event->isp_data.isp_msg.msg_id = isp_msg->msg_id;
isp_event->isp_data.isp_msg.frame_id = isp_msg->sof_count;
+ getnstimeofday(&(isp_event->isp_data.isp_msg.timestamp));
break;
}
case NOTIFY_VFE_MSG_OUT: {
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index da9e071..d60f4b7 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -367,6 +367,8 @@
static void vfe31_stop(void)
{
+
+ uint8_t axiBusyFlag = true;
unsigned long flags;
atomic_set(&vfe31_ctrl->vstate, 0);
@@ -377,12 +379,6 @@
spin_unlock_irqrestore(&vfe31_ctrl->stop_flag_lock, flags);
/* disable all interrupts. */
- /* in either continuous or snapshot mode, stop command can be issued
- * at any time. stop camif immediately. */
- msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
- vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
- /* disable all interrupts. */
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
vfe31_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
@@ -398,16 +394,30 @@
msm_camera_io_w_mb(1,
vfe31_ctrl->vfebase + VFE_IRQ_CMD);
+ /* in either continuous or snapshot mode, stop command can be issued
+ * at any time. stop camif immediately. */
+ msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
+ vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
+
+ /* axi halt command. */
+ msm_camera_io_w(AXI_HALT,
+ vfe31_ctrl->vfebase + VFE_AXI_CMD);
+ wmb();
+ while (axiBusyFlag) {
+ if (msm_camera_io_r(vfe31_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
+ axiBusyFlag = false;
+ }
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_camera_io_w_mb(AXI_HALT_CLEAR,
+ vfe31_ctrl->vfebase + VFE_AXI_CMD);
+
/* now enable only halt_irq & reset_irq */
msm_camera_io_w(0xf0000000, /* this is for async timer. */
vfe31_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
vfe31_ctrl->vfebase + VFE_IRQ_MASK_1);
- /* then apply axi halt command. */
- msm_camera_io_w_mb(AXI_HALT,
- vfe31_ctrl->vfebase + VFE_AXI_CMD);
-
msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
vfe31_ctrl->vfebase + VFE_GLOBAL_RESET);
}
@@ -2362,8 +2372,7 @@
/* later we need to add check for live snapshot mode. */
if (vfe31_ctrl->frame_skip_pattern & (0x1 <<
(vfe31_ctrl->snapshot_frame_cnt %
- vfe31_ctrl->frame_skip_cnt))) {
- vfe31_ctrl->vfe_capture_count--;
+ vfe31_ctrl->frame_skip_cnt))) {
/* if last frame to be captured: */
if (vfe31_ctrl->vfe_capture_count == 0) {
/* stop the bus output:write master enable = 0*/
@@ -2393,7 +2402,6 @@
vfe31_ctrl->frame_skip_pattern = 0xffffffff;
} /*if snapshot count is 0*/
} /*if frame is not being dropped*/
- vfe31_ctrl->snapshot_frame_cnt++;
/* then do reg_update. */
msm_camera_io_w(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
} /* if snapshot mode. */
@@ -2493,6 +2501,17 @@
else
vfe31_ctrl->sync_timer_repeat_count--;
}
+ if ((vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
+ (vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) ||
+ (vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) ||
+ (vfe31_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) {
+ if (vfe31_ctrl->frame_skip_pattern & (0x1 <<
+ (vfe31_ctrl->snapshot_frame_cnt %
+ vfe31_ctrl->frame_skip_cnt))) {
+ vfe31_ctrl->vfe_capture_count--;
+ }
+ vfe31_ctrl->snapshot_frame_cnt++;
+ }
}
static void vfe31_process_error_irq(uint32_t errStatus)
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 2f0b6c9..b8344fb 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -4022,6 +4022,7 @@
vfe32_ctrl->fs_vfe = NULL;
vfe_fs_failed:
iounmap(vfe32_ctrl->vfebase);
+ vfe32_ctrl->vfebase = NULL;
vfe_remap_failed:
disable_irq(vfe32_ctrl->vfeirq->start);
return rc;
@@ -4041,6 +4042,7 @@
vfe32_ctrl->fs_vfe = NULL;
}
iounmap(vfe32_ctrl->vfebase);
+ vfe32_ctrl->vfebase = NULL;
if (atomic_read(&irq_cnt))
pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 8567fb3..cd503f9 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -86,6 +86,15 @@
{
uint32_t vpe_version;
uint32_t rc = 0;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&vpe_ctrl->lock, flags);
+ if (vpe_ctrl->state == VPE_STATE_IDLE) {
+ CDBG("%s: VPE already disabled.", __func__);
+ spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
+ return rc;
+ }
+ spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
vpe_reset_state_variables();
vpe_version = msm_camera_io_r(
@@ -673,6 +682,7 @@
/* from this part it is error handling. */
vpe_unmap_mem_region:
iounmap(vpe_ctrl->vpebase);
+ vpe_ctrl->vpebase = NULL;
return rc; /* this rc should have error code. */
}
@@ -684,7 +694,10 @@
return;
}
+ vpe_reset();
+ vpe_disable();
iounmap(vpe_ctrl->vpebase);
+ vpe_ctrl->vpebase = NULL;
atomic_set(&vpe_init_done, 0);
}
EXPORT_SYMBOL(msm_vpe_subdev_release);
diff --git a/drivers/media/video/msm/msm_vpe1.c b/drivers/media/video/msm/msm_vpe1.c
index 96988a9..984aea5 100644
--- a/drivers/media/video/msm/msm_vpe1.c
+++ b/drivers/media/video/msm/msm_vpe1.c
@@ -1422,7 +1422,7 @@
return rc; /* this rc should be zero.*/
iounmap(vpe_device->vpebase); /* this path should never occur */
-
+ vpe_device->vpebase = NULL;
/* from this part it is error handling. */
vpe_release_mem_region:
release_mem_region(vpemem->start, (vpemem->end - vpemem->start) + 1);
@@ -1436,6 +1436,7 @@
vpemem = vpe_device->vpemem;
iounmap(vpe_device->vpebase);
+ vpe_device->vpebase = NULL;
release_mem_region(vpemem->start,
(vpemem->end - vpemem->start) + 1);
return 0;
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
index 7f0fbc3..e6e2d52 100644
--- a/drivers/media/video/msm/sensors/mt9e013_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -271,8 +271,6 @@
ARRAY_SIZE(mt9e013_prev_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
{&mt9e013_hfr60_settings[0],
ARRAY_SIZE(mt9e013_hfr60_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
- {&mt9e013_hfr60_settings[0],
- ARRAY_SIZE(mt9e013_hfr60_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
{&mt9e013_hfr90_settings[0],
ARRAY_SIZE(mt9e013_hfr90_settings), 0, MSM_CAMERA_I2C_WORD_DATA},
{&mt9e013_hfr120_settings[0],
@@ -312,15 +310,6 @@
.y_output = 0x212,
.line_length_pclk = 0x970,
.frame_length_lines = 0x2A1,
- .vt_pixel_clk = 98400000,
- .op_pixel_clk = 98400000,
- .binning_factor = 1,
- },
- {
- .x_output = 0x340,
- .y_output = 0x212,
- .line_length_pclk = 0x970,
- .frame_length_lines = 0x2A1,
.vt_pixel_clk = 146400000,
.op_pixel_clk = 146400000,
.binning_factor = 1,
@@ -350,7 +339,6 @@
&mt9e013_csi_params,
&mt9e013_csi_params,
&mt9e013_csi_params,
- &mt9e013_csi_params,
};
static struct msm_sensor_output_reg_addr_t mt9e013_reg_addr = {
diff --git a/drivers/media/video/msm/sn12m0pz.c b/drivers/media/video/msm/sn12m0pz.c
index affa581..2eabb3c 100644
--- a/drivers/media/video/msm/sn12m0pz.c
+++ b/drivers/media/video/msm/sn12m0pz.c
@@ -1579,7 +1579,7 @@
CDBG("init_done");
return rc;
}
-static int __init sn12m0pz_init_client(struct i2c_client *client)
+static int __devinit sn12m0pz_init_client(struct i2c_client *client)
{
/* Initialize the MSM_CAMI2C Chip */
init_waitqueue_head(&sn12m0pz_wait_queue);
@@ -1591,7 +1591,7 @@
{ }
};
-static int sn12m0pz_i2c_probe(struct i2c_client *client,
+static int __devinit sn12m0pz_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int rc = 0;
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 483eab0..95cdc59 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -33,6 +33,7 @@
struct mem_region *mregion);
u32 width;
u32 height;
+ int secure;
};
struct venc {
@@ -72,7 +73,7 @@
u32 i;
u32 found = false;
- for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+ for (i = 0; i < VID_ENC_MAX_ENCODER_CLIENTS; i++) {
if (!venc_p.venc_clients[i].venc_client.vcd_handle) {
found = true;
break;
@@ -266,6 +267,7 @@
struct venc_inst *inst;
struct video_client_ctx *client_ctx;
struct venc_msg_ops *vmops = arg;
+ int flags = 0;
mutex_lock(&venc_p.lock);
client_index = venc_get_empty_client_index();
if (client_index < 0) {
@@ -284,7 +286,11 @@
inst->op_buffer_done = vmops->op_buffer_done;
inst->ip_buffer_done = vmops->ip_buffer_done;
inst->cbdata = vmops->cbdata;
-
+ inst->secure = vmops->secure;
+ if (vmops->secure) {
+ WFD_MSG_ERR("OPENING SECURE SESSION\n");
+ flags |= VCD_CP_SESSION;
+ }
if (vcd_get_ion_status()) {
client_ctx->user_ion_client = vcd_get_ion_client();
if (!client_ctx->user_ion_client) {
@@ -294,9 +300,10 @@
}
rc = vcd_open(venc_p.device_handle, false, venc_cb,
- inst);
+ inst, flags);
if (rc) {
WFD_MSG_ERR("vcd_open failed, rc = %d\n", rc);
+ rc = -ENODEV;
goto no_free_client;
}
wait_for_completion(&client_ctx->event);
@@ -1522,6 +1529,87 @@
return rc;
}
+static long venc_set_entropy_mode(struct video_client_ctx *client_ctx,
+ __s32 value)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_entropy_control entropy_control;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto set_entropy_mode_fail;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
+ vcd_property_hdr.sz = sizeof(entropy_control);
+
+ switch (value) {
+ case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
+ entropy_control.entropy_sel = VCD_ENTROPY_SEL_CAVLC;
+ break;
+ case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
+ entropy_control.entropy_sel = VCD_ENTROPY_SEL_CABAC;
+ entropy_control.cabac_model = VCD_CABAC_MODEL_NUMBER_0;
+ break;
+ default:
+ WFD_MSG_ERR("Entropy type %d not supported\n", value);
+ rc = -ENOTSUPP;
+ goto set_entropy_mode_fail;
+ }
+ rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &entropy_control);
+ if (rc) {
+ WFD_MSG_ERR("Failed to set entropy mode\n");
+ goto set_entropy_mode_fail;
+ }
+
+set_entropy_mode_fail:
+ return rc;
+}
+
+static long venc_get_entropy_mode(struct video_client_ctx *client_ctx,
+ __s32 *value)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_entropy_control entropy_control;
+ int rc = 0;
+
+ if (!client_ctx || !value) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto get_entropy_mode_fail;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
+ vcd_property_hdr.sz = sizeof(entropy_control);
+
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &entropy_control);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to get entropy mode\n");
+ goto get_entropy_mode_fail;
+ }
+
+ switch (entropy_control.entropy_sel) {
+ case VCD_ENTROPY_SEL_CAVLC:
+ *value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
+ break;
+ case VCD_ENTROPY_SEL_CABAC:
+ *value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
+ break;
+ default:
+ WFD_MSG_ERR("Entropy type %d not known\n",
+ entropy_control.entropy_sel);
+ rc = -EINVAL;
+ goto get_entropy_mode_fail;
+ }
+get_entropy_mode_fail:
+ return rc;
+}
+
static long venc_set_input_buffer(struct v4l2_subdev *sd, void *arg)
{
struct mem_region *mregion = arg;
@@ -1684,6 +1772,7 @@
struct vcd_property_enc_recon_buffer *ctrl = NULL;
unsigned long phy_addr;
int i = 0;
+ int flags = 0;
u32 len;
control.width = inst->width;
control.height = inst->height;
@@ -1696,6 +1785,8 @@
WFD_MSG_ERR("Failed to get recon buf size\n");
goto err;
}
+ flags = ION_HEAP(ION_CP_MM_HEAP_ID);
+ flags |= inst->secure ? ION_SECURE : ION_HEAP(ION_IOMMU_HEAP_ID);
if (vcd_get_ion_status()) {
for (i = 0; i < 4; ++i) {
@@ -1706,8 +1797,7 @@
ctrl->user_virtual_addr = (void *)i;
client_ctx->recon_buffer_ion_handle[i]
= ion_alloc(client_ctx->user_ion_client,
- control.size, SZ_8K, ION_HEAP(ION_IOMMU_HEAP_ID) |
- ION_HEAP(ION_CP_MM_HEAP_ID));
+ control.size, SZ_8K, flags);
ctrl->kernel_virtual_addr = ion_map_kernel(
client_ctx->user_ion_client,
@@ -1895,6 +1985,9 @@
case V4L2_CID_MPEG_QCOM_SET_PERF_LEVEL:
rc = venc_set_max_perf_level(client_ctx, ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+ rc = venc_set_entropy_mode(client_ctx, ctrl->value);
+ break;
default:
WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
@@ -1954,6 +2047,9 @@
rc = venc_get_multislicing_mode(client_ctx, ctrl->id,
&ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+ rc = venc_get_entropy_mode(client_ctx, &ctrl->value);
+ break;
default:
WFD_MSG_ERR("Get property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
diff --git a/drivers/media/video/msm/wfd/enc-subdev.h b/drivers/media/video/msm/wfd/enc-subdev.h
index 69e7521..cafc9d5 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.h
+++ b/drivers/media/video/msm/wfd/enc-subdev.h
@@ -44,6 +44,7 @@
struct venc_msg_ops {
void *cookie;
void *cbdata;
+ int secure;
void (*op_buffer_done)(void *cookie, u32 status,
struct vb2_buffer *buf);
void (*ip_buffer_done)(void *cookie, u32 status,
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.c b/drivers/media/video/msm/wfd/mdp-subdev.c
index e519a4d..a6d244f 100644
--- a/drivers/media/video/msm/wfd/mdp-subdev.c
+++ b/drivers/media/video/msm/wfd/mdp-subdev.c
@@ -45,13 +45,6 @@
goto exit;
}
- /*Tell HDMI daemon to open fb1*/
- rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ADD);
- if (rc) {
- WFD_MSG_ERR("Failed add to kobj");
- goto exit;
- }
-
msm_fb_writeback_init(fbi);
inst->mdp = fbi;
*cookie = inst;
@@ -78,9 +71,6 @@
rc = -ENODEV;
goto exit;
}
- rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ONLINE);
- if (rc)
- WFD_MSG_ERR("Failed to send ONLINE event\n");
}
exit:
return rc;
@@ -89,19 +79,12 @@
{
struct mdp_instance *inst = arg;
int rc = 0;
- struct fb_info *fbi = NULL;
if (inst) {
rc = msm_fb_writeback_stop(inst->mdp);
if (rc) {
WFD_MSG_ERR("Failed to stop writeback mode\n");
return rc;
}
- fbi = (struct fb_info *)inst->mdp;
- rc = kobject_uevent(&fbi->dev->kobj, KOBJ_OFFLINE);
- if (rc) {
- WFD_MSG_ERR("Failed to send offline event\n");
- return -EIO;
- }
}
return 0;
}
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 2c2c551..7ab5d17 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -43,6 +43,7 @@
#define VENC_INPUT_BUFFERS 4
struct wfd_device {
+ struct mutex dev_lock;
struct platform_device *pdev;
struct v4l2_device v4l2_dev;
struct video_device *pvdev;
@@ -51,6 +52,7 @@
struct v4l2_subdev vsg_sdev;
struct ion_client *ion_client;
bool secure_device;
+ bool in_use;
};
struct mem_info {
@@ -152,7 +154,7 @@
int rc;
alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
- alloc_regions |= secure ? 0 :
+ alloc_regions |= secure ? ION_SECURE :
ION_HEAP(ION_IOMMU_HEAP_ID);
handle = ion_alloc(client,
mregion->size, SZ_4K, alloc_regions);
@@ -1243,13 +1245,25 @@
static int wfd_open(struct file *filp)
{
int rc = 0;
- struct wfd_inst *inst;
- struct wfd_device *wfd_dev;
+ struct wfd_inst *inst = NULL;
+ struct wfd_device *wfd_dev = NULL;
struct venc_msg_ops enc_mops;
struct vsg_msg_ops vsg_mops;
WFD_MSG_DBG("wfd_open: E\n");
wfd_dev = video_drvdata(filp);
+
+ mutex_lock(&wfd_dev->dev_lock);
+ if (wfd_dev->in_use) {
+ WFD_MSG_ERR("Device already in use.\n");
+ rc = -EBUSY;
+ mutex_unlock(&wfd_dev->dev_lock);
+ goto err_dev_busy;
+ }
+
+ wfd_dev->in_use = true;
+ mutex_unlock(&wfd_dev->dev_lock);
+
inst = kzalloc(sizeof(struct wfd_inst), GFP_KERNEL);
if (!inst || !wfd_dev) {
WFD_MSG_ERR("Could not allocate memory for "
@@ -1279,6 +1293,7 @@
enc_mops.op_buffer_done = venc_op_buffer_done;
enc_mops.ip_buffer_done = venc_ip_buffer_done;
enc_mops.cbdata = filp;
+ enc_mops.secure = wfd_dev->secure_device;
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, OPEN,
(void *)&enc_mops);
if (rc || !enc_mops.cookie) {
@@ -1309,6 +1324,7 @@
MDP_CLOSE, (void *)inst->mdp_inst);
err_mdp_open:
kfree(inst);
+err_dev_busy:
return rc;
}
@@ -1340,10 +1356,14 @@
if (rc)
WFD_MSG_ERR("Failed to CLOSE vsg subdev: %d\n", rc);
+ wfd_stats_deinit(&inst->stats);
kfree(inst);
}
- wfd_stats_deinit(&inst->stats);
+ mutex_lock(&wfd_dev->dev_lock);
+ wfd_dev->in_use = false;
+ mutex_unlock(&wfd_dev->dev_lock);
+
WFD_MSG_DBG("wfd_close: X\n");
return 0;
}
@@ -1486,7 +1506,9 @@
}
/* Other device specific stuff */
+ mutex_init(&wfd_dev[c].dev_lock);
wfd_dev[c].ion_client = ion_client;
+ wfd_dev[c].in_use = false;
switch (WFD_DEVICE_NUMBER_BASE + c) {
case WFD_DEVICE_SECURE:
wfd_dev[c].secure_device = true;
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 6443250..670d0f8 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -154,7 +154,10 @@
unsigned int *nplanes, unsigned long sizes[],
void *alloc_ctxs[])
{
- *nbuffers = 3;
+ *nbuffers += 2;
+ if (*nbuffers > VIDEO_MAX_FRAME)
+ return -EINVAL;
+
*nplanes = 1;
return 0;
}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e1a6ffd..0e096eb 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -168,16 +168,12 @@
/* Prevent idle power collapse(pc) while operating in peripheral mode */
static void msmsdcc_pm_qos_update_latency(struct msmsdcc_host *host, int vote)
{
- u32 swfi_latency = 0;
-
- if (!host->plat->swfi_latency)
+ if (!host->cpu_dma_latency)
return;
- swfi_latency = host->plat->swfi_latency + 1;
-
if (vote)
pm_qos_update_request(&host->pm_qos_req_dma,
- swfi_latency);
+ host->cpu_dma_latency);
else
pm_qos_update_request(&host->pm_qos_req_dma,
PM_QOS_DEFAULT_VALUE);
@@ -4082,21 +4078,22 @@
};
#endif
-void msmsdcc_print_regs(const char *name, void __iomem *base,
- unsigned int no_of_regs)
+static void msmsdcc_print_regs(const char *name, void __iomem *base,
+ u32 phys_base, unsigned int no_of_regs)
{
unsigned int i;
if (!base)
return;
- pr_info("===== %s: Register Dumps @base=0x%x =====\n",
- name, (u32)base);
+
+ pr_info("===== %s: Register Dumps @phys_base=0x%x, @virt_base=0x%x"
+ " =====\n", name, phys_base, (u32)base);
for (i = 0; i < no_of_regs; i = i + 4) {
- pr_info("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x.\n", i*4,
- (u32)readl_relaxed(base + i*4),
- (u32)readl_relaxed(base + ((i+1)*4)),
- (u32)readl_relaxed(base + ((i+2)*4)),
- (u32)readl_relaxed(base + ((i+3)*4)));
+ pr_info("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x\n", i*4,
+ (u32)readl_relaxed(base + i*4),
+ (u32)readl_relaxed(base + ((i+1)*4)),
+ (u32)readl_relaxed(base + ((i+2)*4)),
+ (u32)readl_relaxed(base + ((i+3)*4)));
}
}
@@ -4104,17 +4101,17 @@
{
/* Dump current state of SDCC clocks, power and irq */
pr_info("%s: SDCC PWR is %s\n", mmc_hostname(host->mmc),
- (host->pwr ? "ON" : "OFF"));
+ (host->pwr ? "ON" : "OFF"));
pr_info("%s: SDCC clks are %s, MCLK rate=%d\n",
- mmc_hostname(host->mmc),
- (host->clks_on ? "ON" : "OFF"),
- (u32)clk_get_rate(host->clk));
+ mmc_hostname(host->mmc), (host->clks_on ? "ON" : "OFF"),
+ (u32)clk_get_rate(host->clk));
pr_info("%s: SDCC irq is %s\n", mmc_hostname(host->mmc),
(host->sdcc_irq_disabled ? "disabled" : "enabled"));
/* Now dump SDCC registers. Don't print FIFO registers */
if (host->clks_on)
- msmsdcc_print_regs("SDCC-CORE", host->base, 28);
+ msmsdcc_print_regs("SDCC-CORE", host->base,
+ host->core_memres->start, 28);
if (host->curr.data) {
if (!msmsdcc_is_dma_possible(host, host->curr.data))
@@ -4123,22 +4120,27 @@
pr_info("%s: ADM mode: busy=%d, chnl=%d, crci=%d\n",
mmc_hostname(host->mmc), host->dma.busy,
host->dma.channel, host->dma.crci);
- else if (host->is_sps_mode)
+ else if (host->is_sps_mode) {
+ if (host->sps.busy)
+ msmsdcc_print_regs("SDCC-DML", host->dml_base,
+ host->dml_memres->start,
+ 16);
pr_info("%s: SPS mode: busy=%d\n",
mmc_hostname(host->mmc), host->sps.busy);
+ }
pr_info("%s: xfer_size=%d, data_xfered=%d, xfer_remain=%d\n",
mmc_hostname(host->mmc), host->curr.xfer_size,
host->curr.data_xfered, host->curr.xfer_remain);
- pr_info("%s: got_dataend=%d, prog_enable=%d,"
- " wait_for_auto_prog_done=%d,"
- " got_auto_prog_done=%d\n",
- mmc_hostname(host->mmc), host->curr.got_dataend,
- host->prog_enable, host->curr.wait_for_auto_prog_done,
- host->curr.got_auto_prog_done);
}
+ pr_info("%s: got_dataend=%d, prog_enable=%d,"
+ " wait_for_auto_prog_done=%d, got_auto_prog_done=%d\n",
+ mmc_hostname(host->mmc), host->curr.got_dataend,
+ host->prog_enable, host->curr.wait_for_auto_prog_done,
+ host->curr.got_auto_prog_done);
}
+
static void msmsdcc_req_tout_timer_hdlr(unsigned long data)
{
struct msmsdcc_host *host = (struct msmsdcc_host *)data;
@@ -4537,9 +4539,13 @@
/* Apply Hard reset to SDCC to put it in power on default state */
msmsdcc_hard_reset(host);
+#define MSM_MMC_DEFAULT_CPUDMA_LATENCY 200 /* usecs */
/* pm qos request to prevent apps idle power collapse */
- if (host->plat->swfi_latency)
- pm_qos_add_request(&host->pm_qos_req_dma,
+ if (host->plat->cpu_dma_latency)
+ host->cpu_dma_latency = host->plat->cpu_dma_latency;
+ else
+ host->cpu_dma_latency = MSM_MMC_DEFAULT_CPUDMA_LATENCY;
+ pm_qos_add_request(&host->pm_qos_req_dma,
PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
ret = msmsdcc_vreg_init(host, true);
@@ -4825,7 +4831,7 @@
msmsdcc_vreg_init(host, false);
clk_disable:
clk_disable(host->clk);
- if (host->plat->swfi_latency)
+ if (host->cpu_dma_latency)
pm_qos_remove_request(&host->pm_qos_req_dma);
clk_put:
clk_put(host->clk);
@@ -4899,7 +4905,7 @@
if (!IS_ERR_OR_NULL(host->dfab_pclk))
clk_put(host->dfab_pclk);
- if (host->plat->swfi_latency)
+ if (host->cpu_dma_latency)
pm_qos_remove_request(&host->pm_qos_req_dma);
msmsdcc_vreg_init(host, false);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 406af4f..50477da 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -395,6 +395,7 @@
bool sdio_gpio_lpm;
bool irq_wake_enabled;
struct pm_qos_request_list pm_qos_req_dma;
+ u32 cpu_dma_latency;
bool sdcc_suspending;
bool sdcc_irq_disabled;
bool sdcc_suspended;
diff --git a/drivers/mtd/devices/msm_nand.c b/drivers/mtd/devices/msm_nand.c
index 2479a11..3675d2c 100644
--- a/drivers/mtd/devices/msm_nand.c
+++ b/drivers/mtd/devices/msm_nand.c
@@ -6720,6 +6720,14 @@
((devcfg >> 4) & 0x3);
supported_flash.oobsize = (8 << ((devcfg >> 2) & 0x3)) *
(supported_flash.pagesize >> 9);
+
+ if ((supported_flash.oobsize > 64) &&
+ (supported_flash.pagesize == 2048)) {
+ pr_info("msm_nand: Found a 2K page device with"
+ " %d oobsize - changing oobsize to 64 "
+ "bytes.\n", supported_flash.oobsize);
+ supported_flash.oobsize = 64;
+ }
} else {
supported_flash.flash_id = flash_id;
supported_flash.density = flashdev->chipsize << 20;
diff --git a/drivers/net/msm_rmnet_sdio.c b/drivers/net/msm_rmnet_sdio.c
index 883c649..acdffd1 100644
--- a/drivers/net/msm_rmnet_sdio.c
+++ b/drivers/net/msm_rmnet_sdio.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
@@ -78,6 +78,7 @@
#endif
struct sk_buff *skb;
spinlock_t lock;
+ spinlock_t tx_queue_lock;
struct tasklet_struct tsklt;
u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
uint8_t device_up;
@@ -361,6 +362,7 @@
static void sdio_write_done(void *dev, struct sk_buff *skb)
{
struct rmnet_private *p = netdev_priv(dev);
+ unsigned long flags;
if (skb)
dev_kfree_skb_any(skb);
@@ -368,12 +370,14 @@
if (!p->in_reset) {
DBG1("%s: write complete skb=%p\n", __func__, skb);
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (netif_queue_stopped(dev) &&
msm_sdio_dmux_is_ch_low(p->ch_id)) {
DBG0("%s: Low WM hit, waking queue=%p\n",
__func__, skb);
netif_wake_queue(dev);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
} else {
DBG1("%s: write in reset skb=%p\n", __func__, skb);
}
@@ -454,6 +458,7 @@
static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rmnet_private *p = netdev_priv(dev);
+ unsigned long flags;
if (netif_queue_stopped(dev)) {
pr_err("[%s]fatal: rmnet_xmit called when "
@@ -463,10 +468,12 @@
_rmnet_xmit(skb, dev);
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (msm_sdio_dmux_is_ch_full(p->ch_id)) {
netif_stop_queue(dev);
DBG0("%s: High WM hit, stopping queue=%p\n", __func__, skb);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
return 0;
}
@@ -667,6 +674,7 @@
p->operation_mode = RMNET_MODE_LLP_ETH;
p->ch_id = n;
spin_lock_init(&p->lock);
+ spin_lock_init(&p->tx_queue_lock);
#ifdef CONFIG_MSM_RMNET_DEBUG
p->timeout_us = timeout_us;
p->wakeups_xmit = p->wakeups_rcv = 0;
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index ae3f934..3352380 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -13,6 +13,8 @@
#include <linux/mii.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/usb.h>
#include <linux/usb/usbnet.h>
#include <linux/msm_rmnet.h>
@@ -416,6 +418,90 @@
dev->watchdog_timeo = 1000; /* 10 seconds? */
}
+static int rmnet_usb_data_status(struct seq_file *s, void *unused)
+{
+ struct usbnet *unet = s->private;
+
+ seq_printf(s, "RMNET_MODE_LLP_IP: %d\n",
+ test_bit(RMNET_MODE_LLP_IP, &unet->data[0]));
+ seq_printf(s, "RMNET_MODE_LLP_ETH: %d\n",
+ test_bit(RMNET_MODE_LLP_ETH, &unet->data[0]));
+ seq_printf(s, "RMNET_MODE_QOS: %d\n",
+ test_bit(RMNET_MODE_QOS, &unet->data[0]));
+ seq_printf(s, "Net MTU: %u\n", unet->net->mtu);
+ seq_printf(s, "rx_urb_size: %u\n", unet->rx_urb_size);
+ seq_printf(s, "rx skb q len: %u\n", unet->rxq.qlen);
+ seq_printf(s, "rx skb done q len: %u\n", unet->done.qlen);
+ seq_printf(s, "rx errors: %lu\n", unet->net->stats.rx_errors);
+ seq_printf(s, "rx over errors: %lu\n",
+ unet->net->stats.rx_over_errors);
+ seq_printf(s, "rx length errors: %lu\n",
+ unet->net->stats.rx_length_errors);
+ seq_printf(s, "rx packets: %lu\n", unet->net->stats.rx_packets);
+ seq_printf(s, "rx bytes: %lu\n", unet->net->stats.rx_bytes);
+ seq_printf(s, "tx skb q len: %u\n", unet->txq.qlen);
+ seq_printf(s, "tx errors: %lu\n", unet->net->stats.tx_errors);
+ seq_printf(s, "tx packets: %lu\n", unet->net->stats.tx_packets);
+ seq_printf(s, "tx bytes: %lu\n", unet->net->stats.tx_bytes);
+ seq_printf(s, "suspend count: %d\n", unet->suspend_count);
+ seq_printf(s, "EVENT_DEV_OPEN: %d\n",
+ test_bit(EVENT_DEV_OPEN, &unet->flags));
+ seq_printf(s, "EVENT_TX_HALT: %d\n",
+ test_bit(EVENT_TX_HALT, &unet->flags));
+ seq_printf(s, "EVENT_RX_HALT: %d\n",
+ test_bit(EVENT_RX_HALT, &unet->flags));
+ seq_printf(s, "EVENT_RX_MEMORY: %d\n",
+ test_bit(EVENT_RX_MEMORY, &unet->flags));
+ seq_printf(s, "EVENT_DEV_ASLEEP: %d\n",
+ test_bit(EVENT_DEV_ASLEEP, &unet->flags));
+
+ return 0;
+}
+
+static int rmnet_usb_data_status_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rmnet_usb_data_status, inode->i_private);
+}
+
+const struct file_operations rmnet_usb_data_fops = {
+ .open = rmnet_usb_data_status_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int rmnet_usb_data_debugfs_init(struct usbnet *unet)
+{
+ struct dentry *rmnet_usb_data_dbg_root;
+ struct dentry *rmnet_usb_data_dentry;
+
+ rmnet_usb_data_dbg_root = debugfs_create_dir(unet->net->name, NULL);
+ if (!rmnet_usb_data_dbg_root || IS_ERR(rmnet_usb_data_dbg_root))
+ return -ENODEV;
+
+ rmnet_usb_data_dentry = debugfs_create_file("status",
+ S_IRUGO | S_IWUSR,
+ rmnet_usb_data_dbg_root, unet,
+ &rmnet_usb_data_fops);
+
+ if (!rmnet_usb_data_dentry) {
+ debugfs_remove_recursive(rmnet_usb_data_dbg_root);
+ return -ENODEV;
+ }
+
+ unet->data[2] = (unsigned long)rmnet_usb_data_dbg_root;
+
+ return 0;
+}
+
+static void rmnet_usb_data_debugfs_cleanup(struct usbnet *unet)
+{
+ struct dentry *root = (struct dentry *)unet->data[2];
+
+ debugfs_remove_recursive(root);
+ unet->data[2] = 0;
+}
+
static int rmnet_usb_probe(struct usb_interface *iface,
const struct usb_device_id *prod)
{
@@ -469,6 +555,10 @@
if (status)
goto out;
+ status = rmnet_usb_data_debugfs_init(unet);
+ if (status)
+ dev_dbg(&udev->dev, "mode debugfs file is not available\n");
+
/* allow modem to wake up suspended system */
device_set_wakeup_enable(&udev->dev, 1);
out:
@@ -490,6 +580,8 @@
return;
}
+ rmnet_usb_data_debugfs_cleanup(unet);
+
dev = (struct rmnet_ctrl_dev *)unet->data[1];
if (!dev) {
dev_err(&udev->dev, "%s:ctrl device not found\n", __func__);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index ce748f5..aa1a589 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -78,9 +78,13 @@
/**
* struct pm8921_bms_chip -
* @bms_output_lock: lock to prevent concurrent bms reads
- * @bms_100_lock: lock to prevent concurrent updates to values that force
- * 100% charge
*
+ * @last_ocv_uv_mutex: mutex to protect simultaneous invocations of calculate
+ * state of charge, note that last_ocv_uv could be
+ * changed as soc is adjusted. This mutex protects
+ * simultaneous updates of last_ocv_uv as well. This mutex
+ * also protects changes to *_at_100 variables used in
+ * faking 100% SOC.
*/
struct pm8921_bms_chip {
struct device *dev;
@@ -111,7 +115,6 @@
unsigned int pmic_bms_irq[PM_BMS_MAX_INTS];
DECLARE_BITMAP(enabled_irqs, PM_BMS_MAX_INTS);
struct mutex bms_output_lock;
- spinlock_t bms_100_lock;
struct single_row_lut *adjusted_fcc_temp_lut;
unsigned int charging_began;
unsigned int start_percent;
@@ -127,6 +130,8 @@
int amux_2_trim_delta;
uint16_t prev_last_good_ocv_raw;
unsigned int rconn_mohm;
+ struct mutex last_ocv_uv_mutex;
+ int last_ocv_uv;
};
static struct pm8921_bms_chip *the_chip;
@@ -144,7 +149,6 @@
module_param(last_charge_increase, int, 0644);
static int last_rbatt = -EINVAL;
-static int last_ocv_uv = -EINVAL;
static int last_soc = -EINVAL;
static int last_real_fcc_mah = -EINVAL;
static int last_real_fcc_batt_temp = -EINVAL;
@@ -163,7 +167,6 @@
};
module_param_cb(last_rbatt, &bms_param_ops, &last_rbatt, 0644);
-module_param_cb(last_ocv_uv, &bms_param_ops, &last_ocv_uv, 0644);
module_param_cb(last_soc, &bms_param_ops, &last_soc, 0644);
/*
@@ -957,16 +960,28 @@
adjust_pon_ocv_raw(chip, raw);
convert_vbatt_raw_to_uv(chip, usb_chg,
raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
- last_ocv_uv = raw->last_good_ocv_uv;
+ chip->last_ocv_uv = raw->last_good_ocv_uv;
} else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
convert_vbatt_raw_to_uv(chip, usb_chg,
raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
- last_ocv_uv = raw->last_good_ocv_uv;
+ chip->last_ocv_uv = raw->last_good_ocv_uv;
} else {
- raw->last_good_ocv_uv = last_ocv_uv;
+ raw->last_good_ocv_uv = chip->last_ocv_uv;
}
+ /* fake a high OCV if we are just done charging */
+ if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
+ chip->ocv_reading_at_100 = 0;
+ chip->cc_reading_at_100 = 0;
+ } else {
+ /*
+ * force 100% ocv by selecting the highest voltage the
+ * battery could ever reach
+ */
+ raw->last_good_ocv_uv = chip->max_voltage_uv;
+ chip->last_ocv_uv = chip->max_voltage_uv;
+ }
pr_debug("0p625 = %duV\n", chip->xoadc_v0625);
pr_debug("1p25 = %duV\n", chip->xoadc_v125);
pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
@@ -1120,7 +1135,7 @@
cc_voltage_uv = cc;
cc_voltage_uv -= chip->cc_reading_at_100;
- pr_debug("cc = %d. after subtracting %d cc = %lld\n",
+ pr_debug("cc = %d. after subtracting 0x%x cc = %lld\n",
cc, chip->cc_reading_at_100,
cc_voltage_uv);
cc_voltage_uv = cc_to_microvolt(chip, cc_voltage_uv);
@@ -1156,25 +1171,7 @@
{
int ocv, pc;
- /* calculate remainging charge */
- ocv = 0;
- if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
- chip->ocv_reading_at_100 = 0;
- chip->cc_reading_at_100 = 0;
- ocv = raw->last_good_ocv_uv;
- } else {
- /*
- * force 100% ocv by selecting the highest voltage the
- * battery could every reach
- */
- ocv = chip->max_voltage_uv;
- }
-
- if (ocv == 0) {
- ocv = last_ocv_uv;
- pr_debug("ocv not available using last_ocv_uv=%d\n", ocv);
- }
-
+ ocv = raw->last_good_ocv_uv;
pc = calculate_pc(chip, ocv, batt_temp, chargecycles);
pr_debug("ocv = %d pc = %d\n", ocv, pc);
return (fcc_uah * pc) / 100;
@@ -1189,7 +1186,6 @@
int *cc_uah,
int *rbatt)
{
- unsigned long flags;
int soc_rbatt;
*fcc_uah = calculate_fcc_uah(chip, batt_temp, chargecycles);
@@ -1197,7 +1193,6 @@
*fcc_uah, batt_temp, chargecycles);
- spin_lock_irqsave(&chip->bms_100_lock, flags);
/* calculate remainging charge */
*remaining_charge_uah = calculate_remaining_charge_uah(chip, raw,
*fcc_uah, batt_temp, chargecycles);
@@ -1205,11 +1200,10 @@
/* calculate cc micro_volt_hour */
calculate_cc_uah(chip, raw->cc, cc_uah);
- pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %d\n",
+ pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %x\n",
*cc_uah, raw->cc,
(int64_t)raw->cc - chip->cc_reading_at_100,
chip->cc_reading_at_100);
- spin_unlock_irqrestore(&chip->bms_100_lock, flags);
soc_rbatt = ((*remaining_charge_uah - *cc_uah) * 100) / *fcc_uah;
if (soc_rbatt < 0)
@@ -1245,6 +1239,108 @@
real_fcc_uah, remaining_charge_uah, cc_uah, fcc_uah);
return real_fcc_uah;
}
+
+static int bound_soc(int soc)
+{
+ soc = max(0, soc);
+ soc = min(100, soc);
+ return soc;
+}
+
+static int last_soc_est = -EINVAL;
+static int adjust_soc(struct pm8921_bms_chip *chip, int soc, int batt_temp,
+ int rbatt , int fcc_uah, int uuc_uah, int cc_uah)
+{
+ int ibat_ua = 0, vbat_uv = 0;
+ int ocv_est_uv = 0, soc_est = 0, pc_est = 0, pc = 0;
+ int delta_ocv_uv = 0;
+ int n = 0;
+ int rc_new_uah = 0;
+ int pc_new = 0;
+ int soc_new = 0;
+ int m = 0;
+
+ pm8921_bms_get_simultaneous_battery_voltage_and_current(&ibat_ua,
+ &vbat_uv);
+
+ if (ibat_ua < 0)
+ goto out;
+ ocv_est_uv = vbat_uv + (ibat_ua * rbatt)/1000;
+ pc_est = calculate_pc(chip, ocv_est_uv, batt_temp, last_chargecycles);
+ soc_est = div_s64((s64)fcc_uah * pc_est - uuc_uah*100,
+ (s64)fcc_uah - uuc_uah);
+ soc_est = bound_soc(soc_est);
+
+ /*
+ * do not adjust if soc_est is between 45 and 25 OR soc_est is
+ * same as what bms calculated
+ */
+ if (is_between(45, 25, soc_est) || soc_est == soc)
+ goto out;
+
+ if (last_soc_est == -EINVAL)
+ last_soc_est = soc;
+
+ n = min(200, max(1 , soc + soc_est + last_soc_est));
+ /* remember the last soc_est in last_soc_est */
+ last_soc_est = soc_est;
+
+ pc = calculate_pc(chip, chip->last_ocv_uv,
+ batt_temp, last_chargecycles);
+ if (pc > 0) {
+ pc_new = calculate_pc(chip, chip->last_ocv_uv - (++m * 1000),
+ batt_temp, last_chargecycles);
+ while (pc_new == pc) {
+ /* start taking 10mV steps */
+ m = m + 10;
+ pc_new = calculate_pc(chip,
+ chip->last_ocv_uv - (m * 1000),
+ batt_temp, last_chargecycles);
+ }
+ } else {
+ /*
+ * pc is already at the lowest point,
+ * assume 1 millivolt translates to 1% pc
+ */
+ pc = 1;
+ pc_new = 0;
+ m = 1;
+ }
+
+ delta_ocv_uv = div_s64((soc - soc_est) * (s64)m * 1000,
+ n * (pc - pc_new));
+ chip->last_ocv_uv -= delta_ocv_uv;
+
+ if (chip->last_ocv_uv >= chip->max_voltage_uv)
+ chip->last_ocv_uv = chip->max_voltage_uv;
+
+ /* calculate the soc based on this new ocv */
+ pc_new = calculate_pc(chip, chip->last_ocv_uv,
+ batt_temp, last_chargecycles);
+ rc_new_uah = (fcc_uah * pc_new) / 100;
+ soc_new = (rc_new_uah - cc_uah - uuc_uah)*100 / (fcc_uah - uuc_uah);
+ soc_new = bound_soc(soc_new);
+
+ /*
+ * if soc_new is ZERO force it higher so that phone doesnt report soc=0
+ * soc = 0 should happen only when soc_est == 0
+ */
+ if (soc_new == 0 && soc_est != 0)
+ soc_new = 1;
+
+ soc = soc_new;
+
+out:
+ pr_debug("ibat_ua = %d, vbat_uv = %d, ocv_est_uv = %d, pc_est = %d, "
+ "soc_est = %d, n = %d, delta_ocv_uv = %d, last_ocv_uv = %d, "
+ "pc_new = %d, soc_new = %d\n",
+ ibat_ua, vbat_uv, ocv_est_uv, pc_est,
+ soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
+ pc_new, soc_new);
+
+ return soc;
+}
+
/*
* Remaining Usable Charge = remaining_charge (charge at ocv instance)
* - coloumb counter charge
@@ -1257,7 +1353,6 @@
{
int remaining_usable_charge_uah, fcc_uah, unusable_charge_uah;
int remaining_charge_uah, soc;
- int update_userspace = 1;
int cc_uah;
int rbatt;
@@ -1302,30 +1397,31 @@
pr_err("for bad rem_usb_chg last_ocv_uv = %d"
"chargecycles = %d, batt_temp = %d"
"fcc = %d soc =%d\n",
- last_ocv_uv, chargecycles, batt_temp,
+ chip->last_ocv_uv, chargecycles, batt_temp,
fcc_uah, soc);
- update_userspace = 0;
soc = 0;
}
- if (last_soc == -EINVAL || soc <= last_soc) {
- last_soc = update_userspace ? soc : last_soc;
- return soc;
- }
+ soc = adjust_soc(chip, soc, batt_temp, rbatt,
+ fcc_uah, unusable_charge_uah, cc_uah);
- /*
- * soc > last_soc
- * the device must be charging for reporting a higher soc, if not ignore
- * this soc and continue reporting the last_soc
- */
- if (the_chip->start_percent != -EINVAL) {
+ if (last_soc == -EINVAL || soc <= last_soc) {
last_soc = soc;
} else {
- pr_debug("soc = %d reporting last_soc = %d\n", soc, last_soc);
- soc = last_soc;
+ /*
+ * soc > last_soc
+ * the device must be charging for reporting a higher soc, if
+ * not ignore this soc and continue reporting the last_soc
+ */
+ if (the_chip->start_percent != -EINVAL)
+ last_soc = soc;
+ else
+ pr_debug("soc = %d reporting last_soc = %d\n", soc,
+ last_soc);
}
- return soc;
+ pr_debug("Reported SOC = %u%%\n", last_soc);
+ return last_soc;
}
#define MIN_DELTA_625_UV 1000
static void calib_hkadc(struct pm8921_bms_chip *chip)
@@ -1452,6 +1548,7 @@
int batt_temp, rc;
struct pm8xxx_adc_chan_result result;
struct pm8921_soc_params raw;
+ int soc;
if (!the_chip) {
pr_err("called before initialization\n");
@@ -1468,10 +1565,13 @@
result.measurement);
batt_temp = (int)result.physical;
+ mutex_lock(&the_chip->last_ocv_uv_mutex);
read_soc_params_raw(the_chip, &raw);
- return calculate_state_of_charge(the_chip, &raw,
+ soc = calculate_state_of_charge(the_chip, &raw,
batt_temp, last_chargecycles);
+ mutex_unlock(&the_chip->last_ocv_uv_mutex);
+ return soc;
}
EXPORT_SYMBOL_GPL(pm8921_bms_get_percent_charge);
@@ -1501,6 +1601,8 @@
result.measurement);
batt_temp = (int)result.physical;
+ mutex_lock(&the_chip->last_ocv_uv_mutex);
+
read_soc_params_raw(the_chip, &raw);
calculate_soc_params(the_chip, &raw, batt_temp, last_chargecycles,
@@ -1509,6 +1611,8 @@
&remaining_charge_uah,
&cc_uah,
&rbatt);
+ mutex_unlock(&the_chip->last_ocv_uv_mutex);
+
return rbatt;
}
EXPORT_SYMBOL_GPL(pm8921_bms_get_rbatt);
@@ -1556,10 +1660,13 @@
result.measurement);
batt_temp = (int)result.physical;
+ mutex_lock(&the_chip->last_ocv_uv_mutex);
read_soc_params_raw(the_chip, &raw);
the_chip->start_percent = calculate_state_of_charge(the_chip, &raw,
batt_temp, last_chargecycles);
+ mutex_unlock(&the_chip->last_ocv_uv_mutex);
+
bms_start_percent = the_chip->start_percent;
bms_start_ocv_uv = raw.last_good_ocv_uv;
calculate_cc_uah(the_chip, raw.cc, &bms_start_cc_uah);
@@ -1590,13 +1697,16 @@
result.measurement);
batt_temp = (int)result.physical;
+ mutex_lock(&the_chip->last_ocv_uv_mutex);
+
read_soc_params_raw(the_chip, &raw);
calculate_cc_uah(the_chip, raw.cc, &bms_end_cc_uah);
+ bms_end_ocv_uv = raw.last_good_ocv_uv;
+
if (is_battery_full
&& the_chip->start_percent <= MIN_START_PERCENT_FOR_LEARNING) {
- unsigned long flags;
int fcc_uah, new_fcc_uah, delta_fcc_uah;
new_fcc_uah = calculate_real_fcc_uah(the_chip, &raw,
@@ -1627,20 +1737,24 @@
last_real_fcc_batt_temp = batt_temp;
readjust_fcc_table();
- spin_lock_irqsave(&the_chip->bms_100_lock, flags);
+ }
+
+ if (is_battery_full) {
the_chip->ocv_reading_at_100 = raw.last_good_ocv_raw;
the_chip->cc_reading_at_100 = raw.cc;
- spin_unlock_irqrestore(&the_chip->bms_100_lock, flags);
- pr_debug("EOC ocv_reading = 0x%x cc = %d\n",
+
+ the_chip->last_ocv_uv = the_chip->max_voltage_uv;
+ raw.last_good_ocv_uv = the_chip->max_voltage_uv;
+ pr_debug("EOC ocv_reading = 0x%x cc = 0x%x\n",
the_chip->ocv_reading_at_100,
the_chip->cc_reading_at_100);
}
the_chip->end_percent = calculate_state_of_charge(the_chip, &raw,
batt_temp, last_chargecycles);
+ mutex_unlock(&the_chip->last_ocv_uv_mutex);
bms_end_percent = the_chip->end_percent;
- bms_end_ocv_uv = raw.last_good_ocv_uv;
if (the_chip->end_percent > the_chip->start_percent) {
last_charge_increase +=
@@ -1804,6 +1918,8 @@
chip->batt_temp_channel, rc);
}
chip->batt_temp_suspend = (int)result.physical;
+
+ mutex_lock(&chip->last_ocv_uv_mutex);
read_soc_params_raw(chip, &raw);
fcc_uah = calculate_fcc_uah(chip,
@@ -1818,12 +1934,14 @@
/* calculate cc micro_volt_hour */
calculate_cc_uah(chip, raw.cc, &cc_uah);
- pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %d\n",
+ pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %x\n",
cc_uah, raw.cc,
(int64_t)raw.cc - chip->cc_reading_at_100,
chip->cc_reading_at_100);
chip->soc_rbatt_suspend = ((remaining_charge_uah - cc_uah) * 100)
/ fcc_uah;
+ mutex_unlock(&chip->last_ocv_uv_mutex);
+
return 0;
}
@@ -1911,9 +2029,9 @@
pr_err("failed to read adc based ocv_uv rc = %d\n", rc);
ocv_uv = DEFAULT_OCV_MICROVOLTS;
}
- last_ocv_uv = ocv_uv;
}
- pr_debug("ocv_uv = %d last_ocv_uv = %d\n", ocv_uv, last_ocv_uv);
+ chip->last_ocv_uv = ocv_uv;
+ pr_debug("ocv_uv = %d last_ocv_uv = %d\n", ocv_uv, chip->last_ocv_uv);
}
static int64_t read_battery_id(struct pm8921_bms_chip *chip)
@@ -2314,8 +2432,9 @@
pr_err("Cannot allocate pm_bms_chip\n");
return -ENOMEM;
}
+
mutex_init(&chip->bms_output_lock);
- spin_lock_init(&chip->bms_100_lock);
+ mutex_init(&chip->last_ocv_uv_mutex);
chip->dev = &pdev->dev;
chip->r_sense = pdata->r_sense;
chip->i_test = pdata->i_test;
@@ -2387,7 +2506,7 @@
get_battery_uvolts(chip, &vbatt);
pr_info("OK battery_capacity_at_boot=%d volt = %d ocv = %d\n",
pm8921_bms_get_percent_charge(),
- vbatt, last_ocv_uv);
+ vbatt, chip->last_ocv_uv);
return 0;
free_irqs:
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index eea4fa1..8e9d753 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -2211,7 +2211,7 @@
reg_loop = pm_chg_get_regulation_loop(chip);
pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
- if (reg_loop & VIN_ACTIVE_BIT) {
+ if ((reg_loop & VIN_ACTIVE_BIT) && (usb_ma > USB_WALL_THRESHOLD_MA)) {
decrease_usb_ma_value(&usb_ma);
usb_target_ma = usb_ma;
/* end AICL here */
diff --git a/drivers/power/smb349.c b/drivers/power/smb349.c
index 148f188..4c07285 100644
--- a/drivers/power/smb349.c
+++ b/drivers/power/smb349.c
@@ -415,7 +415,7 @@
debugfs_remove_recursive(smb349_chg->dent);
}
-static int __devinit smb349_hwinit(struct smb349_struct *smb349_chg)
+static int smb349_hwinit(struct smb349_struct *smb349_chg)
{
int ret;
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index cc008ab..24da4d1 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1978,6 +1978,9 @@
slc1 = ctrl->sched.chc1[coeff1];
}
}
+ /* Leave some slots for messaging space */
+ if (opensl1[1] == 0 && opensl1[0] == 0)
+ return -EXFULL;
if (opensl1[1] > opensl1[0]) {
int temp = opensl1[0];
opensl1[0] = opensl1[1];
@@ -2180,6 +2183,9 @@
slc1 = ctrl->sched.chc1[coeff1];
}
}
+ /* Leave some slots for messaging space */
+ if (opensl3[1] == 0 && opensl3[0] == 0)
+ return -EXFULL;
/* swap 1st and 2nd bucket if 2nd bucket has more open slots */
if (opensl3[1] > opensl3[0]) {
int temp = opensl3[0];
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index e2d77e9..69e0546 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1155,6 +1155,22 @@
return xfrs_grped;
}
+static inline void write_force_cs(struct msm_spi *dd, bool set_flag)
+{
+ u32 spi_ioc;
+ u32 spi_ioc_orig;
+
+ spi_ioc = readl_relaxed(dd->base + SPI_IO_CONTROL);
+ spi_ioc_orig = spi_ioc;
+ if (set_flag)
+ spi_ioc |= SPI_IO_C_FORCE_CS;
+ else
+ spi_ioc &= ~SPI_IO_C_FORCE_CS;
+
+ if (spi_ioc != spi_ioc_orig)
+ writel_relaxed(spi_ioc, dd->base + SPI_IO_CONTROL);
+}
+
static void msm_spi_process_message(struct msm_spi *dd)
{
int xfrs_grped = 0;
@@ -1178,11 +1194,10 @@
}
if (dd->qup_ver) {
+ write_force_cs(dd, 0);
list_for_each_entry(dd->cur_transfer,
&dd->cur_msg->transfers,
transfer_list) {
- u32 spi_ioc;
- u32 spi_ioc_orig;
struct spi_transfer *t = dd->cur_transfer;
struct spi_transfer *nxt;
@@ -1191,18 +1206,10 @@
struct spi_transfer,
transfer_list);
- spi_ioc = readl_relaxed(dd->base +
- SPI_IO_CONTROL);
- spi_ioc_orig = spi_ioc;
if (t->cs_change == nxt->cs_change)
- spi_ioc |= SPI_IO_C_FORCE_CS;
+ write_force_cs(dd, 1);
else
- spi_ioc &= ~SPI_IO_C_FORCE_CS;
-
- if (spi_ioc != spi_ioc_orig) {
- writel_relaxed(spi_ioc,
- dd->base + SPI_IO_CONTROL);
- }
+ write_force_cs(dd, 0);
}
dd->cur_msg_len = dd->cur_transfer->len;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index fc665ed..5b0b279 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -367,7 +367,7 @@
* test scripts.
* writing 0 disables the internal loopback mode. Default is disabled.
*/
-static void __init msm_serial_debugfs_init(struct msm_hs_port *msm_uport,
+static void __devinit msm_serial_debugfs_init(struct msm_hs_port *msm_uport,
int id)
{
char node_name[15];
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 0598c7b..02b2cc3 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -100,8 +100,6 @@
u32 ntb_input_size;
u16 ntb_max_datagrams;
- pid_t user_pid;
-
atomic_t error;
};
@@ -619,6 +617,59 @@
atomic_set(&mbim->online, 0);
}
+static void mbim_reset_function_queue(struct f_mbim *dev)
+{
+ struct ctrl_pkt *cpkt = NULL;
+
+ pr_debug("Queue empty packet for QBI");
+
+ spin_lock(&dev->lock);
+ if (!dev->is_open) {
+ pr_err("%s: mbim file handler %p is not open", __func__, dev);
+ spin_unlock(&dev->lock);
+ return;
+ }
+
+ cpkt = mbim_alloc_ctrl_pkt(0, GFP_ATOMIC);
+ if (!cpkt) {
+ pr_err("%s: Unable to allocate reset function pkt\n", __func__);
+ spin_unlock(&dev->lock);
+ return;
+ }
+
+ list_add_tail(&cpkt->list, &dev->cpkt_req_q);
+ spin_unlock(&dev->lock);
+
+ pr_debug("%s: Wake up read queue", __func__);
+ wake_up(&dev->read_wq);
+}
+
+static void fmbim_reset_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_mbim *dev = req->context;
+
+ mbim_reset_function_queue(dev);
+}
+
+static void mbim_clear_queues(struct f_mbim *mbim)
+{
+ struct ctrl_pkt *cpkt = NULL;
+ struct list_head *act, *tmp;
+
+ spin_lock(&mbim->lock);
+ list_for_each_safe(act, tmp, &mbim->cpkt_req_q) {
+ cpkt = list_entry(act, struct ctrl_pkt, list);
+ list_del(&cpkt->list);
+ mbim_free_ctrl_pkt(cpkt);
+ }
+ list_for_each_safe(act, tmp, &mbim->cpkt_resp_q) {
+ cpkt = list_entry(act, struct ctrl_pkt, list);
+ list_del(&cpkt->list);
+ mbim_free_ctrl_pkt(cpkt);
+ }
+ spin_unlock(&mbim->lock);
+}
+
/*
* Context: mbim->lock held
*/
@@ -741,6 +792,9 @@
mbim->not_port.notify_state = NCM_NOTIFY_NONE;
atomic_set(&mbim->not_port.notify_count, 0);
pr_info("ESHUTDOWN/ECONNRESET, connection gone");
+ spin_unlock(&mbim->lock);
+ mbim_clear_queues(mbim);
+ mbim_reset_function_queue(mbim);
break;
default:
pr_err("Unknown event %02x --> %d\n",
@@ -880,21 +934,8 @@
pr_info("USB_CDC_RESET_FUNCTION");
value = 0;
- if (!_mbim_dev->user_pid) {
- pr_err("QBI pid is not set");
- break;
- }
-
- if (!_mbim_dev->is_open) {
- pr_err("QBI is not up yet");
- break;
- }
-
- send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
- find_task_by_vpid(_mbim_dev->user_pid));
-
- pr_info("Sent signal to QBI pid %d",
- _mbim_dev->user_pid);
+ req->complete = fmbim_reset_cmd_complete;
+ req->context = mbim;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
@@ -1200,12 +1241,8 @@
pr_info("SET DEVICE OFFLINE");
atomic_set(&mbim->online, 0);
- if (_mbim_dev && _mbim_dev->user_pid && _mbim_dev->is_open) {
- send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
- find_task_by_vpid(_mbim_dev->user_pid));
- pr_info("Sending reset signal to QBI pid %d",
- _mbim_dev->user_pid);
- }
+ mbim_clear_queues(mbim);
+ mbim_reset_function_queue(mbim);
mbim_bam_disconnect(mbim);
@@ -1599,9 +1636,6 @@
if (!atomic_read(&_mbim_dev->online))
pr_err("USB cable not connected\n");
- pr_info("Set QBI pid %d\n", pid_nr(task_pid(current)));
- _mbim_dev->user_pid = pid_nr(task_pid(current));
-
fp->private_data = _mbim_dev;
atomic_set(&_mbim_dev->error, 0);
@@ -1627,8 +1661,6 @@
mbim_notify(mbim);
spin_unlock(&mbim->lock);
- mbim->user_pid = 0;
-
mbim_unlock(&_mbim_dev->open_excl);
return 0;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index b428bd2..f319eb5 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -45,6 +45,7 @@
#include <mach/clk.h>
#include <mach/msm_xo.h>
#include <mach/msm_bus.h>
+#include <mach/rpm-regulator.h>
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
@@ -61,6 +62,7 @@
#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
+#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
@@ -104,53 +106,25 @@
#endif
}
-static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
-{
- int ret = 0;
+enum usb_vdd_value {
+ VDD_NONE = 0,
+ VDD_MIN,
+ VDD_MAX,
+ VDD_VAL_MAX,
+};
- if (init) {
- hsusb_vddcx = devm_regulator_get(motg->otg.dev, "HSUSB_VDDCX");
- if (IS_ERR(hsusb_vddcx)) {
- dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
- return PTR_ERR(hsusb_vddcx);
- }
-
- ret = regulator_set_voltage(hsusb_vddcx,
- USB_PHY_VDD_DIG_VOL_MIN,
- USB_PHY_VDD_DIG_VOL_MAX);
- if (ret) {
- dev_err(motg->otg.dev, "unable to set the voltage "
- "for hsusb vddcx\n");
- return ret;
- }
-
- ret = regulator_enable(hsusb_vddcx);
- if (ret) {
- regulator_set_voltage(hsusb_vddcx, 0,
- USB_PHY_VDD_DIG_VOL_MIN);
- dev_err(motg->otg.dev, "unable to enable the hsusb vddcx\n");
- return ret;
- }
-
- } else {
-
- ret = regulator_disable(hsusb_vddcx);
- if (ret) {
- dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
- return ret;
- }
-
- ret = regulator_set_voltage(hsusb_vddcx, 0,
- USB_PHY_VDD_DIG_VOL_MIN);
- if (ret) {
- dev_err(motg->otg.dev, "unable to set the voltage"
- "for hsusb vddcx\n");
- return ret;
- }
- }
-
- return ret;
-}
+static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
+ { /* VDD_CX CORNER Voting */
+ [VDD_NONE] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
+ [VDD_MAX] = RPM_VREG_CORNER_HIGH,
+ },
+ { /* VDD_CX Voltage Voting */
+ [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
+ [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
+ [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
+ },
+};
static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
{
@@ -194,19 +168,15 @@
return rc;
}
-#ifdef CONFIG_PM_SLEEP
-#define USB_PHY_SUSP_DIG_VOL 500000
static int msm_hsusb_config_vddcx(int high)
{
- int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+ struct msm_otg *motg = the_msm_otg;
+ enum usb_vdd_type vdd_type = motg->vdd_type;
+ int max_vol = vdd_val[vdd_type][VDD_MAX];
int min_vol;
int ret;
- if (high)
- min_vol = USB_PHY_VDD_DIG_VOL_MIN;
- else
- min_vol = USB_PHY_SUSP_DIG_VOL;
-
+ min_vol = vdd_val[vdd_type][!!high];
ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
if (ret) {
pr_err("%s: unable to set the voltage for regulator "
@@ -218,12 +188,6 @@
return ret;
}
-#else
-static int msm_hsusb_config_vddcx(int high)
-{
- return 0;
-}
-#endif
static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
{
@@ -565,6 +529,8 @@
ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
} else if (pdata->otg_control == OTG_PMIC_CONTROL) {
+ ulpi_write(otg, OTG_COMP_DISABLE,
+ ULPI_SET(ULPI_PWR_CLK_MNG_REG));
/* Enable PMIC pull-up */
pm8xxx_usb_id_pullup(1);
}
@@ -804,15 +770,6 @@
ulpi_write(otg, 0x08, 0x09);
}
- /*
- * Turn off the OTG comparators, if depends on PMIC for
- * VBUS and ID notifications.
- */
- if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !host_bus_suspend) {
- ulpi_write(otg, OTG_COMP_DISABLE,
- ULPI_SET(ULPI_PWR_CLK_MNG_REG));
- motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
- }
/* Set the PHCD bit, only if it is not set by the controller.
* PHY may take some time or even fail to enter into low power
@@ -986,12 +943,6 @@
}
skip_phy_resume:
- /* Turn on the OTG comparators on resume */
- if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
- ulpi_write(otg, OTG_COMP_DISABLE,
- ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
- motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
- }
if (device_may_wakeup(otg->dev)) {
disable_irq_wake(motg->irq);
if (motg->pdata->pmic_id_irq)
@@ -1134,6 +1085,10 @@
if (on) {
dev_dbg(otg->dev, "host on\n");
+ if (pdata->otg_control == OTG_PHY_CONTROL)
+ ulpi_write(otg, OTG_COMP_DISABLE,
+ ULPI_SET(ULPI_PWR_CLK_MNG_REG));
+
/*
* Some boards have a switch cotrolled by gpio
* to enable/disable internal HUB. Enable internal
@@ -1151,6 +1106,10 @@
if (pdata->setup_gpio)
pdata->setup_gpio(OTG_STATE_UNDEFINED);
+
+ if (pdata->otg_control == OTG_PHY_CONTROL)
+ ulpi_write(otg, OTG_COMP_DISABLE,
+ ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
}
}
@@ -3321,22 +3280,33 @@
clk_prepare_enable(motg->pclk);
- ret = msm_hsusb_init_vddcx(motg, 1);
- if (ret) {
- dev_err(&pdev->dev, "hsusb vddcx init failed\n");
- goto devote_xo_handle;
+ motg->vdd_type = VDDCX_CORNER;
+ hsusb_vddcx = devm_regulator_get(motg->otg.dev, "hsusb_vdd_dig");
+ if (IS_ERR(hsusb_vddcx)) {
+ hsusb_vddcx = devm_regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+ if (IS_ERR(hsusb_vddcx)) {
+ dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+ goto devote_xo_handle;
+ }
+ motg->vdd_type = VDDCX;
}
ret = msm_hsusb_config_vddcx(1);
if (ret) {
dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
- goto free_init_vddcx;
+ goto devote_xo_handle;
+ }
+
+ ret = regulator_enable(hsusb_vddcx);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
+ goto free_config_vddcx;
}
ret = msm_hsusb_ldo_init(motg, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
- goto free_init_vddcx;
+ goto free_hsusb_vddcx;
}
if (pdata->mhl_enable) {
@@ -3427,8 +3397,7 @@
(!(motg->pdata->mode == USB_OTG) ||
motg->pdata->pmic_id_irq))
motg->caps = ALLOW_PHY_POWER_COLLAPSE |
- ALLOW_PHY_RETENTION |
- ALLOW_PHY_COMP_DISABLE;
+ ALLOW_PHY_RETENTION;
if (motg->pdata->otg_control == OTG_PHY_CONTROL)
motg->caps = ALLOW_PHY_RETENTION;
@@ -3460,8 +3429,12 @@
msm_hsusb_ldo_enable(motg, 0);
free_ldo_init:
msm_hsusb_ldo_init(motg, 0);
-free_init_vddcx:
- msm_hsusb_init_vddcx(motg, 0);
+free_hsusb_vddcx:
+ regulator_disable(hsusb_vddcx);
+free_config_vddcx:
+ regulator_set_voltage(hsusb_vddcx,
+ vdd_val[motg->vdd_type][VDD_NONE],
+ vdd_val[motg->vdd_type][VDD_MAX]);
devote_xo_handle:
clk_disable_unprepare(motg->pclk);
msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
@@ -3535,7 +3508,10 @@
msm_xo_put(motg->xo_handle);
msm_hsusb_ldo_enable(motg, 0);
msm_hsusb_ldo_init(motg, 0);
- msm_hsusb_init_vddcx(motg, 0);
+ regulator_disable(hsusb_vddcx);
+ regulator_set_voltage(hsusb_vddcx,
+ vdd_val[motg->vdd_type][VDD_NONE],
+ vdd_val[motg->vdd_type][VDD_MAX]);
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index 578e339..b8d1df8 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -802,9 +802,18 @@
Support for HDMI CEC Feature
Choose to enable CEC
-config FB_MSM_HDMI_MHL
+config FB_MSM_HDMI_MHL_9244
depends on FB_MSM_HDMI_MSM_PANEL
- bool 'HDMI to MHL support'
+ bool 'SI_MHL 9244 support'
+ default n
+ ---help---
+ Support the HDMI to MHL conversion.
+ MHL (Mobile High-Definition Link) technology
+ uses USB connector to output HDMI content
+
+config FB_MSM_HDMI_MHL_8334
+ depends on FB_MSM_HDMI_MSM_PANEL
+ bool 'SI_MHL 8334 support '
default n
---help---
Support the HDMI to MHL conversion.
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index 5a72ad4..b2ecb08 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -171,6 +171,11 @@
obj-$(CONFIG_FB_MSM_TVOUT) += tvout_msm.o
+ccflags-y := -I$(src)/mhl
+obj-$(CONFIG_FB_MSM_HDMI_MHL_8334) += mhl-8334.o
+mhl-8334-objs += mhl/mhl_8334.o
+mhl-8334-objs += mhl/mhl_i2c_utils.o
+
obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_wfd_writeback_panel.o
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index e749a44..2ca9296 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -177,6 +177,9 @@
case MDP_BLOCK_OVERLAY_1:
base = 0x18000;
break;
+ case MDP_BLOCK_OVERLAY_2:
+ base = (mdp_rev >= MDP_REV_44) ? 0x88000 : 0;
+ break;
default:
break;
}
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index d765744..860209f 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -238,6 +238,9 @@
#define MDP4_OP_SCALEY_EN BIT(1)
#define MDP4_OP_SCALEX_EN BIT(0)
+#define MDP4_REV40_UP_SCALING_MAX (8)
+#define MDP4_REV41_OR_LATER_UP_SCALING_MAX (20)
+
#define MDP4_PIPE_PER_MIXER 2
#define MDP4_MAX_PLANE 4
@@ -755,7 +758,7 @@
int mdp4_csc_enable(struct mdp_csc_cfg_data *config);
int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr);
int mdp4_argc_cfg(struct mdp_pgc_lut_data *pgc_ptr);
-
+int mdp4_qseed_cfg(struct mdp_qseed_cfg_data *cfg);
u32 mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
void mdp4_free_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index b40d88a..7cc73de 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -99,7 +99,7 @@
static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
static int new_perf_level;
static struct ion_client *display_iclient;
-static struct mdp4_iommu_pipe_info mdp_iommu[MDP4_MIXER_MAX][OVERLAY_PIPE_RGB3];
+static struct mdp4_iommu_pipe_info mdp_iommu[MDP4_MIXER_MAX][OVERLAY_PIPE_MAX];
int mdp4_overlay_iommu_map_buf(int mem_id,
struct mdp4_overlay_pipe *pipe, unsigned int plane,
@@ -160,7 +160,7 @@
if (!display_iclient)
return;
- for (j = 0; j < OVERLAY_PIPE_RGB3; j++) {
+ for (j = 0; j < OVERLAY_PIPE_MAX; j++) {
iom_pipe_info = &mdp_iommu[pipe->mixer_num][j];
for (i = 0; i < MDP4_MAX_PLANE; i++) {
if (iom_pipe_info->prev_ihdl[i]) {
@@ -497,8 +497,13 @@
pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
- if (pipe->dst_h > pipe->src_h * 8) /* too much */
+ u32 upscale_max;
+ upscale_max = (mdp_rev >= MDP_REV_41) ?
+ MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+ MDP4_REV40_UP_SCALING_MAX;
+ if (pipe->dst_h > pipe->src_h * upscale_max)
return;
+
pipe->op_mode |= MDP4_OP_SCALEY_EN;
if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
@@ -520,10 +525,14 @@
}
if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
- if (pipe->dst_w > pipe->src_w * 8) /* too much */
+ u32 upscale_max;
+ upscale_max = (mdp_rev >= MDP_REV_41) ?
+ MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+ MDP4_REV40_UP_SCALING_MAX;
+
+ if (pipe->dst_w > pipe->src_w * upscale_max)
return;
pipe->op_mode |= MDP4_OP_SCALEX_EN;
-
if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
if (pipe->flags & MDP_BACKEND_COMPOSITION &&
pipe->alpha_enable && pipe->dst_w > pipe->src_w)
@@ -1895,6 +1904,11 @@
struct mdp4_iommu_pipe_info *iom_pipe_info;
int ret, ptype;
+ u32 upscale_max;
+ upscale_max = (mdp_rev >= MDP_REV_41) ?
+ MDP4_REV41_OR_LATER_UP_SCALING_MAX :
+ MDP4_REV40_UP_SCALING_MAX;
+
if (mfd == NULL) {
pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
return -ENODEV;
@@ -1919,8 +1933,7 @@
return -EINVAL;
}
-
- if (req->dst_rect.h > (req->src_rect.h * 8)) { /* too much */
+ if (req->dst_rect.h > (req->src_rect.h * upscale_max)) {
mdp4_stat.err_scale++;
pr_err("%s: scale up, too much (h)!\n", __func__);
return -ERANGE;
@@ -1932,7 +1945,7 @@
return -ERANGE;
}
- if (req->dst_rect.w > (req->src_rect.w * 8)) { /* too much */
+ if (req->dst_rect.w > (req->src_rect.w * upscale_max)) {
mdp4_stat.err_scale++;
pr_err("%s: scale up, too much (w)!\n", __func__);
return -ERANGE;
@@ -2671,6 +2684,11 @@
pipe = mdp4_overlay_ndx2pipe(req->id);
+ if (!pipe) {
+ mdp4_stat.err_play++;
+ return -ENODEV;
+ }
+
if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
return -EINTR;
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 5e0b0c7..b9760bf 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -259,14 +259,8 @@
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
if (dtv_pipe != NULL) {
- mdp4_mixer_stage_down(dtv_pipe);
- /*
- * wait4vsync to make sure pipes are
- * dis-engaged from mixer1
- * before turn off timing generator
- */
- mdp4_overlay_dtv_wait4vsync();
mdp4_dtv_stop(mfd);
+ mdp4_mixer_stage_down(dtv_pipe);
mdp4_overlay_pipe_free(dtv_pipe);
mdp4_iommu_unmap(dtv_pipe);
dtv_pipe = NULL;
@@ -453,6 +447,12 @@
if (mfd->ov_start)
return;
+ if (!dtv_pipe) {
+ pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+ __func__);
+ return;
+ }
+
if (dtv_pipe->blt_addr) {
mdp4_dtv_blt_ov_update(dtv_pipe);
dtv_pipe->ov_cnt++;
@@ -481,6 +481,12 @@
return;
if (!(data & 0x1) || (pipe == NULL))
return;
+ if (!dtv_pipe) {
+ pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+ __func__);
+ return;
+ }
+
wait_for_completion_timeout(&dtv_pipe->comp,
msecs_to_jiffies(VSYNC_PERIOD*2));
mdp_disable_irq(MDP_OVERLAY1_TERM);
@@ -521,11 +527,15 @@
void mdp4_dma_e_done_dtv()
{
+ if (!dtv_pipe)
+ return;
+
complete(&dtv_pipe->comp);
}
void mdp4_external_vsync_dtv()
{
+
complete_all(&dtv_comp);
}
@@ -534,6 +544,8 @@
*/
void mdp4_overlay1_done_dtv()
{
+ if (!dtv_pipe)
+ return;
if (dtv_pipe->blt_addr) {
mdp4_dtv_blt_dmae_update(dtv_pipe);
dtv_pipe->dmae_cnt++;
@@ -593,6 +605,11 @@
{
unsigned long flag;
+ if (!dtv_pipe) {
+ pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+ __func__);
+ return;
+ }
/* enable irq */
spin_lock_irqsave(&mdp_spin_lock, flag);
mdp_enable_irq(MDP_DMA_E_TERM);
@@ -616,6 +633,12 @@
return;
}
+ if (!dtv_pipe) {
+ pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+ __func__);
+ return;
+ }
+
spin_lock_irqsave(&mdp_spin_lock, flag);
if (enable && dtv_pipe->blt_addr == 0) {
dtv_pipe->blt_addr = mfd->ov1_wb_buf->phys_addr;
@@ -656,7 +679,11 @@
struct mdp4_overlay_pipe *pipe;
if (!mfd->panel_power_on)
return;
-
+ if (!dtv_pipe) {
+ pr_debug("%s: no mixer1 base layer pipe allocated!\n",
+ __func__);
+ return;
+ }
mutex_lock(&mfd->dma->ov_mutex);
pipe = dtv_pipe;
if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 9f8b5c6..b2657cf 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -2413,6 +2413,9 @@
case MDP_BLOCK_OVERLAY_1:
base = 0x1A000;
break;
+ case MDP_BLOCK_OVERLAY_2:
+ base = (mdp_rev >= MDP_REV_44) ? 0x8A000 : 0x0;
+ break;
case MDP_BLOCK_VG_1:
base = 0x24000;
break;
@@ -2468,6 +2471,11 @@
output = config->csc_data.flags;
mask = 0x07;
break;
+ case MDP_BLOCK_OVERLAY_2:
+ base = 0x88200;
+ output = config->csc_data.flags;
+ mask = 0x07;
+ break;
default:
pr_err("%s - CSC block does not exist on MDP_BLOCK = %d\n",
__func__, config->block);
@@ -2779,13 +2787,11 @@
#define MDP_PCC_OFFSET 0xA000
#define MDP_DMA_GC_OFFSET 0x8800
-#define MDP_LM_0_GC_OFFSET 0x4800
-#define MDP_LM_1_GC_OFFSET 0x4880
-
+#define MDP_LM_GC_OFFSET 0x4800
#define MDP_DMA_P_OP_MODE_OFFSET 0x70
#define MDP_DMA_S_OP_MODE_OFFSET 0x28
-#define MDP_LM_OP_MODE_OFFSET 0x10
+#define MDP_LM_OP_MODE_OFFSET 0x14
#define DMA_PCC_R2_OFFSET 0x100
@@ -2886,6 +2892,10 @@
valid = (mdp_rev >= MDP_REV_42) ? 1 : 0;
break;
+ case MDP_BLOCK_OVERLAY_2:
+ valid = (mdp_rev >= MDP_REV_44) ? 1 : 0;
+ break;
+
default:
break;
}
@@ -3021,11 +3031,8 @@
case MDP_BLOCK_OVERLAY_0:
case MDP_BLOCK_OVERLAY_1:
- offset = (uint32_t *)(blockbase +
- (MDP_BLOCK_OVERLAY_0 == pgc_ptr->block ?
- MDP_LM_0_GC_OFFSET
- : MDP_LM_1_GC_OFFSET));
-
+ case MDP_BLOCK_OVERLAY_2:
+ offset = (uint32_t *)(blockbase + MDP_LM_GC_OFFSET);
pgc_enable_offset = (uint32_t *)(blockbase
+ MDP_LM_OP_MODE_OFFSET);
lshift_bits = 2;
@@ -3205,3 +3212,90 @@
error:
return ret;
}
+
+#define QSEED_TABLE_1_COUNT 2
+#define QSEED_TABLE_2_COUNT 1024
+
+static uint32_t mdp4_pp_block2qseed(uint32_t block)
+{
+ uint32_t valid = 0;
+ switch (block) {
+ case MDP_BLOCK_VG_1:
+ case MDP_BLOCK_VG_2:
+ valid = 0x1;
+ break;
+ default:
+ break;
+ }
+ return valid;
+}
+
+static int mdp4_qseed_write_cfg(struct mdp_qseed_cfg_data *cfg)
+{
+ int i, ret = 0;
+ uint32_t base = (uint32_t) (MDP_BASE + mdp_block2base(cfg->block));
+ uint32_t *values;
+
+ if ((cfg->table_num != 1) && (cfg->table_num != 2)) {
+ ret = -ENOTTY;
+ goto error;
+ }
+
+ if (((cfg->table_num == 1) && (cfg->len != QSEED_TABLE_1_COUNT)) ||
+ ((cfg->table_num == 2) && (cfg->len != QSEED_TABLE_2_COUNT))) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ values = kmalloc(cfg->len * sizeof(uint32_t), GFP_KERNEL);
+ if (!values) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ ret = copy_from_user(values, cfg->data, sizeof(uint32_t) * cfg->len);
+
+ base += (cfg->table_num == 1) ? MDP4_QSEED_TABLE1_OFF :
+ MDP4_QSEED_TABLE2_OFF;
+ for (i = 0; i < cfg->len; i++) {
+ MDP_OUTP(base , values[i]);
+ base += sizeof(uint32_t);
+ }
+
+ kfree(values);
+error:
+ return ret;
+}
+
+int mdp4_qseed_cfg(struct mdp_qseed_cfg_data *cfg)
+{
+ int ret = 0;
+
+ if (!mdp4_pp_block2qseed(cfg->block)) {
+ ret = -ENOTTY;
+ goto error;
+ }
+
+ if (cfg->table_num != 1) {
+ ret = -ENOTTY;
+ pr_info("%s: Only QSEED table1 supported.\n", __func__);
+ goto error;
+ }
+
+ switch ((cfg->ops & 0x6) >> 1) {
+ case 0x1:
+ pr_info("%s: QSEED read not supported\n", __func__);
+ ret = -ENOTTY;
+ break;
+ case 0x2:
+ ret = mdp4_qseed_write_cfg(cfg);
+ if (ret)
+ goto error;
+ break;
+ default:
+ break;
+ }
+
+error:
+ return ret;
+}
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
new file mode 100644
index 0000000..43280a5
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -0,0 +1,849 @@
+/* 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/types.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <mach/msm_hdmi_audio.h>
+#include <mach/clk.h>
+#include <mach/msm_iomap.h>
+#include <mach/socinfo.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include "msm_fb.h"
+#include "external_common.h"
+#include "mhl_8334.h"
+#include "mhl_i2c_utils.h"
+
+#define DEBUG
+
+
+static struct i2c_device_id mhl_sii_i2c_id[] = {
+ { MHL_DRIVER_NAME, 0 },
+ { }
+};
+
+struct mhl_msm_state_t *mhl_msm_state;
+spinlock_t mhl_state_lock;
+
+static int mhl_i2c_probe(struct i2c_client *client,\
+ const struct i2c_device_id *id);
+static int mhl_i2c_remove(struct i2c_client *client);
+static void force_usb_switch_open(void);
+static void release_usb_switch_open(void);
+static void switch_mode(enum mhl_st_type to_mode);
+static irqreturn_t mhl_tx_isr(int irq, void *dev_id);
+
+static struct i2c_driver mhl_sii_i2c_driver = {
+ .driver = {
+ .name = MHL_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = mhl_i2c_probe,
+ /*.remove = __exit_p(mhl_i2c_remove),*/
+ .remove = mhl_i2c_remove,
+ .id_table = mhl_sii_i2c_id,
+};
+
+bool mhl_is_connected(void)
+{
+ return true;
+}
+
+static void cbus_reset(void)
+{
+ uint8_t i;
+
+ /*
+ * REG_SRST
+ */
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0000, BIT3, BIT3);
+ msleep(20);
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0000, BIT3, 0x00);
+ /*
+ * REG_INTR1 and REG_INTR4
+ */
+ mhl_i2c_reg_write(TX_PAGE_L0, 0x0075, BIT6 | BIT5);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0022,
+ BIT0 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
+ /* REG5 */
+ if (mhl_msm_state->chip_rev_id < 1)
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0024, BIT3 | BIT4);
+ else
+ /*REG5 Mask disabled due to auto FIFO reset ??*/
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0024, 0x00);
+
+ /* Unmask CBUS1 Intrs */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0009,
+ BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
+
+ /* Unmask CBUS2 Intrs */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x001F, BIT2 | BIT3);
+
+ for (i = 0; i < 4; i++) {
+ /*
+ * Enable WRITE_STAT interrupt for writes to
+ * all 4 MSC Status registers.
+ */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, (0xE0 + i), 0xFF);
+
+ /*
+ * Enable SET_INT interrupt for writes to
+ * all 4 MSC Interrupt registers.
+ */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, (0xF0 + i), 0xFF);
+ }
+}
+
+static void init_cbus_regs(void)
+{
+ uint8_t regval;
+
+ /* Increase DDC translation layer timer*/
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0007, 0xF2);
+ /* Drive High Time */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0036, 0x03);
+ /* Use programmed timing */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0039, 0x30);
+ /* CBUS Drive Strength */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0040, 0x03);
+ /*
+ * Write initial default settings
+ * to devcap regs: default settings
+ */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEV_STATE,
+ DEVCAP_VAL_DEV_STATE);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_MHL_VERSION,
+ DEVCAP_VAL_MHL_VERSION);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEV_CAT,
+ DEVCAP_VAL_DEV_CAT);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_ADOPTER_ID_H,
+ DEVCAP_VAL_ADOPTER_ID_H);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_ADOPTER_ID_L,
+ DEVCAP_VAL_ADOPTER_ID_L);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_VID_LINK_MODE,
+ DEVCAP_VAL_VID_LINK_MODE);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_AUD_LINK_MODE,
+ DEVCAP_VAL_AUD_LINK_MODE);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_VIDEO_TYPE,
+ DEVCAP_VAL_VIDEO_TYPE);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_LOG_DEV_MAP,
+ DEVCAP_VAL_LOG_DEV_MAP);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_BANDWIDTH,
+ DEVCAP_VAL_BANDWIDTH);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_FEATURE_FLAG,
+ DEVCAP_VAL_FEATURE_FLAG);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEVICE_ID_H,
+ DEVCAP_VAL_DEVICE_ID_H);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEVICE_ID_L,
+ DEVCAP_VAL_DEVICE_ID_L);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_SCRATCHPAD_SIZE,
+ DEVCAP_VAL_SCRATCHPAD_SIZE);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_INT_STAT_SIZE,
+ DEVCAP_VAL_INT_STAT_SIZE);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_RESERVED,
+ DEVCAP_VAL_RESERVED);
+
+ /* Make bits 2,3 (initiator timeout) to 1,1
+ * for register CBUS_LINK_CONTROL_2
+ * REG_CBUS_LINK_CONTROL_2
+ */
+ regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0031);
+ regval = (regval | 0x0C);
+ /* REG_CBUS_LINK_CONTROL_2 */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0031, regval);
+ /* REG_MSC_TIMEOUT_LIMIT */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0022, 0x0F);
+ /* REG_CBUS_LINK_CONTROL_1 */
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0030, 0x01);
+ /* disallow vendor specific commands */
+ mhl_i2c_reg_modify(TX_PAGE_CBUS, 0x002E, BIT4, BIT4);
+}
+
+/*
+ * Configure the initial reg settings
+ */
+static void mhl_init_reg_settings(void)
+{
+
+ /*
+ * ============================================
+ * POWER UP
+ * ============================================
+ */
+
+ /* Power up 1.2V core */
+ mhl_i2c_reg_write(TX_PAGE_L1, 0x003D, 0x3F);
+ /* Enable Tx PLL Clock */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0011, 0x01);
+ /* Enable Tx Clock Path and Equalizer */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0012, 0x11);
+ /* Tx Source Termination ON */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0030, 0x10);
+ /* Enable 1X MHL Clock output */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0035, 0xAC);
+ /* Tx Differential Driver Config */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0031, 0x3C);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0033, 0xD9);
+ /* PLL Bandwidth Control */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0037, 0x02);
+ /*
+ * ============================================
+ * Analog PLL Control
+ * ============================================
+ */
+ /* Enable Rx PLL clock */
+ mhl_i2c_reg_write(TX_PAGE_L0, 0x0080, 0x00);
+ mhl_i2c_reg_write(TX_PAGE_L0, 0x00F8, 0x0C);
+ mhl_i2c_reg_write(TX_PAGE_L0, 0x0085, 0x02);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0000, 0x00);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0013, 0x60);
+ /* PLL Cal ref sel */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0017, 0x03);
+ /* VCO Cal */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x001A, 0x20);
+ /* Auto EQ */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0022, 0xE0);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0023, 0xC0);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0024, 0xA0);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0025, 0x80);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0026, 0x60);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0027, 0x40);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0028, 0x20);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0029, 0x00);
+ /* Rx PLL Bandwidth 4MHz */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0031, 0x0A);
+ /* Rx PLL Bandwidth value from I2C */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x0045, 0x06);
+ mhl_i2c_reg_write(TX_PAGE_2, 0x004B, 0x06);
+ /* Manual zone control */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x004C, 0xE0);
+ /* PLL Mode value */
+ mhl_i2c_reg_write(TX_PAGE_2, 0x004D, 0x00);
+ mhl_i2c_reg_write(TX_PAGE_L0, 0x0008, 0x35);
+ /*
+ * Discovery Control and Status regs
+ * Setting De-glitch time to 50 ms (default)
+ * Switch Control Disabled
+ */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0011, 0xAD);
+ /* 1.8V CBUS VTH */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0014, 0x55);
+ /* RGND and single Discovery attempt */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0015, 0x11);
+ /* Ignore VBUS */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0017, 0x82);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0018, 0x24);
+ /* Pull-up resistance off for IDLE state */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0013, 0x84);
+ /* Enable CBUS Discovery */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0010, 0x27);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0016, 0x20);
+ /* MHL CBUS Discovery - immediate comm. */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0012, 0x86);
+ /* Do not force HPD to 0 during wake-up from D3 */
+ if (mhl_msm_state->cur_state != POWER_STATE_D3) {
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0020,
+ BIT5 | BIT4, BIT4);
+ }
+ /* Enable Auto Soft RESET */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0000, 0x084);
+ /* HDMI Transcode mode enable */
+ mhl_i2c_reg_write(TX_PAGE_L0, 0x000D, 0x1C);
+
+ cbus_reset();
+ init_cbus_regs();
+}
+
+static int mhl_chip_init(void)
+{
+ /* Read the chip rev ID */
+ mhl_msm_state->chip_rev_id = mhl_i2c_reg_read(TX_PAGE_L0, 0x04);
+ pr_debug("MHL: chip rev ID read=[%x]\n", mhl_msm_state->chip_rev_id);
+
+ /* Reset the TX chip */
+ mhl_msm_state->mhl_data->reset_pin(0);
+ msleep(20);
+ mhl_msm_state->mhl_data->reset_pin(1);
+ /* MHL spec requires a 100 ms wait here. */
+ msleep(100);
+
+ mhl_init_reg_settings();
+
+ /*
+ * Power down the chip to the
+ * D3 - a low power standby mode
+ * cable impedance measurement logic is operational
+ */
+ switch_mode(POWER_STATE_D3);
+ return 0;
+}
+
+/*
+ * I2C probe
+ */
+static int mhl_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ mhl_msm_state->mhl_data = kzalloc(sizeof(struct msm_mhl_platform_data),
+ GFP_KERNEL);
+ if (!(mhl_msm_state->mhl_data)) {
+ ret = -ENOMEM;
+ goto probe_exit;
+ }
+ pr_debug("Inside probe\n");
+ mhl_msm_state->i2c_client = client;
+
+ spin_lock_init(&mhl_state_lock);
+
+ i2c_set_clientdata(client, mhl_msm_state);
+ mhl_msm_state->mhl_data = client->dev.platform_data;
+
+ /* Init GPIO stuff here */
+ ret = mhl_msm_state->mhl_data->gpio_setup(1);
+ if (ret == -1) {
+ pr_err("MHL: mhl_gpio_init has failed\n");
+ ret = -ENODEV;
+ goto probe_exit;
+ }
+ return 0;
+
+probe_exit:
+ if (mhl_msm_state->mhl_data) {
+ /* free the gpios */
+ mhl_msm_state->mhl_data->gpio_setup(0);
+ kfree(mhl_msm_state->mhl_data);
+ mhl_msm_state->mhl_data = NULL;
+ }
+ return ret;
+}
+
+static int mhl_i2c_remove(struct i2c_client *client)
+{
+ pr_debug("inside i2c remove\n");
+ mhl_msm_state->mhl_data->gpio_setup(0);
+ kfree(mhl_msm_state->mhl_data);
+ return 0;
+}
+
+static int __init mhl_msm_init(void)
+{
+ int32_t ret;
+
+ mhl_msm_state = kzalloc(sizeof(struct mhl_msm_state_t), GFP_KERNEL);
+ if (!mhl_msm_state) {
+ pr_err("mhl_msm_init FAILED: out of memory\n");
+ ret = -ENOMEM;
+ goto init_exit;
+ }
+
+ mhl_msm_state->i2c_client = NULL;
+ ret = i2c_add_driver(&mhl_sii_i2c_driver);
+ if (ret) {
+ pr_err("MHL: I2C driver add failed: %d\n", ret);
+ ret = -ENODEV;
+ goto init_exit;
+ } else {
+ if (mhl_msm_state->i2c_client == NULL) {
+ pr_err("JSR: I2C driver add failed\n");
+ ret = -ENODEV;
+ goto init_exit;
+ }
+ pr_debug("MHL: I2C driver added\n");
+ }
+
+ /* Request IRQ stuff here */
+ pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
+ mhl_msm_state->mhl_data->irq);
+ ret = request_threaded_irq(mhl_msm_state->mhl_data->irq, NULL,
+ &mhl_tx_isr,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "mhl_tx_isr", mhl_msm_state);
+ if (ret != 0) {
+ pr_err("request_threaded_irq failed, status: %d\n",
+ ret);
+ ret = -EACCES; /* Error code???? */
+ goto init_exit;
+ }
+
+ mhl_msm_state->cur_state = POWER_STATE_D0_MHL;
+
+ /* MHL SII 8334 chip specific init */
+ mhl_chip_init();
+ return 0;
+
+init_exit:
+ pr_err("Exiting from the init with err\n");
+ i2c_del_driver(&mhl_sii_i2c_driver);
+ if (!mhl_msm_state) {
+ kfree(mhl_msm_state);
+ mhl_msm_state = NULL;
+ }
+ return ret;
+}
+
+static void switch_mode(enum mhl_st_type to_mode)
+{
+ unsigned long flags;
+
+ switch (to_mode) {
+ case POWER_STATE_D0_NO_MHL:
+ break;
+ case POWER_STATE_D0_MHL:
+ mhl_init_reg_settings();
+
+ /* REG_DISC_CTRL1 */
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0010, BIT1, 0);
+
+ /*
+ * TPI_DEVICE_POWER_STATE_CTRL_REG
+ * TX_POWER_STATE_MASK = BIT1 | BIT0
+ */
+ mhl_i2c_reg_modify(TX_PAGE_TPI, 0x001E, BIT1 | BIT0, 0x00);
+ break;
+ case POWER_STATE_D3:
+ if (mhl_msm_state->cur_state != POWER_STATE_D3) {
+ /* Force HPD to 0 when not in MHL mode. */
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0020,
+ BIT5 | BIT4, BIT4);
+
+ /*
+ * Change TMDS termination to high impedance
+ * on disconnection.
+ */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0030, 0xD0);
+ mhl_i2c_reg_modify(TX_PAGE_L1, 0x003D,
+ BIT1 | BIT0, BIT0);
+ spin_lock_irqsave(&mhl_state_lock, flags);
+ mhl_msm_state->cur_state = POWER_STATE_D3;
+ spin_unlock_irqrestore(&mhl_state_lock, flags);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void mhl_drive_hpd(uint8_t to_state)
+{
+ pr_debug("%s: To state=[0x%x]\n", __func__, to_state);
+ if (to_state == HPD_UP) {
+ /*
+ * Drive HPD to UP state
+ *
+ * The below two reg configs combined
+ * enable TMDS output.
+ */
+
+ /* Enable TMDS on TMDS_CCTRL */
+ mhl_i2c_reg_modify(TX_PAGE_L0, 0x0080, BIT4, BIT4);
+
+ /*
+ * Set HPD_OUT_OVR_EN = HPD State
+ * EDID read and Un-force HPD (from low)
+ * propogate to src let HPD float by clearing
+ * HPD OUT OVRRD EN
+ */
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0020, BIT4, 0x00);
+ } else {
+ /*
+ * Drive HPD to DOWN state
+ * Disable TMDS Output on REG_TMDS_CCTRL
+ * Enable/Disable TMDS output (MHL TMDS output only)
+ */
+ mhl_i2c_reg_modify(TX_PAGE_L0, 0x0080, BIT4, 0x00);
+ }
+ return;
+}
+
+static void mhl_msm_connection(void)
+{
+ uint8_t val;
+ unsigned long flags;
+
+ pr_err("%s: cur state = [0x%x]\n", __func__, mhl_msm_state->cur_state);
+
+ if (mhl_msm_state->cur_state == POWER_STATE_D0_MHL) {
+ /* Already in D0 - MHL power state */
+ return;
+ }
+ spin_lock_irqsave(&mhl_state_lock, flags);
+ mhl_msm_state->cur_state = POWER_STATE_D0_MHL;
+ spin_unlock_irqrestore(&mhl_state_lock, flags);
+
+ mhl_i2c_reg_write(TX_PAGE_3, 0x30, 0x10);
+
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x07, 0xF2);
+
+ /*
+ * Keep the discovery enabled. Need RGND interrupt
+ * Possibly chip disables discovery after MHL_EST??
+ * Need to re-enable here
+ */
+ val = mhl_i2c_reg_read(TX_PAGE_3, 0x10);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x10, val | BIT(0));
+
+ return;
+}
+
+static void mhl_msm_disconnection(void)
+{
+ uint8_t reg;
+
+ /* Clear interrupts - REG INTR4 */
+ reg = mhl_i2c_reg_read(TX_PAGE_3, 0x0021);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0021, reg);
+ /*
+ * MHL TX CTL1
+ * Disabling Tx termination
+ */
+ mhl_i2c_reg_write(TX_PAGE_3, 0x30, 0xD0);
+ /*
+ * MSC REQUESTOR ABORT REASON
+ * Clear CBUS_HPD status
+ */
+ mhl_i2c_reg_modify(TX_PAGE_CBUS, 0x000D, BIT6, 0x00);
+ /* Change HPD line to drive it low */
+ mhl_drive_hpd(HPD_DOWN);
+ /* switch power state to D3 */
+ switch_mode(POWER_STATE_D3);
+ return;
+}
+
+/*
+ * If hardware detected a change in impedence and raised an INTR
+ * We check the range of this impedence to infer if the connected
+ * device is MHL or USB and take appropriate actions.
+ */
+static void mhl_msm_read_rgnd_int(void)
+{
+ uint8_t rgnd_imp;
+
+ /*
+ * DISC STATUS REG 2
+ * 1:0 RGND
+ * 00 - open (USB)
+ * 01 - 2 kOHM (USB)
+ * 10 - 1 kOHM ***(MHL)**** It's range 800 - 1200 OHM from MHL spec
+ * 11 - short (USB)
+ */
+ rgnd_imp = mhl_i2c_reg_read(TX_PAGE_3, 0x001C);
+ pr_debug("Imp Range read = %02X\n", (int)rgnd_imp);
+
+
+ if (0x02 == rgnd_imp) {
+ pr_debug("MHL: MHL DEVICE!!!\n");
+ /*
+ * Handling the MHL event in driver
+ */
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0018, BIT0, BIT0);
+ } else {
+ pr_debug("MHL: NON-MHL DEVICE!!!\n");
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0018, BIT3, BIT3);
+ }
+}
+
+static void force_usb_switch_open(void)
+{
+ /*DISABLE_DISCOVERY*/
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0010, BIT0, 0);
+ /* Force USB ID switch to open*/
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0015, BIT6, BIT6);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0012, 0x86);
+ /* Force HPD to 0 when not in Mobile HD mode. */
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0020, BIT5 | BIT4, BIT4);
+}
+
+static void release_usb_switch_open(void)
+{
+ msleep(50);
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0015, BIT6, 0x00);
+ mhl_i2c_reg_modify(TX_PAGE_3, 0x0010, BIT0, BIT0);
+}
+
+static void int_4_isr(void)
+{
+ uint8_t status;
+
+ /* INTR_STATUS4 */
+ status = mhl_i2c_reg_read(TX_PAGE_3, 0x0021);
+
+ /*
+ * When I2C is inoperational (D3) and
+ * a previous interrupt brought us here,
+ * do nothing.
+ */
+ pr_debug("MHL: MRR Interrupt status is = %02X\n", (int) status);
+ if (0xFF != status) {
+ if ((status & BIT0) && (mhl_msm_state->chip_rev_id < 1)) {
+ uint8_t tmds_cstat;
+ uint8_t mhl_fifo_status;
+
+ /* TMDS CSTAT */
+ tmds_cstat = mhl_i2c_reg_read(TX_PAGE_3, 0x0040);
+
+ pr_debug("TMDS CSTAT: 0x%02x\n", tmds_cstat);
+
+ if (tmds_cstat & 0x02) {
+ mhl_fifo_status = mhl_i2c_reg_read(TX_PAGE_3,
+ 0x0023);
+ pr_debug("MHL FIFO status: 0x%02x\n",
+ mhl_fifo_status);
+ if (mhl_fifo_status & 0x0C) {
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0023,
+ 0x0C);
+
+ pr_debug("Apply MHL FIFO Reset\n");
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0000,
+ 0x94);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0000,
+ 0x84);
+ }
+ }
+ }
+
+ if (status & BIT1)
+ pr_err("MHL: INT4 BIT1 is set\n");
+
+ /* MHL_EST interrupt */
+ if (status & BIT2) {
+ pr_err("MHL: Calling mhl_msm_connection() from ISR\n");
+ mhl_msm_connection();
+ pr_err("MHL Connect Drv: INT4 Status = %02X\n",
+ (int) status);
+ } else if (status & BIT3) {
+ pr_err("MHL: uUSB-A type device detected.\n");
+ mhl_i2c_reg_write(TX_PAGE_3, 0x001C, 0x80);
+ switch_mode(POWER_STATE_D3);
+ }
+
+ if (status & BIT5) {
+ mhl_msm_disconnection();
+ pr_err("MHL Disconnect Drv: INT4 Status = %02X\n",
+ (int)status);
+ }
+
+ if ((mhl_msm_state->cur_state != POWER_STATE_D0_MHL) &&\
+ (status & BIT6)) {
+ /* RGND READY Intr */
+ switch_mode(POWER_STATE_D0_MHL);
+ mhl_msm_read_rgnd_int();
+ }
+
+ /* Can't succeed at these in D3 */
+ if (mhl_msm_state->cur_state != POWER_STATE_D3) {
+ /* CBUS Lockout interrupt? */
+ /*
+ * Hardware detection mechanism figures that
+ * CBUS line is latched and raises this intr
+ * where we force usb switch open and release
+ */
+ if (status & BIT4) {
+ force_usb_switch_open();
+ release_usb_switch_open();
+ }
+ }
+ }
+ pr_debug("MHL END Drv: INT4 Status = %02X\n", (int) status);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0021, status);
+
+ return;
+}
+
+static void int_5_isr(void)
+{
+ uint8_t intr_5_stat;
+
+ /*
+ * Clear INT 5 ??
+ * Probably need to revisit this later
+ * INTR5 is related to FIFO underflow/overflow reset
+ * which is handled in 8334 by auto FIFO reset
+ */
+ intr_5_stat = mhl_i2c_reg_read(TX_PAGE_3, 0x0023);
+ mhl_i2c_reg_write(TX_PAGE_3, 0x0023, intr_5_stat);
+}
+
+
+static void int_1_isr(void)
+{
+ /* This ISR mainly handles the HPD status changes */
+ uint8_t intr_1_stat;
+ uint8_t cbus_stat;
+
+ /* INTR STATUS 1 */
+ intr_1_stat = mhl_i2c_reg_read(TX_PAGE_L0, 0x0071);
+
+ if (intr_1_stat) {
+ /* Clear interrupts */
+ mhl_i2c_reg_write(TX_PAGE_L0, 0x0071, intr_1_stat);
+ if (BIT6 & intr_1_stat) {
+ /*
+ * HPD status change event is pending
+ * Read CBUS HPD status for this info
+ */
+
+ /* MSC REQ ABRT REASON */
+ cbus_stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0D);
+ if (BIT6 & cbus_stat)
+ mhl_drive_hpd(HPD_UP);
+ }
+ }
+ return;
+}
+
+/*
+ * RCP, RAP messages - mandatory for compliance
+ *
+ */
+static void mhl_cbus_isr(void)
+{
+ uint8_t regval;
+ int req_done = FALSE;
+ uint8_t sub_cmd;
+ uint8_t cmd_data;
+ int msc_msg_recved = FALSE;
+ int rc = -1;
+
+ regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x08);
+ if (regval == 0xff)
+ return;
+
+ /* clear all interrupts that were raised even if we did not process */
+ if (regval)
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x08, regval);
+
+ pr_err("%s: CBUS_INT = %02x\n", __func__, regval);
+
+ /* MSC_MSG (RCP/RAP) */
+ if (regval & BIT(3)) {
+ sub_cmd = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x18);
+ cmd_data = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x19);
+ msc_msg_recved = TRUE;
+ }
+
+ /* MSC_REQ_DONE */
+ if (regval & BIT(4))
+ req_done = TRUE;
+
+ /* Now look for interrupts on CBUS_MSC_INT2 */
+ regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x1E);
+
+ /* clear all interrupts that were raised */
+ /* even if we did not process */
+ if (regval)
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x1E, regval);
+
+ pr_err("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval);
+
+ /* received SET_INT */
+ if (regval & BIT(2)) {
+ uint8_t intr;
+ intr = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xA0);
+ pr_debug("%s: MHL_INT_0 = %02x\n", __func__, intr);
+ intr = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xA1);
+ pr_debug("%s: MHL_INT_1 = %02x\n", __func__, intr);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA0, 0xFF);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA1, 0xFF);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA2, 0xFF);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA3, 0xFF);
+ }
+
+ /* received WRITE_STAT */
+ if (regval & BIT(3)) {
+ uint8_t stat;
+ stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB0);
+ pr_err("%s: MHL_STATUS_0 = %02x\n", __func__, stat);
+ stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB1);
+ pr_err("%s: MHL_STATUS_1 = %02x\n", __func__, stat);
+
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB0, 0xFF);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB1, 0xFF);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB2, 0xFF);
+ mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB3, 0xFF);
+ }
+
+ /* received MSC_MSG */
+ if (msc_msg_recved) {
+ /*mhl msc recv msc msg*/
+ if (rc)
+ pr_err("MHL: mhl msc recv msc msg failed(%d)!\n", rc);
+ }
+
+ return;
+}
+
+static irqreturn_t mhl_tx_isr(int irq, void *dev_id)
+{
+ /*
+ * Check discovery interrupt
+ * if not yet connected
+ */
+ pr_debug("MHL: Current POWER state is [0x%x]\n",
+ mhl_msm_state->cur_state);
+ /*
+ * Check RGND, MHL_EST, CBUS_LOCKOUT, SCDT
+ * interrupts. In D3, we get only RGND
+ */
+ int_4_isr();
+
+ pr_debug("MHL: Current POWER state is [0x%x]\n",
+ mhl_msm_state->cur_state);
+ if (mhl_msm_state->cur_state == POWER_STATE_D0_MHL) {
+ /*
+ * If int_4_isr() didn't move the tx to D3
+ * on disconnect, continue to check other
+ * interrupt sources.
+ */
+ int_5_isr();
+
+ /*
+ * Check for any peer messages for DCAP_CHG etc
+ * Dispatch to have the CBUS module working only
+ * once connected.
+ */
+ mhl_cbus_isr();
+ int_1_isr();
+ }
+ return IRQ_HANDLED;
+}
+
+static void __exit mhl_msm_exit(void)
+{
+ pr_warn("MHL: Exiting, Bye\n");
+ /*
+ * Delete driver if i2c client structure is NULL
+ */
+ i2c_del_driver(&mhl_sii_i2c_driver);
+ if (!mhl_msm_state) {
+ kfree(mhl_msm_state);
+ mhl_msm_state = NULL;
+ }
+}
+
+module_init(mhl_msm_init);
+module_exit(mhl_msm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MHL SII 8334 TX driver");
diff --git a/drivers/video/msm/mhl/mhl_8334.h b/drivers/video/msm/mhl/mhl_8334.h
new file mode 100644
index 0000000..c1d9030
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_8334.h
@@ -0,0 +1,74 @@
+/* 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 __MHL_MSM_H__
+#define __MHL_MSM_H__
+
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <mach/board.h>
+
+#include "mhl_devcap.h"
+#include "mhl_defs.h"
+
+#define GPIO_MHL_RESET 15
+#define GPIO_MHL_INT 4
+
+#define MHL_DEVICE_NAME "sii8334"
+#define MHL_DRIVER_NAME "sii8334"
+
+#define HPD_UP 1
+#define HPD_DOWN 0
+
+struct mhl_msm_state_t {
+ struct i2c_client *i2c_client;
+ struct i2c_driver *i2c_driver;
+ uint8_t cur_state;
+ uint8_t chip_rev_id;
+ struct msm_mhl_platform_data *mhl_data;
+};
+
+enum {
+ TX_PAGE_TPI = 0x00,
+ TX_PAGE_L0 = 0x01,
+ TX_PAGE_L1 = 0x02,
+ TX_PAGE_2 = 0x03,
+ TX_PAGE_3 = 0x04,
+ TX_PAGE_CBUS = 0x05,
+ TX_PAGE_DDC_EDID = 0x06,
+ TX_PAGE_DDC_SEGM = 0x07,
+};
+
+enum mhl_st_type {
+ POWER_STATE_D0_NO_MHL = 0,
+ POWER_STATE_D0_MHL = 2,
+ POWER_STATE_D3 = 3,
+};
+
+enum {
+ DEV_PAGE_TPI_0 = (0x72),
+ DEV_PAGE_TX_L0_0 = (0x72),
+ DEV_PAGE_TPI_1 = (0x76),
+ DEV_PAGE_TX_L0_1 = (0x76),
+ DEV_PAGE_TX_L1_0 = (0x7A),
+ DEV_PAGE_TX_L1_1 = (0x7E),
+ DEV_PAGE_TX_2_0 = (0x92),
+ DEV_PAGE_TX_2_1 = (0x96),
+ DEV_PAGE_TX_3_0 = (0x9A),
+ DEV_PAGE_TX_3_1 = (0x9E),
+ DEV_PAGE_CBUS = (0xC8),
+ DEV_PAGE_DDC_EDID = (0xA0),
+ DEV_PAGE_DDC_SEGM = (0x60),
+};
+
+#endif /* __MHL_MSM_H__ */
diff --git a/drivers/video/msm/mhl/mhl_defs.h b/drivers/video/msm/mhl/mhl_defs.h
new file mode 100644
index 0000000..094874e
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_defs.h
@@ -0,0 +1,222 @@
+/* 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 __MHL_SPEC_DEFS_H__
+#define __MHL_SPEC_DEFS_H__
+
+enum DevCapOffset_e {
+ DEVCAP_OFFSET_DEV_STATE = 0x00,
+ DEVCAP_OFFSET_MHL_VERSION = 0x01,
+ DEVCAP_OFFSET_DEV_CAT = 0x02,
+ DEVCAP_OFFSET_ADOPTER_ID_H = 0x03,
+ DEVCAP_OFFSET_ADOPTER_ID_L = 0x04,
+ DEVCAP_OFFSET_VID_LINK_MODE = 0x05,
+ DEVCAP_OFFSET_AUD_LINK_MODE = 0x06,
+ DEVCAP_OFFSET_VIDEO_TYPE = 0x07,
+ DEVCAP_OFFSET_LOG_DEV_MAP = 0x08,
+ DEVCAP_OFFSET_BANDWIDTH = 0x09,
+ DEVCAP_OFFSET_FEATURE_FLAG = 0x0A,
+ DEVCAP_OFFSET_DEVICE_ID_H = 0x0B,
+ DEVCAP_OFFSET_DEVICE_ID_L = 0x0C,
+ DEVCAP_OFFSET_SCRATCHPAD_SIZE = 0x0D,
+ DEVCAP_OFFSET_INT_STAT_SIZE = 0x0E,
+ DEVCAP_OFFSET_RESERVED = 0x0F,
+ /* this one must be last */
+ DEVCAP_SIZE
+};
+
+#ifndef __MHL_MSM_8334_REGS_H__
+#define __MHL_MSM_8334_REGS_H__
+
+#define BIT0 0x01
+#define BIT1 0x02
+#define BIT2 0x04
+#define BIT3 0x08
+#define BIT4 0x10
+#define BIT5 0x20
+#define BIT6 0x40
+#define BIT7 0x80
+
+#define LOW 0
+#define HIGH 1
+
+#define MAX_PAGES 8
+#endif
+
+
+/* Version that this chip supports*/
+/* bits 4..7 */
+#define MHL_VER_MAJOR (0x01 << 4)
+/* bits 0..3 */
+#define MHL_VER_MINOR 0x01
+#define MHL_VERSION (MHL_VER_MAJOR | MHL_VER_MINOR)
+
+/*Device Category*/
+#define MHL_DEV_CATEGORY_OFFSET DEVCAP_OFFSET_DEV_CAT
+#define MHL_DEV_CATEGORY_POW_BIT (BIT4)
+
+#define MHL_DEV_CAT_SOURCE 0x02
+
+/*Video Link Mode*/
+#define MHL_DEV_VID_LINK_SUPPRGB444 0x01
+#define MHL_DEV_VID_LINK_SUPPYCBCR444 0x02
+#define MHL_DEV_VID_LINK_SUPPYCBCR422 0x04
+#define MHL_DEV_VID_LINK_SUPP_PPIXEL 0x08
+#define MHL_DEV_VID_LINK_SUPP_ISLANDS 0x10
+
+/*Audio Link Mode Support*/
+#define MHL_DEV_AUD_LINK_2CH 0x01
+#define MHL_DEV_AUD_LINK_8CH 0x02
+
+
+/*Feature Flag in the devcap*/
+#define MHL_DEV_FEATURE_FLAG_OFFSET DEVCAP_OFFSET_FEATURE_FLAG
+/* Dongles have freedom to not support RCP */
+#define MHL_FEATURE_RCP_SUPPORT BIT0
+/* Dongles have freedom to not support RAP */
+#define MHL_FEATURE_RAP_SUPPORT BIT1
+/* Dongles have freedom to not support SCRATCHPAD */
+#define MHL_FEATURE_SP_SUPPORT BIT2
+
+/*Logical Dev Map*/
+#define MHL_DEV_LD_DISPLAY (0x01 << 0)
+#define MHL_DEV_LD_VIDEO (0x01 << 1)
+#define MHL_DEV_LD_AUDIO (0x01 << 2)
+#define MHL_DEV_LD_MEDIA (0x01 << 3)
+#define MHL_DEV_LD_TUNER (0x01 << 4)
+#define MHL_DEV_LD_RECORD (0x01 << 5)
+#define MHL_DEV_LD_SPEAKER (0x01 << 6)
+#define MHL_DEV_LD_GUI (0x01 << 7)
+
+/*Bandwidth*/
+/* 225 MHz */
+#define MHL_BANDWIDTH_LIMIT 22
+
+
+#define MHL_STATUS_REG_CONNECTED_RDY 0x30
+#define MHL_STATUS_REG_LINK_MODE 0x31
+
+#define MHL_STATUS_DCAP_RDY BIT0
+
+#define MHL_STATUS_CLK_MODE_MASK 0x07
+#define MHL_STATUS_CLK_MODE_PACKED_PIXEL 0x02
+#define MHL_STATUS_CLK_MODE_NORMAL 0x03
+#define MHL_STATUS_PATH_EN_MASK 0x08
+#define MHL_STATUS_PATH_ENABLED 0x08
+#define MHL_STATUS_PATH_DISABLED 0x00
+#define MHL_STATUS_MUTED_MASK 0x10
+
+#define MHL_RCHANGE_INT 0x20
+#define MHL_DCHANGE_INT 0x21
+
+#define MHL_INT_DCAP_CHG BIT0
+#define MHL_INT_DSCR_CHG BIT1
+#define MHL_INT_REQ_WRT BIT2
+#define MHL_INT_GRT_WRT BIT3
+
+/* On INTR_1 the EDID_CHG is located at BIT 0*/
+#define MHL_INT_EDID_CHG BIT1
+
+/* This contains one nibble each - max offset */
+#define MHL_INT_AND_STATUS_SIZE 0x33
+#define MHL_SCRATCHPAD_SIZE 16
+/* manually define highest number */
+#define MHL_MAX_BUFFER_SIZE MHL_SCRATCHPAD_SIZE
+
+
+
+enum {
+ /* RCP sub-command */
+ MHL_MSC_MSG_RCP = 0x10,
+ /* RCP Acknowledge sub-command */
+ MHL_MSC_MSG_RCPK = 0x11,
+ /* RCP Error sub-command */
+ MHL_MSC_MSG_RCPE = 0x12,
+ /* Mode Change Warning sub-command */
+ MHL_MSC_MSG_RAP = 0x20,
+ /* MCW Acknowledge sub-command */
+ MHL_MSC_MSG_RAPK = 0x21,
+};
+
+#define RCPE_NO_ERROR 0x00
+#define RCPE_INEEFECTIVE_KEY_CODE 0x01
+#define RCPE_BUSY 0x02
+/* MHL spec related defines*/
+enum {
+ /* Command or Data byte acknowledge */
+ MHL_ACK = 0x33,
+ /* Command or Data byte not acknowledge */
+ MHL_NACK = 0x34,
+ /* Transaction abort */
+ MHL_ABORT = 0x35,
+ /* 0xE0 - Write one status register strip top bit */
+ MHL_WRITE_STAT = 0x60 | 0x80,
+ /* Write one interrupt register */
+ MHL_SET_INT = 0x60,
+ /* Read one register */
+ MHL_READ_DEVCAP = 0x61,
+ /* Read CBUS revision level from follower */
+ MHL_GET_STATE = 0x62,
+ /* Read vendor ID value from follower. */
+ MHL_GET_VENDOR_ID = 0x63,
+ /* Set Hot Plug Detect in follower */
+ MHL_SET_HPD = 0x64,
+ /* Clear Hot Plug Detect in follower */
+ MHL_CLR_HPD = 0x65,
+ /* Set Capture ID for downstream device. */
+ MHL_SET_CAP_ID = 0x66,
+ /* Get Capture ID from downstream device. */
+ MHL_GET_CAP_ID = 0x67,
+ /* VS command to send RCP sub-commands */
+ MHL_MSC_MSG = 0x68,
+ /* Get Vendor-Specific command error code. */
+ MHL_GET_SC1_ERRORCODE = 0x69,
+ /* Get DDC channel command error code. */
+ MHL_GET_DDC_ERRORCODE = 0x6A,
+ /* Get MSC command error code. */
+ MHL_GET_MSC_ERRORCODE = 0x6B,
+ /* Write 1-16 bytes to responder's scratchpad. */
+ MHL_WRITE_BURST = 0x6C,
+ /* Get channel 3 command error code. */
+ MHL_GET_SC3_ERRORCODE = 0x6D,
+};
+
+/* Turn content streaming ON. */
+#define MHL_RAP_CONTENT_ON 0x10
+/* Turn content streaming OFF. */
+#define MHL_RAP_CONTENT_OFF 0x11
+
+/*
+ *
+ * MHL Timings applicable to this driver.
+ *
+ */
+/* 100 - 1000 milliseconds. Per MHL 1.0 Specs */
+#define T_SRC_VBUS_CBUS_TO_STABLE (200)
+/* 20 milliseconds. Per MHL 1.0 Specs */
+#define T_SRC_WAKE_PULSE_WIDTH_1 (20)
+/* 60 milliseconds. Per MHL 1.0 Specs */
+#define T_SRC_WAKE_PULSE_WIDTH_2 (60)
+
+/* 100 - 1000 milliseconds. Per MHL 1.0 Specs */
+#define T_SRC_WAKE_TO_DISCOVER (500)
+
+#define T_SRC_VBUS_CBUS_T0_STABLE (500)
+
+/* Allow RSEN to stay low this much before reacting.*/
+#define T_SRC_RSEN_DEGLITCH (100)
+
+/* Wait this much after connection before reacting to RSEN (300-500ms)*/
+/* Per specs between 300 to 500 ms*/
+#define T_SRC_RXSENSE_CHK (400)
+
+#endif /* __MHL_SPEC_DEFS_H__ */
diff --git a/drivers/video/msm/mhl/mhl_devcap.h b/drivers/video/msm/mhl/mhl_devcap.h
new file mode 100644
index 0000000..6d01daf
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_devcap.h
@@ -0,0 +1,45 @@
+/* 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 __MHL_DEVCAP_H__
+#define __MHL_DEVCAP_H__
+
+#define SILICON_IMAGE_ADOPTER_ID 322
+#define TRANSCODER_DEVICE_ID 0x8334
+
+#define MHL_DEV_LD_AUDIO (0x01 << 2)
+#define MHL_DEV_LD_VIDEO (0x01 << 1)
+#define MHL_DEV_LD_MEDIA (0x01 << 3)
+#define MHL_DEV_LD_GUI (0x01 << 7)
+#define MHL_LOGICAL_DEVICE_MAP (MHL_DEV_LD_AUDIO |\
+ MHL_DEV_LD_VIDEO | MHL_DEV_LD_MEDIA | MHL_DEV_LD_GUI)
+
+#define DEVCAP_VAL_DEV_STATE 0
+#define DEVCAP_VAL_MHL_VERSION MHL_VERSION
+#define DEVCAP_VAL_DEV_CAT (MHL_DEV_CAT_SOURCE |\
+ MHL_DEV_CATEGORY_POW_BIT)
+#define DEVCAP_VAL_ADOPTER_ID_H (uint8_t)(SILICON_IMAGE_ADOPTER_ID >> 8)
+#define DEVCAP_VAL_ADOPTER_ID_L (uint8_t)(SILICON_IMAGE_ADOPTER_ID & 0xFF)
+#define DEVCAP_VAL_VID_LINK_MODE MHL_DEV_VID_LINK_SUPPRGB444
+#define DEVCAP_VAL_AUD_LINK_MODE MHL_DEV_AUD_LINK_2CH
+#define DEVCAP_VAL_VIDEO_TYPE 0
+#define DEVCAP_VAL_LOG_DEV_MAP MHL_LOGICAL_DEVICE_MAP
+#define DEVCAP_VAL_BANDWIDTH 0
+#define DEVCAP_VAL_FEATURE_FLAG (MHL_FEATURE_RCP_SUPPORT |\
+ MHL_FEATURE_RAP_SUPPORT | MHL_FEATURE_SP_SUPPORT)
+#define DEVCAP_VAL_DEVICE_ID_H (uint8_t)(TRANSCODER_DEVICE_ID >> 8)
+#define DEVCAP_VAL_DEVICE_ID_L (uint8_t)(TRANSCODER_DEVICE_ID & 0xFF)
+#define DEVCAP_VAL_SCRATCHPAD_SIZE MHL_SCRATCHPAD_SIZE
+#define DEVCAP_VAL_INT_STAT_SIZE MHL_INT_AND_STATUS_SIZE
+#define DEVCAP_VAL_RESERVED 0
+
+#endif /* __MHL_DEVCAP_H__ */
diff --git a/drivers/video/msm/mhl/mhl_i2c_utils.c b/drivers/video/msm/mhl/mhl_i2c_utils.c
new file mode 100644
index 0000000..596af2e
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_i2c_utils.c
@@ -0,0 +1,107 @@
+/* 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/i2c.h>
+
+#include "mhl_i2c_utils.h"
+#include "mhl_8334.h"
+
+#define DEBUG
+
+uint8_t slave_addrs[MAX_PAGES] = {
+ DEV_PAGE_TPI_0 ,
+ DEV_PAGE_TX_L0_0 ,
+ DEV_PAGE_TX_L1_0 ,
+ DEV_PAGE_TX_2_0 ,
+ DEV_PAGE_TX_3_0 ,
+ DEV_PAGE_CBUS ,
+ DEV_PAGE_DDC_EDID ,
+ DEV_PAGE_DDC_SEGM ,
+};
+
+int mhl_i2c_reg_read(uint8_t slave_addr_index, uint8_t reg_offset)
+{
+ struct i2c_msg msgs[2];
+ uint8_t buffer = 0;
+ int ret = -1;
+
+ pr_debug("MRR: Reading from slave_addr_index=[%x] and offset=[%x]\n",
+ slave_addr_index, reg_offset);
+ pr_debug("MRR: Addr slave_addr_index=[%x]\n",
+ slave_addrs[slave_addr_index]);
+
+ /* Slave addr */
+ msgs[0].addr = slave_addrs[slave_addr_index] >> 1;
+ msgs[1].addr = slave_addrs[slave_addr_index] >> 1;
+
+ /* Write Command */
+ msgs[0].flags = 0;
+ msgs[1].flags = I2C_M_RD;
+
+ /* Register offset for the next transaction */
+ msgs[0].buf = ®_offset;
+ msgs[1].buf = &buffer;
+
+ /* Offset is 1 Byte long */
+ msgs[0].len = 1;
+ msgs[1].len = 1;
+
+ ret = i2c_transfer(mhl_msm_state->i2c_client->adapter, msgs, 2);
+ if (ret < 1) {
+ pr_err("I2C READ FAILED=[%d]\n", ret);
+ return -EACCES;
+ }
+ pr_err("Buffer is [%x]\n", buffer);
+ return buffer;
+}
+
+
+int mhl_i2c_reg_write(uint8_t slave_addr_index, uint8_t reg_offset,
+ uint8_t value)
+{
+ return mhl_i2c_reg_write_cmds(slave_addr_index, reg_offset, &value, 1);
+}
+
+int mhl_i2c_reg_write_cmds(uint8_t slave_addr_index, uint8_t reg_offset,
+ uint8_t *value, uint16_t count)
+{
+ struct i2c_msg msgs[1];
+ uint8_t data[2];
+ int status = -EACCES;
+
+ msgs[0].addr = slave_addrs[slave_addr_index] >> 1;
+ msgs[0].flags = 0;
+ msgs[0].len = 2;
+ msgs[0].buf = data;
+ data[0] = reg_offset;
+ data[1] = *value;
+
+ status = i2c_transfer(mhl_msm_state->i2c_client->adapter, msgs, 1);
+ if (status < 1) {
+ pr_err("I2C WRITE FAILED=[%d]\n", status);
+ return -EACCES;
+ }
+
+ return status;
+}
+
+void mhl_i2c_reg_modify(uint8_t slave_addr_index, uint8_t reg_offset,
+ uint8_t mask, uint8_t val)
+{
+ uint8_t temp;
+
+ temp = mhl_i2c_reg_read(slave_addr_index, reg_offset);
+ temp &= (~mask);
+ temp |= (mask & val);
+ mhl_i2c_reg_write(slave_addr_index, reg_offset, temp);
+}
+
diff --git a/drivers/video/msm/mhl/mhl_i2c_utils.h b/drivers/video/msm/mhl/mhl_i2c_utils.h
new file mode 100644
index 0000000..76498d4
--- /dev/null
+++ b/drivers/video/msm/mhl/mhl_i2c_utils.h
@@ -0,0 +1,39 @@
+/* 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 __MHL_I2C_UTILS_H__
+#define __MHL_I2C_UTILS_H__
+
+#include <linux/i2c.h>
+#include <linux/types.h>
+
+#include "mhl_defs.h"
+
+/*
+ * I2C command to the adapter to append
+ * the buffer from next msg to this one.
+ */
+#define I2C_M_APPND_NXT_WR 0x0002
+
+extern uint8_t slave_addrs[MAX_PAGES];
+extern struct mhl_msm_state_t *mhl_msm_state;
+
+int mhl_i2c_reg_read(uint8_t slave_addr_index, uint8_t reg_offset);
+int mhl_i2c_reg_write(uint8_t slave_addr_index, uint8_t reg_offset,
+ uint8_t value);
+int mhl_i2c_reg_write_cmds(uint8_t slave_addr_index, uint8_t reg_offset,
+ uint8_t *value, uint16_t count);
+void mhl_i2c_reg_modify(uint8_t slave_addr_index, uint8_t reg_offset,
+ uint8_t mask, uint8_t val);
+
+#endif /* __MHL_I2C_UTILS_H__ */
diff --git a/drivers/video/msm/mhl_api.h b/drivers/video/msm/mhl_api.h
index 627f802..a4364ea 100644
--- a/drivers/video/msm/mhl_api.h
+++ b/drivers/video/msm/mhl_api.h
@@ -14,7 +14,7 @@
#ifndef __MHL_API_H__
#define __MHL_API_H__
-#ifdef CONFIG_FB_MSM_HDMI_MHL
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
bool mhl_is_connected(void);
#else
static bool mhl_is_connected(void)
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 76653ec..c6b0440 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -3070,6 +3070,10 @@
break;
}
break;
+ case mdp_op_qseed_cfg:
+ ret = mdp4_qseed_cfg((struct mdp_qseed_cfg_data *)
+ &pp_ptr->data.qseed_cfg_data);
+ break;
#endif
default:
pr_warn("Unsupported request to MDP_PP IOCTL.\n");
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index b4161dd..a8ccebf 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -60,7 +60,7 @@
#define DDL_ENC_MIN_DPB_BUFFERS 2
#define DDL_ENC_MAX_DPB_BUFFERS 4
-#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE (DDL_KILO_BYTE(8))
+#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE (DDL_KILO_BYTE(4))
#define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
#define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
#define DDL_FW_H264ENC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(20))
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index b720800..62f0976 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -1000,7 +1000,8 @@
(decoder->frame_size.scan_lines ==
decoder->client_frame_size.scan_lines) &&
(decoder->frame_size.stride ==
- decoder->client_frame_size.stride))
+ decoder->client_frame_size.stride) &&
+ decoder->progressive_only)
need_reconfig = false;
}
return need_reconfig;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 6aa7451..126698c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -348,7 +348,7 @@
void ddl_fw_release(void)
{
-
+ res_trk_close_secure_session();
}
void ddl_set_core_start_time(const char *func_name, u32 index)
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 90c98d7..e94a302 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
@@ -673,6 +673,15 @@
return 0;
}
+int res_trk_check_for_sec_session(void)
+{
+ int rc;
+ mutex_lock(&resource_context.secure_lock);
+ rc = resource_context.secure_session;
+ mutex_unlock(&resource_context.secure_lock);
+ return rc;
+}
+
int res_trk_get_mem_type(void)
{
int mem_type = -1;
@@ -783,43 +792,37 @@
return 0;
}
-int res_trk_check_for_sec_session()
-{
- int rc;
- mutex_lock(&resource_context.secure_lock);
- rc = (resource_context.secure_session) ? -EBUSY : 0;
- mutex_unlock(&resource_context.secure_lock);
- return rc;
-}
-
void res_trk_secure_unset(void)
{
mutex_lock(&resource_context.secure_lock);
- resource_context.secure_session = 0;
+ resource_context.secure_session--;
mutex_unlock(&resource_context.secure_lock);
}
void res_trk_secure_set(void)
{
mutex_lock(&resource_context.secure_lock);
- resource_context.secure_session = 1;
+ resource_context.secure_session++;
mutex_unlock(&resource_context.secure_lock);
}
int res_trk_open_secure_session()
{
int rc;
- mutex_lock(&resource_context.secure_lock);
- rc = res_trk_enable_iommu_clocks();
- if (rc) {
- pr_err("IOMMU clock enabled failed while open");
- goto error_open;
+ if (res_trk_check_for_sec_session() == 1) {
+ mutex_lock(&resource_context.secure_lock);
+ pr_err("Securing...\n");
+ rc = res_trk_enable_iommu_clocks();
+ if (rc) {
+ pr_err("IOMMU clock enabled failed while open");
+ goto error_open;
+ }
+ msm_ion_secure_heap(ION_HEAP(resource_context.memtype));
+ msm_ion_secure_heap(ION_HEAP(resource_context.cmd_mem_type));
+ res_trk_disable_iommu_clocks();
+ mutex_unlock(&resource_context.secure_lock);
}
- msm_ion_secure_heap(ION_HEAP(resource_context.memtype));
- msm_ion_secure_heap(ION_HEAP(resource_context.cmd_mem_type));
- res_trk_disable_iommu_clocks();
- mutex_unlock(&resource_context.secure_lock);
return 0;
error_open:
mutex_unlock(&resource_context.secure_lock);
@@ -829,17 +832,19 @@
int res_trk_close_secure_session()
{
int rc;
- mutex_lock(&resource_context.secure_lock);
- rc = res_trk_enable_iommu_clocks();
- if (rc) {
- pr_err("IOMMU clock enabled failed while close");
- goto error_close;
+ if (res_trk_check_for_sec_session() == 1) {
+ pr_err("Unsecuring....\n");
+ mutex_lock(&resource_context.secure_lock);
+ rc = res_trk_enable_iommu_clocks();
+ if (rc) {
+ pr_err("IOMMU clock enabled failed while close");
+ goto error_close;
+ }
+ msm_ion_unsecure_heap(ION_HEAP(resource_context.memtype));
+ msm_ion_unsecure_heap(ION_HEAP(resource_context.cmd_mem_type));
+ res_trk_disable_iommu_clocks();
+ mutex_unlock(&resource_context.secure_lock);
}
- msm_ion_unsecure_heap(ION_HEAP(resource_context.memtype));
- msm_ion_unsecure_heap(ION_HEAP(resource_context.cmd_mem_type));
- res_trk_disable_iommu_clocks();
- resource_context.secure_session = 0;
- mutex_unlock(&resource_context.secure_lock);
return 0;
error_close:
mutex_unlock(&resource_context.secure_lock);
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 61deb8d..420fc19 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -869,7 +869,7 @@
client_ctx->h264_mv_ion_handle = ion_import_fd(
client_ctx->user_ion_client,
vcd_h264_mv_buffer->pmem_fd);
- if (!client_ctx->h264_mv_ion_handle) {
+ if (IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
ERR("%s(): get_ION_handle failed\n", __func__);
goto import_ion_error;
}
@@ -916,12 +916,16 @@
else
return true;
ion_map_error:
- if (vcd_h264_mv_buffer->kernel_virtual_addr)
+ if (vcd_h264_mv_buffer->kernel_virtual_addr) {
ion_unmap_kernel(client_ctx->user_ion_client,
client_ctx->h264_mv_ion_handle);
- if (client_ctx->h264_mv_ion_handle)
+ vcd_h264_mv_buffer->kernel_virtual_addr = NULL;
+ }
+ if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
ion_free(client_ctx->user_ion_client,
client_ctx->h264_mv_ion_handle);
+ client_ctx->h264_mv_ion_handle = NULL;
+ }
import_ion_error:
return false;
}
@@ -990,7 +994,7 @@
vcd_status = vcd_set_property(client_ctx->vcd_handle,
&vcd_property_hdr, &h264_mv_buffer_size);
- if (client_ctx->h264_mv_ion_handle != NULL) {
+ if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
ion_unmap_kernel(client_ctx->user_ion_client,
client_ctx->h264_mv_ion_handle);
ion_unmap_iommu(client_ctx->user_ion_client,
@@ -999,6 +1003,7 @@
VIDEO_MAIN_POOL);
ion_free(client_ctx->user_ion_client,
client_ctx->h264_mv_ion_handle);
+ client_ctx->h264_mv_ion_handle = NULL;
}
if (vcd_status)
@@ -2034,29 +2039,38 @@
return true;
}
-struct video_client_ctx *vid_dec_open_client(void)
+int vid_dec_open_client(struct video_client_ctx **vid_clnt_ctx, int flags)
{
+ int rc = 0;
s32 client_index;
- struct video_client_ctx *client_ctx;
- u32 vcd_status = VCD_ERR_FAIL;
+ struct video_client_ctx *client_ctx = NULL;
u8 client_count;
+ if (!vid_clnt_ctx) {
+ ERR("Invalid input\n");
+ return -EINVAL;
+ }
+ *vid_clnt_ctx = NULL;
client_count = vcd_get_num_of_clients();
if (client_count == VIDC_MAX_NUM_CLIENTS) {
ERR("ERROR : vid_dec_open() max number of clients"
"limit reached\n");
+ rc = -ENOMEM;
goto client_failure;
}
DBG(" Virtual Address of ioremap is %p\n", vid_dec_device_p->virt_base);
if (!vid_dec_device_p->num_clients) {
- if (!vidc_load_firmware())
+ if (!vidc_load_firmware()) {
+ rc = -ENOMEM;
goto client_failure;
+ }
}
client_index = vid_dec_get_empty_client_index();
- if (client_index < 0) {
- ERR("%s() : No free clients client_index < 0\n", __func__);
+ if (client_index == -1) {
+ ERR("%s() : No free clients client_index == -1\n", __func__);
+ rc = -ENOMEM;
goto client_failure;
}
client_ctx = &vid_dec_device_p->vdec_clients[client_index];
@@ -2074,72 +2088,75 @@
client_ctx->user_ion_client = vcd_get_ion_client();
if (!client_ctx->user_ion_client) {
ERR("vcd_open ion client get failed");
+ rc = -ENOMEM;
goto client_failure;
}
}
- vcd_status = vcd_open(vid_dec_device_p->device_handle, true,
- vid_dec_vcd_cb, client_ctx);
- if (!vcd_status) {
+ rc = vcd_open(vid_dec_device_p->device_handle, true,
+ vid_dec_vcd_cb, client_ctx, flags);
+ if (!rc) {
wait_for_completion(&client_ctx->event);
if (client_ctx->event_status) {
ERR("callback for vcd_open returned error: %u",
client_ctx->event_status);
+ rc = -ENODEV;
goto client_failure;
}
} else {
- ERR("vcd_open returned error: %u", vcd_status);
+ ERR("vcd_open returned error: %u", rc);
goto client_failure;
}
client_ctx->seq_header_set = false;
- return client_ctx;
+ *vid_clnt_ctx = client_ctx;
client_failure:
- return NULL;
+ return rc;
}
static int vid_dec_open_secure(struct inode *inode, struct file *file)
{
+ int rc = 0;
+ struct video_client_ctx *client_ctx;
mutex_lock(&vid_dec_device_p->lock);
- if (res_trk_check_for_sec_session() || vcd_get_num_of_clients()) {
- ERR("Secure session present return failure\n");
- mutex_unlock(&vid_dec_device_p->lock);
- return -ENODEV;
- }
- res_trk_secure_set();
- file->private_data = vid_dec_open_client();
- if (!file->private_data) {
+ rc = vid_dec_open_client(&client_ctx, VCD_CP_SESSION);
+ if (rc)
+ goto error;
+ if (!client_ctx) {
+ rc = -ENOMEM;
goto error;
}
+ file->private_data = client_ctx;
if (res_trk_open_secure_session()) {
ERR("Secure session operation failure\n");
+ rc = -EACCES;
goto error;
}
mutex_unlock(&vid_dec_device_p->lock);
return 0;
-
error:
- res_trk_secure_unset();
mutex_unlock(&vid_dec_device_p->lock);
- return -ENODEV;
-
+ return rc;
}
static int vid_dec_open(struct inode *inode, struct file *file)
{
+ int rc = 0;
+ struct video_client_ctx *client_ctx;
INFO("msm_vidc_dec: Inside %s()", __func__);
mutex_lock(&vid_dec_device_p->lock);
- if (res_trk_check_for_sec_session()) {
- ERR("Secure session present return failure\n");
+ rc = vid_dec_open_client(&client_ctx, 0);
+ if (rc) {
mutex_unlock(&vid_dec_device_p->lock);
- return -ENODEV;
+ return rc;
}
- file->private_data = vid_dec_open_client();
- if (!file->private_data) {
+ if (!client_ctx) {
mutex_unlock(&vid_dec_device_p->lock);
- return -ENODEV;
+ return -ENOMEM;
}
+
+ file->private_data = client_ctx;
mutex_unlock(&vid_dec_device_p->lock);
- return 0;
+ return rc;
}
static int vid_dec_release_secure(struct inode *inode, struct file *file)
@@ -2149,7 +2166,6 @@
INFO("msm_vidc_dec: Inside %s()", __func__);
vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
- res_trk_close_secure_session();
vid_dec_close_client(client_ctx);
vidc_release_firmware();
#ifndef USE_RES_TRACKER
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 93b1848..d93d07e 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -521,7 +521,7 @@
{
s32 client_index;
struct video_client_ctx *client_ctx;
- u32 vcd_status = VCD_ERR_FAIL;
+ int rc = 0;
u8 client_count = 0;
INFO("\n msm_vidc_enc: Inside %s()", __func__);
@@ -530,10 +530,9 @@
stop_cmd = 0;
client_count = vcd_get_num_of_clients();
- if (client_count == VIDC_MAX_NUM_CLIENTS ||
- res_trk_check_for_sec_session()) {
+ if (client_count == VIDC_MAX_NUM_CLIENTS) {
ERR("ERROR : vid_enc_open() max number of clients"
- "limit reached or secure session is open\n");
+ "limit reached\n");
mutex_unlock(&vid_enc_device_p->lock);
return -ENODEV;
}
@@ -568,11 +567,11 @@
return -EFAULT;
}
}
- vcd_status = vcd_open(vid_enc_device_p->device_handle, false,
- vid_enc_vcd_cb, client_ctx);
+ rc = vcd_open(vid_enc_device_p->device_handle, false,
+ vid_enc_vcd_cb, client_ctx, 0);
client_ctx->stop_msg = 0;
- if (!vcd_status) {
+ if (!rc) {
wait_for_completion(&client_ctx->event);
if (client_ctx->event_status) {
ERR("callback for vcd_open returned error: %u",
@@ -581,13 +580,13 @@
return -EFAULT;
}
} else {
- ERR("vcd_open returned error: %u", vcd_status);
+ ERR("vcd_open returned error: %u", rc);
mutex_unlock(&vid_enc_device_p->lock);
- return -EFAULT;
+ return rc;
}
file->private_data = client_ctx;
mutex_unlock(&vid_enc_device_p->lock);
- return 0;
+ return rc;
}
static int vid_enc_release(struct inode *inode, struct file *file)
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index dda81ed..6fdb1c6 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -285,14 +285,14 @@
if (unlikely(rc)) {
ERR("%s() :request_irq failed\n", __func__);
- goto error_vidc_platfom_register;
+ goto error_vidc_request_irq;
}
res_trk_init(vidc_device_p->device, vidc_device_p->irq);
vidc_timer_wq = create_singlethread_workqueue("vidc_timer_wq");
if (!vidc_timer_wq) {
ERR("%s: create workque failed\n", __func__);
rc = -ENOMEM;
- goto error_vidc_platfom_register;
+ goto error_vidc_create_workqueue;
}
DBG("Disabling IRQ in %s()\n", __func__);
disable_irq_nosync(vidc_device_p->irq);
@@ -315,6 +315,10 @@
#endif
return 0;
+error_vidc_create_workqueue:
+ free_irq(vidc_device_p->irq, vidc_device_p->device);
+error_vidc_request_irq:
+ platform_driver_unregister(&msm_vidc_720p_platform_driver);
error_vidc_platfom_register:
cdev_del(&(vidc_device_p->cdev));
error_vidc_cdev_add:
@@ -417,16 +421,21 @@
buf_addr_table[i].client_data);
buf_addr_table[i].client_data = NULL;
}
- if (buf_addr_table[i].buff_ion_handle) {
- ion_unmap_kernel(client_ctx->user_ion_client,
- buf_addr_table[i].buff_ion_handle);
- ion_unmap_iommu(client_ctx->user_ion_client,
- buf_addr_table[i].buff_ion_handle,
- VIDEO_DOMAIN,
- VIDEO_MAIN_POOL);
- ion_free(client_ctx->user_ion_client,
- buf_addr_table[i].buff_ion_handle);
- buf_addr_table[i].buff_ion_handle = NULL;
+ if (!IS_ERR_OR_NULL(buf_addr_table[i].buff_ion_handle)) {
+ if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ buf_addr_table[i].
+ buff_ion_handle);
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ buf_addr_table[i].
+ buff_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ ion_free(client_ctx->user_ion_client,
+ buf_addr_table[i].
+ buff_ion_handle);
+ buf_addr_table[i].buff_ion_handle = NULL;
+ }
}
}
if (client_ctx->vcd_h264_mv_buffer.client_data) {
@@ -434,16 +443,18 @@
client_ctx->vcd_h264_mv_buffer.client_data);
client_ctx->vcd_h264_mv_buffer.client_data = NULL;
}
- if (client_ctx->h264_mv_ion_handle) {
- ion_unmap_kernel(client_ctx->user_ion_client,
- client_ctx->h264_mv_ion_handle);
- ion_unmap_iommu(client_ctx->user_ion_client,
- client_ctx->h264_mv_ion_handle,
- VIDEO_DOMAIN,
- VIDEO_MAIN_POOL);
- ion_free(client_ctx->user_ion_client,
- client_ctx->h264_mv_ion_handle);
- client_ctx->h264_mv_ion_handle = NULL;
+ if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
+ if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ client_ctx->h264_mv_ion_handle = NULL;
+ }
}
bail_out_cleanup:
return;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
index e0ef3af..7aadc2b 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -74,25 +74,106 @@
}
EXPORT_SYMBOL(vcd_term);
+struct client_security_info {
+ int secure_enc;
+ int secure_dec;
+ int non_secure_enc;
+ int non_secure_dec;
+};
+
+static int vcd_get_clients_security_info(struct client_security_info *sec_info)
+{
+ struct vcd_drv_ctxt *drv_ctxt;
+ struct vcd_clnt_ctxt *cctxt;
+ int count = 0;
+ if (!sec_info) {
+ VCD_MSG_ERROR("Invalid argument\n");
+ return -EINVAL;
+ }
+ memset(sec_info, 0 , sizeof(*sec_info));
+ drv_ctxt = vcd_get_drv_context();
+ mutex_lock(&drv_ctxt->dev_mutex);
+ cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+ while (cctxt) {
+ if (cctxt->secure && cctxt->decoding)
+ sec_info->secure_dec++;
+ else if (cctxt->secure && !cctxt->decoding)
+ sec_info->secure_enc++;
+ else if (!cctxt->secure && cctxt->decoding)
+ sec_info->non_secure_dec++;
+ else
+ sec_info->non_secure_enc++;
+ count++;
+ cctxt = cctxt->next;
+ }
+ mutex_unlock(&drv_ctxt->dev_mutex);
+ return count;
+}
+
+static int is_session_invalid(u32 decoding, u32 flags)
+{
+ int is_secure;
+ struct client_security_info sec_info;
+ int client_count = 0;
+ int secure_session_running = 0;
+ is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
+ client_count = vcd_get_clients_security_info(&sec_info);
+ secure_session_running = (sec_info.secure_enc > 0) ||
+ (sec_info.secure_dec > 0);
+ if (!decoding && is_secure) {
+ if ((sec_info.secure_dec == 1))
+ VCD_MSG_LOW("SE-SD: SUCCESS\n");
+ else {
+ VCD_MSG_LOW("SE is permitted only with SD: FAILURE\n");
+ return -EACCES;
+ }
+ } else if (!decoding && !is_secure) {
+ if (secure_session_running) {
+ VCD_MSG_LOW("SD-NSE: FAILURE\n");
+ VCD_MSG_LOW("SE-NSE: FAILURE\n");
+ return -EACCES;
+ }
+ } else if (decoding && is_secure) {
+ if (client_count > 0) {
+ VCD_MSG_LOW("S/NS-SD: FAILURE\n");
+ if (sec_info.secure_enc > 0 ||
+ sec_info.non_secure_enc > 0) {
+ return -EAGAIN;
+ }
+ return -EACCES;
+ }
+ } else {
+ if (sec_info.secure_dec > 0) {
+ VCD_MSG_LOW("SD-NSD: FAILURE\n");
+ return -EACCES;
+ }
+ }
+ return 0;
+}
+
u32 vcd_open(s32 driver_handle, u32 decoding,
void (*callback) (u32 event, u32 status, void *info, size_t sz,
void *handle, void *const client_data),
- void *client_data)
+ void *client_data, int flags)
{
- u32 rc = VCD_S_SUCCESS;
+ u32 rc = 0;
struct vcd_drv_ctxt *drv_ctxt;
-
+ struct vcd_clnt_ctxt *cctxt;
+ int is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
VCD_MSG_MED("vcd_open:");
if (!callback) {
VCD_MSG_ERROR("Bad parameters");
-
- return VCD_ERR_ILLEGAL_PARM;
+ return -EINVAL;
}
- if (res_trk_check_for_sec_session() && vcd_get_num_of_clients()) {
- VCD_MSG_ERROR("Secure session in progress");
- return VCD_ERR_BAD_STATE;
+ rc = is_session_invalid(decoding, flags);
+ if (rc) {
+ VCD_MSG_ERROR("Invalid Session: is_decoder: %d, secure: %d\n",
+ decoding, flags);
+ return rc;
}
+ if (is_secure)
+ res_trk_secure_set();
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
@@ -100,17 +181,22 @@
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
open(drv_ctxt, driver_handle, decoding, callback,
client_data);
+ if (rc) {
+ rc = -ENODEV;
+ }
} else {
VCD_MSG_ERROR("Unsupported API in device state %d",
drv_ctxt->dev_state.state);
-
- rc = VCD_ERR_BAD_STATE;
+ rc = -EPERM;
}
+ if (!rc) {
+ cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
+ cctxt->secure = is_secure;
+ } else if (is_secure)
+ res_trk_secure_unset();
mutex_unlock(&drv_ctxt->dev_mutex);
-
return rc;
-
}
EXPORT_SYMBOL(vcd_open);
@@ -120,7 +206,7 @@
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
-
+ int is_secure = 0;
VCD_MSG_MED("vcd_close:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
@@ -129,6 +215,7 @@
return VCD_ERR_BAD_HANDLE;
}
+ is_secure = cctxt->secure;
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (drv_ctxt->dev_state.state_table->ev_hdlr.close) {
@@ -141,6 +228,8 @@
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
+ if (is_secure)
+ res_trk_secure_unset();
return rc;
}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 86e9ff6..0d5ba9c 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -342,6 +342,7 @@
static u32 vcd_flush_in_eos(struct vcd_clnt_ctxt *cctxt,
u32 mode)
{
+ u32 rc = VCD_S_SUCCESS;
VCD_MSG_LOW("vcd_flush_in_eos:");
if (mode > VCD_FLUSH_ALL || !mode) {
@@ -351,10 +352,18 @@
}
VCD_MSG_MED("Flush mode requested %d", mode);
+ if (!(cctxt->status.frame_submitted) &&
+ (!cctxt->decoding)) {
+ rc = vcd_flush_buffers(cctxt, mode);
+ if (!VCD_FAILED(rc)) {
+ VCD_MSG_HIGH("All buffers are flushed");
+ cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
+ vcd_send_flush_done(cctxt, VCD_S_SUCCESS);
+ }
+ } else
+ cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
- cctxt->status.mask |= (mode & VCD_FLUSH_ALL);
-
- return VCD_S_SUCCESS;
+ return rc;
}
static u32 vcd_flush_in_invalid(struct vcd_clnt_ctxt *cctxt,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index b8438e1..e33c8cd 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -210,6 +210,7 @@
struct vcd_clnt_ctxt *next;
u32 meta_mode;
int perf_set_by_client;
+ int secure;
};
#define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
new file mode 100644
index 0000000..0104abc
--- /dev/null
+++ b/include/linux/iopoll.h
@@ -0,0 +1,88 @@
+/*
+ * 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 _LINUX_IOPOLL_H
+#define _LINUX_IOPOLL_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <asm-generic/errno.h>
+#include <asm/io.h>
+
+/**
+ * readl_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in uS (0 tight-loops)
+ * @timeout_us: Timeout in uS, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ */
+#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
+({ \
+ unsigned long timeout = jiffies + usecs_to_jiffies(timeout_us); \
+ might_sleep_if(timeout_us); \
+ for (;;) { \
+ (val) = readl(addr); \
+ if ((cond) || (timeout_us && time_after(jiffies, timeout))) \
+ break; \
+ if (sleep_us) \
+ usleep_range(1, sleep_us); \
+ } \
+ (cond) ? 0 : -ETIMEDOUT; \
+})
+
+/**
+ * readl_poll - Periodically poll an address until a condition is met
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in uS (0 tight-loops)
+ *
+ * Must not be called from atomic context if sleep_us is used.
+ */
+#define readl_poll(addr, val, cond, sleep_us) \
+ readl_poll_timeout(addr, val, cond, sleep_us, 0)
+
+/**
+ * readl_tight_poll_timeout - Tight-loop on an address until a condition is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @timeout_us: Timeout in uS, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if timeout_us is used.
+ */
+#define readl_tight_poll_timeout(addr, val, cond, timeout_us) \
+ readl_poll_timeout(addr, val, cond, 0, timeout_us)
+
+/**
+ * readl_tight_poll - Tight-loop on an address until a condition is met
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ *
+ * May be called from atomic context.
+ */
+#define readl_tight_poll(addr, val, cond) \
+ readl_poll_timeout(addr, val, cond, 0, 0)
+
+#endif /* _LINUX_IOPOLL_H */
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 0df513b..bdd6b2a 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -36,6 +36,7 @@
/* Look up a kernel symbol and return it in a text buffer. */
extern int sprint_symbol(char *buffer, unsigned long address);
+extern int sprint_symbol_no_offset(char *buffer, unsigned long address);
extern int sprint_backtrace(char *buffer, unsigned long address);
/* Look up a kernel symbol and print it to the kernel messages. */
@@ -80,6 +81,12 @@
return 0;
}
+static inline int sprint_symbol_no_offset(char *buffer, unsigned long addr)
+{
+ *buffer = '\0';
+ return 0;
+}
+
static inline int sprint_backtrace(char *buffer, unsigned long addr)
{
*buffer = '\0';
diff --git a/include/linux/mfd/pm8xxx/pm8xxx-adc.h b/include/linux/mfd/pm8xxx/pm8xxx-adc.h
index d2b1cfc..84f8e03 100644
--- a/include/linux/mfd/pm8xxx/pm8xxx-adc.h
+++ b/include/linux/mfd/pm8xxx/pm8xxx-adc.h
@@ -51,6 +51,10 @@
CHANNEL_MPP_1,
CHANNEL_MPP_2,
CHANNEL_BATT_THERM,
+ /* PM8018 ADC Arbiter uses a single channel on AMUX8
+ * to read either Batt_id or Batt_therm.
+ */
+ CHANNEL_BATT_ID_THERM = CHANNEL_BATT_THERM,
CHANNEL_BATT_ID,
CHANNEL_USBIN,
CHANNEL_DIE_TEMP,
diff --git a/include/linux/mfd/wcd9xxx/wcd9304_registers.h b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
index 65e4728..70902bc 100644
--- a/include/linux/mfd/wcd9xxx/wcd9304_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
@@ -517,7 +517,7 @@
#define SITAR_A_CDC_CLK_TX_I2S_CTL (0x306)
#define SITAR_A_CDC_CLK_TX_I2S_CTL__POR (0x00000003)
#define SITAR_A_CDC_CLK_OTHR_RESET_CTL (0x307)
-#define SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR (0x00000010)
#define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL (0x308)
#define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR (0x00000000)
#define SITAR_A_CDC_CLK_OTHR_CTL (0x30A)
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 84c8bfe..a0af4b5 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -328,6 +328,7 @@
MDP_BLOCK_DMA_P,
MDP_BLOCK_DMA_S,
MDP_BLOCK_DMA_E,
+ MDP_BLOCK_OVERLAY_2,
MDP_BLOCK_MAX,
};
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e7cc68e..1dae562 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1031,6 +1031,55 @@
* %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into
* (Re)Association Response frames when the driver (or firmware) replies to
* (Re)Association Request frames.
+ * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
+ * of the station, see &enum nl80211_sta_wme_attr.
+ * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working
+ * as AP.
+ *
+ * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of
+ * roaming to another AP in the same ESS if the signal lever is low.
+ *
+ * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching
+ * candidate information, see &enum nl80211_pmksa_candidate_attr.
+ *
+ * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not
+ * for management frames transmission. In order to avoid p2p probe/action
+ * frames are being transmitted at CCK rate in 2GHz band, the user space
+ * applications use this attribute.
+ * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and
+ * %NL80211_CMD_FRAME commands.
+ *
+ * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
+ * request, link setup confirm, link teardown, etc.). Values are
+ * described in the TDLS (802.11z) specification.
+ * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
+ * TDLS conversation between two devices.
+ * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
+ * &enum nl80211_tdls_operation, represented as a u8.
+ * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
+ * as a TDLS peer sta.
+ * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
+ * procedures should be performed by sending TDLS packets via
+ * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
+ * used for asking the driver to perform a TDLS operation.
+ *
+ * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
+ * that have AP support to indicate that they have the AP SME integrated
+ * with support for the features listed in this attribute, see
+ * &enum nl80211_ap_sme_features.
+ *
+ * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
+ * the driver to not wait for an acknowledgement. Note that due to this,
+ * it will also not give a status callback nor return a cookie. This is
+ * mostly useful for probe responses to save airtime.
+ *
+ * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
+ * &enum nl80211_feature_flags and is advertised in wiphy information.
+ * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe
+ *
+ * requests while operating in AP-mode.
+ * This attribute holds a bitmap of the supported protocols for
+ * offloading (see &enum nl80211_probe_resp_offload_support_attr).
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1254,6 +1303,19 @@
NL80211_ATTR_TX_NO_CCK_RATE,
+ NL80211_ATTR_TDLS_ACTION,
+ NL80211_ATTR_TDLS_DIALOG_TOKEN,
+ NL80211_ATTR_TDLS_OPERATION,
+ NL80211_ATTR_TDLS_SUPPORT,
+ NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+ NL80211_ATTR_DEVICE_AP_SME,
+
+ NL80211_ATTR_DONT_WAIT_FOR_ACK,
+
+ NL80211_ATTR_FEATURE_FLAGS,
+
+ NL80211_ATTR_PROBE_RESP_OFFLOAD,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -2436,4 +2498,35 @@
NL80211_HIDDEN_SSID_ZERO_CONTENTS
};
+/*
+ * enum nl80211_ap_sme_features - device-integrated AP features
+ * Reserved for future use, no bits are defined in
+ * NL80211_ATTR_DEVICE_AP_SME yet.
+enum nl80211_ap_sme_features {
+};
+ */
+
+/**
+ * enum nl80211_probe_resp_offload_support_attr - optional supported
+ * protocols for probe-response offloading by the driver/FW.
+ * To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute.
+ * Each enum value represents a bit in the bitmap of supported
+ * protocols. Typically a subset of probe-requests belonging to a
+ * supported protocol will be excluded from offload and uploaded
+ * to the host.
+ *
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u
+ */
+
+enum nl80211_probe_resp_offload_support_attr {
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 1<<0,
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 1<<1,
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 1<<2,
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3,
+};
+
+
#endif /* __LINUX_NL80211_H */
diff --git a/include/linux/qpnp/gpio.h b/include/linux/qpnp/gpio.h
index 0447a08..a31b7f3 100644
--- a/include/linux/qpnp/gpio.h
+++ b/include/linux/qpnp/gpio.h
@@ -69,10 +69,6 @@
* can be paired (shorted) with each other. Some gpio pin
* can act as alternate functions. This parameter should
* be of type QPNP_GPIO_FUNC_*
- * @inv_int_pol: Invert polarity before feeding the line to the interrupt
- * module in pmic. This feature will almost be never used
- * since the pm8xxx interrupt block can detect both edges
- * and both levels.
* @master_en: 1 = Enable features within the GPIO block based on
* configurations.
* 0 = Completely disable the GPIO block and let the pin
@@ -86,7 +82,6 @@
int vin_sel;
int out_strength;
int src_select;
- int inv_int_pol;
int master_en;
};
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index a731774..4c0ae07 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -149,6 +149,17 @@
};
/**
+ * Used different VDDCX voltage voting mechnism
+ * VDDCX_CORNER Vote for VDDCX Corner voltage
+ * VDDCX Vote for VDDCX Absolute voltage
+ */
+enum usb_vdd_type {
+ VDDCX_CORNER = 0,
+ VDDCX,
+ VDD_TYPE_MAX,
+};
+
+/**
* SPS Pipes direction.
*
* USB_TO_PEER_PERIPHERAL USB (as Producer) to other
@@ -327,21 +338,16 @@
* voltage regulator(VDDCX).
*/
#define ALLOW_PHY_RETENTION BIT(1)
- /*
- * Disable the OTG comparators to save more power
- * if depends on PMIC for VBUS and ID interrupts.
- */
-#define ALLOW_PHY_COMP_DISABLE BIT(2)
unsigned long lpm_flags;
#define PHY_PWR_COLLAPSED BIT(0)
#define PHY_RETENTIONED BIT(1)
-#define PHY_OTG_COMP_DISABLED BIT(2)
struct pm_qos_request_list pm_qos_req_dma;
int reset_counter;
unsigned long b_last_se0_sess;
unsigned long tmouts;
u8 active_tmout;
struct hrtimer timer;
+ enum usb_vdd_type vdd_type;
};
struct msm_hsic_host_platform_data {
diff --git a/include/media/gpio-ir-recv.h b/include/media/gpio-ir-recv.h
index 61a7fbb..3eab611 100644
--- a/include/media/gpio-ir-recv.h
+++ b/include/media/gpio-ir-recv.h
@@ -16,6 +16,7 @@
struct gpio_ir_recv_platform_data {
unsigned int gpio_nr;
bool active_low;
+ bool can_wakeup;
};
#endif /* __GPIO_IR_RECV_H__ */
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 20d3ef9..32a1759 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -116,11 +116,14 @@
void (*timer_stop) (void *timer_handle);
};
+/*Flags passed to vcd_open*/
+#define VCD_CP_SESSION 0x00000001
+
u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle);
u32 vcd_term(s32 driver_handle);
u32 vcd_open(s32 driver_handle, u32 decoding,
void (*callback) (u32 event, u32 status, void *info, size_t sz,
- void *handle, void *const client_data), void *client_data);
+ void *handle, void *const client_data), void *client_data, int flags);
u32 vcd_close(void *handle);
u32 vcd_encode_start(void *handle);
u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame);
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 31977ed..7aae5e1 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -148,50 +148,44 @@
#define MSM_CAM_IOCTL_PUT_ST_FRAME \
_IOW(MSM_CAM_IOCTL_MAGIC, 39, struct msm_camera_st_frame *)
-#define MSM_CAM_IOCTL_GET_CONFIG_INFO \
- _IOR(MSM_CAM_IOCTL_MAGIC, 40, struct msm_cam_config_dev_info *)
-
#define MSM_CAM_IOCTL_V4L2_EVT_NOTIFY \
- _IOR(MSM_CAM_IOCTL_MAGIC, 41, struct v4l2_event *)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 40, struct v4l2_event *)
#define MSM_CAM_IOCTL_SET_MEM_MAP_INFO \
- _IOR(MSM_CAM_IOCTL_MAGIC, 42, struct msm_mem_map_info *)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 41, struct msm_mem_map_info *)
#define MSM_CAM_IOCTL_ACTUATOR_IO_CFG \
- _IOW(MSM_CAM_IOCTL_MAGIC, 43, struct msm_actuator_cfg_data *)
+ _IOW(MSM_CAM_IOCTL_MAGIC, 42, struct msm_actuator_cfg_data *)
#define MSM_CAM_IOCTL_MCTL_POST_PROC \
- _IOW(MSM_CAM_IOCTL_MAGIC, 44, struct msm_mctl_post_proc_cmd *)
+ _IOW(MSM_CAM_IOCTL_MAGIC, 43, struct msm_mctl_post_proc_cmd *)
#define MSM_CAM_IOCTL_RESERVE_FREE_FRAME \
- _IOW(MSM_CAM_IOCTL_MAGIC, 45, struct msm_cam_evt_divert_frame *)
+ _IOW(MSM_CAM_IOCTL_MAGIC, 44, struct msm_cam_evt_divert_frame *)
#define MSM_CAM_IOCTL_RELEASE_FREE_FRAME \
- _IOR(MSM_CAM_IOCTL_MAGIC, 46, struct msm_cam_evt_divert_frame *)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 45, struct msm_cam_evt_divert_frame *)
#define MSM_CAM_IOCTL_PICT_PP_DIVERT_DONE \
- _IOR(MSM_CAM_IOCTL_MAGIC, 47, struct msm_pp_frame *)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 46, struct msm_pp_frame *)
#define MSM_CAM_IOCTL_SENSOR_V4l2_S_CTRL \
- _IOR(MSM_CAM_IOCTL_MAGIC, 48, struct v4l2_control)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 47, struct v4l2_control)
#define MSM_CAM_IOCTL_SENSOR_V4l2_QUERY_CTRL \
- _IOR(MSM_CAM_IOCTL_MAGIC, 49, struct v4l2_queryctrl)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 48, struct v4l2_queryctrl)
#define MSM_CAM_IOCTL_GET_KERNEL_SYSTEM_TIME \
- _IOW(MSM_CAM_IOCTL_MAGIC, 50, struct timeval *)
+ _IOW(MSM_CAM_IOCTL_MAGIC, 49, struct timeval *)
#define MSM_CAM_IOCTL_SET_VFE_OUTPUT_TYPE \
- _IOW(MSM_CAM_IOCTL_MAGIC, 51, uint32_t *)
-
-#define MSM_CAM_IOCTL_GET_MCTL_INFO \
- _IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_mctl_node_info *)
+ _IOW(MSM_CAM_IOCTL_MAGIC, 50, uint32_t *)
#define MSM_CAM_IOCTL_MCTL_DIVERT_DONE \
- _IOR(MSM_CAM_IOCTL_MAGIC, 53, struct msm_cam_evt_divert_frame *)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 51, struct msm_cam_evt_divert_frame *)
#define MSM_CAM_IOCTL_GET_ACTUATOR_INFO \
- _IOW(MSM_CAM_IOCTL_MAGIC, 54, struct msm_actuator_cfg_data *)
+ _IOW(MSM_CAM_IOCTL_MAGIC, 52, struct msm_actuator_cfg_data *)
struct msm_mctl_pp_cmd {
int32_t id;
@@ -260,6 +254,8 @@
uint32_t timeout_ms;
int resp_fd; /* FIXME: to be used by the kernel, pass-through for now */
int vnode_id; /* video dev id. Can we overload resp_fd? */
+ int queue_idx;
+ uint32_t evt_id;
uint32_t stream_type; /* used to pass value to qcamera server */
int config_ident; /*used as identifier for config node*/
};
@@ -270,6 +266,7 @@
unsigned int len; /* size in, number of bytes out */
uint32_t frame_id;
void *data;
+ struct timespec timestamp;
};
struct msm_pp_frame_sp {
@@ -1362,4 +1359,23 @@
#define QCAMERA_DEVICE_GROUP_ID 1
#define QCAMERA_VNODE_GROUP_ID 2
+#define MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_camera_v4l2_ioctl_t *)
+
+#define MSM_CAM_V4L2_IOCTL_GET_CONFIG_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct msm_camera_v4l2_ioctl_t *)
+
+#define MSM_CAM_V4L2_IOCTL_GET_MCTL_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct msm_camera_v4l2_ioctl_t *)
+
+#define MSM_CAM_V4L2_IOCTL_CTRL_CMD_DONE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct msm_camera_v4l2_ioctl_t *)
+
+#define MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t *)
+
+struct msm_camera_v4l2_ioctl_t {
+ void __user *ioctl_ptr;
+};
+
#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2b5824c..5053bd8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -629,7 +629,7 @@
if (conn->state == BT_CONNECTED) {
timeo = msecs_to_jiffies(conn->disc_timeout);
if (!conn->out)
- timeo *= 20;
+ timeo *= 4;
} else
timeo = msecs_to_jiffies(10);
} else
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4898ea2..53c7196 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1584,6 +1584,21 @@
* @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
* auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
* @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans.
+ * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the
+ * firmware.
+ * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP.
+ * @WIPHY_FLAG_SUPPORTS_TDLS: The device supports TDLS (802.11z) operation.
+ * @WIPHY_FLAG_TDLS_EXTERNAL_SETUP: The device does not handle TDLS (802.11z)
+ * link setup/discovery operations internally. Setup, discovery and
+ * teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT
+ * command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
+ * used for asking the driver/firmware to perform a TDLS operation.
+ * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
+ * @WIPHY_FLAG_REPORTS_OBSS: the device will report beacons from other BSSes
+ * when there are virtual interfaces in AP mode by calling
+ * cfg80211_report_obss_beacon().
+ * @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD: When operating as an AP, the device
+ * responds to probe-requests in hardware.
*/
enum wiphy_flags {
WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
@@ -1598,6 +1613,13 @@
WIPHY_FLAG_MESH_AUTH = BIT(10),
WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11),
WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12),
+ WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13),
+ WIPHY_FLAG_AP_UAPSD = BIT(14),
+ WIPHY_FLAG_SUPPORTS_TDLS = BIT(15),
+ WIPHY_FLAG_TDLS_EXTERNAL_SETUP = BIT(16),
+ WIPHY_FLAG_HAVE_AP_SME = BIT(17),
+ WIPHY_FLAG_REPORTS_OBSS = BIT(18),
+ WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD = BIT(19),
};
/**
@@ -1788,6 +1810,7 @@
* may request, if implemented.
*
* @wowlan: WoWLAN support information
+ * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -1811,6 +1834,8 @@
u32 flags;
+ u32 ap_sme_capa;
+
enum cfg80211_signal_type signal_type;
int bss_priv_size;
@@ -1838,6 +1863,13 @@
u32 available_antennas_tx;
u32 available_antennas_rx;
+ /*
+ * Bitmap of supported protocols for probe response offloading
+ * see &enum nl80211_probe_resp_offload_support_attr. Only valid
+ * when the wiphy flag @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD is set.
+ */
+ u32 probe_resp_offload;
+
/* If multiple wiphys are registered and you're handed e.g.
* a regular netdev with assigned ieee80211_ptr, you won't
* know whether it points to a wiphy your driver has registered
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index f71d743..782ee8d 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -992,6 +992,7 @@
struct asm_qcelp13_read_cfg qcelp13;
struct asm_sbc_read_cfg sbc;
struct asm_amrwb_read_cfg amrwb;
+ struct asm_multi_channel_pcm_fmt_blk mpcm;
} __attribute__((packed)) cfg;
};
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index c3d4bd5..aec4171 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -238,6 +238,9 @@
int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels);
+int q6asm_enc_cfg_blk_multi_ch_pcm(struct audio_client *ac,
+ uint32_t rate, uint32_t channels);
+
int q6asm_enable_sbrps(struct audio_client *ac,
uint32_t sbr_ps);
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 8d52423..f51b006 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -815,6 +815,7 @@
struct mutex mutex;
struct mutex dapm_mutex;
struct mutex dsp_mutex;
+ spinlock_t dsp_spinlock;
bool instantiated;
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 079f1d3..2169fee 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -343,7 +343,7 @@
/* Look up a kernel symbol and return it in a text buffer. */
static int __sprint_symbol(char *buffer, unsigned long address,
- int symbol_offset)
+ int symbol_offset, int add_offset)
{
char *modname;
const char *name;
@@ -358,13 +358,13 @@
if (name != buffer)
strcpy(buffer, name);
len = strlen(buffer);
- buffer += len;
offset -= symbol_offset;
+ if (add_offset)
+ len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
+
if (modname)
- len += sprintf(buffer, "+%#lx/%#lx [%s]", offset, size, modname);
- else
- len += sprintf(buffer, "+%#lx/%#lx", offset, size);
+ len += sprintf(buffer + len, " [%s]", modname);
return len;
}
@@ -382,12 +382,28 @@
*/
int sprint_symbol(char *buffer, unsigned long address)
{
- return __sprint_symbol(buffer, address, 0);
+ return __sprint_symbol(buffer, address, 0, 1);
}
-
EXPORT_SYMBOL_GPL(sprint_symbol);
/**
+ * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer
+ * @buffer: buffer to be stored
+ * @address: address to lookup
+ *
+ * This function looks up a kernel symbol with @address and stores its name
+ * and module name to @buffer if possible. If no symbol was found, just saves
+ * its @address as is.
+ *
+ * This function returns the number of bytes stored in @buffer.
+ */
+int sprint_symbol_no_offset(char *buffer, unsigned long address)
+{
+ return __sprint_symbol(buffer, address, 0, 0);
+}
+EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
+
+/**
* sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
* @buffer: buffer to be stored
* @address: address to lookup
@@ -403,7 +419,7 @@
*/
int sprint_backtrace(char *buffer, unsigned long address)
{
- return __sprint_symbol(buffer, address, -1);
+ return __sprint_symbol(buffer, address, -1, 1);
}
/* Look up a kernel symbol and print it to the kernel messages. */
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index 4755b98..fb4e88d 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -61,7 +61,7 @@
printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
msg, raw_smp_processor_id(),
current->comm, task_pid_nr(current));
- printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
+ printk(KERN_EMERG " lock: %ps, .magic: %08x, .owner: %s/%d, "
".owner_cpu: %d\n",
lock, lock->magic,
owner ? owner->comm : "<none>",
@@ -114,7 +114,7 @@
if (print_once) {
print_once = 0;
printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
- "%s/%d, %p\n",
+ "%s/%d, %ps\n",
raw_smp_processor_id(), current->comm,
task_pid_nr(current), lock);
dump_stack();
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 4365df3..44657bc 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -438,7 +438,7 @@
else if (ext != 'f' && ext != 's')
sprint_symbol(sym, value);
else
- kallsyms_lookup(value, NULL, NULL, NULL, sym);
+ sprint_symbol_no_offset(sym, value);
return string(buf, end, sym, spec);
#else
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c0eb50c..8d51644 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1563,7 +1563,7 @@
list_del(&hdev->list);
write_unlock_bh(&hci_dev_list_lock);
- hci_dev_do_close(hdev, 0);
+ hci_dev_do_close(hdev, hdev->bus == HCI_SMD);
for (i = 0; i < NUM_REASSEMBLY; i++)
kfree_skb(hdev->reassembly[i]);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3b5ad95..37ee9b1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5371,7 +5371,7 @@
release_sock(sk);
}
-int l2cap_logical_link_complete(struct hci_chan *chan, u8 status)
+static void l2cap_logical_link_complete(struct hci_chan *chan, u8 status)
{
struct l2cap_pinfo *pi;
struct sock *sk;
@@ -5385,11 +5385,14 @@
BT_DBG("sk %p", sk);
+ if (!sk)
+ return;
+
lock_sock(sk);
if (sk->sk_state != BT_CONNECTED && !l2cap_pi(sk)->amp_id) {
release_sock(sk);
- return 0;
+ return;
}
pi = l2cap_pi(sk);
@@ -5516,7 +5519,6 @@
}
release_sock(sk);
- return 0;
}
static void l2cap_logical_link_worker(struct work_struct *work)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 6a4a2f0..8eb1e16 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -505,8 +505,10 @@
memset(&sec, 0, sizeof(sec));
sec.level = l2cap_pi(sk)->sec_level;
- if (sk->sk_state == BT_CONNECTED)
+ if (sk->sk_state == BT_CONNECTED) {
sec.key_size = l2cap_pi(sk)->conn->hcon->enc_key_size;
+ sec.level = l2cap_pi(sk)->conn->hcon->sec_level;
+ }
len = min_t(unsigned int, len, sizeof(sec));
if (copy_to_user(optval, (char *) &sec, len))
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8b6f23e..e15609c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1353,20 +1353,23 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENETDOWN);
- goto failed;
+ goto done;
}
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
- &cp->bdaddr);
- if (!conn)
- return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENOTCONN);
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+ if (!conn) {
+ err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENOTCONN);
+ goto done;
+ }
- if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
- return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINPROGRESS);
+ if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+ err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINPROGRESS);
+ goto done;
+ }
if (conn->link_mode & HCI_LM_AUTH) {
enc.handle = cpu_to_le16(conn->handle);
@@ -1383,8 +1386,8 @@
}
}
-failed:
- hci_dev_unlock(hdev);
+done:
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 2484a9a..31fc4dc 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -717,6 +717,7 @@
memset(&cp, 0, sizeof(cp));
build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
+ hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
hcon->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&hcon->preq[1], &cp, sizeof(cp));
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 880dbe2..e921d00 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -488,6 +488,10 @@
int i;
u16 ifmodes = wiphy->interface_modes;
+ if (WARN_ON(wiphy->ap_sme_capa &&
+ !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
+ return -EINVAL;
+
if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
return -EINVAL;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index bf6915b..e6457ff 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -718,6 +718,10 @@
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
dev->wiphy.available_antennas_rx);
+ if (dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD)
+ NLA_PUT_U32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
+ dev->wiphy.probe_resp_offload);
+
if ((dev->wiphy.available_antennas_tx ||
dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) {
u32 tx_ant = 0, rx_ant = 0;
@@ -954,6 +958,10 @@
if (nl80211_put_iface_combinations(&dev->wiphy, msg))
goto nla_put_failure;
+ if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME)
+ NLA_PUT_U32(msg, NL80211_ATTR_DEVICE_AP_SME,
+ dev->wiphy.ap_sme_capa);
+
return genlmsg_end(msg, hdr);
nla_put_failure:
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 3229bce..1fe28a2 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1474,6 +1474,8 @@
pr_err("%s %d\n", __func__, event);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
+ 0x00);
snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x01,
0x01);
snd_soc_update_bits(codec, SITAR_A_CDC_CLSG_CTL, 0x08, 0x08);
@@ -1996,7 +1998,6 @@
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x05);
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x00);
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x04);
- snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
usleep_range(50, 50);
sitar->clock_active = true;
return 0;
@@ -2005,7 +2006,6 @@
{
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
pr_err("%s\n", __func__);
- snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x00);
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
ndelay(160);
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
@@ -3962,6 +3962,9 @@
/*enable HPF filter for TX paths */
{SITAR_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
{SITAR_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
+
+ /*enable External clock select*/
+ {SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01},
};
static void sitar_codec_init_reg(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 753ef2e..3d489ff 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -63,9 +63,14 @@
SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
SLIM_2_RX_1 = 147, /* HDMI RX */
- SLIM_3_RX_1 = 148, /* In-call recording RX */
- SLIM_3_RX_2 = 149, /* In-call recording RX */
- SLIM_4_TX_1 = 150, /* In-call musid delivery TX */
+ SLIM_4_TX_1 = 148, /* In-call recording RX */
+ SLIM_4_TX_2 = 149, /* In-call recording RX */
+ SLIM_4_RX_1 = 150, /* In-call music delivery TX */
+};
+
+enum {
+ INCALL_REC_MONO,
+ INCALL_REC_STEREO,
};
static u32 top_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(18);
@@ -79,6 +84,8 @@
static int msm_btsco_rate = BTSCO_RATE_8KHZ;
static int msm_btsco_ch = 1;
+static int rec_mode = INCALL_REC_MONO;
+
static struct clk *codec_clk;
static int clk_users;
@@ -611,6 +618,23 @@
return 0;
}
+static int msm_incall_rec_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = rec_mode;
+ return 0;
+}
+
+static int msm_incall_rec_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ rec_mode = ucontrol->value.integer.value[0];
+ pr_debug("%s: rec_mode:%d\n", __func__, rec_mode);
+
+ return 0;
+}
+
static const struct snd_kcontrol_new tabla_msm_controls[] = {
SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
msm_set_spk),
@@ -625,6 +649,11 @@
msm_btsco_rate_get, msm_btsco_rate_put),
};
+static const struct snd_kcontrol_new incall_rec_mode_mixer_controls[] = {
+ SOC_SINGLE_EXT("Incall Rec Mode", SND_SOC_NOPM, 0, 1, 0,
+ msm_incall_rec_mode_get, msm_incall_rec_mode_put),
+};
+
static int msm_btsco_init(struct snd_soc_pcm_runtime *rtd)
{
int err = 0;
@@ -638,6 +667,19 @@
return 0;
}
+static int msm_incall_rec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int err = 0;
+ struct snd_soc_platform *platform = rtd->platform;
+
+ err = snd_soc_add_platform_controls(platform,
+ incall_rec_mode_mixer_controls,
+ ARRAY_SIZE(incall_rec_mode_mixer_controls));
+ if (err < 0)
+ return err;
+ return 0;
+}
+
static void *def_tabla_mbhc_cal(void)
{
void *tabla_cal;
@@ -831,6 +873,49 @@
return ret;
}
+static int msm_slimbus_4_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+ unsigned int rx_ch = SLIM_4_RX_1, tx_ch[2];
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ pr_debug("%s: APQ Incall Playback SLIMBUS_4_RX -> MDM TX shared ch %d\n",
+ __func__, rx_ch);
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, 1, &rx_ch);
+ if (ret < 0) {
+ pr_err("%s: Erorr %d setting SLIM_4 RX channel map\n",
+ __func__, ret);
+
+ }
+ } else {
+ if (rec_mode == INCALL_REC_STEREO) {
+ tx_ch[0] = SLIM_4_TX_1;
+ tx_ch[1] = SLIM_4_TX_2;
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 2,
+ tx_ch, 0, 0);
+ } else {
+ tx_ch[0] = SLIM_4_TX_1;
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 1,
+ tx_ch, 0, 0);
+ }
+ pr_debug("%s: Incall Record shared tx_ch[0]:%d, tx_ch[1]:%d\n",
+ __func__, tx_ch[0], tx_ch[1]);
+
+ if (ret < 0) {
+ pr_err("%s: Erorr %d setting SLIM_4 TX channel map\n",
+ __func__, ret);
+
+ }
+ }
+
+ return ret;
+}
+
+
static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int err;
@@ -1118,6 +1203,12 @@
.shutdown = msm_shutdown,
};
+static struct snd_soc_ops msm_slimbus_4_be_ops = {
+ .startup = msm_startup,
+ .hw_params = msm_slimbus_4_hw_params,
+ .shutdown = msm_shutdown,
+};
+
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link msm_dai[] = {
/* FrontEnd DAI Links */
@@ -1413,6 +1504,35 @@
.ops = &msm_be_ops,
},
+ /* Incall Music Back End DAI Link */
+ {
+ .name = LPASS_BE_SLIMBUS_4_RX,
+ .stream_name = "Slimbus4 Playback",
+ .cpu_dai_name = "msm-dai-q6.16392",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .no_codec = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_slimbus_4_be_ops,
+ },
+ /* Incall Record Back End DAI Link */
+ {
+ .name = LPASS_BE_SLIMBUS_4_TX,
+ .stream_name = "Slimbus4 Capture",
+ .cpu_dai_name = "msm-dai-q6.16393",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .no_codec = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .init = &msm_incall_rec_init,
+ .ops = &msm_slimbus_4_be_ops,
+ },
};
struct snd_soc_card snd_soc_card_msm = {
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index 758ad94..760f13d 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -1021,6 +1021,17 @@
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
},
+ {
+ .name = "VoLTE",
+ .stream_name = "VoLTE",
+ .cpu_dai_name = "VoLTE",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dsp_link = &fe_media,
+ .be_id = MSM_FRONTEND_DAI_VOLTE,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
/* Backend BT DAI Links */
{
.name = LPASS_BE_INT_BT_SCO_RX,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 14d9adf..3f86962 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -62,7 +62,7 @@
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 4,
.rate_min = 8000,
.rate_max = 48000,
},
@@ -293,6 +293,28 @@
.ops = &msm_fe_dai_ops,
.name = "VOICE_STUB",
},
+ {
+ .playback = {
+ .stream_name = "VoLTE Playback",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "VoLTE Capture",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "VoLTE",
+ },
};
static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index e6d5012..a53dd44 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -388,6 +388,8 @@
case SLIMBUS_0_TX:
case SLIMBUS_1_TX:
case SLIMBUS_2_TX:
+ case SLIMBUS_4_RX:
+ case SLIMBUS_4_TX:
rc = msm_dai_q6_slim_bus_hw_params(params, dai,
substream->stream);
break;
@@ -885,6 +887,7 @@
switch (dai->id) {
case SLIMBUS_0_RX:
case SLIMBUS_1_RX:
+ case SLIMBUS_4_RX:
/* channel number to be between 128 and 255. For RX port
* use channel numbers from 138 to 144, for TX port
* use channel numbers from 128 to 137
@@ -909,7 +912,7 @@
case SLIMBUS_0_TX:
case SLIMBUS_1_TX:
case SLIMBUS_2_TX:
-
+ case SLIMBUS_4_TX:
/* channel number to be between 128 and 255. For RX port
* use channel numbers from 138 to 144, for TX port
* use channel numbers from 128 to 137
@@ -1004,7 +1007,7 @@
SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 4,
.rate_min = 8000,
.rate_max = 48000,
},
@@ -1245,10 +1248,12 @@
&msm_dai_q6_mi2s_rx_dai);
break;
case SLIMBUS_0_RX:
+ case SLIMBUS_4_RX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_slimbus_rx_dai);
break;
case SLIMBUS_0_TX:
+ case SLIMBUS_4_TX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_slimbus_tx_dai);
break;
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index dd194d6..4686386 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -55,7 +55,7 @@
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 4,
.buffer_bytes_max = CAPTURE_NUM_PERIODS * CAPTURE_PERIOD_SIZE,
.period_bytes_min = CAPTURE_PERIOD_SIZE,
.period_bytes_max = CAPTURE_PERIOD_SIZE,
@@ -248,8 +248,14 @@
pr_debug("Samp_rate = %d\n", prtd->samp_rate);
pr_debug("Channel = %d\n", prtd->channel_mode);
- ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client, prtd->samp_rate,
- prtd->channel_mode);
+ if (prtd->channel_mode > 2) {
+ ret = q6asm_enc_cfg_blk_multi_ch_pcm(prtd->audio_client,
+ prtd->samp_rate, prtd->channel_mode);
+ } else {
+ ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client,
+ prtd->samp_rate, prtd->channel_mode);
+ }
+
if (ret < 0)
pr_debug("%s: cmd cfg pcm was block failed", __func__);
@@ -331,13 +337,6 @@
/* Capture path */
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
runtime->hw = msm_pcm_hardware_capture;
- ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
- if (ret < 0) {
- pr_err("%s: pcm in open failed\n", __func__);
- q6asm_audio_client_free(prtd->audio_client);
- kfree(prtd);
- return -ENOMEM;
- }
}
pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
@@ -622,12 +621,28 @@
struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
struct audio_buffer *buf;
int dir, ret;
+ int format = FORMAT_LINEAR_PCM;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dir = IN;
else
dir = OUT;
+ /*capture path*/
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ if (params_channels(params) > 2)
+ format = FORMAT_MULTI_CHANNEL_LINEAR_PCM;
+ pr_debug("%s format = :0x%x\n", __func__, format);
+
+ ret = q6asm_open_read(prtd->audio_client, format);
+ if (ret < 0) {
+ pr_err("%s: q6asm_open_read failed\n", __func__);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ }
+
ret = q6asm_audio_client_buf_alloc_contiguous(dir,
prtd->audio_client,
runtime->hw.period_bytes_min,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 6bac324..0f74afb 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -131,6 +131,8 @@
{ SECONDARY_I2S_RX, 0, 0, 0, 0, 0},
{ SLIMBUS_1_RX, 0, 0, 0, 0, 0},
{ SLIMBUS_1_TX, 0, 0, 0, 0, 0},
+ { SLIMBUS_4_RX, 0, 0, 0, 0, 0},
+ { SLIMBUS_4_TX, 0, 0, 0, 0, 0},
{ SLIMBUS_INVALID, 0, 0, 0, 0, 0},
};
@@ -439,6 +441,8 @@
if (val == MSM_FRONTEND_DAI_CS_VOICE)
session_id = voc_get_session_id(VOICE_SESSION_NAME);
+ else if (val == MSM_FRONTEND_DAI_VOLTE)
+ session_id = voc_get_session_id(VOLTE_SESSION_NAME);
else
session_id = voc_get_session_id(VOIP_SESSION_NAME);
@@ -946,6 +950,15 @@
msm_routing_put_audio_mixer),
};
+static const struct snd_kcontrol_new slimbus_4_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1031,6 +1044,9 @@
SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("SLIM_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
@@ -1046,6 +1062,9 @@
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new sec_i2s_rx_voice_mixer_controls[] = {
@@ -1055,6 +1074,9 @@
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
@@ -1064,6 +1086,9 @@
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
@@ -1076,6 +1101,9 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
@@ -1088,6 +1116,9 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
@@ -1100,6 +1131,9 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
@@ -1109,6 +1143,9 @@
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
@@ -1141,6 +1178,24 @@
msm_routing_put_voice_mixer),
};
+static const struct snd_kcontrol_new tx_volte_mixer_controls[] = {
+ SOC_SINGLE_EXT("PRI_TX_VoLTE", MSM_BACKEND_DAI_PRI_I2S_TX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SLIM_0_TX_VoLTE", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_VoLTE",
+ MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_VOLTE, 1, 0,
+ msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX_VoLTE", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_AUXPCM_TX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+};
+
static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
@@ -1432,6 +1487,8 @@
SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VoLTE_UL", "VoLTE Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
0, 0, 0, 0),
@@ -1473,10 +1530,15 @@
/* incall */
SND_SOC_DAPM_AIF_OUT("VOICE_PLAYBACK_TX", "Voice Farend Playback",
0, 0, 0 , 0),
+ SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback",
+ 0, 0, 0 , 0),
SND_SOC_DAPM_AIF_IN("INCALL_RECORD_TX", "Voice Uplink Capture",
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("INCALL_RECORD_RX", "Voice Downlink Capture",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture",
+ 0, 0, 0, 0),
+
SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
@@ -1512,6 +1574,9 @@
SND_SOC_DAPM_MIXER("Incall_Music Audio Mixer", SND_SOC_NOPM, 0, 0,
incall_music_delivery_mixer_controls,
ARRAY_SIZE(incall_music_delivery_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SLIMBUS_4_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+ slimbus_4_rx_mixer_controls,
+ ARRAY_SIZE(slimbus_4_rx_mixer_controls)),
/* Voice Mixer */
SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
@@ -1546,6 +1611,9 @@
SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
ARRAY_SIZE(tx_voip_mixer_controls)),
+ SND_SOC_DAPM_MIXER("VoLTE_Tx Mixer",
+ SND_SOC_NOPM, 0, 0, tx_volte_mixer_controls,
+ ARRAY_SIZE(tx_volte_mixer_controls)),
SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -1604,9 +1672,13 @@
{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
{"VOICE_PLAYBACK_TX", NULL, "Incall_Music Audio Mixer"},
+ {"SLIMBUS_4_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+ {"SLIMBUS_4_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+ {"SLIMBUS_4_RX", NULL, "SLIMBUS_4_RX Audio Mixer"},
{"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
+ {"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
{"MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
@@ -1650,30 +1722,37 @@
{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"SLIM_0_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
{"HDMI", NULL, "HDMI_DL_HL"},
@@ -1684,6 +1763,12 @@
{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
+ {"VoLTE_Tx Mixer", "PRI_TX_VoLTE", "PRI_I2S_TX"},
+ {"VoLTE_Tx Mixer", "SLIM_0_TX_VoLTE", "SLIMBUS_0_TX"},
+ {"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
+ {"VoLTE_Tx Mixer", "AFE_PCM_TX_VoLTE", "PCM_TX"},
+ {"VoLTE_Tx Mixer", "AUX_PCM_TX_VoLTE", "AUX_PCM_TX"},
+ {"VoLTE_UL", NULL, "VoLTE_Tx Mixer"},
{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
{"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
{"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
@@ -1816,8 +1901,9 @@
if (fe_dai_map[i][session_type] != INVALID_SESSION) {
channels = bedai->channel;
- if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
- (channels > 2))
+ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+ substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ && (channels > 2))
adm_multi_ch_copp_open(bedai->port_id,
path_type,
bedai->sample_rate,
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index eb6db4b..e5d8638 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -37,6 +37,9 @@
#define LPASS_BE_SLIMBUS_1_RX "(Backend) SLIMBUS_1_RX"
#define LPASS_BE_SLIMBUS_1_TX "(Backend) SLIMBUS_1_TX"
+#define LPASS_BE_SLIMBUS_4_RX "(Backend) SLIMBUS_4_RX"
+#define LPASS_BE_SLIMBUS_4_TX "(Backend) SLIMBUS_4_TX"
+
/* For multimedia front-ends, asm session is allocated dynamically.
* Hence, asm session/multimedia front-end mapping has to be maintained.
* Due to this reason, additional multimedia front-end must be placed before
@@ -53,6 +56,7 @@
MSM_FRONTEND_DAI_AFE_RX,
MSM_FRONTEND_DAI_AFE_TX,
MSM_FRONTEND_DAI_VOICE_STUB,
+ MSM_FRONTEND_DAI_VOLTE,
MSM_FRONTEND_DAI_MAX,
};
@@ -80,6 +84,8 @@
MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_BACKEND_DAI_SLIMBUS_1_RX,
MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ MSM_BACKEND_DAI_SLIMBUS_4_TX,
MSM_BACKEND_DAI_INVALID,
MSM_BACKEND_DAI_MAX,
};
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index 5a0f27a..59b8bbd 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -29,7 +29,7 @@
#include "msm-pcm-voice.h"
#include "qdsp6/q6voice.h"
-static struct msm_voice voice_info;
+static struct msm_voice voice_info[VOICE_SESSION_INDEX_MAX];
static struct snd_pcm_hardware msm_pcm_hardware = {
@@ -49,6 +49,13 @@
.fifo_size = 0,
};
+static int is_volte(struct msm_voice *pvolte)
+{
+ if (pvolte == &voice_info[VOLTE_SESSION_INDEX])
+ return true;
+ else
+ return false;
+}
static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
{
@@ -78,8 +85,17 @@
static int msm_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- struct msm_voice *voice = &voice_info;
+ struct msm_voice *voice;
+ if (!strncmp("VoLTE", substream->pcm->id, 5)) {
+ voice = &voice_info[VOLTE_SESSION_INDEX];
+ pr_debug("%s: Open VoLTE Substream Id=%s\n",
+ __func__, substream->pcm->id);
+ } else {
+ voice = &voice_info[VOICE_SESSION_INDEX];
+ pr_debug("%s: Open VOICE Substream Id=%s\n",
+ __func__, substream->pcm->id);
+ }
mutex_lock(&voice->lock);
runtime->hw = msm_pcm_hardware;
@@ -90,7 +106,8 @@
voice->capture_substream = substream;
voice->instance++;
- pr_debug(" %s: instance: %d\n", __func__ , voice->instance);
+ pr_debug("%s: Instance = %d, Stream ID = %s\n",
+ __func__ , voice->instance, substream->pcm->id);
runtime->private_data = voice;
mutex_unlock(&voice->lock);
@@ -129,6 +146,7 @@
struct snd_pcm_runtime *runtime = substream->runtime;
struct msm_voice *prtd = runtime->private_data;
+ uint16_t session_id = 0;
int ret = 0;
mutex_lock(&prtd->lock);
@@ -140,7 +158,11 @@
prtd->instance--;
if (!prtd->playback_start && !prtd->capture_start) {
pr_debug("end voice call\n");
- voc_end_voice_call(voc_get_session_id(VOICE_SESSION_NAME));
+ if (is_volte(prtd))
+ session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+ else
+ session_id = voc_get_session_id(VOICE_SESSION_NAME);
+ voc_end_voice_call(session_id);
}
mutex_unlock(&prtd->lock);
@@ -151,6 +173,7 @@
int ret = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct msm_voice *prtd = runtime->private_data;
+ uint16_t session_id = 0;
mutex_lock(&prtd->lock);
@@ -159,9 +182,13 @@
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
ret = msm_pcm_capture_prepare(substream);
- if (prtd->playback_start && prtd->capture_start)
- voc_start_voice_call(voc_get_session_id(VOICE_SESSION_NAME));
-
+ if (prtd->playback_start && prtd->capture_start) {
+ if (is_volte(prtd))
+ session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+ else
+ session_id = voc_get_session_id(VOICE_SESSION_NAME);
+ voc_start_voice_call(session_id);
+ }
mutex_unlock(&prtd->lock);
return ret;
@@ -189,12 +216,26 @@
struct snd_ctl_elem_value *ucontrol)
{
int volume = ucontrol->value.integer.value[0];
-
pr_debug("%s: volume: %d\n", __func__, volume);
-
voc_set_rx_vol_index(voc_get_session_id(VOICE_SESSION_NAME),
- RX_PATH,
- volume);
+ RX_PATH, volume);
+ return 0;
+}
+
+static int msm_volte_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = 0;
+ return 0;
+}
+
+static int msm_volte_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int volume = ucontrol->value.integer.value[0];
+ pr_debug("%s: volume: %d\n", __func__, volume);
+ voc_set_rx_vol_index(voc_get_session_id(VOLTE_SESSION_NAME),
+ RX_PATH, volume);
return 0;
}
@@ -217,6 +258,25 @@
return 0;
}
+static int msm_volte_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = 0;
+ return 0;
+}
+
+static int msm_volte_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int mute = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: mute=%d\n", __func__, mute);
+
+ voc_set_tx_mute(voc_get_session_id(VOLTE_SESSION_NAME), TX_PATH, mute);
+
+ return 0;
+}
+
static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -237,6 +297,26 @@
return 0;
}
+static int msm_volte_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] =
+ voc_get_rx_device_mute(voc_get_session_id(VOLTE_SESSION_NAME));
+ return 0;
+}
+
+static int msm_volte_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int mute = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: mute=%d\n", __func__, mute);
+
+ voc_set_rx_device_mute(voc_get_session_id(VOLTE_SESSION_NAME), mute);
+
+ return 0;
+}
+
static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
static const struct soc_enum msm_tty_mode_enum[] = {
SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -343,6 +423,13 @@
msm_voice_slowtalk_get, msm_voice_slowtalk_put),
SOC_SINGLE_EXT("FENS Enable", SND_SOC_NOPM, 0, 1, 0,
msm_voice_fens_get, msm_voice_fens_put),
+ SOC_SINGLE_EXT("VoLTE Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+ msm_volte_rx_device_mute_get,
+ msm_volte_rx_device_mute_put),
+ SOC_SINGLE_EXT("VoLTE Tx Mute", SND_SOC_NOPM, 0, 1, 0,
+ msm_volte_mute_get, msm_volte_mute_put),
+ SOC_SINGLE_EXT("VoLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
+ msm_volte_volume_get, msm_volte_volume_put),
};
static struct snd_pcm_ops msm_pcm_ops = {
@@ -402,7 +489,8 @@
static int __init msm_soc_platform_init(void)
{
memset(&voice_info, 0, sizeof(voice_info));
- mutex_init(&voice_info.lock);
+ mutex_init(&voice_info[VOICE_SESSION_INDEX].lock);
+ mutex_init(&voice_info[VOLTE_SESSION_INDEX].lock);
return platform_driver_register(&msm_pcm_driver);
}
diff --git a/sound/soc/msm/msm-pcm-voice.h b/sound/soc/msm/msm-pcm-voice.h
index 71bdbc1..aa00577 100644
--- a/sound/soc/msm/msm-pcm-voice.h
+++ b/sound/soc/msm/msm-pcm-voice.h
@@ -13,6 +13,11 @@
#define _MSM_PCM_VOICE_H
#include <sound/apr_audio.h>
+enum {
+ VOICE_SESSION_INDEX,
+ VOLTE_SESSION_INDEX,
+ VOICE_SESSION_INDEX_MAX,
+};
struct msm_voice {
struct snd_pcm_substream *playback_substream;
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index aec1bb2..570d71c 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, 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
@@ -37,6 +37,9 @@
/* Length of the DSP frame info header added to the voc packet. */
#define DSP_FRAME_HDR_LEN 1
+#define MODE_IS127 0x2
+#define MODE_4GV_NB 0x3
+#define MODE_4GV_WB 0x4
#define MODE_AMR 0x5
#define MODE_AMR_WB 0xD
#define MODE_PCM 0xC
@@ -74,7 +77,10 @@
};
struct voip_frame {
+ union {
uint32_t frame_type;
+ uint32_t packet_rate;
+ } header;
uint32_t len;
uint8_t voc_pkt[VOIP_MAX_VOC_PKT_SIZE];
};
@@ -276,7 +282,8 @@
* Bits 0-3: Frame rate
* Bits 4-7: Frame type
*/
- buf_node->frame.frame_type = ((*voc_pkt) & 0xF0) >> 4;
+ buf_node->frame.header.frame_type =
+ ((*voc_pkt) & 0xF0) >> 4;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
memcpy(&buf_node->frame.voc_pkt[0],
@@ -285,6 +292,24 @@
list_add_tail(&buf_node->list, &prtd->out_queue);
break;
}
+ case MODE_IS127:
+ case MODE_4GV_NB:
+ case MODE_4GV_WB: {
+ /* Remove the DSP frame info header.
+ * Header format:
+ * Bits 0-3: frame rate
+ */
+ buf_node->frame.header.packet_rate = (*voc_pkt) & 0x0F;
+ voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+ buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+
+ memcpy(&buf_node->frame.voc_pkt[0],
+ voc_pkt,
+ buf_node->frame.len);
+
+ list_add_tail(&buf_node->list, &prtd->out_queue);
+ break;
+ }
default: {
buf_node->frame.len = pkt_len;
memcpy(&buf_node->frame.voc_pkt[0],
@@ -332,8 +357,8 @@
* Bits 0-3: Frame rate
* Bits 4-7: Frame type
*/
- *voc_pkt = ((buf_node->frame.frame_type & 0x0F) << 4) |
- (prtd->rate_type & 0x0F);
+ *voc_pkt = ((buf_node->frame.header.frame_type &
+ 0x0F) << 4) | (prtd->rate_type & 0x0F);
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
memcpy(voc_pkt,
@@ -342,6 +367,23 @@
list_add_tail(&buf_node->list, &prtd->free_in_queue);
break;
}
+ case MODE_IS127:
+ case MODE_4GV_NB:
+ case MODE_4GV_WB: {
+ /* Add the DSP frame info header. Header format:
+ * Bits 0-3 : Frame rate
+ */
+ *voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
+ voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+ *pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
+
+ memcpy(voc_pkt,
+ &buf_node->frame.voc_pkt[0],
+ buf_node->frame.len);
+
+ list_add_tail(&buf_node->list, &prtd->free_in_queue);
+ break;
+ }
default: {
*pkt_len = buf_node->frame.len;
@@ -691,7 +733,7 @@
int ret = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct voip_drv_info *prtd = runtime->private_data;
- int32_t media_type = 0;
+ uint32_t media_type = 0;
uint32_t rate_type = 0;
mutex_lock(&prtd->lock);
@@ -702,7 +744,9 @@
ret = msm_pcm_capture_prepare(substream);
if ((runtime->format != FORMAT_SPECIAL) &&
- ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB))) {
+ ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB) ||
+ (prtd->mode == MODE_IS127) || (prtd->mode == MODE_4GV_NB) ||
+ (prtd->mode == MODE_4GV_WB))) {
pr_err("mode:%d and format:%u are not mached\n",
prtd->mode, (uint32_t)runtime->format);
ret = -EINVAL;
@@ -976,6 +1020,24 @@
*rate_type = 0;
break;
}
+ case MODE_IS127:
+ case MODE_4GV_NB:
+ case MODE_4GV_WB: {
+ switch (rate) {
+ case VOC_0_RATE:
+ case VOC_8_RATE:
+ case VOC_4_RATE:
+ case VOC_2_RATE:
+ case VOC_1_RATE:
+ *rate_type = rate;
+ break;
+ default:
+ pr_err("wrong rate for IS127/4GV_NB/WB.\n");
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ }
default:
pr_err("wrong mode type.\n");
ret = -EINVAL;
@@ -988,7 +1050,7 @@
static int voip_get_media_type(uint32_t mode,
unsigned int samp_rate)
{
- int32_t media_type;
+ uint32_t media_type;
pr_debug("%s: mode=%d, samp_rate=%d\n", __func__,
mode, samp_rate);
@@ -1005,6 +1067,15 @@
else
media_type = VSS_MEDIA_ID_PCM_WB;
break;
+ case MODE_IS127: /* EVRC-A */
+ media_type = VSS_MEDIA_ID_EVRC_MODEM;
+ break;
+ case MODE_4GV_NB: /* EVRC-B */
+ media_type = VSS_MEDIA_ID_4GV_NB_MODEM;
+ break;
+ case MODE_4GV_WB: /* EVRC-WB */
+ media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
+ break;
default:
pr_debug(" input mode is not supported\n");
media_type = -EINVAL;
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index e254cce..04b0fb0 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -129,8 +129,8 @@
if (!clk_users) {
pr_debug("%s: disabling MCLK. clk_users = %d\n",
__func__, clk_users);
- clk_disable_unprepare(codec_clk);
sitar_mclk_enable(codec, 0);
+ clk_disable_unprepare(codec_clk);
}
}
return 0;
@@ -520,9 +520,6 @@
}
codec_clk = clk_get(cpu_dai->dev, "osr_clk");
- sitar_hs_detect(codec, &hs_jack, &button_jack, sitar_mbhc_cal,
- SITAR_MICBIAS2, msm8930_enable_codec_ext_clk, 0,
- SITAR_EXT_CLK_RATE);
return 0;
}
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index de98aa3..abfadb8 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1175,6 +1175,17 @@
.no_codec = 1,
.ignore_suspend = 1,
},
+ {
+ .name = "VoLTE",
+ .stream_name = "VoLTE",
+ .cpu_dai_name = "VoLTE",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dsp_link = &fe_media,
+ .be_id = MSM_FRONTEND_DAI_VOLTE,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
/* Backend BT/FM DAI Links */
{
.name = LPASS_BE_INT_BT_SCO_RX,
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index bc5c007..676ecf1 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -143,14 +143,14 @@
s32 result = 0;
struct adm_set_params_command adm_params;
int index = afe_get_port_index(port_id);
-
- pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
-
if (index < 0 || index >= AFE_MAX_PORTS) {
pr_err("%s: invalid port idx %d portid %d\n",
__func__, index, port_id);
- goto done;
+ return 0;
}
+
+ pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
+
if (!aud_cal || aud_cal->cal_size == 0) {
pr_debug("%s: No ADM cal to send for port_id = %d!\n",
__func__, port_id);
@@ -489,6 +489,11 @@
} else if (channel_mode == 2) {
open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channel_mode == 4) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
} else if (channel_mode == 6) {
open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
@@ -575,16 +580,15 @@
int ret = 0, i = 0;
/* Assumes port_ids have already been validated during adm_open */
int index = afe_get_port_index(copp_id);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d token %d\n",
+ __func__, index, copp_id);
+ return 0;
+ }
pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
__func__, session_id, path, num_copps, port_id[0]);
- if (index < 0 || index >= AFE_MAX_PORTS) {
- pr_err("%s: invalid port idx %d token %d\n",
- __func__, index, copp_id);
- ret = -EINVAL;
- goto fail_cmd;
- }
route.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
route.hdr.pkt_size = sizeof(route);
@@ -609,7 +613,7 @@
pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
port_id[i], tmp);
- if ((tmp >= 0) && (tmp < AFE_MAX_PORTS))
+ if (tmp >= 0 && tmp < AFE_MAX_PORTS)
route.session[0].copp_id[i] =
atomic_read(&this_adm.copp_id[tmp]);
}
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index f474542..dc120b08 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -152,6 +152,7 @@
case INT_FM_RX:
case VOICE_PLAYBACK_TX:
case RT_PROXY_PORT_001_RX:
+ case SLIMBUS_4_RX:
ret = MSM_AFE_PORT_TYPE_RX;
break;
@@ -168,6 +169,7 @@
case VOICE_RECORD_RX:
case INT_BT_SCO_TX:
case RT_PROXY_PORT_001_TX:
+ case SLIMBUS_4_TX:
ret = MSM_AFE_PORT_TYPE_TX;
break;
@@ -211,6 +213,8 @@
case INT_FM_TX:
case RT_PROXY_PORT_001_RX:
case RT_PROXY_PORT_001_TX:
+ case SLIMBUS_4_RX:
+ case SLIMBUS_4_TX:
{
ret = 0;
break;
@@ -274,6 +278,8 @@
case INT_FM_TX: return IDX_INT_FM_TX;
case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
+ case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
+ case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
default: return -EINVAL;
}
@@ -299,6 +305,8 @@
case SLIMBUS_1_RX:
case SLIMBUS_1_TX:
case SLIMBUS_2_TX:
+ case SLIMBUS_4_RX:
+ case SLIMBUS_4_TX:
ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
break;
case RT_PROXY_PORT_001_RX:
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index c7ebd2c..f3a2383 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1228,6 +1228,10 @@
open.uMode = STREAM_PRIORITY_HIGH;
open.format = LINEAR_PCM;
break;
+ case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
+ open.uMode = STREAM_PRIORITY_HIGH;
+ open.format = MULTI_CHANNEL_PCM;
+ break;
case FORMAT_MPEG4_AAC:
open.uMode = BUFFER_META_ENABLE | STREAM_PRIORITY_HIGH;
open.format = MPEG4_AAC;
@@ -1664,6 +1668,56 @@
return -EINVAL;
}
+int q6asm_enc_cfg_blk_multi_ch_pcm(struct audio_client *ac,
+ uint32_t rate, uint32_t channels)
+{
+ struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
+
+ int rc = 0;
+
+ pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
+ ac->session, rate, channels);
+
+ q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+
+ enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
+ enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
+ enc_cfg.enc_blk.frames_per_buf = 1;
+ enc_cfg.enc_blk.format_id = MULTI_CHANNEL_PCM;
+ enc_cfg.enc_blk.cfg_size =
+ sizeof(struct asm_multi_channel_pcm_fmt_blk);
+ enc_cfg.enc_blk.cfg.mpcm.num_channels = channels;
+ enc_cfg.enc_blk.cfg.mpcm.bits_per_sample = 16;
+ enc_cfg.enc_blk.cfg.mpcm.sample_rate = rate;
+ enc_cfg.enc_blk.cfg.mpcm.is_signed = 1;
+ enc_cfg.enc_blk.cfg.mpcm.is_interleaved = 1;
+ enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
+ enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
+ enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = PCM_CHANNEL_RB;
+ enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = PCM_CHANNEL_LB;
+ enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
+ enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
+ enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
+ enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+ if (rc < 0) {
+ pr_err("Comamnd open failed\n");
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("timeout opcode[0x%x] ", enc_cfg.hdr.opcode);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
int q6asm_enable_sbrps(struct audio_client *ac,
uint32_t sbr_ps_enable)
{
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 6050929..f4b4dd1 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -33,6 +33,7 @@
#define VOC_PATH_PASSIVE 0
#define VOC_PATH_FULL 1
+#define VOC_PATH_VOLTE_PASSIVE 2
/* CVP CAL Size: 245760 = 240 * 1024 */
#define CVP_CAL_SIZE 245760
@@ -145,6 +146,9 @@
if (name != NULL) {
if (!strncmp(name, "Voice session", 13))
session_id = common.voice[VOC_PATH_PASSIVE].session_id;
+ else if (!strncmp(name, "VoLTE session", 13))
+ session_id =
+ common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
else
session_id = common.voice[VOC_PATH_FULL].session_id;
@@ -180,6 +184,11 @@
return (session_id == common.voice[VOC_PATH_FULL].session_id);
}
+static bool is_volte_session(u16 session_id)
+{
+ return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id);
+}
+
static int voice_apr_register(void)
{
pr_debug("%s\n", __func__);
@@ -250,6 +259,65 @@
return -ENODEV;
}
+static int voice_send_dual_control_cmd(struct voice_data *v)
+{
+ int ret = 0;
+ struct mvm_modem_dual_control_session_cmd mvm_voice_ctl_cmd;
+ void *apr_mvm;
+ u16 mvm_handle;
+
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ apr_mvm = common.apr_q6_mvm;
+ if (!apr_mvm) {
+ pr_err("%s: apr_mvm is NULL.\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: VoLTE command to MVM\n", __func__);
+ if (is_volte_session(v->session_id)) {
+ mvm_handle = voice_get_mvm_handle(v);
+ mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
+ APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ mvm_voice_ctl_cmd.hdr.pkt_size = APR_PKT_SIZE(
+ APR_HDR_SIZE,
+ sizeof(mvm_voice_ctl_cmd) -
+ APR_HDR_SIZE);
+ pr_debug("%s: send mvm Voice Ctl pkt size = %d\n",
+ __func__, mvm_voice_ctl_cmd.hdr.pkt_size);
+ mvm_voice_ctl_cmd.hdr.src_port = v->session_id;
+ mvm_voice_ctl_cmd.hdr.dest_port = mvm_handle;
+ mvm_voice_ctl_cmd.hdr.token = 0;
+ mvm_voice_ctl_cmd.hdr.opcode =
+ VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL;
+ mvm_voice_ctl_cmd.voice_ctl.enable_flag = true;
+ v->mvm_state = CMD_STATUS_FAIL;
+
+ ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_voice_ctl_cmd);
+ if (ret < 0) {
+ pr_err("%s: Error sending MVM Voice CTL CMD\n",
+ __func__);
+ ret = -EINVAL;
+ goto fail;
+ }
+ ret = wait_event_timeout(v->mvm_wait,
+ (v->mvm_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+ ret = 0;
+fail:
+ return ret;
+}
+
+
static int voice_create_mvm_cvs_session(struct voice_data *v)
{
int ret = 0;
@@ -281,7 +349,8 @@
/* send cmd to create mvm session and wait for response */
if (!mvm_handle) {
- if (is_voice_session(v->session_id)) {
+ if (is_voice_session(v->session_id) ||
+ is_volte_session(v->session_id)) {
mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
@@ -297,9 +366,15 @@
mvm_session_cmd.hdr.token = 0;
mvm_session_cmd.hdr.opcode =
VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
+ if (is_volte_session(v->session_id)) {
+ strlcpy(mvm_session_cmd.mvm_session.name,
+ "default volte voice",
+ sizeof(mvm_session_cmd.mvm_session.name));
+ } else {
strlcpy(mvm_session_cmd.mvm_session.name,
"default modem voice",
sizeof(mvm_session_cmd.mvm_session.name));
+ }
v->mvm_state = CMD_STATUS_FAIL;
@@ -356,7 +431,8 @@
}
/* send cmd to create cvs session */
if (!cvs_handle) {
- if (is_voice_session(v->session_id)) {
+ if (is_voice_session(v->session_id) ||
+ is_volte_session(v->session_id)) {
pr_debug("%s: creating CVS passive session\n",
__func__);
@@ -373,10 +449,15 @@
cvs_session_cmd.hdr.token = 0;
cvs_session_cmd.hdr.opcode =
VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
+ if (is_volte_session(v->session_id)) {
+ strlcpy(mvm_session_cmd.mvm_session.name,
+ "default volte voice",
+ sizeof(mvm_session_cmd.mvm_session.name));
+ } else {
strlcpy(cvs_session_cmd.cvs_session.name,
"default modem voice",
sizeof(cvs_session_cmd.cvs_session.name));
-
+ }
v->cvs_state = CMD_STATUS_FAIL;
ret = apr_send_pkt(apr_cvs,
@@ -3350,6 +3431,11 @@
pr_err("create mvm and cvs failed\n");
goto fail;
}
+ ret = voice_send_dual_control_cmd(v);
+ if (ret < 0) {
+ pr_err("Err Dual command failed\n");
+ goto fail;
+ }
ret = voice_setup_vocproc(v);
if (ret < 0) {
pr_err("setup voice failed\n");
@@ -3373,7 +3459,6 @@
v->voc_state = VOC_RUN;
}
-
fail: mutex_unlock(&v->lock);
return ret;
}
@@ -3471,6 +3556,7 @@
case VSS_ICOMMON_CMD_SET_NETWORK:
case VSS_ICOMMON_CMD_SET_VOICE_TIMING:
case VSS_IWIDEVOICE_CMD_SET_WIDEVOICE:
+ case VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL:
pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
v->mvm_state = CMD_STATUS_SUCCESS;
wake_up(&v->mvm_wait);
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 0fc7a01..cf691c0 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -107,6 +107,15 @@
#define VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION 0x000110FF
/**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
+#define VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL 0x00011327
+/*
+ * VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL
+ * Description: This command is required to let MVM know
+ * who is in control of session.
+ * Payload: Defined by vss_imvm_cmd_set_policy_dual_control_t.
+ * Result: Wait for APRV2_IBASIC_RSP_RESULT response.
+ */
+
#define VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION 0x000110FE
/* Create a new full control MVM session. */
@@ -154,6 +163,14 @@
#define VSS_IWIDEVOICE_CMD_SET_WIDEVOICE 0x00011243
/* Enable/disable WideVoice */
+enum msm_audio_voc_rate {
+ VOC_0_RATE, /* Blank frame */
+ VOC_8_RATE, /* 1/8 rate */
+ VOC_4_RATE, /* 1/4 rate */
+ VOC_2_RATE, /* 1/2 rate */
+ VOC_1_RATE /* Full rate */
+};
+
struct vss_istream_cmd_set_tty_mode_t {
uint32_t mode;
/**<
@@ -228,6 +245,12 @@
*/
} __packed;
+
+struct vss_imvm_cmd_set_policy_dual_control_t {
+ bool enable_flag;
+ /* Set to TRUE to enable modem state machine control */
+} __packed;
+
struct vss_iwidevoice_cmd_set_widevoice_t {
uint32_t enable;
/* WideVoice enable/disable; possible values:
@@ -251,6 +274,11 @@
struct vss_imvm_cmd_create_control_session_t mvm_session;
} __packed;
+struct mvm_modem_dual_control_session_cmd {
+ struct apr_hdr hdr;
+ struct vss_imvm_cmd_set_policy_dual_control_t voice_ctl;
+} __packed;
+
struct mvm_set_tty_mode_cmd {
struct apr_hdr hdr;
struct vss_istream_cmd_set_tty_mode_t tty_mode;
@@ -637,6 +665,10 @@
/* G.711 mu-law (contains two 10ms vocoder frames). */
#define VSS_MEDIA_ID_G729 0x00010FD0
/* G.729AB (contains two 10ms vocoder frames. */
+#define VSS_MEDIA_ID_4GV_NB_MODEM 0x00010FC3
+/*CDMA EVRC-B vocoder modem format */
+#define VSS_MEDIA_ID_4GV_WB_MODEM 0x00010FC4
+/*CDMA EVRC-WB vocoder modem format */
#define VSS_IVOCPROC_CMD_SET_MUTE 0x000110EF
@@ -878,7 +910,7 @@
void *buf;
};
-#define MAX_VOC_SESSIONS 2
+#define MAX_VOC_SESSIONS 3
#define SESSION_ID_BASE 0xFFF0
struct common_data {
@@ -947,6 +979,7 @@
#define VOICE_SESSION_NAME "Voice session"
#define VOIP_SESSION_NAME "VoIP session"
+#define VOLTE_SESSION_NAME "VoLTE session"
uint16_t voc_get_session_id(char *name);
int voc_start_playback(uint32_t set);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 0068c2a..f47b0d3 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3812,6 +3812,7 @@
mutex_init(&card->mutex);
mutex_init(&card->dapm_mutex);
mutex_init(&card->dsp_mutex);
+ spin_lock_init(&card->dsp_spinlock);
mutex_lock(&client_mutex);
list_add(&card->list, &card_list);
diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c
index 6d4f178..1fb5585 100644
--- a/sound/soc/soc-dsp.c
+++ b/sound/soc/soc-dsp.c
@@ -635,10 +635,15 @@
{
struct snd_soc_dsp_params *dsp_params;
int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fe->card->dsp_spinlock, flags);
if ((cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) ||
- (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH))
+ (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)) {
+ spin_unlock_irqrestore(&fe->card->dsp_spinlock, flags);
return ret;
+ }
list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
@@ -687,10 +692,14 @@
}
break;
}
- if (ret < 0)
+
+ if (ret < 0) {
+ spin_unlock_irqrestore(&fe->card->dsp_spinlock, flags);
return ret;
+ }
}
+ spin_unlock_irqrestore(&fe->card->dsp_spinlock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(soc_dsp_be_dai_trigger);