Merge "USB: msm72k_udc: set QMULT for ISO endpoints"
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
index b16d40f..7f2a21b 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
@@ -8,13 +8,25 @@
that need to be monitored for usage requirement to check if a given low power
state can be entered.Each resource is identified by a combination of the name,
id,type and key which is also used by the RPM to identify a shared resource.
+The name and resource-type are required nodes; the type, id and key are
+optional nodes which are needed if the resource type is RPM shared resource
+(MSM_LPM_RPM_RS_TYPE).
-The required nodes for lpm-resources are:
+The nodes for lpm-resources are:
+
+Required Nodes:
- compatible: "qcom,lpm-resources"
- reg: The numeric level id
- qcom,name: The name of the low power resource represented
as a string.
+- qcom,resource-type: The type of the LPM resource.
+ MSM_LPM_RPM_RS_TYPE = 0
+ MSM_LPM_LOCAL_RS_TYPE = 1
+
+
+Optional Nodes:
+
- qcom,type: The type of resource used like smps or pxo
represented as a hex value.
- qcom,id: The id representing a device within a resource type.
@@ -25,6 +37,7 @@
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
+ qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
diff --git a/Documentation/devicetree/bindings/gpio/gpio_keys.txt b/Documentation/devicetree/bindings/gpio/gpio_keys.txt
index 5c2c021..4e810e1 100644
--- a/Documentation/devicetree/bindings/gpio/gpio_keys.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio_keys.txt
@@ -4,6 +4,7 @@
- compatible = "gpio-keys";
Optional properties:
+ - input-name: input name of the device
- autorepeat: Boolean, Enable auto repeat feature of Linux input
subsystem.
@@ -28,6 +29,7 @@
#address-cells = <1>;
#size-cells = <0>;
autorepeat;
+ input-name = "gpio-keys";
button@21 {
label = "GPIO Key UP";
linux,code = <103>;
diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt
index 8b17ba9..5e7c42a 100644
--- a/Documentation/devicetree/bindings/qseecom/qseecom.txt
+++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt
@@ -2,9 +2,21 @@
Required properties:
- compatible : Should be "qcom,qseecom"
+- qcom, msm_bus,name: Should be "qseecom-noc"
+- qcom, msm_bus,num_cases: Depends on the use cases for bus scaling
+- qcom, msm_bus,num_paths: The paths for source and destination ports
+- qcom, msm_bus,vectors: Vectors for bus topology.
Example:
-
qcom,qseecom@fe806000 {
compatible = "qcom,qseecom";
+ qcom,msm_bus,name = "qseecom-noc";
+ qcom,msm_bus,num_cases = <4>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm_bus,vectors =
+ <55 512 0 0>,
+ <55 512 3936000000 393600000>,
+ <55 512 3936000000 393600000>,
+ <55 512 3936000000 393600000>;
};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 2864fd1..3c8cb1b 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -123,16 +123,18 @@
- compatible : "qcom,msm-ocmem-audio"
- - qcom,msm-ocmem-audio-src-id: Master port id
+ - qcom,msm_bus,name: Client name
- - qcom,msm-ocmem-audio-dst-id: Slave port id
+ - qcom,msm_bus,num_cases: Total number of use cases
- - qcom,msm-ocmem-audio-ab: arbitrated bandwidth
- in Bytes/s
+ - qcom,msm_bus,active_only: Context flag for requests in active or
+ dual (active & sleep) contex
- - qcom,msm-ocmem-audio-ib: instantaneous bandwidth
- in Bytes/s
+ - qcom,msm_bus,num_paths: Total number of master-slave pairs
+ - qcom,msm_bus,vectors: Arrays of unsigned integers representing:
+ master-id, slave-id, arbitrated bandwidth,
+ instantaneous bandwidth
Example:
qcom,msm-pcm {
@@ -234,10 +236,13 @@
qcom,msm-ocmem-audio {
compatible = "qcom,msm-ocmem-audio";
- qcom,msm-ocmem-audio-src-id = <11>;
- qcom,msm-ocmem-audio-dst-id = <604>;
- qcom,msm-ocmem-audio-ab = <209715200>;
- qcom,msm-ocmem-audio-ib = <471859200>;
+ qcom,msm_bus,name = "audio-ocmem";
+ qcom,msm_bus,num_cases = <2>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm_bus,vectors =
+ <11 604 0 0>,
+ <11 604 32505856 325058560>;
};
* MSM8974 ASoC Machine driver
diff --git a/arch/arm/boot/dts/msm-iommu.dtsi b/arch/arm/boot/dts/msm-iommu.dtsi
index 2b2a3c0..709f40a 100755
--- a/arch/arm/boot/dts/msm-iommu.dtsi
+++ b/arch/arm/boot/dts/msm-iommu.dtsi
@@ -108,6 +108,32 @@
qcom,needs-alt-core-clk;
status = "disabled";
+ qcom,iommu-bfb-regs = <0x204c
+ 0x2050
+ 0x2514
+ 0x2540
+ 0x256c
+ 0x20ac
+ 0x215c
+ 0x220c
+ 0x2314
+ 0x2394
+ 0x2414
+ 0x2008>;
+
+ qcom,iommu-bfb-data = <0xffffffff
+ 0xffffffff
+ 0x00000004
+ 0x00000010
+ 0x00000000
+ 0x00000000
+ 0x00000001
+ 0x00000021
+ 0x0
+ 0x1
+ 0x81
+ 0x0>;
+
qcom,iommu-ctx@fdb18000 {
reg = <0xfdb18000 0x1000>;
interrupts = <0 241 0>;
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index 4330849..aeda1d8 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -58,4 +58,21 @@
reg = <0xf995e000 0x1000>;
interrupts = <0 114 0>;
};
+
+ usb@f9a55000 {
+ compatible = "qcom,hsusb-otg";
+ reg = <0xf9a55000 0x400>;
+ interrupts = <0 134 0>;
+ interrupt-names = "core_irq";
+
+ qcom,hsusb-otg-phy-type = <2>;
+ qcom,hsusb-otg-mode = <1>;
+ qcom,hsusb-otg-otg-control = <1>;
+ qcom,hsusb-otg-disable-reset;
+ };
+
+ android_usb {
+ compatible = "qcom,android-usb";
+ };
+
};
diff --git a/arch/arm/boot/dts/msm8910-sim.dts b/arch/arm/boot/dts/msm8910-sim.dts
new file mode 100644
index 0000000..268e1f8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8910-sim.dts
@@ -0,0 +1,51 @@
+/* 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.
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8910 Simulator";
+ compatible = "qcom,msm8910-sim", "qcom,msm8910";
+ qcom,msm-id = <147 1 0>;
+ interrupt-parent = <&intc>;
+
+ intc: interrupt-controller@f9000000 {
+ compatible = "qcom,msm-qgic2";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0xf9000000 0x1000>,
+ <0xf9002000 0x1000>;
+ };
+
+ msmgpio: gpio@fd510000 {
+ compatible = "qcom,msm-gpio";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0xfd510000 0x4000>;
+ #gpio-cells = <2>;
+ };
+
+ timer: msm-qtimer@f9021000 {
+ compatible = "qcom,msm-qtimer", "arm,armv7-timer";
+ reg = <0xf9021000 0x1000>;
+ interrupts = <0 7 0 0 8 0>;
+ irq-is-not-percpu;
+ clock-frequency = <19200000>;
+ };
+
+ serial@f991f000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0xf991f000 0x1000>;
+ interrupts = <0 109 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index aff0adc..05fcc4f 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -112,6 +112,7 @@
gpio_keys {
compatible = "gpio-keys";
+ input-name = "gpio-keys";
camera_snapshot {
label = "camera_snapshot";
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index 00aec9f..e0d6ad3 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -112,6 +112,7 @@
gpio_keys {
compatible = "gpio-keys";
+ input-name = "gpio-keys";
camera_snapshot {
label = "camera_snapshot";
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index b992e86..8e6f1e6 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -761,10 +761,13 @@
qcom,msm-ocmem-audio {
compatible = "qcom,msm-ocmem-audio";
- qcom,msm-ocmem-audio-src-id = <11>;
- qcom,msm-ocmem-audio-dst-id = <604>;
- qcom,msm-ocmem-audio-ab = <32505856>;
- qcom,msm-ocmem-audio-ib = <32505856>;
+ qcom,msm_bus,name = "audio-ocmem";
+ qcom,msm_bus,num_cases = <2>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm_bus,vectors =
+ <11 604 0 0>,
+ <11 604 32505856 32505856>;
};
qcom,mss@fc880000 {
@@ -883,6 +886,15 @@
qcom,qseecom@fe806000 {
compatible = "qcom,qseecom";
+ qcom,msm_bus,name = "qseecom-noc";
+ qcom,msm_bus,num_cases = <4>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm_bus,vectors =
+ <55 512 0 0>,
+ <55 512 3936000000 393600000>,
+ <55 512 3936000000 393600000>,
+ <55 512 3936000000 393600000>;
};
qcom,wdt@f9017000 {
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index e39a72a..f108d37 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -130,6 +130,7 @@
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
+ qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
@@ -138,6 +139,7 @@
qcom,lpm-resources@1 {
reg = <0x1>;
qcom,name = "vdd-mem";
+ qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x01>;
qcom,key = <0x7675>; /* "uv" */
@@ -146,10 +148,17 @@
qcom,lpm-resources@2 {
reg = <0x2>;
qcom,name = "pxo";
+ qcom,resource-type = <0>;
qcom,type = <0x306b6c63>; /* "clk0" */
qcom,id = <0x00>;
qcom,key = <0x62616e45>; /* "Enab" */
};
+
+ qcom,lpm-resources@3 {
+ reg = <0x3>;
+ qcom,name = "l2";
+ qcom,resource-type = <1>;
+ };
};
qcom,lpm-levels {
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
new file mode 100644
index 0000000..ebcc6f5
--- /dev/null
+++ b/arch/arm/configs/msm8910_defconfig
@@ -0,0 +1,100 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+# CONFIG_FAIR_GROUP_SCHED is not set
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM8910=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_CPU_HAS_L2_PMU=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_USE_OF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_ANDROID_PMEM is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 2cc801e..9d4ef05 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -49,6 +49,7 @@
CONFIG_MSM_SUBSYSTEM_RESTART=y
# CONFIG_MSM_SYSMON_COMM is not set
CONFIG_MSM_MODEM_8960=y
+CONFIG_MSM_PIL_MODEM_QDSP6V4=y
CONFIG_MSM_LPASS_8960=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 60963c6..d7cdbc4 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -105,7 +105,11 @@
# CONFIG_HWMON is not set
CONFIG_REGULATOR=y
CONFIG_REGULATOR_QPNP=y
-# CONFIG_HID_SUPPORT is not set
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
CONFIG_USB_GADGET=y
CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_G_ANDROID=y
@@ -150,3 +154,12 @@
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index 90c9c9e..8f58adf 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -709,8 +709,6 @@
static struct arm_pmu scorpion_pmu = {
.handle_irq = armv7pmu_handle_irq,
- .request_pmu_irq = msm_request_irq,
- .free_pmu_irq = msm_free_irq,
.enable = scorpion_pmu_enable_event,
.disable = scorpion_pmu_disable_event,
.read_counter = armv7pmu_read_counter,
@@ -731,6 +729,9 @@
scorpion_pmu.name = "ARMv7 Scorpion";
scorpion_pmu.num_events = armv7_read_num_pmnc_events();
scorpion_pmu.pmu.attr_groups = msm_l1_pmu_attr_grps;
+ /* Unicore can't use the percpu IRQ API. */
+ scorpion_pmu.request_pmu_irq = armpmu_generic_request_irq;
+ scorpion_pmu.free_pmu_irq = armpmu_generic_free_irq;
scorpion_clear_pmuregs();
return &scorpion_pmu;
}
@@ -741,6 +742,8 @@
scorpion_pmu.name = "ARMv7 Scorpion-MP";
scorpion_pmu.num_events = armv7_read_num_pmnc_events();
scorpion_pmu.pmu.attr_groups = msm_l1_pmu_attr_grps;
+ scorpion_pmu.request_pmu_irq = msm_request_irq;
+ scorpion_pmu.free_pmu_irq = msm_free_irq;
scorpion_clear_pmuregs();
return &scorpion_pmu;
}
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 8d8f47a..eec614b 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -540,8 +540,8 @@
int err = 0;
int cpu;
- err = request_percpu_irq(irq, *handle_irq, "krait-l1-armpmu",
- &cpu_hw_events);
+ err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
+ &cpu_hw_events);
if (!err) {
for_each_cpu(cpu, cpu_online_mask) {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 6e841c7..ac4aeba 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -356,10 +356,13 @@
select CPU_V7
select MSM_GPIOMUX
select MSM_RPM_SMD
+ select MSM_NATIVE_RESTART
+ select MSM_RESTART_V2
select MULTI_IRQ_HANDLER
select GPIO_MSM_V3
select MAY_HAVE_SPARSE_IRQ
select SPARSE_IRQ
+ select MSM_MULTIMEDIA_USE_ION
config ARCH_MSM8910
bool "MSM8910"
@@ -1942,7 +1945,7 @@
config MSM_PIL_MODEM_QDSP6V4
tristate "Modem QDSP6v4 (Hexagon) Boot Support"
- depends on MSM_PIL
+ depends on MSM_SUBSYSTEM_RESTART
help
Support for booting and shutting down QDSP6v4 processors (hexagon)
in modem subsystems. If you would like to make or receive phone
@@ -2030,14 +2033,6 @@
bool "Secure Channel Manager (SCM) support"
default n
-config MSM_MODEM_8960
- bool "MSM 8960 Modem driver"
- depends on (ARCH_MSM8960 || ARCH_MSM9615)
- help
- This option enables the modem driver for the MSM8960 and MSM9615, which monitors
- modem hardware watchdog interrupt lines and plugs into the subsystem
- restart and PIL drivers. For MSM9615, it only supports a full chip reset.
-
config MSM_LPASS_8960
tristate "MSM 8960 Lpass driver"
depends on (ARCH_MSM8960 || ARCH_MSM9615)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 0329896..76972ec 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -107,6 +107,7 @@
ifndef CONFIG_ARCH_MSM8226
ifndef CONFIG_ARCH_MSM9625
ifndef CONFIG_ARCH_MPQ8092
+ifndef CONFIG_ARCH_MSM8910
obj-y += nand_partitions.o
endif
endif
@@ -115,6 +116,7 @@
endif
endif
endif
+endif
obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -198,7 +200,6 @@
obj-y += ramdump.o
endif
obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
-obj-$(CONFIG_MSM_MODEM_8960) += modem-8960.o
obj-$(CONFIG_MSM_MODEM_SSR_8974) += modem-ssr-8974.o
obj-$(CONFIG_MSM_LPASS_8960) += lpass-8960.o
obj-$(CONFIG_MSM_ADSP_SSR_8974) += adsp-8974.o
@@ -290,6 +291,7 @@
obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o
obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
+obj-$(CONFIG_ARCH_MSM8910) += board-8910.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -347,6 +349,7 @@
obj-$(CONFIG_ARCH_MSM9625) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MPQ8092) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM8910) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_mpdecision.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 9234b2c..cf1f401 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -65,3 +65,5 @@
# MPQ8092
zreladdr-$(CONFIG_ARCH_MPQ8092) := 0x00008000
+# MSM8910
+ zreladdr-$(CONFIG_ARCH_MSM8910) := 0x00008000
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index c79f82f..0a95e51 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -503,6 +503,34 @@
.i2c_mux_mode = MODE_L,
};
+static struct msm_camera_sensor_flash_data flash_imx135 = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_csi_lane_params imx135_csi_lane_params = {
+ .csi_lane_assign = 0xE4,
+ .csi_lane_mask = 0xF,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_imx135 = {
+ .mount_angle = 90,
+ .cam_vreg = apq_8064_cam_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
+ .gpio_conf = &apq8064_back_cam_gpio_conf,
+ .i2c_conf = &apq8064_back_cam_i2c_conf,
+ .csi_lane_params = &imx135_csi_lane_params,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_imx135_data = {
+ .sensor_name = "imx135",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_imx135,
+ .sensor_platform_info = &sensor_board_info_imx135,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+ .sensor_type = BAYER_SENSOR,
+};
+
static struct msm_camera_sensor_flash_data flash_imx074 = {
.flash_type = MSM_CAMERA_FLASH_LED,
.flash_src = &msm_flash_src
@@ -700,6 +728,10 @@
.platform_data = &msm_camera_sensor_imx074_data,
},
{
+ I2C_BOARD_INFO("imx135", 0x10),
+ .platform_data = &msm_camera_sensor_imx135_data,
+ },
+ {
I2C_BOARD_INFO("mt9m114", 0x48),
.platform_data = &msm_camera_sensor_mt9m114_data,
},
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 2bef087..851f7d9 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -64,6 +64,7 @@
VREG_CONSUMERS(L8) = {
REGULATOR_SUPPLY("8921_l8", NULL),
REGULATOR_SUPPLY("cam_vana", "4-001a"),
+ REGULATOR_SUPPLY("cam_vana", "4-0010"),
REGULATOR_SUPPLY("cam_vana", "4-0048"),
REGULATOR_SUPPLY("cam_vana", "4-006c"),
REGULATOR_SUPPLY("cam_vana", "4-0034"),
@@ -84,6 +85,7 @@
};
VREG_CONSUMERS(L12) = {
REGULATOR_SUPPLY("cam_vdig", "4-001a"),
+ REGULATOR_SUPPLY("cam_vdig", "4-0010"),
REGULATOR_SUPPLY("cam_vdig", "4-0048"),
REGULATOR_SUPPLY("cam_vdig", "4-006c"),
REGULATOR_SUPPLY("cam_vdig", "4-0034"),
@@ -102,6 +104,7 @@
VREG_CONSUMERS(L16) = {
REGULATOR_SUPPLY("8921_l16", NULL),
REGULATOR_SUPPLY("cam_vaf", "4-001a"),
+ REGULATOR_SUPPLY("cam_vaf", "4-0010"),
REGULATOR_SUPPLY("cam_vaf", "4-0048"),
REGULATOR_SUPPLY("cam_vaf", "4-006c"),
REGULATOR_SUPPLY("cam_vaf", "4-0034"),
@@ -214,6 +217,7 @@
VREG_CONSUMERS(LVS5) = {
REGULATOR_SUPPLY("8921_lvs5", NULL),
REGULATOR_SUPPLY("cam_vio", "4-001a"),
+ REGULATOR_SUPPLY("cam_vio", "4-0010"),
REGULATOR_SUPPLY("cam_vio", "4-0048"),
REGULATOR_SUPPLY("cam_vio", "4-006c"),
REGULATOR_SUPPLY("cam_vio", "4-0034"),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index e2dc98e..b3add3b 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2562,6 +2562,7 @@
&apq8064_rpm_device,
&apq8064_rpm_log_device,
&apq8064_rpm_stat_device,
+ &apq8064_rpm_master_stat_device,
&apq_device_tz_log,
&msm_bus_8064_apps_fabric,
&msm_bus_8064_sys_fabric,
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 9545c7a..767736f 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -46,6 +46,8 @@
static struct clk_lookup msm_clocks_dummy[] = {
CLK_DUMMY("core_clk", BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
+ CLK_DUMMY("iface_clk", HSUSB_IFACE_CLK, "msm_otg", OFF),
+ CLK_DUMMY("core_clk", HSUSB_CORE_CLK, "msm_otg", OFF),
};
struct clock_init_data msm_dummy_clock_init_data __initdata = {
@@ -62,6 +64,8 @@
static struct of_dev_auxdata msm8226_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
"msm_serial_hsl.0", NULL),
+ OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
+ "msm_otg", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-8910.c b/arch/arm/mach-msm/board-8910.c
new file mode 100644
index 0000000..18463e3
--- /dev/null
+++ b/arch/arm/mach-msm/board-8910.c
@@ -0,0 +1,94 @@
+/* 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/memory.h>
+#include <asm/mach/map.h>
+#include <asm/arch_timer.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+#ifdef CONFIG_ION_MSM
+#include <mach/ion.h>
+#endif
+#include <mach/socinfo.h>
+#include <mach/board.h>
+#include <mach/clk-provider.h>
+#include "clock.h"
+
+static struct clk_lookup msm_clocks_dummy[] = {
+ CLK_DUMMY("core_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+ CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+};
+
+struct clock_init_data msm_dummy_clock_init_data __initdata = {
+ .table = msm_clocks_dummy,
+ .size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+static struct of_device_id irq_match[] __initdata = {
+ { .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
+ { .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
+ {},
+};
+
+static void __init msm8910_dt_timer_init(void)
+{
+ arch_timer_of_register();
+}
+
+static struct sys_timer msm8910_dt_timer = {
+ .init = msm8910_dt_timer_init
+};
+
+void __init msm8910_init_irq(void)
+{
+ of_irq_init(irq_match);
+}
+
+void __init msm8910_init(void)
+{
+ msm_clock_init(&msm_dummy_clock_init_data);
+
+ if (socinfo_init() < 0)
+ pr_err("%s: socinfo_init() failed\n", __func__);
+
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *msm8910_dt_match[] __initconst = {
+ "qcom,msm8910",
+ NULL
+};
+
+DT_MACHINE_START(MSM8910_DT, "Qualcomm MSM 8910 (Flattened Device Tree)")
+ .map_io = msm_map_msm8910_io,
+ .init_irq = msm8910_init_irq,
+ .init_machine = msm8910_init,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm8910_dt_timer,
+ .dt_compat = msm8910_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index fc4b819..f0f59ec 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -2397,6 +2397,7 @@
&msm8930_rpm_log_device,
&msm8930_rpm_rbcpr_device,
&msm8930_rpm_stat_device,
+ &msm8930_rpm_master_stat_device,
#ifdef CONFIG_ION_MSM
&msm8930_ion_dev,
#endif
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 9bb6e09..88fd527 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -752,6 +752,33 @@
.eeprom_info = &imx091_eeprom_info,
};
+static struct msm_camera_sensor_flash_data flash_imx135 = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_csi_lane_params imx135_csi_lane_params = {
+ .csi_lane_assign = 0xE4,
+ .csi_lane_mask = 0xF,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_imx135 = {
+ .mount_angle = 90,
+ .cam_vreg = msm_8960_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
+ .gpio_conf = &msm_8960_back_cam_gpio_conf,
+ .csi_lane_params = &imx135_csi_lane_params,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_imx135_data = {
+ .sensor_name = "imx135",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_imx135,
+ .sensor_platform_info = &sensor_board_info_imx135,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+ .sensor_type = BAYER_SENSOR,
+};
+
static struct pm8xxx_mpp_config_data privacy_light_on_config = {
.type = PM8XXX_MPP_TYPE_SINK,
.level = PM8XXX_MPP_CS_OUT_5MA,
@@ -838,6 +865,10 @@
.platform_data = &msm_camera_sensor_ov2720_data,
},
{
+ I2C_BOARD_INFO("imx135", 0x10),
+ .platform_data = &msm_camera_sensor_imx135_data,
+ },
+ {
I2C_BOARD_INFO("mt9m114", 0x48),
.platform_data = &msm_camera_sensor_mt9m114_data,
},
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index a6c0bc7..f9e2c8e 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -78,6 +78,7 @@
REGULATOR_SUPPLY("cam_vana", "4-0048"),
REGULATOR_SUPPLY("cam_vana", "4-0020"),
REGULATOR_SUPPLY("cam_vana", "4-0034"),
+ REGULATOR_SUPPLY("cam_vana", "4-0010"),
};
VREG_CONSUMERS(L12) = {
REGULATOR_SUPPLY("8921_l12", NULL),
@@ -86,6 +87,7 @@
REGULATOR_SUPPLY("cam_vdig", "4-0048"),
REGULATOR_SUPPLY("cam_vdig", "4-0020"),
REGULATOR_SUPPLY("cam_vdig", "4-0034"),
+ REGULATOR_SUPPLY("cam_vdig", "4-0010"),
};
VREG_CONSUMERS(L14) = {
REGULATOR_SUPPLY("8921_l14", NULL),
@@ -101,6 +103,7 @@
REGULATOR_SUPPLY("cam_vaf", "4-0048"),
REGULATOR_SUPPLY("cam_vaf", "4-0020"),
REGULATOR_SUPPLY("cam_vaf", "4-0034"),
+ REGULATOR_SUPPLY("cam_vaf", "4-0010"),
};
VREG_CONSUMERS(L17) = {
REGULATOR_SUPPLY("8921_l17", NULL),
@@ -220,6 +223,7 @@
REGULATOR_SUPPLY("cam_vio", "4-0048"),
REGULATOR_SUPPLY("cam_vio", "4-0020"),
REGULATOR_SUPPLY("cam_vio", "4-0034"),
+ REGULATOR_SUPPLY("cam_vio", "4-0010"),
};
/* This mapping is used for CDP only. */
VREG_CONSUMERS(CDP_LVS6) = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 7833225..7e96edf 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2753,6 +2753,7 @@
&msm8960_rpm_device,
&msm8960_rpm_log_device,
&msm8960_rpm_stat_device,
+ &msm8960_rpm_master_stat_device,
&msm_device_tz_log,
&coresight_tpiu_device,
&coresight_etb_device,
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index ca95b62..fb94ac0 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -870,6 +870,7 @@
#ifdef CONFIG_LTC4088_CHARGER
&msm_device_charger,
#endif
+ &msm_9615_q6_mss,
&msm_device_otg,
&msm_device_hsic_peripheral,
&msm_device_gadget_peripheral,
@@ -933,6 +934,7 @@
&msm_bus_def_fab,
&msm9615_rpm_log_device,
&msm9615_rpm_stat_device,
+ &msm9615_rpm_master_stat_device,
&msm_tsens_device,
};
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index ca9bdaa..2c641ed 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -28,6 +28,7 @@
#include <asm/mach/time.h>
#include <mach/socinfo.h>
#include <mach/board.h>
+#include <mach/restart.h>
#include <mach/gpio.h>
#include <mach/clk-provider.h>
#include <mach/qpnp-int.h>
@@ -308,4 +309,5 @@
.timer = &msm_dt_timer,
.dt_compat = msm9625_dt_match,
.reserve = msm9625_reserve,
+ .restart = msm_restart,
MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 3a72be3..285b037 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5351,6 +5351,7 @@
CLK_LOOKUP("core_clk", pmic_ssbi2_clk.c, ""),
CLK_LOOKUP("mem_clk", rpm_msg_ram_p_clk.c, ""),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-001a"),
+ CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0010"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0034"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0020"),
CLK_LOOKUP("cam_clk", cam1_clk.c, "4-0048"),
@@ -5711,6 +5712,7 @@
CLK_LOOKUP("cam_clk", cam2_clk.c, NULL),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0020"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0034"),
+ CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0010"),
CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_csid.0"),
CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, "msm_csid.1"),
CLK_LOOKUP("csi_src_clk", csi2_src_clk.c, "msm_csid.2"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 10de231..0adb9a2 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -789,7 +789,6 @@
static DEFINE_CLK_VOTER(pnoc_sdcc4_clk, &pnoc_clk.c, 0);
static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, 0);
-static DEFINE_CLK_VOTER(pnoc_qseecom_clk, &pnoc_clk.c, 0);
static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
F(125000000, gpll0, 1, 5, 24),
@@ -5079,6 +5078,11 @@
CLK_LOOKUP("bus_clk", gcc_ce2_axi_clk.c, "qcrypto.0"),
CLK_LOOKUP("core_clk_src", ce2_clk_src.c, "qcrypto.0"),
+ CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "qseecom"),
+ CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "qseecom"),
+ CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "qseecom"),
+ CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "qseecom"),
+
CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
@@ -5361,7 +5365,6 @@
CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
- CLK_LOOKUP("bus_clk", pnoc_qseecom_clk.c, "qseecom"),
CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 6e7283b..a49a145 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -101,6 +101,7 @@
#define PCIE20_SIZE SZ_4K
#define MSM8064_PC_CNTR_PHYS (APQ8064_IMEM_PHYS + 0x664)
#define MSM8064_PC_CNTR_SIZE 0x40
+#define MSM8064_RPM_MASTER_STATS_BASE 0x10BB00
static struct resource msm8064_resources_pccntr[] = {
{
@@ -2351,6 +2352,37 @@
},
};
+static struct resource resources_rpm_master_stats[] = {
+ {
+ .start = MSM8064_RPM_MASTER_STATS_BASE,
+ .end = MSM8064_RPM_MASTER_STATS_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static char *master_names[] = {
+ "KPSS",
+ "MPSS",
+ "LPASS",
+ "RIVA",
+ "DSPS",
+};
+
+static struct msm_rpm_master_stats_platform_data msm_rpm_master_stat_pdata = {
+ .masters = master_names,
+ .nomasters = ARRAY_SIZE(master_names),
+};
+
+struct platform_device apq8064_rpm_master_stat_device = {
+ .name = "msm_rpm_master_stat",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_rpm_master_stats),
+ .resource = resources_rpm_master_stats,
+ .dev = {
+ .platform_data = &msm_rpm_master_stat_pdata,
+ },
+};
+
static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
.phys_addr_base = 0x0010C000,
.reg_offsets = {
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index ef3b950..30a99cd 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -38,6 +38,7 @@
#endif
#define MSM8930_PC_CNTR_PHYS (MSM8930_IMEM_PHYS + 0x664)
#define MSM8930_PC_CNTR_SIZE 0x40
+#define MSM8930_RPM_MASTER_STATS_BASE 0x10B100
static struct resource msm8930_resources_pccntr[] = {
{
@@ -558,6 +559,36 @@
},
};
+static struct resource resources_rpm_master_stats[] = {
+ {
+ .start = MSM8930_RPM_MASTER_STATS_BASE,
+ .end = MSM8930_RPM_MASTER_STATS_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static char *master_names[] = {
+ "KPSS",
+ "MPSS",
+ "LPASS",
+ "RIVA",
+};
+
+static struct msm_rpm_master_stats_platform_data msm_rpm_master_stat_pdata = {
+ .masters = master_names,
+ .nomasters = ARRAY_SIZE(master_names),
+};
+
+struct platform_device msm8930_rpm_master_stat_device = {
+ .name = "msm_rpm_master_stat",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_rpm_master_stats),
+ .resource = resources_rpm_master_stats,
+ .dev = {
+ .platform_data = &msm_rpm_master_stat_pdata,
+ },
+};
+
static struct resource msm_rpm_rbcpr_resource = {
.start = 0x0010DB00,
.end = 0x0010DB00 + SZ_8K - 1,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 0b167e5..433ed31 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -105,6 +105,7 @@
#define MSM8960_PC_CNTR_PHYS (MSM8960_IMEM_PHYS + 0x664)
#define MSM8960_PC_CNTR_SIZE 0x40
+#define MSM8960_RPM_MASTER_STATS_BASE 0x10BB00
static struct resource msm8960_resources_pccntr[] = {
{
@@ -1372,10 +1373,30 @@
.flags = IORESOURCE_MEM,
},
{
+ .start = 0x08882000,
+ .end = 0x08882000 + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
.start = 0x08900000,
.end = 0x08900000 + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = 0x08982000,
+ .end = 0x08982000 + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = Q6FW_WDOG_EXPIRED_IRQ,
+ .end = Q6FW_WDOG_EXPIRED_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = Q6SW_WDOG_EXPIRED_IRQ,
+ .end = Q6SW_WDOG_EXPIRED_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct pil_q6v4_pdata msm_8960_q6_mss_data[2] = {
@@ -3720,6 +3741,37 @@
},
};
+static struct resource resources_rpm_master_stats[] = {
+ {
+ .start = MSM8960_RPM_MASTER_STATS_BASE,
+ .end = MSM8960_RPM_MASTER_STATS_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static char *master_names[] = {
+ "KPSS",
+ "GPSS",
+ "LPASS",
+ "RIVA",
+ "DSPS",
+};
+
+static struct msm_rpm_master_stats_platform_data msm_rpm_master_stat_pdata = {
+ .masters = master_names,
+ .nomasters = ARRAY_SIZE(master_names),
+};
+
+struct platform_device msm8960_rpm_master_stat_device = {
+ .name = "msm_rpm_master_stat",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_rpm_master_stats),
+ .resource = resources_rpm_master_stats,
+ .dev = {
+ .platform_data = &msm_rpm_master_stat_pdata,
+ },
+};
+
struct platform_device msm_bus_sys_fabric = {
.name = "msm_bus_fabric",
.id = MSM_BUS_FAB_SYSTEM,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 46853ac..b8c5a1f 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -64,6 +64,7 @@
#define MSM_GPIO_I2C_CLK 16
#define MSM_GPIO_I2C_SDA 17
+#define MSM9615_RPM_MASTER_STATS_BASE 0x10A700
static struct msm_watchdog_pdata msm_watchdog_pdata = {
.pet_time = 10000,
@@ -704,6 +705,26 @@
.id = -1,
};
+static struct resource msm_9615_q6_mss_resources[] = {
+ {
+ .start = Q6FW_WDOG_EXPIRED_IRQ,
+ .end = Q6FW_WDOG_EXPIRED_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = Q6SW_WDOG_EXPIRED_IRQ,
+ .end = Q6SW_WDOG_EXPIRED_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_9615_q6_mss = {
+ .name = "pil-q6v4-modem",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(msm_9615_q6_mss_resources),
+ .resource = msm_9615_q6_mss_resources,
+};
+
#ifdef CONFIG_HW_RANDOM_MSM
/* PRNG device */
#define MSM_PRNG_PHYS 0x1A500000
@@ -1328,6 +1349,35 @@
},
};
+static struct resource resources_rpm_master_stats[] = {
+ {
+ .start = MSM9615_RPM_MASTER_STATS_BASE,
+ .end = MSM9615_RPM_MASTER_STATS_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static char *master_names[] = {
+ "KPSS",
+ "MPSS",
+ "LPASS",
+};
+
+static struct msm_rpm_master_stats_platform_data msm_rpm_master_stat_pdata = {
+ .masters = master_names,
+ .nomasters = ARRAY_SIZE(master_names),
+};
+
+struct platform_device msm9615_rpm_master_stat_device = {
+ .name = "msm_rpm_master_stat",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_rpm_master_stats),
+ .resource = resources_rpm_master_stats,
+ .dev = {
+ .platform_data = &msm_rpm_master_stat_pdata,
+ },
+};
+
static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
.phys_addr_base = 0x0010AC00,
.reg_offsets = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 5b291a7..744db1d 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -252,6 +252,7 @@
extern struct platform_device msm_pil_vidc;
extern struct platform_device msm_8960_q6_lpass;
extern struct platform_device msm_8960_q6_mss;
+extern struct platform_device msm_9615_q6_mss;
extern struct platform_device msm_8960_riva;
extern struct platform_device msm_gss;
@@ -334,10 +335,12 @@
extern struct platform_device msm8960_rpm_device;
extern struct platform_device msm8960_rpm_stat_device;
+extern struct platform_device msm8960_rpm_master_stat_device;
extern struct platform_device msm8960_rpm_log_device;
extern struct platform_device msm8930_rpm_device;
extern struct platform_device msm8930_rpm_stat_device;
+extern struct platform_device msm8930_rpm_master_stat_device;
extern struct platform_device msm8930_rpm_log_device;
extern struct platform_device msm8930_rpm_rbcpr_device;
@@ -347,10 +350,12 @@
extern struct platform_device msm9615_rpm_device;
extern struct platform_device msm9615_rpm_stat_device;
+extern struct platform_device msm9615_rpm_master_stat_device;
extern struct platform_device msm9615_rpm_log_device;
extern struct platform_device apq8064_rpm_device;
extern struct platform_device apq8064_rpm_stat_device;
+extern struct platform_device apq8064_rpm_master_stat_device;
extern struct platform_device apq8064_rpm_log_device;
extern struct platform_device msm_device_rng;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 433fee3..0b53bad 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -586,6 +586,8 @@
void msm_map_msm8226_io(void);
void msm8226_init_irq(void);
void msm8226_init_gpiomux(void);
+void msm_map_msm8910_io(void);
+void msm8910_init_irq(void);
struct mmc_platform_data;
int msm_add_sdcc(unsigned int controller,
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 765de13..652563c 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -43,6 +43,9 @@
#define MSM9625_IMEM_PHYS 0xFC42B000
#define MSM9625_IMEM_SIZE SZ_2K
+#define MSM9625_MPM2_PSHOLD_PHYS 0xFC4AB000
+#define MSM9625_MPM2_PSHOLD_SIZE SZ_4K
+
#ifdef CONFIG_DEBUG_MSM9625_UART
#define MSM_DEBUG_UART_BASE IOMEM(0xFA71E000)
#define MSM_DEBUG_UART_PHYS 0xF991E000
diff --git a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
index 92dfe12..2cfdabf 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 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
@@ -123,7 +123,8 @@
uint64_t bytecount_given;
uint64_t bytecount_query;
- struct list_head pmem_region_queue; /* protected by lock */
+ struct list_head ion_region_queue; /* protected by lock */
+ struct ion_client *client;
int eq_enable;
int eq_needs_commit;
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h b/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h
index 487e814..da639ce 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h
@@ -78,7 +78,7 @@
} __packed;
/* Max number of static located transparent data (bytes) */
-#define USM_MAX_CFG_DATA_SIZE 20
+#define USM_MAX_CFG_DATA_SIZE 100
struct usm_encode_cfg_blk {
u32 frames_per_buf;
u32 format_id;
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 8ebead8..4b81ce7 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -461,6 +461,7 @@
static struct map_desc msm9625_io_desc[] __initdata = {
MSM_CHIP_DEVICE(APCS_GCC, MSM9625),
MSM_CHIP_DEVICE(TLMM, MSM9625),
+ MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM9625),
MSM_CHIP_DEVICE(TMR, MSM9625),
MSM_CHIP_DEVICE(IMEM, MSM9625),
{
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 48d31f3..364f297 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -104,6 +104,11 @@
struct msm_rpm_request *handle;
};
+enum {
+ MSM_LPM_RPM_RS_TYPE = 0,
+ MSM_LPM_LOCAL_RS_TYPE = 1,
+};
+
struct msm_lpm_resource {
struct msm_lpm_rs_data rs_data;
uint32_t sleep_value;
@@ -126,7 +131,7 @@
.aggregate = msm_lpm_aggregate_l2,
.flush = msm_lpm_flush_l2,
.notify = NULL,
- .valid = true,
+ .valid = false,
.rs_data = {
.value = MSM_LPM_L2_CACHE_ACTIVE,
.default_value = MSM_LPM_L2_CACHE_ACTIVE,
@@ -787,6 +792,7 @@
struct msm_lpm_resource *rs = NULL;
const char *val;
int i;
+ uint32_t resource_type;
key = "qcom,name";
ret = of_property_read_string(node, key, &val);
@@ -810,49 +816,73 @@
continue;
}
- key = "qcom,type";
- ret = of_property_read_u32(node, key, &rs->rs_data.type);
+ key = "qcom,resource-type";
+ ret = of_property_read_u32(node, key, &resource_type);
if (ret) {
- pr_err("Failed to read type\n");
+ pr_err("Failed to read resource-type\n");
goto fail;
}
- key = "qcom,id";
- ret = of_property_read_u32(node, key, &rs->rs_data.id);
- if (ret) {
- pr_err("Failed to read id\n");
+ switch (resource_type) {
+ case MSM_LPM_RPM_RS_TYPE:
+ key = "qcom,type";
+ ret = of_property_read_u32(node, key,
+ &rs->rs_data.type);
+ if (ret) {
+ pr_err("Failed to read type\n");
+ goto fail;
+ }
+
+ key = "qcom,id";
+ ret = of_property_read_u32(node, key, &rs->rs_data.id);
+ if (ret) {
+ pr_err("Failed to read id\n");
+ goto fail;
+ }
+
+ key = "qcom,key";
+ ret = of_property_read_u32(node, key, &rs->rs_data.key);
+ if (ret) {
+ pr_err("Failed to read key\n");
+ goto fail;
+ }
+
+ rs->rs_data.handle = msm_lpm_create_rpm_request(
+ rs->rs_data.type,
+ rs->rs_data.id);
+
+ if (!rs->rs_data.handle) {
+ pr_err("%s: Failed to allocate handle for %s\n",
+ __func__, rs->name);
+ ret = -1;
+ goto fail;
+ }
+ /* fall through */
+
+ case MSM_LPM_LOCAL_RS_TYPE:
+ rs->valid = true;
+ break;
+ default:
+ pr_err("%s: Invalid resource type %d", __func__,
+ resource_type);
goto fail;
}
-
- key = "qcom,key";
- ret = of_property_read_u32(node, key, &rs->rs_data.key);
- if (ret) {
- pr_err("Failed to read key\n");
- goto fail;
- }
-
- rs->rs_data.handle = msm_lpm_create_rpm_request(
- rs->rs_data.type, rs->rs_data.id);
-
- if (!rs->rs_data.handle) {
- pr_err("%s: Failed to allocate handle for %s\n",
- __func__, rs->name);
- ret = -1;
- goto fail;
- }
-
- rs->valid = true;
}
msm_rpm_register_notifier(&msm_lpm_rpm_nblk);
msm_lpm_init_rpm_ctl();
- register_hotcpu_notifier(&msm_lpm_cpu_nblk);
- /* For UP mode, set the default to HSFS OPEN*/
- if (num_possible_cpus() == 1) {
- msm_lpm_l2.rs_data.default_value = MSM_LPM_L2_CACHE_HSFS_OPEN;
- msm_lpm_l2.rs_data.value = MSM_LPM_L2_CACHE_HSFS_OPEN;
- }
- msm_pm_set_l2_flush_flag(0);
- return 0;
+
+ if (msm_lpm_l2.valid) {
+ register_hotcpu_notifier(&msm_lpm_cpu_nblk);
+ /* For UP mode, set the default to HSFS OPEN*/
+ if (num_possible_cpus() == 1) {
+ msm_lpm_l2.rs_data.default_value =
+ MSM_LPM_L2_CACHE_HSFS_OPEN;
+ msm_lpm_l2.rs_data.value = MSM_LPM_L2_CACHE_HSFS_OPEN;
+ }
+ msm_pm_set_l2_flush_flag(0);
+ } else
+ msm_pm_set_l2_flush_flag(1);
+
fail:
return ret;
}
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
deleted file mode 100644
index 83b3bc4..0000000
--- a/arch/arm/mach-msm/modem-8960.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * 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/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/debugfs.h>
-
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-#include <mach/socinfo.h>
-#include <mach/msm_smsm.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-static int crash_shutdown;
-
-static struct subsys_device *modem_8960_dev;
-
-#define MAX_SSR_REASON_LEN 81U
-
-static void log_modem_sfr(void)
-{
- u32 size;
- char *smem_reason, reason[MAX_SSR_REASON_LEN];
-
- smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
- if (!smem_reason || !size) {
- pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
- return;
- }
- if (!smem_reason[0]) {
- pr_err("modem subsystem failure reason: (unknown, init string found).\n");
- return;
- }
-
- size = min(size, MAX_SSR_REASON_LEN-1);
- memcpy(reason, smem_reason, size);
- reason[size] = '\0';
- pr_err("modem subsystem failure reason: %s.\n", reason);
-
- smem_reason[0] = '\0';
- wmb();
-}
-
-static void restart_modem(void)
-{
- log_modem_sfr();
- subsystem_restart_dev(modem_8960_dev);
-}
-
-static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
-{
- /* Ignore if we're the one that set SMSM_RESET */
- if (crash_shutdown)
- return;
-
- if (new_state & SMSM_RESET) {
- pr_err("Probable fatal error on the modem.\n");
- restart_modem();
- }
-}
-
-#define Q6_FW_WDOG_ENABLE 0x08882024
-#define Q6_SW_WDOG_ENABLE 0x08982024
-
-static int modem_shutdown(const struct subsys_desc *subsys)
-{
- void __iomem *q6_fw_wdog_addr;
- void __iomem *q6_sw_wdog_addr;
-
- /*
- * Disable the modem watchdog since it keeps running even after the
- * modem is shutdown.
- */
- q6_fw_wdog_addr = ioremap_nocache(Q6_FW_WDOG_ENABLE, 4);
- if (!q6_fw_wdog_addr)
- return -ENOMEM;
-
- q6_sw_wdog_addr = ioremap_nocache(Q6_SW_WDOG_ENABLE, 4);
- if (!q6_sw_wdog_addr) {
- iounmap(q6_fw_wdog_addr);
- return -ENOMEM;
- }
-
- writel_relaxed(0x0, q6_fw_wdog_addr);
- writel_relaxed(0x0, q6_sw_wdog_addr);
- mb();
- iounmap(q6_sw_wdog_addr);
- iounmap(q6_fw_wdog_addr);
-
- pil_force_shutdown("modem");
- pil_force_shutdown("modem_fw");
- disable_irq_nosync(Q6FW_WDOG_EXPIRED_IRQ);
- disable_irq_nosync(Q6SW_WDOG_EXPIRED_IRQ);
-
- return 0;
-}
-
-#define MODEM_WDOG_CHECK_TIMEOUT_MS 10000
-
-static int modem_powerup(const struct subsys_desc *subsys)
-{
- pil_force_boot("modem_fw");
- pil_force_boot("modem");
- enable_irq(Q6FW_WDOG_EXPIRED_IRQ);
- enable_irq(Q6SW_WDOG_EXPIRED_IRQ);
- return 0;
-}
-
-void modem_crash_shutdown(const struct subsys_desc *subsys)
-{
- crash_shutdown = 1;
- smsm_reset_modem(SMSM_RESET);
-}
-
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment modemsw_segments[] = {
- {0x89000000, 0x8D400000 - 0x89000000},
-};
-
-static struct ramdump_segment modemfw_segments[] = {
- {0x8D400000, 0x8DA00000 - 0x8D400000},
-};
-
-static struct ramdump_segment smem_segments[] = {
- {0x80000000, 0x00200000},
-};
-
-static void *modemfw_ramdump_dev;
-static void *modemsw_ramdump_dev;
-static void *smem_ramdump_dev;
-
-static int modem_ramdump(int enable, const struct subsys_desc *crashed_subsys)
-{
- int ret = 0;
-
- if (enable) {
- ret = do_ramdump(modemsw_ramdump_dev, modemsw_segments,
- ARRAY_SIZE(modemsw_segments));
-
- if (ret < 0) {
- pr_err("Unable to dump modem sw memory (rc = %d).\n",
- ret);
- goto out;
- }
-
- ret = do_ramdump(modemfw_ramdump_dev, modemfw_segments,
- ARRAY_SIZE(modemfw_segments));
-
- if (ret < 0) {
- pr_err("Unable to dump modem fw memory (rc = %d).\n",
- ret);
- goto out;
- }
-
- ret = do_ramdump(smem_ramdump_dev, smem_segments,
- ARRAY_SIZE(smem_segments));
-
- if (ret < 0) {
- pr_err("Unable to dump smem memory (rc = %d).\n", ret);
- goto out;
- }
- }
-
-out:
- return ret;
-}
-
-static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
-{
- switch (irq) {
-
- case Q6SW_WDOG_EXPIRED_IRQ:
- pr_err("Watchdog bite received from modem software!\n");
- restart_modem();
- break;
- case Q6FW_WDOG_EXPIRED_IRQ:
- pr_err("Watchdog bite received from modem firmware!\n");
- restart_modem();
- break;
- break;
-
- default:
- pr_err("%s: Unknown IRQ!\n", __func__);
- }
-
- return IRQ_HANDLED;
-}
-
-static struct subsys_desc modem_8960 = {
- .name = "modem",
- .shutdown = modem_shutdown,
- .powerup = modem_powerup,
- .ramdump = modem_ramdump,
- .crash_shutdown = modem_crash_shutdown
-};
-
-static int modem_subsystem_restart_init(void)
-{
- modem_8960_dev = subsys_register(&modem_8960);
- if (IS_ERR(modem_8960_dev))
- return PTR_ERR(modem_8960_dev);
- return 0;
-}
-
-static int modem_debug_set(void *data, u64 val)
-{
- if (val == 1)
- subsystem_restart_dev(modem_8960_dev);
-
- return 0;
-}
-
-static int modem_debug_get(void *data, u64 *val)
-{
- *val = 0;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(modem_debug_fops, modem_debug_get, modem_debug_set,
- "%llu\n");
-
-static int modem_debugfs_init(void)
-{
- struct dentry *dent;
- dent = debugfs_create_dir("modem_debug", 0);
-
- if (IS_ERR(dent))
- return PTR_ERR(dent);
-
- debugfs_create_file("reset_modem", 0644, dent, NULL,
- &modem_debug_fops);
- return 0;
-}
-
-static int __init modem_8960_init(void)
-{
- int ret;
-
- if (cpu_is_apq8064() || cpu_is_apq8064ab())
- return -ENODEV;
-
- ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
- smsm_state_cb, 0);
-
- if (ret < 0)
- pr_err("%s: Unable to register SMSM callback! (%d)\n",
- __func__, ret);
-
- ret = request_irq(Q6FW_WDOG_EXPIRED_IRQ, modem_wdog_bite_irq,
- IRQF_TRIGGER_RISING, "modem_wdog_fw", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to request q6fw watchdog IRQ. (%d)\n",
- __func__, ret);
- goto out;
- }
-
- ret = request_irq(Q6SW_WDOG_EXPIRED_IRQ, modem_wdog_bite_irq,
- IRQF_TRIGGER_RISING, "modem_wdog_sw", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to request q6sw watchdog IRQ. (%d)\n",
- __func__, ret);
- disable_irq_nosync(Q6FW_WDOG_EXPIRED_IRQ);
- goto out;
- }
-
- ret = modem_subsystem_restart_init();
-
- if (ret < 0) {
- pr_err("%s: Unable to reg with subsystem restart. (%d)\n",
- __func__, ret);
- goto out;
- }
-
- modemfw_ramdump_dev = create_ramdump_device("modem_fw");
-
- if (!modemfw_ramdump_dev) {
- pr_err("%s: Unable to create modem fw ramdump device. (%d)\n",
- __func__, -ENOMEM);
- ret = -ENOMEM;
- goto out;
- }
-
- modemsw_ramdump_dev = create_ramdump_device("modem_sw");
-
- if (!modemsw_ramdump_dev) {
- pr_err("%s: Unable to create modem sw ramdump device. (%d)\n",
- __func__, -ENOMEM);
- ret = -ENOMEM;
- goto out;
- }
-
- smem_ramdump_dev = create_ramdump_device("smem-modem");
-
- if (!smem_ramdump_dev) {
- pr_err("%s: Unable to create smem ramdump device. (%d)\n",
- __func__, -ENOMEM);
- ret = -ENOMEM;
- goto out;
- }
-
- ret = modem_debugfs_init();
-
- pr_info("%s: modem fatal driver init'ed.\n", __func__);
-out:
- return ret;
-}
-
-module_init(modem_8960_init);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
index 2072cb1..97299a0 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
@@ -485,7 +485,7 @@
};
#define M_PRIOLVL_OVERRIDE_ADDR(b, n) \
- (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000220)
+ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000230)
enum bimc_m_priolvl_override {
M_PRIOLVL_OVERRIDE_RMSK = 0x301,
M_PRIOLVL_OVERRIDE_BMSK = 0x300,
@@ -495,10 +495,10 @@
};
#define M_RD_CMD_OVERRIDE_ADDR(b, n) \
- (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000230)
+ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000240)
enum bimc_m_read_command_override {
- M_RD_CMD_OVERRIDE_RMSK = 0x37f3f,
- M_RD_CMD_OVERRIDE_AREQPRIO_BMSK = 0x300000,
+ M_RD_CMD_OVERRIDE_RMSK = 0x3071f7f,
+ M_RD_CMD_OVERRIDE_AREQPRIO_BMSK = 0x3000000,
M_RD_CMD_OVERRIDE_AREQPRIO_SHFT = 0x18,
M_RD_CMD_OVERRIDE_AMEMTYPE_BMSK = 0x70000,
M_RD_CMD_OVERRIDE_AMEMTYPE_SHFT = 0x10,
@@ -529,13 +529,15 @@
};
#define M_WR_CMD_OVERRIDE_ADDR(b, n) \
- (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000240)
+ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000250)
enum bimc_m_write_command_override {
- M_WR_CMD_OVERRIDE_RMSK = 0x37f3f,
- M_WR_CMD_OVERRIDE_AREQPRIO_BMSK = 0x30000,
- M_WR_CMD_OVERRIDE_AREQPRIO_SHFT = 0x10,
- M_WR_CMD_OVERRIDE_AMEMTYPE_BMSK = 0x7000,
- M_WR_CMD_OVERRIDE_AMEMTYPE_SHFT = 0xc,
+ M_WR_CMD_OVERRIDE_RMSK = 0x3071f7f,
+ M_WR_CMD_OVERRIDE_AREQPRIO_BMSK = 0x3000000,
+ M_WR_CMD_OVERRIDE_AREQPRIO_SHFT = 0x18,
+ M_WR_CMD_OVERRIDE_AMEMTYPE_BMSK = 0x70000,
+ M_WR_CMD_OVERRIDE_AMEMTYPE_SHFT = 0x10,
+ M_WR_CMD_OVERRIDE_ATRANSIENT_BMSK = 0x1000,
+ M_WR_CMD_OVERRIDE_ATRANSIENT_SHFT = 0xc,
M_WR_CMD_OVERRIDE_ASHARED_BMSK = 0x800,
M_WR_CMD_OVERRIDE_ASHARED_SHFT = 0xb,
M_WR_CMD_OVERRIDE_AREDIRECT_BMSK = 0x400,
@@ -544,8 +546,10 @@
M_WR_CMD_OVERRIDE_AOOO_SHFT = 0x9,
M_WR_CMD_OVERRIDE_AINNERSHARED_BMSK = 0x100,
M_WR_CMD_OVERRIDE_AINNERSHARED_SHFT = 0x8,
- M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK = 0x20,
- M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT = 0x5,
+ M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK = 0x40,
+ M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT = 0x6,
+ M_WR_CMD_OVERRIDE_OVERRIDE_ATRANSIENT_BMSK = 0x20,
+ M_WR_CMD_OVERRIDE_OVERRIDE_ATRANSIENT_SHFT = 0x5,
M_WR_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_BMSK = 0x10,
M_WR_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_SHFT = 0x4,
M_WR_CMD_OVERRIDE_OVERRIDE_ASHARED_BMSK = 0x8,
@@ -1454,7 +1458,7 @@
* boundary in future
*/
wmb();
- set_qos_mode(binfo->base, mas_index, 1, 1, 1);
+ set_qos_mode(binfo->base, mas_index, 0, 1, 1);
break;
case BIMC_QOS_MODE_BYPASS:
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c
index 1b8c07e..cfd84eb 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c
@@ -641,6 +641,7 @@
.mode = NOC_QOS_MODE_FIXED,
.qport = qports_crypto_c0,
.mas_hw_id = MAS_CRYPTO_CORE0,
+ .hw_sel = MSM_BUS_NOC,
},
{
.id = MSM_BUS_MASTER_CRYPTO_CORE1,
@@ -651,6 +652,7 @@
.mode = NOC_QOS_MODE_FIXED,
.qport = qports_crypto_c1,
.mas_hw_id = MAS_CRYPTO_CORE1,
+ .hw_sel = MSM_BUS_NOC,
},
{
.id = MSM_BUS_MASTER_LPASS_PROC,
@@ -719,6 +721,7 @@
.mas_hw_id = MAS_USB3,
.prio_rd = 2,
.prio_wr = 2,
+ .hw_sel = MSM_BUS_NOC,
},
{
.id = MSM_BUS_SLAVE_AMPSS,
@@ -1046,9 +1049,8 @@
.qport = qports_kmpss,
.ws = 10000,
.mas_hw_id = MAS_APPSS_PROC,
- .prio_lvl = 0,
- .prio_rd = 2,
- .prio_wr = 2,
+ .prio_rd = 1,
+ .prio_wr = 1,
},
{
.id = MSM_BUS_MASTER_AMPSS_M1,
@@ -1061,6 +1063,8 @@
.qport = qports_kmpss,
.ws = 10000,
.mas_hw_id = MAS_APPSS_PROC,
+ .prio_rd = 1,
+ .prio_wr = 1,
},
{
.id = MSM_BUS_MASTER_MSS_PROC,
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index 1c5377f..310197e 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -696,6 +696,26 @@
return ret;
}
+static int get_core_offset(enum msm_dcvs_core_type type, int num)
+{
+ int offset = -EINVAL;
+
+ switch (type) {
+ case MSM_DCVS_CORE_TYPE_CPU:
+ offset = CPU_OFFSET + num;
+ BUG_ON(offset >= GPU_OFFSET);
+ break;
+ case MSM_DCVS_CORE_TYPE_GPU:
+ offset = GPU_OFFSET + num;
+ BUG_ON(offset >= CORES_MAX);
+ break;
+ default:
+ BUG();
+ }
+
+ return offset;
+}
+
/* Return the core and initialize non platform data specific numbers in it */
static struct dcvs_core *msm_dcvs_add_core(enum msm_dcvs_core_type type,
int num)
@@ -704,20 +724,14 @@
int i;
char name[CORE_NAME_MAX];
- switch (type) {
- case MSM_DCVS_CORE_TYPE_CPU:
- i = CPU_OFFSET + num;
- BUG_ON(i >= GPU_OFFSET);
- snprintf(name, CORE_NAME_MAX, "cpu%d", num);
- break;
- case MSM_DCVS_CORE_TYPE_GPU:
- i = GPU_OFFSET + num;
- BUG_ON(i >= CORES_MAX);
- snprintf(name, CORE_NAME_MAX, "gpu%d", num);
- break;
- default:
+ i = get_core_offset(type, num);
+ if (i < 0)
return NULL;
- }
+
+ if (type == MSM_DCVS_CORE_TYPE_CPU)
+ snprintf(name, CORE_NAME_MAX, "cpu%d", num);
+ else
+ snprintf(name, CORE_NAME_MAX, "gpu%d", num);
core = &core_list[i];
core->dcvs_core_id = i;
@@ -750,10 +764,17 @@
int sensor)
{
int ret = -EINVAL;
+ int offset;
struct dcvs_core *core = NULL;
uint32_t ret1;
uint32_t ret2;
+ offset = get_core_offset(type, type_core_num);
+ if (offset < 0)
+ return ret;
+ if (core_list[offset].dcvs_core_id != -1)
+ return core_list[offset].dcvs_core_id;
+
core = msm_dcvs_add_core(type, type_core_num);
if (!core)
return ret;
diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c
index 184ec61..9f6cc11 100644
--- a/arch/arm/mach-msm/msm_mpdecision.c
+++ b/arch/arm/mach-msm/msm_mpdecision.c
@@ -201,9 +201,6 @@
time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms;
if (time_taken_ms > hp_latencies.hp_up_max_ms)
hp_latencies.hp_up_max_ms = time_taken_ms;
- if (time_taken_ms > 5)
- pr_warn("cpu_up for cpu%d exceeded 5ms (%d)\n",
- cpu, time_taken_ms);
hp_latencies.hp_up_ms += time_taken_ms;
hp_latencies.hp_up_count++;
ret = msm_dcvs_scm_event(
@@ -232,9 +229,6 @@
time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms;
if (time_taken_ms > hp_latencies.hp_dw_max_ms)
hp_latencies.hp_dw_max_ms = time_taken_ms;
- if (time_taken_ms > 5)
- pr_warn("cpu_down for cpu%d exceeded 5ms (%d)\n",
- cpu, time_taken_ms);
hp_latencies.hp_dw_ms += time_taken_ms;
hp_latencies.hp_dw_count++;
ret = msm_dcvs_scm_event(
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index 65b56d3..61b5536 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -18,9 +18,15 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/interrupt.h>
#include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/msm_smsm.h>
+#include <mach/peripheral-loader.h>
+#include "smd_private.h"
+#include "ramdump.h"
#include "peripheral-loader.h"
#include "pil-q6v4.h"
#include "scm-pas.h"
@@ -35,6 +41,13 @@
struct q6v4_data q6_fw;
struct q6v4_data q6_sw;
void __iomem *modem_base;
+ void *fw_ramdump_dev;
+ void *sw_ramdump_dev;
+ void *smem_ramdump_dev;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ int crash_shutdown;
+ int loadable;
};
static DEFINE_MUTEX(pil_q6v4_modem_lock);
@@ -124,6 +137,138 @@
.proxy_unvote = pil_q6v4_remove_proxy_votes,
};
+static void log_modem_sfr(void)
+{
+ u32 size;
+ char *smem_reason, reason[81];
+
+ smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+ if (!smem_reason || !size) {
+ pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
+ return;
+ }
+ if (!smem_reason[0]) {
+ pr_err("modem subsystem failure reason: (unknown, init string found).\n");
+ return;
+ }
+
+ size = min(size, sizeof(reason)-1);
+ memcpy(reason, smem_reason, size);
+ reason[size] = '\0';
+ pr_err("modem subsystem failure reason: %s.\n", reason);
+
+ smem_reason[0] = '\0';
+ wmb();
+}
+
+static void restart_modem(struct q6v4_modem *drv)
+{
+ log_modem_sfr();
+ subsystem_restart_dev(drv->subsys);
+}
+
+#define desc_to_modem(d) container_of(d, struct q6v4_modem, subsys_desc)
+
+static int modem_shutdown(const struct subsys_desc *subsys)
+{
+ struct q6v4_modem *drv = desc_to_modem(subsys);
+
+ /* The watchdogs keep running even after the modem is shutdown */
+ writel_relaxed(0x0, drv->q6_fw.wdog_base + 0x24);
+ writel_relaxed(0x0, drv->q6_sw.wdog_base + 0x24);
+ mb();
+
+ if (drv->loadable) {
+ pil_force_shutdown("modem");
+ pil_force_shutdown("modem_fw");
+ }
+
+ disable_irq_nosync(drv->q6_fw.wdog_irq);
+ disable_irq_nosync(drv->q6_sw.wdog_irq);
+
+ return 0;
+}
+
+static int modem_powerup(const struct subsys_desc *subsys)
+{
+ struct q6v4_modem *drv = desc_to_modem(subsys);
+
+ if (drv->loadable) {
+ pil_force_boot("modem_fw");
+ pil_force_boot("modem");
+ }
+ enable_irq(drv->q6_fw.wdog_irq);
+ enable_irq(drv->q6_sw.wdog_irq);
+ return 0;
+}
+
+void modem_crash_shutdown(const struct subsys_desc *subsys)
+{
+ struct q6v4_modem *drv = desc_to_modem(subsys);
+
+ drv->crash_shutdown = 1;
+ smsm_reset_modem(SMSM_RESET);
+}
+
+static struct ramdump_segment sw_segments[] = {
+ {0x89000000, 0x8D400000 - 0x89000000},
+};
+
+static struct ramdump_segment fw_segments[] = {
+ {0x8D400000, 0x8DA00000 - 0x8D400000},
+};
+
+static struct ramdump_segment smem_segments[] = {
+ {0x80000000, 0x00200000},
+};
+
+static int modem_ramdump(int enable, const struct subsys_desc *subsys)
+{
+ struct q6v4_modem *drv = desc_to_modem(subsys);
+ int ret;
+
+ if (!enable)
+ return 0;
+
+ ret = do_ramdump(drv->sw_ramdump_dev, sw_segments,
+ ARRAY_SIZE(sw_segments));
+ if (ret < 0)
+ return ret;
+
+ ret = do_ramdump(drv->fw_ramdump_dev, fw_segments,
+ ARRAY_SIZE(fw_segments));
+ if (ret < 0)
+ return ret;
+
+ ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
+ ARRAY_SIZE(smem_segments));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+{
+ struct q6v4_modem *drv = data;
+
+ /* Ignore if we're the one that set SMSM_RESET */
+ if (drv->crash_shutdown)
+ return;
+
+ if (new_state & SMSM_RESET) {
+ pr_err("Probable fatal error on the modem.\n");
+ restart_modem(drv);
+ }
+}
+
+static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
+{
+ struct q6v4_modem *drv = dev_id;
+ restart_modem(drv);
+ return IRQ_HANDLED;
+}
+
static int __devinit
pil_q6v4_proc_init(struct q6v4_data *drv, struct platform_device *pdev, int i)
{
@@ -134,7 +279,7 @@
struct pil_desc *desc;
struct resource *res;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + (i * 2));
if (!res)
return -EINVAL;
@@ -142,6 +287,15 @@
if (!drv->base)
return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2 + (i * 2));
+ if (!res)
+ return -EINVAL;
+
+ drv->wdog_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->wdog_base)
+ return -ENOMEM;
+
snprintf(reg_name, sizeof(reg_name), "%s_core_vdd", name[i]);
drv->vreg = devm_regulator_get(&pdev->dev, reg_name);
if (IS_ERR(drv->vreg))
@@ -176,6 +330,7 @@
struct resource *res;
struct regulator *pll_supply;
int ret;
+ const struct pil_q6v4_pdata *pdata = pdev->dev.platform_data;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@@ -185,57 +340,139 @@
drv_fw = &drv->q6_fw;
drv_sw = &drv->q6_sw;
- ret = pil_q6v4_proc_init(drv_fw, pdev, 0);
+ drv_fw->wdog_irq = platform_get_irq(pdev, 0);
+ if (drv_fw->wdog_irq < 0)
+ return drv_fw->wdog_irq;
+
+ drv_sw->wdog_irq = platform_get_irq(pdev, 1);
+ if (drv_sw->wdog_irq < 0)
+ return drv_sw->wdog_irq;
+
+ drv->loadable = !!pdata; /* No pdata = don't use PIL */
+ if (drv->loadable) {
+ ret = pil_q6v4_proc_init(drv_fw, pdev, 0);
+ if (ret)
+ return ret;
+
+ ret = pil_q6v4_proc_init(drv_sw, pdev, 1);
+ if (ret)
+ return ret;
+
+ pll_supply = devm_regulator_get(&pdev->dev, "pll_vdd");
+ drv_fw->pll_supply = drv_sw->pll_supply = pll_supply;
+ if (IS_ERR(pll_supply))
+ return PTR_ERR(pll_supply);
+
+ ret = regulator_set_voltage(pll_supply, 1800000, 1800000);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to set pll voltage\n");
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(pll_supply, 100000);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to set pll optimum mode\n");
+ return ret;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ drv->modem_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->modem_base)
+ return -ENOMEM;
+
+ drv_fw->pil = msm_pil_register(&drv_fw->desc);
+ if (IS_ERR(drv_fw->pil))
+ return PTR_ERR(drv_fw->pil);
+
+ drv_sw->pil = msm_pil_register(&drv_sw->desc);
+ if (IS_ERR(drv_sw->pil)) {
+ ret = PTR_ERR(drv_sw->pil);
+ goto err_pil_sw;
+ }
+ }
+
+ drv->subsys_desc.name = "modem";
+ drv->subsys_desc.shutdown = modem_shutdown;
+ drv->subsys_desc.powerup = modem_powerup;
+ drv->subsys_desc.ramdump = modem_ramdump;
+ drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
+
+ drv->fw_ramdump_dev = create_ramdump_device("modem_fw");
+ if (!drv->fw_ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_fw_ramdump;
+ }
+
+ drv->sw_ramdump_dev = create_ramdump_device("modem_sw");
+ if (!drv->sw_ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_sw_ramdump;
+ }
+
+ drv->smem_ramdump_dev = create_ramdump_device("smem-modem");
+ if (!drv->smem_ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_smem_ramdump;
+ }
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv_fw->wdog_irq,
+ modem_wdog_bite_irq, IRQF_TRIGGER_RISING,
+ dev_name(&pdev->dev), drv);
if (ret)
- return ret;
+ goto err_irq;
- ret = pil_q6v4_proc_init(drv_sw, pdev, 1);
+ ret = devm_request_irq(&pdev->dev, drv_sw->wdog_irq,
+ modem_wdog_bite_irq, IRQF_TRIGGER_RISING,
+ dev_name(&pdev->dev), drv);
if (ret)
- return ret;
+ goto err_irq;
- pll_supply = devm_regulator_get(&pdev->dev, "pll_vdd");
- drv_fw->pll_supply = drv_sw->pll_supply = pll_supply;
- if (IS_ERR(pll_supply))
- return PTR_ERR(pll_supply);
-
- ret = regulator_set_voltage(pll_supply, 1800000, 1800000);
- if (ret) {
- dev_err(&pdev->dev, "failed to set pll voltage\n");
- return ret;
- }
-
- ret = regulator_set_optimum_mode(pll_supply, 100000);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to set pll optimum mode\n");
- return ret;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
- drv->modem_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!drv->modem_base)
- return -ENOMEM;
-
- drv_fw->pil = msm_pil_register(&drv_fw->desc);
- if (IS_ERR(drv_fw->pil))
- return PTR_ERR(drv_fw->pil);
-
- drv_sw->pil = msm_pil_register(&drv_sw->desc);
- if (IS_ERR(drv_sw->pil)) {
- msm_pil_unregister(drv_fw->pil);
- return PTR_ERR(drv_sw->pil);
- }
+ ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
+ smsm_state_cb, drv);
+ if (ret)
+ goto err_irq;
return 0;
+
+err_irq:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ destroy_ramdump_device(drv->smem_ramdump_dev);
+err_smem_ramdump:
+ destroy_ramdump_device(drv->sw_ramdump_dev);
+err_sw_ramdump:
+ destroy_ramdump_device(drv->fw_ramdump_dev);
+err_fw_ramdump:
+ if (drv->loadable)
+ msm_pil_unregister(drv_sw->pil);
+err_pil_sw:
+ msm_pil_unregister(drv_fw->pil);
+ return ret;
}
static int __devexit pil_q6v4_modem_driver_exit(struct platform_device *pdev)
{
struct q6v4_modem *drv = platform_get_drvdata(pdev);
- msm_pil_unregister(drv->q6_sw.pil);
- msm_pil_unregister(drv->q6_fw.pil);
+
+ smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
+ smsm_state_cb, drv);
+ subsys_unregister(drv->subsys);
+ destroy_ramdump_device(drv->smem_ramdump_dev);
+ destroy_ramdump_device(drv->sw_ramdump_dev);
+ destroy_ramdump_device(drv->fw_ramdump_dev);
+ if (drv->loadable) {
+ msm_pil_unregister(drv->q6_sw.pil);
+ msm_pil_unregister(drv->q6_fw.pil);
+ }
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v4.h b/arch/arm/mach-msm/pil-q6v4.h
index d280d84..0395bed 100644
--- a/arch/arm/mach-msm/pil-q6v4.h
+++ b/arch/arm/mach-msm/pil-q6v4.h
@@ -35,6 +35,7 @@
*/
struct q6v4_data {
void __iomem *base;
+ void __iomem *wdog_base;
unsigned long start_addr;
unsigned long strap_tcm_base;
unsigned long strap_ahb_upper;
@@ -43,6 +44,7 @@
void __iomem *jtag_clk_reg;
unsigned pas_id;
int bus_port;
+ int wdog_irq;
struct regulator *vreg;
struct regulator *pll_supply;
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 7b45a0e..9ff1234 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -79,7 +79,6 @@
static int pil_mss_enable_clks(struct q6v5_data *drv)
{
int ret;
- void __iomem *mpll1_config_ctl;
ret = clk_prepare_enable(drv->ahb_clk);
if (ret)
@@ -91,12 +90,6 @@
if (ret)
goto err_rom_clk;
- /* TODO: Remove when support for 8974v1.0 HW is dropped. */
- mpll1_config_ctl = ioremap(0xFC981034, 0x4);
- writel_relaxed(0x0300403D, mpll1_config_ctl);
- mb();
- iounmap(mpll1_config_ctl);
-
return 0;
err_rom_clk:
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index ed15a0c..7bc4fe0 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -211,7 +211,10 @@
char *key = NULL;
uint32_t val = 0;
int ret = 0;
- int flag = 0;
+ uint32_t vaddr_val;
+
+ pdata.p_addr = 0;
+ vaddr_val = 0;
key = "qcom,mode";
ret = of_property_read_u32(pdev->dev.of_node, key, &val);
@@ -223,24 +226,43 @@
key = "qcom,phy-addr";
ret = of_property_read_u32(pdev->dev.of_node, key, &val);
- if (ret && pdata.mode == MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS)
- goto fail;
- if (!ret) {
+ if (!ret)
pdata.p_addr = val;
- flag++;
- }
+
key = "qcom,virt-addr";
- ret = of_property_read_u32(pdev->dev.of_node, key, &val);
- if (ret && pdata.mode == MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT)
- goto fail;
- if (!ret) {
- pdata.v_addr = (void *)val;
- flag++;
- }
+ ret = of_property_read_u32(pdev->dev.of_node, key, &vaddr_val);
- if (pdata.mode == MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR && (flag != 2)) {
- key = "addresses for boot remap";
+ switch (pdata.mode) {
+ case MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS:
+ if (!pdata.p_addr) {
+ key = "qcom,phy-addr";
+ goto fail;
+ }
+ break;
+ case MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT:
+ if (!vaddr_val)
+ goto fail;
+
+ pdata.v_addr = (void *)vaddr_val;
+ break;
+ case MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR:
+ if (!vaddr_val)
+ goto fail;
+
+ pdata.v_addr = ioremap_nocache(vaddr_val, SZ_8);
+
+ pdata.p_addr = allocate_contiguous_ebi_nomap(SZ_8, SZ_64K);
+ if (!pdata.p_addr) {
+ key = "qcom,phy-addr";
+ goto fail;
+ }
+ break;
+ case MSM_PM_BOOT_CONFIG_TZ:
+ break;
+ default:
+ pr_err("%s: Unsupported boot mode %d",
+ __func__, pdata.mode);
goto fail;
}
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_a2dp_in.c b/arch/arm/mach-msm/qdsp5v2/audio_a2dp_in.c
index 733b7a1..e396186 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_a2dp_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_a2dp_in.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2008 HTC Corporation
* Copyright (C) 2008 Google, Inc.
+ * Copyright (c) 2012 The Linux Foundation. All rights reserved.
*
* All source code in this file is licensed under the following license except
* where indicated.
@@ -34,7 +35,7 @@
#include <linux/dma-mapping.h>
#include <linux/msm_audio.h>
#include <linux/msm_audio_sbc.h>
-#include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
#include <linux/memory_alloc.h>
#include <mach/iommu.h>
@@ -115,6 +116,8 @@
int stopped; /* set when stopped, cleared on flush */
int abort; /* set when error, like sample rate mismatch */
char *build_id;
+ struct ion_client *client;
+ struct ion_handle *output_buff_handle;
};
static struct audio_a2dp_in the_audio_a2dp_in;
@@ -848,10 +851,11 @@
audio->audrec = NULL;
audio->opened = 0;
if (audio->data) {
- iounmap(audio->msm_map);
- free_contiguous_memory_by_paddr(audio->phys);
+ ion_unmap_kernel(audio->client, audio->output_buff_handle);
+ ion_free(audio->client, audio->output_buff_handle);
audio->data = NULL;
}
+ ion_client_destroy(audio->client);
mutex_unlock(&audio->lock);
return 0;
}
@@ -861,6 +865,11 @@
struct audio_a2dp_in *audio = &the_audio_a2dp_in;
int rc;
int encid;
+ int len = 0;
+ unsigned long ionflag = 0;
+ ion_phys_addr_t addr = 0;
+ struct ion_handle *handle = NULL;
+ struct ion_client *client = NULL;
mutex_lock(&audio->lock);
if (audio->opened) {
@@ -868,22 +877,56 @@
goto done;
}
- audio->phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K);
- if (audio->phys) {
- audio->msm_map = ioremap(audio->phys, DMASZ);
- if (IS_ERR(audio->msm_map)) {
- MM_ERR("could not map the phys address to kernel"
- "space\n");
+ client = msm_ion_client_create(UINT_MAX, "Audio_a2dp_in_client");
+ if (IS_ERR_OR_NULL(client)) {
+ MM_ERR("Unable to create ION client\n");
rc = -ENOMEM;
- free_contiguous_memory_by_paddr(audio->phys);
- goto done;
- }
- audio->data = (u8 *)audio->msm_map;
- } else {
- MM_ERR("could not allocate DMA buffers\n");
- rc = -ENOMEM;
- goto done;
+ goto client_create_error;
}
+ audio->client = client;
+
+ MM_DBG("allocating mem sz = %d\n", DMASZ);
+ handle = ion_alloc(client, DMASZ, SZ_4K,
+ ION_HEAP(ION_AUDIO_HEAP_ID), 0);
+ if (IS_ERR_OR_NULL(handle)) {
+ MM_ERR("Unable to create allocate O/P buffers\n");
+ rc = -ENOMEM;
+ goto output_buff_alloc_error;
+ }
+
+ audio->output_buff_handle = handle;
+
+ rc = ion_phys(client , handle, &addr, &len);
+ if (rc) {
+ MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
+ (unsigned int) addr, (unsigned int) len);
+ rc = -ENOMEM;
+ goto output_buff_get_phys_error;
+ } else {
+ MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
+ (unsigned int) addr, (unsigned int) len);
+ }
+ audio->phys = (int32_t)addr;
+
+ rc = ion_handle_get_flags(client, handle, &ionflag);
+ if (rc) {
+ MM_ERR("could not get flags for the handle\n");
+ rc = -ENOMEM;
+ goto output_buff_get_flags_error;
+ }
+
+ audio->msm_map = ion_map_kernel(client, handle);
+ if (IS_ERR(audio->data)) {
+ MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
+ (int)audio);
+ rc = -ENOMEM;
+ goto output_buff_map_error;
+ }
+ MM_DBG("read buf: phy addr 0x%08x kernel addr 0x%08x\n",
+ audio->phys, (int)audio->data);
+
+ audio->data = (char *)audio->msm_map;
+
MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\
(int) audio->data, (int) audio->phys);
@@ -953,6 +996,13 @@
mutex_unlock(&audio->lock);
return rc;
evt_error:
+output_buff_map_error:
+output_buff_get_phys_error:
+output_buff_get_flags_error:
+ ion_free(client, audio->output_buff_handle);
+output_buff_alloc_error:
+ ion_client_destroy(client);
+client_create_error:
msm_adsp_put(audio->audrec);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c b/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
index 60f43b9..7ec0617 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_lpa.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
@@ -27,7 +27,7 @@
#include <linux/delay.h>
#include <linux/earlysuspend.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
#include <asm/atomic.h>
#include <asm/ioctls.h>
#include <mach/msm_adsp.h>
@@ -136,9 +136,9 @@
union msm_audio_event_payload payload;
};
-struct audlpa_pmem_region {
+struct audlpa_ion_region {
struct list_head list;
- struct file *file;
+ struct ion_handle *handle;
int fd;
void *vaddr;
unsigned long paddr;
@@ -170,7 +170,7 @@
static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
static void audlpa_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
-static unsigned long audlpa_pmem_fixup(struct audio *audio, void *addr,
+static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr,
unsigned long len, int ref_up);
static void audlpa_async_send_data(struct audio *audio, unsigned needed,
uint32_t *payload);
@@ -778,7 +778,7 @@
if (drv_evt->event_type == AUDIO_EVENT_WRITE_DONE ||
drv_evt->event_type == AUDIO_EVENT_READ_DONE) {
mutex_lock(&audio->lock);
- audlpa_pmem_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+ audlpa_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
drv_evt->payload.aio_buf.buf_len, 0);
mutex_unlock(&audio->lock);
}
@@ -788,94 +788,118 @@
return rc;
}
-static int audlpa_pmem_check(struct audio *audio,
+static int audlpa_ion_check(struct audio *audio,
void *vaddr, unsigned long len)
{
- struct audlpa_pmem_region *region_elt;
- struct audlpa_pmem_region t = { .vaddr = vaddr, .len = len };
+ struct audlpa_ion_region *region_elt;
+ struct audlpa_ion_region t = {.vaddr = vaddr, .len = len };
- list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
+ list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
OVERLAPS(region_elt, &t)) {
- MM_ERR("region (vaddr %p len %ld)"
+ MM_ERR("[%p]:region (vaddr %p len %ld)"
" clashes with registered region"
" (vaddr %p paddr %p len %ld)\n",
- vaddr, len,
+ audio, vaddr, len,
region_elt->vaddr,
- (void *)region_elt->paddr,
- region_elt->len);
+ (void *)region_elt->paddr, region_elt->len);
return -EINVAL;
}
}
return 0;
}
-
-static int audlpa_pmem_add(struct audio *audio,
- struct msm_audio_pmem_info *info)
+static int audlpa_ion_add(struct audio *audio,
+ struct msm_audio_ion_info *info)
{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct audlpa_pmem_region *region;
+ ion_phys_addr_t paddr;
+ size_t len;
+ unsigned long kvaddr;
+ struct audlpa_ion_region *region;
int rc = -EINVAL;
+ struct ion_handle *handle;
+ unsigned long ionflag;
- MM_DBG("\n"); /* Macro prints the file name and function */
+ MM_ERR("\n"); /* Macro prints the file name and function */
region = kmalloc(sizeof(*region), GFP_KERNEL);
if (!region) {
rc = -ENOMEM;
goto end;
}
-
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- goto end;
+ handle = ion_import_dma_buf(audio->client, info->fd);
+ if (IS_ERR_OR_NULL(handle)) {
+ pr_err("%s: could not get handle of the given fd\n", __func__);
+ goto import_error;
}
-
- rc = audlpa_pmem_check(audio, info->vaddr, len);
+ rc = ion_handle_get_flags(audio->client, handle, &ionflag);
+ if (rc) {
+ pr_err("%s: could not get flags for the handle\n", __func__);
+ goto flag_error;
+ }
+ kvaddr = (unsigned long)ion_map_kernel(audio->client, handle);
+ if (IS_ERR_OR_NULL((void *)kvaddr)) {
+ pr_err("%s: could not get virtual address\n", __func__);
+ goto map_error;
+ }
+ rc = ion_phys(audio->client, handle, &paddr, &len);
+ if (rc) {
+ pr_err("%s: could not get physical address\n", __func__);
+ goto ion_error;
+ }
+ rc = audlpa_ion_check(audio, info->vaddr, len);
if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- goto end;
+ MM_ERR("audpcm_ion_check failed\n");
+ goto ion_error;
}
-
+ region->handle = handle;
region->vaddr = info->vaddr;
region->fd = info->fd;
region->paddr = paddr;
region->kvaddr = kvaddr;
region->len = len;
- region->file = file;
region->ref_cnt = 0;
- MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
- region->vaddr, region->len);
- list_add_tail(®ion->list, &audio->pmem_region_queue);
+ MM_DBG("[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
+ audio, region->paddr, region->vaddr,
+ region->len, region->kvaddr);
+ list_add_tail(®ion->list, &audio->ion_region_queue);
+
+ return rc;
+
+ion_error:
+ ion_unmap_kernel(audio->client, handle);
+map_error:
+flag_error:
+ ion_free(audio->client, handle);
+import_error:
+ kfree(region);
end:
return rc;
}
-static int audlpa_pmem_remove(struct audio *audio,
- struct msm_audio_pmem_info *info)
+static int audlpa_ion_remove(struct audio *audio,
+ struct msm_audio_ion_info *info)
{
- struct audlpa_pmem_region *region;
+ struct audlpa_ion_region *region;
struct list_head *ptr, *next;
int rc = -EINVAL;
- MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
+ list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+ region = list_entry(ptr, struct audlpa_ion_region, list);
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audlpa_pmem_region, list);
-
- if ((region->fd == info->fd) &&
+ if (region != NULL && (region->fd == info->fd) &&
(region->vaddr == info->vaddr)) {
if (region->ref_cnt) {
- MM_DBG("region %p in use ref_cnt %d\n",
- region, region->ref_cnt);
+ MM_DBG("%s[%p]:region %p in use ref_cnt %d\n",
+ __func__, audio, region,
+ region->ref_cnt);
break;
}
MM_DBG("remove region fd %d vaddr %p\n",
info->fd, info->vaddr);
list_del(®ion->list);
- put_pmem_file(region->file);
+ ion_unmap_kernel(audio->client, region->handle);
+ ion_free(audio->client, region->handle);
kfree(region);
rc = 0;
break;
@@ -885,23 +909,20 @@
return rc;
}
-static int audlpa_pmem_lookup_vaddr(struct audio *audio, void *addr,
- unsigned long len, struct audlpa_pmem_region **region)
+static int audlpa_ion_lookup_vaddr(struct audio *audio, void *addr,
+ unsigned long len, struct audlpa_ion_region **region)
{
- struct audlpa_pmem_region *region_elt;
-
+ struct audlpa_ion_region *region_elt;
int match_count = 0;
-
*region = NULL;
/* returns physical address or zero */
- list_for_each_entry(region_elt, &audio->pmem_region_queue,
- list) {
+ list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
if (addr >= region_elt->vaddr &&
addr < region_elt->vaddr + region_elt->len &&
addr + len <= region_elt->vaddr + region_elt->len) {
/* offset since we could pass vaddr inside a registerd
- * pmem buffer
+ * ion buffer
*/
match_count++;
@@ -911,13 +932,16 @@
}
if (match_count > 1) {
- MM_ERR("multiple hits for vaddr %p, len %ld\n", addr, len);
- list_for_each_entry(region_elt,
- &audio->pmem_region_queue, list) {
+ MM_ERR("%s[%p]:multiple hits for vaddr %p, len %ld\n",
+ __func__, audio, addr, len);
+ list_for_each_entry(region_elt, &audio->ion_region_queue,
+ list) {
if (addr >= region_elt->vaddr &&
addr < region_elt->vaddr + region_elt->len &&
addr + len <= region_elt->vaddr + region_elt->len)
- MM_ERR("\t%p, %ld --> %p\n", region_elt->vaddr,
+ MM_ERR("\t%s[%p]:%p, %ld --> %p\n",
+ __func__, audio,
+ region_elt->vaddr,
region_elt->len,
(void *)region_elt->paddr);
}
@@ -925,17 +949,17 @@
return *region ? 0 : -1;
}
-
-unsigned long audlpa_pmem_fixup(struct audio *audio, void *addr,
+static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr,
unsigned long len, int ref_up)
{
- struct audlpa_pmem_region *region;
+ struct audlpa_ion_region *region;
unsigned long paddr;
int ret;
- ret = audlpa_pmem_lookup_vaddr(audio, addr, len, ®ion);
+ ret = audlpa_ion_lookup_vaddr(audio, addr, len, ®ion);
if (ret) {
- MM_ERR("lookup (%p, %ld) failed\n", addr, len);
+ MM_ERR("%s[%p]:lookup (%p, %ld) failed\n",
+ __func__, audio, addr, len);
return 0;
}
if (ref_up)
@@ -969,7 +993,7 @@
buf_node->buf.buf_addr, buf_node->buf.buf_len,
buf_node->buf.data_len);
- buf_node->paddr = audlpa_pmem_fixup(
+ buf_node->paddr = audlpa_ion_fixup(
audio, buf_node->buf.buf_addr,
buf_node->buf.buf_len, 1);
@@ -1269,25 +1293,26 @@
audio->drv_status &= ~ADRV_STATUS_PAUSE;
break;
- case AUDIO_REGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
+ case AUDIO_REGISTER_ION: {
+ struct msm_audio_ion_info info;
+ MM_DBG("AUDIO_REGISTER_ION\n");
+ if (copy_from_user(&info, (void *) arg, sizeof(info)))
rc = -EFAULT;
else
- rc = audlpa_pmem_add(audio, &info);
+ rc = audlpa_ion_add(audio, &info);
break;
}
- case AUDIO_DEREGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_DEREGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
+ case AUDIO_DEREGISTER_ION: {
+ struct msm_audio_ion_info info;
+ MM_DBG("AUDIO_DEREGISTER_ION\n");
+ if (copy_from_user(&info, (void *) arg, sizeof(info)))
rc = -EFAULT;
else
- rc = audlpa_pmem_remove(audio, &info);
+ rc = audlpa_ion_remove(audio, &info);
break;
}
+
case AUDIO_ASYNC_WRITE:
if (audio->drv_status & ADRV_STATUS_FSYNC)
rc = -EBUSY;
@@ -1373,15 +1398,16 @@
return audlpa_async_fsync(audio);
}
-static void audlpa_reset_pmem_region(struct audio *audio)
+static void audpcm_reset_ion_region(struct audio *audio)
{
- struct audlpa_pmem_region *region;
+ struct audlpa_ion_region *region;
struct list_head *ptr, *next;
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audlpa_pmem_region, list);
+ list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+ region = list_entry(ptr, struct audlpa_ion_region, list);
list_del(®ion->list);
- put_pmem_file(region->file);
+ ion_unmap_kernel(audio->client, region->handle);
+ ion_free(audio->client, region->handle);
kfree(region);
}
@@ -1399,7 +1425,7 @@
auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->dec_id);
audio_disable(audio);
audlpa_async_flush(audio);
- audlpa_reset_pmem_region(audio);
+ audpcm_reset_ion_region(audio);
msm_adsp_put(audio->audplay);
audpp_adec_free(audio->dec_id);
@@ -1410,13 +1436,12 @@
audio->event_abort = 1;
wake_up(&audio->event_wait);
audlpa_reset_event_queue(audio);
- iounmap(audio->data);
- free_contiguous_memory_by_paddr(audio->phys);
mutex_unlock(&audio->lock);
#ifdef CONFIG_DEBUG_FS
if (audio->dentry)
debugfs_remove(audio->dentry);
#endif
+ ion_client_destroy(audio->client);
kfree(audio);
return 0;
}
@@ -1589,7 +1614,7 @@
spin_lock_init(&audio->dsp_lock);
init_waitqueue_head(&audio->write_wait);
INIT_LIST_HEAD(&audio->out_queue);
- INIT_LIST_HEAD(&audio->pmem_region_queue);
+ INIT_LIST_HEAD(&audio->ion_region_queue);
INIT_LIST_HEAD(&audio->free_event_queue);
INIT_LIST_HEAD(&audio->event_queue);
init_waitqueue_head(&audio->wait);
@@ -1650,13 +1675,19 @@
break;
}
}
+
+ audio->client = msm_ion_client_create(UINT_MAX, "Audio_LPA_Client");
+ if (IS_ERR_OR_NULL(audio->client)) {
+ pr_err("Unable to create ION client\n");
+ goto err;
+ }
+ MM_DBG("Ion client created\n");
+
done:
return rc;
event_err:
msm_adsp_put(audio->audplay);
err:
- iounmap(audio->data);
- free_contiguous_memory_by_paddr(audio->phys);
audpp_adec_free(audio->dec_id);
MM_INFO("audio instance 0x%08x freeing\n", (int)audio);
kfree(audio);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_out.c b/arch/arm/mach-msm/qdsp5v2/audio_out.c
index 147ac77..e5c59ba 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_out.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-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,7 +43,7 @@
#include <mach/qdsp5v2/audio_dev_ctl.h>
#include <mach/msm_memtypes.h>
#include <mach/cpuidle.h>
-
+#include <linux/msm_ion.h>
#include <mach/htc_pwrsink.h>
#include <mach/debug_mm.h>
@@ -98,6 +98,8 @@
struct pm_qos_request pm_qos_req;
struct audpp_cmd_cfg_object_params_volume vol_pan;
+ struct ion_client *client;
+ struct ion_handle *buff_handle;
};
static void audio_out_listener(u32 evt_id, union auddev_evt_data *evt_payload,
@@ -702,19 +704,53 @@
static int __init audio_init(void)
{
- the_audio.phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K);
- if (the_audio.phys) {
- the_audio.map_v_write = ioremap(the_audio.phys, DMASZ);
- if (IS_ERR(the_audio.map_v_write)) {
- MM_ERR("could not map physical buffers\n");
- free_contiguous_memory_by_paddr(the_audio.phys);
- return -ENOMEM;
- }
- the_audio.data = the_audio.map_v_write;
- } else {
- MM_ERR("could not allocate physical buffers\n");
- return -ENOMEM;
+ unsigned long ionflag = 0;
+ ion_phys_addr_t addr = 0;
+ int rc;
+ int len = 0;
+ struct ion_handle *handle = NULL;
+ struct ion_client *client = NULL;
+
+ client = msm_ion_client_create(UINT_MAX, "HostPCM");
+ if (IS_ERR_OR_NULL(client)) {
+ MM_ERR("Unable to create ION client\n");
+ rc = -ENOMEM;
+ goto client_create_error;
}
+ the_audio.client = client;
+
+ handle = ion_alloc(client, DMASZ, SZ_4K,
+ ION_HEAP(ION_AUDIO_HEAP_ID), 0);
+ if (IS_ERR_OR_NULL(handle)) {
+ MM_ERR("Unable to create allocate O/P buffers\n");
+ rc = -ENOMEM;
+ goto buff_alloc_error;
+ }
+ the_audio.buff_handle = handle;
+
+ rc = ion_phys(client, handle, &addr, &len);
+ if (rc) {
+ MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
+ (unsigned int) addr, (unsigned int) len);
+ goto buff_get_phys_error;
+ } else
+ MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
+ (unsigned int) addr, (unsigned int) len);
+ the_audio.phys = (int32_t)addr;
+
+ rc = ion_handle_get_flags(client, handle, &ionflag);
+ if (rc) {
+ MM_ERR("could not get flags for the handle\n");
+ goto buff_get_flags_error;
+ }
+
+ the_audio.map_v_write = ion_map_kernel(client, handle);
+ if (IS_ERR(the_audio.map_v_write)) {
+ MM_ERR("could not map write buffers\n");
+ rc = -ENOMEM;
+ goto buff_map_error;
+ }
+ the_audio.data = (char *)the_audio.map_v_write;
MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\
(int) the_audio.data, (int) the_audio.phys);
mutex_init(&the_audio.lock);
@@ -725,6 +761,15 @@
pm_qos_add_request(&the_audio.pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
return misc_register(&audio_misc);
+buff_map_error:
+buff_get_phys_error:
+buff_get_flags_error:
+ ion_free(client, the_audio.buff_handle);
+buff_alloc_error:
+ ion_client_destroy(client);
+client_create_error:
+ return rc;
+
}
late_initcall(audio_init);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5v2/audio_pcm_in.c
index ce67ebb..ff3a696 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_pcm_in.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-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
@@ -27,7 +27,7 @@
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
#include <linux/memory_alloc.h>
#include <mach/msm_memtypes.h>
@@ -121,6 +121,8 @@
int abort; /* set when error, like sample rate mismatch */
int dual_mic_config;
char *build_id;
+ struct ion_client *client;
+ struct ion_handle *output_buff_handle;
};
static struct audio_in the_audio_in;
@@ -842,10 +844,11 @@
audio->audrec = NULL;
audio->opened = 0;
if (audio->data) {
- iounmap(audio->map_v_read);
- free_contiguous_memory_by_paddr(audio->phys);
+ ion_unmap_kernel(audio->client, audio->output_buff_handle);
+ ion_free(audio->client, audio->output_buff_handle);
audio->data = NULL;
}
+ ion_client_destroy(audio->client);
mutex_unlock(&audio->lock);
return 0;
}
@@ -855,27 +858,68 @@
struct audio_in *audio = &the_audio_in;
int rc;
int encid;
+ int len = 0;
+ unsigned long ionflag = 0;
+ ion_phys_addr_t addr = 0;
+ struct ion_handle *handle = NULL;
+ struct ion_client *client = NULL;
mutex_lock(&audio->lock);
if (audio->opened) {
rc = -EBUSY;
goto done;
}
- audio->phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K);
- if (audio->phys) {
- audio->map_v_read = ioremap(audio->phys, DMASZ);
- if (IS_ERR(audio->map_v_read)) {
- MM_ERR("could not map read phys buffers\n");
+
+ client = msm_ion_client_create(UINT_MAX, "Audio_PCM_in_client");
+ if (IS_ERR_OR_NULL(client)) {
+ MM_ERR("Unable to create ION client\n");
rc = -ENOMEM;
- free_contiguous_memory_by_paddr(audio->phys);
- goto done;
- }
- audio->data = audio->map_v_read;
- } else {
- MM_ERR("could not allocate read buffers\n");
- rc = -ENOMEM;
- goto done;
+ goto client_create_error;
}
+ audio->client = client;
+
+ MM_DBG("allocating mem sz = %d\n", DMASZ);
+ handle = ion_alloc(client, DMASZ, SZ_4K,
+ ION_HEAP(ION_AUDIO_HEAP_ID), 0);
+ if (IS_ERR_OR_NULL(handle)) {
+ MM_ERR("Unable to create allocate O/P buffers\n");
+ rc = -ENOMEM;
+ goto output_buff_alloc_error;
+ }
+
+ audio->output_buff_handle = handle;
+
+ rc = ion_phys(client , handle, &addr, &len);
+ if (rc) {
+ MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
+ (unsigned int) addr, (unsigned int) len);
+ rc = -ENOMEM;
+ goto output_buff_get_phys_error;
+ } else {
+ MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
+ (unsigned int) addr, (unsigned int) len);
+ }
+ audio->phys = (int32_t)addr;
+
+ rc = ion_handle_get_flags(client, handle, &ionflag);
+ if (rc) {
+ MM_ERR("could not get flags for the handle\n");
+ rc = -ENOMEM;
+ goto output_buff_get_flags_error;
+ }
+
+ audio->map_v_read = ion_map_kernel(client, handle);
+ if (IS_ERR(audio->data)) {
+ MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
+ (int)audio);
+ rc = -ENOMEM;
+ goto output_buff_map_error;
+ }
+ MM_DBG("read buf: phy addr 0x%08x kernel addr 0x%08x\n",
+ audio->phys, (int)audio->data);
+
+ audio->data = (char *)audio->map_v_read;
+
MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\
(int) audio->data, (int) audio->phys);
if ((file->f_mode & FMODE_WRITE) &&
@@ -941,6 +985,13 @@
mutex_unlock(&audio->lock);
return rc;
evt_error:
+output_buff_map_error:
+output_buff_get_phys_error:
+output_buff_get_flags_error:
+ ion_free(client, audio->output_buff_handle);
+output_buff_alloc_error:
+ ion_client_destroy(client);
+client_create_error:
msm_adsp_put(audio->audrec);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
index 5400ccc..dce3812 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
@@ -515,6 +515,9 @@
case FORMAT_USRAW:
int_format = US_RAW_FORMAT;
break;
+ case FORMAT_USPROX:
+ int_format = US_PROX_FORMAT;
+ break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, ext_format);
break;
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h
index 1338e86..1fe71bf 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h
@@ -20,6 +20,7 @@
#define FORMAT_USPS_EPOS 0x00000000
#define FORMAT_USRAW 0x00000001
+#define FORMAT_USPROX 0x00000002
#define INVALID_FORMAT 0xffffffff
#define IN 0x000
diff --git a/arch/arm/mach-msm/rpm_stats.h b/arch/arm/mach-msm/rpm_stats.h
index 918d4fb..a3beaa4 100644
--- a/arch/arm/mach-msm/rpm_stats.h
+++ b/arch/arm/mach-msm/rpm_stats.h
@@ -20,4 +20,19 @@
phys_addr_t phys_addr_base;
u32 phys_size;
};
+
+struct msm_rpm_master_stats_platform_data {
+ phys_addr_t phys_addr_base;
+ u32 phys_size;
+ char **masters;
+ /*
+ * RPM maintains PC stats for each master in MSG RAM,
+ * it allocates 256 bytes for this use.
+ * No of masters differs for different targets.
+ * Based on the number of masters, linux rpm stat
+ * driver reads (32 * nomasters) bytes to display
+ * master stats.
+ */
+ u32 nomasters;
+};
#endif
diff --git a/arch/arm/mach-msm/wdog_debug.c b/arch/arm/mach-msm/wdog_debug.c
index 82800cf..08dd9ce 100644
--- a/arch/arm/mach-msm/wdog_debug.c
+++ b/arch/arm/mach-msm/wdog_debug.c
@@ -110,7 +110,6 @@
goto err;
wdog_data->dev = &pdev->dev;
platform_set_drvdata(pdev, wdog_data);
- msm_enable_wdog_debug();
return 0;
err:
kzfree(wdog_data);
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 6a010a9..2681836 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -531,7 +531,11 @@
#define RBBM_BLOCK_ID_MARB_3 0x2b
/* RBBM_CLOCK_CTL default value */
-#define A3XX_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
+#define A305_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
+#define A320_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
+#define A330_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAE
+
+#define A330_RBBM_GPR0_CTL_DEFAULT 0x0AE2B8AE
/* COUNTABLE FOR SP PERFCOUNTER */
#define SP_FS_FULL_ALU_INSTRUCTIONS 0x0E
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index c525943..fd9a0c3 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -179,6 +179,8 @@
unsigned int value);
int adreno_dump(struct kgsl_device *device, int manual);
+unsigned int adreno_a3xx_rbbm_clock_ctl_default(struct adreno_device
+ *adreno_dev);
struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
unsigned int pt_base,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 104baf8..4c7534c 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -433,6 +433,19 @@
tmp_ctx.cmd = cmd;
}
+unsigned int adreno_a3xx_rbbm_clock_ctl_default(struct adreno_device
+ *adreno_dev)
+{
+ if (adreno_is_a305(adreno_dev))
+ return A305_RBBM_CLOCK_CTL_DEFAULT;
+ else if (adreno_is_a320(adreno_dev))
+ return A320_RBBM_CLOCK_CTL_DEFAULT;
+ else if (adreno_is_a330(adreno_dev))
+ return A330_RBBM_CLOCK_CTL_DEFAULT;
+
+ BUG_ON(1);
+}
+
/* Copy GMEM contents to system memory shadow. */
static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt,
@@ -442,7 +455,7 @@
unsigned int *start = cmds;
*cmds++ = cp_type0_packet(A3XX_RBBM_CLOCK_CTL, 1);
- *cmds++ = A3XX_RBBM_CLOCK_CTL_DEFAULT;
+ *cmds++ = adreno_a3xx_rbbm_clock_ctl_default(adreno_dev);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
*cmds++ = CP_REG(A3XX_RB_MODE_CONTROL);
@@ -1238,7 +1251,7 @@
unsigned int *start = cmds;
*cmds++ = cp_type0_packet(A3XX_RBBM_CLOCK_CTL, 1);
- *cmds++ = A3XX_RBBM_CLOCK_CTL_DEFAULT;
+ *cmds++ = adreno_a3xx_rbbm_clock_ctl_default(adreno_dev);
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
*cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
@@ -2826,7 +2839,11 @@
/* Enable Clock gating */
adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL,
- A3XX_RBBM_CLOCK_CTL_DEFAULT);
+ adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
+
+ if (adreno_is_a330(adreno_dev))
+ adreno_regwrite(device, A3XX_RBBM_GPR0_CTL,
+ A330_RBBM_GPR0_CTL_DEFAULT);
/* Set the OCMEM base address for A330 */
if (adreno_is_a330(adreno_dev)) {
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index d49fc23..a410445 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -383,7 +383,7 @@
/* Enable Clock gating */
adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL,
- A3XX_RBBM_CLOCK_CTL_DEFAULT);
+ adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
return snapshot;
}
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 0c61d7f..afe384b 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1481,6 +1481,8 @@
return -ENOMEM;
memdesc->sglen = sglen;
+ memdesc->sglen_alloc = sglen;
+
sg_init_table(memdesc->sg, sglen);
spin_lock(¤t->mm->page_table_lock);
@@ -1771,6 +1773,11 @@
entry->memdesc.priv |= param->flags & KGSL_MEMTYPE_MASK;
+ if (entry->memdesc.size >= SZ_1M)
+ entry->memdesc.priv |= ilog2(SZ_1M) << KGSL_MEMALIGN_SHIFT;
+ else if (entry->memdesc.size >= SZ_64K)
+ entry->memdesc.priv |= ilog2(SZ_64K) << KGSL_MEMALIGN_SHIFT;
+
result = kgsl_mmu_map(private->pagetable,
&entry->memdesc,
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 472474b..2861117 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -135,7 +135,8 @@
unsigned int size;
unsigned int priv;
struct scatterlist *sg;
- unsigned int sglen;
+ unsigned int sglen; /* Active entries in the sglist */
+ unsigned int sglen_alloc; /* Allocated entries in the sglist */
struct kgsl_memdesc_ops *ops;
int flags;
};
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 40ed7ca..b49c260 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -168,8 +168,9 @@
struct kgsl_mem_entry *entry;
struct rb_node *node;
struct kgsl_process_private *private = s->private;
- char flags[3];
+ char flags[4];
char usage[16];
+ unsigned int align;
spin_lock(&private->mem_lock);
seq_printf(s, "%8s %8s %5s %10s %16s %5s\n",
@@ -182,7 +183,16 @@
flags[0] = m->priv & KGSL_MEMFLAGS_GLOBAL ? 'g' : '-';
flags[1] = m->priv & KGSL_MEMFLAGS_GPUREADONLY ? 'r' : '-';
- flags[2] = '\0';
+
+ align = (m->priv & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT;
+ if (align >= ilog2(SZ_1M))
+ flags[2] = 'L';
+ else if (align >= ilog2(SZ_64K))
+ flags[2] = 'l';
+ else
+ flags[2] = '-';
+
+ flags[3] = '\0';
kgsl_get_memory_usage(usage, sizeof(usage), m->priv);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 54ba5ad..dbb88ee 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -606,6 +606,7 @@
int ret;
struct gen_pool *pool;
int size;
+ int page_align = ilog2(PAGE_SIZE);
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
if (memdesc->sglen == 1) {
@@ -630,7 +631,17 @@
/* Allocate from kgsl pool if it exists for global mappings */
pool = _get_pool(pagetable, memdesc->priv);
- memdesc->gpuaddr = gen_pool_alloc(pool, size);
+ /* Allocate aligned virtual addresses for iommu. This allows
+ * more efficient pagetable entries if the physical memory
+ * is also aligned. Don't do this for GPUMMU, because
+ * the address space is so small.
+ */
+ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype() &&
+ (memdesc->priv & KGSL_MEMALIGN_MASK)) {
+ page_align = (memdesc->priv & KGSL_MEMALIGN_MASK)
+ >> KGSL_MEMALIGN_SHIFT;
+ }
+ memdesc->gpuaddr = gen_pool_alloc_aligned(pool, size, page_align);
if (memdesc->gpuaddr == 0) {
KGSL_CORE_ERR("gen_pool_alloc(%d) failed from pool: %s\n",
size,
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index bb4ecd1..2e4ac3b 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -159,29 +159,34 @@
container_of(device->parentdev, struct platform_device, dev);
struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
- priv = pwrscale->priv = kzalloc(sizeof(struct msm_priv),
- GFP_KERNEL);
- if (pwrscale->priv == NULL)
- return -ENOMEM;
+ if (the_msm_priv) {
+ priv = pwrscale->priv = the_msm_priv;
+ } else {
+ priv = pwrscale->priv = kzalloc(sizeof(struct msm_priv),
+ GFP_KERNEL);
+ if (pwrscale->priv == NULL)
+ return -ENOMEM;
- priv->core_info = pdata->core_info;
- tbl = priv->core_info->freq_tbl;
- /* Fill in frequency table from low to high, reversing order. */
- low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
- for (i = 0; i <= low_level; i++)
- tbl[i].freq = pwr->pwrlevels[low_level - i].gpu_freq / 1000;
- priv->dcvs_core_id = msm_dcvs_register_core(MSM_DCVS_CORE_TYPE_GPU, 0,
+ priv->core_info = pdata->core_info;
+ tbl = priv->core_info->freq_tbl;
+ /* Fill in frequency table from low to high, reversing order. */
+ low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
+ for (i = 0; i <= low_level; i++)
+ tbl[i].freq =
+ pwr->pwrlevels[low_level - i].gpu_freq / 1000;
+ priv->dcvs_core_id =
+ msm_dcvs_register_core(MSM_DCVS_CORE_TYPE_GPU,
+ 0,
priv->core_info,
msm_set_freq, msm_get_freq, msm_idle_enable,
priv->core_info->sensors[0]);
- if (priv->dcvs_core_id < 0) {
- KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
- goto err;
+ if (priv->dcvs_core_id < 0) {
+ KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
+ goto err;
+ }
+ the_msm_priv = priv;
}
-
priv->device = device;
-
- the_msm_priv = priv;
ret = msm_dcvs_freq_sink_start(priv->dcvs_core_id);
if (ret >= 0) {
if (device->ftbl->isidle(device)) {
@@ -198,7 +203,8 @@
KGSL_PWR_ERR(device, "msm_dcvs_freq_sink_register failed\n");
err:
- kfree(pwrscale->priv);
+ if (!the_msm_priv)
+ kfree(pwrscale->priv);
pwrscale->priv = NULL;
return ret;
@@ -212,7 +218,6 @@
if (pwrscale->priv == NULL)
return;
msm_dcvs_freq_sink_stop(priv->dcvs_core_id);
- kfree(pwrscale->priv);
pwrscale->priv = NULL;
msm_restore_io_fraction(device);
}
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index d48337a..77617ba 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -317,21 +317,42 @@
struct vm_area_struct *vma,
struct vm_fault *vmf)
{
- unsigned long offset;
- struct page *page;
- int i;
+ int i, pgoff;
+ struct scatterlist *s = memdesc->sg;
+ unsigned int offset;
- offset = (unsigned long) vmf->virtual_address - vma->vm_start;
+ offset = ((unsigned long) vmf->virtual_address - vma->vm_start);
- i = offset >> PAGE_SHIFT;
- page = sg_page(&memdesc->sg[i]);
- if (page == NULL)
+ if (offset >= memdesc->size)
return VM_FAULT_SIGBUS;
- get_page(page);
+ pgoff = offset >> PAGE_SHIFT;
- vmf->page = page;
- return 0;
+ /*
+ * The sglist might be comprised of mixed blocks of memory depending
+ * on how many 64K pages were allocated. This means we have to do math
+ * to find the actual 4K page to map in user space
+ */
+
+ for (i = 0; i < memdesc->sglen; i++) {
+ int npages = s->length >> PAGE_SHIFT;
+
+ if (pgoff < npages) {
+ struct page *page = sg_page(s);
+
+ page = nth_page(page, pgoff);
+
+ get_page(page);
+ vmf->page = page;
+
+ return 0;
+ }
+
+ pgoff -= npages;
+ s = sg_next(s);
+ }
+
+ return VM_FAULT_SIGBUS;
}
static int kgsl_page_alloc_vmflags(struct kgsl_memdesc *memdesc)
@@ -357,7 +378,7 @@
}
if (memdesc->sg)
for_each_sg(memdesc->sg, sg, sglen, i)
- __free_page(sg_page(sg));
+ __free_pages(sg_page(sg), get_order(sg->length));
}
static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc)
@@ -379,23 +400,32 @@
pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
struct page **pages = NULL;
struct scatterlist *sg;
+ int npages = PAGE_ALIGN(memdesc->size) >> PAGE_SHIFT;
int sglen = memdesc->sglen;
- int i;
+ int i, count = 0;
/* Don't map the guard page if it exists */
if (memdesc->flags & KGSL_MEMDESC_GUARD_PAGE)
sglen--;
/* create a list of pages to call vmap */
- pages = vmalloc(sglen * sizeof(struct page *));
+ pages = vmalloc(npages * sizeof(struct page *));
if (!pages) {
KGSL_CORE_ERR("vmalloc(%d) failed\n",
- sglen * sizeof(struct page *));
+ npages * sizeof(struct page *));
return -ENOMEM;
}
- for_each_sg(memdesc->sg, sg, sglen, i)
- pages[i] = sg_page(sg);
- memdesc->hostptr = vmap(pages, sglen,
+
+ for_each_sg(memdesc->sg, sg, sglen, i) {
+ struct page *page = sg_page(sg);
+ int j;
+
+ for (j = 0; j < sg->length >> PAGE_SHIFT; j++)
+ pages[count++] = page++;
+ }
+
+
+ memdesc->hostptr = vmap(pages, count,
VM_IOREMAP, page_prot);
KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.vmalloc,
kgsl_driver.stats.vmalloc_max);
@@ -503,14 +533,15 @@
static int
_kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable,
- size_t size, unsigned int protflags)
+ size_t size, unsigned int flags, unsigned int protflags)
{
- int i, order, ret = 0;
- int sglen = PAGE_ALIGN(size) / PAGE_SIZE;
+ int pcount = 0, order, ret = 0;
+ int j, len, page_size, sglen_alloc, sglen = 0;
struct page **pages = NULL;
pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
void *ptr;
struct sysinfo si;
+ unsigned int align;
/*
* Get the current memory information to be used in deciding if we
@@ -530,23 +561,36 @@
if (size >= ((si.freeram << PAGE_SHIFT) - SZ_32M))
return -ENOMEM;
+ align = (flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT;
+
+ page_size = (align >= ilog2(SZ_64K) && size >= SZ_64K)
+ ? SZ_64K : PAGE_SIZE;
+
+ /*
+ * There needs to be enough room in the sg structure to be able to
+ * service the allocation entirely with PAGE_SIZE sized chunks
+ */
+
+ sglen_alloc = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
/*
* Add guard page to the end of the allocation when the
* IOMMU is in use.
*/
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU)
- sglen++;
+ sglen_alloc++;
memdesc->size = size;
memdesc->pagetable = pagetable;
+ memdesc->priv |= (flags & KGSL_MEMALIGN_MASK);
memdesc->ops = &kgsl_page_alloc_ops;
- memdesc->sg = kgsl_sg_alloc(sglen);
+ memdesc->sg = kgsl_sg_alloc(sglen_alloc);
if (memdesc->sg == NULL) {
KGSL_CORE_ERR("vmalloc(%d) failed\n",
- sglen * sizeof(struct scatterlist));
+ sglen_alloc * sizeof(struct scatterlist));
ret = -ENOMEM;
goto done;
}
@@ -558,38 +602,52 @@
* two pages; well within the acceptable limits for using kmalloc.
*/
- pages = kmalloc(sglen * sizeof(struct page *), GFP_KERNEL);
+ pages = kmalloc(sglen_alloc * sizeof(struct page *), GFP_KERNEL);
if (pages == NULL) {
KGSL_CORE_ERR("kmalloc (%d) failed\n",
- sglen * sizeof(struct page *));
+ sglen_alloc * sizeof(struct page *));
ret = -ENOMEM;
goto done;
}
kmemleak_not_leak(memdesc->sg);
- memdesc->sglen = sglen;
- sg_init_table(memdesc->sg, sglen);
+ memdesc->sglen_alloc = sglen_alloc;
+ sg_init_table(memdesc->sg, sglen_alloc);
- for (i = 0; i < PAGE_ALIGN(size) / PAGE_SIZE; i++) {
+ len = size;
- /*
- * Don't use GFP_ZERO here because it is faster to memset the
- * range ourselves (see below)
- */
+ while (len > 0) {
+ struct page *page;
+ unsigned int gfp_mask = GFP_KERNEL | __GFP_HIGHMEM |
+ __GFP_NOWARN;
+ int j;
- pages[i] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
- if (pages[i] == NULL) {
- ret = -ENOMEM;
- memdesc->sglen = i;
- goto done;
+ /* don't waste space at the end of the allocation*/
+ if (len < page_size)
+ page_size = PAGE_SIZE;
+
+ if (page_size != PAGE_SIZE)
+ gfp_mask |= __GFP_COMP;
+
+ page = alloc_pages(gfp_mask, get_order(page_size));
+
+ if (page == NULL) {
+ if (page_size != PAGE_SIZE) {
+ page_size = PAGE_SIZE;
+ continue;
+ }
}
- sg_set_page(&memdesc->sg[i], pages[i], PAGE_SIZE, 0);
+ for (j = 0; j < page_size >> PAGE_SHIFT; j++)
+ pages[pcount++] = nth_page(page, j);
+
+ sg_set_page(&memdesc->sg[sglen++], page, page_size, 0);
+ len -= page_size;
}
- /* ADd the guard page to the end of the sglist */
+ /* Add the guard page to the end of the sglist */
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) {
/*
@@ -603,13 +661,14 @@
__GFP_HIGHMEM);
if (kgsl_guard_page != NULL) {
- sg_set_page(&memdesc->sg[sglen - 1], kgsl_guard_page,
+ sg_set_page(&memdesc->sg[sglen++], kgsl_guard_page,
PAGE_SIZE, 0);
memdesc->flags |= KGSL_MEMDESC_GUARD_PAGE;
- } else
- memdesc->sglen--;
+ }
}
+ memdesc->sglen = sglen;
+
/*
* All memory that goes to the user has to be zeroed out before it gets
* exposed to userspace. This means that the memory has to be mapped in
@@ -629,18 +688,16 @@
* path
*/
- ptr = vmap(pages, i, VM_IOREMAP, page_prot);
+ ptr = vmap(pages, pcount, VM_IOREMAP, page_prot);
if (ptr != NULL) {
memset(ptr, 0, memdesc->size);
dmac_flush_range(ptr, ptr + memdesc->size);
vunmap(ptr);
} else {
- int j;
-
/* Very, very, very slow path */
- for (j = 0; j < i; j++) {
+ for (j = 0; j < pcount; j++) {
ptr = kmap_atomic(pages[j]);
memset(ptr, 0, PAGE_SIZE);
dmac_flush_range(ptr, ptr + PAGE_SIZE);
@@ -683,7 +740,7 @@
size = ALIGN(size, PAGE_SIZE * 2);
ret = _kgsl_sharedmem_page_alloc(memdesc, pagetable, size,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ 0, GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
if (!ret)
ret = kgsl_page_alloc_map_kernel(memdesc);
if (ret)
@@ -707,7 +764,7 @@
protflags |= GSL_PT_PAGE_WV;
return _kgsl_sharedmem_page_alloc(memdesc, pagetable, size,
- protflags);
+ flags, protflags);
}
EXPORT_SYMBOL(kgsl_sharedmem_page_alloc_user);
@@ -757,7 +814,7 @@
if (memdesc->ops && memdesc->ops->free)
memdesc->ops->free(memdesc);
- kgsl_sg_free(memdesc->sg, memdesc->sglen);
+ kgsl_sg_free(memdesc->sg, memdesc->sglen_alloc);
memset(memdesc, 0, sizeof(*memdesc));
}
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 62bfce4..ce1a18e 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -557,6 +557,7 @@
memset(pdata, 0, sizeof *pdata);
pdata->rep = !!of_get_property(node, "autorepeat", NULL);
+ pdata->name = of_get_property(node, "input-name", NULL);
/* First count the subnodes */
pdata->nbuttons = 0;
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index e17e1f8..df66a3a 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -467,6 +467,92 @@
return pgprot;
}
+static unsigned long *make_second_level(struct msm_priv *priv,
+ unsigned long *fl_pte)
+{
+ unsigned long *sl;
+ sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
+ get_order(SZ_4K));
+
+ if (!sl) {
+ pr_debug("Could not allocate second level table\n");
+ goto fail;
+ }
+ memset(sl, 0, SZ_4K);
+ clean_pte(sl, sl + NUM_SL_PTE, priv->redirect);
+
+ *fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | \
+ FL_TYPE_TABLE);
+
+ clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+fail:
+ return sl;
+}
+
+static int sl_4k(unsigned long *sl_pte, phys_addr_t pa, unsigned int pgprot)
+{
+ int ret = 0;
+
+ if (*sl_pte) {
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_NG | SL_SHARED
+ | SL_TYPE_SMALL | pgprot;
+fail:
+ return ret;
+}
+
+static int sl_64k(unsigned long *sl_pte, phys_addr_t pa, unsigned int pgprot)
+{
+ int ret = 0;
+
+ int i;
+
+ for (i = 0; i < 16; i++)
+ if (*(sl_pte+i)) {
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ for (i = 0; i < 16; i++)
+ *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_NG
+ | SL_SHARED | SL_TYPE_LARGE | pgprot;
+
+fail:
+ return ret;
+}
+
+
+static inline int fl_1m(unsigned long *fl_pte, phys_addr_t pa, int pgprot)
+{
+ if (*fl_pte)
+ return -EBUSY;
+
+ *fl_pte = (pa & 0xFFF00000) | FL_NG | FL_TYPE_SECT | FL_SHARED
+ | pgprot;
+
+ return 0;
+}
+
+
+static inline int fl_16m(unsigned long *fl_pte, phys_addr_t pa, int pgprot)
+{
+ int i;
+ int ret = 0;
+ for (i = 0; i < 16; i++)
+ if (*(fl_pte+i)) {
+ ret = -EBUSY;
+ goto fail;
+ }
+ for (i = 0; i < 16; i++)
+ *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION
+ | FL_TYPE_SECT | FL_SHARED | FL_NG | pgprot;
+fail:
+ return ret;
+}
+
static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
phys_addr_t pa, size_t len, int prot)
{
@@ -514,28 +600,16 @@
fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
if (len == SZ_16M) {
- int i = 0;
-
- for (i = 0; i < 16; i++)
- if (*(fl_pte+i)) {
- ret = -EBUSY;
- goto fail;
- }
-
- for (i = 0; i < 16; i++)
- *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION
- | FL_TYPE_SECT | FL_SHARED | FL_NG | pgprot;
+ ret = fl_16m(fl_pte, pa, pgprot);
+ if (ret)
+ goto fail;
clean_pte(fl_pte, fl_pte + 16, priv->redirect);
}
if (len == SZ_1M) {
- if (*fl_pte) {
- ret = -EBUSY;
+ ret = fl_1m(fl_pte, pa, pgprot);
+ if (ret)
goto fail;
- }
-
- *fl_pte = (pa & 0xFFF00000) | FL_NG | FL_TYPE_SECT | FL_SHARED
- | pgprot;
clean_pte(fl_pte, fl_pte + 1, priv->redirect);
}
@@ -543,22 +617,10 @@
if (len == SZ_4K || len == SZ_64K) {
if (*fl_pte == 0) {
- unsigned long *sl;
- sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
- get_order(SZ_4K));
-
- if (!sl) {
- pr_debug("Could not allocate second level table\n");
+ if (make_second_level(priv, fl_pte) == NULL) {
ret = -ENOMEM;
goto fail;
}
- memset(sl, 0, SZ_4K);
- clean_pte(sl, sl + NUM_SL_PTE, priv->redirect);
-
- *fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | \
- FL_TYPE_TABLE);
-
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
}
if (!(*fl_pte & FL_TYPE_TABLE)) {
@@ -572,29 +634,17 @@
sl_pte = sl_table + sl_offset;
if (len == SZ_4K) {
- if (*sl_pte) {
- ret = -EBUSY;
+ ret = sl_4k(sl_pte, pa, pgprot);
+ if (ret)
goto fail;
- }
- *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_NG | SL_SHARED
- | SL_TYPE_SMALL | pgprot;
clean_pte(sl_pte, sl_pte + 1, priv->redirect);
}
if (len == SZ_64K) {
- int i;
-
- for (i = 0; i < 16; i++)
- if (*(sl_pte+i)) {
- ret = -EBUSY;
- goto fail;
- }
-
- for (i = 0; i < 16; i++)
- *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_NG
- | SL_SHARED | SL_TYPE_LARGE | pgprot;
-
+ ret = sl_64k(sl_pte, pa, pgprot);
+ if (ret)
+ goto fail;
clean_pte(sl_pte, sl_pte + 16, priv->redirect);
}
@@ -712,22 +762,28 @@
return pa;
}
+static inline int is_fully_aligned(unsigned int va, phys_addr_t pa, size_t len,
+ int align)
+{
+ return IS_ALIGNED(va, align) && IS_ALIGNED(pa, align)
+ && (len >= align);
+}
+
static int msm_iommu_map_range(struct iommu_domain *domain, unsigned int va,
struct scatterlist *sg, unsigned int len,
int prot)
{
unsigned int pa;
unsigned int offset = 0;
- unsigned int pgprot;
unsigned long *fl_table;
unsigned long *fl_pte;
unsigned long fl_offset;
- unsigned long *sl_table;
+ unsigned long *sl_table = NULL;
unsigned long sl_offset, sl_start;
- unsigned int chunk_offset = 0;
- unsigned int chunk_pa;
+ unsigned int chunk_size, chunk_offset = 0;
int ret = 0;
struct msm_priv *priv;
+ unsigned int pgprot4k, pgprot64k, pgprot1m, pgprot16m;
mutex_lock(&msm_iommu_lock);
@@ -736,49 +792,78 @@
priv = domain->priv;
fl_table = priv->pgtable;
- pgprot = __get_pgprot(prot, SZ_4K);
+ pgprot4k = __get_pgprot(prot, SZ_4K);
+ pgprot64k = __get_pgprot(prot, SZ_64K);
+ pgprot1m = __get_pgprot(prot, SZ_1M);
+ pgprot16m = __get_pgprot(prot, SZ_16M);
- if (!pgprot) {
+ if (!pgprot4k || !pgprot64k || !pgprot1m || !pgprot16m) {
ret = -EINVAL;
goto fail;
}
fl_offset = FL_OFFSET(va); /* Upper 12 bits */
fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
-
- sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
- sl_offset = SL_OFFSET(va);
-
- chunk_pa = get_phys_addr(sg);
- if (chunk_pa == 0) {
- pr_debug("No dma address for sg %p\n", sg);
- ret = -EINVAL;
- goto fail;
- }
+ pa = get_phys_addr(sg);
while (offset < len) {
- /* Set up a 2nd level page table if one doesn't exist */
- if (*fl_pte == 0) {
- sl_table = (unsigned long *)
- __get_free_pages(GFP_KERNEL, get_order(SZ_4K));
+ chunk_size = SZ_4K;
- if (!sl_table) {
- pr_debug("Could not allocate second level table\n");
+ if (is_fully_aligned(va, pa, sg->length - chunk_offset,
+ SZ_16M))
+ chunk_size = SZ_16M;
+ else if (is_fully_aligned(va, pa, sg->length - chunk_offset,
+ SZ_1M))
+ chunk_size = SZ_1M;
+ /* 64k or 4k determined later */
+
+ /* for 1M and 16M, only first level entries are required */
+ if (chunk_size >= SZ_1M) {
+ if (chunk_size == SZ_16M) {
+ ret = fl_16m(fl_pte, pa, pgprot16m);
+ if (ret)
+ goto fail;
+ clean_pte(fl_pte, fl_pte + 16, priv->redirect);
+ fl_pte += 16;
+ } else if (chunk_size == SZ_1M) {
+ ret = fl_1m(fl_pte, pa, pgprot1m);
+ if (ret)
+ goto fail;
+ clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ fl_pte++;
+ }
+
+ offset += chunk_size;
+ chunk_offset += chunk_size;
+ va += chunk_size;
+ pa += chunk_size;
+
+ if (chunk_offset >= sg->length && offset < len) {
+ chunk_offset = 0;
+ sg = sg_next(sg);
+ pa = get_phys_addr(sg);
+ if (pa == 0) {
+ pr_debug("No dma address for sg %p\n",
+ sg);
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+ continue;
+ }
+ /* for 4K or 64K, make sure there is a second level table */
+ if (*fl_pte == 0) {
+ if (!make_second_level(priv, fl_pte)) {
ret = -ENOMEM;
goto fail;
}
-
- memset(sl_table, 0, SZ_4K);
- clean_pte(sl_table, sl_table + NUM_SL_PTE,
- priv->redirect);
-
- *fl_pte = ((((int)__pa(sl_table)) & FL_BASE_MASK) |
- FL_TYPE_TABLE);
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
- } else
- sl_table = (unsigned long *)
- __va(((*fl_pte) & FL_BASE_MASK));
-
+ }
+ if (!(*fl_pte & FL_TYPE_TABLE)) {
+ ret = -EBUSY;
+ goto fail;
+ }
+ sl_table = __va(((*fl_pte) & FL_BASE_MASK));
+ sl_offset = SL_OFFSET(va);
/* Keep track of initial position so we
* don't clean more than we have to
*/
@@ -786,21 +871,39 @@
/* Build the 2nd level page table */
while (offset < len && sl_offset < NUM_SL_PTE) {
- pa = chunk_pa + chunk_offset;
- sl_table[sl_offset] = (pa & SL_BASE_MASK_SMALL) |
- pgprot | SL_NG | SL_SHARED | SL_TYPE_SMALL;
- sl_offset++;
- offset += SZ_4K;
- chunk_offset += SZ_4K;
+ /* Map a large 64K page if the chunk is large enough and
+ * the pa and va are aligned
+ */
+
+ if (is_fully_aligned(va, pa, sg->length - chunk_offset,
+ SZ_64K))
+ chunk_size = SZ_64K;
+ else
+ chunk_size = SZ_4K;
+
+ if (chunk_size == SZ_4K) {
+ sl_4k(&sl_table[sl_offset], pa, pgprot4k);
+ sl_offset++;
+ } else {
+ BUG_ON(sl_offset + 16 > NUM_SL_PTE);
+ sl_64k(&sl_table[sl_offset], pa, pgprot64k);
+ sl_offset += 16;
+ }
+
+
+ offset += chunk_size;
+ chunk_offset += chunk_size;
+ va += chunk_size;
+ pa += chunk_size;
if (chunk_offset >= sg->length && offset < len) {
chunk_offset = 0;
sg = sg_next(sg);
- chunk_pa = get_phys_addr(sg);
- if (chunk_pa == 0) {
+ pa = get_phys_addr(sg);
+ if (pa == 0) {
pr_debug("No dma address for sg %p\n",
- sg);
+ sg);
ret = -EINVAL;
goto fail;
}
@@ -808,7 +911,7 @@
}
clean_pte(sl_table + sl_start, sl_table + sl_offset,
- priv->redirect);
+ priv->redirect);
fl_pte++;
sl_offset = 0;
@@ -842,45 +945,53 @@
fl_offset = FL_OFFSET(va); /* Upper 12 bits */
fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
- sl_start = SL_OFFSET(va);
-
while (offset < len) {
- sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
- sl_end = ((len - offset) / SZ_4K) + sl_start;
+ if (*fl_pte & FL_TYPE_TABLE) {
+ sl_start = SL_OFFSET(va);
+ sl_table = __va(((*fl_pte) & FL_BASE_MASK));
+ sl_end = ((len - offset) / SZ_4K) + sl_start;
- if (sl_end > NUM_SL_PTE)
- sl_end = NUM_SL_PTE;
+ if (sl_end > NUM_SL_PTE)
+ sl_end = NUM_SL_PTE;
- memset(sl_table + sl_start, 0, (sl_end - sl_start) * 4);
- clean_pte(sl_table + sl_start, sl_table + sl_end,
- priv->redirect);
+ memset(sl_table + sl_start, 0, (sl_end - sl_start) * 4);
+ clean_pte(sl_table + sl_start, sl_table + sl_end,
+ priv->redirect);
- offset += (sl_end - sl_start) * SZ_4K;
+ offset += (sl_end - sl_start) * SZ_4K;
+ va += (sl_end - sl_start) * SZ_4K;
- /* Unmap and free the 2nd level table if all mappings in it
- * were removed. This saves memory, but the table will need
- * to be re-allocated the next time someone tries to map these
- * VAs.
- */
- used = 0;
+ /* Unmap and free the 2nd level table if all mappings
+ * in it were removed. This saves memory, but the table
+ * will need to be re-allocated the next time someone
+ * tries to map these VAs.
+ */
+ used = 0;
- /* If we just unmapped the whole table, don't bother
- * seeing if there are still used entries left.
- */
- if (sl_end - sl_start != NUM_SL_PTE)
- for (i = 0; i < NUM_SL_PTE; i++)
- if (sl_table[i]) {
- used = 1;
- break;
- }
- if (!used) {
- free_page((unsigned long)sl_table);
+ /* If we just unmapped the whole table, don't bother
+ * seeing if there are still used entries left.
+ */
+ if (sl_end - sl_start != NUM_SL_PTE)
+ for (i = 0; i < NUM_SL_PTE; i++)
+ if (sl_table[i]) {
+ used = 1;
+ break;
+ }
+ if (!used) {
+ free_page((unsigned long)sl_table);
+ *fl_pte = 0;
+
+ clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ }
+
+ sl_start = 0;
+ } else {
*fl_pte = 0;
-
clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ va += SZ_1M;
+ offset += SZ_1M;
+ sl_start = 0;
}
-
- sl_start = 0;
fl_pte++;
}
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index e9b4e2b..be9c43c 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -208,6 +208,15 @@
two mipi lanes, required for msm8625 platform.
Say Y here if this is msm8625 variant platform.
+config IMX135
+ bool "Sensor imx135 (Sony 13MP)"
+ depends on MSM_CAMERA
+ ---help---
+ Support for IMX135 sensor driver.
+ This is a Sony 13MP Bayer Sensor with autofocus and video HDR
+ support.
+ Say Y if the platform uses IMX135 sensor.
+
config VB6801
bool "Sensor vb6801"
depends on MSM_CAMERA && !ARCH_MSM8X60 && !MSM_CAMERA_V4L2
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 105426e..7155d4c 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -681,6 +681,7 @@
ret_frame.dirty = 0;
ret_frame.node_type = frame.node_type;
ret_frame.timestamp = frame.timestamp;
+ ret_frame.frame_id = frame.frame_id;
D("%s Frame done id: %d\n", __func__, frame.frame_id);
rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
return rc;
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index cd228a1..a70a632 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -8,6 +8,7 @@
obj-$(CONFIG_OV8825) += ov8825_v4l2.o
obj-$(CONFIG_IMX074) += imx074_v4l2.o
obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
+obj-$(CONFIG_IMX135) += imx135_v4l2.o
obj-$(CONFIG_OV2720) += ov2720.o
obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
diff --git a/drivers/media/video/msm/sensors/imx135_v4l2.c b/drivers/media/video/msm/sensors/imx135_v4l2.c
new file mode 100644
index 0000000..f480923
--- /dev/null
+++ b/drivers/media/video/msm/sensors/imx135_v4l2.c
@@ -0,0 +1,553 @@
+/* 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 "msm_sensor.h"
+#define SENSOR_NAME "imx135"
+#define PLATFORM_DRIVER_NAME "msm_camera_imx135"
+#define imx135_obj imx135_##obj
+
+DEFINE_MUTEX(imx135_mut);
+static struct msm_sensor_ctrl_t imx135_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf imx135_start_settings[] = {
+ {0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf imx135_stop_settings[] = {
+ {0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf imx135_groupon_settings[] = {
+ {0x104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf imx135_groupoff_settings[] = {
+ {0x104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf imx135_recommend_settings[] = {
+/* Recommended global settings */
+ {0x0220, 0x01},
+ {0x3008, 0xB0},
+ {0x320A, 0x01},
+ {0x320D, 0x10},
+ {0x3216, 0x2E},
+ {0x3230, 0x0A},
+ {0x3228, 0x05},
+ {0x3229, 0x02},
+ {0x322C, 0x02},
+ {0x3302, 0x10},
+ {0x3390, 0x45},
+ {0x3409, 0x0C},
+ {0x340B, 0xF5},
+ {0x340C, 0x2D},
+ {0x3412, 0x41},
+ {0x3413, 0xAD},
+ {0x3414, 0x1E},
+ {0x3427, 0x04},
+ {0x3480, 0x1E},
+ {0x3484, 0x1E},
+ {0x3488, 0x1E},
+ {0x348C, 0x1E},
+ {0x3490, 0x1E},
+ {0x3494, 0x1E},
+ {0x349C, 0x38},
+ {0x34A3, 0x38},
+ {0x3511, 0x8F},
+ {0x3518, 0x00},
+ {0x3519, 0x94},
+ {0x3833, 0x20},
+ {0x3893, 0x01},
+ {0x38C2, 0x08},
+ {0x3C09, 0x01},
+ {0x4300, 0x00},
+ {0x4316, 0x12},
+ {0x4317, 0x22},
+ {0x431A, 0x00},
+ {0x4324, 0x03},
+ {0x4325, 0x20},
+ {0x4326, 0x03},
+ {0x4327, 0x84},
+ {0x4328, 0x03},
+ {0x4329, 0x20},
+ {0x432A, 0x03},
+ {0x432B, 0x84},
+ {0x4401, 0x3F},
+ {0x4412, 0x3F},
+ {0x4413, 0xFF},
+ {0x4446, 0x3F},
+ {0x4447, 0xFF},
+ {0x4452, 0x00},
+ {0x4453, 0xA0},
+ {0x4454, 0x08},
+ {0x4455, 0x00},
+ {0x4458, 0x18},
+ {0x4459, 0x18},
+ {0x445A, 0x3F},
+ {0x445B, 0x3A},
+ {0x4463, 0x00},
+ {0x4465, 0x00},
+ {0x446E, 0x01},
+/* Image Quality Settings */
+/* Bypass Settings */
+ {0x4203, 0x48},
+/* Defect Correction Recommended Setting */
+ {0x4100, 0xE0},
+ {0x4102, 0x0B},
+/* RGB Filter Recommended Setting */
+ {0x4281, 0x22},
+ {0x4282, 0x82},
+ {0x4284, 0x00},
+ {0x4287, 0x18},
+ {0x4288, 0x00},
+ {0x428B, 0x1E},
+ {0x428C, 0x00},
+ {0x428F, 0x08},
+/* DLC/ADP Recommended Setting */
+ {0x4207, 0x00},
+ {0x4218, 0x02},
+ {0x421B, 0x00},
+ {0x4222, 0x04},
+ {0x4223, 0x44},
+ {0x4224, 0x46},
+ {0x4225, 0xFF},
+ {0x4226, 0x14},
+ {0x4227, 0xF2},
+ {0x4228, 0xFC},
+ {0x4229, 0x60},
+ {0x422A, 0xFA},
+ {0x422B, 0xFE},
+ {0x422C, 0xFE},
+/* Color Artifact Recommended Setting */
+ {0x4243, 0xAA}
+};
+
+/* IMX135 mode 1/2 HV at 24MHz */
+static struct msm_camera_i2c_reg_conf imx135_prev_settings[] = {
+/* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0304, 0x0B},
+ {0x0305, 0x03},
+ {0x0306, 0x01},
+ {0x0307, 0x5E},
+ {0x0309, 0x05},
+ {0x030B, 0x02},
+ {0x030C, 0x00},
+ {0x030D, 0x71},
+ {0x030E, 0x01},
+ {0x3A06, 0x12},
+/* Mode setting */
+ {0x0101, 0x00},
+ {0x0105, 0x00},
+ {0x0108, 0x03},
+ {0x0109, 0x30},
+ {0x010B, 0x32},
+ {0x0112, 0x0A},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x01}, /* binning_en = 1 */
+ {0x0391, 0x22}, /* binning_type */
+ {0x0392, 0x00}, /* binning_mode = 0 (average) */
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x4083, 0x01},
+/* Size setting*/
+ {0x0340, 0x0A}, /* frame_length_lines = 2680*/
+ {0x0341, 0x78},
+ {0x034C, 0x08},
+ {0x034D, 0x38},
+ {0x034E, 0x06},
+ {0x034F, 0x18},
+ {0x0354, 0x08},
+ {0x0355, 0x38},
+ {0x0356, 0x06},
+ {0x0357, 0x18},
+ {0x3310, 0x08},
+ {0x3311, 0x38},
+ {0x3312, 0x06},
+ {0x3313, 0x18},
+ {0x331C, 0x02},
+ {0x331D, 0xC0},
+ {0x33B0, 0x04},
+ {0x33B1, 0x00},
+ {0x33B3, 0x00},
+ {0x7006, 0x04},
+/* Global Timing Setting */
+ {0x0830, 0x67},
+ {0x0831, 0x27},
+ {0x0832, 0x47},
+ {0x0833, 0x27},
+ {0x0834, 0x27},
+ {0x0835, 0x1F},
+ {0x0836, 0x87},
+ {0x0837, 0x2F},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+/* Integration Time Setting */
+ {0x0254, 0x00},
+/* Gain Setting */
+ {0x0205, 0x33}
+};
+
+/* IMX135 Mode Fullsize at 24MHz */
+static struct msm_camera_i2c_reg_conf imx135_snap_settings[] = {
+/* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0304, 0x0B},
+ {0x0305, 0x03},
+ {0x0306, 0x01},
+ {0x0307, 0x5E},
+ {0x0309, 0x05},
+ {0x030B, 0x01},
+ {0x030C, 0x00},
+ {0x030D, 0x60}, /* pll_multiplier = 96 */
+ {0x030E, 0x01},
+ {0x3A06, 0x11},
+/* Mode setting */
+ {0x0101, 0x00},
+ {0x0105, 0x00},
+ {0x0108, 0x03},
+ {0x0109, 0x30},
+ {0x010B, 0x32},
+ {0x0112, 0x0A},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x00},
+ {0x0391, 0x11},
+ {0x0392, 0x00},
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x4083, 0x01},
+/* Size setting */
+ {0x0340, 0x0C},
+ {0x0341, 0x46},
+ {0x034C, 0x10},
+ {0x034D, 0x70},
+ {0x034E, 0x0C},
+ {0x034F, 0x30},
+ {0x0354, 0x10},
+ {0x0355, 0x70},
+ {0x0356, 0x0C},
+ {0x0357, 0x30},
+ {0x3310, 0x10},
+ {0x3311, 0x70},
+ {0x3312, 0x0C},
+ {0x3313, 0x30},
+ {0x331C, 0x06},
+ {0x331D, 0x00},
+ {0x33B0, 0x04},
+ {0x33B1, 0x00},
+ {0x33B3, 0x00},
+ {0x7006, 0x04},
+/* Global Timing Setting */
+ {0x0830, 0x7F},
+ {0x0831, 0x37},
+ {0x0832, 0x5F},
+ {0x0833, 0x37},
+ {0x0834, 0x37},
+ {0x0835, 0x3F},
+ {0x0836, 0xC7},
+ {0x0837, 0x3F},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+/* Integration Time Setting */
+ {0x0250, 0x0B},
+/* Gain Setting */
+ {0x0205, 0x33}
+};
+
+
+static struct msm_camera_i2c_reg_conf imx135_hdr_settings[] = {
+/* Clock Setting */
+ {0x011E, 0x18},
+ {0x011F, 0x00},
+ {0x0301, 0x05},
+ {0x0303, 0x01},
+ {0x0304, 0x0B},
+ {0x0305, 0x03},
+ {0x0306, 0x01},
+ {0x0307, 0x5E},
+ {0x0309, 0x05},
+ {0x030B, 0x02},
+ {0x030C, 0x00},
+ {0x030D, 0x71},
+ {0x030E, 0x01},
+ {0x3A06, 0x12},
+/* Mode setting */
+ {0x0101, 0x00},
+ {0x0105, 0x00},
+ {0x0108, 0x03},
+ {0x0109, 0x30},
+ {0x010B, 0x32},
+ {0x0112, 0x0E},
+ {0x0113, 0x0A},
+ {0x0381, 0x01},
+ {0x0383, 0x01},
+ {0x0385, 0x01},
+ {0x0387, 0x01},
+ {0x0390, 0x00},
+ {0x0391, 0x11},
+ {0x0392, 0x00},
+ {0x0401, 0x00},
+ {0x0404, 0x00},
+ {0x0405, 0x10},
+ {0x4083, 0x01},
+/* Size setting */
+ {0x0340, 0x0C},
+ {0x0341, 0x48},
+ {0x034C, 0x08},
+ {0x034D, 0x38},
+ {0x034E, 0x06},
+ {0x034F, 0x18},
+ {0x0354, 0x08},
+ {0x0355, 0x38},
+ {0x0356, 0x06},
+ {0x0357, 0x18},
+ {0x3310, 0x08},
+ {0x3311, 0x38},
+ {0x3312, 0x06},
+ {0x3313, 0x18},
+ {0x331C, 0x02},
+ {0x331D, 0xA0},
+ {0x33B0, 0x08},
+ {0x33B1, 0x38},
+ {0x33B3, 0x01},
+ {0x7006, 0x04},
+/* Global Timing Setting */
+ {0x0830, 0x67},
+ {0x0831, 0x27},
+ {0x0832, 0x47},
+ {0x0833, 0x27},
+ {0x0834, 0x27},
+ {0x0835, 0x1F},
+ {0x0836, 0x87},
+ {0x0837, 0x2F},
+ {0x0839, 0x1F},
+ {0x083A, 0x17},
+ {0x083B, 0x02},
+/* Integration Time Setting */
+ {0x0250, 0x0B},
+/* Gain Setting */
+ {0x0205, 0x33}
+};
+
+static struct v4l2_subdev_info imx135_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array imx135_init_conf[] = {
+ {&imx135_recommend_settings[0],
+ ARRAY_SIZE(imx135_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array imx135_confs[] = {
+ {&imx135_snap_settings[0],
+ ARRAY_SIZE(imx135_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&imx135_prev_settings[0],
+ ARRAY_SIZE(imx135_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&imx135_hdr_settings[0],
+ ARRAY_SIZE(imx135_hdr_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t imx135_dimensions[] = {
+ /* RES0 snapshot(FULL SIZE) */
+ {
+ .x_output = 4208,
+ .y_output = 3120,
+ .line_length_pclk = 4572,
+ .frame_length_lines = 3142,
+ .vt_pixel_clk = 307200000,
+ .op_pixel_clk = 307200000,
+ .binning_factor = 1,
+ },
+ /* RES1 4:3 preview(1/2HV QTR SIZE) */
+ {
+ .x_output = 2104,
+ .y_output = 1560,
+ .line_length_pclk = 4572,
+ .frame_length_lines = 2680,
+ .vt_pixel_clk = 361600000,
+ .op_pixel_clk = 180800000,
+ .binning_factor = 1,
+ },
+ /* RES2 4:3 HDR movie mode */
+ {
+ .x_output = 2104,
+ .y_output = 1560,
+ .line_length_pclk = 4572,
+ .frame_length_lines = 3144,
+ .vt_pixel_clk = 361600000,
+ .op_pixel_clk = 180800000,
+ .binning_factor = 1,
+ },
+};
+
+static struct msm_sensor_output_reg_addr_t imx135_reg_addr = {
+ .x_output = 0x34C,
+ .y_output = 0x34E,
+ .line_length_pclk = 0x342,
+ .frame_length_lines = 0x340,
+};
+
+static struct msm_sensor_id_info_t imx135_id_info = {
+ .sensor_id_reg_addr = 0x0000,
+ .sensor_id = 0x0087,
+};
+
+static struct msm_sensor_exp_gain_info_t imx135_exp_gain_info = {
+ .coarse_int_time_addr = 0x202,
+ .global_gain_addr = 0x205,
+ .vert_offset = 4,
+};
+
+static const struct i2c_device_id imx135_i2c_id[] = {
+ {SENSOR_NAME, (kernel_ulong_t)&imx135_s_ctrl},
+ { }
+};
+
+static struct i2c_driver imx135_i2c_driver = {
+ .id_table = imx135_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client imx135_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ return i2c_add_driver(&imx135_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops imx135_subdev_core_ops = {
+ .ioctl = msm_sensor_subdev_ioctl,
+ .s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops imx135_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops imx135_subdev_ops = {
+ .core = &imx135_subdev_core_ops,
+ .video = &imx135_subdev_video_ops,
+};
+
+int32_t imx135_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t gain, uint32_t line)
+{
+ uint32_t fl_lines;
+ uint8_t offset;
+ fl_lines = s_ctrl->curr_frame_length_lines;
+ fl_lines = (fl_lines * s_ctrl->fps_divider) / Q10;
+ offset = s_ctrl->sensor_exp_gain_info->vert_offset;
+ if (line > (fl_lines - offset))
+ fl_lines = line + offset;
+
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_output_reg_addr->frame_length_lines, fl_lines,
+ MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr, line,
+ MSM_CAMERA_I2C_WORD_DATA);
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr, gain,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+ return 0;
+}
+
+static struct msm_sensor_fn_t imx135_func_tbl = {
+ .sensor_start_stream = msm_sensor_start_stream,
+ .sensor_stop_stream = msm_sensor_stop_stream,
+ .sensor_group_hold_on = msm_sensor_group_hold_on,
+ .sensor_group_hold_off = msm_sensor_group_hold_off,
+ .sensor_set_fps = msm_sensor_set_fps,
+ .sensor_write_exp_gain = imx135_write_exp_gain,
+ .sensor_write_snapshot_exp_gain = imx135_write_exp_gain,
+ .sensor_setting = msm_sensor_setting,
+ .sensor_csi_setting = msm_sensor_setting1,
+ .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+ .sensor_mode_init = msm_sensor_mode_init,
+ .sensor_get_output_info = msm_sensor_get_output_info,
+ .sensor_config = msm_sensor_config,
+ .sensor_power_up = msm_sensor_power_up,
+ .sensor_power_down = msm_sensor_power_down,
+ .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines1,
+ .sensor_get_csi_params = msm_sensor_get_csi_params,
+};
+
+static struct msm_sensor_reg_t imx135_regs = {
+ .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+ .start_stream_conf = imx135_start_settings,
+ .start_stream_conf_size = ARRAY_SIZE(imx135_start_settings),
+ .stop_stream_conf = imx135_stop_settings,
+ .stop_stream_conf_size = ARRAY_SIZE(imx135_stop_settings),
+ .group_hold_on_conf = imx135_groupon_settings,
+ .group_hold_on_conf_size = ARRAY_SIZE(imx135_groupon_settings),
+ .group_hold_off_conf = imx135_groupoff_settings,
+ .group_hold_off_conf_size =
+ ARRAY_SIZE(imx135_groupoff_settings),
+ .init_settings = &imx135_init_conf[0],
+ .init_size = ARRAY_SIZE(imx135_init_conf),
+ .mode_settings = &imx135_confs[0],
+ .output_settings = &imx135_dimensions[0],
+ .num_conf = ARRAY_SIZE(imx135_confs),
+};
+
+static struct msm_sensor_ctrl_t imx135_s_ctrl = {
+ .msm_sensor_reg = &imx135_regs,
+ .sensor_i2c_client = &imx135_sensor_i2c_client,
+ .sensor_i2c_addr = 0x20,
+ .sensor_output_reg_addr = &imx135_reg_addr,
+ .sensor_id_info = &imx135_id_info,
+ .sensor_exp_gain_info = &imx135_exp_gain_info,
+ .cam_mode = MSM_SENSOR_MODE_INVALID,
+ .msm_sensor_mutex = &imx135_mut,
+ .sensor_i2c_driver = &imx135_i2c_driver,
+ .sensor_v4l2_subdev_info = imx135_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(imx135_subdev_info),
+ .sensor_v4l2_subdev_ops = &imx135_subdev_ops,
+ .func_tbl = &imx135_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Sony 13MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index d843d87..e7b5caf 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -709,7 +709,6 @@
static inline int start_streaming(struct msm_vidc_inst *inst)
{
int rc = 0;
- unsigned long flags;
struct vb2_buf_entry *temp;
struct list_head *ptr, *next;
inst->in_reconfig = false;
@@ -737,7 +736,7 @@
goto fail_start;
}
- spin_lock_irqsave(&inst->lock, flags);
+ mutex_lock(&inst->sync_lock);
if (!list_empty(&inst->pendingq)) {
list_for_each_safe(ptr, next, &inst->pendingq) {
temp = list_entry(ptr, struct vb2_buf_entry, list);
@@ -751,7 +750,7 @@
kfree(temp);
}
}
- spin_unlock_irqrestore(&inst->lock, flags);
+ mutex_unlock(&inst->sync_lock);
return rc;
fail_start:
return rc;
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 525835e9..73a7f8b 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -650,7 +650,6 @@
static inline int start_streaming(struct msm_vidc_inst *inst)
{
int rc = 0;
- unsigned long flags;
struct vb2_buf_entry *temp;
struct list_head *ptr, *next;
@@ -681,7 +680,7 @@
"Failed to move inst: %p to start done state\n", inst);
goto fail_start;
}
- spin_lock_irqsave(&inst->lock, flags);
+ mutex_lock(&inst->sync_lock);
if (!list_empty(&inst->pendingq)) {
list_for_each_safe(ptr, next, &inst->pendingq) {
temp = list_entry(ptr, struct vb2_buf_entry, list);
@@ -695,7 +694,7 @@
kfree(temp);
}
}
- spin_unlock_irqrestore(&inst->lock, flags);
+ mutex_unlock(&inst->sync_lock);
return rc;
fail_start:
return rc;
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 1cad40f..a6805af 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1451,7 +1451,6 @@
int rc = 0;
struct vb2_queue *q;
struct msm_vidc_inst *inst;
- unsigned long flags;
struct vb2_buf_entry *entry;
struct vidc_frame_data frame_data;
q = vb->vb2_queue;
@@ -1468,10 +1467,9 @@
goto err_no_mem;
}
entry->vb = vb;
- dprintk(VIDC_DBG, "Queueing buffer in pendingq\n");
- spin_lock_irqsave(&inst->lock, flags);
+ mutex_lock(&inst->sync_lock);
list_add_tail(&entry->list, &inst->pendingq);
- spin_unlock_irqrestore(&inst->lock, flags);
+ mutex_unlock(&inst->sync_lock);
} else {
int64_t time_usec = timeval_to_ns(&vb->v4l2_buf.timestamp);
do_div(time_usec, NSEC_PER_USEC);
@@ -1777,18 +1775,46 @@
int rc = 0;
bool ip_flush = false;
bool op_flush = false;
+ struct list_head *ptr, *next;
+ struct vb2_buf_entry *temp;
+ struct mutex *lock;
ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
-
if (ip_flush && !op_flush) {
dprintk(VIDC_WARN, "Input only flush not supported\n");
return 0;
}
mutex_lock(&inst->sync_lock);
if (inst->in_reconfig && !ip_flush && op_flush) {
+ if (!list_empty(&inst->pendingq)) {
+ /*Execution can never reach here since port reconfig
+ * wont happen unless pendingq is emptied out
+ * (both pendingq and flush being secured with same
+ * lock). Printing a message here incase this breaks.*/
+ dprintk(VIDC_WARN,
+ "FLUSH BUG: Pending q not empty! It should be empty\n");
+ }
rc = vidc_hal_session_flush(inst->session,
HAL_FLUSH_OUTPUT);
} else {
+ if (!list_empty(&inst->pendingq)) {
+ /*If flush is called after queueing buffers but before
+ * streamon driver should flush the pending queue*/
+ list_for_each_safe(ptr, next, &inst->pendingq) {
+ temp =
+ list_entry(ptr, struct vb2_buf_entry, list);
+ if (temp->vb->v4l2_buf.type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ lock = &inst->bufq[CAPTURE_PORT].lock;
+ else
+ lock = &inst->bufq[OUTPUT_PORT].lock;
+ mutex_lock(lock);
+ vb2_buffer_done(temp->vb, VB2_BUF_STATE_DONE);
+ mutex_unlock(lock);
+ list_del(&temp->list);
+ kfree(temp);
+ }
+ }
rc = vidc_hal_session_flush(inst->session,
HAL_FLUSH_ALL);
}
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index f0d0e73..8ac35d9 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -1437,6 +1437,7 @@
prop->multi_slice);
break;
}
+ hfi->slice_size = prop->slice_size;
pkt->size += sizeof(u32) + sizeof(struct
hfi_multi_slice_control);
break;
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 753171c..a160915 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -19,6 +19,8 @@
#include <linux/videodev2.h>
#include <linux/platform_device.h>
#include <linux/memory_alloc.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
#include <mach/board.h>
#include <mach/gpio.h>
@@ -51,13 +53,31 @@
static struct vcap_dev *vcap_ctrl;
-static unsigned debug;
-
-#define dprintk(level, fmt, arg...) \
- do { \
- if (debug >= level) \
- printk(KERN_DEBUG "VCAP: " fmt, ## arg); \
- } while (0)
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *vcap_debugfs_base;
+static struct reg_range debug_reg_range[] = {
+ {
+ VCAP_REG_RANGE_1_MIN,
+ VCAP_REG_RANGE_1_MAX,
+ },
+ {
+ VCAP_REG_RANGE_2_MIN,
+ VCAP_REG_RANGE_2_MAX,
+ },
+ {
+ VCAP_REG_RANGE_3_MIN,
+ VCAP_REG_RANGE_3_MAX,
+ },
+ {
+ VCAP_REG_RANGE_4_MIN,
+ VCAP_REG_RANGE_4_MAX,
+ },
+ {
+ VCAP_REG_RANGE_5_MIN,
+ VCAP_REG_RANGE_5_MAX,
+ },
+};
+#endif
int vcap_reg_powerup(struct vcap_dev *dev)
{
@@ -91,7 +111,7 @@
int num_gpios = pdata->num_gpios;
unsigned *gpios = pdata->gpios;
- dprintk(4, "GPIO config start\n");
+ pr_debug("GPIO config start\n");
if (on) {
for (i = 0; i < num_gpios; i++) {
ret = gpio_request(gpios[i], "vcap:vc");
@@ -112,7 +132,7 @@
for (i = 0; i < num_gpios; i++)
gpio_free(gpios[i]);
}
- dprintk(4, "GPIO config exit\n");
+ pr_debug("GPIO config exit\n");
return 0;
gpio_failed:
for (i--; i >= 0; i--)
@@ -151,6 +171,7 @@
pr_err("%s: Failed core set_rate %d\n", __func__, ret);
goto fail_vcap_clk;
}
+ dev->dbg_p.clk_rate = (uint32_t) rate;
dev->vcap_npl_clk = clk_get(ddev, "vcap_npl_clk");
if (IS_ERR(dev->vcap_npl_clk)) {
@@ -198,6 +219,7 @@
dev->vcap_npl_clk = NULL;
fail_vcap_clk:
+ dev->dbg_p.clk_rate = 0;
clk_disable(dev->vcap_clk);
fail_vcap_clk_unprep:
clk_unprepare(dev->vcap_clk);
@@ -228,6 +250,8 @@
clk_put(dev->vcap_clk);
dev->vcap_clk = NULL;
}
+
+ dev->dbg_p.clk_rate = 0;
}
int vcap_get_bus_client_handle(struct vcap_dev *dev)
@@ -244,6 +268,7 @@
unsigned long rate)
{
int rc;
+ pr_debug("Enter %s", __func__);
rc = vcap_reg_powerup(dev);
if (rc < 0)
@@ -259,6 +284,7 @@
goto gpio_failed;
writel_relaxed(0x00030003, VCAP_OFFSET(0xD78));
writel_relaxed(0x00030003, VCAP_OFFSET(0xD7C));
+ pr_debug("Success Exit %s", __func__);
return 0;
gpio_failed:
@@ -274,10 +300,12 @@
int vcap_disable(struct vcap_dev *dev)
{
+ pr_debug("Enter %s", __func__);
config_gpios(0, dev->vcap_pdata);
msm_bus_scale_unregister_client(dev->bus_client_handle);
dev->bus_client_handle = 0;
+ dev->dbg_p.bw_request = 0;
vcap_clk_powerdown(dev);
vcap_reg_powerdown(dev);
return 0;
@@ -311,34 +339,34 @@
struct vb2_buffer *vb;
if (q->fileio) {
- dprintk(1, "%s: file io in progress\n", __func__);
+ pr_debug("%s: file io in progress\n", __func__);
return -EBUSY;
}
if (b->type != q->type) {
- dprintk(1, "%s: invalid buffer type\n", __func__);
+ pr_debug("%s: invalid buffer type\n", __func__);
return -EINVAL;
}
if (b->index >= q->num_buffers) {
- dprintk(1, "%s: buffer index out of range\n", __func__);
+ pr_debug("%s: buffer index out of range\n", __func__);
return -EINVAL;
}
vb = q->bufs[b->index];
if (NULL == vb) {
- dprintk(1, "%s: buffer is NULL\n", __func__);
+ pr_debug("%s: buffer is NULL\n", __func__);
return -EINVAL;
}
if (b->memory != q->memory) {
- dprintk(1, "%s: invalid memory type\n", __func__);
+ pr_debug("%s: invalid memory type\n", __func__);
return -EINVAL;
}
if (vb->state != VB2_BUF_STATE_DEQUEUED &&
vb->state != VB2_BUF_STATE_PREPARED) {
- dprintk(1, "%s: buffer already in use\n", __func__);
+ pr_err("%s: buffer already in use\n", __func__);
return -EINVAL;
}
@@ -361,17 +389,17 @@
unsigned long flags;
if (q->fileio) {
- dprintk(1, "%s: file io in progress\n", __func__);
+ pr_debug("%s: file io in progress\n", __func__);
return -EBUSY;
}
if (b->type != q->type) {
- dprintk(1, "%s: invalid buffer type\n", __func__);
+ pr_debug("%s: invalid buffer type\n", __func__);
return -EINVAL;
}
if (!q->streaming) {
- dprintk(1, "Streaming off, will not wait for buffers\n");
+ pr_debug("Streaming off, will not wait for buffers\n");
return -EINVAL;
}
@@ -384,13 +412,13 @@
switch (vb->state) {
case VB2_BUF_STATE_DONE:
- dprintk(3, "%s: Returning done buffer\n", __func__);
+ pr_debug("%s: Returning done buffer\n", __func__);
break;
case VB2_BUF_STATE_ERROR:
- dprintk(3, "%s: Ret done buf with err\n", __func__);
+ pr_debug("%s: Ret done buf with err\n", __func__);
break;
default:
- dprintk(1, "%s: Invalid buffer state\n", __func__);
+ pr_debug("%s: Invalid buffer state\n", __func__);
return -EINVAL;
}
@@ -402,7 +430,7 @@
return 0;
}
- dprintk(1, "No buffers to dequeue\n");
+ pr_debug("%s: No buffers to dequeue\n", __func__);
return -EAGAIN;
}
@@ -415,28 +443,28 @@
int rc;
if (q->fileio) {
- dprintk(1, "%s: file io in progress\n", __func__);
+ pr_debug("%s: file io in progress\n", __func__);
return -EBUSY;
}
if (b->type != q->type) {
- dprintk(1, "%s: invalid buffer type\n", __func__);
+ pr_debug("%s: invalid buffer type\n", __func__);
return -EINVAL;
}
if (b->index >= q->num_buffers) {
- dprintk(1, "%s: buffer index out of range\n", __func__);
+ pr_debug("%s: buffer index out of range\n", __func__);
return -EINVAL;
}
vb = q->bufs[b->index];
if (NULL == vb) {
- dprintk(1, "%s: buffer is NULL\n", __func__);
+ pr_debug("%s: buffer is NULL\n", __func__);
return -EINVAL;
}
if (vb->state != VB2_BUF_STATE_DEQUEUED) {
- dprintk(1, "%s: buffer already in use\n", __func__);
+ pr_debug("%s: buffer already in use\n", __func__);
return -EINVAL;
}
@@ -468,7 +496,7 @@
buf = container_of(vb, struct vcap_buffer, vb);
if (buf->ion_handle == NULL) {
- dprintk(1, "%s: no ION handle to free\n", __func__);
+ pr_debug("%s: no ION handle to free\n", __func__);
return;
}
buf->paddr = 0;
@@ -546,7 +574,7 @@
static int capture_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct vcap_client_data *c_data = vb2_get_drv_priv(vq);
- dprintk(2, "VC start streaming\n");
+ pr_debug("VC start streaming\n");
return vc_start_capture(c_data);
}
@@ -643,7 +671,7 @@
static int vp_in_start_streaming(struct vb2_queue *vq, unsigned int count)
{
- dprintk(2, "VP IN start streaming\n");
+ pr_debug("VP IN start streaming\n");
return 0;
}
@@ -652,7 +680,7 @@
struct vcap_client_data *c_data = vb2_get_drv_priv(vq);
struct vb2_buffer *vb;
- dprintk(2, "VP stop streaming\n");
+ pr_debug("VP IN stop streaming\n");
while (!list_empty(&c_data->vp_action.in_active)) {
struct vcap_buffer *buf;
@@ -749,7 +777,7 @@
struct vcap_client_data *c_data = vb2_get_drv_priv(vq);
struct vb2_buffer *vb;
- dprintk(2, "VP out q stop streaming\n");
+ pr_debug("VP OUT q stop streaming\n");
vp_stop_capture(c_data);
while (!list_empty(&c_data->vp_action.out_active)) {
@@ -890,7 +918,7 @@
struct vcap_dev *dev = c_data->dev;
int rc;
- dprintk(3, "In Req Buf %08x\n", (unsigned int)rb->type);
+ pr_debug("VCAP: In Req Buf %08x\n", (unsigned int)rb->type);
c_data->op_mode = determine_mode(c_data);
if (c_data->op_mode == UNKNOWN_VCAP_OP) {
pr_err("VCAP Error: %s: VCAP in unknown mode\n", __func__);
@@ -968,25 +996,25 @@
struct vb2_queue *q;
int rc;
- dprintk(3, "In Q Buf %08x\n", (unsigned int)p->type);
+ pr_debug("VCAP In Q Buf %08x\n", (unsigned int)p->type);
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (c_data->op_mode == VC_AND_VP_VCAP_OP) {
/* If buffer in vp_in_q it will be coming back */
q = &c_data->vp_in_vidq;
if (p->index >= q->num_buffers) {
- dprintk(1, "qbuf: buffer index out of range\n");
+ pr_debug("VCAP qbuf: buffer index out of range\n");
return -EINVAL;
}
vb = q->bufs[p->index];
if (NULL == vb) {
- dprintk(1, "qbuf: buffer is NULL\n");
+ pr_debug("VCAP qbuf: buffer is NULL\n");
return -EINVAL;
}
if (vb->state != VB2_BUF_STATE_DEQUEUED) {
- dprintk(1, "qbuf: buffer already in use\n");
+ pr_debug("VCAP qbuf: buffer already in use\n");
return -EINVAL;
}
rc = get_phys_addr(c_data->dev, &c_data->vc_vidq, p);
@@ -1035,7 +1063,7 @@
struct vcap_client_data *c_data = to_client_data(file->private_data);
int rc;
- dprintk(3, "In DQ Buf %08x\n", (unsigned int)p->type);
+ pr_debug("VCAP In DQ Buf %08x\n", (unsigned int)p->type);
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (c_data->op_mode == VC_AND_VP_VCAP_OP)
@@ -1072,18 +1100,18 @@
int streamon_validate_q(struct vb2_queue *q)
{
if (q->fileio) {
- dprintk(1, "streamon: file io in progress\n");
+ pr_debug("%s: file io in progress\n", __func__);
return -EBUSY;
}
if (q->streaming) {
- dprintk(1, "streamon: already streaming\n");
+ pr_debug("%s: already streaming\n", __func__);
return -EBUSY;
}
if (V4L2_TYPE_IS_OUTPUT(q->type)) {
if (list_empty(&q->queued_list)) {
- dprintk(1, "streamon: no output buffers queued\n");
+ pr_debug("%s: no output buffers queued\n", __func__);
return -EINVAL;
}
}
@@ -1103,10 +1131,11 @@
idx++;
} while (idx < length);
if (idx == length) {
- pr_err("VCAP: Defaulting to highest BW request\n");
+ pr_info("VCAP: Defaulting to highest BW request\n");
idx--;
}
msm_bus_scale_client_update_request(dev->bus_client_handle, idx);
+ dev->dbg_p.bw_request = bus_vectors[idx].vectors[0].ab;
return 0;
}
@@ -1118,7 +1147,7 @@
unsigned long rate;
long rate_rc;
- dprintk(3, "In Stream ON\n");
+ pr_debug("VCAP: In Stream ON\n");
if (determine_mode(c_data) != c_data->op_mode) {
pr_err("VCAP Error: %s: s_fmt called after req_buf", __func__);
return -ENOTRECOVERABLE;
@@ -1160,6 +1189,8 @@
if (rc < 0)
goto free_res;
+ dev->dbg_p.clk_rate = (uint32_t) rate;
+
rate = (c_data->vc_format.hactive_end -
c_data->vc_format.hactive_start);
@@ -1204,6 +1235,8 @@
}
rate = (unsigned long)rate_rc;
rc = clk_set_rate(dev->vcap_clk, rate);
+
+ dev->dbg_p.clk_rate = (uint32_t) rate;
if (rc < 0)
goto free_res;
@@ -1279,6 +1312,8 @@
if (rc < 0)
goto free_res;
+ dev->dbg_p.clk_rate = (uint32_t) rate;
+
rate = (c_data->vc_format.hactive_end -
c_data->vc_format.hactive_start);
@@ -1376,12 +1411,12 @@
int streamoff_validate_q(struct vb2_queue *q)
{
if (q->fileio) {
- dprintk(1, "streamoff: file io in progress\n");
+ pr_debug("%s: file io in progress\n", __func__);
return -EBUSY;
}
if (!q->streaming) {
- dprintk(1, "streamoff: not streaming\n");
+ pr_debug("%s: not streaming\n", __func__);
return -EINVAL;
}
return 0;
@@ -1791,7 +1826,7 @@
struct vb2_queue *q;
unsigned int mask = 0;
- dprintk(1, "Enter slect/poll\n");
+ pr_debug("%s: Enter slect/poll\n", __func__);
switch (c_data->op_mode) {
case VC_VCAP_OP:
@@ -1866,13 +1901,276 @@
return vc_handler(vcap_ctrl);
}
+#ifdef CONFIG_DEBUG_FS
+/* Query VCAP resource usage */
+static ssize_t read_dump_info(struct file *file, char __user *user_buf,
+ size_t len, loff_t *ppos)
+{
+ struct vcap_dev *dev = file->private_data;
+ char str_buf[512];
+ size_t tot_size = 0, size;
+
+ if (dev->vc_client) {
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "VCAP: VC\n");
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vc_resourse = %d\n", dev->vc_resource);
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vc_enabled = %d\n", atomic_read(&dev->vc_enabled));
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vc_client id = %p\n", dev->vc_client);
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vc_queue_count = %d\n",
+ atomic_read(&dev->vc_client->vc_vidq.queued_count));
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vc_total_buffers = %d\n",
+ dev->vc_client->vc_action.tot_buf);
+ tot_size += size;
+ } else {
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "VCAP: VC not in use\n");
+ tot_size += size;
+ }
+ if (dev->vp_client) {
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "VCAP: VP\n");
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vp_resourse = %d\n", dev->vp_resource);
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vp_enabled = %d\n", atomic_read(&dev->vp_enabled));
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vp_client id = %p\n", dev->vp_client);
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vp_in_queue_count = %d\n",
+ atomic_read(
+ &dev->vp_client->vp_in_vidq.queued_count));
+ tot_size += size;
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "vp_out_queue_count = %d\n",
+ atomic_read(
+ &dev->vp_client->vp_out_vidq.queued_count));
+ tot_size += size;
+ } else {
+ size = scnprintf(str_buf + tot_size, sizeof(str_buf) - tot_size,
+ "VCAP: VP not in use\n");
+ tot_size += size;
+ }
+
+ return simple_read_from_buffer(user_buf, len, ppos, str_buf, tot_size);
+}
+
+static const struct file_operations dump_info_fops = {
+ .read = read_dump_info,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
+
+static int vcap_debug_clk_rate_get(void *data, u64 *val)
+{
+ struct vcap_dev *dev = data;
+ *val = (u64)dev->dbg_p.clk_rate;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clk_rate_fops, vcap_debug_clk_rate_get,
+ NULL, "%llu\n");
+
+static int vcap_debug_bw_req_get(void *data, u64 *val)
+{
+ struct vcap_dev *dev = data;
+ *val = (u64)dev->dbg_p.bw_request;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(bw_req_fops, vcap_debug_bw_req_get,
+ NULL, "%llu\n");
+
+static int vcap_debug_drop_frames_get(void *data, u64 *val)
+{
+ struct vcap_dev *dev = data;
+ struct timeval tv;
+ int drop_count;
+
+ if (!dev->vc_resource)
+ return -EPERM;
+ drop_count = atomic_read(&dev->dbg_p.vc_drop_count);
+ atomic_set(&dev->dbg_p.vc_drop_count, 0);
+
+ do_gettimeofday(&tv);
+ dev->dbg_p.vc_timestamp = (uint32_t) (tv.tv_sec * VCAP_USEC +
+ tv.tv_usec);
+
+ *val = (u64)drop_count;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(tot_frame_drop_fops, vcap_debug_drop_frames_get,
+ NULL, "%llu\n");
+
+static int vcap_debug_drop_fps_get(void *data, u64 *val)
+{
+ struct vcap_dev *dev = data;
+ struct timeval tv;
+ int drop_count;
+ uint32_t new_ts;
+
+ if (!dev->vc_resource)
+ return -EPERM;
+ drop_count = atomic_read(&dev->dbg_p.vc_drop_count);
+ atomic_set(&dev->dbg_p.vc_drop_count, 0);
+
+ do_gettimeofday(&tv);
+ new_ts = (uint32_t) (tv.tv_sec * VCAP_USEC +
+ tv.tv_usec);
+
+ if ((new_ts - dev->dbg_p.vc_timestamp) / VCAP_USEC &&
+ new_ts > dev->dbg_p.vc_timestamp)
+ drop_count /= ((new_ts - dev->dbg_p.vc_timestamp) / VCAP_USEC);
+ else
+ drop_count = 0;
+
+ dev->dbg_p.vc_timestamp = new_ts;
+ *val = (u64)drop_count;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(drop_fps_fops, vcap_debug_drop_fps_get,
+ NULL, "%llu\n");
+
+static int vcap_debug_vp_lat_get(void *data, u64 *val)
+{
+ struct vcap_dev *dev = data;
+
+ if (!dev->vp_resource)
+ return -EPERM;
+ *val = (u64)dev->dbg_p.vp_ewma;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vp_lat_fops, vcap_debug_vp_lat_get,
+ NULL, "%llu\n");
+
+/* Read/Write to VCAP Registers */
+static int vcap_debug_reg_set(void *data, u64 val)
+{
+ struct vcap_dev *dev = data;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(debug_reg_range); i++) {
+ if (val >= debug_reg_range[i].min_val && val <=
+ debug_reg_range[i].max_val)
+ break;
+ }
+ if (i == ARRAY_SIZE(debug_reg_range))
+ return -EINVAL;
+ dev->dbg_p.reg_addr = (uint32_t) val;
+ return 0;
+}
+
+static int vcap_debug_reg_get(void *data, u64 *val)
+{
+ struct vcap_dev *dev = data;
+ *val = (u64)dev->dbg_p.reg_addr;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vcap_reg_fops, vcap_debug_reg_get,
+ vcap_debug_reg_set, "0x%08llx\n")
+
+static int vcap_debug_reg_rdwr_set(void *data, u64 val)
+{
+ struct vcap_dev *dev = data;
+ u32 reg_val = (u32) val;
+
+ writel_iowmb(reg_val, VCAP_OFFSET(dev->dbg_p.reg_addr));
+ return 0;
+}
+
+static int vcap_debug_reg_rdwr_get(void *data, u64 *val)
+{
+ struct vcap_dev *dev = data;
+ *val = (u64)readl_relaxed(VCAP_OFFSET(dev->dbg_p.reg_addr));
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vcap_reg_rdwr_fops, vcap_debug_reg_rdwr_get,
+ vcap_debug_reg_rdwr_set, "0x%08llx\n");
+
+static int vcap_debugfs_init(struct vcap_dev *dev)
+{
+ vcap_debugfs_base = debugfs_create_dir("vcap", NULL);
+ if (!vcap_debugfs_base)
+ return -ENOMEM;
+
+ if (!debugfs_create_file("dump_info", S_IRUGO,
+ vcap_debugfs_base, dev, &dump_info_fops))
+ goto error;
+
+ if (!debugfs_create_file("vcap_core_clk_rate", S_IRUGO,
+ vcap_debugfs_base, dev, &clk_rate_fops))
+ goto error;
+
+ if (!debugfs_create_file("vcap_bw_req", S_IRUGO,
+ vcap_debugfs_base, dev, &bw_req_fops))
+ goto error;
+
+ if (!debugfs_create_file("vc_total_frames_drop", S_IRUGO,
+ vcap_debugfs_base, dev, &tot_frame_drop_fops))
+ goto error;
+
+ if (!debugfs_create_file("vc_drop_fps", S_IRUGO,
+ vcap_debugfs_base, dev, &drop_fps_fops))
+ goto error;
+
+ if (!debugfs_create_file("vp_avg_completion_t", S_IRUGO,
+ vcap_debugfs_base, dev, &vp_lat_fops))
+ goto error;
+
+ if (!debugfs_create_file("vcap_reg_addr", S_IRUGO | S_IWUSR,
+ vcap_debugfs_base, dev, &vcap_reg_fops))
+ goto error;
+
+ if (!debugfs_create_file("vcap_reg_val", S_IRUGO | S_IWUSR,
+ vcap_debugfs_base, dev, &vcap_reg_rdwr_fops))
+ goto error;
+ return 0;
+
+error:
+ debugfs_remove_recursive(vcap_debugfs_base);
+ vcap_debugfs_base = NULL;
+ return -ENOMEM;
+}
+
+static void vcap_debugfs_remove(void)
+{
+ if (vcap_debugfs_base) {
+ debugfs_remove_recursive(vcap_debugfs_base);
+ vcap_debugfs_base = NULL;
+ }
+}
+#else
+
+static int vcap_debugfs_init(struct vcap_dev *dev)
+{
+ return 0;
+}
+static void vcap_debugfs_remove(void) {}
+#endif
+
static int __devinit vcap_probe(struct platform_device *pdev)
{
struct vcap_dev *dev;
struct video_device *vfd;
int ret;
- dprintk(1, "Probe started\n");
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
@@ -1949,6 +2247,7 @@
if (ret)
goto unreg_dev;
msm_bus_scale_client_update_request(dev->bus_client_handle, 0);
+ dev->dbg_p.bw_request = 0;
ret = detect_vc(dev);
@@ -1987,6 +2286,11 @@
goto rel_vcap_wq;
}
+ atomic_set(&dev->dbg_p.vc_drop_count, 0);
+ ret = vcap_debugfs_init(dev);
+ if (ret < 0)
+ pr_err("VCAP debugfs failed to load");
+
dev->vc_tot_buf = 2;
atomic_set(&dev->vc_enabled, 0);
atomic_set(&dev->vp_enabled, 0);
@@ -1996,7 +2300,6 @@
init_waitqueue_head(&dev->vp_dummy_waitq);
vcap_disable(dev);
- dprintk(1, "Exit probe succesfully");
return 0;
rel_vcap_wq:
destroy_workqueue(dev->vcap_wq);
@@ -2020,6 +2323,7 @@
static int __devexit vcap_remove(struct platform_device *pdev)
{
struct vcap_dev *dev = vcap_ctrl;
+ vcap_debugfs_remove();
ion_client_destroy(dev->ion_client);
flush_workqueue(dev->vcap_wq);
destroy_workqueue(dev->vcap_wq);
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 572c272..3d81161 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -27,14 +27,6 @@
#include <media/vcap_fmt.h>
#include "vcap_vc.h"
-static unsigned debug;
-
-#define dprintk(level, fmt, arg...) \
- do { \
- if (debug >= level) \
- printk(KERN_DEBUG "VC: " fmt, ## arg); \
- } while (0)
-
void config_buffer(struct vcap_client_data *c_data,
struct vcap_buffer *buf,
void __iomem *y_addr,
@@ -73,7 +65,7 @@
vb_vc = vp_work->cd->vc_vidq.bufs[p.index];
if (NULL == vb_vc) {
- dprintk(1, "%s: buffer is NULL\n", __func__);
+ pr_debug("%s: buffer is NULL\n", __func__);
vcvp_qbuf(&vp_work->cd->vc_vidq, &p);
return;
}
@@ -81,7 +73,7 @@
vb_vp = vp_work->cd->vp_in_vidq.bufs[p.index];
if (NULL == vb_vp) {
- dprintk(1, "%s: buffer is NULL\n", __func__);
+ pr_debug("%s: buffer is NULL\n", __func__);
vcvp_qbuf(&vp_work->cd->vc_vidq, &p);
return;
}
@@ -145,7 +137,7 @@
irq = readl_relaxed(VCAP_VC_INT_STATUS);
- dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
+ pr_debug("%s: irq=0x%08x\n", __func__, irq);
c_data = dev->vc_client;
if (!c_data->streaming) {
@@ -254,6 +246,8 @@
v4l2_event_queue(dev->vfd, &v4l2_evt);
c_data->vc_action.top_field =
!c_data->vc_action.top_field;
+
+ atomic_inc(&dev->dbg_p.vc_drop_count);
continue;
}
buf = list_entry(c_data->vc_action.active.next,
@@ -296,12 +290,13 @@
{
struct vc_action *vc_action = &c_data->vc_action;
struct vcap_dev *dev;
+ struct timeval tv;
unsigned long flags = 0;
int rc, i, counter = 0;
struct vcap_buffer *buf;
dev = c_data->dev;
- dprintk(2, "Start Kickoff\n");
+ pr_debug("Start Kickoff\n");
if (dev->vc_client == NULL) {
pr_err("No active vc client\n");
@@ -344,6 +339,11 @@
c_data->vc_action.vc_ts.tv_usec =
c_data->vc_action.last_ts % VCAP_USEC;
+ atomic_set(&dev->dbg_p.vc_drop_count, 0);
+ do_gettimeofday(&tv);
+ dev->dbg_p.vc_timestamp = (uint32_t) (tv.tv_sec * VCAP_USEC +
+ tv.tv_usec);
+
rc = 0;
for (i = 0; i < c_data->vc_action.tot_buf; i++)
rc = rc << 1 | 0x2;
@@ -416,7 +416,7 @@
rc = readl_relaxed(VCAP_VC_NPL_CTRL);
writel_iowmb(0x00000002, VCAP_VC_NPL_CTRL);
- dprintk(2, "%s: Starting VC configuration\n", __func__);
+ pr_debug("%s: Starting VC configuration\n", __func__);
writel_iowmb(0x00000002, VCAP_VC_NPL_CTRL);
writel_iowmb(0x00000004 | vc_format->color_space << 1 |
vc_format->mode << 3 |
@@ -464,7 +464,7 @@
writel_relaxed(0x00006b38, VCAP_VC_IN_CTRL5);
writel_iowmb(0x00000001 , VCAP_OFFSET(0x0d00));
- dprintk(2, "%s: Done VC configuration\n", __func__);
+ pr_debug("%s: Done VC configuration\n", __func__);
return 0;
}
@@ -473,7 +473,7 @@
{
int result;
result = readl_relaxed(VCAP_HARDWARE_VERSION_REG);
- dprintk(1, "Hardware version: %08x\n", result);
+ pr_debug("Hardware version: %08x\n", result);
if (result != VCAP_HARDWARE_VERSION)
return -ENODEV;
INIT_WORK(&dev->vc_to_vp_work.work, mov_buf_to_vp);
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index a017cf2..c7de465 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -25,14 +25,6 @@
#include <media/vcap_fmt.h>
#include "vcap_vp.h"
-static unsigned debug;
-
-#define dprintk(level, fmt, arg...) \
- do { \
- if (debug >= level) \
- printk(KERN_DEBUG "VP: " fmt, ## arg); \
- } while (0)
-
void config_nr_buffer(struct vcap_client_data *c_data,
struct vcap_buffer *buf)
{
@@ -72,10 +64,10 @@
if (!c_data->streaming)
return -ENOEXEC;
dev = c_data->dev;
- dprintk(2, "Start setup buffers\n");
+ pr_debug("VP: Start setup buffers\n");
if (dev->vp_shutdown) {
- dprintk(1, "%s: VP shutting down, no buf setup\n",
+ pr_debug("%s: VP shutting down, no buf setup\n",
__func__);
return -EPERM;
}
@@ -86,7 +78,7 @@
spin_lock_irqsave(&dev->vp_client->cap_slock, flags);
if (list_empty(&vp_act->in_active)) {
spin_unlock_irqrestore(&dev->vp_client->cap_slock, flags);
- dprintk(1, "%s: VP We have no more input buffers\n",
+ pr_debug("%s: VP We have no more input buffers\n",
__func__);
return -EAGAIN;
}
@@ -94,7 +86,7 @@
if (list_empty(&vp_act->out_active)) {
spin_unlock_irqrestore(&dev->vp_client->cap_slock,
flags);
- dprintk(1, "%s: VP We have no more output buffers\n",
+ pr_debug("%s: VP We have no more output buffers\n",
__func__);
return -EAGAIN;
}
@@ -136,7 +128,7 @@
vb_vc = vp_work->cd->vc_vidq.bufs[p.index];
if (NULL == vb_vc) {
- dprintk(1, "%s: buffer is NULL\n", __func__);
+ pr_debug("%s: buffer is NULL\n", __func__);
vcvp_qbuf(&vp_work->cd->vp_in_vidq, &p);
return;
}
@@ -144,7 +136,7 @@
vb_vp = vp_work->cd->vp_in_vidq.bufs[p.index];
if (NULL == vb_vp) {
- dprintk(1, "%s: buffer is NULL\n", __func__);
+ pr_debug("%s: buffer is NULL\n", __func__);
vcvp_qbuf(&vp_work->cd->vp_in_vidq, &p);
return;
}
@@ -158,7 +150,7 @@
/* This call should not fail */
rc = vcvp_qbuf(&vp_work->cd->vc_vidq, &p);
if (rc < 0) {
- dprintk(1, "%s: qbuf to vc failed\n", __func__);
+ pr_err("%s: qbuf to vc failed\n", __func__);
buf_vp->ion_handle = buf_vc->ion_handle;
buf_vp->paddr = buf_vc->paddr;
buf_vc->ion_handle = NULL;
@@ -197,6 +189,7 @@
struct vp_work_t *vp_work = container_of(work, struct vp_work_t, work);
struct vcap_dev *dev;
struct vp_action *vp_act;
+ struct timeval tv;
unsigned long flags = 0;
uint32_t irq;
int rc;
@@ -278,6 +271,11 @@
writel_iowmb(0x00000000 | top_field, VCAP_VP_CTRL);
writel_iowmb(0x00010000 | top_field, VCAP_VP_CTRL);
enable_irq(dev->vpirq->start);
+
+ do_gettimeofday(&tv);
+ dev->dbg_p.vp_timestamp = (uint32_t) (tv.tv_sec * VCAP_USEC +
+ tv.tv_usec);
+
writel_iowmb(irq, VCAP_VP_INT_CLEAR);
}
@@ -288,6 +286,8 @@
struct v4l2_event v4l2_evt;
uint32_t irq;
int rc;
+ struct timeval tv;
+ uint32_t new_ts;
irq = readl_relaxed(VCAP_VP_INT_STATUS);
if (dev->vp_dummy_event == true) {
@@ -318,7 +318,7 @@
v4l2_event_queue(dev->vfd, &v4l2_evt);
}
- dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
+ pr_debug("%s: irq=0x%08x\n", __func__, irq);
if (!(irq & (VP_PIC_DONE | VP_MODE_CHANGE))) {
writel_relaxed(irq, VCAP_VP_INT_CLEAR);
pr_err("VP IRQ shows some error\n");
@@ -341,6 +341,17 @@
return -EAGAIN;
}
+ do_gettimeofday(&tv);
+ new_ts = (uint32_t) (tv.tv_sec * VCAP_USEC +
+ tv.tv_usec);
+ if (new_ts > dev->dbg_p.vp_timestamp) {
+ dev->dbg_p.vp_ewma = ((new_ts - dev->dbg_p.vp_timestamp) /
+ 10 + (dev->dbg_p.vp_ewma / 10 * 9));
+ }
+
+ dev->dbg_p.vp_timestamp = (uint32_t) (tv.tv_sec * VCAP_USEC +
+ tv.tv_usec);
+
INIT_WORK(&dev->vp_work.work, vp_wq_fnc);
dev->vp_work.cd = c_data;
rc = queue_work(dev->vcap_wq, &dev->vp_work.work);
@@ -663,7 +674,7 @@
uint32_t reg;
int rc = 0;
- dprintk(2, "%s: Start VP dummy event\n", __func__);
+ pr_debug("%s: Start VP dummy event\n", __func__);
handle = ion_alloc(dev->ion_client, 0x1200, SZ_4K,
ION_HEAP(ION_CP_MM_HEAP_ID), 0);
if (IS_ERR_OR_NULL(handle)) {
@@ -723,7 +734,7 @@
c_data->vp_out_fmt.height = height;
ion_free(dev->ion_client, handle);
- dprintk(2, "%s: Exit VP dummy event\n", __func__);
+ pr_debug("%s: Exit VP dummy event\n", __func__);
return rc;
}
@@ -731,6 +742,7 @@
{
struct vcap_dev *dev;
struct vp_action *vp_act;
+ struct timeval tv;
unsigned long flags = 0;
unsigned int chroma_fmt = 0;
int size;
@@ -740,7 +752,7 @@
return -ENOEXEC;
dev = c_data->dev;
- dprintk(2, "Start Kickoff\n");
+ pr_debug("Start VP Kickoff\n");
if (dev->vp_client == NULL) {
pr_err("No active vp client\n");
@@ -815,6 +827,11 @@
writel_iowmb(0x00010000 | top_field, VCAP_VP_CTRL);
atomic_set(&c_data->dev->vp_enabled, 1);
enable_irq(dev->vpirq->start);
+
+ do_gettimeofday(&tv);
+ dev->dbg_p.vp_timestamp = (uint32_t) (tv.tv_sec * VCAP_USEC +
+ tv.tv_usec);
+
return 0;
}
@@ -822,10 +839,11 @@
{
struct vcap_dev *dev;
struct vp_action *vp_act;
+ struct timeval tv;
int rc;
bool top_field = 0;
- dprintk(2, "Start Continue\n");
+ pr_debug("Start VP Continue\n");
dev = c_data->dev;
if (dev->vp_client == NULL) {
@@ -854,5 +872,10 @@
atomic_set(&c_data->dev->vp_enabled, 1);
enable_irq(dev->vpirq->start);
+
+ do_gettimeofday(&tv);
+ dev->dbg_p.vp_timestamp = (uint32_t) (tv.tv_sec * VCAP_USEC +
+ tv.tv_usec);
+
return 0;
}
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index bc8eccf..12f896e 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -38,6 +38,7 @@
#include <mach/msm_bus_board.h>
#include <mach/scm.h>
#include <mach/peripheral-loader.h>
+#include <mach/socinfo.h>
#include "qseecom_legacy.h"
#define QSEECOM_DEV "qseecom"
@@ -179,6 +180,7 @@
int send_resp_flag;
uint32_t qseos_version;
+ struct device *pdev;
};
struct qseecom_client_handle {
@@ -208,9 +210,16 @@
atomic_t ioctl_count;
};
+struct clk *ce_core_clk;
+struct clk *ce_clk;
+struct clk *ce_core_src_clk;
+struct clk *ce_bus_clk;
+
/* Function proto types */
static int qsee_vote_for_clock(int32_t);
static void qsee_disable_clock_vote(int32_t);
+static int __qseecom_init_clk(void);
+static void __qseecom_disable_clk(void);
static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
struct qseecom_register_listener_req *svc)
@@ -1735,9 +1744,131 @@
.release = qseecom_release
};
+static int __qseecom_init_clk()
+{
+ int rc = 0;
+ struct device *pdev;
+
+ pdev = qseecom.pdev;
+ /* Get CE3 src core clk. */
+ ce_core_src_clk = clk_get(pdev, "core_clk_src");
+ if (!IS_ERR(ce_core_src_clk)) {
+ ce_core_src_clk = ce_core_src_clk;
+
+ /* Set the core src clk @100Mhz */
+ rc = clk_set_rate(ce_core_src_clk, 100000000);
+ if (rc) {
+ clk_put(ce_core_src_clk);
+ pr_err("Unable to set the core src clk @100Mhz.\n");
+ goto err_clk;
+ }
+ } else {
+ pr_warn("Unable to get CE core src clk, set to NULL\n");
+ ce_core_src_clk = NULL;
+ }
+
+ /* Get CE core clk */
+ ce_core_clk = clk_get(pdev, "core_clk");
+ if (IS_ERR(ce_core_clk)) {
+ rc = PTR_ERR(ce_core_clk);
+ pr_err("Unable to get CE core clk\n");
+ if (ce_core_src_clk != NULL)
+ clk_put(ce_core_src_clk);
+ goto err_clk;
+ }
+
+ /* Get CE Interface clk */
+ ce_clk = clk_get(pdev, "iface_clk");
+ if (IS_ERR(ce_clk)) {
+ rc = PTR_ERR(ce_clk);
+ pr_err("Unable to get CE interface clk\n");
+ if (ce_core_src_clk != NULL)
+ clk_put(ce_core_src_clk);
+ clk_put(ce_core_clk);
+ goto err_clk;
+ }
+
+ /* Get CE AXI clk */
+ ce_bus_clk = clk_get(pdev, "bus_clk");
+ if (IS_ERR(ce_bus_clk)) {
+ rc = PTR_ERR(ce_bus_clk);
+ pr_err("Unable to get CE BUS interface clk\n");
+ if (ce_core_src_clk != NULL)
+ clk_put(ce_core_src_clk);
+ clk_put(ce_core_clk);
+ clk_put(ce_clk);
+ goto err_clk;
+ }
+
+ /* Enable CE core clk */
+ rc = clk_prepare_enable(ce_core_clk);
+ if (rc) {
+ pr_err("Unable to enable/prepare CE core clk\n");
+ if (ce_core_src_clk != NULL)
+ clk_put(ce_core_src_clk);
+ clk_put(ce_core_clk);
+ clk_put(ce_clk);
+ goto err_clk;
+ } else {
+ /* Enable CE clk */
+ rc = clk_prepare_enable(ce_clk);
+ if (rc) {
+ pr_err("Unable to enable/prepare CE iface clk\n");
+ clk_disable_unprepare(ce_core_clk);
+ if (ce_core_src_clk != NULL)
+ clk_put(ce_core_src_clk);
+ clk_put(ce_core_clk);
+ clk_put(ce_clk);
+ goto err_clk;
+ } else {
+ /* Enable AXI clk */
+ rc = clk_prepare_enable(ce_bus_clk);
+ if (rc) {
+ pr_err("Unable to enable/prepare CE iface clk\n");
+ clk_disable_unprepare(ce_core_clk);
+ clk_disable_unprepare(ce_clk);
+ if (ce_core_src_clk != NULL)
+ clk_put(ce_core_src_clk);
+ clk_put(ce_core_clk);
+ clk_put(ce_clk);
+ goto err_clk;
+ }
+ }
+ }
+ return rc;
+
+err_clk:
+ if (rc)
+ pr_err("Unable to init CE clks, rc = %d\n", rc);
+ clk_disable_unprepare(ce_clk);
+ clk_disable_unprepare(ce_core_clk);
+ clk_disable_unprepare(ce_bus_clk);
+ if (ce_core_src_clk != NULL)
+ clk_put(ce_core_src_clk);
+ clk_put(ce_clk);
+ clk_put(ce_core_clk);
+ clk_put(ce_bus_clk);
+ return rc;
+}
+
+
+
+static void __qseecom_disable_clk()
+{
+ clk_disable_unprepare(ce_clk);
+ clk_disable_unprepare(ce_core_clk);
+ clk_disable_unprepare(ce_bus_clk);
+ if (ce_core_src_clk != NULL)
+ clk_put(ce_core_src_clk);
+ clk_put(ce_clk);
+ clk_put(ce_core_clk);
+ clk_put(ce_bus_clk);
+}
+
static int __devinit qseecom_probe(struct platform_device *pdev)
{
int rc;
+ int ret;
struct device *class_dev;
char qsee_not_legacy = 0;
struct msm_bus_scale_pdata *qseecom_platform_support;
@@ -1796,6 +1927,8 @@
pil = NULL;
pil_ref_cnt = 0;
}
+
+ qseecom.pdev = class_dev;
/* Create ION msm client */
qseecom.ion_clnt = msm_ion_client_create(0x03, "qseecom-kernel");
if (qseecom.ion_clnt == NULL) {
@@ -1805,17 +1938,23 @@
}
/* register client for bus scaling */
- if (!pdev->dev.of_node) {
+ if (pdev->dev.of_node) {
+ ret = __qseecom_init_clk();
+ if (ret)
+ goto err;
+ qseecom_platform_support = (struct msm_bus_scale_pdata *)
+ msm_bus_cl_get_pdata(pdev);
+ } else {
qseecom_platform_support = (struct msm_bus_scale_pdata *)
pdev->dev.platform_data;
- qsee_perf_client = msm_bus_scale_register_client(
- qseecom_platform_support);
-
- if (!qsee_perf_client)
- pr_err("Unable to register bus client\n");
}
- return 0;
+ qsee_perf_client = msm_bus_scale_register_client(
+ qseecom_platform_support);
+
+ if (!qsee_perf_client)
+ pr_err("Unable to register bus client\n");
+ return 0;
err:
device_destroy(driver_class, qseecom_device_no);
class_destroy:
@@ -1856,6 +1995,9 @@
static void __devexit qseecom_exit(void)
{
+
+ __qseecom_disable_clk();
+
device_destroy(driver_class, qseecom_device_no);
class_destroy(driver_class);
unregister_chrdev_region(qseecom_device_no, 1);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 9b4c82a..89e7af0 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -884,6 +884,9 @@
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
+ if (card->ext_csd.bkops_en)
+ card->bkops_info.sectors_changed += blk_rq_sectors(req);
+
if (mmc_can_discard(card))
arg = MMC_DISCARD_ARG;
else if (mmc_can_trim(card))
@@ -1541,8 +1544,12 @@
break;
}
- if (rq_data_dir(next) == WRITE)
+ if (rq_data_dir(next) == WRITE) {
mq->num_of_potential_packed_wr_reqs++;
+ if (card->ext_csd.bkops_en)
+ card->bkops_info.sectors_changed +=
+ blk_rq_sectors(next);
+ }
list_add_tail(&next->queuelist, &mq->mqrq_cur->packed_list);
cur = next;
reqs++;
@@ -1761,8 +1768,11 @@
if (!rqc && !mq->mqrq_prev->req)
return 0;
- if (rqc)
+ if (rqc) {
+ if ((card->ext_csd.bkops_en) && (rq_data_dir(rqc) == WRITE))
+ card->bkops_info.sectors_changed += blk_rq_sectors(rqc);
reqs = mmc_blk_prep_packed_list(mq, rqc);
+ }
do {
if (rqc) {
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index f3692a9..cc91646 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -59,6 +59,7 @@
struct mmc_queue *mq = d;
struct request_queue *q = mq->queue;
struct request *req;
+ struct mmc_card *card = mq->card;
current->flags |= PF_MEMALLOC;
@@ -74,6 +75,17 @@
spin_unlock_irq(q->queue_lock);
if (req || mq->mqrq_prev->req) {
+ /*
+ * If this is the first request, BKOPs might be in
+ * progress and needs to be stopped before issuing the
+ * request
+ */
+ if (card->ext_csd.bkops_en &&
+ card->bkops_info.started_delayed_bkops) {
+ card->bkops_info.started_delayed_bkops = false;
+ mmc_stop_bkops(card);
+ }
+
set_current_state(TASK_RUNNING);
mq->issue_fn(mq, req);
} else {
@@ -81,6 +93,7 @@
set_current_state(TASK_RUNNING);
break;
}
+ mmc_start_delayed_bkops(card);
up(&mq->thread_sem);
schedule();
down(&mq->thread_sem);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9b316bb..9b9e8cc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -280,9 +280,42 @@
}
/**
+ * mmc_start_delayed_bkops() - Start a delayed work to check for
+ * the need of non urgent BKOPS
+ *
+ * @card: MMC card to start BKOPS on
+ */
+void mmc_start_delayed_bkops(struct mmc_card *card)
+{
+ if (!card || !card->ext_csd.bkops_en || mmc_card_doing_bkops(card))
+ return;
+
+ if (card->bkops_info.sectors_changed <
+ BKOPS_MIN_SECTORS_TO_QUEUE_DELAYED_WORK)
+ return;
+
+ pr_debug("%s: %s: queueing delayed_bkops_work\n",
+ mmc_hostname(card->host), __func__);
+
+ card->bkops_info.sectors_changed = 0;
+
+ /*
+ * cancel_delayed_bkops_work will prevent a race condition between
+ * fetching a request by the mmcqd and the delayed work, in case
+ * it was removed from the queue work but not started yet
+ */
+ card->bkops_info.cancel_delayed_work = false;
+ card->bkops_info.started_delayed_bkops = true;
+ queue_delayed_work(system_nrt_wq, &card->bkops_info.dw,
+ msecs_to_jiffies(
+ card->bkops_info.delay_ms));
+}
+EXPORT_SYMBOL(mmc_start_delayed_bkops);
+
+/**
* mmc_start_bkops - start BKOPS for supported cards
* @card: MMC card to start BKOPS
- * @form_exception: A flag to indicate if this function was
+ * @from_exception: A flag to indicate if this function was
* called due to an exception raised by the card
*
* Start background operations whenever requested.
@@ -296,25 +329,47 @@
bool use_busy_signal;
BUG_ON(!card);
-
- if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card))
+ if (!card->ext_csd.bkops_en)
return;
+ mmc_claim_host(card->host);
+
+ if ((card->bkops_info.cancel_delayed_work) && !from_exception) {
+ pr_debug("%s: %s: cancel_delayed_work was set, exit\n",
+ mmc_hostname(card->host), __func__);
+ card->bkops_info.cancel_delayed_work = false;
+ goto out;
+ }
+
+ if (mmc_card_doing_bkops(card)) {
+ pr_debug("%s: %s: already doing bkops, exit\n",
+ mmc_hostname(card->host), __func__);
+ goto out;
+ }
+
err = mmc_read_bkops_status(card);
if (err) {
pr_err("%s: Failed to read bkops status: %d\n",
mmc_hostname(card->host), err);
- return;
+ goto out;
}
if (!card->ext_csd.raw_bkops_status)
- return;
+ goto out;
+ pr_info("%s: %s: card->ext_csd.raw_bkops_status = 0x%x\n",
+ mmc_hostname(card->host), __func__,
+ card->ext_csd.raw_bkops_status);
+
+ /*
+ * If the function was called due to exception but there is no need
+ * for urgent BKOPS, BKOPs will be performed by the delayed BKOPs
+ * work, before going to suspend
+ */
if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
from_exception)
- return;
+ goto out;
- mmc_claim_host(card->host);
if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
timeout = MMC_BKOPS_MAX_TIMEOUT;
use_busy_signal = true;
@@ -336,13 +391,108 @@
* bkops executed synchronously, otherwise
* the operation is in progress
*/
- if (!use_busy_signal)
+ if (!use_busy_signal) {
mmc_card_set_doing_bkops(card);
+ pr_debug("%s: %s: starting the polling thread\n",
+ mmc_hostname(card->host), __func__);
+ queue_work(system_nrt_wq,
+ &card->bkops_info.poll_for_completion);
+ }
+
out:
mmc_release_host(card->host);
}
EXPORT_SYMBOL(mmc_start_bkops);
+/**
+ * mmc_bkops_completion_polling() - Poll on the card status to
+ * wait for the non-blocking BKOPS completion
+ * @work: The completion polling work
+ *
+ * The on-going reading of the card status will prevent the card
+ * from getting into suspend while it is in the middle of
+ * performing BKOPS.
+ * Since the non blocking BKOPS can be interrupted by a fetched
+ * request we also check IF mmc_card_doing_bkops in each
+ * iteration.
+ */
+void mmc_bkops_completion_polling(struct work_struct *work)
+{
+ struct mmc_card *card = container_of(work, struct mmc_card,
+ bkops_info.poll_for_completion);
+ unsigned long timeout_jiffies = jiffies +
+ msecs_to_jiffies(BKOPS_COMPLETION_POLLING_TIMEOUT_MS);
+ u32 status;
+ int err;
+
+ /*
+ * Wait for the BKOPs to complete. Keep reading the status to prevent
+ * the host from getting into suspend
+ */
+ do {
+ mmc_claim_host(card->host);
+
+ if (!mmc_card_doing_bkops(card))
+ goto out;
+
+ err = mmc_send_status(card, &status);
+ if (err) {
+ pr_err("%s: error %d requesting status\n",
+ mmc_hostname(card->host), err);
+ goto out;
+ }
+
+ /*
+ * Some cards mishandle the status bits, so make sure to check
+ * both the busy indication and the card state.
+ */
+ if ((status & R1_READY_FOR_DATA) &&
+ (R1_CURRENT_STATE(status) != R1_STATE_PRG)) {
+ pr_debug("%s: %s: completed BKOPs, exit polling\n",
+ mmc_hostname(card->host), __func__);
+ mmc_card_clr_doing_bkops(card);
+ card->bkops_info.started_delayed_bkops = false;
+ goto out;
+ }
+
+ mmc_release_host(card->host);
+
+ /*
+ * Sleep before checking the card status again to allow the
+ * card to complete the BKOPs operation
+ */
+ msleep(BKOPS_COMPLETION_POLLING_INTERVAL_MS);
+ } while (time_before(jiffies, timeout_jiffies));
+
+ pr_err("%s: %s: exit polling due to timeout\n",
+ mmc_hostname(card->host), __func__);
+
+ return;
+out:
+ mmc_release_host(card->host);
+}
+
+/**
+ * mmc_start_idle_time_bkops() - check if a non urgent BKOPS is
+ * needed
+ * @work: The idle time BKOPS work
+ */
+void mmc_start_idle_time_bkops(struct work_struct *work)
+{
+ struct mmc_card *card = container_of(work, struct mmc_card,
+ bkops_info.dw.work);
+
+ /*
+ * Prevent a race condition between mmc_stop_bkops and the delayed
+ * BKOPS work in case the delayed work is executed on another CPU
+ */
+ if (card->bkops_info.cancel_delayed_work)
+ return;
+
+ mmc_start_bkops(card, false);
+}
+EXPORT_SYMBOL(mmc_start_idle_time_bkops);
+
static void mmc_wait_done(struct mmc_request *mrq)
{
complete(&mrq->completion);
@@ -599,6 +749,19 @@
int err = 0;
BUG_ON(!card);
+
+ mmc_claim_host(card->host);
+
+ /*
+ * Notify the delayed work to be cancelled, in case it was already
+ * removed from the queue, but was not started yet
+ */
+ card->bkops_info.cancel_delayed_work = true;
+ if (delayed_work_pending(&card->bkops_info.dw))
+ cancel_delayed_work_sync(&card->bkops_info.dw);
+ if (!mmc_card_doing_bkops(card))
+ goto out;
+
err = mmc_interrupt_hpi(card);
/*
@@ -610,6 +773,8 @@
err = 0;
}
+out:
+ mmc_release_host(card->host);
return err;
}
EXPORT_SYMBOL(mmc_stop_bkops);
@@ -2615,15 +2780,13 @@
switch (mode) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
- if (host->card && mmc_card_mmc(host->card) &&
- mmc_card_doing_bkops(host->card)) {
+ if (host->card && mmc_card_mmc(host->card)) {
err = mmc_stop_bkops(host->card);
if (err) {
pr_err("%s: didn't stop bkops\n",
mmc_hostname(host));
return err;
}
- mmc_card_clr_doing_bkops(host->card);
}
spin_lock_irqsave(&host->lock, flags);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 2653744..457db7f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1315,6 +1315,28 @@
if (!card->wr_pack_stats.packing_events)
goto free_card;
}
+
+ if (card->ext_csd.bkops_en) {
+ INIT_DELAYED_WORK(&card->bkops_info.dw,
+ mmc_start_idle_time_bkops);
+ INIT_WORK(&card->bkops_info.poll_for_completion,
+ mmc_bkops_completion_polling);
+
+ /*
+ * Calculate the time to start the BKOPs checking.
+ * The idle time of the host controller should be taken
+ * into account in order to prevent a race condition
+ * before starting BKOPs and going into suspend.
+ * If the host controller didn't set its idle time,
+ * a default value is used.
+ */
+ card->bkops_info.delay_ms = MMC_IDLE_BKOPS_TIME_MS;
+ if (card->bkops_info.host_suspend_tout_ms)
+ card->bkops_info.delay_ms = min(
+ card->bkops_info.delay_ms,
+ card->bkops_info.host_suspend_tout_ms/2);
+
+ }
}
if (!oldcard)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 357d290..4e92dd7 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -4145,25 +4145,35 @@
.hw_reset = msmsdcc_hw_reset,
};
+static void msmsdcc_enable_status_gpio(struct msmsdcc_host *host)
+{
+ unsigned int gpio_no = host->plat->status_gpio;
+ int status;
+
+ if (!gpio_is_valid(gpio_no))
+ return;
+
+ status = gpio_request(gpio_no, "SD_HW_Detect");
+ if (status)
+ pr_err("%s: %s: gpio_request(%d) failed\n",
+ mmc_hostname(host->mmc), __func__, gpio_no);
+}
+
+static void msmsdcc_disable_status_gpio(struct msmsdcc_host *host)
+{
+ if (gpio_is_valid(host->plat->status_gpio))
+ gpio_free(host->plat->status_gpio);
+}
+
static unsigned int
msmsdcc_slot_status(struct msmsdcc_host *host)
{
int status;
- unsigned int gpio_no = host->plat->status_gpio;
- status = gpio_request(gpio_no, "SD_HW_Detect");
- if (status) {
- pr_err("%s: %s: Failed to request GPIO %d\n",
- mmc_hostname(host->mmc), __func__, gpio_no);
- } else {
- status = gpio_direction_input(gpio_no);
- if (!status) {
- status = gpio_get_value_cansleep(gpio_no);
- if (host->plat->is_status_gpio_active_low)
- status = !status;
- }
- gpio_free(gpio_no);
- }
+ status = gpio_get_value_cansleep(host->plat->status_gpio);
+ if (host->plat->is_status_gpio_active_low)
+ status = !status;
+
return status;
}
@@ -5825,6 +5835,7 @@
MMC_CAP_SET_XPC_180);
mmc->caps2 |= MMC_CAP2_PACKED_WR;
+ 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;
@@ -5911,11 +5922,12 @@
plat->wpswitch_gpio = -ENOENT;
if (plat->status || gpio_is_valid(plat->status_gpio)) {
- if (plat->status)
+ if (plat->status) {
host->oldstat = plat->status(mmc_dev(host->mmc));
- else
+ } else {
+ msmsdcc_enable_status_gpio(host);
host->oldstat = msmsdcc_slot_status(host);
-
+ }
host->eject = !host->oldstat;
}
@@ -6098,6 +6110,7 @@
if (plat->status_irq)
free_irq(plat->status_irq, host);
+ msmsdcc_disable_status_gpio(host);
sdiowakeup_irq_free:
wake_lock_destroy(&host->sdio_suspend_wlock);
if (plat->sdiowakeup_irq)
@@ -6194,6 +6207,7 @@
if (plat->status_irq)
free_irq(plat->status_irq, host);
+ msmsdcc_disable_status_gpio(host);
wake_lock_destroy(&host->sdio_suspend_wlock);
if (plat->sdiowakeup_irq) {
@@ -6522,8 +6536,10 @@
rc = 0;
goto out;
}
- if (host->plat->status_irq)
+ if (host->plat->status_irq) {
disable_irq(host->plat->status_irq);
+ msmsdcc_disable_status_gpio(host);
+ }
if (!pm_runtime_suspended(dev))
rc = msmsdcc_runtime_suspend(dev);
@@ -6579,6 +6595,7 @@
host->pending_resume = true;
if (host->plat->status_irq) {
+ msmsdcc_enable_status_gpio(host);
msmsdcc_check_status((unsigned long)host);
enable_irq(host->plat->status_irq);
}
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 8809abe..ebe3ad06 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -439,7 +439,7 @@
int i, pwm_size, rc = 0;
int burst_size = SPMI_MAX_BUF_LEN;
int list_len = lut->list_len << 1;
- int offset = lut->lo_index << 2;
+ int offset = lut->lo_index << 1;
pwm_size = QPNP_GET_PWM_SIZE(
chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) &
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 5bbcc84..25febff 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1828,19 +1828,6 @@
if (virt_addr != NULL)
bam->props.virt_addr = virt_addr;
- if ((bam_props->manage & SPS_BAM_MGR_DEVICE_REMOTE) != 0 &&
- (bam_props->manage & SPS_BAM_MGR_MULTI_EE) != 0 &&
- bam_props->ee == 0) {
- /*
- * BAM global is owned by a remote processor, so force EE index
- * to a non-zero value to insure EE zero globals are not
- * modified.
- */
- SPS_DBG2("sps:Setting EE for BAM %x to non-zero",
- bam_props->phys_addr);
- bam->props.ee = 1;
- }
-
ok = sps_bam_device_init(bam);
mutex_unlock(&bam->lock);
if (ok) {
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index a9b0dbb..23903df 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -640,6 +640,26 @@
raw->last_good_ocv_raw -= MBG_TRANSIENT_ERROR_RAW;
}
+#define SEL_ALT_OREG_BIT BIT(2)
+static int ocv_ir_compensation(struct pm8921_bms_chip *chip, int ocv)
+{
+ int compensated_ocv;
+ int ibatt_ua;
+ int rbatt_mohm = chip->default_rbatt_mohm + chip->rconn_mohm;
+
+ pm_bms_masked_write(chip, BMS_TEST1,
+ SEL_ALT_OREG_BIT, SEL_ALT_OREG_BIT);
+
+ /* since the SEL_ALT_OREG_BIT is set this will give us VSENSE_OCV */
+ pm8921_bms_get_battery_current(&ibatt_ua);
+ compensated_ocv = ocv + div_s64((s64)ibatt_ua * rbatt_mohm, 1000);
+ pr_debug("comp ocv = %d, ocv = %d, ibatt_ua = %d, rbatt_mohm = %d\n",
+ compensated_ocv, ocv, ibatt_ua, rbatt_mohm);
+
+ pm_bms_masked_write(chip, BMS_TEST1, SEL_ALT_OREG_BIT, 0);
+ return compensated_ocv;
+}
+
static int read_soc_params_raw(struct pm8921_bms_chip *chip,
struct pm8921_soc_params *raw)
{
@@ -662,6 +682,8 @@
adjust_pon_ocv_raw(chip, raw);
convert_vbatt_raw_to_uv(chip, usb_chg,
raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
+ raw->last_good_ocv_uv = ocv_ir_compensation(chip,
+ raw->last_good_ocv_uv);
chip->last_ocv_uv = raw->last_good_ocv_uv;
pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
} else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
@@ -1012,7 +1034,7 @@
* samples with the the shutdown_iavg_ua
*/
if (firsttime && chip->shutdown_iavg_ua != 0) {
- pr_emerg("Using shutdown_iavg_ua = %d in all samples\n",
+ pr_debug("Using shutdown_iavg_ua = %d in all samples\n",
chip->shutdown_iavg_ua);
for (i = 0; i < IAVG_SAMPLES; i++)
iavg_samples[i] = chip->shutdown_iavg_ua;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 19454ca..b4080df 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -2621,6 +2621,11 @@
pr_debug("USB charger active\n");
pm_chg_iusbmax_get(chip, &usb_ma);
+ if (usb_ma == 500 && !usb_target_ma) {
+ pr_debug("Stopping Unplug Check Worker USB == 500mA\n");
+ disable_input_voltage_regulation(chip);
+ return;
+ }
if (usb_ma <= 100) {
pr_debug(
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a3f6e58..b2709d2 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1021,6 +1021,9 @@
dev_vdbg(dwc->dev, "queing request %p to %s length %d\n",
request, ep->name, request->length);
+ WARN(!dep->direction && (request->length % ep->desc->wMaxPacketSize),
+ "trying to queue unaligned request (%d)\n", request->length);
+
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_queue(dep, req);
spin_unlock_irqrestore(&dwc->lock, flags);
diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c
index 108caf9..0353848 100644
--- a/drivers/usb/gadget/f_accessory.c
+++ b/drivers/usb/gadget/f_accessory.c
@@ -40,7 +40,7 @@
#define BULK_BUFFER_SIZE 16384
#define ACC_STRING_SIZE 256
-#define PROTOCOL_VERSION 1
+#define PROTOCOL_VERSION 2
/* String IDs */
#define INTERFACE_STRING_INDEX 0
@@ -78,6 +78,8 @@
/* set to 1 if we have a pending start request */
int start_requested;
+ int audio_mode;
+
/* synchronize access to our device file */
atomic_t open_excl;
@@ -510,6 +512,8 @@
break;
case ACCESSORY_IS_START_REQUESTED:
return dev->start_requested;
+ case ACCESSORY_GET_AUDIO_MODE:
+ return dev->audio_mode;
}
if (!src)
return -EINVAL;
@@ -586,6 +590,10 @@
cdev->gadget->ep0->driver_data = dev;
cdev->req->complete = acc_complete_set_string;
value = w_length;
+ } else if (b_request == ACCESSORY_SET_AUDIO_MODE &&
+ w_index == 0 && w_length == 0) {
+ dev->audio_mode = w_value;
+ value = 0;
}
} else if (b_requestType == (USB_DIR_IN | USB_TYPE_VENDOR)) {
if (b_request == ACCESSORY_GET_PROTOCOL) {
@@ -600,6 +608,7 @@
memset(dev->uri, 0, sizeof(dev->uri));
memset(dev->serial, 0, sizeof(dev->serial));
dev->start_requested = 0;
+ dev->audio_mode = 0;
}
}
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index 96790c5..ccbc330 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -463,6 +463,10 @@
if (count > MTP_BULK_BUFFER_SIZE)
return -EINVAL;
+ if (!IS_ALIGNED(count, dev->ep_out->maxpacket))
+ DBG(cdev, "%s - count(%d) not multiple of mtu(%d)\n", __func__,
+ count, dev->ep_out->maxpacket);
+
/* we will block until we're online */
DBG(cdev, "mtp_read: waiting for online state\n");
ret = wait_event_interruptible(dev->read_wq,
@@ -484,7 +488,7 @@
requeue_req:
/* queue a request */
req = dev->rx_req[0];
- req->length = count;
+ req->length = MTP_BULK_BUFFER_SIZE;
dev->rx_done = 0;
ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL);
if (ret < 0) {
@@ -751,6 +755,9 @@
count = dev->xfer_file_length;
DBG(cdev, "receive_file_work(%lld)\n", count);
+ if (!IS_ALIGNED(count, dev->ep_out->maxpacket))
+ DBG(cdev, "%s- count(%lld) not multiple of mtu(%d)\n", __func__,
+ count, dev->ep_out->maxpacket);
while (count > 0 || write_req) {
if (count > 0) {
@@ -758,8 +765,9 @@
read_req = dev->rx_req[cur_buf];
cur_buf = (cur_buf + 1) % RX_REQ_MAX;
- read_req->length = (count > MTP_BULK_BUFFER_SIZE
- ? MTP_BULK_BUFFER_SIZE : count);
+ /* some h/w expects size to be aligned to ep's MTU */
+ read_req->length = MTP_BULK_BUFFER_SIZE;
+
dev->rx_done = 0;
ret = usb_ep_queue(dev->ep_out, read_req, GFP_KERNEL);
if (ret < 0) {
@@ -795,6 +803,10 @@
usb_ep_dequeue(dev->ep_out, read_req);
break;
}
+ /* Check if we aligned the size due to MTU constraint */
+ if (count < read_req->length)
+ read_req->actual = (read_req->actual > count ?
+ count : read_req->actual);
/* if xfer_file_length is 0xFFFFFFFF, then we read until
* we get a zero length packet
*/
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 813fc94..f27e0eb 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -2041,6 +2041,8 @@
udelay(20);
break;
case SNPS_28NM_INTEGRATED_PHY:
+ /* disable DP and DM pull down resistors */
+ ulpi_write(phy, 0x6, 0xC);
/* Clear charger detecting control bits */
ulpi_write(phy, 0x1F, 0x86);
/* Clear alt interrupt latch and enable bits */
@@ -2120,8 +2122,7 @@
switch (motg->chg_state) {
case USB_CHG_STATE_UNDEFINED:
msm_chg_block_on(motg);
- if (motg->pdata->enable_dcd)
- msm_chg_enable_dcd(motg);
+ msm_chg_enable_dcd(motg);
msm_chg_enable_aca_det(motg);
motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
motg->dcd_retries = 0;
@@ -2148,12 +2149,10 @@
break;
}
}
- if (motg->pdata->enable_dcd)
- is_dcd = msm_chg_check_dcd(motg);
+ is_dcd = msm_chg_check_dcd(motg);
tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
if (is_dcd || tmout) {
- if (motg->pdata->enable_dcd)
- msm_chg_disable_dcd(motg);
+ msm_chg_disable_dcd(motg);
msm_chg_enable_primary_det(motg);
delay = MSM_CHG_PRIMARY_DET_TIME;
motg->chg_state = USB_CHG_STATE_DCD_DONE;
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 2188704..6faf3e7 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1989,7 +1989,8 @@
if (s_pipe->pipe_type == OVERLAY_TYPE_VIDEO &&
((s_pipe->op_mode & MDP4_OP_SCALEY_EN) ||
(s_pipe->op_mode & MDP4_OP_SCALEX_EN)) &&
- !(s_pipe->op_mode & MDP4_OP_SCALEY_PIXEL_RPT))
+ !(s_pipe->op_mode & (MDP4_OP_SCALEX_PIXEL_RPT |
+ MDP4_OP_SCALEY_PIXEL_RPT)))
alpha_drop = 1;
d_pipe = mdp4_background_layer(mixer, s_pipe);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 6bb86c2..257bcc0 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -229,6 +229,48 @@
#define MMC_BLK_DATA_AREA_GP (1<<2)
};
+/**
+ * struct mmc_bkops_info - BKOPS data
+ * @dw: Idle time bkops delayed work
+ * @host_suspend_tout_ms: The host controller idle time,
+ * before getting into suspend
+ * @delay_ms: The time to start the BKOPS
+ * delayed work once MMC thread is idle
+ * @poll_for_completion: Poll on BKOPS completion
+ * @cancel_delayed_work: A flag to indicate if the delayed work
+ * should be cancelled
+ * @started_delayed_bkops: A flag to indicate if the delayed
+ * work was scheduled
+ * @sectors_changed: number of sectors written or
+ * discard since the last idle BKOPS were scheduled
+ */
+struct mmc_bkops_info {
+ struct delayed_work dw;
+ unsigned int host_suspend_tout_ms;
+ unsigned int delay_ms;
+/*
+ * A default time for checking the need for non urgent BKOPS once mmcqd
+ * is idle.
+ */
+#define MMC_IDLE_BKOPS_TIME_MS 2000
+ struct work_struct poll_for_completion;
+/* Polling timeout and interval for waiting on non-blocking BKOPs completion */
+#define BKOPS_COMPLETION_POLLING_TIMEOUT_MS 10000 /* in ms */
+#define BKOPS_COMPLETION_POLLING_INTERVAL_MS 1000 /* in ms */
+ bool cancel_delayed_work;
+ bool started_delayed_bkops;
+ unsigned int sectors_changed;
+/*
+ * Since canceling the delayed work might have significant effect on the
+ * performance of small requests we won't queue the delayed work every time
+ * mmcqd thread is idle.
+ * The delayed work for idle BKOPS will be scheduled only after a significant
+ * amount of write or discard data.
+ * 100MB is chosen based on benchmark tests.
+ */
+#define BKOPS_MIN_SECTORS_TO_QUEUE_DELAYED_WORK 204800 /* 100MB */
+};
+
/*
* MMC device
*/
@@ -304,6 +346,8 @@
unsigned int nr_parts;
struct mmc_wr_pack_stats wr_pack_stats; /* packed commands stats*/
+
+ struct mmc_bkops_info bkops_info;
};
/*
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 3f26a80..2795734 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -149,6 +149,9 @@
extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
struct mmc_command *, int);
extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
+extern void mmc_start_delayed_bkops(struct mmc_card *card);
+extern void mmc_start_idle_time_bkops(struct work_struct *work);
+extern void mmc_bkops_completion_polling(struct work_struct *work);
extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool);
extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 62b8a73..6912087 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -46,6 +46,13 @@
#define KGSL_MEMTYPE_MULTISAMPLE 20
#define KGSL_MEMTYPE_KERNEL 255
+/*
+ * Alignment hint, passed as the power of 2 exponent.
+ * i.e 4k (2^12) would be 12, 64k (2^16)would be 16.
+ */
+#define KGSL_MEMALIGN_MASK 0x00FF0000
+#define KGSL_MEMALIGN_SHIFT 16
+
/* generic flag values */
#define KGSL_FLAGS_NORMALMODE 0x00000000
#define KGSL_FLAGS_SAFEMODE 0x00000001
diff --git a/include/linux/usb/f_accessory.h b/include/linux/usb/f_accessory.h
index 5b2dcf9..ddb2fd0 100644
--- a/include/linux/usb/f_accessory.h
+++ b/include/linux/usb/f_accessory.h
@@ -36,13 +36,15 @@
#define ACCESSORY_STRING_URI 4
#define ACCESSORY_STRING_SERIAL 5
-/* Control request for retrieving device's protocol version (currently 1)
+/* Control request for retrieving device's protocol version
*
* requestType: USB_DIR_IN | USB_TYPE_VENDOR
* request: ACCESSORY_GET_PROTOCOL
* value: 0
* index: 0
* data version number (16 bits little endian)
+ * 1 for original accessory support
+ * 2 adds device to host audio support
*/
#define ACCESSORY_GET_PROTOCOL 51
@@ -70,6 +72,17 @@
*/
#define ACCESSORY_START 53
+/* Control request for setting the audio mode.
+ *
+ * requestType: USB_DIR_OUT | USB_TYPE_VENDOR
+ * request: ACCESSORY_SET_AUDIO_MODE
+ * value: 0 - no audio
+ * 1 - device to host, 44100 16-bit stereo PCM
+ * index: 0
+ * data none
+ */
+#define ACCESSORY_SET_AUDIO_MODE 58
+
/* ioctls for retrieving strings set by the host */
#define ACCESSORY_GET_STRING_MANUFACTURER _IOW('M', 1, char[256])
#define ACCESSORY_GET_STRING_MODEL _IOW('M', 2, char[256])
@@ -79,5 +92,7 @@
#define ACCESSORY_GET_STRING_SERIAL _IOW('M', 6, char[256])
/* returns 1 if there is a start request pending */
#define ACCESSORY_IS_START_REQUESTED _IO('M', 7)
+/* returns audio mode (set via the ACCESSORY_SET_AUDIO_MODE control request) */
+#define ACCESSORY_GET_AUDIO_MODE _IO('M', 8)
#endif /* __LINUX_USB_F_ACCESSORY_H */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 920cf77..d45889c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -192,9 +192,6 @@
* @mhl_enable: indicates MHL connector or not.
* @disable_reset_on_disconnect: perform USB PHY and LINK reset
* on USB cable disconnection.
- * @enable_dcd: Enable Data Contact Detection circuit. if not set
- * wait for 600msec before proceeding to primary
- * detection.
* @enable_lpm_on_suspend: Enable the USB core to go into Low
* Power Mode, when USB bus is suspended but cable
* is connected.
@@ -216,7 +213,6 @@
unsigned int mpm_otgsessvld_int;
bool mhl_enable;
bool disable_reset_on_disconnect;
- bool enable_dcd;
bool enable_lpm_on_dev_suspend;
bool core_clk_always_on_workaround;
struct msm_bus_scale_pdata *bus_scale_table;
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index b2a538c..dd39124 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -41,6 +41,22 @@
#define VCAP_BASE (dev->vcapbase)
#define VCAP_OFFSET(off) (VCAP_BASE + off)
+struct reg_range {
+ u32 min_val;
+ u32 max_val;
+};
+
+#define VCAP_REG_RANGE_1_MIN 0x0
+#define VCAP_REG_RANGE_1_MAX 0x48
+#define VCAP_REG_RANGE_2_MIN 0x100
+#define VCAP_REG_RANGE_2_MAX 0x104
+#define VCAP_REG_RANGE_3_MIN 0x400
+#define VCAP_REG_RANGE_3_MAX 0x7F0
+#define VCAP_REG_RANGE_4_MIN 0x800
+#define VCAP_REG_RANGE_4_MAX 0x8A0
+#define VCAP_REG_RANGE_5_MIN 0xC00
+#define VCAP_REG_RANGE_5_MAX 0xDF0
+
#define VCAP_SW_RESET_REQ (VCAP_BASE + 0x024)
#define VCAP_SW_RESET_STATUS (VCAP_BASE + 0x028)
@@ -128,6 +144,16 @@
struct vcap_client_data *cd;
};
+struct vcap_debugfs_params {
+ atomic_t vc_drop_count;
+ uint32_t vc_timestamp;
+ uint32_t vp_timestamp;
+ uint32_t vp_ewma;/* Exponential moving average */
+ uint32_t clk_rate;
+ uint32_t bw_request;
+ uint32_t reg_addr;
+};
+
struct vcap_dev {
struct v4l2_device v4l2_dev;
@@ -176,6 +202,7 @@
struct nr_param nr_param;
bool nr_update;
+ struct vcap_debugfs_params dbg_p;
};
struct vp_format_data {
diff --git a/include/net/scm.h b/include/net/scm.h
index d456f4c..0c0017c 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -71,9 +71,11 @@
}
static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
- struct scm_cookie *scm)
+ struct scm_cookie *scm, bool forcecreds)
{
memset(scm, 0, sizeof(*scm));
+ if (forcecreds)
+ scm_set_cred(scm, task_tgid(current), current_cred());
unix_get_peersec_dgram(sock, scm);
if (msg->msg_controllen <= 0)
return 0;
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 90872c9..afbe7e0 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1170,6 +1170,7 @@
#define MPEG4_MULTI_AAC 0x00010D86
#define US_POINT_EPOS_FORMAT 0x00012310
#define US_RAW_FORMAT 0x0001127C
+#define US_PROX_FORMAT 0x00012721
#define MULTI_CHANNEL_PCM 0x00010C66
#define ASM_ENCDEC_SBCRATE 0x00010C13
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index faa48f7..59debb7 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1329,7 +1329,7 @@
if (NULL == siocb->scm)
siocb->scm = &scm;
- err = scm_send(sock, msg, siocb->scm);
+ err = scm_send(sock, msg, siocb->scm, true);
if (err < 0)
return err;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d510353..109e30b 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1446,7 +1446,7 @@
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
wait_for_unix_gc();
- err = scm_send(sock, msg, siocb->scm);
+ err = scm_send(sock, msg, siocb->scm, false);
if (err < 0)
return err;
@@ -1607,7 +1607,7 @@
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
wait_for_unix_gc();
- err = scm_send(sock, msg, siocb->scm);
+ err = scm_send(sock, msg, siocb->scm, false);
if (err < 0)
return err;
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index b303878..e9e950f 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -41,6 +41,7 @@
#define ADC_DMIC_SEL_ADC 0
#define ADC_DMIC_SEL_DMIC 1
+#define NUM_AMIC 3
#define NUM_DECIMATORS 4
#define NUM_INTERPOLATORS 3
#define BITS_PER_REG 8
@@ -4860,6 +4861,7 @@
u8 flag = pdata->amic_settings.use_pdata;
u8 i = 0, j = 0;
u8 val_txfe = 0, value = 0;
+ int amic_reg_count = 0;
if (!pdata) {
rc = -ENODEV;
@@ -4905,7 +4907,8 @@
snd_soc_update_bits(codec, SITAR_A_MICB_2_CTL, 0x10,
(pdata->micbias.bias2_cap_mode << 4));
- for (i = 0; i < 6; j++, i += 2) {
+ amic_reg_count = (NUM_AMIC % 2) ? NUM_AMIC + 1 : NUM_AMIC;
+ for (i = 0; i < amic_reg_count; j++, i += 2) {
if (flag & (0x01 << i)) {
value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index e8bb652..a0a272f 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -778,6 +778,9 @@
struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
u32 rate = taiko->comp_fs[w->shift];
+ pr_debug("%s: %s event %d enabled = %d", __func__, w->name,
+ event, taiko->comp_enabled[w->shift]);
+
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (taiko->comp_enabled[w->shift] != 0) {
@@ -3123,7 +3126,7 @@
{"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
{"SPK PA", NULL, "SPK DAC"},
- {"SPK DAC", NULL, "RX7 MIX1"},
+ {"SPK DAC", NULL, "RX7 MIX2"},
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
@@ -4297,13 +4300,17 @@
taiko_spk_dac_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX7 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER_E("RX2 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_MIXER_E("RX7 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+ SND_SOC_DAPM_MIXER_E("RX3 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
@@ -4315,14 +4322,10 @@
SND_SOC_DAPM_MIXER_E("RX6 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_MIXER_E("RX7 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
+ SND_SOC_DAPM_MIXER_E("RX7 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_MIXER("RX3 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
-
SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0,
&rx4_dsm_mux, taiko_codec_enable_interpolator,
SND_SOC_DAPM_PRE_PMU),
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 16a4aaa..dc8d9e6 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -270,9 +270,9 @@
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "SLIMBUS0 Hostless Capture",
@@ -280,9 +280,9 @@
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.ops = &msm_fe_dai_ops,
.name = "SLIMBUS0_HOSTLESS",
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index 86a82e2..c046b63 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -106,9 +106,13 @@
break;
case OCMEM_ALLOC_GROW:
audio_ocmem_lcl.buf = data;
+ pr_debug("%s: Alloc grow request received buf->addr: 0x%ld\n",
+ __func__,
+ (audio_ocmem_lcl.buf)->addr);
atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_GROW);
break;
case OCMEM_ALLOC_SHRINK:
+ pr_debug("%s: Alloc shrink request received\n", __func__);
atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_SHRINK);
break;
default:
@@ -150,11 +154,14 @@
audio_ocmem_lcl.buf = buf;
atomic_set(&audio_ocmem_lcl.audio_exit, 0);
+ atomic_set(&audio_ocmem_lcl.audio_cond, 1);
+ pr_debug("%s: buf->len: %ld\n", __func__, buf->len);
if (!buf->len) {
+ pr_debug("%s: buf.len is 0, waiting for ocmem region\n",
+ __func__);
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
(atomic_read(&audio_ocmem_lcl.audio_cond) == 0) ||
(atomic_read(&audio_ocmem_lcl.audio_exit) == 1));
-
if (atomic_read(&audio_ocmem_lcl.audio_exit)) {
pr_err("%s: audio playback ended while waiting for ocmem\n",
__func__);
@@ -162,6 +169,7 @@
goto fail_cmd;
}
}
+ pr_debug("%s: buf->len: %ld\n", __func__, (audio_ocmem_lcl.buf)->len);
if (audio_ocmem_lcl.lp_memseg_ptr == NULL) {
/* Retrieve low power segments */
ret = core_get_low_power_segments(
@@ -190,19 +198,28 @@
/* vote for ocmem bus bandwidth */
ret = msm_bus_scale_client_update_request(
audio_ocmem_lcl.audio_ocmem_bus_client,
- 0);
+ 1);
if (ret)
pr_err("%s: failed to vote for bus bandwidth\n", __func__);
atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_TRANSITION);
+ pr_debug("%s: buf->addr: 0x%ld, len: %ld, audio_state[0x%x]\n",
+ __func__,
+ audio_ocmem_lcl.buf->addr,
+ audio_ocmem_lcl.buf->len,
+ atomic_read(&audio_ocmem_lcl.audio_state));
+
+ atomic_set(&audio_ocmem_lcl.audio_cond, 1);
ret = ocmem_map(cid, audio_ocmem_lcl.buf, &audio_ocmem_lcl.mlist);
if (ret) {
pr_err("%s: ocmem_map failed\n", __func__);
goto fail_cmd;
}
-
+ pr_debug("%s: audio_cond[%d] audio_state[0x%x]\n", __func__,
+ atomic_read(&audio_ocmem_lcl.audio_cond),
+ atomic_read(&audio_ocmem_lcl.audio_state));
while ((atomic_read(&audio_ocmem_lcl.audio_state) !=
OCMEM_STATE_EXIT)) {
@@ -219,6 +236,8 @@
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
break;
case OCMEM_STATE_SHRINK:
+ pr_debug("%s: ocmem shrink request process\n",
+ __func__);
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
ret = ocmem_unmap(cid, audio_ocmem_lcl.buf,
&audio_ocmem_lcl.mlist);
@@ -242,9 +261,11 @@
atomic_read(&audio_ocmem_lcl.audio_state));
goto fail_cmd;
}
-
+ atomic_set(&audio_ocmem_lcl.audio_cond, 1);
break;
case OCMEM_STATE_GROW:
+ pr_debug("%s: ocmem grow request process\n",
+ __func__);
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
ret = ocmem_map(cid, audio_ocmem_lcl.buf,
&audio_ocmem_lcl.mlist);
@@ -260,6 +281,7 @@
atomic_read(&audio_ocmem_lcl.audio_cond) == 0);
atomic_set(&audio_ocmem_lcl.audio_state,
OCMEM_STATE_MAP_COMPL);
+ atomic_set(&audio_ocmem_lcl.audio_cond, 1);
break;
}
}
@@ -280,8 +302,10 @@
{
int ret;
+ pr_debug("%s: disable\n", __func__);
if (atomic_read(&audio_ocmem_lcl.audio_cond))
atomic_set(&audio_ocmem_lcl.audio_cond, 0);
+
pr_debug("%s: audio_cond[0x%x], audio_state[0x%x]\n", __func__,
atomic_read(&audio_ocmem_lcl.audio_cond),
atomic_read(&audio_ocmem_lcl.audio_state));
@@ -309,6 +333,7 @@
atomic_read(&audio_ocmem_lcl.audio_state));
goto fail_cmd;
}
+ atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_EXIT);
pr_debug("%s: ocmem_free success\n", __func__);
default:
pr_debug("%s: state=%d", __func__,
@@ -316,6 +341,9 @@
break;
}
+ msm_bus_scale_client_update_request(
+ audio_ocmem_lcl.audio_ocmem_bus_client,
+ 0);
return 0;
fail_cmd:
return ret;
@@ -345,6 +373,7 @@
rc = -EINVAL;
}
+ return;
}
/**
* voice_ocmem_process_req() - disable/enable OCMEM during voice call
@@ -441,6 +470,7 @@
rc = -EINVAL;
}
+ return;
}
/**
@@ -484,86 +514,21 @@
static int audio_ocmem_platform_data_populate(struct platform_device *pdev)
{
- int ret;
- struct msm_bus_scale_pdata *audio_ocmem_bus_scale_pdata = NULL;
- struct msm_bus_vectors *audio_ocmem_bus_vectors = NULL;
- struct msm_bus_paths *ocmem_audio_bus_paths = NULL;
- u32 val;
+ struct msm_bus_scale_pdata *audio_ocmem_adata = NULL;
if (!pdev->dev.of_node) {
pr_err("%s: device tree information missing\n", __func__);
return -ENODEV;
}
-
- audio_ocmem_bus_vectors = kzalloc(sizeof(struct msm_bus_vectors),
- GFP_KERNEL);
- if (!audio_ocmem_bus_vectors) {
- dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
- return -ENOMEM;
+ audio_ocmem_adata = msm_bus_cl_get_pdata(pdev);
+ if (!audio_ocmem_adata) {
+ pr_err("%s: bus device tree allocation failed\n", __func__);
+ return -EINVAL;
}
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,msm-ocmem-audio-src-id", &val);
- if (ret) {
- dev_err(&pdev->dev, "%s: qcom,msm-ocmem-audio-src-id missing in DT node\n",
- __func__);
- goto fail1;
- }
- audio_ocmem_bus_vectors->src = val;
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,msm-ocmem-audio-dst-id", &val);
- if (ret) {
- dev_err(&pdev->dev, "%s: qcom,msm-ocmem-audio-dst-id missing in DT node\n",
- __func__);
- goto fail1;
- }
- audio_ocmem_bus_vectors->dst = val;
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,msm-ocmem-audio-ab", &val);
- if (ret) {
- dev_err(&pdev->dev, "%s: qcom,msm-ocmem-audio-ab missing in DT node\n",
- __func__);
- goto fail1;
- }
- audio_ocmem_bus_vectors->ab = val;
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,msm-ocmem-audio-ib", &val);
- if (ret) {
- dev_err(&pdev->dev, "%s: qcom,msm-ocmem-audio-ib missing in DT node\n",
- __func__);
- goto fail1;
- }
- audio_ocmem_bus_vectors->ib = val;
+ dev_set_drvdata(&pdev->dev, audio_ocmem_adata);
- ocmem_audio_bus_paths = kzalloc(sizeof(struct msm_bus_paths),
- GFP_KERNEL);
- if (!ocmem_audio_bus_paths) {
- dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
- goto fail1;
- }
- ocmem_audio_bus_paths->num_paths = 1;
- ocmem_audio_bus_paths->vectors = audio_ocmem_bus_vectors;
-
- audio_ocmem_bus_scale_pdata =
- kzalloc(sizeof(struct msm_bus_scale_pdata), GFP_KERNEL);
-
- if (!audio_ocmem_bus_scale_pdata) {
- dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
- goto fail2;
- }
-
- audio_ocmem_bus_scale_pdata->usecase = ocmem_audio_bus_paths;
- audio_ocmem_bus_scale_pdata->num_usecases = 1;
- audio_ocmem_bus_scale_pdata->name = "audio-ocmem";
-
- dev_set_drvdata(&pdev->dev, audio_ocmem_bus_scale_pdata);
- return ret;
-
-fail2:
- kfree(ocmem_audio_bus_paths);
-fail1:
- kfree(audio_ocmem_bus_vectors);
- return ret;
+ return 0;
}
static int ocmem_audio_client_probe(struct platform_device *pdev)
{
@@ -628,9 +593,7 @@
audio_ocmem_bus_scale_pdata = (struct msm_bus_scale_pdata *)
dev_get_drvdata(&pdev->dev);
- kfree(audio_ocmem_bus_scale_pdata->usecase->vectors);
- kfree(audio_ocmem_bus_scale_pdata->usecase);
- kfree(audio_ocmem_bus_scale_pdata);
+ msm_bus_cl_clear_pdata(audio_ocmem_bus_scale_pdata);
ocmem_notifier_unregister(audio_ocmem_lcl.audio_hdl,
&audio_ocmem_client_nb);
return 0;
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index bbd43f7..01a9538 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -34,6 +34,7 @@
#include "msm-compr-q6-v2.h"
#include "msm-pcm-routing-v2.h"
+#include "audio_ocmem.h"
#define COMPRE_CAPTURE_NUM_PERIODS 16
/* Allocate the worst case frame size for compressed audio */
@@ -440,6 +441,9 @@
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
prtd->pcm_irq_pos = 0;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ audio_ocmem_process_req(AUDIO, true);
+
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
switch (compr->info.codec_param.codec.id) {
case SND_AUDIOCODEC_AMRWB:
@@ -459,6 +463,9 @@
break;
case SNDRV_PCM_TRIGGER_STOP:
pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ audio_ocmem_process_req(AUDIO, false);
+
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
switch (compr->info.codec_param.codec.id) {
case SND_AUDIOCODEC_AMRWB:
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index a6cdad2..dacd59c 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -1091,7 +1091,7 @@
SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.rate_min = 8000,
.rate_max = 48000,
},
@@ -1106,7 +1106,7 @@
SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.rate_min = 8000,
.rate_max = 48000,
},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 7483bb6..af1e19c 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -56,7 +56,7 @@
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 4,
.buffer_bytes_max = CAPTURE_NUM_PERIODS * CAPTURE_PERIOD_SIZE,
.period_bytes_min = CAPTURE_PERIOD_SIZE,
.period_bytes_max = CAPTURE_PERIOD_SIZE,
@@ -297,7 +297,6 @@
static int msm_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
struct msm_audio *prtd;
int ret = 0;
@@ -315,36 +314,14 @@
kfree(prtd);
return -ENOMEM;
}
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- runtime->hw = msm_pcm_hardware_playback;
- ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
- if (ret < 0) {
- pr_err("%s: pcm out open failed\n", __func__);
- q6asm_audio_client_free(prtd->audio_client);
- kfree(prtd);
- return -ENOMEM;
- }
- }
- /* Capture path */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- runtime->hw = msm_pcm_hardware_capture;
- ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
- if (ret < 0) {
- pr_err("%s: pcm in open failed\n", __func__);
- q6asm_audio_client_free(prtd->audio_client);
- kfree(prtd);
- return -ENOMEM;
- }
- }
-
- pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
-
- prtd->session_id = prtd->audio_client->session;
- msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
- prtd->session_id, substream->stream);
-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prtd->cmd_ack = 1;
+ runtime->hw = msm_pcm_hardware_playback;
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ runtime->hw = msm_pcm_hardware_capture;
+ else {
+ pr_err("Invalid Stream type %d\n", substream->stream);
+ return -EINVAL;
+ }
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
@@ -530,12 +507,15 @@
int dir = OUT;
pr_debug("%s\n", __func__);
- q6asm_cmd(prtd->audio_client, CMD_CLOSE);
- q6asm_audio_client_buf_free_contiguous(dir,
+ if (prtd->audio_client) {
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
prtd->audio_client);
+ q6asm_audio_client_free(prtd->audio_client);
+ }
+
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
- SNDRV_PCM_STREAM_CAPTURE);
- q6asm_audio_client_free(prtd->audio_client);
+ SNDRV_PCM_STREAM_CAPTURE);
kfree(prtd);
return 0;
@@ -617,13 +597,43 @@
struct snd_pcm_runtime *runtime = substream->runtime;
struct msm_audio *prtd = runtime->private_data;
struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
struct audio_buffer *buf;
int dir, ret;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
dir = IN;
- else
+ pr_debug("%s Opening %d-ch PCM Write stream\n",
+ __func__, params_channels(params));
+
+ ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
+ if (ret < 0) {
+ pr_err("%s: pcm out open failed\n", __func__);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ } else {
dir = OUT;
+ pr_debug("%s Opening %d-ch PCM read stream\n",
+ __func__, params_channels(params));
+ ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
+ if (ret < 0) {
+ pr_err("%s: pcm in open failed\n", __func__);
+ q6asm_audio_client_free(prtd->audio_client);
+ prtd->audio_client = NULL;
+ return -ENOMEM;
+ }
+ }
+
+ pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
+ prtd->session_id = prtd->audio_client->session;
+ msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+ prtd->session_id, substream->stream);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prtd->cmd_ack = 1;
+
pr_debug("%s: before buf alloc\n", __func__);
ret = q6asm_audio_client_buf_alloc_contiguous(dir,
prtd->audio_client,
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index fac55b4..0466eb6 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -470,6 +470,21 @@
} else if (channel_mode == 2) {
open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channel_mode == 3) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 4) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
+ } else if (channel_mode == 5) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_RB;
} else if (channel_mode == 6) {
open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
@@ -477,6 +492,15 @@
open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ } else if (channel_mode == 8) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+ open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
+ open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
} else {
pr_err("%s invalid num_chan %d\n", __func__,
channel_mode);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 0dd6faf..072e293 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1693,7 +1693,7 @@
enc_cfg.bits_per_sample = 16;
enc_cfg.sample_rate = rate;
enc_cfg.is_signed = 1;
- channel_mapping = enc_cfg.channel_mapping; /* ??? PHANI */
+ channel_mapping = enc_cfg.channel_mapping;
memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
@@ -1743,7 +1743,8 @@
enc_cfg.bits_per_sample = 16;
enc_cfg.sample_rate = 0;/*rate;*/
enc_cfg.is_signed = 1;
- channel_mapping = enc_cfg.channel_mapping; /* ??? PHANI */
+ channel_mapping = enc_cfg.channel_mapping;
+
memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
@@ -1778,27 +1779,36 @@
lchannel_mapping[0] = PCM_CHANNEL_FL;
lchannel_mapping[1] = PCM_CHANNEL_FR;
} else if (channels == 3) {
- lchannel_mapping[0] = PCM_CHANNEL_FC;
- lchannel_mapping[1] = PCM_CHANNEL_FL;
- lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_FC;
} else if (channels == 4) {
- lchannel_mapping[0] = PCM_CHANNEL_FC;
- lchannel_mapping[1] = PCM_CHANNEL_FL;
- lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_RB;
lchannel_mapping[3] = PCM_CHANNEL_LB;
} else if (channels == 5) {
- lchannel_mapping[0] = PCM_CHANNEL_FC;
- lchannel_mapping[1] = PCM_CHANNEL_FL;
- lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_FC;
lchannel_mapping[3] = PCM_CHANNEL_LB;
lchannel_mapping[4] = PCM_CHANNEL_RB;
} else if (channels == 6) {
- lchannel_mapping[0] = PCM_CHANNEL_FC;
- lchannel_mapping[1] = PCM_CHANNEL_FL;
- lchannel_mapping[2] = PCM_CHANNEL_FR;
- lchannel_mapping[3] = PCM_CHANNEL_LB;
- lchannel_mapping[4] = PCM_CHANNEL_RB;
- lchannel_mapping[5] = PCM_CHANNEL_LFE;
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_LFE;
+ lchannel_mapping[3] = PCM_CHANNEL_FC;
+ lchannel_mapping[4] = PCM_CHANNEL_LB;
+ lchannel_mapping[5] = PCM_CHANNEL_RB;
+ } else if (channels == 6) {
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_LFE;
+ lchannel_mapping[3] = PCM_CHANNEL_FC;
+ lchannel_mapping[4] = PCM_CHANNEL_LB;
+ lchannel_mapping[5] = PCM_CHANNEL_RB;
+ lchannel_mapping[6] = PCM_CHANNEL_FLC;
+ lchannel_mapping[7] = PCM_CHANNEL_FRC;
} else {
pr_err("%s: ERROR.unsupported num_ch = %u\n",
__func__, channels);