Merge "msm: acpuclock-7627: Avoid AXI freq. change while going into power collapse"
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index 3ee63c0..717dd8c 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -11,11 +11,10 @@
KERNEL_MODULES_OUT := $(TARGET_OUT)/lib/modules
KERNEL_IMG=$(KERNEL_OUT)/arch/arm/boot/Image
-MSM_ARCH ?= $(shell $(PERL) -e 'while (<>) {$$a = $$1 if /CONFIG_ARCH_((?:MSM|QSD)[a-zA-Z0-9]+)=y/; $$r = $$1 if /CONFIG_MSM_SOC_REV_(?!NONE)(\w+)=y/;} print lc("$$a$$r\n");' $(KERNEL_CONFIG))
+DTS_NAMES ?= $(shell $(PERL) -e 'while (<>) {$$a = $$1 if /CONFIG_ARCH_((?:MSM|QSD)[a-zA-Z0-9]+)=y/; $$r = $$1 if /CONFIG_MSM_SOC_REV_(?!NONE)(\w+)=y/; $$arch = $$arch.lc("$$a$$r ") if /CONFIG_ARCH_((?:MSM|QSD)[a-zA-Z0-9]+)=y/} print $$arch;' $(KERNEL_CONFIG))
KERNEL_USE_OF ?= $(shell $(PERL) -e '$$of = "n"; while (<>) { if (/CONFIG_USE_OF=y/) { $$of = "y"; break; } } print $$of;' kernel/arch/arm/configs/$(KERNEL_DEFCONFIG))
ifeq "$(KERNEL_USE_OF)" "y"
-DTS_NAME ?= $(MSM_ARCH)
DTS_FILES = $(wildcard $(TOP)/kernel/arch/arm/boot/dts/$(DTS_NAME)*.dts)
DTS_FILE = $(lastword $(subst /, ,$(1)))
DTB_FILE = $(addprefix $(KERNEL_OUT)/arch/arm/boot/,$(patsubst %.dts,%.dtb,$(call DTS_FILE,$(1))))
@@ -25,9 +24,10 @@
define append-dtb
mkdir -p $(KERNEL_OUT)/arch/arm/boot;\
-$(foreach d, $(DTS_FILES), \
- $(DTC) -p 1024 -O dtb -o $(call DTB_FILE,$(d)) $(d); \
- cat $(KERNEL_ZIMG) $(call DTB_FILE,$(d)) > $(call ZIMG_FILE,$(d));)
+$(foreach DTS_NAME, $(DTS_NAMES), \
+ $(foreach d, $(DTS_FILES), \
+ $(DTC) -p 1024 -O dtb -o $(call DTB_FILE,$(d)) $(d); \
+ cat $(KERNEL_ZIMG) $(call DTB_FILE,$(d)) > $(call ZIMG_FILE,$(d));))
endef
else
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 1fd96f9..de9e98c 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -58,6 +58,15 @@
status = "okay";
compatible = "qcom,rpm-regulator-smd";
};
+ pm8841_s1_so: regulator-s1-so {
+ regulator-name = "8841_s1_so";
+ qcom,set = <2>;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ qcom,init-voltage = <675000>;
+ status = "okay";
+ compatible = "qcom,rpm-regulator-smd";
+ };
};
rpm-regulator-smpb2 {
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 25d97af..aeb59af 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -53,6 +53,8 @@
CONFIG_PM8XXX_RPC_VIBRATOR=y
CONFIG_MSM_SPM_V2=y
CONFIG_MSM_MULTIMEDIA_USE_ION=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_CPR=y
CONFIG_MSM_VP_REGULATOR=y
CONFIG_ARM_THUMBEE=y
@@ -379,4 +381,3 @@
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 2c8f71e..b08869a 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -96,6 +96,7 @@
CONFIG_MSM_L1_ERR_PANIC=y
CONFIG_MSM_L1_ERR_LOG=y
CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_DCVS=y
CONFIG_MSM_HSIC_SYSMON=y
CONFIG_STRICT_MEMORY_RWX=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index a2deab2..26e7f32 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -87,6 +87,7 @@
CONFIG_MSM_RPM_RBCPR_STATS_LOG=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
+CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_WATCHDOG=y
CONFIG_MSM_DLOAD_MODE=y
CONFIG_MSM_RTB=y
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 7d26726..e46fd92 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -507,7 +507,7 @@
raw_spin_unlock(&stop_lock);
}
- set_cpu_online(cpu, false);
+ set_cpu_active(cpu, false);
local_fiq_disable();
local_irq_disable();
@@ -657,10 +657,10 @@
/* Wait up to one second for other CPUs to stop */
timeout = USEC_PER_SEC;
- while (num_online_cpus() > 1 && timeout--)
+ while (num_active_cpus() > 1 && timeout--)
udelay(1);
- if (num_online_cpus() > 1)
+ if (num_active_cpus() > 1)
pr_warning("SMP: failed to stop secondary CPUs\n");
smp_kill_cpus(&mask);
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index badee85..c9b786c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2142,6 +2142,14 @@
depends on PM
bool
+config MSM_EVENT_TIMER
+ bool "Event timer"
+ help
+ This option enables a modules that manages a list of event timers that
+ need to be monitored by the PM. The enables the PM code to monitor
+ events that require the core to be awake and ready to handle the
+ event.
+
config MSM_NOPM
default y if !PM
bool
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1be6e51..d8e625a 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -292,7 +292,7 @@
obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_MACH_APQ8064_LIQUID) += board-8064-all.o board-8064-regulator.o
-obj-$(CONFIG_MACH_MPQ8064_HRD) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_MPQ8064_HRD) += board-8064-all.o board-8064-regulator.o board-8064-bt.o
obj-$(CONFIG_MACH_MPQ8064_DTV) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
@@ -343,6 +343,7 @@
obj-$(CONFIG_MSM_BUSPM_DEV) += msm-buspm-dev.o
obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o iommu_domains.o
+obj-$(CONFIG_MSM_EVENT_TIMER) += event_timer.o
ifdef CONFIG_VCM
obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
diff --git a/arch/arm/mach-msm/board-8064-bt.c b/arch/arm/mach-msm/board-8064-bt.c
new file mode 100644
index 0000000..a8ae9fa
--- /dev/null
+++ b/arch/arm/mach-msm/board-8064-bt.c
@@ -0,0 +1,547 @@
+/* Copyright (c) 2011-2012, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/rfkill.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/marimba.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <mach/rpc_pmapp.h>
+#include <mach/msm_xo.h>
+#include <mach/socinfo.h>
+
+#include "board-8064.h"
+
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+
+#define BAHAMA_SLAVE_ID_FM_ADDR 0x2A
+#define BAHAMA_SLAVE_ID_QMEMBIST_ADDR 0x7B
+
+struct bt_vreg_info {
+ const char *name;
+ unsigned int pmapp_id;
+ unsigned int min_level;
+ unsigned int max_level;
+ unsigned int is_pin_controlled;
+ struct regulator *reg;
+};
+
+struct bahama_config_register {
+ u8 reg;
+ u8 value;
+ u8 mask;
+};
+static struct bt_vreg_info bt_vregs[] = {
+ {"bha_vddxo", 2, 1800000, 1800000, 0, NULL},
+ {"bha_vddpx", 21, 1800000, 1800000, 0, NULL},
+ {"bha_vddpa", 21, 2900000, 3300000, 0, NULL}
+};
+
+static struct msm_xo_voter *bt_clock;
+
+static struct platform_device msm_bt_power_device = {
+ .name = "bt_power",
+ .id = -1,
+};
+
+static unsigned bt_config_pcm_on[] = {
+ /*PCM_DOUT*/
+ GPIO_CFG(43, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+ /*PCM_DIN*/
+ GPIO_CFG(44, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+ /*PCM_SYNC*/
+ GPIO_CFG(45, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+ /*PCM_CLK*/
+ GPIO_CFG(46, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+};
+
+static unsigned bt_config_pcm_off[] = {
+ /*PCM_DOUT*/
+ GPIO_CFG(43, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /*PCM_DIN*/
+ GPIO_CFG(44, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /*PCM_SYNC*/
+ GPIO_CFG(45, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /*PCM_CLK*/
+ GPIO_CFG(46, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+};
+
+static int config_pcm(int mode)
+{
+ int pin, rc = 0;
+
+ if (mode == BT_PCM_ON) {
+ pr_err("%s mode =BT_PCM_ON", __func__);
+ for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_on);
+ pin++) {
+ rc = gpio_tlmm_config(bt_config_pcm_on[pin],
+ GPIO_CFG_ENABLE);
+ if (rc < 0)
+ return rc;
+ }
+ } else if (mode == BT_PCM_OFF) {
+ pr_err("%s mode =BT_PCM_OFF", __func__);
+ for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_off);
+ pin++) {
+ rc = gpio_tlmm_config(bt_config_pcm_off[pin],
+ GPIO_CFG_ENABLE);
+ if (rc < 0)
+ return rc;
+ }
+
+ }
+
+ return rc;
+}
+
+static int bahama_bt(int on)
+{
+ int rc = 0;
+ int i;
+
+ struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
+
+ struct bahama_variant_register {
+ const size_t size;
+ const struct bahama_config_register *set;
+ };
+
+ const struct bahama_config_register *p;
+
+ u8 version;
+
+ const struct bahama_config_register v10_bt_on[] = {
+ { 0xE9, 0x00, 0xFF },
+ { 0xF4, 0x80, 0xFF },
+ { 0xE4, 0x00, 0xFF },
+ { 0xE5, 0x00, 0x0F },
+#ifdef CONFIG_WLAN
+ { 0xE6, 0x38, 0x7F },
+ { 0xE7, 0x06, 0xFF },
+#endif
+ { 0xE9, 0x21, 0xFF },
+ { 0x01, 0x0C, 0x1F },
+ { 0x01, 0x08, 0x1F },
+ };
+
+ const struct bahama_config_register v20_bt_on_fm_off[] = {
+ { 0x11, 0x0C, 0xFF },
+ { 0x13, 0x01, 0xFF },
+ { 0xF4, 0x80, 0xFF },
+ { 0xF0, 0x00, 0xFF },
+ { 0xE9, 0x00, 0xFF },
+#ifdef CONFIG_WLAN
+ { 0x81, 0x00, 0x7F },
+ { 0x82, 0x00, 0xFF },
+ { 0xE6, 0x38, 0x7F },
+ { 0xE7, 0x06, 0xFF },
+#endif
+ { 0x8E, 0x15, 0xFF },
+ { 0x8F, 0x15, 0xFF },
+ { 0x90, 0x15, 0xFF },
+
+ { 0xE9, 0x21, 0xFF },
+ };
+
+ const struct bahama_config_register v20_bt_on_fm_on[] = {
+ { 0x11, 0x0C, 0xFF },
+ { 0x13, 0x01, 0xFF },
+ { 0xF4, 0x86, 0xFF },
+ { 0xF0, 0x06, 0xFF },
+ { 0xE9, 0x00, 0xFF },
+#ifdef CONFIG_WLAN
+ { 0x81, 0x00, 0x7F },
+ { 0x82, 0x00, 0xFF },
+ { 0xE6, 0x38, 0x7F },
+ { 0xE7, 0x06, 0xFF },
+#endif
+ { 0xE9, 0x21, 0xFF },
+ };
+
+ const struct bahama_config_register v10_bt_off[] = {
+ { 0xE9, 0x00, 0xFF },
+ };
+
+ const struct bahama_config_register v20_bt_off_fm_off[] = {
+ { 0xF4, 0x84, 0xFF },
+ { 0xF0, 0x04, 0xFF },
+ { 0xE9, 0x00, 0xFF }
+ };
+
+ const struct bahama_config_register v20_bt_off_fm_on[] = {
+ { 0xF4, 0x86, 0xFF },
+ { 0xF0, 0x06, 0xFF },
+ { 0xE9, 0x00, 0xFF }
+ };
+
+ const struct bahama_variant_register bt_bahama[2][3] = {
+ {
+ { ARRAY_SIZE(v10_bt_off), v10_bt_off },
+ { ARRAY_SIZE(v20_bt_off_fm_off), v20_bt_off_fm_off },
+ { ARRAY_SIZE(v20_bt_off_fm_on), v20_bt_off_fm_on }
+ },
+ {
+ { ARRAY_SIZE(v10_bt_on), v10_bt_on },
+ { ARRAY_SIZE(v20_bt_on_fm_off), v20_bt_on_fm_off },
+ { ARRAY_SIZE(v20_bt_on_fm_on), v20_bt_on_fm_on }
+ }
+ };
+
+ u8 offset = 0; /* index into bahama configs */
+ on = on ? 1 : 0;
+ version = marimba_read_bahama_ver(&config);
+ if ((int)version < 0 || version == BAHAMA_VER_UNSUPPORTED) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s : Bahama version read Error, version = %d\n",
+ __func__, version);
+ return -EIO;
+ }
+ if (version == BAHAMA_VER_2_0) {
+ if (marimba_get_fm_status(&config))
+ offset = 0x01;
+ }
+
+ p = bt_bahama[on][version + offset].set;
+
+ dev_dbg(&msm_bt_power_device.dev,
+ "%s: found version %d\n", __func__, version);
+
+ for (i = 0; i < bt_bahama[on][version + offset].size; i++) {
+ u8 value = (p+i)->value;
+ rc = marimba_write_bit_mask(&config,
+ (p+i)->reg,
+ &value,
+ sizeof((p+i)->value),
+ (p+i)->mask);
+ if (rc < 0) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: reg %x write failed: %d\n",
+ __func__, (p+i)->reg, rc);
+ return rc;
+ }
+ dev_dbg(&msm_bt_power_device.dev,
+ "%s: reg 0x%02x write value 0x%02x mask 0x%02x\n",
+ __func__, (p+i)->reg,
+ value, (p+i)->mask);
+ value = 0;
+ rc = marimba_read_bit_mask(&config,
+ (p+i)->reg, &value,
+ sizeof((p+i)->value), (p+i)->mask);
+ if (rc < 0)
+ dev_err(&msm_bt_power_device.dev,
+ "%s marimba_read_bit_mask- error",
+ __func__);
+ dev_dbg(&msm_bt_power_device.dev,
+ "%s: reg 0x%02x read value 0x%02x mask 0x%02x\n",
+ __func__, (p+i)->reg,
+ value, (p+i)->mask);
+ }
+ /* Update BT Status */
+ if (on)
+ marimba_set_bt_status(&config, true);
+ else
+ marimba_set_bt_status(&config, false);
+ return rc;
+}
+
+static int bluetooth_switch_regulators(int on)
+{
+ int i, rc = 0;
+
+ for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+ if (IS_ERR_OR_NULL(bt_vregs[i].reg)) {
+ bt_vregs[i].reg =
+ regulator_get(&msm_bt_power_device.dev,
+ bt_vregs[i].name);
+ if (IS_ERR(bt_vregs[i].reg)) {
+ rc = PTR_ERR(bt_vregs[i].reg);
+ dev_err(&msm_bt_power_device.dev,
+ "%s: invalid regulator handle for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+ }
+ rc = on ? regulator_set_voltage(bt_vregs[i].reg,
+ bt_vregs[i].min_level,
+ bt_vregs[i].max_level) : 0;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not set voltage for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+
+ rc = on ? regulator_enable(bt_vregs[i].reg) : 0;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not %sable regulator %s: %d\n",
+ __func__, "en", bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+
+ rc = on ? 0 : regulator_disable(bt_vregs[i].reg);
+
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not %sable regulator %s: %d\n",
+ __func__, "dis", bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+ }
+
+ return rc;
+reg_disable:
+ pr_err("bluetooth_switch_regulators - FAIL!!!!\n");
+ while (i) {
+ if (on) {
+ i--;
+ regulator_disable(bt_vregs[i].reg);
+ regulator_put(bt_vregs[i].reg);
+ bt_vregs[i].reg = NULL;
+ }
+ }
+ return rc;
+}
+
+static unsigned int msm_bahama_setup_power(void)
+{
+ int rc = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+ bt_vregs[i].reg = regulator_get(&msm_bt_power_device.dev,
+ bt_vregs[i].name);
+ if (IS_ERR(bt_vregs[i].reg)) {
+ rc = PTR_ERR(bt_vregs[i].reg);
+ pr_err("%s: could not get regulator %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_fail;
+ }
+ rc = regulator_set_voltage(bt_vregs[i].reg,
+ bt_vregs[i].min_level,
+ bt_vregs[i].max_level);
+ if (rc) {
+ pr_err("%s: could not set voltage for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_fail;
+ }
+ rc = regulator_enable(bt_vregs[i].reg);
+ if (rc) {
+ pr_err("%s: could not enable regulator %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_fail;
+ }
+ }
+ return rc;
+reg_fail:
+ pr_err("msm_bahama_setup_power FAILED !!!\n");
+
+ while (i) {
+ i--;
+ regulator_disable(bt_vregs[i].reg);
+ regulator_put(bt_vregs[i].reg);
+ bt_vregs[i].reg = NULL;
+ }
+ return rc;
+}
+
+static unsigned int msm_bahama_shutdown_power(int value)
+{
+ int rc = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+ rc = regulator_disable(bt_vregs[i].reg);
+
+ if (rc < 0) {
+ pr_err("%s: could not disable regulator %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto out;
+ }
+
+ regulator_put(bt_vregs[i].reg);
+ bt_vregs[i].reg = NULL;
+ }
+out:
+ return rc;
+}
+
+static unsigned int msm_bahama_core_config(int type)
+{
+ int rc = 0;
+
+ if (type == BAHAMA_ID) {
+ int i;
+ struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
+ const struct bahama_config_register v20_init[] = {
+ /* reg, value, mask */
+ { 0xF4, 0x84, 0xFF }, /* AREG */
+ { 0xF0, 0x04, 0xFF } /* DREG */
+ };
+ if (marimba_read_bahama_ver(&config) == BAHAMA_VER_2_0) {
+ for (i = 0; i < ARRAY_SIZE(v20_init); i++) {
+ u8 value = v20_init[i].value;
+ rc = marimba_write_bit_mask(&config,
+ v20_init[i].reg,
+ &value,
+ sizeof(v20_init[i].value),
+ v20_init[i].mask);
+ if (rc < 0) {
+ pr_err("%s: reg %d write failed: %d\n",
+ __func__, v20_init[i].reg, rc);
+ return rc;
+ }
+ pr_debug("%s: reg 0x%02x value 0x%02x mask 0x%02x\n",
+ __func__, v20_init[i].reg,
+ v20_init[i].value, v20_init[i].mask);
+ }
+ }
+ }
+ pr_debug("core type: %d\n", type);
+ return rc;
+}
+
+static int bluetooth_power(int on)
+{
+ int rc = 0;
+ const char *id = "BTPW";
+ int cid = 0;
+
+ pr_debug("bluetooth_power entered....\n");
+ cid = adie_get_detected_connectivity_type();
+ if (cid != BAHAMA_ID) {
+ pr_err("%s: unexpected adie connectivity type: %d\n",
+ __func__, cid);
+ return -ENODEV;
+ }
+
+ if (on) {
+ rc = bluetooth_switch_regulators(on);
+ if (rc < 0) {
+ pr_err("%s: bluetooth_switch_regulators rc = %d",
+ __func__, rc);
+ goto exit;
+ }
+ /* UART GPIO configuration to be done by by UART module*/
+ /*Setup BT clocks*/
+ bt_clock = msm_xo_get(MSM_XO_TCXO_A2, id);
+ if (IS_ERR(bt_clock)) {
+ rc = PTR_ERR(bt_clock);
+ pr_err("%s: failed to get the handle for A2(%d)\n",
+ __func__, rc);
+ }
+ rc = msm_xo_mode_vote(bt_clock, MSM_XO_MODE_ON);
+ if (rc < 0) {
+ pr_err("%s: Failed to vote for TCXO_A2 ON\n", __func__);
+ goto fail_xo_vote;
+ }
+ msleep(20);
+
+ /*I2C config for Bahama*/
+ rc = bahama_bt(1);
+ if (rc < 0) {
+ pr_err("%s: bahama_bt rc = %d", __func__, rc);
+ goto fail_i2c;
+ }
+ msleep(20);
+
+ /*setup BT PCM lines*/
+ rc = config_pcm(BT_PCM_ON);
+ if (rc < 0) {
+ pr_err("%s: config_pcm , rc =%d\n",
+ __func__, rc);
+ goto fail_power;
+ }
+ /* TO DO - Enable PIN CTRL */
+ /*
+ rc = msm_xo_mode_vote(bt_clock, MSM_XO_MODE_PIN_CTRL);
+ if (rc < 0) {
+ pr_err("%s: Failed to vote for TCXO_A2 in PIN_CTRL\n",
+ __func__);
+ goto fail_xo_vote;
+ } */
+ } else {
+ rc = bahama_bt(0);
+ if (rc < 0)
+ pr_err("%s: bahama_bt rc = %d", __func__, rc);
+
+ rc = config_pcm(BT_PCM_OFF);
+ if (rc < 0) {
+ pr_err("%s: msm_bahama_setup_pcm_i2s, rc =%d\n",
+ __func__, rc);
+ }
+fail_i2c:
+ pr_err("bluetooth_power...FAIL_I2C\n");
+
+fail_xo_vote:
+ pr_err("bluetooth_power...FAIL_XO_VOTE\n");
+ msm_xo_put(bt_clock);
+fail_power:
+ pr_err("bluetooth_power...FAIL POWER\n");
+ rc = bluetooth_switch_regulators(0);
+ if (rc < 0) {
+ pr_err("%s: switch_regulators : rc = %d",\
+ __func__, rc);
+ goto exit;
+ }
+ }
+ return rc;
+exit:
+ pr_err("%s: failed with rc = %d", __func__, rc);
+ return rc;
+}
+
+static struct marimba_platform_data marimba_pdata = {
+ .slave_id[SLAVE_ID_BAHAMA_FM] = BAHAMA_SLAVE_ID_FM_ADDR,
+ .slave_id[SLAVE_ID_BAHAMA_QMEMBIST] = BAHAMA_SLAVE_ID_QMEMBIST_ADDR,
+ .bahama_setup = msm_bahama_setup_power,
+ .bahama_shutdown = msm_bahama_shutdown_power,
+ .bahama_core_config = msm_bahama_core_config,
+ .fm = NULL,
+};
+
+static struct i2c_board_info bahama_devices[] = {
+{
+ I2C_BOARD_INFO("marimba", 0xc),
+ .platform_data = &marimba_pdata,
+},
+};
+
+void __init apq8064_bt_power_init(void)
+{
+ int rc = 0;
+ struct device *dev;
+
+ rc = i2c_register_board_info(APQ_8064_GSBI5_QUP_I2C_BUS_ID,
+ bahama_devices,
+ ARRAY_SIZE(bahama_devices));
+ if (rc < 0) {
+ pr_err("%s: I2C Register failed\n", __func__);
+ return;
+ }
+ rc = platform_device_register(&msm_bt_power_device);
+ if (rc < 0) {
+ pr_err("%s: device register failed\n", __func__);
+ platform_device_unregister(&msm_bt_power_device);
+ return;
+ }
+
+ dev = &msm_bt_power_device.dev;
+ dev->platform_data = &bluetooth_power;
+
+ return;
+}
+#endif
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index f4e9a8f..a08f45c 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -1477,9 +1477,9 @@
pr_err(KERN_ERR "msm_gpiomux_init failed %d\n", rc);
return;
}
-
- msm_gpiomux_install(wcnss_5wire_interface,
- ARRAY_SIZE(wcnss_5wire_interface));
+ if (!(machine_is_mpq8064_hrd()))
+ msm_gpiomux_install(wcnss_5wire_interface,
+ ARRAY_SIZE(wcnss_5wire_interface));
if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()) {
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index c1798bf..bbb9a81 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -47,6 +47,7 @@
REGULATOR_SUPPLY("8921_l4", NULL),
REGULATOR_SUPPLY("HSUSB_1p8", "msm_otg"),
REGULATOR_SUPPLY("iris_vddxo", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("bha_vddxo", "bt_power"),
};
VREG_CONSUMERS(L5) = {
REGULATOR_SUPPLY("8921_l5", NULL),
@@ -75,6 +76,7 @@
VREG_CONSUMERS(L10) = {
REGULATOR_SUPPLY("8921_l10", NULL),
REGULATOR_SUPPLY("iris_vddpa", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("bha_vddpa", "bt_power"),
};
VREG_CONSUMERS(L11) = {
REGULATOR_SUPPLY("8921_l11", NULL),
@@ -182,6 +184,7 @@
REGULATOR_SUPPLY("CDC_VDDA_TX", "0-000d"),
REGULATOR_SUPPLY("CDC_VDDA_RX", "0-000d"),
REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("bha_vddpx", "bt_power"),
REGULATOR_SUPPLY("vcc_i2c", "3-005b"),
REGULATOR_SUPPLY("vcc_i2c", "3-0024"),
REGULATOR_SUPPLY("vddp", "0-0048"),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ec52d1a..8755f08 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -3443,6 +3443,11 @@
#endif
}
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+ if (machine_is_mpq8064_hrd())
+ apq8064_bt_power_init();
+#endif
+
if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
platform_device_register(&cdp_kp_pdev);
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 740fa39..5d6f988 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -110,6 +110,10 @@
void apq8064_pm8xxx_gpio_mpp_init(void);
void __init configure_apq8064_pm8917_power_grid(void);
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+void __init apq8064_bt_power_init(void);
+#endif
+
#define PLATFORM_IS_MPQ8064() \
(machine_is_mpq8064_hrd() || \
machine_is_mpq8064_dtv() || \
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 3a82b07..7c9f652 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2822,19 +2822,24 @@
msm_kgsl_3d0.dev.platform_data;
uint32_t soc_platform_version = socinfo_get_version();
+ /* Fixup data that needs to change based on GPU ID */
if (cpu_is_msm8960ab()) {
kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
/* 8960PRO nominal clock rate is 325Mhz instead of 320Mhz */
kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 325000000;
- } else if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
- kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
- kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
- } else if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
- /* 8960v3 GPU registers returns 5 for patch release
- * but it should be 6, so dummy up the chipid here
- * based the platform type
- */
- kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+ } else {
+ kgsl_3d0_pdata->iommu_count = 1;
+ if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
+ kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+ kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
+ }
+ if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
+ /* 8960v3 GPU registers returns 5 for patch release
+ * but it should be 6, so dummy up the chipid here
+ * based the platform type
+ */
+ kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+ }
}
/* Register the 3D core */
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index d22690c..33782ab 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -3145,18 +3145,29 @@
},
};
-static const struct kgsl_iommu_ctx kgsl_3d0_iommu_ctxs[] = {
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu0_ctxs[] = {
{ "gfx3d_user", 0 },
{ "gfx3d_priv", 1 },
};
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu1_ctxs[] = {
+ { "gfx3d1_user", 0 },
+ { "gfx3d1_priv", 1 },
+};
+
static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = {
{
- .iommu_ctxs = kgsl_3d0_iommu_ctxs,
- .iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu_ctxs),
+ .iommu_ctxs = kgsl_3d0_iommu0_ctxs,
+ .iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu0_ctxs),
.physstart = 0x07C00000,
.physend = 0x07C00000 + SZ_1M - 1,
},
+ {
+ .iommu_ctxs = kgsl_3d0_iommu1_ctxs,
+ .iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu1_ctxs),
+ .physstart = 0x07D00000,
+ .physend = 0x07D00000 + SZ_1M - 1,
+ },
};
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
diff --git a/arch/arm/mach-msm/event_timer.c b/arch/arm/mach-msm/event_timer.c
new file mode 100644
index 0000000..e06dad4
--- /dev/null
+++ b/arch/arm/mach-msm/event_timer.c
@@ -0,0 +1,318 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <mach/event_timer.h>
+
+#define __INIT_HEAD(x) { .head = RB_ROOT,\
+ .next = NULL, }
+
+#define DEFINE_TIME_HEAD(x) struct timerqueue_head x = __INIT_HEAD(x)
+
+/**
+ * struct event_timer_info - basic event timer structure
+ * @node: timerqueue node to track time ordered data structure
+ * of event timers
+ * @timer: hrtimer created for this event.
+ * @function : callback function for event timer.
+ * @data : callback data for event timer.
+ */
+struct event_timer_info {
+ struct timerqueue_node node;
+ void (*function)(void *);
+ void *data;
+};
+
+
+static DEFINE_TIME_HEAD(timer_head);
+static DEFINE_SPINLOCK(event_timer_lock);
+static struct hrtimer event_hrtimer;
+static enum hrtimer_restart event_hrtimer_cb(struct hrtimer *hrtimer);
+
+static int msm_event_debug_mask;
+module_param_named(
+ debug_mask, msm_event_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP
+);
+
+enum {
+ MSM_EVENT_TIMER_DEBUG = 1U << 0,
+};
+
+
+/**
+ * add_event_timer() : Add a wakeup event. Intended to be called
+ * by clients once. Returns a handle to be used
+ * for future transactions.
+ * @function : The callback function will be called when event
+ * timer expires.
+ * @data: callback data provided by client.
+ */
+struct event_timer_info *add_event_timer(void (*function)(void *), void *data)
+{
+ struct event_timer_info *event_info =
+ kzalloc(sizeof(struct event_timer_info), GFP_KERNEL);
+
+ if (!event_info)
+ return NULL;
+
+ event_info->function = function;
+ event_info->data = data;
+ /* Init rb node and hr timer */
+ timerqueue_init(&event_info->node);
+
+ return event_info;
+}
+
+/**
+ * is_event_next(): Helper function to check if the event is the next
+ * next expiring event
+ * @event : handle to the event to be checked.
+ */
+static bool is_event_next(struct event_timer_info *event)
+{
+ struct event_timer_info *next_event;
+ struct timerqueue_node *next;
+ bool ret = false;
+
+ next = timerqueue_getnext(&timer_head);
+ if (!next)
+ goto exit_is_next_event;
+
+ next_event = container_of(next, struct event_timer_info, node);
+ if (!next_event)
+ goto exit_is_next_event;
+
+ if (next_event == event)
+ ret = true;
+
+exit_is_next_event:
+ return ret;
+}
+
+/**
+ * is_event_active(): Helper function to check if the timer for a given event
+ * has been started.
+ * @event : handle to the event to be checked.
+ */
+static bool is_event_active(struct event_timer_info *event)
+{
+ struct timerqueue_node *next;
+ struct event_timer_info *next_event;
+ bool ret = false;
+
+ for (next = timerqueue_getnext(&timer_head); next;
+ next = timerqueue_iterate_next(next)) {
+ next_event = container_of(next, struct event_timer_info, node);
+
+ if (event == next_event) {
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+}
+
+/**
+ * create_httimer(): Helper function to setup hrtimer.
+ */
+static void create_hrtimer(ktime_t expires)
+{
+ static bool timer_initialized;
+
+ if (!timer_initialized) {
+ hrtimer_init(&event_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ timer_initialized = true;
+ }
+
+ event_hrtimer.function = event_hrtimer_cb;
+ hrtimer_start(&event_hrtimer, expires, HRTIMER_MODE_ABS);
+
+ if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+ pr_info("%s: Setting timer for %lu", __func__,
+ (unsigned long)ktime_to_ns(expires));
+}
+
+/**
+ * event_hrtimer_cb() : Callback function for hr timer.
+ * Make the client CB from here and remove the event
+ * from the time ordered queue.
+ */
+static enum hrtimer_restart event_hrtimer_cb(struct hrtimer *hrtimer)
+{
+ struct event_timer_info *event;
+ struct timerqueue_node *next;
+
+ next = timerqueue_getnext(&timer_head);
+
+ while (next && (ktime_to_ns(next->expires)
+ <= ktime_to_ns(hrtimer->node.expires))) {
+ if (!next)
+ goto hrtimer_cb_exit;
+
+ event = container_of(next, struct event_timer_info, node);
+ if (!event)
+ goto hrtimer_cb_exit;
+
+ if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+ pr_info("%s: Deleting event @ %lu", __func__,
+ (unsigned long)ktime_to_ns(next->expires));
+
+ timerqueue_del(&timer_head, &event->node);
+
+ if (event->function)
+ event->function(event->data);
+ next = timerqueue_getnext(&timer_head);
+ }
+
+ if (next)
+ create_hrtimer(next->expires);
+
+hrtimer_cb_exit:
+ return HRTIMER_NORESTART;
+}
+
+/**
+ * create_timer_smp(): Helper function used setting up timer on core 0.
+ */
+static void create_timer_smp(void *data)
+{
+ unsigned long flags;
+ struct event_timer_info *event =
+ (struct event_timer_info *)data;
+
+ local_irq_save(flags);
+ create_hrtimer(event->node.expires);
+ local_irq_restore(flags);
+}
+
+/**
+ * setup_timer() : Helper function to setup timer on primary
+ * core during hrtimer callback.
+ * @event: event handle causing the wakeup.
+ */
+static void setup_event_hrtimer(struct event_timer_info *event)
+{
+ struct timerqueue_node *next;
+ unsigned long flags;
+
+ spin_lock_irqsave(&event_timer_lock, flags);
+ if (is_event_active(event))
+ timerqueue_del(&timer_head, &event->node);
+
+ next = timerqueue_getnext(&timer_head);
+ timerqueue_add(&timer_head, &event->node);
+ spin_unlock_irqrestore(&event_timer_lock, flags);
+
+ if (!next ||
+ (next && (ktime_to_ns(event->node.expires) <
+ ktime_to_ns(next->expires)))) {
+ if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+ pr_info("%s: Setting timer for %lu", __func__,
+ (unsigned long)ktime_to_ns(event->node.expires));
+
+ smp_call_function_single(0, create_timer_smp, event, 1);
+ }
+}
+
+/**
+ * activate_event_timer() : Set the expiration time for an event in absolute
+ * ktime. This is a oneshot event timer, clients
+ * should call this again to set another expiration.
+ * @event : event handle.
+ * @event_time : event time in absolute ktime.
+ */
+void activate_event_timer(struct event_timer_info *event, ktime_t event_time)
+{
+ if (!event)
+ return;
+
+ if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+ pr_info("%s: Adding event timer @ %lu", __func__,
+ (unsigned long)ktime_to_us(event_time));
+
+ event->node.expires = event_time;
+ /* Start hr timer and add event to rb tree */
+ setup_event_hrtimer(event);
+}
+
+
+/**
+ * deactivate_event_timer() : Deactivate an event timer, this removes the event from
+ * the time ordered queue of event timers.
+ * @event: event handle.
+ */
+void deactivate_event_timer(struct event_timer_info *event)
+{
+ unsigned long flags;
+
+ if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+ pr_info("%s: Deactivate timer", __func__);
+
+ spin_lock_irqsave(&event_timer_lock, flags);
+ if (is_event_active(event)) {
+ if (is_event_next(event))
+ hrtimer_try_to_cancel(&event_hrtimer);
+
+ timerqueue_del(&timer_head, &event->node);
+ }
+ spin_unlock_irqrestore(&event_timer_lock, flags);
+}
+
+/**
+ * destroy_event_timer() : Free the event info data structure allocated during
+ * add_event_timer().
+ * @event: event handle.
+ */
+void destroy_event_timer(struct event_timer_info *event)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&event_timer_lock, flags);
+ if (is_event_active(event)) {
+ if (is_event_next(event))
+ hrtimer_try_to_cancel(&event_hrtimer);
+
+ timerqueue_del(&timer_head, &event->node);
+ }
+ spin_unlock_irqrestore(&event_timer_lock, flags);
+ kfree(event);
+}
+
+/**
+ * get_next_event_timer() - Get the next wakeup event. Returns
+ * a ktime value of the next expiring event.
+ */
+ktime_t get_next_event_time(void)
+{
+ unsigned long flags;
+ struct timerqueue_node *next;
+ ktime_t next_event = ns_to_ktime(0);
+
+ spin_lock_irqsave(&event_timer_lock, flags);
+ next = timerqueue_getnext(&timer_head);
+ spin_unlock_irqrestore(&event_timer_lock, flags);
+
+ if (!next)
+ return next_event;
+
+ next_event = hrtimer_get_remaining(&event_hrtimer);
+ if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+ pr_info("%s: Next Event %lu", __func__,
+ (unsigned long)ktime_to_us(next_event));
+
+ return next_event;
+}
diff --git a/arch/arm/mach-msm/include/mach/event_timer.h b/arch/arm/mach-msm/include/mach/event_timer.h
new file mode 100644
index 0000000..7a00b23
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/event_timer.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2012, The Linux Foundation. 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_EVENT_TIMER_H
+#define __ARCH_ARM_MACH_MSM_EVENT_TIMER_H
+
+#include <linux/hrtimer.h>
+
+struct event_timer_info;
+
+#ifdef CONFIG_MSM_EVENT_TIMER
+/**
+ * add_event_timer() : Add a wakeup event. Intended to be called
+ * by clients once. Returns a handle to be used
+ * for future transactions.
+ * @function : The callback function will be called when event
+ * timer expires.
+ * @data : Callback data provided by client.
+ */
+struct event_timer_info *add_event_timer(void (*function)(void *), void *data);
+
+/** activate_event_timer() : Set the expiration time for an event in absolute
+ * ktime. This is a oneshot event timer, clients
+ * should call this again to set another expiration.
+ * @event : Event handle.
+ * @event_time : Event time in absolute ktime.
+ */
+void activate_event_timer(struct event_timer_info *event, ktime_t event_time);
+
+/**
+ * deactivate_event_timer() : Deactivate an event timer.
+ * @event: event handle.
+ */
+void deactivate_event_timer(struct event_timer_info *event);
+
+/**
+ * destroy_event_timer() : Free the event info data structure allocated during
+ * add_event_timer().
+ * @event: event handle.
+ */
+void destroy_event_timer(struct event_timer_info *event);
+
+/**
+ * get_next_event_timer() : Get the next wakeup event.
+ * returns a ktime value of the next
+ * expiring event.
+ */
+ktime_t get_next_event_time(void);
+#else
+static inline void *add_event_timer(void (*function)(void *), void *data)
+{
+ return NULL;
+}
+
+static inline void activate_event_timer(void *event, ktime_t event_time) {}
+
+static inline void deactivate_event_timer(void *event) {}
+
+static inline void destroy_event_timer(void *event) {}
+
+static inline ktime_t get_next_event_time(void)
+{
+ return ns_to_ktime(0);
+}
+
+#endif /* CONFIG_MSM_EVENT_TIMER_MANAGER */
+#endif /* __ARCH_ARM_MACH_MSM_EVENT_TIMER_H */
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 5430f99..e0fec65 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -497,7 +497,7 @@
void __init msm_map_mpq8092_io(void)
{
- msm_shared_ram_phys = MSM8974_MSM_SHARED_RAM_PHYS;
+ msm_shared_ram_phys = MSM8092_MSM_SHARED_RAM_PHYS;
msm_map_io(mpq8092_io_desc, ARRAY_SIZE(mpq8092_io_desc));
}
#endif /* CONFIG_ARCH_MPQ8092 */
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 3040a31..ba0e242 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -21,6 +21,7 @@
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
+#include <asm/mach-types.h>
#include <mach/msm_iomap.h>
#include "peripheral-loader.h"
@@ -358,12 +359,18 @@
static int __init pil_riva_init(void)
{
+ if (machine_is_mpq8064_hrd()) {
+ pr_err("pil_riva not supported on this target\n");
+ return 0;
+ }
return platform_driver_register(&pil_riva_driver);
}
module_init(pil_riva_init);
static void __exit pil_riva_exit(void)
{
+ if (machine_is_mpq8064_hrd())
+ return;
platform_driver_unregister(&pil_riva_driver);
}
module_exit(pil_riva_exit);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
index 485234f..44ab611 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-2012, The Linux Foundation. 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
@@ -81,7 +81,13 @@
aac_cfg.spectral_data_resilience =
aac_config->aac_spectral_data_resilience_flag;
aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
- aac_cfg.sample_rate = audio->pcm_cfg.sample_rate;
+ if (audio->feedback == TUNNEL_MODE) {
+ aac_cfg.sample_rate = aac_config->sample_rate;
+ aac_cfg.ch_cfg = aac_config->channel_configuration;
+ } else {
+ aac_cfg.sample_rate = audio->pcm_cfg.sample_rate;
+ aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
+ }
pr_debug("%s:format=%x aot=%d ch=%d sr=%d\n",
__func__, aac_cfg.format,
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index fbd94c5..b53edd9 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-2012, The Linux Foundation. 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
@@ -43,8 +43,13 @@
struct msm_audio_aac_config *aac_config;
uint32_t sbr_ps = 0x00;
aac_config = (struct msm_audio_aac_config *)audio->codec_cfg;
- aac_cfg.ch_cfg = aac_config->channel_configuration;
- aac_cfg.sample_rate = audio->pcm_cfg.sample_rate;
+ if (audio->feedback == TUNNEL_MODE) {
+ aac_cfg.sample_rate = aac_config->sample_rate;
+ aac_cfg.ch_cfg = aac_config->channel_configuration;
+ } else {
+ aac_cfg.sample_rate = audio->pcm_cfg.sample_rate;
+ aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
+ }
pr_debug("%s: AUDIO_START session_id[%d]\n", __func__,
audio->ac->session);
if (audio->feedback == NON_TUNNEL_MODE) {
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 25723d5..53736ac 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -26,6 +26,7 @@
#include <linux/mfd/pm8xxx/misc.h>
#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
#include <mach/msm_iomap.h>
#include <mach/restart.h>
@@ -221,6 +222,8 @@
__raw_writel(0x77665501, restart_reason);
}
}
+
+ flush_cache_all();
}
void msm_restart(char mode, const char *cmd)
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 318523b..f014df9 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/wcnss_wlan.h>
#include <linux/err.h>
+#include <asm/mach-types.h>
#include <mach/irqs.h>
#include <mach/scm.h>
#include <mach/subsystem_restart.h>
@@ -221,6 +222,11 @@
{
int ret;
+ if (machine_is_mpq8064_hrd()) {
+ pr_err("Riva not supported on this target\n");
+ return 0;
+ }
+
ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
smsm_state_cb_hdlr, 0);
if (ret < 0) {
@@ -259,6 +265,8 @@
static void __exit riva_ssr_module_exit(void)
{
+ if (machine_is_mpq8064_hrd())
+ return;
subsys_unregister(riva_8960_dev);
free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
}
diff --git a/drivers/base/sync.c b/drivers/base/sync.c
index 9bc0da5..c0690c8 100644
--- a/drivers/base/sync.c
+++ b/drivers/base/sync.c
@@ -218,8 +218,10 @@
spin_lock_irqsave(&obj->active_list_lock, flags);
err = _sync_pt_has_signaled(pt);
- if (err != 0)
+ if (err != 0) {
+ sync_fence_signal_pt(pt);
goto out;
+ }
list_add_tail(&pt->active_list, &obj->active_list_head);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 1c14859..b18d709 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -279,12 +279,14 @@
struct diag_request *write_ptr_mdm;
/* HSIC variables */
int hsic_ch;
+ int hsic_inited;
int hsic_device_enabled;
int hsic_device_opened;
int hsic_suspend;
int in_busy_hsic_read_on_device;
int in_busy_hsic_write;
struct work_struct diag_read_hsic_work;
+ struct mutex bridge_mutex;
/* USB MDM channel variables */
int usb_mdm_connected;
int read_len_mdm;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 7e827b9..59139dc 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -93,6 +93,9 @@
ret += length; \
} while (0)
+/* Identifier for data from MDM */
+#define MDM_TOKEN -1
+
static void drain_timer_func(unsigned long data)
{
queue_work(driver->diag_wq , &(driver->diag_drain_work));
@@ -650,6 +653,10 @@
{
int index = -1, i = 0, ret = 0;
int num_data = 0, data_type;
+#if defined(CONFIG_DIAG_SDIO_PIPE) || defined(CONFIG_DIAG_BRIDGE_CODE)
+ int mdm_token = MDM_TOKEN;
+#endif
+
for (i = 0; i < driver->num_clients; i++)
if (driver->client_map[i].pid == current->tgid)
index = i;
@@ -789,6 +796,8 @@
/* copy 9K data over SDIO */
if (driver->in_busy_sdio == 1) {
num_data++;
+ /*Copy the negative token of data being passed*/
+ COPY_USER_SPACE_OR_EXIT(buf+ret, mdm_token, 4);
/*Copy the length of data being passed*/
COPY_USER_SPACE_OR_EXIT(buf+ret,
(driver->write_ptr_mdm->length), 4);
@@ -818,6 +827,14 @@
i, (unsigned int)hsic_buf_tbl[i].buf,
hsic_buf_tbl[i].length);
num_data++;
+
+ /* Copy the negative token */
+ if (copy_to_user(buf+ret, &mdm_token, 4)) {
+ num_data--;
+ goto drop_hsic;
+ }
+ ret += 4;
+
/* Copy the length of data being passed */
if (copy_to_user(buf+ret,
(void *)&(hsic_buf_tbl[i].length),
@@ -846,6 +863,21 @@
diagfwd_write_complete_hsic(NULL);
}
}
+ if (driver->in_busy_smux == 1) {
+ num_data++;
+
+ /* Copy the negative token of data being passed */
+ COPY_USER_SPACE_OR_EXIT(buf+ret, mdm_token, 4);
+ /* 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_smux),
+ driver->write_ptr_mdm->length);
+ pr_debug("diag: SMUX data copied\n");
+ driver->in_busy_smux = 0;
+ }
#endif
/* copy number of data fields */
COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
@@ -950,6 +982,7 @@
size_t count, loff_t *ppos)
{
int err, ret = 0, pkt_type;
+ bool mdm_mask = false;
#ifdef DIAG_DEBUG
int length = 0, i;
#endif
@@ -985,6 +1018,12 @@
payload_size);
/* Check masks for On-Device logging */
if (driver->mask_check) {
+ /* Check if mask is for MDM or MSM */
+ if (*(int *)driver->user_space_data == MDM_TOKEN) {
+ mdm_mask = true;
+ driver->user_space_data += 4;
+ buf += 4;
+ }
if (!mask_request_validate(driver->user_space_data)) {
pr_alert("diag: mask request Invalid\n");
return -EFAULT;
@@ -998,7 +1037,7 @@
#endif
#ifdef CONFIG_DIAG_SDIO_PIPE
/* send masks to 9k too */
- if (driver->sdio_ch) {
+ if (driver->sdio_ch && mdm_mask) {
wait_event_interruptible(driver->wait_q,
(sdio_write_avail(driver->sdio_ch) >=
payload_size));
@@ -1010,7 +1049,7 @@
#endif
#ifdef CONFIG_DIAG_BRIDGE_CODE
/* send masks to 9k too */
- if (driver->hsic_ch && (payload_size > 0)) {
+ if (driver->hsic_ch && (payload_size > 0) && mdm_mask) {
/* wait sending mask updates if HSIC ch not ready */
if (driver->in_busy_hsic_write)
wait_event_interruptible(driver->wait_q,
@@ -1032,9 +1071,22 @@
driver->in_busy_hsic_write = 0;
}
}
+ if (driver->diag_smux_enabled && mdm_mask && driver->lcid) {
+ if (payload_size > 0) {
+ err = msm_smux_write(driver->lcid, NULL,
+ driver->user_space_data,
+ payload_size);
+ if (err) {
+ pr_err("diag:send mask to MDM err %d",
+ err);
+ return err;
+ }
+ }
+ }
#endif
/* send masks to 8k now */
- diag_process_hdlc((void *)(driver->user_space_data),
+ if (!mdm_mask)
+ diag_process_hdlc((void *)(driver->user_space_data),
payload_size);
return 0;
}
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 52fd673..e417d5a 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -558,6 +558,7 @@
ret = scnprintf(buf, DEBUG_BUF_SIZE,
"hsic ch: %d\n"
+ "hsic_inited: %d\n"
"hsic enabled: %d\n"
"hsic_opened: %d\n"
"hsic_suspend: %d\n"
@@ -575,6 +576,7 @@
"diag_disconnect_work: %d\n"
"diag_usb_read_complete_work: %d\n",
driver->hsic_ch,
+ driver->hsic_inited,
driver->hsic_device_enabled,
driver->hsic_device_opened,
driver->hsic_suspend,
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 3878a82..56f2fae 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -236,20 +236,20 @@
.resume = diag_hsic_resume,
};
-static int diag_hsic_close(void)
+static void diag_hsic_close(void)
{
if (driver->hsic_device_enabled) {
driver->hsic_ch = 0;
if (driver->hsic_device_opened) {
driver->hsic_device_opened = 0;
diag_bridge_close();
+ pr_debug("diag: %s: closed successfully\n", __func__);
+ } else {
+ pr_debug("diag: %s: already closed\n", __func__);
}
- pr_debug("diag: in %s: closed successfully\n", __func__);
} else {
- pr_debug("diag: in %s: already closed\n", __func__);
+ pr_debug("diag: %s: HSIC device already removed\n", __func__);
}
-
- return 0;
}
/* diagfwd_cancel_hsic is called to cancel outstanding read/writes */
@@ -257,6 +257,7 @@
{
int err;
+ mutex_lock(&driver->bridge_mutex);
if (driver->hsic_device_enabled) {
if (driver->hsic_device_opened) {
driver->hsic_ch = 0;
@@ -274,6 +275,7 @@
}
}
+ mutex_unlock(&driver->bridge_mutex);
return 0;
}
@@ -284,6 +286,7 @@
pr_debug("diag: in %s\n", __func__);
+ mutex_lock(&driver->bridge_mutex);
/* If the usb cable is being connected */
if (process_cable) {
err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE,
@@ -301,6 +304,7 @@
} else if (driver->diag_smux_enabled) {
driver->in_busy_smux = 0;
diagfwd_connect_smux();
+ mutex_unlock(&driver->bridge_mutex);
return 0;
}
@@ -323,22 +327,24 @@
* Turn on communication over usb mdm and hsic, if the hsic
* device driver is enabled and opened
*/
- if (driver->hsic_device_opened)
+ if (driver->hsic_device_opened) {
driver->hsic_ch = 1;
- /* Poll USB mdm channel to check for data */
- if (driver->logging_mode == USB_MODE)
- queue_work(driver->diag_bridge_wq,
- &driver->diag_read_mdm_work);
+ /* Poll USB mdm channel to check for data */
+ if (driver->logging_mode == USB_MODE)
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_read_mdm_work);
- /* Poll HSIC channel to check for data */
- queue_work(driver->diag_bridge_wq,
- &driver->diag_read_hsic_work);
+ /* Poll HSIC channel to check for data */
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_read_hsic_work);
+ }
} else {
/* The hsic device driver has not yet been enabled */
pr_info("diag: HSIC channel not yet enabled\n");
}
+ mutex_unlock(&driver->bridge_mutex);
return 0;
}
@@ -350,6 +356,8 @@
{
pr_debug("diag: In %s, process_cable: %d\n", __func__, process_cable);
+ mutex_lock(&driver->bridge_mutex);
+
/* If the usb cable is being disconnected */
if (process_cable) {
driver->usb_mdm_connected = 0;
@@ -361,7 +369,7 @@
driver->in_busy_hsic_read_on_device = 1;
driver->in_busy_hsic_write = 1;
/* Turn off communication over usb mdm and hsic */
- return diag_hsic_close();
+ diag_hsic_close();
} else if (driver->diag_smux_enabled &&
driver->logging_mode == USB_MODE) {
driver->in_busy_smux = 1;
@@ -370,6 +378,8 @@
/* Turn off communication over usb mdm and smux */
msm_smux_close(LCID_VALID);
}
+
+ mutex_unlock(&driver->bridge_mutex);
return 0;
}
@@ -551,13 +561,15 @@
{
int err = 0;
pr_debug("diag: in %s\n", __func__);
- if (!driver->hsic_device_enabled) {
+ if (!driver->hsic_inited) {
diagmem_hsic_init(driver);
INIT_WORK(&(driver->diag_read_hsic_work),
diag_read_hsic_work_fn);
- driver->hsic_device_enabled = 1;
+ driver->hsic_inited = 1;
}
+ mutex_lock(&driver->bridge_mutex);
+
/*
* The probe function was called after the usb was connected
* on the legacy channel OR ODL is turned on. Communication over usb
@@ -565,11 +577,17 @@
*/
if (driver->usb_mdm_connected || (driver->logging_mode ==
MEMORY_DEVICE_MODE)) {
- /* The hsic (diag_bridge) platform device driver is enabled */
+ if (driver->hsic_device_opened) {
+ /* should not happen. close it before re-opening */
+ pr_warn("diag: HSIC channel already opened in probe\n");
+ diag_bridge_close();
+ }
+
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;
+ mutex_unlock(&driver->bridge_mutex);
return err;
}
@@ -591,13 +609,19 @@
&driver->diag_read_hsic_work);
}
+ /* The hsic (diag_bridge) platform device driver is enabled */
+ driver->hsic_device_enabled = 1;
+ mutex_unlock(&driver->bridge_mutex);
return err;
}
static int diag_hsic_remove(struct platform_device *pdev)
{
pr_debug("diag: %s called\n", __func__);
+ mutex_lock(&driver->bridge_mutex);
diag_hsic_close();
+ driver->hsic_device_enabled = 0;
+ mutex_unlock(&driver->bridge_mutex);
return 0;
}
@@ -670,6 +694,7 @@
driver->itemsize_hsic_write = sizeof(struct diag_request);
driver->poolsize_hsic_write = N_MDM_WRITE;
+ mutex_init(&driver->bridge_mutex);
#ifdef CONFIG_DIAG_OVER_USB
INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
#endif
@@ -713,8 +738,9 @@
if (driver->hsic_device_enabled) {
diag_hsic_close();
driver->hsic_device_enabled = 0;
- diagmem_exit(driver, POOL_TYPE_ALL);
}
+ driver->hsic_inited = 0;
+ diagmem_exit(driver, POOL_TYPE_ALL);
if (driver->diag_smux_enabled) {
driver->lcid = LCID_INVALID;
kfree(driver->buf_in_smux);
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index 82c47af..1a522d5 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -106,7 +106,7 @@
printk(KERN_ALERT "Unable to destroy STRUCT mempool");
}
#ifdef CONFIG_DIAG_BRIDGE_CODE
- if (driver->diag_hsic_pool && (driver->hsic_device_enabled == 0)) {
+ if (driver->diag_hsic_pool && (driver->hsic_inited == 0)) {
if (driver->count_hsic_pool == 0) {
mempool_destroy(driver->diag_hdlc_pool);
driver->diag_hdlc_pool = NULL;
@@ -114,8 +114,7 @@
pr_err("Unable to destroy HDLC mempool");
}
- if (driver->diag_hsic_write_pool &&
- (driver->hsic_device_enabled == 0)) {
+ if (driver->diag_hsic_write_pool && (driver->hsic_inited == 0)) {
/*
* Free up struct pool ONLY if there are no outstanding
* transactions(aggregation buffer) with USB
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 03fdc5a..c799c1f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -556,7 +556,6 @@
PMICs through RPC.
config GPIO_QPNP_PIN
- depends on ARCH_MSM8974
depends on SPMI
depends on OF_SPMI
depends on MSM_QPNP_INT
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 98254b5..7f760ed 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1391,8 +1391,10 @@
sizeof(struct ion_fd_data)))
return -EFAULT;
data.handle = ion_import_dma_buf(client, data.fd);
- if (IS_ERR(data.handle))
+ if (IS_ERR(data.handle)) {
+ ret = PTR_ERR(data.handle);
data.handle = NULL;
+ }
if (copy_to_user((void __user *)arg, &data,
sizeof(struct ion_fd_data)))
return -EFAULT;
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index 3969319..56b8841 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -102,8 +102,6 @@
#define EPM_PSOC_BUFFERED_DATA_LENGTH 48
#define EPM_PSOC_BUFFERED_DATA_LENGTH2 54
-#define EPM_SPI_NOR_CS_N_GPIO 53
-
struct epm_adc_drv {
struct platform_device *pdev;
struct device *hwmon;
@@ -172,14 +170,6 @@
{
int rc = 0;
- rc = gpio_request(EPM_SPI_NOR_CS_N_GPIO, "SPI_NOR_CS_N");
- if (!rc)
- gpio_direction_output(EPM_SPI_NOR_CS_N_GPIO, 1);
- else {
- pr_err("Configure spi nor Failed\n");
- return -EINVAL;
- }
-
if (epm_adc_first_request) {
rc = gpio_request(GPIO_EPM_GLOBAL_ENABLE, "EPM_GLOBAL_EN");
if (!rc) {
@@ -521,27 +511,27 @@
struct epm_adc_platform_data *pdata = epm_adc->pdev->dev.platform_data;
uint32_t chan_idx = (conv->device_idx * pdata->chan_per_adc) +
conv->channel_idx;
- int64_t *adc_scaled_data = 0;
+ int64_t adc_scaled_data = 0;
/* Get the channel number */
channel_num = (adc_raw_data[0] & EPM_ADC_ADS_CHANNEL_DATA_CHID);
sign_bit = 1;
/* This is the 16-bit raw data */
- *adc_scaled_data = ((adc_raw_data[1] << 8) | adc_raw_data[2]);
+ adc_scaled_data = ((adc_raw_data[1] << 8) | adc_raw_data[2]);
/* Obtain the internal system reading */
if (channel_num == EPM_ADC_ADS_CHANNEL_VCC) {
- *adc_scaled_data *= EPM_ADC_SCALE_MILLI;
- do_div(*adc_scaled_data, EPM_ADC_SCALE_CODE_VOLTS);
+ adc_scaled_data *= EPM_ADC_SCALE_MILLI;
+ do_div(adc_scaled_data, EPM_ADC_SCALE_CODE_VOLTS);
} else if (channel_num == EPM_ADC_ADS_CHANNEL_GAIN) {
- do_div(*adc_scaled_data, EPM_ADC_SCALE_CODE_GAIN);
+ do_div(adc_scaled_data, EPM_ADC_SCALE_CODE_GAIN);
} else if (channel_num == EPM_ADC_ADS_CHANNEL_REF) {
- *adc_scaled_data *= EPM_ADC_SCALE_MILLI;
- do_div(*adc_scaled_data, EPM_ADC_SCALE_CODE_VOLTS);
+ adc_scaled_data *= EPM_ADC_SCALE_MILLI;
+ do_div(adc_scaled_data, EPM_ADC_SCALE_CODE_VOLTS);
} else if (channel_num == EPM_ADC_ADS_CHANNEL_TEMP) {
/* Convert Code to micro-volts */
/* Use this formula to get the temperature reading */
- *adc_scaled_data -= EPM_ADC_TEMP_TO_DEGC_COEFF;
- do_div(*adc_scaled_data, EPM_ADC_TEMP_SENSOR_COEFF);
+ adc_scaled_data -= EPM_ADC_TEMP_TO_DEGC_COEFF;
+ do_div(adc_scaled_data, EPM_ADC_TEMP_SENSOR_COEFF);
} else if (channel_num == EPM_ADC_ADS_CHANNEL_OFFSET) {
/* The offset should be zero */
pr_debug("%s: ADC Channel Offset\n", __func__);
@@ -553,31 +543,31 @@
* mvVRef is in milli-volts and resistorvalue is in micro-ohms.
* Hence, I = V/R gives us current in kilo-amps.
*/
- if (*adc_scaled_data & EPM_ADC_MAX_NEGATIVE_SCALE_CODE) {
+ if (adc_scaled_data & EPM_ADC_MAX_NEGATIVE_SCALE_CODE) {
sign_bit = -1;
- *adc_scaled_data = (~*adc_scaled_data
+ adc_scaled_data = (~adc_scaled_data
& EPM_ADC_NEG_LSB_CODE);
}
- if (*adc_scaled_data != 0) {
- *adc_scaled_data *= EPM_ADC_SCALE_FACTOR;
+ if (adc_scaled_data != 0) {
+ adc_scaled_data *= EPM_ADC_SCALE_FACTOR;
/* Device is calibrated for 1LSB = VREF/7800h.*/
- *adc_scaled_data *= EPM_ADC_MILLI_VOLTS_SOURCE;
- do_div(*adc_scaled_data, EPM_ADC_VREF_CODE);
+ adc_scaled_data *= EPM_ADC_MILLI_VOLTS_SOURCE;
+ do_div(adc_scaled_data, EPM_ADC_VREF_CODE);
/* Data will now be in micro-volts.*/
- *adc_scaled_data *= EPM_ADC_SCALE_MILLI;
+ adc_scaled_data *= EPM_ADC_SCALE_MILLI;
/* Divide by amplifier gain value.*/
- do_div(*adc_scaled_data, pdata->channel[chan_idx].gain);
+ do_div(adc_scaled_data, pdata->channel[chan_idx].gain);
/* Data will now be in nano-volts.*/
- do_div(*adc_scaled_data, EPM_ADC_SCALE_FACTOR);
- *adc_scaled_data *= EPM_ADC_SCALE_MILLI;
+ do_div(adc_scaled_data, EPM_ADC_SCALE_FACTOR);
+ adc_scaled_data *= EPM_ADC_SCALE_MILLI;
/* Data is now in micro-amps.*/
- do_div(*adc_scaled_data,
+ do_div(adc_scaled_data,
pdata->channel[chan_idx].resistorvalue);
/* Set the sign bit for lekage current. */
- *adc_scaled_data *= sign_bit;
+ adc_scaled_data *= sign_bit;
}
}
- conv->physical = (int32_t) *adc_scaled_data;
+ conv->physical = (int32_t) adc_scaled_data;
return 0;
}
@@ -1600,16 +1590,15 @@
struct device_node *node = spi->dev.of_node;
int rc = 0;
- if (!node) {
- dev_err(&spi->dev, "no platform data?\n");
- pr_info("Error in the probe\n");
- return -EINVAL;
- }
-
if (node)
rc = get_device_tree_data(spi);
- else
- return -ENODEV;
+ else {
+ epm_adc = epm_adc_drv;
+ epm_adc_drv->epm_spi_client = spi;
+ epm_adc_drv->epm_spi_client->bits_per_word =
+ EPM_ADC_ADS_SPI_BITS_PER_WORD;
+ return rc;
+ }
epm_adc = epm_adc_drv;
epm_adc->misc.name = EPM_ADC_DRIVER_NAME;
diff --git a/drivers/media/dvb/mpq/video/mpq_dvb_video.c b/drivers/media/dvb/mpq/video/mpq_dvb_video.c
index 68653ba..3dc31bb 100644
--- a/drivers/media/dvb/mpq/video/mpq_dvb_video.c
+++ b/drivers/media/dvb/mpq/video/mpq_dvb_video.c
@@ -55,6 +55,8 @@
static int mpq_int_vid_dec_decode_frame(struct video_client_ctx *client_ctx,
struct video_data_buffer *input_frame);
+static int mpq_int_vid_dec_get_buffer_req(struct video_client_ctx *client_ctx,
+ struct video_buffer_req *vdec_buf_req);
static struct mpq_dvb_video_dev *mpq_dvb_video_device;
@@ -819,11 +821,32 @@
return 0;
}
+static int mpq_int_set_out_buffer_req(struct video_client_ctx *client_ctx,
+ struct video_buffer_req *vdec_buf_req)
+{
+ struct vcd_buffer_requirement buffer_req;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ buffer_req.actual_count = vdec_buf_req->num_output_buffers;
+ buffer_req.align = vdec_buf_req->output_buf_prop.alignment;
+ buffer_req.max_count = vdec_buf_req->num_output_buffers;
+ buffer_req.min_count = vdec_buf_req->num_output_buffers;
+ buffer_req.sz = vdec_buf_req->output_buf_prop.buf_size;
+
+ vcd_status = vcd_set_buffer_requirements(client_ctx->vcd_handle,
+ VCD_BUFFER_OUTPUT, &buffer_req);
+ if (vcd_status)
+ return -EFAULT;
+ else
+ return 0;
+}
+
static int mpq_int_set_full_hd_frame_resolution(
struct video_client_ctx *client_ctx)
{
struct vdec_picsize pic_res;
int rc;
+ struct video_buffer_req vdec_buf_req;
pic_res.frame_height = 1080;
pic_res.frame_width = 1920;
@@ -841,6 +864,15 @@
DBG("Failed in mpq_int_vid_dec_set_cont_on_reconfig : %d\n",\
rc);
+ rc = mpq_int_vid_dec_get_buffer_req(client_ctx, &vdec_buf_req);
+ if (rc)
+ DBG("Failed in mpq_int_vid_dec_get_buffer_req : %d\n", rc);
+
+ vdec_buf_req.num_output_buffers = 15;
+ rc = mpq_int_set_out_buffer_req(client_ctx, &vdec_buf_req);
+ if (rc)
+ DBG("Failed in mpq_int_set_out_buffer_req (15) : %d\n", rc);
+
return rc;
}
diff --git a/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
index 9549dcc..d508c1d 100644
--- a/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
+++ b/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
@@ -139,11 +139,11 @@
switch (perf_setting) {
case S_INIT:
add_axi_qos();
- break;
- case S_PREVIEW:
update_axi_qos(MSM_AXI_QOS_PREVIEW);
axi_allocate(AXI_FLOW_VIEWFINDER_HI);
break;
+ case S_PREVIEW:
+ break;
case S_VIDEO:
update_axi_qos(MSM_AXI_QOS_RECORDING);
break;
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 2613986..1e17c5c 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -555,6 +555,7 @@
case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC:
case CMD_AXI_START:
case CMD_AXI_STOP:
+ case CMD_AXI_RESET:
case CMD_AXI_CFG_TERT1:
case CMD_AXI_CFG_TERT2:
/* Dont need to pass buffer information.
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index eb6a8b0..f6cf427 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -23,6 +23,8 @@
static struct msm_camera_i2c_reg_conf ov5647_start_settings[] = {
{0x4202, 0x00}, /* streaming on */
+ {0x0100, 0x01},
+ {0x4800, 0x04},
};
static struct msm_camera_i2c_reg_conf ov5647_stop_settings[] = {
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index bb9a9b7..b78e20d 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1643,6 +1643,10 @@
rp = (struct msm_vfe_resp *)arg;
frame_info = rp->evt_msg.data;
+ if (!frame_info) {
+ interface = PIX_0;
+ break;
+ }
if (frame_info->inst_handle) {
vnode_id = GET_DEVID_MODE(frame_info->inst_handle);
if (vnode_id < MAX_NUM_ACTIVE_CAMERA &&
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
index 15c38af..9deae65 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
@@ -1561,6 +1561,11 @@
}
return 0;
+ case CMD_AXI_START:
+ case CMD_AXI_STOP:
+ case CMD_AXI_RESET:
+ return 0;
+
case CMD_CONFIG_FREE_BUF_ADDR: {
int path = *((int *)cmd->value);
struct buf_info *outch = vfe2x_get_ch(path);
@@ -1853,9 +1858,6 @@
flags);
if (op_mode & SNAPSHOT_MASK_MODE) {
vfe2x_ctrl->stop_pending = 0;
- vfe2x_send_isp_msg(vfe2x_ctrl,
- msgs_map[MSG_STOP_ACK].
- isp_id);
spin_unlock_irqrestore(
&vfe2x_ctrl->table_lock,
flags);
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 170322c..a4c4b83 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -31,7 +31,6 @@
#include "msm_smem.h"
#define BASE_DEVICE_NUMBER 32
-#define MAX_EVENTS 30
#define SHARED_QSIZE 0x1000000
static struct msm_bus_vectors enc_ocmem_init_vectors[] = {
@@ -451,7 +450,7 @@
};
struct msm_v4l2_vid_inst {
- struct msm_vidc_inst vidc_inst;
+ struct msm_vidc_inst *vidc_inst;
void *mem_client;
struct list_head registered_bufs;
};
@@ -468,22 +467,7 @@
struct msm_vidc_inst *vidc_inst;
vidc_inst = container_of(filp->private_data,
struct msm_vidc_inst, event_handler);
- return container_of((void *)vidc_inst,
- struct msm_v4l2_vid_inst, vidc_inst);
-}
-
-static int msm_vidc_v4l2_setup_event_queue(void *inst,
- struct video_device *pvdev)
-{
- int rc = 0;
- struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
- spin_lock_init(&pvdev->fh_lock);
- INIT_LIST_HEAD(&pvdev->fh_list);
-
- v4l2_fh_init(&vidc_inst->event_handler, pvdev);
- v4l2_fh_add(&vidc_inst->event_handler);
-
- return rc;
+ return (struct msm_v4l2_vid_inst *)vidc_inst->priv;
}
struct buffer_info *get_registered_buf(struct list_head *list,
@@ -556,7 +540,8 @@
rc = -ENOMEM;
goto fail_mem_client;
}
- rc = msm_vidc_open(&v4l2_inst->vidc_inst, core->id, vid_dev->type);
+
+ v4l2_inst->vidc_inst = msm_vidc_open(core->id, vid_dev->type);
if (rc) {
dprintk(VIDC_ERR,
"Failed to create video instance, core: %d, type = %d\n",
@@ -565,9 +550,9 @@
goto fail_open;
}
INIT_LIST_HEAD(&v4l2_inst->registered_bufs);
- rc = msm_vidc_v4l2_setup_event_queue(&v4l2_inst->vidc_inst, vdev);
+ v4l2_inst->vidc_inst->priv = v4l2_inst;
clear_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags);
- filp->private_data = &(v4l2_inst->vidc_inst.event_handler);
+ filp->private_data = &(v4l2_inst->vidc_inst->event_handler);
return rc;
fail_open:
msm_smem_delete_client(v4l2_inst->mem_client);
@@ -667,7 +652,7 @@
buffer_info.m.planes[0].reserved[0],
buffer_info.m.planes[0].reserved[1],
buffer_info.m.planes[0].length);
- rc = msm_vidc_release_buf(&v4l2_inst->vidc_inst,
+ rc = msm_vidc_release_buf(v4l2_inst->vidc_inst,
&buffer_info);
list_del(&bi->list);
if (bi->handle)
@@ -752,7 +737,7 @@
list_add_tail(&binfo->list, &v4l2_inst->registered_bufs);
b->m.planes[i].m.userptr = binfo->device_addr;
}
- rc = msm_vidc_prepare_buf(&v4l2_inst->vidc_inst, b);
+ rc = msm_vidc_prepare_buf(v4l2_inst->vidc_inst, b);
exit:
return rc;
}
@@ -794,7 +779,7 @@
}
}
}
- rc = msm_vidc_qbuf(&v4l2_inst->vidc_inst, b);
+ rc = msm_vidc_qbuf(v4l2_inst->vidc_inst, b);
err_invalid_buff:
return rc;
}
@@ -823,17 +808,17 @@
static int msm_v4l2_subscribe_event(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
- int rc = 0;
- rc = v4l2_event_subscribe(fh, sub, MAX_EVENTS);
- return rc;
+ struct msm_vidc_inst *vidc_inst = container_of(fh,
+ struct msm_vidc_inst, event_handler);
+ return msm_vidc_subscribe_event((void *)vidc_inst, sub);
}
static int msm_v4l2_unsubscribe_event(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
- int rc = 0;
- rc = v4l2_event_unsubscribe(fh, sub);
- return rc;
+ struct msm_vidc_inst *vidc_inst = container_of(fh,
+ struct msm_vidc_inst, event_handler);
+ return msm_vidc_unsubscribe_event((void *)vidc_inst, sub);
}
static int msm_v4l2_decoder_cmd(struct file *file, void *fh,
@@ -936,7 +921,7 @@
struct msm_iova_layout layout;
int rc = 0;
int i;
- struct iommu_info *io_map = core->resources.io_map;
+ struct msm_vidc_iommu_info *io_map = core->resources.io_map;
strlcpy(io_map[CP_MAP].name, "vidc-cp-map",
sizeof(io_map[CP_MAP].name));
strlcpy(io_map[CP_MAP].ctx, "venus_cp",
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 8240890..be2e848 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -229,6 +229,14 @@
.type = OUTPUT_PORT,
},
{
+ .name = "VC1 SP",
+ .description = "VC-1 compressed format G",
+ .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
+ .num_planes = 1,
+ .get_frame_size = get_frame_size_compressed,
+ .type = OUTPUT_PORT,
+ },
+ {
.name = "H264",
.description = "H264 compressed format",
.fourcc = V4L2_PIX_FMT_H264,
@@ -524,6 +532,8 @@
goto err_invalid_fmt;
}
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ inst->prop.width = f->fmt.pix_mp.width;
+ inst->prop.height = f->fmt.pix_mp.height;
fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
OUTPUT_PORT);
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 449dab2..c7269d3 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -21,6 +21,8 @@
#include "msm_smem.h"
#include <linux/delay.h>
+#define MAX_EVENTS 30
+
int msm_vidc_poll(void *instance, struct file *filp,
struct poll_table_struct *wait)
{
@@ -55,9 +57,28 @@
return rc;
}
+int msm_vidc_get_iommu_maps(void *instance,
+ struct msm_vidc_iommu_info maps[MAX_MAP])
+{
+ struct msm_vidc_inst *inst = instance;
+ int c = 0;
+
+ if (!inst || !maps)
+ return -EINVAL;
+
+ for (c = 0; c < MAX_MAP; ++c)
+ maps[c] = inst->core->resources.io_map[c];
+
+ return 0;
+}
+
int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !cap)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_querycap(instance, cap);
else if (inst->session_type == MSM_VIDC_ENCODER)
@@ -67,6 +88,10 @@
int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !f)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_enum_fmt(instance, f);
else if (inst->session_type == MSM_VIDC_ENCODER)
@@ -76,6 +101,10 @@
int msm_vidc_s_fmt(void *instance, struct v4l2_format *f)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !f)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_s_fmt(instance, f);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -85,6 +114,10 @@
int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !f)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_g_fmt(instance, f);
else if (inst->session_type == MSM_VIDC_ENCODER)
@@ -94,6 +127,10 @@
int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !control)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_s_ctrl(instance, control);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -103,6 +140,10 @@
int msm_vidc_g_ctrl(void *instance, struct v4l2_control *control)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !control)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_g_ctrl(instance, control);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -112,6 +153,10 @@
int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !b)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_reqbufs(instance, b);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -122,6 +167,10 @@
int msm_vidc_prepare_buf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !b)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_prepare_buf(instance, b);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -132,6 +181,10 @@
int msm_vidc_release_buf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !b)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_release_buf(instance, b);
return -EINVAL;
@@ -156,6 +209,10 @@
int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !b)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_qbuf(instance, b);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -166,6 +223,10 @@
int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst || !b)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_dqbuf(instance, b);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -176,6 +237,10 @@
int msm_vidc_streamon(void *instance, enum v4l2_buf_type i)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_streamon(instance, i);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -186,6 +251,10 @@
int msm_vidc_streamoff(void *instance, enum v4l2_buf_type i)
{
struct msm_vidc_inst *inst = instance;
+
+ if (!inst)
+ return -EINVAL;
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_streamoff(instance, i);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -193,13 +262,13 @@
return -EINVAL;
}
-void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
+static void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
unsigned long size, int write)
{
return (void *)0xdeadbeef;
}
-void vidc_put_userptr(void *buf_priv)
+static void vidc_put_userptr(void *buf_priv)
{
}
@@ -232,9 +301,60 @@
return vb2_queue_init(q);
}
-int msm_vidc_open(void *vidc_inst, int core_id, int session_type)
+static int setup_event_queue(void *inst,
+ struct video_device *pvdev)
{
- struct msm_vidc_inst *inst = (struct msm_vidc_inst *)vidc_inst;
+ int rc = 0;
+ struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
+ spin_lock_init(&pvdev->fh_lock);
+ INIT_LIST_HEAD(&pvdev->fh_list);
+
+ v4l2_fh_init(&vidc_inst->event_handler, pvdev);
+ v4l2_fh_add(&vidc_inst->event_handler);
+
+ return rc;
+}
+
+int msm_vidc_subscribe_event(void *inst, struct v4l2_event_subscription *sub)
+{
+ int rc = 0;
+ struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
+
+ if (!inst || !sub)
+ return -EINVAL;
+
+ rc = v4l2_event_subscribe(&vidc_inst->event_handler, sub, MAX_EVENTS);
+ return rc;
+}
+
+
+int msm_vidc_unsubscribe_event(void *inst, struct v4l2_event_subscription *sub)
+{
+ int rc = 0;
+ struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
+
+ if (!inst || !sub)
+ return -EINVAL;
+
+ rc = v4l2_event_unsubscribe(&vidc_inst->event_handler, sub);
+ return rc;
+}
+
+int msm_vidc_dqevent(void *inst, struct v4l2_event *event)
+{
+ int rc = 0;
+ struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
+
+ if (!inst || !event)
+ return -EINVAL;
+
+ rc = v4l2_event_dequeue(&vidc_inst->event_handler, event, false);
+ return rc;
+}
+
+void *msm_vidc_open(int core_id, int session_type)
+{
+ struct msm_vidc_inst *inst = NULL;
struct msm_vidc_core *core = NULL;
unsigned long flags;
int rc = 0;
@@ -252,6 +372,13 @@
goto err_invalid_core;
}
+ inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+ if (!inst) {
+ pr_err("Failed to allocate memory\n") ;
+ rc = -ENOMEM;
+ goto err_invalid_core;
+ }
+
mutex_init(&inst->sync_lock);
spin_lock_init(&inst->lock);
inst->session_type = session_type;
@@ -276,6 +403,7 @@
msm_venc_inst_init(inst);
msm_venc_ctrl_init(inst);
}
+
rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
session_type);
if (rc) {
@@ -298,17 +426,20 @@
}
inst->debugfs_root =
msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
+
+ setup_event_queue(inst, &core->vdev[core_id].vdev);
+
spin_lock_irqsave(&core->lock, flags);
list_add_tail(&inst->list, &core->instances);
spin_unlock_irqrestore(&core->lock, flags);
- return rc;
+ return inst;
fail_init:
msm_smem_delete_client(inst->mem_client);
fail_mem_client:
kfree(inst);
inst = NULL;
err_invalid_core:
- return rc;
+ return inst;
}
static void cleanup_instance(struct msm_vidc_inst *inst)
@@ -360,6 +491,10 @@
struct msm_vidc_core *core;
struct list_head *ptr, *next;
int rc = 0;
+
+ if (!inst)
+ return -EINVAL;
+
core = inst->core;
mutex_lock(&core->sync_lock);
list_for_each_safe(ptr, next, &core->instances) {
@@ -373,6 +508,7 @@
dprintk(VIDC_ERR,
"Failed to move video instance to uninit state\n");
cleanup_instance(inst);
+ kfree(inst);
dprintk(VIDC_DBG, "Closed the instance\n");
return 0;
}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 5b83cfb..84552a4 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -166,7 +166,7 @@
int rc;
struct iommu_domain *domain;
int i;
- struct iommu_info *io_map;
+ struct msm_vidc_iommu_info *io_map;
struct device *dev;
for (i = 0; i < MAX_MAP; i++) {
io_map = &core->resources.io_map[i];
@@ -202,7 +202,7 @@
{
struct device *dev;
struct iommu_domain *domain;
- struct iommu_info *io_map;
+ struct msm_vidc_iommu_info *io_map;
int i;
if (!core) {
dprintk(VIDC_ERR, "Invalid paramter: %p\n", core);
@@ -737,7 +737,7 @@
dprintk(VIDC_ERR, "Invalid args: %p\n", core);
return -EINVAL;
}
- num_mbs_per_sec = 2 * msm_comm_get_load(core, MSM_VIDC_ENCODER);
+ num_mbs_per_sec = msm_comm_get_load(core, MSM_VIDC_ENCODER);
num_mbs_per_sec += msm_comm_get_load(core, MSM_VIDC_DECODER);
dprintk(VIDC_INFO, "num_mbs_per_sec = %d\n", num_mbs_per_sec);
rc = clk_set_rate(core->resources.clock[VCODEC_CLK].clk,
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 55aec74..3c14123 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -141,20 +141,6 @@
void *cookie;
};
-struct iommu_info {
- u32 addr_range[2];
- char name[MAX_NAME_LENGTH];
- char ctx[MAX_NAME_LENGTH];
- int domain;
- int partition;
-};
-
-enum io_maps {
- CP_MAP,
- NS_MAP,
- MAX_MAP
-};
-
enum vidc_clocks {
VCODEC_CLK,
VCODEC_AHB_CLK,
@@ -188,7 +174,7 @@
struct msm_vidc_resources {
struct msm_vidc_fw fw;
- struct iommu_info io_map[MAX_MAP];
+ struct msm_vidc_iommu_info io_map[MAX_MAP];
struct core_clock clock[VCODEC_MAX_CLKS];
struct vidc_bus_info bus_info;
struct on_chip_mem ocmem;
@@ -247,6 +233,7 @@
u32 ftb_count;
u32 fbd_count;
struct vb2_buffer *vb2_seq_hdr;
+ void *priv;
};
extern struct msm_vidc_drv *vidc_driver;
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 12ba874..0639dea 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -608,6 +608,9 @@
static void set_vbif_registers(struct hal_device *device)
{
+ /*Disable Dynamic clock gating for Venus VBIF*/
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS_VBIF_CLK_ON, 1, 0);
write_register(device->hal_data->register_base_addr,
VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00000FFF, 0);
write_register(device->hal_data->register_base_addr,
@@ -636,6 +639,8 @@
VIDC_VBIF_OUT_WR_LIM_CONF0, 0x00001010, 0);
write_register(device->hal_data->register_base_addr,
VIDC_VBIF_ARB_CTL, 0x00000030, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY, 0x5555556, 0);
}
int vidc_hal_core_init(void *device, int domain)
@@ -654,10 +659,6 @@
INIT_LIST_HEAD(&dev->sess_head);
spin_lock_init(&dev->read_lock);
spin_lock_init(&dev->write_lock);
-
- /*Disable Dynamic clock gating for Venus VBIF*/
- write_register(dev->hal_data->register_base_addr,
- VIDC_VENUS_VBIF_CLK_ON, 1, 0);
set_vbif_registers(dev);
if (!dev->hal_client) {
dev->hal_client = msm_smem_new_client(SMEM_ION);
diff --git a/drivers/media/video/msm_vidc/vidc_hal_io.h b/drivers/media/video/msm_vidc/vidc_hal_io.h
index c4b1e0c..b85e015 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_io.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_io.h
@@ -124,9 +124,9 @@
#define VIDC_VBIF_AT_NEW_BASE (VIDC_VBIF_BASE_OFFS + 0xC10)
#define VIDC_VBIF_AT_NEW_HIGH (VIDC_VBIF_BASE_OFFS + 0xC18)
-#define VIDC_VENUS0_VENUS_WRAPPER_VBIF_REQ_PRIORITY \
+#define VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY \
(VIDC_WRAPPER_BASE_OFFS + 0x20)
-#define VIDC_VENUS0_VENUS_WRAPPER_VBIF_PRIORITY_LEVEL \
+#define VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL \
(VIDC_WRAPPER_BASE_OFFS + 0x24)
#define VIDC_VENUS_VBIF_REQ_PRIORITY (VIDC_WRAPPER_BASE_OFFS + 0x20)
#define VIDC_VENUS_VBIF_PRIORITY_LEVEL (VIDC_WRAPPER_BASE_OFFS + 0x24)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 52fd5e8..b153b27 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -5798,6 +5798,7 @@
mmc->caps2 |= MMC_CAP2_PACKED_WR_CONTROL;
mmc->caps2 |= (MMC_CAP2_BOOTPART_NOACC | MMC_CAP2_DETECT_ON_ERR);
mmc->caps2 |= MMC_CAP2_SANITIZE;
+ mmc->caps2 |= MMC_CAP2_CACHE_CTRL;
if (plat->nonremovable)
mmc->caps |= MMC_CAP_NONREMOVABLE;
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 0119ebe..996456f 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -435,6 +435,14 @@
return -EINVAL;
}
+ /* mark the interrupts wakeable if they support linux-key */
+ if (cfg->key_code) {
+ enable_irq_wake(cfg->state_irq);
+ /* special handling for RESIN due to a hardware bug */
+ if (cfg->pon_type == PON_RESIN && cfg->support_reset)
+ enable_irq_wake(cfg->bark_irq);
+ }
+
return rc;
}
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 8724138..c32978e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -21,7 +21,6 @@
config MSM_QPNP_INT
depends on SPARSE_IRQ
- depends on ARCH_MSM8974
depends on SPMI
depends on OF_SPMI
bool "MSM QPNP INT"
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
index 6faaf78..b0b9468 100644
--- a/drivers/usb/gadget/ci13xxx_msm_hsic.c
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -67,6 +67,7 @@
struct work_struct suspend_w;
struct msm_hsic_peripheral_platform_data *pdata;
enum usb_vdd_type vdd_type;
+ bool connected;
};
static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
@@ -381,7 +382,7 @@
*/
mb();
- if (!mhsic->pdata->core_clk_always_on_workaround) {
+ if (!mhsic->pdata->core_clk_always_on_workaround || !mhsic->connected) {
clk_disable(mhsic->iface_clk);
clk_disable(mhsic->core_clk);
}
@@ -438,7 +439,7 @@
dev_err(mhsic->dev, "%s failed to vote for TCXO %d\n",
__func__, ret);
- if (!mhsic->pdata->core_clk_always_on_workaround) {
+ if (!mhsic->pdata->core_clk_always_on_workaround || !mhsic->connected) {
clk_enable(mhsic->iface_clk);
clk_enable(mhsic->core_clk);
}
@@ -598,22 +599,38 @@
switch (event) {
case CI13XXX_CONTROLLER_RESET_EVENT:
- dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
+ dev_info(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
writel_relaxed(0, USB_AHBBURST);
writel_relaxed(0x08, USB_AHBMODE);
break;
case CI13XXX_CONTROLLER_CONNECT_EVENT:
- dev_dbg(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
- msm_hsic_start();
+ dev_info(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
+ msm_hsic_wakeup();
+ the_mhsic->connected = true;
break;
case CI13XXX_CONTROLLER_SUSPEND_EVENT:
- dev_dbg(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
+ dev_info(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
queue_work(mhsic->wq, &mhsic->suspend_w);
break;
case CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT:
- dev_dbg(dev, "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
+ dev_info(dev, "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
msm_hsic_wakeup();
break;
+ case CI13XXX_CONTROLLER_UDC_STARTED_EVENT:
+ dev_info(dev, "CI13XXX_CONTROLLER_UDC_STARTED_EVENT received\n");
+ /*
+ * UDC started, suspend the hsic device until it will be
+ * connected by a pullup (CI13XXX_CONTROLLER_CONNECT_EVENT)
+ * Before suspend, finish required configurations.
+ */
+ hw_device_state(_udc->ep0out.qh.dma);
+ msm_hsic_start();
+ usleep(10000);
+
+ mhsic->connected = false;
+ pm_runtime_put_noidle(the_mhsic->dev);
+ pm_runtime_suspend(the_mhsic->dev);
+ break;
default:
dev_dbg(dev, "unknown ci13xxx_udc event\n");
break;
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 831e970..5b39336 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3205,6 +3205,11 @@
spin_unlock_irqrestore(udc->lock, flags);
if (retval || put)
pm_runtime_put_sync(&udc->gadget.dev);
+
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_UDC_STARTED_EVENT);
+
return retval;
}
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 6527b76..3162e15 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -126,6 +126,8 @@
#define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT 3
#define CI13XXX_CONTROLLER_RESUME_EVENT 4
#define CI13XXX_CONTROLLER_DISCONNECT_EVENT 5
+#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT 6
+
void (*notify_event) (struct ci13xxx *udc, unsigned event);
};
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index a9e5d91..45dfb87 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -640,26 +640,6 @@
clear_bit(BAM_CH_OPENED, &d->flags);
}
-static void gbam2bam_disconnect_work(struct work_struct *w)
-{
- struct gbam_port *port =
- container_of(w, struct gbam_port, disconnect_w);
- unsigned long flags;
-
- spin_lock_irqsave(&port->port_lock_ul, flags);
- spin_lock(&port->port_lock_dl);
- port->port_usb = 0;
- spin_unlock(&port->port_lock_dl);
- spin_unlock_irqrestore(&port->port_lock_ul, flags);
-
- /* disable endpoints */
- usb_ep_disable(port->gr->out);
- usb_ep_disable(port->gr->in);
-
- port->gr->in->driver_data = NULL;
- port->gr->out->driver_data = NULL;
-}
-
static void gbam_connect_work(struct work_struct *w)
{
struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
@@ -699,29 +679,6 @@
struct bam_ch_info *d = &port->data_ch;
u32 sps_params;
int ret;
- unsigned long flags;
-
- ret = usb_ep_enable(port->gr->in);
- if (ret) {
- pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
- __func__, port->gr->in);
- return;
- }
- port->gr->in->driver_data = port;
-
- ret = usb_ep_enable(port->gr->out);
- if (ret) {
- pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
- __func__, port->gr->out);
- port->gr->in->driver_data = 0;
- return;
- }
- port->gr->out->driver_data = port;
- spin_lock_irqsave(&port->port_lock_ul, flags);
- spin_lock(&port->port_lock_dl);
- port->port_usb = port->gr;
- spin_unlock(&port->port_lock_dl);
- spin_unlock_irqrestore(&port->port_lock_ul, flags);
ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
&d->dst_pipe_idx);
@@ -916,7 +873,6 @@
spin_lock_init(&port->port_lock_dl);
INIT_WORK(&port->connect_w, gbam2bam_connect_work);
- INIT_WORK(&port->disconnect_w, gbam2bam_disconnect_work);
/* data ch */
d = &port->data_ch;
@@ -1071,7 +1027,7 @@
d = &port->data_ch;
port->gr = gr;
- if (trans == USB_GADGET_XPORT_BAM) {
+ if (trans == USB_GADGET_XPORT_BAM)
gbam_free_buffers(port);
spin_lock_irqsave(&port->port_lock_ul, flags);
@@ -1081,12 +1037,15 @@
spin_unlock(&port->port_lock_dl);
spin_unlock_irqrestore(&port->port_lock_ul, flags);
- /* disable endpoints */
- usb_ep_disable(gr->out);
- usb_ep_disable(gr->in);
- }
+ /* disable endpoints */
+ usb_ep_disable(gr->out);
+ usb_ep_disable(gr->in);
- queue_work(gbam_wq, &port->disconnect_w);
+ gr->in->driver_data = NULL;
+ gr->out->driver_data = NULL;
+
+ if (trans == USB_GADGET_XPORT_BAM)
+ queue_work(gbam_wq, &port->disconnect_w);
}
int gbam_connect(struct grmnet *gr, u8 port_num,
@@ -1121,36 +1080,37 @@
d = &port->data_ch;
- if (trans == USB_GADGET_XPORT_BAM) {
- ret = usb_ep_enable(gr->in);
- if (ret) {
- pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
- __func__, gr->in);
- return ret;
- }
- gr->in->driver_data = port;
+ ret = usb_ep_enable(gr->in);
+ if (ret) {
+ pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
+ __func__, gr->in);
+ return ret;
+ }
+ gr->in->driver_data = port;
- ret = usb_ep_enable(gr->out);
- if (ret) {
- pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
- __func__, gr->out);
- gr->in->driver_data = 0;
- return ret;
- }
- gr->out->driver_data = port;
+ ret = usb_ep_enable(gr->out);
+ if (ret) {
+ pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
+ __func__, gr->out);
+ gr->in->driver_data = 0;
+ return ret;
+ }
+ gr->out->driver_data = port;
spin_lock_irqsave(&port->port_lock_ul, flags);
spin_lock(&port->port_lock_dl);
port->port_usb = gr;
+ if (trans == USB_GADGET_XPORT_BAM) {
d->to_host = 0;
d->to_modem = 0;
d->pending_with_bam = 0;
d->tohost_drp_cnt = 0;
d->tomodem_drp_cnt = 0;
+ }
+
spin_unlock(&port->port_lock_dl);
spin_unlock_irqrestore(&port->port_lock_ul, flags);
- }
if (trans == USB_GADGET_XPORT_BAM2BAM) {
port->gr = gr;
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index cad411d..b1b7763 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -60,6 +60,11 @@
return -ENODEV;
}
+ if (dev->ops) {
+ pr_err("bridge already opened");
+ return -EALREADY;
+ }
+
dev->ops = ops;
dev->err = 0;
@@ -82,6 +87,16 @@
{
struct diag_bridge *dev = __dev;
+ if (!dev) {
+ pr_err("dev is null");
+ return;
+ }
+
+ if (!dev->ops) {
+ pr_err("can't close bridge that was not open");
+ return;
+ }
+
dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
usb_kill_anchored_urbs(&dev->submitted);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index a6d8c17..5637f19 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -67,6 +67,8 @@
#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+#define USB_SUSPEND_DELAY_TIME (500 * HZ/1000) /* 500 msec */
+
static DECLARE_COMPLETION(pmic_vbus_init);
static struct msm_otg *the_msm_otg;
static bool debug_aca_enabled;
@@ -686,7 +688,8 @@
if (aca_enabled())
return 0;
- if (atomic_read(&motg->in_lpm) == suspend)
+ if (atomic_read(&motg->in_lpm) == suspend &&
+ !atomic_read(&motg->suspend_work_pending))
return 0;
if (suspend) {
@@ -705,7 +708,9 @@
if (!(motg->caps & ALLOW_LPM_ON_DEV_SUSPEND))
break;
set_bit(A_BUS_SUSPEND, &motg->inputs);
- queue_work(system_nrt_wq, &motg->sm_work);
+ atomic_set(&motg->suspend_work_pending, 1);
+ queue_delayed_work(system_nrt_wq, &motg->suspend_work,
+ USB_SUSPEND_DELAY_TIME);
break;
default:
@@ -2752,6 +2757,14 @@
queue_work(system_nrt_wq, &motg->sm_work);
}
+static void msm_otg_suspend_work(struct work_struct *w)
+{
+ struct msm_otg *motg =
+ container_of(w, struct msm_otg, suspend_work.work);
+ atomic_set(&motg->suspend_work_pending, 0);
+ msm_otg_sm_work(&motg->sm_work);
+}
+
static irqreturn_t msm_otg_irq(int irq, void *data)
{
struct msm_otg *motg = data;
@@ -3629,6 +3642,7 @@
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
INIT_DELAYED_WORK(&motg->pmic_id_status_work, msm_pmic_id_status_w);
+ INIT_DELAYED_WORK(&motg->suspend_work, msm_otg_suspend_work);
setup_timer(&motg->id_timer, msm_otg_id_timer_func,
(unsigned long) motg);
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
@@ -3791,6 +3805,7 @@
msm_otg_debugfs_cleanup();
cancel_delayed_work_sync(&motg->chg_work);
cancel_delayed_work_sync(&motg->pmic_id_status_work);
+ cancel_delayed_work_sync(&motg->suspend_work);
cancel_work_sync(&motg->sm_work);
pm_runtime_resume(&pdev->dev);
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index 487e5d5..ee7e9ce 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -294,6 +294,7 @@
mdp4_mixer_stage_commit(pipe->mixer_num);
mdp4_writeback_overlay_kickoff(mfd, pipe);
+ mdp4_writeback_dma_busy_wait(mfd);
/* move current committed iommu to freelist */
mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 5432df0..06d8769 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1137,6 +1137,31 @@
return 0;
}
+static int mdss_fb_handle_pp_ioctl(void __user *argp)
+{
+ int ret;
+ struct msmfb_mdp_pp mdp_pp;
+ u32 copyback = 0;
+
+ ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
+ if (ret)
+ return ret;
+
+ switch (mdp_pp.op) {
+ case mdp_op_pa_cfg:
+ ret = mdss_mdp_pa_config(&mdp_pp.data.pa_cfg_data,
+ ©back);
+ break;
+ default:
+ pr_err("Unsupported request to MDP_PP IOCTL.\n");
+ ret = -EINVAL;
+ break;
+ }
+ if ((ret == 0) && copyback)
+ ret = copy_to_user(argp, &mdp_pp, sizeof(struct msmfb_mdp_pp));
+ return ret;
+}
+
static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
@@ -1163,6 +1188,10 @@
return ret;
break;
+ case MSMFB_MDP_PP:
+ ret = mdss_fb_handle_pp_ioctl(argp);
+ break;
+
default:
if (mfd->ioctl_handler)
ret = mfd->ioctl_handler(mfd, cmd, argp);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 80e056f..3fb70bd 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -846,10 +846,17 @@
pr_err("unable to initialize mdss mdp resources\n");
goto probe_done;
}
+ rc = mdss_mdp_pp_init(&pdev->dev);
+ if (rc) {
+ pr_err("unable to initialize mdss pp resources\n");
+ goto probe_done;
+ }
rc = mdss_mdp_bus_scale_register(mdata);
probe_done:
- if (IS_ERR_VALUE(rc))
+ if (IS_ERR_VALUE(rc)) {
mdss_res = NULL;
+ mdss_mdp_pp_term(&pdev->dev);
+ }
return rc;
}
@@ -942,6 +949,7 @@
if (!mdata)
return -ENODEV;
pm_runtime_disable(&pdev->dev);
+ mdss_mdp_pp_term(&pdev->dev);
mdss_mdp_bus_scale_unregister(mdata);
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index a77c18e..610c132 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -295,7 +295,7 @@
int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
int mdss_mdp_csc_setup(u32 block, u32 blk_idx, u32 tbl_idx, u32 csc_type);
-int mdss_mdp_dspp_setup(struct mdss_mdp_ctl *ctl, struct mdss_mdp_mixer *mixer);
+int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum);
struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type);
@@ -318,4 +318,9 @@
int mdss_mdp_wb_kickoff(struct mdss_mdp_ctl *ctl);
int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
+int mdss_mdp_pp_init(struct device *dev);
+void mdss_mdp_pp_term(struct device *dev);
+int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config, u32 *copyback);
+
+int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id);
#endif /* MDSS_MDP_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 1486779..26fbca1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -20,8 +20,8 @@
#include "mdss_fb.h"
#include "mdss_mdp.h"
-/* 1.10 bus fudge factor */
-#define MDSS_MDP_BUS_FUDGE_FACTOR(val) ALIGN((((val) * 11) / 10), SZ_16M)
+/* 1.5 bus fudge factor */
+#define MDSS_MDP_BUS_FUDGE_FACTOR(val) ALIGN((((val) * 3) / 2), SZ_16M)
/* 1.25 clock fudge factor */
#define MDSS_MDP_CLK_FUDGE_FACTOR(val) (((val) * 5) / 4)
@@ -63,7 +63,6 @@
}
}
if (flags & MDSS_MDP_PERF_UPDATE_BUS) {
- bus_ab_quota = MDSS_MDP_BUS_FUDGE_FACTOR(bus_ab_quota);
bus_ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR(bus_ib_quota);
mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
}
@@ -808,9 +807,6 @@
{
mixer->params_changed = 0;
- if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
- mdss_mdp_dspp_setup(mixer->ctl, mixer);
-
/* skip mixer setup for rotator */
if (!mixer->rotator_mode)
mdss_mdp_mixer_setup(mixer->ctl, mixer);
@@ -864,6 +860,8 @@
ctl->flush_bits |= BIT(17); /* CTL */
}
+ /* postprocessing setup, including dspp */
+ mdss_mdp_pp_setup(ctl);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
wmb();
ctl->flush_bits = 0;
@@ -885,3 +883,30 @@
return ret;
}
+
+int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id)
+{
+ int i;
+ struct mdss_mdp_ctl *ctl;
+ u32 mixer_cnt = 0;
+ mutex_lock(&mdss_mdp_ctl_lock);
+ for (i = 0; i < MDSS_MDP_MAX_CTL; i++) {
+ ctl = &mdss_mdp_ctl_list[i];
+ if ((ctl->power_on) &&
+ (ctl->mfd->index == fb_num)) {
+ if (ctl->mixer_left) {
+ mixer_id[mixer_cnt] = ctl->mixer_left->num;
+ mixer_cnt++;
+ }
+ if (mixer_cnt && ctl->mixer_right) {
+ mixer_id[mixer_cnt] = ctl->mixer_right->num;
+ mixer_cnt++;
+ }
+ if (mixer_cnt)
+ break;
+ }
+ }
+ mutex_unlock(&mdss_mdp_ctl_lock);
+ return mixer_cnt;
+}
+
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 8825cc6..0139afd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -321,6 +321,10 @@
MDSS_MDP_MAX_DSPP
};
+#define MDSS_MDP_REG_DSPP_OFFSET(pipe) (0x4600 + ((pipe) * 0x400))
+#define MDSS_MDP_REG_DSPP_OP_MODE 0x000
+#define MDSS_MDP_REG_DSPP_PA_BASE 0x238
+
enum mdss_mpd_intf_index {
MDSS_MDP_NO_INTF,
MDSS_MDP_INTF0,
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index db840a8..7ab3b01 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
+#include "mdss_fb.h"
#include "mdss_mdp.h"
struct mdp_csc_cfg mdp_csc_convert[MDSS_MDP_MAX_CSC] = {
@@ -71,6 +72,27 @@
#define CSC_LV_OFF 0x14
#define CSC_POST_OFF 0xC
+#define MDSS_BLOCK_DISP_NUM (MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0)
+
+struct pp_sts_type {
+ u32 pa_sts;
+};
+
+#define PP_FLAGS_DIRTY_PA 0x1
+
+#define PP_STS_ENABLE 0x1
+
+struct mdss_pp_res_type {
+ /* logical info */
+ u32 pp_disp_flags[MDSS_BLOCK_DISP_NUM];
+ struct mdp_pa_cfg_data pa_disp_cfg[MDSS_BLOCK_DISP_NUM];
+ /* physical info */
+ struct pp_sts_type pp_dspp_sts[MDSS_MDP_MAX_DSPP];
+};
+
+static DEFINE_MUTEX(mdss_pp_mutex);
+static struct mdss_pp_res_type *mdss_pp_res;
+
static int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
struct mdp_csc_cfg *data)
{
@@ -160,16 +182,147 @@
return mdss_mdp_csc_setup_data(block, blk_idx, tbl_idx, data);
}
-int mdss_mdp_dspp_setup(struct mdss_mdp_ctl *ctl, struct mdss_mdp_mixer *mixer)
+static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
+ struct mdss_mdp_mixer *mixer)
{
- int dspp_num;
-
- if (!ctl || !mixer)
- return -EINVAL;
+ u32 flags, base, offset, dspp_num, opmode = 0;
+ struct mdp_pa_cfg_data *pa_config;
+ struct pp_sts_type *pp_sts;
dspp_num = mixer->num;
+ /* no corresponding dspp */
+ if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
+ (dspp_num >= MDSS_MDP_MAX_DSPP))
+ return 0;
- ctl->flush_bits |= BIT(13 + dspp_num); /* DSPP */
+ if (disp_num < MDSS_BLOCK_DISP_NUM)
+ flags = mdss_pp_res->pp_disp_flags[disp_num];
+ else
+ flags = 0;
+
+ /* nothing to update */
+ if (!flags)
+ return 0;
+ pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
+ base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num);
+ if (flags & PP_FLAGS_DIRTY_PA) {
+ pa_config = &mdss_pp_res->pa_disp_cfg[disp_num];
+ if (pa_config->flags & MDP_PP_OPS_WRITE) {
+ offset = base + MDSS_MDP_REG_DSPP_PA_BASE;
+ MDSS_MDP_REG_WRITE(offset, pa_config->hue_adj);
+ offset += 4;
+ MDSS_MDP_REG_WRITE(offset, pa_config->sat_adj);
+ offset += 4;
+ MDSS_MDP_REG_WRITE(offset, pa_config->val_adj);
+ offset += 4;
+ MDSS_MDP_REG_WRITE(offset, pa_config->cont_adj);
+ }
+ if (pa_config->flags & MDP_PP_OPS_DISABLE)
+ pp_sts->pa_sts &= ~PP_STS_ENABLE;
+ else if (pa_config->flags & MDP_PP_OPS_ENABLE)
+ pp_sts->pa_sts |= PP_STS_ENABLE;
+ }
+ if (pp_sts->pa_sts & PP_STS_ENABLE)
+ opmode |= (1 << 20); /* PA_EN */
+ MDSS_MDP_REG_WRITE(base + MDSS_MDP_REG_DSPP_OP_MODE, opmode);
+ ctl->flush_bits |= BIT(13 + dspp_num); /* DSPP */
+ return 0;
+
+}
+int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl)
+{
+ u32 disp_num;
+ if ((!ctl->mfd) || (!mdss_pp_res))
+ return -EINVAL;
+
+ /* treat fb_num the same as block logical id*/
+ disp_num = ctl->mfd->index;
+
+ mutex_lock(&mdss_pp_mutex);
+ if (ctl->mixer_left)
+ pp_dspp_setup(disp_num, ctl, ctl->mixer_left);
+ if (ctl->mixer_right)
+ pp_dspp_setup(disp_num, ctl, ctl->mixer_right);
+ /* clear dirty flag */
+ if (disp_num < MDSS_BLOCK_DISP_NUM)
+ mdss_pp_res->pp_disp_flags[disp_num] = 0;
+ mutex_unlock(&mdss_pp_mutex);
return 0;
}
+
+int mdss_mdp_pp_init(struct device *dev)
+{
+ int ret = 0;
+ mutex_lock(&mdss_pp_mutex);
+ if (!mdss_pp_res) {
+ mdss_pp_res = devm_kzalloc(dev, sizeof(*mdss_pp_res),
+ GFP_KERNEL);
+ if (mdss_pp_res == NULL) {
+ pr_err("%s mdss_pp_res allocation failed!", __func__);
+ ret = -ENOMEM;
+ }
+ }
+ mutex_unlock(&mdss_pp_mutex);
+ return ret;
+}
+void mdss_mdp_pp_term(struct device *dev)
+{
+ if (!mdss_pp_res) {
+ mutex_lock(&mdss_pp_mutex);
+ devm_kfree(dev, mdss_pp_res);
+ mdss_pp_res = NULL;
+ mutex_unlock(&mdss_pp_mutex);
+ }
+}
+
+int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config, u32 *copyback)
+{
+ int i, ret = 0;
+ u32 pa_offset, disp_num, mixer_cnt;
+ u32 mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+
+ if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+ (config->block >= MDP_BLOCK_MAX))
+ return -EINVAL;
+
+ mutex_lock(&mdss_pp_mutex);
+ disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+ if (config->flags & MDP_PP_OPS_READ) {
+ mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
+ if (!mixer_cnt) {
+ ret = -EPERM;
+ goto pa_config_exit;
+ }
+ /* only read the first mixer */
+ for (i = 0; i < mixer_cnt; i++) {
+ if (mixer_id[i] < MDSS_MDP_MAX_DSPP)
+ break;
+ }
+ if (i >= mixer_cnt) {
+ ret = -EPERM;
+ goto pa_config_exit;
+ }
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ pa_offset = MDSS_MDP_REG_DSPP_OFFSET(mixer_id[i]) +
+ MDSS_MDP_REG_DSPP_PA_BASE;
+
+ config->hue_adj = MDSS_MDP_REG_READ(pa_offset);
+ pa_offset += 4;
+ config->sat_adj = MDSS_MDP_REG_READ(pa_offset);
+ pa_offset += 4;
+ config->val_adj = MDSS_MDP_REG_READ(pa_offset);
+ pa_offset += 4;
+ config->cont_adj = MDSS_MDP_REG_READ(pa_offset);
+ *copyback = 1;
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ } else {
+ mdss_pp_res->pa_disp_cfg[disp_num] = *config;
+ mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_PA;
+ }
+
+pa_config_exit:
+ mutex_unlock(&mdss_pp_mutex);
+ return ret;
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
index 3620f1a..2af76f3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
@@ -70,7 +70,6 @@
case VIDC_1080P_ERROR_MEM_ALLOCATION_FAILED:
case VIDC_1080P_ERROR_INSUFFICIENT_CONTEXT_SIZE:
case VIDC_1080P_ERROR_DIVIDE_BY_ZERO:
- case VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY:
case VIDC_1080P_ERROR_DMA_TX_NOT_COMPLETE:
case VIDC_1080P_ERROR_VSP_NOT_READY:
case VIDC_1080P_ERROR_BUFFER_FULL_STATE:
@@ -242,6 +241,7 @@
case VIDC_1080P_ERROR_HEADER_NOT_FOUND:
case VIDC_1080P_ERROR_SLICE_PARSE_ERROR:
case VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED:
+ case VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY:
vcd_status = VCD_ERR_BITSTREAM_ERR;
DDL_MSG_ERROR("VIDC_BIT_STREAM_ERR");
break;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index bfc27dc..4f19de9 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -364,7 +364,7 @@
ddl->command_channel);
} else {
u32 seq_hdr_only_frame = false;
- u32 need_reconfig = false;
+ u32 need_reconfig = false, eos_present = 0;
struct vcd_frame_data *input_vcd_frm =
&ddl->input_frame.vcd_frm;
need_reconfig = ddl_check_reconfig(ddl);
@@ -380,15 +380,25 @@
input_vcd_frm->offset +=
seq_hdr_info.dec_frm_size;
input_vcd_frm->data_len = 0;
- input_vcd_frm->flags |=
- VCD_FRAME_FLAG_CODECCONFIG;
- ddl->input_frame.frm_trans_end =
- !need_reconfig;
- ddl_context->ddl_callback(
+ eos_present =
+ input_vcd_frm->flags & VCD_FRAME_FLAG_EOS;
+ if (!eos_present) {
+ input_vcd_frm->flags |=
+ VCD_FRAME_FLAG_CODECCONFIG;
+ ddl->input_frame.frm_trans_end =
+ !need_reconfig;
+ ddl_context->ddl_callback(
VCD_EVT_RESP_INPUT_DONE,
VCD_S_SUCCESS, &ddl->input_frame,
sizeof(struct ddl_frame_data_tag),
(u32 *) ddl, ddl->client_data);
+ } else {
+ input_vcd_frm->flags &=
+ ~(VCD_FRAME_FLAG_CODECCONFIG);
+ seq_hdr_only_frame = false;
+ pr_err("%s() Codec config buffer with eos\n",
+ __func__);
+ }
} else {
if (decoder->codec.codec ==
VCD_CODEC_VC1_RCV) {
diff --git a/include/linux/msm_audio_aac.h b/include/linux/msm_audio_aac.h
index 620e5ab..ee71c3e 100644
--- a/include/linux/msm_audio_aac.h
+++ b/include/linux/msm_audio_aac.h
@@ -60,6 +60,7 @@
unsigned short sbr_ps_on_flag;
unsigned short dual_mono_mode;
unsigned short channel_configuration;
+ unsigned short sample_rate;
};
struct msm_audio_aac_enc_config {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index c9f9d74..d03ecfa 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -272,8 +272,10 @@
struct msmfb_img img;
};
+#define MDP_PP_OPS_ENABLE 0x1
#define MDP_PP_OPS_READ 0x2
#define MDP_PP_OPS_WRITE 0x4
+#define MDP_PP_OPS_DISABLE 0x8
struct mdp_qseed_cfg {
uint32_t table_num;
@@ -473,12 +475,22 @@
uint32_t scale;
};
+struct mdp_pa_cfg_data {
+ uint32_t block;
+ uint32_t flags;
+ uint32_t hue_adj;
+ uint32_t sat_adj;
+ uint32_t val_adj;
+ uint32_t cont_adj;
+};
+
enum {
mdp_op_pcc_cfg,
mdp_op_csc_cfg,
mdp_op_lut_cfg,
mdp_op_qseed_cfg,
mdp_bl_scale_cfg,
+ mdp_op_pa_cfg,
mdp_op_max,
};
@@ -490,6 +502,7 @@
struct mdp_lut_cfg_data lut_cfg_data;
struct mdp_qseed_cfg_data qseed_cfg_data;
struct mdp_bl_scale_data bl_scale_data;
+ struct mdp_pa_cfg_data pa_cfg_data;
} data;
};
diff --git a/include/linux/sync.h b/include/linux/sync.h
index 943f414..4c00f04 100644
--- a/include/linux/sync.h
+++ b/include/linux/sync.h
@@ -24,6 +24,7 @@
struct sync_timeline;
struct sync_pt;
struct sync_fence;
+struct seq_file;
/**
* struct sync_timeline_ops - sync object implementation ops
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 82f9107..adcc450 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -328,10 +328,12 @@
bool sm_work_pending;
atomic_t pm_suspended;
atomic_t in_lpm;
+ atomic_t suspend_work_pending;
int async_int;
unsigned cur_power;
struct delayed_work chg_work;
struct delayed_work pmic_id_status_work;
+ struct delayed_work suspend_work;
enum usb_chg_state chg_state;
enum usb_chg_type chg_type;
u8 dcd_retries;
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index 2efe31c..cfca799 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -14,8 +14,8 @@
#ifndef _MSM_VIDC_H_
#define _MSM_VIDC_H_
-#include <linux/videodev2.h>
#include <linux/poll.h>
+#include <linux/videodev2.h>
enum core_id {
MSM_VIDC_CORE_0 = 0,
@@ -28,7 +28,21 @@
MSM_VIDC_MAX_DEVICES,
};
-int msm_vidc_open(void *vidc_inst, int core_id, int session_type);
+struct msm_vidc_iommu_info {
+ u32 addr_range[2];
+ char name[64];
+ char ctx[64];
+ int domain;
+ int partition;
+};
+
+enum msm_vidc_io_maps {
+ CP_MAP,
+ NS_MAP,
+ MAX_MAP
+};
+
+void *msm_vidc_open(int core_id, int session_type);
int msm_vidc_close(void *instance);
int msm_vidc_querycap(void *instance, struct v4l2_capability *cap);
int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f);
@@ -47,4 +61,11 @@
int msm_vidc_encoder_cmd(void *instance, struct v4l2_encoder_cmd *enc);
int msm_vidc_poll(void *instance, struct file *filp,
struct poll_table_struct *pt);
+int msm_vidc_get_iommu_maps(void *instance,
+ struct msm_vidc_iommu_info maps[MAX_MAP]);
+int msm_vidc_subscribe_event(void *instance,
+ struct v4l2_event_subscription *sub);
+int msm_vidc_unsubscribe_event(void *instance,
+ struct v4l2_event_subscription *sub);
+int msm_vidc_dqevent(void *instance, struct v4l2_event *event);
#endif
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index e46064b..9bc565e 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1739,6 +1739,48 @@
.ignore_pmdown_time = 1,
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
},
+ {
+ .name = "MSM8960 Media6",
+ .stream_name = "MultiMedia6",
+ .cpu_dai_name = "MultiMedia6",
+ .platform_name = "msm-multi-ch-pcm-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6
+ },
+ {
+ .name = "MSM8960 Compr2",
+ .stream_name = "COMPR2",
+ .cpu_dai_name = "MultiMedia7",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+ },
+ {
+ .name = "MSM8960 Compr3",
+ .stream_name = "COMPR3",
+ .cpu_dai_name = "MultiMedia8",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+ },
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
@@ -2036,7 +2078,8 @@
int ret;
u32 version = socinfo_get_platform_version();
if (!cpu_is_apq8064() || (socinfo_get_id() == 130) ||
- SOCINFO_VERSION_MINOR(version) == 1) {
+ (machine_is_apq8064_mtp() &&
+ (SOCINFO_VERSION_MINOR(version) == 1))) {
pr_info("%s: Not APQ8064 in SLIMBUS mode\n", __func__);
return -ENODEV;
}
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 333f73e..499e4b6 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -54,7 +54,7 @@
#define GPIO_SEC_I2S_RX_WS 48
#define GPIO_SEC_I2S_RX_DOUT 49
#define GPIO_SEC_I2S_RX_MCLK 50
-#define I2S_MCLK_RATE 1536000
+#define I2S_MCLK_RATE 12288000
#define GPIO_MI2S_WS 27
#define GPIO_MI2S_SCLK 28
@@ -813,14 +813,11 @@
static int msm_be_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
- struct snd_interval *rate = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
pr_debug("%s()\n", __func__);
- rate->min = rate->max = 48000;
channels->min = channels->max = 2;
return 0;
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index b76160e..78b3abc 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -354,13 +354,14 @@
switch (compr->info.codec_param.codec.id) {
case SND_AUDIOCODEC_MP3:
+ pr_debug("%s: SND_AUDIOCODEC_MP3\n", __func__);
ret = q6asm_media_format_block(prtd->audio_client,
compr->codec);
if (ret < 0)
pr_info("%s: CMD Format block failed\n", __func__);
break;
case SND_AUDIOCODEC_AAC:
- pr_debug("SND_AUDIOCODEC_AAC\n");
+ pr_debug("%s: SND_AUDIOCODEC_AAC\n", __func__);
memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
aac_cfg.format = 0x03;
@@ -578,7 +579,9 @@
pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (compr->info.codec_param.codec.id ==
- SND_AUDIOCODEC_AC3_PASS_THROUGH) {
+ SND_AUDIOCODEC_AC3_PASS_THROUGH ||
+ compr->info.codec_param.codec.id ==
+ SND_AUDIOCODEC_DTS_PASS_THROUGH) {
msm_pcm_routing_reg_psthr_stream(
soc_prtd->dai_link->be_id,
prtd->session_id, substream->stream,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 6456b2a..41f259d 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -74,6 +74,9 @@
static const DECLARE_TLV_DB_LINEAR(compressed_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
+static int msm_route_compressed2_vol_control;
+static const DECLARE_TLV_DB_LINEAR(compressed2_rx_vol_gain, 0,
+ INT_RX_VOL_MAX_STEPS);
static int msm_route_ec_ref_rx;
/* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
@@ -271,8 +274,10 @@
}
mutex_lock(&routing_lock);
-
- fe_dai_map[fedai_id][session_type] = dspst_id;
+ if (enable)
+ fe_dai_map[fedai_id][session_type] = dspst_id;
+ else
+ fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
if (!is_be_dai_extproc(i) &&
(afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
@@ -867,6 +872,22 @@
return 0;
}
+static int msm_routing_get_compressed2_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = msm_route_compressed2_vol_control;
+ return 0;
+}
+
+static int msm_routing_set_compressed2_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (!compressed_set_volume(ucontrol->value.integer.value[0]))
+ msm_route_compressed2_vol_control =
+ ucontrol->value.integer.value[0];
+ return 0;
+}
+
static int msm_routing_get_srs_trumedia_control(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1431,6 +1452,9 @@
SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("AUX_PCM_TX", MSM_BACKEND_DAI_AUXPCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
@@ -1833,6 +1857,12 @@
msm_routing_set_compressed_vol_mixer, compressed_rx_vol_gain),
};
+static const struct snd_kcontrol_new compressed2_vol_mixer_controls[] = {
+ SOC_SINGLE_EXT_TLV("COMPRESSED2 RX Volume", SND_SOC_NOPM, 0,
+ INT_RX_VOL_GAIN, 0, msm_routing_get_compressed2_vol_mixer,
+ msm_routing_set_compressed2_vol_mixer, compressed2_rx_vol_gain),
+};
+
static const struct snd_kcontrol_new lpa_SRS_trumedia_controls[] = {
{.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "SRS TruMedia",
@@ -2359,6 +2389,7 @@
{"MultiMedia4 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+ {"MultiMedia5 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
{"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2774,6 +2805,9 @@
snd_soc_add_platform_controls(platform,
compressed_vol_mixer_controls,
ARRAY_SIZE(compressed_vol_mixer_controls));
+ snd_soc_add_platform_controls(platform,
+ compressed2_vol_mixer_controls,
+ ARRAY_SIZE(compressed2_vol_mixer_controls));
snd_soc_add_platform_controls(platform,
lpa_SRS_trumedia_controls,
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 6bd6adc..1338e2f 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1372,6 +1372,48 @@
.ignore_pmdown_time = 1,
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
},
+ {
+ .name = "MSM8960 Media6",
+ .stream_name = "MultiMedia6",
+ .cpu_dai_name = "MultiMedia6",
+ .platform_name = "msm-multi-ch-pcm-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6
+ },
+ {
+ .name = "MSM8960 Compr2",
+ .stream_name = "COMPR2",
+ .cpu_dai_name = "MultiMedia7",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+ },
+ {
+ .name = "MSM8960 Compr3",
+ .stream_name = "COMPR3",
+ .cpu_dai_name = "MultiMedia8",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+ },
/* Backend BT/FM DAI Links */
{
.name = LPASS_BE_INT_BT_SCO_RX,