Merge "Merge remote-tracking branch 'kdorfman/emmc_base' into merge/kdorfman" into msm-3.0
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index 50db52c..cc94b69 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -17,7 +17,7 @@
ifeq "$(KERNEL_USE_OF)" "y"
KERNEL_ZIMG = $(KERNEL_OUT)/arch/arm/boot/zImage
DTB_FILE = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH).dtb
-DTS_FILE = $(KERNEL_OUT)/../../../../../../kernel/arch/arm/boot/dts/$(MSM_ARCH).dts
+DTS_FILE = $(TOP)/kernel/arch/arm/boot/dts/$(MSM_ARCH).dts
FULL_KERNEL = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH)-zImage
DTC = $(KERNEL_OUT)/scripts/dtc/dtc
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index 4fb653e..084050e 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -24,13 +24,13 @@
Example:
- qcom,sdcc@F9600000 {
+ qcom,sdcc@f9600000 {
/* SDC1 used as eMMC slot */
cell-index = <1>;
compatible = "qcom,msm-sdcc";
- reg = <0xF9600000 0x800 // SDCC register interface
- 0xF9600800 0x1800 // DML register interface
- 0xF9602000 0x2000> // BAM register interface
+ reg = <0xf9600000 0x800 // SDCC register interface
+ 0xf9600800 0x1800 // DML register interface
+ 0xf9602000 0x2000> // BAM register interface
interrupts = <123>;
qcom,sdcc-clk-rates = <400000 24000000 48000000>;
diff --git a/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt b/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
new file mode 100644
index 0000000..8cc3c54
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
@@ -0,0 +1,32 @@
+Qualcomm SPMI Controller (PMIC Arbiter)
+
+Required properties:
+- cell-index : the bus identifier.
+- compatible : should be "qcom,spmi-pmic-arb".
+- reg : offset and length of the PMIC Arbiter Core register map.
+- reg : offset and length of the PMIC Arbiter Interrupt controller register map.
+- interrupts : the PMIC Arbiter interrupt.
+- qcom,pmic-arb-ee : the execution environment (EE) identifier.
+- qcom,pmic-arb-channel : the assigned channel number for channel registers.
+- qcom,pmic-arb-ppid-map : an array used to map a 12-bit PPID to 8-bit APID.
+
+Peripherals on the SPMI bus are identified with a 12-bit identifier (PPID)
+which is composed of a 4-bit slave address and an 8-bit peripheral identifier.
+The PMIC Arbiter hardware uses an 8-bit APID (Arbiter Peripheral Identifier)
+internally. Software needs the mapping between the APID and the PPID.
+Up to a maximum of 256 peripherals are supported and the mapping is target
+specific.
+
+Example:
+
+ qcom,spmi@fc4c0000 {
+ cell-index = <0>;
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0xfc4cf000 0x1000>,
+ <0Xfc4cb000 0x1000>;
+ interrupts = <0>;
+ qcom,pmic-arb-ee = <0>;
+ qcom,pmic-arb-channel = <0>;
+ qcom,pmic-arb-ppid-map = <0x130 0x00>, /* PPID 0x130, APID 0 */
+ <0x131 0x01>; /* PPID 0x131, APID 1 */
+ };
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index c1399ae..95ddf34 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -35,16 +35,16 @@
- qcom,hsusb-otg-pmic-id-irq: ID, routed to PMIC IRQ number
Example HSUSB OTG controller device node :
- usb@F9690000 {
+ usb@f9690000 {
compatible = "qcom,hsusb-otg";
- reg = <0xF9690000 0x400>;
+ reg = <0xf9690000 0x400>;
interrupts = <134>;
qcom,hsusb-otg-phy-type = <2>;
qcom,hsusb-otg-mode = <1>;
qcom,hsusb-otg-otg-control = <1>;
qcom,hsusb-otg-default-mode = <2>;
- qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xFFFFFFFF>;
+ qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xffffffff>;
qcom,hsusb-otg-power-budget = <500>;
qcom,hsusb-otg-pclk-src-name = "dfab_usb_clk";
qcom,hsusb-otg-pmic-id-irq = <47>
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index 57ad77a..725971d 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -27,15 +27,15 @@
interrupts = <1 2 0>;
};
- serial@F991F000 {
+ serial@f991f000 {
compatible = "qcom,msm-lsuart-v14";
- reg = <0xF991F000 0x1000>;
+ reg = <0xf991f000 0x1000>;
interrupts = <0 109 0>;
};
- usb@F9A55000 {
+ usb@f9a55000 {
compatible = "qcom,hsusb-otg";
- reg = <0xF9A55000 0x400>;
+ reg = <0xf9a55000 0x400>;
interrupts = <0 134 0>;
qcom,hsusb-otg-phy-type = <2>;
@@ -43,10 +43,10 @@
qcom,hsusb-otg-otg-control = <1>;
};
- qcom,sdcc@F980B000 {
+ qcom,sdcc@f980b000 {
cell-index = <1>;
compatible = "qcom,msm-sdcc";
- reg = <0xF980B000 0x1000>;
+ reg = <0xf980b000 0x1000>;
interrupts = <0 123 0>;
qcom,sdcc-clk-rates = <400000 24000000 48000000>;
@@ -56,10 +56,10 @@
qcom,sdcc-disable_cmd23;
};
- qcom,sdcc@F984B000 {
+ qcom,sdcc@f984b000 {
cell-index = <3>;
compatible = "qcom,msm-sdcc";
- reg = <0xF984B000 0x1000>;
+ reg = <0xf984b000 0x1000>;
interrupts = <0 127 0>;
qcom,sdcc-clk-rates = <400000 24000000 48000000>;
@@ -68,10 +68,10 @@
qcom,sdcc-disable_cmd23;
};
- qcom,sps@F9980000 {
+ qcom,sps@f9980000 {
compatible = "qcom,msm_sps";
- reg = <0xF9984000 0x15000>,
- <0xF9999000 0xB000>;
+ reg = <0xf9984000 0x15000>,
+ <0xf9999000 0xb000>;
interrupts = <0 94 0>;
qcom,bam-dma-res-pipes = <6>;
@@ -83,4 +83,104 @@
interrupts = <96>;
spi-max-frequency = <24000000>;
};
+
+ qcom,spmi@fc4c0000 {
+ cell-index = <0>;
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0xfc4cf000 0x1000>,
+ <0Xfc4cb000 0x1000>;
+ /* 190,ee0_krait_hlos_spmi_periph_irq */
+ /* 187,channel_0_krait_hlos_trans_done_irq */
+ interrupts = <0 190 0 0 187 0>;
+ qcom,pmic-arb-ee = <0>;
+ qcom,pmic-arb-channel = <0>;
+ qcom,pmic-arb-ppid-map = <0x130 0x00>, /* PM8941_LDO1 */
+ <0x131 0x01>, /* PM8941_LDO2 */
+ <0x132 0x02>, /* PM8941_LDO3 */
+ <0x133 0x03>, /* PM8941_LDO4 */
+ <0x134 0x04>, /* PM8941_LDO5 */
+ <0x135 0x05>, /* PM8941_LDO6 */
+ <0x136 0x06>, /* PM8941_LDO7 */
+ <0x137 0x07>, /* PM8941_LDO8 */
+ <0x138 0x08>, /* PM8941_LDO9 */
+ <0x139 0x09>, /* PM8941_LDO10 */
+ <0x13a 0x0a>, /* PM8941_LDO11 */
+ <0x13b 0x0b>, /* PM8941_LDO12 */
+ <0x13c 0x0c>, /* PM8941_LDO13 */
+ <0x13d 0x0d>, /* PM8941_LDO14 */
+ <0x13e 0x0e>, /* PM8941_LDO15 */
+ <0x13f 0x0f>, /* PM8941_LDO16 */
+ <0x140 0x10>, /* PM8941_LDO17 */
+ <0x141 0x11>, /* PM8941_LDO18 */
+ <0x142 0x12>, /* PM8941_LDO19 */
+ <0x143 0x13>, /* PM8941_LDO20 */
+ <0x144 0x14>, /* PM8941_LDO21 */
+ <0x145 0x15>, /* PM8941_LDO22 */
+ <0x146 0x16>, /* PM8941_LDO23 */
+ <0x147 0x17>, /* PM8941_LDO24 */
+ <0x148 0x18>, /* PM8941_LDO25 */
+ <0x149 0x19>, /* PM8941_LDO26 */
+ <0x0c0 0x1a>, /* PM8941_GPIO1 */
+ <0x0c1 0x1b>, /* PM8941_GPIO2 */
+ <0x0c2 0x1c>, /* PM8941_GPIO3 */
+ <0x0c3 0x1d>, /* PM8941_GPIO4 */
+ <0x0c4 0x1e>, /* PM8941_GPIO5 */
+ <0x0c5 0x1f>, /* PM8941_GPIO6 */
+ <0x0c6 0x20>, /* PM8941_GPIO7 */
+ <0x0c7 0x21>, /* PM8941_GPIO8 */
+ <0x0c8 0x22>, /* PM8941_GPIO9 */
+ <0x0c9 0x23>, /* PM8941_GPIO10 */
+ <0x0ca 0x24>, /* PM8941_GPIO11 */
+ <0x0cb 0x25>, /* PM8941_GPIO12 */
+ <0x0cc 0x26>, /* PM8941_GPIO13 */
+ <0x0cd 0x27>, /* PM8941_GPIO14 */
+ <0x0ce 0x28>, /* PM8941_GPIO15 */
+ <0x0cf 0x29>, /* PM8941_GPIO16 */
+ <0x0d0 0x2a>, /* PM8941_GPIO17 */
+ <0x0d1 0x2b>, /* PM8941_GPIO18 */
+ <0x0d2 0x2c>, /* PM8941_GPIO19 */
+ <0x0d3 0x2d>, /* PM8941_GPIO20 */
+ <0x0d4 0x2e>, /* PM8941_GPIO21 */
+ <0x0d5 0x2f>, /* PM8941_GPIO22 */
+ <0x0d6 0x30>, /* PM8941_GPIO23 */
+ <0x0d7 0x31>, /* PM8941_GPIO24 */
+ <0x0d8 0x32>, /* PM8941_GPIO25 */
+ <0x0d9 0x33>, /* PM8941_GPIO26 */
+ <0x0da 0x34>, /* PM8941_GPIO27 */
+ <0x0db 0x35>, /* PM8941_GPIO28 */
+ <0x0dc 0x36>, /* PM8941_GPIO29 */
+ <0x0dd 0x37>, /* PM8941_GPIO30 */
+ <0x0de 0x38>, /* PM8941_GPIO31 */
+ <0x0df 0x39>, /* PM8941_GPIO32 */
+ <0x0e0 0x3a>, /* PM8941_GPIO33 */
+ <0x0e1 0x3b>, /* PM8941_GPIO34 */
+ <0x0e2 0x3c>, /* PM8941_GPIO35 */
+ <0x0e3 0x3d>, /* PM8941_GPIO36 */
+ <0x028 0x3e>, /* COINCELL */
+ <0x005 0x3f>, /* INTERRUPT */
+ <0x001 0x40>, /* PM8941_0 */
+ <0x201 0x41>, /* PM8841_0 */
+ <0x101 0x42>, /* PM8941_1 */
+ <0x301 0x43>, /* PM8841_1 */
+ <0x008 0x44>, /* PON0 */
+ <0x208 0x45>, /* PON1 */
+ <0x110 0x46>, /* PM8941_SMPS1 */
+ <0x111 0x47>, /* PM8941_SMPS2 */
+ <0x112 0x48>, /* PM8941_SMPS3 */
+ <0x310 0x49>, /* PM8841_SMPS1 */
+ <0x311 0x4a>, /* PM8841_SMPS2 */
+ <0x312 0x4b>, /* PM8841_SMPS3 */
+ <0x313 0x4c>, /* PM8841_SMPS4 */
+ <0x314 0x4d>, /* PM8841_SMPS5 */
+ <0x315 0x4e>, /* PM8841_SMPS6 */
+ <0x316 0x4f>, /* PM8841_SMPS7 */
+ <0x317 0x50>, /* PM8841_SMPS8 */
+ <0x050 0x51>, /* SHARED_XO */
+ <0x051 0x52>, /* BB_CLK1 */
+ <0x052 0x53>, /* BB_CLK2 */
+ <0x059 0x54>, /* SLEEP_CLK */
+ <0x010 0x55>, /* SMBC_OVP */
+ <0x011 0x56>, /* SMBC_CHG */
+ <0x012 0x57>; /* SMBC_BIF */
+ };
};
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index a708fbc..9672d2c 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -37,10 +37,8 @@
CONFIG_CPU_HAS_L2_PMU=y
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
-# CONFIG_MSM_DALRPC is not set
# CONFIG_MSM_HW3D is not set
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
-# CONFIG_MSM_JTAG_V7 is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -94,6 +92,8 @@
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_DCC_TTY=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
CONFIG_POWER_SUPPLY=y
@@ -168,3 +168,11 @@
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_SMD_DEBUG=y
+CONFIG_MSM_SMD_TTY=y
+CONFIG_MSM_N_WAY_SMD=y
+CONFIG_MSM_N_WAY_SMSM=y
+CONFIG_MSM_SMD_LOGGING=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 3c87f8d..446423d 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -26,6 +26,7 @@
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM7X27=y
+CONFIG_ARCH_MSM8625=y
CONFIG_MSM_SOC_REV_A=y
# CONFIG_MACH_MSM7X27_SURF is not set
# CONFIG_MACH_MSM7X27_FFA is not set
@@ -44,14 +45,15 @@
# CONFIG_MSM_HW3D is not set
CONFIG_MSM7X27A_AUDIO=y
CONFIG_MSM_DMA_TEST=y
-# CONFIG_MSM_JTAG_V7 is not set
CONFIG_MSM_SLEEP_STATS_DEVICE=y
CONFIG_BT_MSM_PINTEST=y
CONFIG_MSM_RPC_VIBRATOR=y
CONFIG_PM8XXX_RPC_VIBRATOR=y
+CONFIG_MSM_SPM_V2=y
CONFIG_ARM_THUMBEE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
@@ -231,6 +233,7 @@
# CONFIG_MT9T013 is not set
# CONFIG_MT9D112 is not set
CONFIG_OV5640=y
+CONFIG_OV5647=y
CONFIG_WEBCAM_OV7692_QRD=y
CONFIG_WEBCAM_OV9726=y
# CONFIG_MT9P012 is not set
@@ -254,6 +257,7 @@
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
+CONFIG_SND_MSM_SOC=y
CONFIG_HID_APPLE=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index cc33b8f..642d843 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -26,6 +26,7 @@
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM7X27=y
+CONFIG_ARCH_MSM8625=y
CONFIG_MSM_SOC_REV_A=y
# CONFIG_MACH_MSM7X27_SURF is not set
# CONFIG_MACH_MSM7X27_FFA is not set
@@ -49,9 +50,11 @@
CONFIG_BT_MSM_PINTEST=y
CONFIG_MSM_RPC_VIBRATOR=y
CONFIG_PM8XXX_RPC_VIBRATOR=y
+CONFIG_MSM_SPM_V2=y
CONFIG_ARM_THUMBEE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
@@ -349,3 +352,4 @@
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRC_CCITT=y
+CONFIG_OV5647=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index b71df28..b3a45d2 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -326,6 +326,7 @@
CONFIG_USB_VIDEO_CLASS=y
CONFIG_WEBCAM_OV9726=y
CONFIG_MT9E013=y
+CONFIG_IMX074=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 9fd7e71..1f511bb 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -326,6 +326,7 @@
CONFIG_USB_VIDEO_CLASS=y
CONFIG_WEBCAM_OV9726=y
CONFIG_MT9E013=y
+CONFIG_IMX074=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 95dd09c..f1b1fa5 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -1,4 +1,5 @@
CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-perf"
CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
@@ -52,6 +53,8 @@
CONFIG_MACH_APQ8064_CDP=y
CONFIG_MACH_APQ8064_MTP=y
CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_HRD=y
+CONFIG_MACH_MPQ8064_DTV=y
# CONFIG_MSM_STACKED_MEMORY is not set
CONFIG_KERNEL_PMEM_EBI_REGION=y
# CONFIG_MSM_FIQ_SUPPORT is not set
@@ -311,6 +314,9 @@
CONFIG_MSM_CAMERA_FLASH_SC628A=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
+CONFIG_IMX074=y
+CONFIG_IMX074_ACT=y
+CONFIG_OV2720=y
CONFIG_S5K3L1YX=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_IRIS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 3a70b22..e58b94b 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -52,6 +52,8 @@
CONFIG_MACH_APQ8064_CDP=y
CONFIG_MACH_APQ8064_MTP=y
CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_HRD=y
+CONFIG_MACH_MPQ8064_DTV=y
# CONFIG_MSM_STACKED_MEMORY is not set
CONFIG_KERNEL_PMEM_EBI_REGION=y
# CONFIG_MSM_FIQ_SUPPORT is not set
@@ -82,6 +84,8 @@
CONFIG_MSM_QDSS=y
CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE=y
CONFIG_MSM_SLEEP_STATS=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -312,6 +316,9 @@
CONFIG_MSM_CAMERA_FLASH_SC628A=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
+CONFIG_IMX074=y
+CONFIG_IMX074_ACT=y
+CONFIG_OV2720=y
CONFIG_S5K3L1YX=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_IRIS=y
@@ -433,13 +440,13 @@
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
-CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_LIST=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 543a4f9f..7ba17e6 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -142,7 +142,6 @@
CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
-CONFIG_CFG80211=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -162,7 +161,7 @@
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_NETDEVICES=y
-CONFIG_HOSTAP=y
+CONFIG_ATH6K_LEGACY=y
# CONFIG_MSM_RMNET is not set
CONFIG_MSM_RMNET_BAM=y
# CONFIG_INPUT_MOUSEDEV is not set
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index c3b841a..d2434e6 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -54,79 +54,46 @@
* consider why they can't support the logging.
*/
+#define __raw_write_logged(v, a, _t) ({ \
+ int _ret; \
+ void *_addr = (void *)(a); \
+ _ret = uncached_logk(LOGK_WRITEL, _addr); \
+ ETB_WAYPOINT; \
+ __raw_write##_t##_no_log((v), _addr); \
+ if (_ret) \
+ LOG_BARRIER; \
+ })
+
+
#define __raw_writeb_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v))
#define __raw_writew_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
#define __raw_writel_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))
-#define __raw_writeb(v, a) ({ \
- int _ret; \
- void *_addr = (void *)(a); \
- _ret = uncached_logk(LOGK_WRITEL, _addr); \
- ETB_WAYPOINT; \
- __raw_writeb_no_log(v, _addr); \
- if (_ret) \
- LOG_BARRIER; \
- })
-#define __raw_writew(v, a) ({ \
- int _ret; \
- void *_addr = (void *)(a); \
- _ret = uncached_logk(LOGK_WRITEL, _addr); \
- ETB_WAYPOINT; \
- __raw_writew_no_log(v, _addr); \
- if (_ret) \
- LOG_BARRIER; \
- })
-
-#define __raw_writel(v, a) ({ \
- int _ret; \
- void *_addr = (void *)(a); \
- _ret = uncached_logk(LOGK_WRITEL, _addr); \
- ETB_WAYPOINT; \
- __raw_writel_no_log(v, _addr); \
- if (_ret) \
- LOG_BARRIER; \
- })
+#define __raw_writeb(v, a) __raw_write_logged((v), (a), b)
+#define __raw_writew(v, a) __raw_write_logged((v), (a), w)
+#define __raw_writel(v, a) __raw_write_logged((v), (a), l)
#define __raw_readb_no_log(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a))
#define __raw_readw_no_log(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
#define __raw_readl_no_log(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a))
-#define __raw_readb(a) ({ \
- unsigned char __a; \
+#define __raw_read_logged(a, _l, _t) ({ \
+ unsigned _t __a; \
void *_addr = (void *)(a); \
int _ret; \
_ret = uncached_logk(LOGK_READL, _addr); \
ETB_WAYPOINT; \
- __a = __raw_readb_no_log(_addr);\
+ __a = __raw_read##_l##_no_log(_addr);\
if (_ret) \
LOG_BARRIER; \
__a; \
})
-#define __raw_readw(a) ({ \
- unsigned short __a; \
- void *_addr = (void *)(a); \
- int _ret; \
- _ret = uncached_logk(LOGK_READL, _addr); \
- ETB_WAYPOINT; \
- __a = __raw_readw_no_log(_addr);\
- if (_ret) \
- LOG_BARRIER; \
- __a; \
- })
-#define __raw_readl(a) ({ \
- unsigned int __a; \
- void *_addr = (void *)(a); \
- int _ret; \
- _ret = uncached_logk(LOGK_READL, _addr); \
- ETB_WAYPOINT; \
- __a = __raw_readl_no_log(_addr);\
- if (_ret) \
- LOG_BARRIER; \
- __a; \
- })
+#define __raw_readb(a) __raw_read_logged((a), b, char)
+#define __raw_readw(a) __raw_read_logged((a), w, short)
+#define __raw_readl(a) __raw_read_logged((a), l, int)
/*
* Architecture ioremap implementation.
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0b0f733..18fbcf6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -747,6 +747,18 @@
help
Support for the Qualcomm APQ8064 LIQUID device.
+config MACH_MPQ8064_HRD
+ depends on ARCH_APQ8064
+ bool "MPQ8064 HRD"
+ help
+ Support for the Qualcomm MPQ8064 HRD device.
+
+config MACH_MPQ8064_DTV
+ depends on ARCH_APQ8064
+ bool "MPQ8064 DTV"
+ help
+ Support for the Qualcomm MPQ8064 DTV device.
+
config MACH_FSM9XXX_SURF
depends on ARCH_FSM9XXX
depends on !MSM_STACKED_MEMORY
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index b2f7c84d..8347a25 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -38,7 +38,12 @@
obj-$(CONFIG_MSM_SOC_REV_NONE) += acpuclock-8x50.o
endif
-obj-$(CONFIG_SMP) += headsmp.o platsmp.o
+obj-$(CONFIG_SMP) += headsmp.o
+ifdef CONFIG_ARCH_MSM8625
+ obj-$(CONFIG_SMP) += platsmp-8625.o
+else
+ obj-$(CONFIG_SMP) += platsmp.o
+endif
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_MSM_CPU_AVS) += avs.o
@@ -88,12 +93,14 @@
ifndef CONFIG_ARCH_APQ8064
ifndef CONFIG_ARCH_MSM8960
ifndef CONFIG_ARCH_MSM8X60
+ifndef CONFIG_ARCH_MSMCOPPER
obj-$(CONFIG_MSM_SMD) += pmic.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += rpc_hsusb.o rpc_pmapp.o rpc_fsusb.o
endif
endif
endif
endif
+endif
ifndef CONFIG_ARCH_MSM8960
ifndef CONFIG_ARCH_MSM8X60
ifndef CONFIG_ARCH_APQ8064
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 6140559..5a21407 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -187,7 +187,7 @@
{ 0, 61440, ACPU_PLL_1, 1, 3, 7680, 3, 1, 61440 },
{ 1, 122880, ACPU_PLL_1, 1, 1, 15360, 3, 2, 61440 },
{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3, 61440 },
- { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
@@ -217,7 +217,7 @@
{ 0, 61440, ACPU_PLL_1, 1, 3, 7680, 3, 1, 61440 },
{ 1, 122880, ACPU_PLL_1, 1, 1, 15360, 3, 2, 61440 },
{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3, 61440 },
- { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
@@ -232,7 +232,7 @@
{ 0, 65536, ACPU_PLL_1, 1, 3, 8192, 3, 1, 49152 },
{ 1, 98304, ACPU_PLL_1, 1, 1, 12288, 3, 2, 49152 },
{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 3, 98304 },
- { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
@@ -247,7 +247,7 @@
{ 0, 61440, ACPU_PLL_1, 1, 3, 7680, 3, 1, 61440 },
{ 1, 122880, ACPU_PLL_1, 1, 1, 15360, 3, 2, 61440 },
{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3, 61440 },
- { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 0, 400000, ACPU_PLL_2, 2, 2, 50000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
@@ -261,7 +261,7 @@
{ 0, 61440, ACPU_PLL_1, 1, 11, 7680, 3, 1, 61440 },
{ 1, 122880, ACPU_PLL_1, 1, 5, 15360, 3, 2, 61440 },
{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3, 61440 },
- { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
@@ -291,7 +291,7 @@
{ 0, 61440, ACPU_PLL_1, 1, 11, 7680, 3, 1, 61440 },
{ 1, 122880, ACPU_PLL_1, 1, 5, 15360, 3, 2, 61440 },
{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3, 61440 },
- { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
@@ -300,13 +300,13 @@
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
-/* 7x27aa PLL4 @ 1008MHz with CDMA capable modem */
+/* 7627aa PLL4 @ 1008MHz with CDMA capable modem */
static struct clkctl_acpu_speed pll0_960_pll1_589_pll2_1200_pll4_1008[] = {
{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
{ 0, 65536, ACPU_PLL_1, 1, 8, 8192, 3, 1, 49152 },
{ 1, 98304, ACPU_PLL_1, 1, 5, 12288, 3, 2, 49152 },
{ 1, 196608, ACPU_PLL_1, 1, 2, 24576, 3, 3, 98304 },
- { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
@@ -315,13 +315,13 @@
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
-/* 7x25a PLL2 @ 1200MHz with GSM capable modem */
+/* 7625a PLL2 @ 1200MHz with GSM capable modem */
static struct clkctl_acpu_speed pll0_960_pll1_737_pll2_1200_25a[] = {
{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
{ 0, 61440, ACPU_PLL_1, 1, 11, 7680, 3, 1, 61440 },
{ 1, 122880, ACPU_PLL_1, 1, 5, 15360, 3, 2, 61440 },
{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3, 61440 },
- { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 122880 },
{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
{ 0, 400000, ACPU_PLL_2, 2, 2, 50000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
@@ -757,7 +757,7 @@
res = clk_set_rate(drv_state.ebi1_clk, speed->axiclk_khz * 1000);
if (res < 0)
pr_warning("Setting AXI min rate failed (%d)\n", res);
- res = clk_enable(drv_state.ebi1_clk);
+ res = clk_prepare_enable(drv_state.ebi1_clk);
if (res < 0)
pr_warning("Enabling AXI clock failed (%d)\n", res);
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 470e836..99c3d78 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -148,10 +148,10 @@
.vreg[VREG_DIG] = { "krait0_dig", 1150000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+ .vreg[VREG_HFPLL_A] = { "hfpll0_s8", 2100000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll0_l23", 1800000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8921_L23 },
},
@@ -160,16 +160,16 @@
.aux_clk_sel = MSM_ACC1_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
.vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+ .vreg[VREG_HFPLL_A] = { "hfpll1_s8", 2100000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll1_l23", 1800000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_L23 },
},
@@ -177,10 +177,10 @@
.hfpll_base = MSM_HFPLL_BASE + 0x400,
.aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
.l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+ .vreg[VREG_HFPLL_A] = { "hfpll_l2_s8", 2100000,
RPM_VREG_VOTER6,
RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll_l2_l23", 1800000,
RPM_VREG_VOTER6,
RPM_VREG_ID_PM8921_L23 },
},
@@ -201,7 +201,7 @@
.vreg[VREG_DIG] = { "krait0_dig", 1150000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8921_LVS7 },
},
@@ -210,13 +210,13 @@
.aux_clk_sel = MSM_ACC1_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
.vreg[VREG_CORE] = { "krait1", 1150000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_LVS7 },
},
@@ -225,13 +225,13 @@
.aux_clk_sel = MSM_ACC2_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
.vreg[VREG_CORE] = { "krait2", 1150000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
+ .vreg[VREG_MEM] = { "krait2_mem", 1150000,
RPM_VREG_VOTER4,
RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
+ .vreg[VREG_DIG] = { "krait2_dig", 1150000,
RPM_VREG_VOTER4,
RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll2", 1800000,
RPM_VREG_VOTER4,
RPM_VREG_ID_PM8921_LVS7 },
},
@@ -240,13 +240,13 @@
.aux_clk_sel = MSM_ACC3_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
.vreg[VREG_CORE] = { "krait3", 1150000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
+ .vreg[VREG_MEM] = { "krait3_mem", 1150000,
RPM_VREG_VOTER5,
RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
+ .vreg[VREG_DIG] = { "krait3_dig", 1150000,
RPM_VREG_VOTER5,
RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll3", 1800000,
RPM_VREG_VOTER5,
RPM_VREG_ID_PM8921_LVS7 },
},
@@ -254,7 +254,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x300,
.aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
.l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
RPM_VREG_VOTER6,
RPM_VREG_ID_PM8921_LVS7 },
},
@@ -272,7 +272,7 @@
.vreg[VREG_DIG] = { "krait0_dig", 1150000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8038_S1 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8038_L23 },
},
@@ -281,13 +281,13 @@
.aux_clk_sel = MSM_ACC1_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
.vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8038_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8038_S1 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8038_L23 },
},
@@ -295,7 +295,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x400,
.aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
.l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
RPM_VREG_VOTER6,
RPM_VREG_ID_PM8038_L23 },
},
@@ -314,7 +314,7 @@
.vreg[VREG_DIG] = { "krait0_dig", 1150000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8038_S1 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8038_L23 },
},
@@ -323,13 +323,13 @@
.aux_clk_sel = MSM_ACC1_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
.vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8038_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8038_S1 },
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8038_L23 },
},
@@ -337,7 +337,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x400,
.aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
.l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+ .vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
RPM_VREG_VOTER6,
RPM_VREG_ID_PM8038_L23 },
},
@@ -922,8 +922,8 @@
sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
sc->vreg[VREG_MEM].max_vdd, 0);
if (rc) {
- pr_err("%s: vdd_mem (cpu%d) increase failed (%d)\n",
- __func__, cpu, rc);
+ pr_err("%s increase failed (%d)\n",
+ sc->vreg[VREG_MEM].name, rc);
return rc;
}
sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
@@ -935,8 +935,8 @@
sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
sc->vreg[VREG_DIG].max_vdd, 0);
if (rc) {
- pr_err("%s: vdd_dig (cpu%d) increase failed (%d)\n",
- __func__, cpu, rc);
+ pr_err("%s increase failed (%d)\n",
+ sc->vreg[VREG_DIG].name, rc);
return rc;
}
sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
@@ -953,8 +953,8 @@
rc = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
sc->vreg[VREG_CORE].max_vdd);
if (rc) {
- pr_err("%s: vdd_core (cpu%d) increase failed (%d)\n",
- __func__, cpu, rc);
+ pr_err("%s increase failed (%d)\n",
+ sc->vreg[VREG_CORE].name, rc);
return rc;
}
sc->vreg[VREG_CORE].cur_vdd = vdd_core;
@@ -980,8 +980,8 @@
ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
sc->vreg[VREG_CORE].max_vdd);
if (ret) {
- pr_err("%s: vdd_core (cpu%d) decrease failed (%d)\n",
- __func__, cpu, ret);
+ pr_err("%s decrease failed (%d)\n",
+ sc->vreg[VREG_CORE].name, ret);
return;
}
sc->vreg[VREG_CORE].cur_vdd = vdd_core;
@@ -993,8 +993,8 @@
sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
sc->vreg[VREG_DIG].max_vdd, 0);
if (ret) {
- pr_err("%s: vdd_dig (cpu%d) decrease failed (%d)\n",
- __func__, cpu, ret);
+ pr_err("%s decrease failed (%d)\n",
+ sc->vreg[VREG_DIG].name, ret);
return;
}
sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
@@ -1009,8 +1009,8 @@
sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
sc->vreg[VREG_MEM].max_vdd, 0);
if (ret) {
- pr_err("%s: vdd_mem (cpu%d) decrease failed (%d)\n",
- __func__, cpu, ret);
+ pr_err("%s decrease failed (%d)\n",
+ sc->vreg[VREG_MEM].name, ret);
return;
}
sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
@@ -1147,7 +1147,7 @@
pr_debug("Initializing HFPLL%d\n", sc - scalable);
/* Disable the PLL for re-programming. */
- hfpll_disable(sc, 0);
+ hfpll_disable(sc, 1);
/* Configure PLL parameters for integer mode. */
writel_relaxed(0x7845C665, sc->hfpll_base + HFPLL_CONFIG_CTL);
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index f1abde4..7e5e2f8 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -208,7 +208,7 @@
static struct delayed_work ul_timeout_work;
static int ul_packet_written;
static atomic_t ul_ondemand_vote = ATOMIC_INIT(0);
-static struct clk *dfab_clk;
+static struct clk *dfab_clk, *xo_clk;
static DEFINE_RWLOCK(ul_wakeup_lock);
static DECLARE_WORK(kickoff_ul_wakeup, kickoff_ul_wakeup_func);
static int bam_connection_is_active;
@@ -671,7 +671,7 @@
skb = info->skb;
kfree(info);
hdr = (struct bam_mux_hdr *)skb->data;
- DBG_INC_WRITE_CNT(skb->data_len);
+ DBG_INC_WRITE_CNT(skb->len);
event_data = (unsigned long)(skb);
spin_lock_irqsave(&bam_ch[hdr->ch_id].lock, flags);
bam_ch[hdr->ch_id].num_tx_pkts--;
@@ -1194,11 +1194,15 @@
int i = 0;
i += scnprintf(buf + i, max - i,
+ "skb read cnt: %u\n"
+ "skb write cnt: %u\n"
"skb copy cnt: %u\n"
"skb copy bytes: %u\n"
"sps tx failures: %u\n"
"sps tx stalls: %u\n"
"rx queue len: %d\n",
+ bam_dmux_read_cnt,
+ bam_dmux_write_cnt,
bam_dmux_write_cpy_cnt,
bam_dmux_write_cpy_bytes,
bam_dmux_tx_sps_failure_cnt,
@@ -1686,6 +1690,9 @@
rc = clk_prepare_enable(dfab_clk);
if (rc)
DMUX_LOG_KERR("bam_dmux vote for dfab failed rc = %d\n", rc);
+ rc = clk_prepare_enable(xo_clk);
+ if (rc)
+ DMUX_LOG_KERR("bam_dmux vote for xo failed rc = %d\n", rc);
dfab_is_on = 1;
mutex_unlock(&dfab_status_lock);
}
@@ -1701,6 +1708,7 @@
return;
}
clk_disable_unprepare(dfab_clk);
+ clk_disable_unprepare(xo_clk);
dfab_is_on = 0;
mutex_unlock(&dfab_status_lock);
}
@@ -2095,6 +2103,11 @@
if (bam_mux_initialized)
return 0;
+ xo_clk = clk_get(&pdev->dev, "xo");
+ if (IS_ERR(xo_clk)) {
+ pr_err("%s: did not get xo clock\n", __func__);
+ return PTR_ERR(xo_clk);
+ }
dfab_clk = clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(dfab_clk)) {
pr_err("%s: did not get dfab clock\n", __func__);
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index cd84722..73221b5 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -41,8 +41,8 @@
},
{
- .func = GPIOMUX_FUNC_1, /*active 3*/
- .drv = GPIOMUX_DRV_8MA,
+ .func = GPIOMUX_FUNC_2, /*active 3*/
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_NONE,
},
@@ -76,6 +76,27 @@
.pull = GPIOMUX_PULL_KEEPER,
},
+ {
+ .func = GPIOMUX_FUNC_9, /*active 9*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+ {
+ .func = GPIOMUX_FUNC_A, /*active 10*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+ {
+ .func = GPIOMUX_FUNC_6, /*active 11*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+ {
+ .func = GPIOMUX_FUNC_4, /*active 12*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
};
@@ -83,7 +104,7 @@
{
.gpio = 2,
.settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_ACTIVE] = &cam_settings[12],
[GPIOMUX_SUSPENDED] = &cam_settings[0],
},
},
@@ -97,7 +118,7 @@
{
.gpio = 4,
.settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
[GPIOMUX_SUSPENDED] = &cam_settings[0],
},
},
@@ -109,7 +130,7 @@
},
},
{
- .gpio = 76,
+ .gpio = 34,
.settings = {
[GPIOMUX_ACTIVE] = &cam_settings[2],
[GPIOMUX_SUSPENDED] = &cam_settings[0],
@@ -122,39 +143,39 @@
[GPIOMUX_SUSPENDED] = &cam_settings[0],
},
},
-};
-
-static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
{
.gpio = 10,
.settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_ACTIVE] = &cam_settings[9],
[GPIOMUX_SUSPENDED] = &cam_settings[8],
},
},
{
.gpio = 11,
.settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_ACTIVE] = &cam_settings[10],
[GPIOMUX_SUSPENDED] = &cam_settings[8],
},
},
{
.gpio = 12,
.settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_ACTIVE] = &cam_settings[11],
[GPIOMUX_SUSPENDED] = &cam_settings[8],
},
},
{
.gpio = 13,
.settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_ACTIVE] = &cam_settings[11],
[GPIOMUX_SUSPENDED] = &cam_settings[8],
},
},
};
+static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
+};
+
#ifdef CONFIG_MSM_CAMERA
static struct msm_bus_vectors cam_init_vectors[] = {
@@ -310,27 +331,34 @@
},
};
-static struct camera_vreg_t msm_8064_back_cam_vreg[] = {
- {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+static struct camera_vreg_t apq_8064_back_cam_vreg[] = {
{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+ {"cam_vio", REG_VS, 0, 0, 0},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
};
+static struct camera_vreg_t apq_8064_front_cam_vreg[] = {
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+ {"cam_vio", REG_VS, 0, 0, 0},
+ {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+ {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
+#define CAML_RSTN PM8921_GPIO_PM_TO_SYS(28)
+#define CAMR_RSTN 34
+
static struct gpio apq8064_common_cam_gpio[] = {
- {5, GPIOF_DIR_IN, "CAMIF_MCLK"},
- {20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
- {21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
};
static struct gpio apq8064_back_cam_gpio[] = {
- {107, GPIOF_DIR_OUT, "CAM_RESET"},
+ {5, GPIOF_DIR_IN, "CAMIF_MCLK"},
+ {CAML_RSTN, GPIOF_DIR_OUT, "CAM_RESET"},
};
static struct msm_gpio_set_tbl apq8064_back_cam_gpio_set_tbl[] = {
- {107, GPIOF_OUT_INIT_LOW, 1000},
- {107, GPIOF_OUT_INIT_HIGH, 4000},
+ {CAML_RSTN, GPIOF_OUT_INIT_LOW, 10000},
+ {CAML_RSTN, GPIOF_OUT_INIT_HIGH, 10000},
};
static struct msm_camera_gpio_conf apq8064_back_cam_gpio_conf = {
@@ -344,6 +372,52 @@
.cam_gpio_set_tbl_size = ARRAY_SIZE(apq8064_back_cam_gpio_set_tbl),
};
+static struct gpio apq8064_front_cam_gpio[] = {
+ {4, GPIOF_DIR_IN, "CAMIF_MCLK"},
+ {12, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
+ {13, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
+ {CAMR_RSTN, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl apq8064_front_cam_gpio_set_tbl[] = {
+ {CAMR_RSTN, GPIOF_OUT_INIT_LOW, 10000},
+ {CAMR_RSTN, GPIOF_OUT_INIT_HIGH, 10000},
+};
+
+static struct msm_camera_gpio_conf apq8064_front_cam_gpio_conf = {
+ .cam_gpiomux_conf_tbl = apq8064_cam_2d_configs,
+ .cam_gpiomux_conf_tbl_size = ARRAY_SIZE(apq8064_cam_2d_configs),
+ .cam_gpio_common_tbl = apq8064_common_cam_gpio,
+ .cam_gpio_common_tbl_size = ARRAY_SIZE(apq8064_common_cam_gpio),
+ .cam_gpio_req_tbl = apq8064_front_cam_gpio,
+ .cam_gpio_req_tbl_size = ARRAY_SIZE(apq8064_front_cam_gpio),
+ .cam_gpio_set_tbl = apq8064_front_cam_gpio_set_tbl,
+ .cam_gpio_set_tbl_size = ARRAY_SIZE(apq8064_front_cam_gpio_set_tbl),
+};
+
+static struct msm_camera_i2c_conf apq8064_back_cam_i2c_conf = {
+ .use_i2c_mux = 1,
+ .mux_dev = &msm8960_device_i2c_mux_gsbi4,
+ .i2c_mux_mode = MODE_L,
+};
+
+static struct i2c_board_info imx074_actuator_i2c_info = {
+ I2C_BOARD_INFO("imx074_act", 0x11),
+};
+
+static struct msm_actuator_info imx074_actuator_info = {
+ .board_info = &imx074_actuator_i2c_info,
+ .bus_id = APQ_8064_GSBI4_QUP_I2C_BUS_ID,
+ .vcm_pwd = 0,
+ .vcm_enable = 1,
+};
+
+static struct msm_camera_i2c_conf apq8064_front_cam_i2c_conf = {
+ .use_i2c_mux = 1,
+ .mux_dev = &msm8960_device_i2c_mux_gsbi4,
+ .i2c_mux_mode = MODE_L,
+};
+
#ifdef CONFIG_IMX074
static struct msm_camera_sensor_flash_data flash_imx074 = {
.flash_type = MSM_CAMERA_FLASH_NONE,
@@ -351,9 +425,10 @@
static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
.mount_angle = 90,
- .cam_vreg = msm_8064_back_cam_vreg,
- .num_vreg = ARRAY_SIZE(msm_8064_back_cam_vreg),
+ .cam_vreg = apq_8064_back_cam_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_back_cam_vreg),
.gpio_conf = &apq8064_back_cam_gpio_conf,
+ .i2c_conf = &apq8064_back_cam_i2c_conf,
};
static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
@@ -363,14 +438,40 @@
.sensor_platform_info = &sensor_board_info_imx074,
.csi_if = 1,
.camera_type = BACK_CAMERA_2D,
+ .actuator_info = &imx074_actuator_info
};
#endif
+#ifdef CONFIG_OV2720
+static struct msm_camera_sensor_flash_data flash_ov2720 = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
+ .mount_angle = 0,
+ .cam_vreg = apq_8064_front_cam_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_front_cam_vreg),
+ .gpio_conf = &apq8064_front_cam_gpio_conf,
+ .i2c_conf = &apq8064_front_cam_i2c_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov2720_data = {
+ .sensor_name = "ov2720",
+ .pdata = &msm_camera_csi_device_data[1],
+ .flash_data = &flash_ov2720,
+ .sensor_platform_info = &sensor_board_info_ov2720,
+ .csi_if = 1,
+ .camera_type = FRONT_CAMERA_2D,
+};
+#endif
+
+
void __init apq8064_init_cam(void)
{
msm_gpiomux_install(apq8064_cam_common_configs,
ARRAY_SIZE(apq8064_cam_common_configs));
+ platform_device_register(&msm8960_device_i2c_mux_gsbi4);
platform_device_register(&msm8960_device_csiphy0);
platform_device_register(&msm8960_device_csiphy1);
platform_device_register(&msm8960_device_csid0);
@@ -388,6 +489,12 @@
.platform_data = &msm_camera_sensor_imx074_data,
},
#endif
+#ifdef CONFIG_OV2720
+ {
+ I2C_BOARD_INFO("ov2720", 0x6C),
+ .platform_data = &msm_camera_sensor_ov2720_data,
+ },
+#endif
};
struct msm_camera_board_info apq8064_camera_board_info = {
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index c3cc9eb..206bebd 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -64,6 +64,18 @@
};
#endif
+static struct gpiomux_setting gpio_i2c_config = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gpio_i2c_config_sus = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+};
+
static struct gpiomux_setting cdc_mclk = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
@@ -347,6 +359,20 @@
[GPIOMUX_SUSPENDED] = &gsbi7_func1_cfg,
},
},
+ {
+ .gpio = 21, /* GSBI1 QUP I2C_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_i2c_config_sus,
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
+ },
+ },
+ {
+ .gpio = 20, /* GSBI1 QUP I2C_DATA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_i2c_config_sus,
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
+ },
+ },
};
static struct msm_gpiomux_config apq8064_slimbus_config[] __initdata = {
@@ -473,7 +499,29 @@
.settings = {
[GPIOMUX_SUSPENDED] = &ap2mdm_pon_reset_n_cfg,
}
- }
+ },
+};
+
+static struct gpiomux_setting gpio_rotate_key_act_config = {
+ .pull = GPIOMUX_PULL_UP,
+ .drv = GPIOMUX_DRV_8MA,
+ .func = GPIOMUX_FUNC_GPIO,
+};
+
+static struct gpiomux_setting gpio_rotate_key_sus_config = {
+ .pull = GPIOMUX_PULL_NONE,
+ .drv = GPIOMUX_DRV_2MA,
+ .func = GPIOMUX_FUNC_GPIO,
+};
+
+struct msm_gpiomux_config apq8064_rotate_key_config[] = {
+ {
+ .gpio = 46,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_rotate_key_sus_config,
+ [GPIOMUX_ACTIVE] = &gpio_rotate_key_act_config,
+ }
+ },
};
static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
@@ -573,11 +621,16 @@
ARRAY_SIZE(cyts_gpio_configs));
#ifdef CONFIG_USB_EHCI_MSM_HSIC
- msm_gpiomux_install(apq8064_hsic_configs,
- ARRAY_SIZE(apq8064_hsic_configs));
+ if (machine_is_apq8064_mtp())
+ msm_gpiomux_install(apq8064_hsic_configs,
+ ARRAY_SIZE(apq8064_hsic_configs));
#endif
if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
msm_gpiomux_install(apq8064_mxt_configs,
ARRAY_SIZE(apq8064_mxt_configs));
+
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+ msm_gpiomux_install(apq8064_rotate_key_config,
+ ARRAY_SIZE(apq8064_rotate_key_config));
}
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 0357c40..213215e 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -122,6 +122,31 @@
},
};
+static const char *kgsl_3d0_iommu0_ctx_names[] = {
+ "gfx3d_user",
+ /* priv_ctx goes here */
+};
+
+static const char *kgsl_3d0_iommu1_ctx_names[] = {
+ "gfx3d1_user",
+ /* priv_ctx goes here */
+};
+
+static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = {
+ {
+ .iommu_ctx_names = kgsl_3d0_iommu0_ctx_names,
+ .iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu0_ctx_names),
+ .physstart = 0x07C00000,
+ .physend = 0x07C00000 + SZ_1M - 1,
+ },
+ {
+ .iommu_ctx_names = kgsl_3d0_iommu1_ctx_names,
+ .iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu1_ctx_names),
+ .physstart = 0x07D00000,
+ .physend = 0x07D00000 + SZ_1M - 1,
+ },
+};
+
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
@@ -154,8 +179,8 @@
#ifdef CONFIG_MSM_BUS_SCALING
.bus_scale_table = &grp3d_bus_scale_pdata,
#endif
- .iommu_user_ctx_name = "gfx3d_user",
- .iommu_priv_ctx_name = NULL,
+ .iommu_data = kgsl_3d0_iommu_data,
+ .iommu_count = ARRAY_SIZE(kgsl_3d0_iommu_data),
};
struct platform_device device_kgsl_3d0 = {
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 02dfc5e..364df81 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -117,6 +117,22 @@
PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
+ PM8921_GPIO_OUTPUT_FUNC(44, 0, PM_GPIO_FUNC_2),
+ PM8921_GPIO_OUTPUT(33, 0, HIGH),
+ PM8921_GPIO_OUTPUT(20, 0, HIGH),
+ PM8921_GPIO_INPUT(35, PM_GPIO_PULL_UP_1P5),
+ PM8921_GPIO_INPUT(38, PM_GPIO_PULL_UP_1P5),
+ /* TABLA CODEC RESET */
+ PM8921_GPIO_OUTPUT(34, 1, MED),
+};
+
+static struct pm8xxx_gpio_init pm8921_mtp_kp_gpios[] __initdata = {
+ PM8921_GPIO_INPUT(3, PM_GPIO_PULL_UP_1P5),
+ PM8921_GPIO_INPUT(4, PM_GPIO_PULL_UP_1P5),
+};
+
+static struct pm8xxx_gpio_init pm8921_cdp_kp_gpios[] __initdata = {
+ PM8921_GPIO_INPUT(37, PM_GPIO_PULL_UP_1P5),
};
/* Initial PM8XXX MPP configurations */
@@ -140,6 +156,28 @@
}
}
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+ for (i = 0; i < ARRAY_SIZE(pm8921_cdp_kp_gpios); i++) {
+ rc = pm8xxx_gpio_config(pm8921_cdp_kp_gpios[i].gpio,
+ &pm8921_cdp_kp_gpios[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ }
+
+ if (machine_is_apq8064_mtp())
+ for (i = 0; i < ARRAY_SIZE(pm8921_mtp_kp_gpios); i++) {
+ rc = pm8xxx_gpio_config(pm8921_mtp_kp_gpios[i].gpio,
+ &pm8921_mtp_kp_gpios[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
&pm8xxx_mpps[i].config);
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 4e29feb..0d12bb5 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -27,8 +27,9 @@
};
VREG_CONSUMERS(L2) = {
REGULATOR_SUPPLY("8921_l2", NULL),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-001a"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-006c"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.0"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.1"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.2"),
REGULATOR_SUPPLY("lvds_pll_vdda", "lvds.0"),
REGULATOR_SUPPLY("dsi1_pll_vdda", "mipi_dsi.1"),
};
@@ -41,8 +42,6 @@
VREG_CONSUMERS(L4) = {
REGULATOR_SUPPLY("8921_l4", NULL),
REGULATOR_SUPPLY("HSUSB_1p8", "msm_otg"),
- REGULATOR_SUPPLY("HSUSB_1p8", "msm_ehci_host.0"),
- REGULATOR_SUPPLY("HSUSB_1p8", "msm_ehci_host.1"),
REGULATOR_SUPPLY("iris_vddxo", "wcnss_wlan.0"),
};
VREG_CONSUMERS(L5) = {
@@ -103,7 +102,8 @@
REGULATOR_SUPPLY("8921_l23", NULL),
REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.1"),
REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.2"),
-
+ REGULATOR_SUPPLY("HSUSB_1p8", "msm_ehci_host.0"),
+ REGULATOR_SUPPLY("HSUSB_1p8", "msm_ehci_host.1"),
};
VREG_CONSUMERS(L24) = {
REGULATOR_SUPPLY("8921_l24", NULL),
@@ -157,6 +157,7 @@
REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
REGULATOR_SUPPLY("vcc_i2c", "3-005b"),
REGULATOR_SUPPLY("vcc_i2c", "3-0024"),
+ REGULATOR_SUPPLY("vddp", "0-0048"),
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
@@ -217,6 +218,7 @@
};
VREG_CONSUMERS(EXT_5V) = {
REGULATOR_SUPPLY("ext_5v", NULL),
+ REGULATOR_SUPPLY("vbus", "msm_ehci_host.0"),
};
VREG_CONSUMERS(EXT_MPP8) = {
REGULATOR_SUPPLY("ext_mpp8", NULL),
@@ -506,7 +508,7 @@
RPM_LDO(L6, 0, 1, 0, 2950000, 2950000, NULL, 0, 0),
RPM_LDO(L7, 0, 1, 0, 1850000, 2950000, NULL, 0, 0),
RPM_LDO(L8, 0, 1, 0, 2800000, 2800000, NULL, 0, 0),
- RPM_LDO(L9, 0, 1, 0, 2850000, 2850000, NULL, 0, 0),
+ RPM_LDO(L9, 0, 1, 0, 3000000, 3000000, NULL, 0, 0),
RPM_LDO(L10, 0, 1, 0, 2900000, 2900000, NULL, 0, 0),
RPM_LDO(L11, 0, 1, 0, 3000000, 3000000, NULL, 0, 0),
RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8921_s4", 0, 0),
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 0d187a9..41be3e7 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -51,7 +51,7 @@
.name = "sdc_vdd",
.high_vol_level = 2950000,
.low_vol_level = 2950000,
- .hpm_uA = 600000, /* 600mA */
+ .hpm_uA = 800000, /* 800mA */
}
};
@@ -121,8 +121,8 @@
static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
{TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
- {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+ {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
};
/* SDC3 pad data */
@@ -146,8 +146,8 @@
static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
{TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_DOWN},
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_DOWN}
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
};
static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
@@ -220,7 +220,7 @@
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
static unsigned int sdc3_sup_clk_rates[] = {
- 400000, 24000000, 48000000, 96000000
+ 400000, 24000000, 48000000, 96000000, 192000000
};
static struct mmc_platform_data sdc3_data = {
@@ -234,6 +234,10 @@
.status_irq = MSM_GPIO_TO_INT(26),
.irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
.is_status_gpio_active_low = 1,
+ .xpc_cap = 1,
+ .uhs_caps = (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
+ MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_800),
};
static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
#else
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index c07f497b..8e7fb1a 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -18,6 +18,7 @@
#include <linux/slimbus/slimbus.h>
#include <linux/mfd/wcd9310/core.h>
#include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/pm8xxx/misc.h>
#include <linux/msm_ssbi.h>
#include <linux/spi/spi.h>
#include <linux/dma-mapping.h>
@@ -26,6 +27,8 @@
#include <linux/memory.h>
#include <linux/i2c/atmel_mxt_ts.h>
#include <linux/cyttsp.h>
+#include <linux/i2c/isa1200.h>
+#include <linux/gpio_keys.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -54,6 +57,7 @@
#include <mach/msm_bus_board.h>
#include <mach/cpuidle.h>
#include <mach/mdm2.h>
+#include <linux/msm_tsens.h>
#include "msm_watchdog.h"
#include "board-8064.h"
@@ -78,7 +82,7 @@
#define MSM_ION_SF_SIZE MSM_PMEM_SIZE
#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
#define MSM_ION_MM_SIZE MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE 0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE 0x300000 /* (3MB) */
#define MSM_ION_MFC_SIZE SZ_8K
#define MSM_ION_AUDIO_SIZE MSM_PMEM_AUDIO_SIZE
#define MSM_ION_HEAP_NUM 8
@@ -233,6 +237,18 @@
.align = SZ_128K,
};
#endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
static struct ion_platform_data ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
@@ -243,14 +259,6 @@
},
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
{
- .id = ION_SF_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_SF_HEAP_NAME,
- .size = MSM_ION_SF_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
- },
- {
.id = ION_CP_MM_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_MM_HEAP_NAME,
@@ -275,6 +283,14 @@
.extra_data = (void *) &cp_mfc_ion_pdata,
},
{
+ .id = ION_SF_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SF_HEAP_NAME,
+ .size = MSM_ION_SF_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .extra_data = (void *) &co_ion_pdata,
+ },
+ {
.id = ION_IOMMU_HEAP_ID,
.type = ION_HEAP_TYPE_IOMMU,
.name = ION_IOMMU_HEAP_NAME,
@@ -459,6 +475,19 @@
.power_budget = 750,
};
+static struct msm_usb_host_platform_data msm_ehci_host_pdata = {
+ .power_budget = 500,
+};
+
+static void __init apq8064_ehci_host_init(void)
+{
+ if (machine_is_apq8064_liquid()) {
+ apq8064_device_ehci_host3.dev.platform_data =
+ &msm_ehci_host_pdata;
+ platform_device_register(&apq8064_device_ehci_host3);
+ }
+}
+
#define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
/* Micbias setting is based on 8660 CDP/MTP/FLUID requirement
@@ -528,6 +557,86 @@
},
};
+#define HAP_SHIFT_LVL_OE_GPIO PM8921_MPP_PM_TO_SYS(8)
+#define ISA1200_HAP_EN_GPIO PM8921_GPIO_PM_TO_SYS(33)
+#define ISA1200_HAP_LEN_GPIO PM8921_GPIO_PM_TO_SYS(20)
+#define ISA1200_HAP_CLK PM8921_GPIO_PM_TO_SYS(44)
+
+static int isa1200_power(int on)
+{
+ gpio_set_value_cansleep(ISA1200_HAP_CLK, !!on);
+
+ return 0;
+}
+
+static int isa1200_dev_setup(bool enable)
+{
+ int rc = 0;
+
+ rc = pm8xxx_aux_clk_control(CLK_MP3_2, XO_DIV_1, enable);
+ if (rc) {
+ pr_err("%s: unable to write aux clock register(%d)\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (!enable)
+ goto free_gpio;
+
+ rc = gpio_request(ISA1200_HAP_CLK, "haptics_clk");
+ if (rc) {
+ pr_err("%s: unable to request gpio %d config(%d)\n",
+ __func__, ISA1200_HAP_CLK, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_output(ISA1200_HAP_CLK, 0);
+ if (rc) {
+ pr_err("%s: unable to set direction\n", __func__);
+ goto free_gpio;
+ }
+
+ return 0;
+
+free_gpio:
+ gpio_free(ISA1200_HAP_CLK);
+ return rc;
+}
+
+static struct isa1200_regulator isa1200_reg_data[] = {
+ {
+ .name = "vddp",
+ .min_uV = ISA_I2C_VTG_MIN_UV,
+ .max_uV = ISA_I2C_VTG_MAX_UV,
+ .load_uA = ISA_I2C_CURR_UA,
+ },
+};
+
+static struct isa1200_platform_data isa1200_1_pdata = {
+ .name = "vibrator",
+ .dev_setup = isa1200_dev_setup,
+ .power_on = isa1200_power,
+ .hap_en_gpio = ISA1200_HAP_EN_GPIO,
+ .hap_len_gpio = ISA1200_HAP_LEN_GPIO,
+ .max_timeout = 15000,
+ .mode_ctrl = PWM_GEN_MODE,
+ .pwm_fd = {
+ .pwm_div = 256,
+ },
+ .is_erm = false,
+ .smart_en = true,
+ .ext_clk_en = true,
+ .chip_en = 1,
+ .regulator_info = isa1200_reg_data,
+ .num_regulators = ARRAY_SIZE(isa1200_reg_data),
+};
+
+static struct i2c_board_info isa1200_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isa1200_1", 0x90>>1),
+ .platform_data = &isa1200_1_pdata,
+ },
+};
/* configuration data for mxt1386e using V2.1 firmware */
static const u8 mxt1386e_config_data_v2_1[] = {
/* T6 Object */
@@ -890,6 +999,14 @@
.peripheral_platform_device = &apq8064_device_hsic_host,
};
+static struct tsens_platform_data apq_tsens_pdata = {
+ .tsens_factor = 1000,
+ .hw_type = APQ_8064,
+ .tsens_num_sensor = 11,
+ .slope = {1176, 1176, 1154, 1176, 1111,
+ 1132, 1132, 1199, 1132, 1199, 1132},
+};
+
#define MSM_SHARED_RAM_PHYS 0x80000000
static void __init apq8064_map_io(void)
{
@@ -1225,7 +1342,6 @@
static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
[0] = {
.reg_base_addr = MSM_SAW_L2_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1238,9 +1354,7 @@
static struct msm_spm_platform_data msm_spm_data[] __initdata = {
[0] = {
.reg_base_addr = MSM_SAW0_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
#if defined(CONFIG_MSM_AVS_HW)
.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1255,9 +1369,7 @@
},
[1] = {
.reg_base_addr = MSM_SAW1_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
#if defined(CONFIG_MSM_AVS_HW)
.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1272,9 +1384,7 @@
},
[2] = {
.reg_base_addr = MSM_SAW2_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
#if defined(CONFIG_MSM_AVS_HW)
.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1289,9 +1399,7 @@
},
[3] = {
.reg_base_addr = MSM_SAW3_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
#if defined(CONFIG_MSM_AVS_HW)
.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1368,6 +1476,7 @@
static struct platform_device *common_devices[] __initdata = {
&apq8064_device_dmov,
+ &apq8064_device_qup_i2c_gsbi1,
&apq8064_device_qup_i2c_gsbi3,
&apq8064_device_qup_i2c_gsbi4,
&apq8064_device_qup_spi_gsbi5,
@@ -1381,7 +1490,6 @@
&apq8064_device_otg,
&apq8064_device_gadget_peripheral,
&apq8064_device_hsusb_host,
- &apq8064_device_hsic_host,
&android_usb_device,
&msm_device_wcnss_wlan,
#ifdef CONFIG_ANDROID_PMEM
@@ -1434,6 +1542,7 @@
&apq_pcm_afe,
&apq_cpudai_auxpcm_rx,
&apq_cpudai_auxpcm_tx,
+ &apq_cpudai_stub,
&apq8064_rpm_device,
&apq8064_rpm_log_device,
&apq8064_rpm_stat_device,
@@ -1496,6 +1605,11 @@
/* add more slimbus slaves as needed */
};
+static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi1_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+};
+
static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
.clk_freq = 100000,
.src_clk_rate = 24000000,
@@ -1506,8 +1620,20 @@
.src_clk_rate = 24000000,
};
+#define GSBI_DUAL_MODE_CODE 0x60
+#define MSM_GSBI1_PHYS 0x12440000
static void __init apq8064_i2c_init(void)
{
+ void __iomem *gsbi_mem;
+
+ apq8064_device_qup_i2c_gsbi1.dev.platform_data =
+ &apq8064_i2c_qup_gsbi1_pdata;
+ gsbi_mem = ioremap_nocache(MSM_GSBI1_PHYS, 4);
+ writel_relaxed(GSBI_DUAL_MODE_CODE, gsbi_mem);
+ /* Ensure protocol code is written before proceeding */
+ wmb();
+ iounmap(gsbi_mem);
+ apq8064_i2c_qup_gsbi1_pdata.use_gsbi_shared_mode = 1;
apq8064_device_qup_i2c_gsbi3.dev.platform_data =
&apq8064_i2c_qup_gsbi3_pdata;
apq8064_device_qup_i2c_gsbi4.dev.platform_data =
@@ -1535,6 +1661,116 @@
}
#endif
+#define GPIO_KEY_HOME PM8921_GPIO_PM_TO_SYS(27)
+#define GPIO_KEY_VOLUME_UP PM8921_GPIO_PM_TO_SYS(35)
+#define GPIO_KEY_VOLUME_DOWN PM8921_GPIO_PM_TO_SYS(38)
+#define GPIO_KEY_CAM_FOCUS PM8921_GPIO_PM_TO_SYS(3)
+#define GPIO_KEY_CAM_SNAP PM8921_GPIO_PM_TO_SYS(4)
+#define GPIO_KEY_ROTATION 46
+
+static struct gpio_keys_button cdp_keys[] = {
+ {
+ .code = KEY_HOME,
+ .gpio = GPIO_KEY_HOME,
+ .desc = "home_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_VOLUMEUP,
+ .gpio = GPIO_KEY_VOLUME_UP,
+ .desc = "volume_up_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_VOLUMEDOWN,
+ .gpio = GPIO_KEY_VOLUME_DOWN,
+ .desc = "volume_down_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = SW_ROTATE_LOCK,
+ .gpio = GPIO_KEY_ROTATION,
+ .desc = "rotate_key",
+ .active_low = 1,
+ .type = EV_SW,
+ .debounce_interval = 15,
+ },
+};
+
+static struct gpio_keys_platform_data cdp_keys_data = {
+ .buttons = cdp_keys,
+ .nbuttons = ARRAY_SIZE(cdp_keys),
+};
+
+static struct platform_device cdp_kp_pdev = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &cdp_keys_data,
+ },
+};
+
+static struct gpio_keys_button mtp_keys[] = {
+ {
+ .code = KEY_CAMERA_FOCUS,
+ .gpio = GPIO_KEY_CAM_FOCUS,
+ .desc = "cam_focus_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_VOLUMEUP,
+ .gpio = GPIO_KEY_VOLUME_UP,
+ .desc = "volume_up_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_VOLUMEDOWN,
+ .gpio = GPIO_KEY_VOLUME_DOWN,
+ .desc = "volume_down_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_CAMERA_SNAPSHOT,
+ .gpio = GPIO_KEY_CAM_SNAP,
+ .desc = "cam_snap_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .debounce_interval = 15,
+ },
+};
+
+static struct gpio_keys_platform_data mtp_keys_data = {
+ .buttons = mtp_keys,
+ .nbuttons = ARRAY_SIZE(mtp_keys),
+};
+
+static struct platform_device mtp_kp_pdev = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &mtp_keys_data,
+ },
+};
+
+
static void __init apq8064_clock_init(void)
{
if (machine_is_apq8064_rumi3())
@@ -1569,6 +1805,12 @@
cyttsp_info,
ARRAY_SIZE(cyttsp_info),
},
+ {
+ I2C_FFA | I2C_LIQUID,
+ APQ_8064_GSBI1_QUP_I2C_BUS_ID,
+ isa1200_board_info,
+ ARRAY_SIZE(isa1200_board_info),
+ },
};
static void __init register_i2c_devices(void)
@@ -1576,6 +1818,14 @@
u8 mach_mask = 0;
int i;
+#ifdef CONFIG_MSM_CAMERA
+ struct i2c_registry apq8064_camera_i2c_devices = {
+ I2C_SURF | I2C_FFA | I2C_LIQUID | I2C_RUMI,
+ APQ_8064_GSBI4_QUP_I2C_BUS_ID,
+ apq8064_camera_board_info.board_info,
+ apq8064_camera_board_info.num_i2c_board_info,
+ };
+#endif
/* Build the matching 'supported_machs' bitmask */
if (machine_is_apq8064_cdp())
mach_mask = I2C_SURF;
@@ -1597,6 +1847,12 @@
apq8064_i2c_devices[i].info,
apq8064_i2c_devices[i].len);
}
+#ifdef CONFIG_MSM_CAMERA
+ if (apq8064_camera_i2c_devices.machs & mach_mask)
+ i2c_register_board_info(apq8064_camera_i2c_devices.bus,
+ apq8064_camera_i2c_devices.info,
+ apq8064_camera_i2c_devices.len);
+#endif
}
static void __init apq8064_common_init(void)
@@ -1618,9 +1874,13 @@
if (machine_is_apq8064_liquid())
msm_otg_pdata.mhl_enable = true;
apq8064_device_otg.dev.platform_data = &msm_otg_pdata;
- apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
+ apq8064_ehci_host_init();
apq8064_init_buses();
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+ if (machine_is_apq8064_mtp()) {
+ apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
+ device_initialize(&apq8064_device_hsic_host.dev);
+ }
apq8064_pm8xxx_gpio_mpp_init();
apq8064_init_mmc();
@@ -1652,12 +1912,14 @@
&msm8064_device_watchdog.dev.platform_data;
wdog_pdata->bark_time = 15000;
+ msm_tsens_early_init(&apq_tsens_pdata);
apq8064_common_init();
platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
}
static void __init apq8064_rumi3_init(void)
{
+ msm_tsens_early_init(&apq_tsens_pdata);
apq8064_common_init();
ethernet_init();
platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
@@ -1668,14 +1930,21 @@
static void __init apq8064_cdp_init(void)
{
+ msm_tsens_early_init(&apq_tsens_pdata);
apq8064_common_init();
ethernet_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
apq8064_init_fb();
apq8064_init_gpu();
- platform_add_devices(msm_footswitch_devices,
- msm_num_footswitch_devices);
+ platform_add_devices(apq8064_fs_devices, apq8064_num_fs_devices);
+ apq8064_init_cam();
+
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+ platform_device_register(&cdp_kp_pdev);
+
+ if (machine_is_apq8064_mtp())
+ platform_device_register(&mtp_kp_pdev);
}
MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
@@ -1727,3 +1996,21 @@
.init_early = apq8064_allocate_memory_regions,
MACHINE_END
+MACHINE_START(MPQ8064_HRD, "QCT MPQ8064 HRD")
+ .map_io = apq8064_map_io,
+ .reserve = apq8064_reserve,
+ .init_irq = apq8064_init_irq,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm_timer,
+ .init_machine = apq8064_cdp_init,
+MACHINE_END
+
+MACHINE_START(MPQ8064_DTV, "QCT MPQ8064 DTV")
+ .map_io = apq8064_map_io,
+ .reserve = apq8064_reserve,
+ .init_irq = apq8064_init_irq,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm_timer,
+ .init_machine = apq8064_cdp_init,
+MACHINE_END
+
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index d401f4c..e8c8144 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -64,6 +64,8 @@
extern struct msm_camera_board_info apq8064_camera_board_info;
void apq8064_init_cam(void);
+
+#define APQ_8064_GSBI1_QUP_I2C_BUS_ID 0
#define APQ_8064_GSBI3_QUP_I2C_BUS_ID 3
#define APQ_8064_GSBI4_QUP_I2C_BUS_ID 4
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index e0bc723..f82c43c 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -349,17 +349,15 @@
};
static struct camera_vreg_t msm_8930_back_cam_vreg[] = {
- {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vio", REG_LDO, 1800000, 1800000, 16000},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+ {"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
};
static struct camera_vreg_t msm_8930_front_cam_vreg[] = {
- {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
};
@@ -409,7 +407,6 @@
.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8930_back_cam_gpio_set_tbl),
};
-#ifdef CONFIG_IMX074_ACT
static struct i2c_board_info imx074_actuator_i2c_info = {
I2C_BOARD_INFO("imx074_act", 0x11),
};
@@ -420,9 +417,7 @@
.vcm_pwd = 0,
.vcm_enable = 1,
};
-#endif
-#ifdef CONFIG_IMX074
static struct msm_camera_sensor_flash_data flash_imx074 = {
.flash_type = MSM_CAMERA_FLASH_LED,
#ifdef CONFIG_MSM_CAMERA_FLASH
@@ -445,21 +440,24 @@
.sensor_platform_info = &sensor_board_info_imx074,
.csi_if = 1,
.camera_type = BACK_CAMERA_2D,
-#ifdef CONFIG_IMX074_ACT
.actuator_info = &imx074_actuator_info
-#endif
};
-#endif
-#ifdef CONFIG_MT9M114
+static struct camera_vreg_t msm_8930_mt9m114_vreg[] = {
+ {"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+ {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+ {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
static struct msm_camera_sensor_flash_data flash_mt9m114 = {
.flash_type = MSM_CAMERA_FLASH_NONE
};
static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
.mount_angle = 90,
- .cam_vreg = msm_8930_back_cam_vreg,
- .num_vreg = ARRAY_SIZE(msm_8930_back_cam_vreg),
+ .cam_vreg = msm_8930_mt9m114_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8930_mt9m114_vreg),
.gpio_conf = &msm_8930_back_cam_gpio_conf,
};
@@ -471,9 +469,7 @@
.csi_if = 1,
.camera_type = BACK_CAMERA_2D,
};
-#endif
-#ifdef CONFIG_OV2720
static struct msm_camera_sensor_flash_data flash_ov2720 = {
.flash_type = MSM_CAMERA_FLASH_NONE,
};
@@ -493,10 +489,8 @@
.csi_if = 1,
.camera_type = FRONT_CAMERA_2D,
};
-#endif
static struct camera_vreg_t msm_8930_s5k3l1yx_vreg[] = {
- {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
@@ -539,18 +533,14 @@
#ifdef CONFIG_I2C
struct i2c_board_info msm8930_camera_i2c_boardinfo[] = {
-#ifdef CONFIG_IMX074
{
I2C_BOARD_INFO("imx074", 0x1A),
.platform_data = &msm_camera_sensor_imx074_data,
},
-#endif
-#ifdef CONFIG_OV2720
{
I2C_BOARD_INFO("ov2720", 0x6C),
.platform_data = &msm_camera_sensor_ov2720_data,
},
-#endif
{
I2C_BOARD_INFO("mt9m114", 0x48),
.platform_data = &msm_camera_sensor_mt9m114_data,
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 9175c75..a840877 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -29,15 +29,19 @@
#include "board-8930.h"
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1376 * 768 * 4), 4096) * 3) /* 4 bpp x 3 pages */
#else
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1376 * 768 * 4), 4096) * 2) /* 4 bpp x 2 pages */
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
#elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
#else
#define MSM_FB_EXT_BUF_SIZE 0
#endif
@@ -87,7 +91,8 @@
PANEL_NAME_MAX_LEN)))
return 0;
-#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+ !defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
PANEL_NAME_MAX_LEN)))
@@ -618,9 +623,15 @@
if (on == prev_on)
return 0;
- if (!reg_ext_5v)
- reg_ext_5v = regulator_get(&hdmi_msm_device.dev,
- "hdmi_mvs");
+ if (!reg_ext_5v) {
+ reg_ext_5v = regulator_get(&hdmi_msm_device.dev, "hdmi_mvs");
+ if (IS_ERR(reg_ext_5v)) {
+ pr_err("'%s' regulator not found, rc=%ld\n",
+ "hdmi_mvs", IS_ERR(reg_ext_5v));
+ reg_ext_5v = NULL;
+ return -ENODEV;
+ }
+ }
if (on) {
rc = regulator_enable(reg_ext_5v);
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 2f9fdcd..3a6a30d 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -30,10 +30,9 @@
REGULATOR_SUPPLY("8038_l2", NULL),
REGULATOR_SUPPLY("iris_vdddig", "wcnss_wlan.0"),
REGULATOR_SUPPLY("dsi_vdda", "mipi_dsi.1"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-001a"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-006c"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-0048"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-0020"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.0"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.1"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.2"),
};
VREG_CONSUMERS(L3) = {
REGULATOR_SUPPLY("8038_l3", NULL),
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 90cc3c5..ad71007 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -77,6 +77,7 @@
#include <linux/ion.h>
#include <mach/ion.h>
#include <mach/mdm2.h>
+#include <mach/msm_rtb.h>
#include "timer.h"
#include "devices.h"
@@ -130,7 +131,7 @@
#define MSM_ION_SF_SIZE MSM_PMEM_SIZE
#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
#define MSM_ION_MM_SIZE MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE 0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE 0x300000 /* (3MB) */
#define MSM_ION_MFC_SIZE SZ_8K
#define MSM_ION_AUDIO_SIZE MSM_PMEM_AUDIO_SIZE
#define MSM_ION_HEAP_NUM 8
@@ -250,6 +251,38 @@
},
};
+#if defined(CONFIG_MSM_RTB)
+static struct msm_rtb_platform_data msm_rtb_pdata = {
+ .size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+ int s;
+
+ s = memparse(p, NULL);
+ msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+ return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+
+static struct platform_device msm_rtb_device = {
+ .name = "msm_rtb",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_rtb_pdata,
+ },
+};
+#endif
+
+static void __init reserve_rtb_memory(void)
+{
+#if defined(CONFIG_MSM_RTB)
+ msm8930_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+#endif
+}
+
static void __init size_pmem_devices(void)
{
#ifdef CONFIG_ANDROID_PMEM
@@ -303,6 +336,18 @@
.align = SZ_128K,
};
#endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
static struct ion_platform_data ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
@@ -313,14 +358,6 @@
},
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
{
- .id = ION_SF_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_SF_HEAP_NAME,
- .size = MSM_ION_SF_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
- },
- {
.id = ION_CP_MM_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_MM_HEAP_NAME,
@@ -345,6 +382,14 @@
.extra_data = (void *) &cp_mfc_ion_pdata,
},
{
+ .id = ION_SF_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SF_HEAP_NAME,
+ .size = MSM_ION_SF_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .extra_data = (void *) &co_ion_pdata,
+ },
+ {
.id = ION_IOMMU_HEAP_ID,
.type = ION_HEAP_TYPE_IOMMU,
.name = ION_IOMMU_HEAP_NAME,
@@ -399,6 +444,7 @@
reserve_pmem_memory();
reserve_ion_memory();
reserve_mdp_memory();
+ reserve_rtb_memory();
}
static struct reserve_info msm8930_reserve_info __initdata = {
@@ -925,12 +971,54 @@
#ifdef CONFIG_USB_MSM_OTG_72K
static struct msm_otg_platform_data msm_otg_pdata;
#else
+#ifdef CONFIG_MSM_BUS_SCALING
+/* Bandwidth requests (zero) if no vote placed */
+static struct msm_bus_vectors usb_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+/* Bus bandwidth requests in Bytes/sec */
+static struct msm_bus_vectors usb_max_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 60000000, /* At least 480Mbps on bus. */
+ .ib = 960000000, /* MAX bursts rate */
+ },
+};
+
+static struct msm_bus_paths usb_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(usb_init_vectors),
+ usb_init_vectors,
+ },
+ {
+ ARRAY_SIZE(usb_max_vectors),
+ usb_max_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata usb_bus_scale_pdata = {
+ usb_bus_scale_usecases,
+ ARRAY_SIZE(usb_bus_scale_usecases),
+ .name = "usb",
+};
+#endif
+
static struct msm_otg_platform_data msm_otg_pdata = {
.mode = USB_OTG,
.otg_control = OTG_PMIC_CONTROL,
.phy_type = SNPS_28NM_INTEGRATED_PHY,
.pmic_id_irq = PM8038_USB_ID_IN_IRQ(PM8038_IRQ_BASE),
.power_budget = 750,
+#ifdef CONFIG_MSM_BUS_SCALING
+ .bus_scale_table = &usb_bus_scale_pdata,
+#endif
};
#endif
@@ -1047,9 +1135,7 @@
static struct msm_spm_platform_data msm_spm_data[] __initdata = {
[0] = {
.reg_base_addr = MSM_SAW0_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
#if defined(CONFIG_MSM_AVS_HW)
.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1064,9 +1150,7 @@
},
[1] = {
.reg_base_addr = MSM_SAW1_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
#if defined(CONFIG_MSM_AVS_HW)
.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1120,7 +1204,6 @@
static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
[0] = {
.reg_base_addr = MSM_SAW_L2_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1577,7 +1660,7 @@
};
static struct tsens_platform_data msm_tsens_pdata = {
- .slope = 910,
+ .slope = {872, 872, 872, 872, 872},
.tsens_factor = 1000,
.hw_type = MSM_8960,
.tsens_num_sensor = 5,
@@ -1719,6 +1802,9 @@
#ifdef MSM8930_PHASE_2
&gpio_keys_8930,
#endif
+#ifdef CONFIG_MSM_RTB
+ &msm_rtb_device,
+#endif
};
static struct platform_device *cdp_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 23c4928..42c09fb 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -411,20 +411,24 @@
.is_vpe = 1,
.cam_bus_scale_table = &cam_bus_client_pdata,
},
+ {
+ .ioclk.mclk_clk_rate = 24000000,
+ .ioclk.vfe_clk_rate = 228570000,
+ .csid_core = 2,
+ .cam_bus_scale_table = &cam_bus_client_pdata,
+ },
};
static struct camera_vreg_t msm_8960_back_cam_vreg[] = {
- {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vio", REG_VS, 0, 0, 0},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+ {"cam_vio", REG_VS, 0, 0, 0},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
};
static struct camera_vreg_t msm_8960_front_cam_vreg[] = {
- {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vio", REG_VS, 0, 0, 0},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
};
@@ -474,7 +478,6 @@
.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8960_back_cam_gpio_set_tbl),
};
-#ifdef CONFIG_IMX074_ACT
static struct i2c_board_info imx074_actuator_i2c_info = {
I2C_BOARD_INFO("imx074_act", 0x11),
};
@@ -485,9 +488,7 @@
.vcm_pwd = 0,
.vcm_enable = 1,
};
-#endif
-#ifdef CONFIG_IMX074
static struct msm_camera_sensor_flash_data flash_imx074 = {
.flash_type = MSM_CAMERA_FLASH_LED,
#ifdef CONFIG_MSM_CAMERA_FLASH
@@ -510,21 +511,24 @@
.sensor_platform_info = &sensor_board_info_imx074,
.csi_if = 1,
.camera_type = BACK_CAMERA_2D,
-#ifdef CONFIG_IMX074_ACT
.actuator_info = &imx074_actuator_info
-#endif
};
-#endif
-#ifdef CONFIG_MT9M114
+static struct camera_vreg_t msm_8960_mt9m114_vreg[] = {
+ {"cam_vio", REG_VS, 0, 0, 0},
+ {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+ {"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
+};
+
static struct msm_camera_sensor_flash_data flash_mt9m114 = {
.flash_type = MSM_CAMERA_FLASH_NONE
};
static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
.mount_angle = 90,
- .cam_vreg = msm_8960_back_cam_vreg,
- .num_vreg = ARRAY_SIZE(msm_8960_back_cam_vreg),
+ .cam_vreg = msm_8960_mt9m114_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8960_mt9m114_vreg),
.gpio_conf = &msm_8960_back_cam_gpio_conf,
};
@@ -536,9 +540,7 @@
.csi_if = 1,
.camera_type = BACK_CAMERA_2D,
};
-#endif
-#ifdef CONFIG_OV2720
static struct msm_camera_sensor_flash_data flash_ov2720 = {
.flash_type = MSM_CAMERA_FLASH_NONE,
};
@@ -558,10 +560,8 @@
.csi_if = 1,
.camera_type = FRONT_CAMERA_2D,
};
-#endif
static struct camera_vreg_t msm_8960_s5k3l1yx_vreg[] = {
- {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vio", REG_VS, 0, 0, 0},
@@ -643,8 +643,10 @@
platform_device_register(&msm8960_device_csiphy0);
platform_device_register(&msm8960_device_csiphy1);
+ platform_device_register(&msm8960_device_csiphy2);
platform_device_register(&msm8960_device_csid0);
platform_device_register(&msm8960_device_csid1);
+ platform_device_register(&msm8960_device_csid2);
platform_device_register(&msm8960_device_ispif);
platform_device_register(&msm8960_device_vfe);
platform_device_register(&msm8960_device_vpe);
@@ -652,18 +654,14 @@
#ifdef CONFIG_I2C
static struct i2c_board_info msm8960_camera_i2c_boardinfo[] = {
-#ifdef CONFIG_IMX074
{
I2C_BOARD_INFO("imx074", 0x1A),
.platform_data = &msm_camera_sensor_imx074_data,
},
-#endif
-#ifdef CONFIG_OV2720
{
I2C_BOARD_INFO("ov2720", 0x6C),
.platform_data = &msm_camera_sensor_ov2720_data,
},
-#endif
{
I2C_BOARD_INFO("mt9m114", 0x48),
.platform_data = &msm_camera_sensor_mt9m114_data,
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index aa8477e..37a988a 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -29,15 +29,19 @@
#include "board-8960.h"
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1920 * 1200 * 4), 4096) * 3) /* 4 bpp x 3 pages */
#else
-#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1920 * 1200 * 4), 4096) * 2) /* 4 bpp x 2 pages */
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
#elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
#else
#define MSM_FB_EXT_BUF_SIZE 0
#endif
@@ -68,6 +72,7 @@
#define MIPI_CMD_NOVATEK_QHD_PANEL_NAME "mipi_cmd_novatek_qhd"
#define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME "mipi_video_novatek_qhd"
#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
+#define MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME "mipi_video_toshiba_wuxga"
#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
#define MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME "mipi_video_chimei_wuxga"
#define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME "mipi_video_simulator_vga"
@@ -81,7 +86,7 @@
}
};
-static void set_mdp_clocks_for_liquid_wuxga(void);
+static void set_mdp_clocks_for_wuxga(void);
static int msm_fb_detect_panel(const char *name)
{
@@ -91,7 +96,7 @@
if (!strncmp(name, MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
strnlen(MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
PANEL_NAME_MAX_LEN))) {
- set_mdp_clocks_for_liquid_wuxga();
+ set_mdp_clocks_for_wuxga();
return 0;
}
} else {
@@ -106,7 +111,8 @@
PANEL_NAME_MAX_LEN)))
return 0;
-#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+ !defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
PANEL_NAME_MAX_LEN)))
@@ -126,6 +132,13 @@
strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
PANEL_NAME_MAX_LEN)))
return 0;
+
+ if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN))) {
+ set_mdp_clocks_for_wuxga();
+ return 0;
+ }
#endif
}
@@ -649,9 +662,9 @@
/**
* Set MDP clocks to high frequency to avoid DSI underflow
- * when using high resolution 1200x1920 WUXGA panel.
+ * when using high resolution 1200x1920 WUXGA panels
*/
-static void set_mdp_clocks_for_liquid_wuxga(void)
+static void set_mdp_clocks_for_wuxga(void)
{
int i;
@@ -866,9 +879,16 @@
if (on == prev_on)
return 0;
- if (!reg_8921_hdmi_mvs)
+ if (!reg_8921_hdmi_mvs) {
reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
- "hdmi_mvs");
+ "hdmi_mvs");
+ if (IS_ERR(reg_8921_hdmi_mvs)) {
+ pr_err("'%s' regulator not found, rc=%ld\n",
+ "hdmi_mvs", IS_ERR(reg_8921_hdmi_mvs));
+ reg_8921_hdmi_mvs = NULL;
+ return -ENODEV;
+ }
+ }
if (on) {
rc = regulator_enable(reg_8921_hdmi_mvs);
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 744709c..5f8f90b 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -88,6 +88,12 @@
PM_GPIO_STRENGTH_HIGH, \
PM_GPIO_FUNC_NORMAL, 0, 0)
+#define PM8XXX_GPIO_OUTPUT_STRENGTH(_gpio, _val, _out_strength) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ _out_strength, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
/* Initial PM8921 GPIO configurations */
static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
PM8XXX_GPIO_OUTPUT_VIN(6, 1, PM_GPIO_VIN_VPH), /* MHL power EN_N */
@@ -104,6 +110,8 @@
PM8XXX_GPIO_INPUT(26, PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
PM8XXX_GPIO_OUTPUT(43, PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
PM8XXX_GPIO_OUTPUT(42, 0), /* USB 5V reg enable */
+ /* TABLA CODEC RESET */
+ PM8XXX_GPIO_OUTPUT_STRENGTH(34, 1, PM_GPIO_STRENGTH_MED)
};
/* Initial PM8921 MPP configurations */
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 0f05af5..d98ae56 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -30,10 +30,9 @@
VREG_CONSUMERS(L2) = {
REGULATOR_SUPPLY("8921_l2", NULL),
REGULATOR_SUPPLY("dsi_vdda", "mipi_dsi.1"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-001a"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-006c"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-0048"),
- REGULATOR_SUPPLY("mipi_csi_vdd", "4-0020"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.0"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.1"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.2"),
};
VREG_CONSUMERS(L3) = {
REGULATOR_SUPPLY("8921_l3", NULL),
@@ -527,7 +526,7 @@
RPM_LDO(L6, 0, 1, 0, 2950000, 2950000, NULL, 0, 0),
RPM_LDO(L7, 1, 1, 0, 1850000, 2950000, NULL, 10000, 10000),
RPM_LDO(L8, 0, 1, 0, 2800000, 3000000, NULL, 0, 0),
- RPM_LDO(L9, 0, 1, 0, 2850000, 2850000, NULL, 0, 0),
+ RPM_LDO(L9, 0, 1, 0, 3000000, 3000000, NULL, 0, 0),
RPM_LDO(L10, 0, 1, 0, 3000000, 3000000, NULL, 0, 0),
RPM_LDO(L11, 0, 1, 0, 2850000, 2850000, NULL, 0, 0),
RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8921_s4", 0, 0),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 76a27ff..e843a39 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -79,6 +79,7 @@
#include <mach/ion.h>
#include <mach/mdm2.h>
#include <mach/mdm-peripheral.h>
+#include <mach/msm_rtb.h>
#include <linux/fmem.h>
@@ -143,7 +144,7 @@
#define MSM_ION_SF_SIZE MSM_PMEM_SIZE
#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
#define MSM_ION_MM_SIZE MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE 0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE 0x300000 /* (3MB) */
#define MSM_ION_MFC_SIZE SZ_8K
#define MSM_ION_AUDIO_SIZE MSM_PMEM_AUDIO_SIZE
#define MSM_ION_HEAP_NUM 8
@@ -270,6 +271,38 @@
},
};
+#if defined(CONFIG_MSM_RTB)
+static struct msm_rtb_platform_data msm_rtb_pdata = {
+ .size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+ int s;
+
+ s = memparse(p, NULL);
+ msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+ return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+
+static struct platform_device msm_rtb_device = {
+ .name = "msm_rtb",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_rtb_pdata,
+ },
+};
+#endif
+
+static void __init reserve_rtb_memory(void)
+{
+#if defined(CONFIG_MSM_RTB)
+ msm8960_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+#endif
+}
+
static void __init size_pmem_devices(void)
{
#ifdef CONFIG_ANDROID_PMEM
@@ -306,30 +339,48 @@
return MEMTYPE_EBI1;
}
+#define FMEM_ENABLED 1
+
#ifdef CONFIG_ION_MSM
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
.permission_type = IPT_TYPE_MM_CARVEOUT,
.align = PAGE_SIZE,
- .reusable = 1,
+ .reusable = FMEM_ENABLED,
+ .mem_is_fmem = FMEM_ENABLED,
};
static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
.permission_type = IPT_TYPE_MFC_SHAREDMEM,
.align = PAGE_SIZE,
.reusable = 0,
+ .mem_is_fmem = FMEM_ENABLED,
};
static struct ion_co_heap_pdata co_ion_pdata = {
.adjacent_mem_id = INVALID_HEAP_ID,
.align = PAGE_SIZE,
+ .mem_is_fmem = 0,
};
static struct ion_co_heap_pdata fw_co_ion_pdata = {
.adjacent_mem_id = ION_CP_MM_HEAP_ID,
.align = SZ_128K,
+ .mem_is_fmem = FMEM_ENABLED,
};
#endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
static struct ion_platform_data ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
@@ -340,14 +391,6 @@
},
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
{
- .id = ION_SF_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_SF_HEAP_NAME,
- .size = MSM_ION_SF_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
- },
- {
.id = ION_CP_MM_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_MM_HEAP_NAME,
@@ -372,6 +415,14 @@
.extra_data = (void *) &cp_mfc_ion_pdata,
},
{
+ .id = ION_SF_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SF_HEAP_NAME,
+ .size = MSM_ION_SF_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .extra_data = (void *) &co_ion_pdata,
+ },
+ {
.id = ION_IOMMU_HEAP_ID,
.type = ION_HEAP_TYPE_IOMMU,
.name = ION_IOMMU_HEAP_NAME,
@@ -432,23 +483,17 @@
msm8960_reserve_table[mem_type].size += size;
}
-static __init const struct ion_platform_heap *find_ion_heap(int heap_id)
-{
- unsigned int i;
- for (i = 0; i < ion_pdata.nr; ++i) {
- const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
- if (heap->id == heap_id)
- return (const struct ion_platform_heap *) heap;
- }
- return 0;
-}
-
/**
* Reserve memory for ION and calculate amount of reusable memory for fmem.
* We only reserve memory for heaps that are not reusable. However, we only
* support one reusable heap at the moment so we ignore the reusable flag for
* other than the first heap with reusable flag set. Also handle special case
- * for adjacent heap when the adjacent heap is adjacent to a reusable heap.
+ * for video heaps (MM,FW, and MFC). Video requires heaps MM and MFC to be
+ * at a higher address than FW in addition to not more than 256MB away from the
+ * base address of the firmware. This means that if MM is reusable the other
+ * two heaps must be allocated in the same region as FW. This is handled by the
+ * mem_is_fmem flag in the platform data. In addition the MM heap must be
+ * adjacent to the FW heap for content protection purposes.
*/
static void __init reserve_ion_memory(void)
{
@@ -458,7 +503,8 @@
adjust_mem_for_liquid();
fmem_pdata.size = 0;
- fmem_pdata.reserved_size = 0;
+ fmem_pdata.reserved_size_low = 0;
+ fmem_pdata.reserved_size_high = 0;
/* We only support 1 reusable heap. Check if more than one heap
* is specified as reusable and set as non-reusable if found.
@@ -483,7 +529,7 @@
for (i = 0; i < ion_pdata.nr; ++i) {
int reusable = 0;
int adjacent_heap_id = INVALID_HEAP_ID;
- int adj_reusable = 0;
+ int mem_is_fmem = 0;
const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
if (heap->extra_data) {
@@ -491,31 +537,30 @@
case ION_HEAP_TYPE_CP:
reusable = ((struct ion_cp_heap_pdata *)
heap->extra_data)->reusable;
+ mem_is_fmem = ((struct ion_cp_heap_pdata *)
+ heap->extra_data)->mem_is_fmem;
break;
case ION_HEAP_TYPE_CARVEOUT:
adjacent_heap_id = ((struct ion_co_heap_pdata *)
heap->extra_data)->adjacent_mem_id;
+ mem_is_fmem = ((struct ion_co_heap_pdata *)
+ heap->extra_data)->mem_is_fmem;
break;
default:
break;
}
}
- if (adjacent_heap_id != INVALID_HEAP_ID) {
- const struct ion_platform_heap *adj_heap =
- find_ion_heap(adjacent_heap_id);
- if (adj_heap) {
- adj_reusable = ((struct ion_cp_heap_pdata *)
- adj_heap->extra_data)->reusable;
- if (adj_reusable)
- fmem_pdata.reserved_size += heap->size;
- }
+ if (mem_is_fmem && !reusable) {
+ if (adjacent_heap_id != INVALID_HEAP_ID)
+ fmem_pdata.reserved_size_low += heap->size;
+ else
+ fmem_pdata.reserved_size_high += heap->size;
}
-
- if (!reusable && !adj_reusable)
- reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
- else
+ if (mem_is_fmem)
fmem_pdata.size += heap->size;
+ else
+ reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
}
#endif
}
@@ -531,6 +576,7 @@
reserve_pmem_memory();
reserve_ion_memory();
reserve_mdp_memory();
+ reserve_rtb_memory();
}
static struct reserve_info msm8960_reserve_info __initdata = {
@@ -1186,9 +1232,7 @@
static struct msm_spm_platform_data msm_spm_data[] __initdata = {
[0] = {
.reg_base_addr = MSM_SAW0_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0xB0,
#if defined(CONFIG_MSM_AVS_HW)
.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1203,9 +1247,7 @@
},
[1] = {
.reg_base_addr = MSM_SAW1_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0xB0,
#if defined(CONFIG_MSM_AVS_HW)
.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1259,7 +1301,6 @@
static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
[0] = {
.reg_base_addr = MSM_SAW_L2_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1675,6 +1716,63 @@
255,
};
+/* configuration data for mxt1386e on 3D SKU using V2.1 firmware */
+static const u8 mxt1386e_config_data_3d[] = {
+ /* T6 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T38 Object */
+ 13, 0, 0, 6, 2, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T7 Object */
+ 100, 16, 50,
+ /* T8 Object */
+ 25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
+ /* T9 Object */
+ 131, 0, 0, 26, 42, 0, 32, 80, 2, 5,
+ 0, 5, 5, 0, 10, 30, 10, 10, 175, 4,
+ 127, 7, 10, 10, 10, 10, 135, 55, 70, 40,
+ 10, 5, 0, 0, 0,
+ /* T18 Object */
+ 0, 0,
+ /* T24 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* T25 Object */
+ 3, 0, 60, 115, 156, 99,
+ /* T27 Object */
+ 0, 0, 0, 0, 0, 0, 0,
+ /* T40 Object */
+ 0, 0, 0, 0, 0,
+ /* T42 Object */
+ 2, 0, 255, 0, 255, 0, 0, 0, 0, 0,
+ /* T43 Object */
+ 0, 0, 0, 0, 0, 0, 0, 64, 0, 8,
+ 16,
+ /* T46 Object */
+ 64, 0, 20, 20, 0, 0, 0, 0, 0,
+ /* T47 Object */
+ 0, 0, 0, 0, 0, 0, 3, 64, 66, 0,
+ /* T48 Object */
+ 31, 64, 64, 0, 0, 0, 0, 0, 0, 0,
+ 48, 40, 0, 10, 10, 0, 0, 100, 10, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 52, 0, 12, 0, 17, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T56 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 99, 33, 0, 149, 24, 193, 255, 255, 255,
+ 255,
+};
+
#define MXT_TS_GPIO_IRQ 11
#define MXT_TS_LDO_EN_GPIO 50
#define MXT_TS_RESET_GPIO 52
@@ -1703,7 +1801,7 @@
gpio_free(MXT_TS_LDO_EN_GPIO);
}
-static struct mxt_config_info mxt_config_array[] = {
+static struct mxt_config_info mxt_config_array_2d[] = {
{
.config = mxt1386_config_data,
.config_length = ARRAY_SIZE(mxt1386_config_data),
@@ -1730,9 +1828,9 @@
},
};
-static struct mxt_platform_data mxt_platform_data = {
- .config_array = mxt_config_array,
- .config_array_size = ARRAY_SIZE(mxt_config_array),
+static struct mxt_platform_data mxt_platform_data_2d = {
+ .config_array = mxt_config_array_2d,
+ .config_array_size = ARRAY_SIZE(mxt_config_array_2d),
.x_size = 1365,
.y_size = 767,
.irqflags = IRQF_TRIGGER_FALLING,
@@ -1741,10 +1839,31 @@
.irq_gpio = MXT_TS_GPIO_IRQ,
};
+static struct mxt_config_info mxt_config_array_3d[] = {
+ {
+ .config = mxt1386e_config_data_3d,
+ .config_length = ARRAY_SIZE(mxt1386e_config_data_3d),
+ .family_id = 0xA0,
+ .variant_id = 0x7,
+ .version = 0x21,
+ .build = 0xAA,
+ },
+};
+
+static struct mxt_platform_data mxt_platform_data_3d = {
+ .config_array = mxt_config_array_3d,
+ .config_array_size = ARRAY_SIZE(mxt_config_array_3d),
+ .x_size = 1919,
+ .y_size = 1199,
+ .irqflags = IRQF_TRIGGER_FALLING,
+ .i2c_pull_up = true,
+ .reset_gpio = MXT_TS_RESET_GPIO,
+ .irq_gpio = MXT_TS_GPIO_IRQ,
+};
+
static struct i2c_board_info mxt_device_info[] __initdata = {
{
I2C_BOARD_INFO("atmel_mxt_ts", 0x5b),
- .platform_data = &mxt_platform_data,
.irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
},
};
@@ -1824,7 +1943,7 @@
};
static struct tsens_platform_data msm_tsens_pdata = {
- .slope = 910,
+ .slope = {910, 910, 910, 910, 910},
.tsens_factor = 1000,
.hw_type = MSM_8960,
.tsens_num_sensor = 5,
@@ -1943,6 +2062,9 @@
#endif
&msm_device_dspcrashd_8960,
&msm8960_device_watchdog,
+#ifdef CONFIG_MSM_RTB
+ &msm_rtb_device,
+#endif
};
static struct platform_device *sim_devices[] __initdata = {
@@ -2419,6 +2541,15 @@
else
pr_err("unmatched machine ID in register_i2c_devices\n");
+ if (machine_is_msm8960_liquid()) {
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_platform_version()) == 3)
+ mxt_device_info[0].platform_data =
+ &mxt_platform_data_3d;
+ else
+ mxt_device_info[0].platform_data =
+ &mxt_platform_data_2d;
+ }
+
/* Run the array and install devices as appropriate */
for (i = 0; i < ARRAY_SIZE(msm8960_i2c_devices); ++i) {
if (msm8960_i2c_devices[i].machs & mach_mask)
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index 95a1347..58e40db 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -70,6 +70,7 @@
REGULATOR_SUPPLY("8018_s1", NULL),
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_otg"),
REGULATOR_SUPPLY("HSIC_VDDCX", "msm_hsic_peripheral"),
+ REGULATOR_SUPPLY("HSIC_VDDCX", "msm_hsic_host"),
};
VREG_CONSUMERS(S2) = {
REGULATOR_SUPPLY("8018_s2", NULL),
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 1f19bf6..74471dd 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -518,6 +518,7 @@
&msm_device_hsic_peripheral,
&msm_device_gadget_peripheral,
&msm_device_hsusb_host,
+ &msm_device_hsic_host,
&msm_device_usb_bam,
&android_usb_device,
&msm9615_device_uart_gsbi4,
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index b4b0b9a..dc26d72 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -36,6 +36,7 @@
#include <mach/ion.h>
#endif
#include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
#include "clock.h"
#define MSM_KERNEL_EBI1_MEM_SIZE 0x280000
@@ -98,6 +99,17 @@
.align = SZ_128K,
};
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
static struct ion_platform_data ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
@@ -107,14 +119,6 @@
.name = ION_VMALLOC_HEAP_NAME,
},
{
- .id = ION_SF_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_SF_HEAP_NAME,
- .size = MSM_ION_SF_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
- },
- {
.id = ION_CP_MM_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_MM_HEAP_NAME,
@@ -139,6 +143,14 @@
.extra_data = (void *) &cp_mfc_ion_pdata,
},
{
+ .id = ION_SF_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SF_HEAP_NAME,
+ .size = MSM_ION_SF_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .extra_data = (void *) &co_ion_pdata,
+ },
+ {
.id = ION_IOMMU_HEAP_ID,
.type = ION_HEAP_TYPE_IOMMU,
.name = ION_IOMMU_HEAP_NAME,
@@ -182,6 +194,126 @@
}
#endif
+static struct resource smd_resource[] = {
+ {
+ .name = "modem_smd_in",
+ .start = 32 + 17, /* mss_sw_to_kpss_ipc_irq0 */
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "modem_smsm_in",
+ .start = 32 + 18, /* mss_sw_to_kpss_ipc_irq1 */
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "adsp_smd_in",
+ .start = 32 + 156, /* lpass_to_kpss_ipc_irq0 */
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "adsp_smsm_in",
+ .start = 32 + 157, /* lpass_to_kpss_ipc_irq1 */
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "wcnss_smd_in",
+ .start = 32 + 142, /* WcnssAppsSmdMedIrq */
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "wcnss_smsm_in",
+ .start = 32 + 144, /* RicaAppsWlanSmsmIrq */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+ {
+ .irq_config_id = SMD_MODEM,
+ .subsys_name = "modem",
+ .edge = SMD_APPS_MODEM,
+
+ .smd_int.irq_name = "modem_smd_in",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 12,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "modem_smsm_in",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smsm_dev",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 13,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+ {
+ .irq_config_id = SMD_Q6,
+ .subsys_name = "q6",
+ .edge = SMD_APPS_QDSP,
+
+ .smd_int.irq_name = "adsp_smd_in",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 8,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "adsp_smsm_in",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smsm_dev",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 9,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+ {
+ .irq_config_id = SMD_WCNSS,
+ .subsys_name = "wcnss",
+ .edge = SMD_APPS_WCNSS,
+
+ .smd_int.irq_name = "wcnss_smd_in",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 17,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "wcnss_smsm_in",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smsm_dev",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 19,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+};
+
+static struct smd_platform smd_platform_data = {
+ .num_ss_configs = ARRAY_SIZE(smd_config_list),
+ .smd_ss_configs = smd_config_list,
+};
+
+struct platform_device msm_device_smd_copper = {
+ .name = "msm_smd",
+ .id = -1,
+ .resource = smd_resource,
+ .num_resources = ARRAY_SIZE(smd_resource),
+ .dev = {
+ .platform_data = &smd_platform_data,
+ }
+};
+
static void __init msm_copper_calculate_reserve_sizes(void)
{
#ifdef CONFIG_ION_MSM
@@ -223,6 +355,7 @@
#ifdef CONFIG_ION_MSM
platform_device_register(&ion_dev);
#endif
+ platform_device_register(&msm_device_smd_copper);
}
static struct of_device_id irq_match[] __initdata = {
@@ -247,6 +380,7 @@
CLK_DUMMY("core_clk", NULL, "msm_otg", OFF),
CLK_DUMMY("alt_core_clk", NULL, "msm_otg", OFF),
CLK_DUMMY("iface_clk", NULL, "msm_otg", OFF),
+ CLK_DUMMY("xo", NULL, "msm_otg", OFF),
CLK_DUMMY("dfab_clk", DFAB_CLK, NULL, 0),
CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, NULL, 0),
CLK_DUMMY("mem_clk", NULL, NULL, 0),
@@ -266,6 +400,8 @@
"msm_otg", NULL),
OF_DEV_AUXDATA("qcom,spi-qup-v2", 0xF9924000, \
"spi_qsd.1", NULL),
+ OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
+ "spmi-pmic-arb.0", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index c0b1d16..06fbb7b 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -22,6 +22,7 @@
#include <mach/irqs-7xxx.h>
#include "devices-msm7x2xa.h"
#include "board-msm7627a.h"
+#include <mach/vreg.h>
#ifdef CONFIG_MSM_CAMERA_V4L2
static uint32_t camera_off_gpio_table[] = {
@@ -177,6 +178,7 @@
static struct msm_camera_sensor_info msm_camera_sensor_s5k4e1_data = {
.sensor_name = "s5k4e1",
.sensor_reset_enable = 1,
+ .pmic_gpio_enable = 0,
.pdata = &msm_camera_device_data_csi1,
.flash_data = &flash_s5k4e1,
.sensor_platform_info = &sensor_board_info_s5k4e1,
@@ -205,6 +207,7 @@
static struct msm_camera_sensor_info msm_camera_sensor_mt9e013_data = {
.sensor_name = "mt9e013",
.sensor_reset_enable = 1,
+ .pmic_gpio_enable = 0,
.pdata = &msm_camera_device_data_csi1,
.flash_data = &flash_mt9e013,
.sensor_platform_info = &sensor_board_info_mt9e013,
@@ -227,6 +230,7 @@
.sensor_name = "imx072",
.sensor_reset_enable = 1,
.sensor_reset = GPIO_CAM_GP_CAMIF_RESET_N, /* TODO 106,*/
+ .pmic_gpio_enable = 0,
.sensor_pwd = 85,
.vcm_pwd = GPIO_CAM_GP_CAM_PWDN,
.vcm_enable = 1,
@@ -261,6 +265,7 @@
static struct msm_camera_sensor_info msm_camera_sensor_ov9726_data = {
.sensor_name = "ov9726",
.sensor_reset_enable = 0,
+ .pmic_gpio_enable = 0,
.pdata = &msm_camera_device_data_csi0,
.flash_data = &flash_ov9726,
.sensor_platform_info = &sensor_board_info_ov9726,
@@ -385,6 +390,85 @@
gpio_direction_output(QRD_GPIO_CAM_3MP_PWDN, 1);
}
+#define GPIO_SKU3_CAM_5MP_SHDN_N 5 /* PWDN */
+#define GPIO_SKU3_CAM_5MP_CAMIF_RESET 6 /* (board_is(EVT))?123:121 RESET */
+#define GPIO_SKU3_CAM_5MP_CAM_DRIVER_PWDN 30
+
+#define GPIO_SKU1_CAM_VGA_SHDN 18
+#define GPIO_SKU1_CAM_VGA_RESET_N 29
+
+static void evb_camera_gpio_cfg(void)
+{
+ int rc = 0;
+
+ rc = gpio_request(GPIO_SKU3_CAM_5MP_SHDN_N, "ov5647");
+ if (rc < 0)
+ pr_err("%s: gpio_request GPIO_SKU3_CAM_5MP_SHDN_N failed!",
+ __func__);
+
+ pr_debug("gpio_tlmm_config %d\r\n", GPIO_SKU3_CAM_5MP_SHDN_N);
+ rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU3_CAM_5MP_SHDN_N, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("%s:unable to enable Powr Dwn gpio for main camera!\n",
+ __func__);
+ gpio_free(GPIO_SKU3_CAM_5MP_SHDN_N);
+ }
+
+ gpio_direction_output(GPIO_SKU3_CAM_5MP_SHDN_N, 1);
+
+ rc = gpio_request(GPIO_SKU3_CAM_5MP_CAMIF_RESET, "ov5647");
+ if (rc < 0)
+ pr_err("%s: gpio_request GPIO_SKU3_CAM_5MP_CAMIF_RESET failed!",
+ __func__);
+
+ pr_debug("gpio_tlmm_config %d\r\n", GPIO_SKU3_CAM_5MP_CAMIF_RESET);
+ rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU3_CAM_5MP_CAMIF_RESET, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("%s: unable to enable reset gpio for main camera!\n",
+ __func__);
+ gpio_free(GPIO_SKU3_CAM_5MP_CAMIF_RESET);
+ }
+
+ gpio_direction_output(GPIO_SKU3_CAM_5MP_CAMIF_RESET, 1);
+
+ rc = gpio_request(GPIO_SKU1_CAM_VGA_SHDN, "ov7692");
+ if (rc < 0)
+ pr_err("%s: gpio_request---GPIO_SKU1_CAM_VGA_SHDN failed!",
+ __func__);
+
+ rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU1_CAM_VGA_SHDN, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+ GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("%s:unable to enable Powr Dwn gpio for frnt camera!\n",
+ __func__);
+ gpio_free(GPIO_SKU1_CAM_VGA_SHDN);
+ }
+
+ gpio_direction_output(GPIO_SKU1_CAM_VGA_SHDN, 1);
+
+ rc = gpio_request(GPIO_SKU1_CAM_VGA_RESET_N, "ov7692");
+ if (rc < 0)
+ pr_err("%s: gpio_request---GPIO_SKU1_CAM_VGA_RESET_N failed!",
+ __func__);
+
+ rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU1_CAM_VGA_RESET_N, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+ GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+
+ if (rc < 0) {
+ pr_err("%s: unable to enable reset gpio for front camera!\n",
+ __func__);
+ gpio_free(GPIO_SKU1_CAM_VGA_RESET_N);
+ }
+ gpio_direction_output(GPIO_SKU1_CAM_VGA_RESET_N, 1);
+
+}
+
static void msm_camera_vreg_config(int vreg_en)
{
int rc = vreg_en ?
@@ -495,6 +579,45 @@
.ioext.appsz = MSM7XXX_CLK_CTL_SIZE,
};
+#ifdef CONFIG_OV5647
+
+static struct msm_camera_sensor_platform_info ov5647_sensor_7627a_info = {
+ .mount_angle = 90
+};
+
+static struct msm_camera_sensor_flash_src msm_flash_src_ov5647 = {
+ .flash_sr_type = MSM_CAMERA_FLASH_SRC_LED,
+ ._fsrc.led_src.led_name = "flashlight",
+ ._fsrc.led_src.led_name_len = 10,
+};
+
+static struct msm_camera_sensor_flash_data flash_ov5647 = {
+ .flash_type = MSM_CAMERA_FLASH_LED,
+ .flash_src = &msm_flash_src_ov5647,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov5647_data = {
+ .sensor_name = "ov5647",
+ .sensor_reset_enable = 1,
+ .sensor_reset = GPIO_SKU3_CAM_5MP_CAMIF_RESET,
+ .pmic_gpio_enable = 1,
+ .sensor_pwd = GPIO_SKU3_CAM_5MP_SHDN_N,
+ .vcm_pwd = GPIO_SKU3_CAM_5MP_CAM_DRIVER_PWDN,
+ .vcm_enable = 1,
+ .pdata = &msm_camera_device_data_rear,
+ .flash_data = &flash_ov5647,
+ .sensor_platform_info = &ov5647_sensor_7627a_info,
+ .csi_if = 1
+};
+
+static struct platform_device msm_camera_sensor_ov5647 = {
+ .name = "msm_camera_ov5647",
+ .dev = {
+ .platform_data = &msm_camera_sensor_ov5647_data,
+ },
+};
+#endif
+
#ifdef CONFIG_S5K4E1
static struct msm_camera_sensor_platform_info s5k4e1_sensor_7627a_info = {
.mount_angle = 90
@@ -509,6 +632,7 @@
.sensor_name = "s5k4e1",
.sensor_reset_enable = 1,
.sensor_reset = GPIO_CAM_GP_CAMIF_RESET_N,
+ .pmic_gpio_enable = 0,
.sensor_pwd = 85,
.vcm_pwd = GPIO_CAM_GP_CAM_PWDN,
.vcm_enable = 1,
@@ -540,6 +664,7 @@
.sensor_name = "imx072",
.sensor_reset_enable = 1,
.sensor_reset = GPIO_CAM_GP_CAMIF_RESET_N, /* TODO 106,*/
+ .pmic_gpio_enable = 0,
.sensor_pwd = 85,
.vcm_pwd = GPIO_CAM_GP_CAM_PWDN,
.vcm_enable = 1,
@@ -572,6 +697,7 @@
.sensor_name = "ov9726",
.sensor_reset_enable = 0,
.sensor_reset = GPIO_CAM_GP_CAM1MP_XCLR,
+ .pmic_gpio_enable = 0,
.sensor_pwd = 85,
.vcm_pwd = 1,
.vcm_enable = 0,
@@ -605,6 +731,7 @@
.sensor_name = "mt9e013",
.sensor_reset = 0,
.sensor_reset_enable = 1,
+ .pmic_gpio_enable = 0,
.sensor_pwd = 85,
.vcm_pwd = 1,
.vcm_enable = 0,
@@ -641,6 +768,7 @@
static struct msm_camera_sensor_info msm_camera_sensor_ov5640_data = {
.sensor_name = "ov5640",
.sensor_reset_enable = 1,
+ .pmic_gpio_enable = 0,
.sensor_reset = QRD_GPIO_CAM_5MP_RESET,
.sensor_pwd = QRD_GPIO_CAM_5MP_SHDN_EN,
.vcm_pwd = 0,
@@ -671,8 +799,9 @@
static struct msm_camera_sensor_info msm_camera_sensor_ov7692_data = {
.sensor_name = "ov7692",
.sensor_reset_enable = 0,
- .sensor_reset = 0,
- .sensor_pwd = QRD_GPIO_CAM_3MP_PWDN,
+ .pmic_gpio_enable = 1,
+ .sensor_reset = GPIO_SKU1_CAM_VGA_RESET_N,
+ .sensor_pwd = GPIO_SKU1_CAM_VGA_SHDN,
.vcm_pwd = 0,
.vcm_enable = 0,
.pdata = &msm_camera_device_data_front,
@@ -731,6 +860,22 @@
#endif
};
+static struct i2c_board_info i2c_camera_devices_evb[] = {
+ #ifdef CONFIG_OV5647
+ {
+ I2C_BOARD_INFO("ov5647", 0x36 << 1),
+ },
+ {
+ I2C_BOARD_INFO("ov5647_af", 0x18 >> 1),
+ },
+ #endif
+ #ifdef CONFIG_WEBCAM_OV7692_QRD
+ {
+ I2C_BOARD_INFO("ov7692", 0x78),
+ },
+ #endif
+};
+
static struct platform_device *camera_devices_msm[] __initdata = {
#ifdef CONFIG_S5K4E1
&msm_camera_sensor_s5k4e1,
@@ -754,6 +899,15 @@
&msm_camera_sensor_ov7692,
#endif
};
+
+static struct platform_device *camera_devices_evb[] __initdata = {
+#ifdef CONFIG_OV5647
+ &msm_camera_sensor_ov5647,
+#endif
+#ifdef CONFIG_WEBCAM_OV7692_QRD
+ &msm_camera_sensor_ov7692,
+#endif
+};
#endif
enum {
@@ -785,24 +939,127 @@
ARRAY_SIZE(cam_exp_i2c_info));
}
+#define LCD_CAMERA_LDO_2V8 35 /* SKU1&SKU3 2.8V LDO */
+#define SKU3_LCD_CAMERA_LDO_1V8 40 /* SKU3 1.8V LDO */
+
+static int lcd_camera_ldo_1v8 = SKU3_LCD_CAMERA_LDO_1V8;
+
+static void lcd_camera_power_init(void)
+{
+ int rc = 0;
+
+ pr_debug("lcd_camera_power_init\n");
+
+ lcd_camera_ldo_1v8 = SKU3_LCD_CAMERA_LDO_1V8; /* SKU3 PVT */
+
+ /* LDO_EXT2V8 */
+ if (gpio_request(LCD_CAMERA_LDO_2V8, "lcd_camera_ldo_2v8")) {
+ pr_err("failed to request gpio lcd_camera_ldo_2v8\n");
+ return;
+ }
+
+ rc = gpio_tlmm_config(GPIO_CFG(LCD_CAMERA_LDO_2V8, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("%s: unable to enable lcd_camera_ldo_2v8!\n", __func__);
+ goto fail_gpio2;
+ }
+
+ /* LDO_EVT1V8 */
+ if (gpio_request(lcd_camera_ldo_1v8, "lcd_camera_ldo_1v8")) {
+ pr_err("failed to request gpio lcd_camera_ldo_1v8\n");
+ goto fail_gpio2;
+ }
+
+ rc = gpio_tlmm_config(GPIO_CFG(lcd_camera_ldo_1v8, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("%s: unable to enable lcd_camera_ldo_1v8!\n", __func__);
+ goto fail_gpio1;
+ }
+
+ return;
+
+fail_gpio1:
+ gpio_free(lcd_camera_ldo_1v8);
+fail_gpio2:
+ gpio_free(LCD_CAMERA_LDO_2V8);
+
+ return;
+}
+
+static int lcd_camera_power_on_sku3(void)
+{
+ int rc = 0;
+
+ pr_debug("turn on sku3 lcd_camera_ldo_1v8\n");
+ gpio_set_value_cansleep(lcd_camera_ldo_1v8, 1);
+
+ pr_debug("turn on sku3 lcd_camera_ldo\n");
+ gpio_set_value_cansleep(LCD_CAMERA_LDO_2V8, 1);
+
+ return rc;
+}
+
+static int lcd_camera_power_off_sku3(void)
+{
+ int rc = 0;
+
+ pr_debug("turn off sku3 lcd_camera_ldo_1v8\n");
+ gpio_set_value_cansleep(lcd_camera_ldo_1v8, 0);
+
+ pr_debug("turn off sku3 lcd_camera_ldo\n");
+ gpio_set_value_cansleep(LCD_CAMERA_LDO_2V8, 0);
+
+ gpio_free(lcd_camera_ldo_1v8);
+ gpio_free(LCD_CAMERA_LDO_2V8);
+
+ return rc;
+}
+
+int lcd_camera_power_onoff(int on)
+{
+ int rc = 0;
+
+ pr_debug("lcd_camera_power_onoff on = %d,\n", on);
+
+ if (on)
+ rc = lcd_camera_power_on_sku3();
+ else
+ rc = lcd_camera_power_off_sku3();
+
+ return rc;
+}
+EXPORT_SYMBOL(lcd_camera_power_onoff);
+
+
void __init msm7627a_camera_init(void)
{
int rc;
+ pr_debug("msm7627a_camera_init Entered\n");
+ /* LCD and camera power (VREG & LDO) init */
+ if (machine_is_msm7627a_evb())
+ lcd_camera_power_init();
+
#ifndef CONFIG_MSM_CAMERA_V4L2
if (machine_is_msm7627a_qrd1()) {
qrd1_camera_gpio_cfg();
platform_add_devices(camera_devices_qrd,
ARRAY_SIZE(camera_devices_qrd));
- } else if (machine_is_msm7627a_evb())
- return;
- else if (machine_is_msm7627a_qrd3())
+ } else if (machine_is_msm7627a_evb()) {
+ evb_camera_gpio_cfg();
+ platform_add_devices(camera_devices_evb,
+ ARRAY_SIZE(camera_devices_evb));
+ } else if (machine_is_msm7627a_qrd3())
return;
else
platform_add_devices(camera_devices_msm,
ARRAY_SIZE(camera_devices_msm));
#endif
- if (!machine_is_msm7627a_qrd1())
+ if (!machine_is_msm7627a_qrd1() || !machine_is_msm7627a_evb())
register_i2c_devices();
rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
@@ -822,11 +1079,16 @@
msm7x27a_init_cam();
#endif
#ifndef CONFIG_MSM_CAMERA_V4L2
- if (machine_is_msm7627a_qrd1())
+ if (machine_is_msm7627a_qrd1()) {
i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
i2c_camera_devices_qrd,
ARRAY_SIZE(i2c_camera_devices_qrd));
- else
+ } else if (machine_is_msm7627a_evb()) {
+ pr_debug("machine_is_msm7627a_evb i2c_register_board_info\n");
+ i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
+ i2c_camera_devices_evb,
+ ARRAY_SIZE(i2c_camera_devices_evb));
+ } else
#endif
i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
i2c_camera_devices,
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 011a4d4..4e856b1 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -28,10 +28,10 @@
#include "board-msm7627a.h"
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE 0x260000
+#define MSM_FB_SIZE 0x261000
#define MSM7x25A_MSM_FB_SIZE 0xE1000
#else
-#define MSM_FB_SIZE 0x195000
+#define MSM_FB_SIZE 0x196000
#define MSM7x25A_MSM_FB_SIZE 0x96000
#endif
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 93a6178..88a519d 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -26,6 +26,7 @@
|| defined(CONFIG_MMC_MSM_SDC3_SUPPORT)\
|| defined(CONFIG_MMC_MSM_SDC4_SUPPORT))
+#define MAX_SDCC_CONTROLLER 4
static unsigned long vreg_sts, gpio_sts;
struct sdcc_gpio {
@@ -72,17 +73,17 @@
};
static struct msm_gpio sdc2_sleep_cfg_data[] = {
- {GPIO_CFG(62, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ {GPIO_CFG(62, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
"sdc2_clk"},
- {GPIO_CFG(63, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ {GPIO_CFG(63, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
"sdc2_cmd"},
- {GPIO_CFG(64, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ {GPIO_CFG(64, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
"sdc2_dat_3"},
- {GPIO_CFG(65, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ {GPIO_CFG(65, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
"sdc2_dat_2"},
- {GPIO_CFG(66, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ {GPIO_CFG(66, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
"sdc2_dat_1"},
- {GPIO_CFG(67, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ {GPIO_CFG(67, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
"sdc2_dat_0"},
};
static struct msm_gpio sdc3_cfg_data[] = {
@@ -152,7 +153,7 @@
gpio_sdc1_hw_det = 42;
}
-static struct regulator *sdcc_vreg_data[ARRAY_SIZE(sdcc_cfg_data)];
+static struct regulator *sdcc_vreg_data[MAX_SDCC_CONTROLLER];
static int msm_sdcc_setup_gpio(int dev_id, unsigned int enable)
{
int rc = 0;
@@ -377,14 +378,14 @@
#endif
/* SDIO WLAN slot */
#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
- if (mmc_regulator_init(2, "mmc", 2850000))
+ if (mmc_regulator_init(2, "smps3", 1800000))
return;
msm_add_sdcc(2, &sdc2_plat_data);
#endif
/* Not Used */
#if (defined(CONFIG_MMC_MSM_SDC4_SUPPORT)\
&& !defined(CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT))
- if (mmc_regulator_init(4, "mmc", 2850000))
+ if (mmc_regulator_init(4, "smps3", 1800000))
return;
msm_add_sdcc(4, &sdc4_plat_data);
#endif
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 51da14b..a6b29dc 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -47,6 +47,7 @@
#include <mach/msm_battery.h>
#include <linux/smsc911x.h>
#include <linux/atmel_maxtouch.h>
+#include <linux/fmem.h>
#include "devices.h"
#include "timer.h"
#include "board-msm7x27a-regulator.h"
@@ -370,6 +371,9 @@
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
.cached = 1,
.memory_type = MEMTYPE_EBI1,
+ .request_region = request_fmem_c_region,
+ .release_region = release_fmem_c_region,
+ .reusable = 1,
};
static struct platform_device android_pmem_adsp_device = {
@@ -672,6 +676,14 @@
static void msm7x27a_cfg_uart2dm_serial(void) { }
#endif
+struct fmem_platform_data fmem_pdata;
+
+struct platform_device fmem_device = {
+ .name = "fmem",
+ .id = -1,
+ .dev = { .platform_data = &fmem_pdata },
+};
+
static struct platform_device *rumi_sim_devices[] __initdata = {
&msm_device_dmov,
&msm_device_smd,
@@ -700,6 +712,7 @@
&msm_gsbi1_qup_i2c_device,
&msm_device_otg,
&msm_device_gadget_peripheral,
+ &fmem_device,
&android_usb_device,
&android_pmem_device,
&android_pmem_adsp_device,
@@ -744,8 +757,19 @@
},
};
+#ifdef CONFIG_ANDROID_PMEM
+static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
+ &android_pmem_adsp_pdata,
+ &android_pmem_audio_pdata,
+ &android_pmem_pdata,
+};
+#endif
+
static void __init size_pmem_devices(void)
{
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned int i;
+ unsigned int reusable_count = 0;
if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
@@ -755,11 +779,30 @@
pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
}
-#ifdef CONFIG_ANDROID_PMEM
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_pdata.size = pmem_mdp_size;
android_pmem_audio_pdata.size = pmem_audio_size;
+
+ fmem_pdata.size = 0;
+
+ /* Find pmem devices that should use FMEM (reusable) memory.
+ */
+ for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+ struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
+
+ if (!reusable_count && pdata->reusable)
+ fmem_pdata.size += pdata->size;
+
+ reusable_count += (pdata->reusable) ? 1 : 0;
+
+ if (pdata->reusable && reusable_count > 1) {
+ pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
+ __func__, pdata->name);
+ pdata->reusable = 0;
+ }
+ }
#endif
+
}
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
@@ -770,9 +813,12 @@
static void __init reserve_pmem_memory(void)
{
#ifdef CONFIG_ANDROID_PMEM
- reserve_memory_for(&android_pmem_adsp_pdata);
- reserve_memory_for(&android_pmem_pdata);
- reserve_memory_for(&android_pmem_audio_pdata);
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+ if (!pmem_pdata_array[i]->reusable)
+ reserve_memory_for(pmem_pdata_array[i]);
+ }
+
msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
#endif
}
@@ -798,6 +844,7 @@
{
reserve_info = &msm7x27a_reserve_info;
msm_reserve();
+ fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
}
static void __init msm8625_reserve(void)
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 47a4605..260c880 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -118,6 +118,7 @@
#define OPTNAV_I2C_SLAVE_ADDR (0xB0 >> 1)
#define OPTNAV_IRQ 20
#define OPTNAV_CHIP_SELECT 19
+#define PMIC_GPIO_SDC4_PWR_EN_N 24 /* PMIC GPIO Number 25 */
/* Macros assume PMIC GPIOs start at 0 */
#define PM8058_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio + NR_GPIO_IRQS)
@@ -167,6 +168,19 @@
},
};
+ struct pm8xxx_gpio_init_info sdc4_pwr_en = {
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_PWR_EN_N),
+ {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .vin_sel = PM8058_GPIO_VIN_L5,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ .out_strength = PM_GPIO_STRENGTH_LOW,
+ .output_value = 0,
+ },
+ };
+
struct pm8xxx_gpio_init_info haptics_enable = {
PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE),
{
@@ -294,6 +308,23 @@
}
gpio_set_value_cansleep(sdc4_en.gpio, 0);
}
+ /* FFA -> gpio_25 controls vdd of sdcc4 */
+ else {
+ /* SCD4 gpio_25 */
+ rc = pm8xxx_gpio_config(sdc4_pwr_en.gpio, &sdc4_pwr_en.config);
+ if (rc) {
+ pr_err("%s PMIC_GPIO_SDC4_PWR_EN_N config failed: %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ rc = gpio_request(sdc4_pwr_en.gpio, "sdc4_pwr_en");
+ if (rc) {
+ pr_err("PMIC_GPIO_SDC4_PWR_EN_N gpio_req failed: %d\n",
+ rc);
+ return rc;
+ }
+ }
return 0;
}
@@ -5478,9 +5509,24 @@
if (test_bit(dev_id, &vreg_sts) == enable)
return rc;
- if (!enable || enabled_once[dev_id - 1])
- return 0;
+ if (dev_id == 4) {
+ if (enable) {
+ pr_debug("Enable Vdd dev_%d\n", dev_id);
+ gpio_set_value_cansleep(
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_PWR_EN_N),
+ 0);
+ set_bit(dev_id, &vreg_sts);
+ } else {
+ pr_debug("Disable Vdd dev_%d\n", dev_id);
+ gpio_set_value_cansleep(
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_PWR_EN_N),
+ 1);
+ clear_bit(dev_id, &vreg_sts);
+ }
+ }
+ if (!enable || enabled_once[dev_id - 1])
+ return 0;
if (!curr)
return -ENODEV;
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 74ba1b3..e3fc97f 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2643,15 +2643,19 @@
#endif /* CONFIG_MSM_DSPS */
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1024 * 600 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1024 * 600 * 4), 4096) * 3) /* 4 bpp x 3 pages */
#else
-#define MSM_FB_PRIM_BUF_SIZE (1024 * 600 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1024 * 600 * 4), 4096) * 2) /* 4 bpp x 2 pages */
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE (1920 * 1080 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((1920 * 1080 * 2), 4096) * 1) /* 2 bpp x 1 page */
#elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
#else
#define MSM_FB_EXT_BUFT_SIZE 0
#endif
@@ -2703,10 +2707,11 @@
#define MSM_ION_MM_SIZE 0x3600000 /* (54MB) */
#define MSM_ION_MFC_SIZE SZ_8K
#define MSM_ION_WB_SIZE 0x600000 /* 6MB */
+#define MSM_ION_QSECOM_SIZE 0x300000 /* (3MB) */
#define MSM_ION_AUDIO_SIZE MSM_PMEM_AUDIO_SIZE
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_ION_HEAP_NUM 8
+#define MSM_ION_HEAP_NUM 9
#else
#define MSM_ION_HEAP_NUM 1
#endif
@@ -5278,6 +5283,18 @@
.align = PAGE_SIZE,
};
#endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
static struct ion_platform_data ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
@@ -5288,14 +5305,6 @@
},
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
{
- .id = ION_SF_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_SF_HEAP_NAME,
- .size = MSM_ION_SF_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = (void *)&co_ion_pdata,
- },
- {
.id = ION_CP_MM_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_MM_HEAP_NAME,
@@ -5312,14 +5321,6 @@
.extra_data = (void *) &fw_co_ion_pdata,
},
{
- .id = ION_CAMERA_HEAP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_CAMERA_HEAP_NAME,
- .size = MSM_ION_CAMERA_SIZE,
- .memory_type = ION_EBI_TYPE,
- .extra_data = &co_ion_pdata,
- },
- {
.id = ION_CP_MFC_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_MFC_HEAP_NAME,
@@ -5328,6 +5329,22 @@
.extra_data = (void *) &cp_mfc_ion_pdata,
},
{
+ .id = ION_SF_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SF_HEAP_NAME,
+ .size = MSM_ION_SF_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+ {
+ .id = ION_CAMERA_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_CAMERA_HEAP_NAME,
+ .size = MSM_ION_CAMERA_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .extra_data = &co_ion_pdata,
+ },
+ {
.id = ION_CP_WB_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_WB_HEAP_NAME,
@@ -5336,6 +5353,14 @@
.extra_data = (void *) &cp_wb_ion_pdata,
},
{
+ .id = ION_QSECOM_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_QSECOM_HEAP_NAME,
+ .size = MSM_ION_QSECOM_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .extra_data = (void *) &co_ion_pdata,
+ },
+ {
.id = ION_AUDIO_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name = ION_AUDIO_HEAP_NAME,
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 8374636..bd7ec87 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -146,7 +146,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = N16(m, n) | SPDIV(SRC_SEL_##s, div), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
#define F_MND8(f, nmsb, nlsb, s, div, m, n) \
@@ -155,7 +154,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(8, m, 0, n), \
.ns_val = N8(nmsb, nlsb, m, n) | SPDIV(SRC_SEL_##s, div), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_ops clk_ops_rcg_7x30;
@@ -227,14 +225,13 @@
static struct clk_ops clk_ops_tcxo = {
.enable = tcxo_clk_enable,
.disable = tcxo_clk_disable,
- .get_rate = fixed_clk_get_rate,
.is_local = pcom_is_local,
};
static struct fixed_clk tcxo_clk = {
- .rate = 19200000,
.c = {
.dbg_name = "tcxo_clk",
+ .rate = 19200000,
.ops = &clk_ops_tcxo,
CLK_INIT(tcxo_clk.c),
},
@@ -253,66 +250,65 @@
static struct clk_ops clk_ops_lpxo = {
.enable = lpxo_clk_enable,
.disable = lpxo_clk_disable,
- .get_rate = fixed_clk_get_rate,
.is_local = pcom_is_local,
};
static struct fixed_clk lpxo_clk = {
- .rate = 24576000,
.c = {
.dbg_name = "lpxo_clk",
+ .rate = 24576000,
.ops = &clk_ops_lpxo,
CLK_INIT(lpxo_clk.c),
},
};
static struct pll_vote_clk pll1_clk = {
- .rate = 768000000,
.en_reg = PLL_ENA_REG,
.en_mask = BIT(1),
.status_reg = PLL1_STATUS_BASE_REG,
.parent = &tcxo_clk.c,
.c = {
.dbg_name = "pll1_clk",
+ .rate = 768000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll1_clk.c),
},
};
static struct pll_vote_clk pll2_clk = {
- .rate = 806400000, /* TODO: Support scaling */
.en_reg = PLL_ENA_REG,
.en_mask = BIT(2),
.status_reg = PLL2_STATUS_BASE_REG,
.parent = &tcxo_clk.c,
.c = {
.dbg_name = "pll2_clk",
+ .rate = 806400000, /* TODO: Support scaling */
.ops = &clk_ops_pll_vote,
CLK_INIT(pll2_clk.c),
},
};
static struct pll_vote_clk pll3_clk = {
- .rate = 737280000,
.en_reg = PLL_ENA_REG,
.en_mask = BIT(3),
.status_reg = PLL3_STATUS_BASE_REG,
.parent = &lpxo_clk.c,
.c = {
.dbg_name = "pll3_clk",
+ .rate = 737280000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll3_clk.c),
},
};
static struct pll_vote_clk pll4_clk = {
- .rate = 891000000,
.en_reg = PLL_ENA_REG,
.en_mask = BIT(4),
.status_reg = PLL4_STATUS_BASE_REG,
.parent = &lpxo_clk.c,
.c = {
.dbg_name = "pll4_clk",
+ .rate = 891000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll4_clk.c),
},
@@ -321,7 +317,7 @@
static struct clk_ops clk_ops_branch;
static struct clk_freq_tbl clk_tbl_axi[] = {
- F_RAW(1, &lpxo_clk.c, 0, 0, 0, 0, NULL),
+ F_RAW(1, &lpxo_clk.c, 0, 0, 0, NULL),
F_END,
};
@@ -998,6 +994,7 @@
.ns_reg = CSI_NS_REG,
.md_reg = CSI_NS_REG - 4,
.ns_mask = F_MASK_MND8(24, 17),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_csi,
.current_freq = &rcg_dummy_freq,
@@ -1011,7 +1008,7 @@
};
static struct clk_freq_tbl clk_tbl_tcxo[] = {
- F_RAW(19200000, &tcxo_clk.c, 0, 0, 0, 0, NULL),
+ F_RAW(19200000, &tcxo_clk.c, 0, 0, 0, NULL),
F_END,
};
@@ -1142,6 +1139,7 @@
.ns_reg = UART1DM_NS_REG,
.md_reg = UART1DM_NS_REG - 4,
.root_en_mask = BIT(11),
+ .mnd_en_mask = BIT(8),
.freq_tbl = clk_tbl_uartdm,
.ns_mask = F_MASK_MND16,
.current_freq = &rcg_dummy_freq,
@@ -1167,6 +1165,7 @@
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_uartdm,
.ns_mask = F_MASK_MND16,
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.current_freq = &rcg_dummy_freq,
.c = {
@@ -1252,7 +1251,7 @@
F_BASIC(192000000, pll1, 4),
F_BASIC(245760000, pll3, 3),
/* Sync to AXI. Hence this "rate" is not fixed. */
- F_RAW(1, &lpxo_clk.c, 0, BIT(14), 0, 0, NULL),
+ F_RAW(1, &lpxo_clk.c, 0, BIT(14), 0, NULL),
F_END,
};
@@ -1354,6 +1353,7 @@
.ns_reg = SDCn_NS_REG(1),
.md_reg = SDCn_NS_REG(1) - 4,
.ns_mask = F_MASK_MND8(19, 12),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_sdc1_3,
.current_freq = &rcg_dummy_freq,
@@ -1377,6 +1377,7 @@
.ns_reg = SDCn_NS_REG(3),
.md_reg = SDCn_NS_REG(3) - 4,
.ns_mask = F_MASK_MND8(19, 12),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_sdc1_3,
.current_freq = &rcg_dummy_freq,
@@ -1412,6 +1413,7 @@
.ns_reg = SDCn_NS_REG(2),
.md_reg = SDCn_NS_REG(2) - 4,
.ns_mask = F_MASK_MND8(20, 13),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_sdc2_4,
.current_freq = &rcg_dummy_freq,
@@ -1435,6 +1437,7 @@
.ns_reg = SDCn_NS_REG(4),
.md_reg = SDCn_NS_REG(4) - 4,
.ns_mask = F_MASK_MND8(20, 13),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_sdc2_4,
.current_freq = &rcg_dummy_freq,
@@ -1505,6 +1508,7 @@
.md_reg = MDP_LCDC_NS_REG - 4,
.root_en_mask = BIT(11),
.ns_mask = F_MASK_MND16,
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_mdp_lcdc,
.current_freq = &rcg_dummy_freq,
@@ -1533,8 +1537,8 @@
};
static struct clk_freq_tbl clk_tbl_mdp_vsync[] = {
- F_RAW( 0, &gnd_clk.c, 0, (0x3<<2), 0, 0, NULL),
- F_RAW(24576000, &lpxo_clk.c, 0, (0x1<<2), 0, 0, NULL),
+ F_RAW( 0, &gnd_clk.c, 0, (0x3<<2), 0, NULL),
+ F_RAW(24576000, &lpxo_clk.c, 0, (0x1<<2), 0, NULL),
F_END,
};
@@ -1578,6 +1582,7 @@
.md_reg = MI2S_RX_NS_REG - 4,
.root_en_mask = BIT(11),
.ns_mask = F_MASK_MND16,
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_mi2s_codec,
.current_freq = &rcg_dummy_freq,
@@ -1617,6 +1622,7 @@
.md_reg = MI2S_TX_NS_REG - 4,
.root_en_mask = BIT(11),
.ns_mask = F_MASK_MND16,
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_mi2s_codec,
.current_freq = &rcg_dummy_freq,
@@ -1662,6 +1668,7 @@
.md_reg = MI2S_NS_REG - 4,
.root_en_mask = BIT(11),
.ns_mask = F_MASK_MND16,
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_mi2s,
.current_freq = &rcg_dummy_freq,
@@ -1694,7 +1701,6 @@
.freq_hz = f, \
.md_val = MD16(m, n), \
.ns_val = N16(m, n) | SPDIV(SRC_SEL_SDAC_##s, div), \
- .mnd_en_mask = BIT(8) * !!(n), \
.src_clk = &s##_clk.c, \
}
@@ -1722,6 +1728,7 @@
.ns_reg = SDAC_NS_REG,
.md_reg = SDAC_NS_REG - 4,
.root_en_mask = BIT(11),
+ .mnd_en_mask = BIT(8),
.freq_tbl = clk_tbl_sdac,
.ns_mask = F_MASK_MND16,
.set_rate = set_rate_mnd,
@@ -1765,6 +1772,7 @@
},
.md_reg = TV_NS_REG - 4,
.ns_mask = F_MASK_MND8(23, 16),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_tv,
.current_freq = &rcg_dummy_freq,
@@ -1856,6 +1864,7 @@
},
.md_reg = USBH_NS_REG - 4,
.ns_mask = F_MASK_MND8(23, 16),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_usb,
.current_freq = &rcg_dummy_freq,
@@ -1994,6 +2003,7 @@
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_vfe_jpeg,
.ns_mask = F_MASK_MND16,
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.current_freq = &rcg_dummy_freq,
.c = {
@@ -2018,6 +2028,7 @@
.root_en_mask = BIT(13),
.freq_tbl = clk_tbl_vfe_jpeg,
.ns_mask = F_MASK_MND16,
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.current_freq = &rcg_dummy_freq,
.c = {
@@ -2102,6 +2113,7 @@
.root_en_mask = BIT(9),
.freq_tbl = clk_tbl_cam,
.ns_mask = F_MASK_MND16,
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.current_freq = &rcg_dummy_freq,
.c = {
@@ -2134,6 +2146,7 @@
.ns_reg = VPE_NS_REG,
.md_reg = VPE_NS_REG - 4,
.ns_mask = F_MASK_MND8(22, 15),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_vpe,
.current_freq = &rcg_dummy_freq,
@@ -2170,6 +2183,7 @@
.ns_reg = MFC_NS_REG,
.md_reg = MFC_NS_REG - 4,
.ns_mask = F_MASK_MND8(24, 17),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_mfc,
.current_freq = &rcg_dummy_freq,
@@ -2218,6 +2232,7 @@
.ns_reg = SPI_NS_REG,
.md_reg = SPI_NS_REG - 4,
.ns_mask = F_MASK_MND8(19, 12),
+ .mnd_en_mask = BIT(8),
.root_en_mask = BIT(11),
.freq_tbl = clk_tbl_spi,
.current_freq = &rcg_dummy_freq,
@@ -2231,10 +2246,10 @@
};
static struct clk_freq_tbl clk_tbl_lpa_codec[] = {
- F_RAW(1, NULL, 0, 0, 0, 0, NULL), /* src MI2S_CODEC_RX */
- F_RAW(2, NULL, 0, 1, 0, 0, NULL), /* src ECODEC_CIF */
- F_RAW(3, NULL, 0, 2, 0, 0, NULL), /* src MI2S */
- F_RAW(4, NULL, 0, 3, 0, 0, NULL), /* src SDAC */
+ F_RAW(1, NULL, 0, 0, 0, NULL), /* src MI2S_CODEC_RX */
+ F_RAW(2, NULL, 0, 1, 0, NULL), /* src ECODEC_CIF */
+ F_RAW(3, NULL, 0, 2, 0, NULL), /* src MI2S */
+ F_RAW(4, NULL, 0, 3, 0, NULL), /* src SDAC */
F_END,
};
@@ -2260,7 +2275,7 @@
};
static struct clk_freq_tbl clk_tbl_mdc[] = {
- F_RAW(1, NULL, 0, 0, 0, 0, NULL),
+ F_RAW(1, NULL, 0, 0, 0, NULL),
F_END
};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 493a210..7c2788de 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -423,7 +423,7 @@
RPM_VREG_VOTER3, 1800000, 1800000, 1);
} else {
rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
- RPM_VREG_VOTER3, 2200000, 2200000, 1);
+ RPM_VREG_VOTER3, 2100000, 2100000, 1);
if (rc)
return rc;
rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
@@ -470,14 +470,13 @@
static struct clk_ops clk_ops_pxo = {
.enable = pxo_clk_enable,
.disable = pxo_clk_disable,
- .get_rate = fixed_clk_get_rate,
.is_local = local_clk_is_local,
};
static struct fixed_clk pxo_clk = {
- .rate = 27000000,
.c = {
.dbg_name = "pxo_clk",
+ .rate = 27000000,
.ops = &clk_ops_pxo,
CLK_INIT(pxo_clk.c),
},
@@ -496,36 +495,35 @@
static struct clk_ops clk_ops_cxo = {
.enable = cxo_clk_enable,
.disable = cxo_clk_disable,
- .get_rate = fixed_clk_get_rate,
.is_local = local_clk_is_local,
};
static struct fixed_clk cxo_clk = {
- .rate = 19200000,
.c = {
.dbg_name = "cxo_clk",
+ .rate = 19200000,
.ops = &clk_ops_cxo,
CLK_INIT(cxo_clk.c),
},
};
static struct pll_clk pll2_clk = {
- .rate = 800000000,
.mode_reg = MM_PLL1_MODE_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll2_clk",
+ .rate = 800000000,
.ops = &clk_ops_pll,
CLK_INIT(pll2_clk.c),
},
};
static struct pll_clk pll3_clk = {
- .rate = 1200000000,
.mode_reg = BB_MMCC_PLL2_MODE_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll3_clk",
+ .rate = 1200000000,
.ops = &clk_ops_pll,
.vdd_class = &vdd_sr2_pll,
.fmax[VDD_SR2_PLL_ON] = ULONG_MAX,
@@ -534,50 +532,50 @@
};
static struct pll_vote_clk pll4_clk = {
- .rate = 393216000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(4),
.status_reg = LCC_PLL0_STATUS_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll4_clk",
+ .rate = 393216000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll4_clk.c),
},
};
static struct pll_vote_clk pll8_clk = {
- .rate = 384000000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(8),
.status_reg = BB_PLL8_STATUS_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll8_clk",
+ .rate = 384000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll8_clk.c),
},
};
static struct pll_vote_clk pll14_clk = {
- .rate = 480000000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(14),
.status_reg = BB_PLL14_STATUS_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll14_clk",
+ .rate = 480000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll14_clk.c),
},
};
static struct pll_clk pll15_clk = {
- .rate = 975000000,
.mode_reg = MM_PLL3_MODE_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll15_clk",
+ .rate = 975000000,
.ops = &clk_ops_pll,
CLK_INIT(pll15_clk.c),
},
@@ -1246,6 +1244,7 @@
.md_reg = GPn_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gp, \
.current_freq = &rcg_dummy_freq, \
@@ -1262,7 +1261,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gp[] = {
F_GP( 0, gnd, 1, 0, 0),
@@ -1297,6 +1295,7 @@
.md_reg = GSBIn_UART_APPS_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(31, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gsbi_uart, \
.current_freq = &rcg_dummy_freq, \
@@ -1313,7 +1312,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
F_GSBI_UART( 0, gnd, 1, 0, 0),
@@ -1361,6 +1359,7 @@
.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gsbi_qup, \
.current_freq = &rcg_dummy_freq, \
@@ -1377,7 +1376,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
F_GSBI_QUP( 0, gnd, 1, 0, 0),
@@ -1500,6 +1498,7 @@
.md_reg = SDCn_APPS_CLK_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_sdc, \
.current_freq = &rcg_dummy_freq, \
@@ -1516,7 +1515,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_sdc[] = {
F_SDC( 0, gnd, 1, 0, 0),
@@ -1545,7 +1543,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_tsif_ref[] = {
F_TSIF_REF( 0, gnd, 1, 0, 0),
@@ -1564,6 +1561,7 @@
.md_reg = TSIF_REF_CLK_MD_REG,
.root_en_mask = BIT(11),
.ns_mask = (BM(31, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_tsif_ref,
.current_freq = &rcg_dummy_freq,
@@ -1621,6 +1619,7 @@
.md_reg = USB_HS##n##_XCVR_FS_CLK_MD_REG, \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_usb, \
.current_freq = &rcg_dummy_freq, \
@@ -1638,7 +1637,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_usb[] = {
F_USB( 0, gnd, 1, 0, 0),
@@ -1667,6 +1665,7 @@
.md_reg = USB_HSIC_XCVR_FS_CLK_MD_REG,
.root_en_mask = BIT(11),
.ns_mask = (BM(23, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_usb_hsic,
.current_freq = &rcg_dummy_freq,
@@ -1787,6 +1786,7 @@
.md_reg = USB_FSn_XCVR_FS_CLK_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_usb, \
.current_freq = &rcg_dummy_freq, \
@@ -2522,6 +2522,7 @@
.md_reg = CAMCLK##n##_MD_REG, \
.root_en_mask = BIT(2), \
.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0), \
+ .mnd_en_mask = BIT(5), \
.ctl_mask = BM(7, 6), \
.set_rate = set_rate_mnd_8, \
.freq_tbl = clk_tbl_cam, \
@@ -2540,7 +2541,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_cam[] = {
F_CAM( 0, gnd, 1, 0, 0),
@@ -2569,7 +2569,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_csi[] = {
F_CSI( 0, gnd, 1, 0, 0),
@@ -2588,6 +2587,7 @@
.md_reg = CSI0_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_csi,
@@ -2643,6 +2643,7 @@
.md_reg = CSI1_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_csi,
@@ -2698,6 +2699,7 @@
.md_reg = CSI2_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_csi,
@@ -3005,7 +3007,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_csi_phytimer[] = {
F_CSI_PHYTIMER( 0, gnd, 1, 0, 0),
@@ -3023,6 +3024,7 @@
.md_reg = CSIPHYTIMER_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(31, 24) | BM(15, 14) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd_8,
.freq_tbl = clk_tbl_csi_phytimer,
@@ -3194,7 +3196,6 @@
.md_val = MD4(4, m, 0, n), \
.ns_val = NS_MND_BANKED4(20, 16, n, m, 3, 0, s##_to_mm_mux), \
.ctl_val = CC_BANKED(9, 6, n), \
- .mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gfx2d[] = {
F_GFX2D( 0, gnd, 0, 0),
@@ -3308,7 +3309,6 @@
.md_val = MD4(4, m, 0, n), \
.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
.ctl_val = CC_BANKED(9, 6, n), \
- .mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gfx3d_8960[] = {
@@ -3410,7 +3410,6 @@
.md_val = MD4(4, m, 0, n), \
.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
.ctl_val = CC_BANKED(9, 6, n), \
- .mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_vcap[] = {
@@ -3487,7 +3486,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(23, 16, n, m, 15, 12, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_ijpeg[] = {
@@ -3527,6 +3525,7 @@
.md_reg = IJPEG_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(23, 16) | BM(15, 12) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_ijpeg,
@@ -3590,7 +3589,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MND_BANKED8(22, 14, n, m, 3, 0, s##_to_mm_mux), \
.ctl_val = CC_BANKED(9, 6, n), \
- .mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_mdp[] = {
F_MDP( 0, gnd, 0, 0),
@@ -3822,7 +3820,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
#define F_TV(f, s, p_r, d, m, n) \
{ \
@@ -3831,7 +3828,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
.extra_freq_data = (void *)p_r, \
}
/* Switching TV freqs requires PLL reconfiguration. */
@@ -3873,6 +3869,7 @@
.md_reg = TV_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(23, 16) | BM(15, 14) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_tv,
.freq_tbl = clk_tbl_tv,
@@ -3885,6 +3882,21 @@
},
};
+static struct cdiv_clk tv_src_div_clk = {
+ .b = {
+ .ctl_reg = TV_NS_REG,
+ .halt_check = NOCHECK,
+ },
+ .ns_reg = TV_NS_REG,
+ .div_offset = 6,
+ .max_div = 2,
+ .c = {
+ .dbg_name = "tv_src_div_clk",
+ .ops = &clk_ops_cdiv,
+ CLK_INIT(tv_src_div_clk.c),
+ },
+};
+
static struct branch_clk tv_enc_clk = {
.b = {
.ctl_reg = TV_CC_REG,
@@ -3953,6 +3965,36 @@
},
};
+static struct branch_clk rgb_tv_clk = {
+ .b = {
+ .ctl_reg = TV_CC2_REG,
+ .en_mask = BIT(14),
+ .halt_reg = DBG_BUS_VEC_J_REG,
+ .halt_bit = 27,
+ },
+ .parent = &tv_src_clk.c,
+ .c = {
+ .dbg_name = "rgb_tv_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(rgb_tv_clk.c),
+ },
+};
+
+static struct branch_clk npl_tv_clk = {
+ .b = {
+ .ctl_reg = TV_CC2_REG,
+ .en_mask = BIT(16),
+ .halt_reg = DBG_BUS_VEC_J_REG,
+ .halt_bit = 26,
+ },
+ .parent = &tv_src_clk.c,
+ .c = {
+ .dbg_name = "npl_tv_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(npl_tv_clk.c),
+ },
+};
+
static struct branch_clk hdmi_app_clk = {
.b = {
.ctl_reg = MISC_CC2_REG,
@@ -3993,7 +4035,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MND_BANKED8(11, 19, n, m, 0, 27, s##_to_mm_mux), \
.ctl_val = CC_BANKED(6, 11, n), \
- .mnd_en_mask = (BIT(10) | BIT(5)) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_vcodec[] = {
F_VCODEC( 0, gnd, 0, 0),
@@ -4087,7 +4128,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(23, 16, n, m, 11, 10, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_vfe[] = {
@@ -4133,6 +4173,7 @@
.md_reg = VFE_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(23, 16) | BM(11, 10) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_vfe,
@@ -4173,7 +4214,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(8, m, 0, n), \
.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_aif_osr[] = {
F_AIF_OSR( 0, gnd, 1, 0, 0),
@@ -4206,6 +4246,7 @@
.md_reg = md, \
.root_en_mask = BIT(9), \
.ns_mask = (BM(31, 24) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_aif_osr, \
.current_freq = &rcg_dummy_freq, \
@@ -4231,6 +4272,7 @@
.md_reg = md, \
.root_en_mask = BIT(9), \
.ns_mask = (BM(31, 24) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_aif_osr, \
.current_freq = &rcg_dummy_freq, \
@@ -4310,7 +4352,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_pcm[] = {
F_PCM( 0, gnd, 1, 0, 0),
@@ -4342,6 +4383,7 @@
.md_reg = LCC_PCM_MD_REG,
.root_en_mask = BIT(9),
.ns_mask = (BM(31, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_pcm,
.current_freq = &rcg_dummy_freq,
@@ -4367,6 +4409,7 @@
.md_reg = LCC_SLIMBUS_MD_REG,
.root_en_mask = BIT(9),
.ns_mask = (BM(31, 24) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_aif_osr,
.current_freq = &rcg_dummy_freq,
@@ -4632,6 +4675,8 @@
{ TEST_MM_HS(0x33), &vcap_clk.c },
{ TEST_MM_HS(0x34), &vcap_npl_clk.c },
{ TEST_MM_HS(0x35), &vcap_axi_clk.c },
+ { TEST_MM_HS(0x36), &rgb_tv_clk.c },
+ { TEST_MM_HS(0x37), &npl_tv_clk.c },
{ TEST_MM_HS(0x38), &gfx3d_axi_clk.c },
{ TEST_LPA(0x0F), &mi2s_bit_clk.c },
@@ -4842,6 +4887,7 @@
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.1"),
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.2"),
CLK_LOOKUP("xo", cxo_clk.c, "pil_gss"),
+ CLK_LOOKUP("xo", cxo_clk.c, "BAM_RMNT"),
CLK_LOOKUP("pll2", pll2_clk.c, NULL),
CLK_LOOKUP("pll8", pll8_clk.c, NULL),
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
@@ -4877,10 +4923,10 @@
CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi6_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi7_uart_clk.c, "msm_serial_hsl.0"),
- CLK_LOOKUP("core_clk", gsbi1_qup_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi1_qup_clk.c, "qup_i2c.0"),
CLK_LOOKUP("core_clk", gsbi2_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi3_qup_clk.c, "qup_i2c.3"),
- CLK_LOOKUP("core_clk", gsbi4_qup_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi4_qup_clk.c, "qup_i2c.4"),
CLK_LOOKUP("core_clk", gsbi5_qup_clk.c, "spi_qsd.0"),
CLK_LOOKUP("core_clk", gsbi6_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi7_qup_clk.c, ""),
@@ -4911,9 +4957,10 @@
CLK_LOOKUP("ce3_core_src_clk", ce3_src_clk.c, "qcrypto.0"),
CLK_LOOKUP("dma_bam_pclk", dma_bam_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", gsbi1_p_clk.c, "msm_serial_hsl.1"),
+ CLK_LOOKUP("iface_clk", gsbi1_p_clk.c, "qup_i2c.0"),
CLK_LOOKUP("iface_clk", gsbi2_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi3_p_clk.c, "qup_i2c.3"),
- CLK_LOOKUP("iface_clk", gsbi4_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gsbi4_p_clk.c, "qup_i2c.4"),
CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "spi_qsd.0"),
CLK_LOOKUP("iface_clk", gsbi6_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi7_p_clk.c, "msm_serial_hsl.0"),
@@ -4934,38 +4981,38 @@
CLK_LOOKUP("core_clk", pmic_ssbi2_clk.c, ""),
CLK_LOOKUP("mem_clk", rpm_msg_ram_p_clk.c, ""),
CLK_LOOKUP("core_clk", amp_clk.c, ""),
- CLK_LOOKUP("cam_clk", cam0_clk.c, ""),
- CLK_LOOKUP("cam_clk", cam1_clk.c, ""),
- CLK_LOOKUP("cam_clk", cam0_clk.c, ""),
- CLK_LOOKUP("cam_clk", cam0_clk.c, ""),
- CLK_LOOKUP("cam_clk", cam0_clk.c, ""),
- CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, ""),
- CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, ""),
- CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, ""),
- CLK_LOOKUP("csi_src_clk", csi2_src_clk.c, ""),
- CLK_LOOKUP("csi_clk", csi0_clk.c, ""),
- CLK_LOOKUP("csi_clk", csi1_clk.c, ""),
- CLK_LOOKUP("csi_clk", csi1_clk.c, ""),
- CLK_LOOKUP("csi_clk", csi2_clk.c, ""),
- CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, ""),
- CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, ""),
- CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, ""),
- CLK_LOOKUP("csi_phy_clk", csi2_phy_clk.c, ""),
- CLK_LOOKUP("csi_pix_clk", csi_pix_clk.c, ""),
- CLK_LOOKUP("csi_pix_clk", csi_pix1_clk.c, ""),
- CLK_LOOKUP("csi_rdi_clk", csi_rdi_clk.c, ""),
- CLK_LOOKUP("csi_rdi_clk", csi_rdi1_clk.c, ""),
- CLK_LOOKUP("csi_rdi_clk", csi_rdi2_clk.c, ""),
- CLK_LOOKUP("csiphy_timer_src_clk", csiphy_timer_src_clk.c, ""),
- CLK_LOOKUP("csiphy_timer_clk", csi0phy_timer_clk.c, ""),
- CLK_LOOKUP("csiphy_timer_clk", csi1phy_timer_clk.c, ""),
- CLK_LOOKUP("csiphy_timer_clk", csi2phy_timer_clk.c, ""),
+ CLK_LOOKUP("cam_clk", cam0_clk.c, "4-001a"),
+ CLK_LOOKUP("cam_clk", cam1_clk.c, "4-006c"),
+ 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"),
+ CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_clk", csi2_clk.c, "msm_csid.2"),
+ CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_phy_clk", csi2_phy_clk.c, "msm_csid.2"),
+ CLK_LOOKUP("csi_pix_clk", csi_pix_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_pix1_clk", csi_pix1_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_rdi_clk", csi_rdi_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_rdi1_clk", csi_rdi1_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_rdi2_clk", csi_rdi2_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csiphy_timer_src_clk",
+ csiphy_timer_src_clk.c, "msm_csiphy.0"),
+ CLK_LOOKUP("csiphy_timer_src_clk",
+ csiphy_timer_src_clk.c, "msm_csiphy.1"),
+ CLK_LOOKUP("csiphy_timer_src_clk",
+ csiphy_timer_src_clk.c, "msm_csiphy.2"),
+ CLK_LOOKUP("csiphy_timer_clk", csi0phy_timer_clk.c, "msm_csiphy.0"),
+ CLK_LOOKUP("csiphy_timer_clk", csi1phy_timer_clk.c, "msm_csiphy.1"),
+ CLK_LOOKUP("csiphy_timer_clk", csi2phy_timer_clk.c, "msm_csiphy.2"),
CLK_LOOKUP("dsi_byte_div_clk", dsi1_byte_clk.c, NULL),
CLK_LOOKUP("dsi_byte_div_clk", dsi2_byte_clk.c, NULL),
CLK_LOOKUP("dsi_esc_clk", dsi1_esc_clk.c, NULL),
CLK_LOOKUP("dsi_esc_clk", dsi2_esc_clk.c, NULL),
- CLK_DUMMY("rgb_tv_clk", RGB_TV_CLK, "", OFF),
- CLK_DUMMY("npl_tv_clk", NPL_TV_CLK, "", OFF),
+ CLK_LOOKUP("rgb_clk", rgb_tv_clk.c, ""),
+ CLK_LOOKUP("npl_clk", npl_tv_clk.c, ""),
+
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("bus_clk", gfx3d_axi_clk.c, "footswitch-8x60.2"),
@@ -4988,18 +5035,20 @@
CLK_LOOKUP("lut_clk", lut_mdp_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("core_clk", rot_clk.c, "msm_rotator.0"),
CLK_LOOKUP("core_clk", rot_clk.c, "footswitch-8x60.6"),
- CLK_DUMMY("tv_src_clk", TV_SRC_CLK, NULL, OFF),
+ CLK_LOOKUP("tv_src_clk", tv_src_clk.c, "footswitch-8x60.4"),
+ CLK_LOOKUP("tv_src_clk", tv_src_clk.c, ""),
+ CLK_LOOKUP("tv_src_div_clk", tv_src_div_clk.c, ""),
CLK_LOOKUP("core_clk", vcodec_clk.c, "msm_vidc.0"),
CLK_LOOKUP("core_clk", vcodec_clk.c, "footswitch-8x60.7"),
- CLK_DUMMY("mdp_tv_clk", MDP_TV_CLK, NULL, OFF),
- CLK_DUMMY("tv_clk", MDP_TV_CLK, "footswitch-8x60.4", OFF),
- CLK_DUMMY("hdmi_clk", HDMI_TV_CLK, "", OFF),
+ CLK_LOOKUP("mdp_tv_clk", mdp_tv_clk.c, ""),
+ CLK_LOOKUP("tv_clk", mdp_tv_clk.c, "footswitch-8x60.4"),
+ CLK_LOOKUP("hdmi_clk", hdmi_tv_clk.c, ""),
CLK_LOOKUP("core_clk", hdmi_app_clk.c, ""),
CLK_LOOKUP("vpe_clk", vpe_clk.c, ""),
CLK_LOOKUP("core_clk", vpe_clk.c, "footswitch-8x60.9"),
- CLK_LOOKUP("vfe_clk", vfe_clk.c, ""),
+ CLK_LOOKUP("vfe_clk", vfe_clk.c, "msm_vfe.0"),
CLK_LOOKUP("core_clk", vfe_clk.c, "footswitch-8x60.8"),
- CLK_LOOKUP("csi_vfe_clk", csi_vfe_clk.c, ""),
+ CLK_LOOKUP("csi_vfe_clk", csi_vfe_clk.c, "msm_vfe.0"),
CLK_LOOKUP("bus_clk", vfe_axi_clk.c, "footswitch-8x60.8"),
CLK_LOOKUP("bus_clk", mdp_axi_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("bus_clk", rot_axi_clk.c, "footswitch-8x60.6"),
@@ -5008,7 +5057,9 @@
CLK_LOOKUP("bus_b_clk", vcodec_axi_b_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("bus_clk", vpe_axi_clk.c, "footswitch-8x60.9"),
CLK_LOOKUP("amp_pclk", amp_p_clk.c, NULL),
- CLK_LOOKUP("csi_pclk", csi_p_clk.c, ""),
+ CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.2"),
CLK_LOOKUP("dsi_m_pclk", dsi1_m_p_clk.c, NULL),
CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, NULL),
CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, NULL),
@@ -5028,24 +5079,32 @@
CLK_LOOKUP("iface_clk", rot_p_clk.c, "footswitch-8x60.6"),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "msm_vidc.0"),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "footswitch-8x60.7"),
- CLK_LOOKUP("vfe_pclk", vfe_p_clk.c, ""),
+ CLK_LOOKUP("vfe_pclk", vfe_p_clk.c, "msm_vfe.0"),
CLK_LOOKUP("iface_clk", vfe_p_clk.c, "footswitch-8x60.8"),
CLK_LOOKUP("vpe_pclk", vpe_p_clk.c, ""),
- CLK_LOOKUP("iface_pclk", vpe_p_clk.c, "footswitch-8x60.9"),
+ CLK_LOOKUP("iface_clk", vpe_p_clk.c, "footswitch-8x60.9"),
- CLK_LOOKUP("mi2s_bit_clk", mi2s_bit_clk.c, ""),
- CLK_LOOKUP("mi2s_osr_clk", mi2s_osr_clk.c, ""),
- CLK_LOOKUP("i2s_mic_bit_clk", codec_i2s_mic_bit_clk.c, ""),
- CLK_LOOKUP("i2s_mic_osr_clk", codec_i2s_mic_osr_clk.c, ""),
- CLK_LOOKUP("i2s_mic_bit_clk", spare_i2s_mic_bit_clk.c, ""),
- CLK_LOOKUP("i2s_mic_osr_clk", spare_i2s_mic_osr_clk.c, ""),
- CLK_LOOKUP("i2s_spkr_bit_clk", codec_i2s_spkr_bit_clk.c, ""),
- CLK_LOOKUP("i2s_spkr_osr_clk", codec_i2s_spkr_osr_clk.c, ""),
- CLK_LOOKUP("i2s_spkr_bit_clk", spare_i2s_spkr_bit_clk.c, ""),
- CLK_LOOKUP("i2s_spkr_osr_clk", spare_i2s_spkr_osr_clk.c, ""),
- CLK_LOOKUP("pcm_clk", pcm_clk.c, ""),
+ CLK_LOOKUP("bit_clk", mi2s_bit_clk.c, "msm-dai-q6.6"),
+ CLK_LOOKUP("osr_clk", mi2s_osr_clk.c, "msm-dai-q6.6"),
+ CLK_LOOKUP("bit_clk", codec_i2s_mic_bit_clk.c,
+ "msm-dai-q6.1"),
+ CLK_LOOKUP("osr_clk", codec_i2s_mic_osr_clk.c,
+ "msm-dai-q6.1"),
+ CLK_LOOKUP("bit_clk", spare_i2s_mic_bit_clk.c,
+ "msm-dai-q6.5"),
+ CLK_LOOKUP("osr_clk", spare_i2s_mic_osr_clk.c,
+ "msm-dai-q6.5"),
+ CLK_LOOKUP("bit_clk", codec_i2s_spkr_bit_clk.c,
+ "msm-dai-q6.16384"),
+ CLK_LOOKUP("osr_clk", codec_i2s_spkr_osr_clk.c,
+ "msm-dai-q6.16384"),
+ CLK_LOOKUP("bit_clk", spare_i2s_spkr_bit_clk.c,
+ "msm-dai-q6.4"),
+ CLK_LOOKUP("osr_clk", spare_i2s_spkr_osr_clk.c,
+ "msm-dai-q6.4"),
+ CLK_LOOKUP("pcm_clk", pcm_clk.c, "msm-dai-q6.2"),
CLK_LOOKUP("sps_slimbus_clk", sps_slimbus_clk.c, ""),
- CLK_LOOKUP("audio_slimbus_clk", audio_slimbus_clk.c, NULL),
+ CLK_LOOKUP("core_clk", audio_slimbus_clk.c, "msm_slim_ctrl.1"),
CLK_LOOKUP("core_clk", jpegd_axi_clk.c, ""),
CLK_LOOKUP("core_clk", vpe_axi_clk.c, ""),
CLK_LOOKUP("core_clk", mdp_axi_clk.c, ""),
@@ -5104,6 +5163,7 @@
CLK_LOOKUP("xo", pxo_clk.c, "pil_qdsp6v4.0"),
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.1"),
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.2"),
+ CLK_LOOKUP("xo", cxo_clk.c, "BAM_RMNT"),
CLK_LOOKUP("pll2", pll2_clk.c, NULL),
CLK_LOOKUP("pll8", pll8_clk.c, NULL),
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
@@ -5220,10 +5280,13 @@
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0020"),
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"),
CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_csid.0"),
CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_clk", csi2_clk.c, "msm_csid.2"),
CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_csid.0"),
CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_phy_clk", csi2_phy_clk.c, "msm_csid.2"),
CLK_LOOKUP("csi_pix_clk", csi_pix_clk.c, "msm_ispif.0"),
CLK_LOOKUP("csi_rdi_clk", csi_rdi_clk.c, "msm_ispif.0"),
CLK_LOOKUP("csi_src_clk", csi2_src_clk.c, NULL),
@@ -5237,8 +5300,11 @@
csiphy_timer_src_clk.c, "msm_csiphy.0"),
CLK_LOOKUP("csiphy_timer_src_clk",
csiphy_timer_src_clk.c, "msm_csiphy.1"),
+ CLK_LOOKUP("csiphy_timer_src_clk",
+ csiphy_timer_src_clk.c, "msm_csiphy.2"),
CLK_LOOKUP("csiphy_timer_clk", csi0phy_timer_clk.c, "msm_csiphy.0"),
CLK_LOOKUP("csiphy_timer_clk", csi1phy_timer_clk.c, "msm_csiphy.1"),
+ CLK_LOOKUP("csiphy_timer_clk", csi2phy_timer_clk.c, "msm_csiphy.2"),
CLK_LOOKUP("dsi_byte_div_clk", dsi1_byte_clk.c, NULL),
CLK_LOOKUP("dsi_byte_div_clk", dsi2_byte_clk.c, NULL),
CLK_LOOKUP("dsi_esc_clk", dsi1_esc_clk.c, NULL),
@@ -5287,6 +5353,7 @@
CLK_LOOKUP("amp_pclk", amp_p_clk.c, NULL),
CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.0"),
CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.2"),
CLK_LOOKUP("dsi_m_pclk", dsi1_m_p_clk.c, NULL),
CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, NULL),
CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, NULL),
@@ -5315,19 +5382,27 @@
CLK_LOOKUP("iface_clk", vfe_p_clk.c, "footswitch-8x60.8"),
CLK_LOOKUP("vpe_pclk", vpe_p_clk.c, "msm_vpe.0"),
CLK_LOOKUP("iface_clk", vpe_p_clk.c, "footswitch-8x60.9"),
- CLK_LOOKUP("mi2s_bit_clk", mi2s_bit_clk.c, NULL),
- CLK_LOOKUP("mi2s_osr_clk", mi2s_osr_clk.c, NULL),
- CLK_LOOKUP("i2s_mic_bit_clk", codec_i2s_mic_bit_clk.c, NULL),
- CLK_LOOKUP("i2s_mic_osr_clk", codec_i2s_mic_osr_clk.c, NULL),
- CLK_LOOKUP("i2s_mic_bit_clk", spare_i2s_mic_bit_clk.c, NULL),
- CLK_LOOKUP("i2s_mic_osr_clk", spare_i2s_mic_osr_clk.c, NULL),
- CLK_LOOKUP("i2s_spkr_bit_clk", codec_i2s_spkr_bit_clk.c, NULL),
- CLK_LOOKUP("i2s_spkr_osr_clk", codec_i2s_spkr_osr_clk.c, NULL),
- CLK_LOOKUP("i2s_spkr_bit_clk", spare_i2s_spkr_bit_clk.c, NULL),
- CLK_LOOKUP("i2s_spkr_osr_clk", spare_i2s_spkr_osr_clk.c, NULL),
- CLK_LOOKUP("pcm_clk", pcm_clk.c, NULL),
+ CLK_LOOKUP("bit_clk", mi2s_bit_clk.c, "msm-dai-q6.6"),
+ CLK_LOOKUP("osr_clk", mi2s_osr_clk.c, "msm-dai-q6.6"),
+ CLK_LOOKUP("bit_clk", codec_i2s_mic_bit_clk.c,
+ "msm-dai-q6.1"),
+ CLK_LOOKUP("osr_clk", codec_i2s_mic_osr_clk.c,
+ "msm-dai-q6.1"),
+ CLK_LOOKUP("bit_clk", spare_i2s_mic_bit_clk.c,
+ "msm-dai-q6.5"),
+ CLK_LOOKUP("osr_clk", spare_i2s_mic_osr_clk.c,
+ "msm-dai-q6.5"),
+ CLK_LOOKUP("bit_clk", codec_i2s_spkr_bit_clk.c,
+ "msm-dai-q6.16384"),
+ CLK_LOOKUP("osr_clk", codec_i2s_spkr_osr_clk.c,
+ "msm-dai-q6.16384"),
+ CLK_LOOKUP("bit_clk", spare_i2s_spkr_bit_clk.c,
+ "msm-dai-q6.4"),
+ CLK_LOOKUP("osr_clk", spare_i2s_spkr_osr_clk.c,
+ "msm-dai-q6.4"),
+ CLK_LOOKUP("pcm_clk", pcm_clk.c, "msm-dai-q6.2"),
CLK_LOOKUP("sps_slimbus_clk", sps_slimbus_clk.c, NULL),
- CLK_LOOKUP("audio_slimbus_clk", audio_slimbus_clk.c, NULL),
+ CLK_LOOKUP("core_clk", audio_slimbus_clk.c, "msm_slim_ctrl.1"),
CLK_LOOKUP("core_clk", jpegd_axi_clk.c, "msm_iommu.0"),
CLK_LOOKUP("core_clk", vpe_axi_clk.c, "msm_iommu.1"),
CLK_LOOKUP("core_clk", mdp_axi_clk.c, "msm_iommu.2"),
@@ -5599,10 +5674,6 @@
/* Local clock driver initialization. */
static void __init msm8960_clock_init(void)
{
- /* Copy gfx2d's frequency table because it's modified by both clocks */
- gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
- sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
- GFP_KERNEL);
if (cpu_is_msm8960()) {
rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
@@ -5672,6 +5743,7 @@
clk_set_rate(&usb_hsic_xcvr_fs_clk.c, 60000000);
clk_set_rate(&usb_hsic_hsic_src_clk.c, 480000000);
clk_set_rate(&usb_hsic_hsio_cal_clk.c, 9000000);
+ clk_set_rate(&usb_hsic_system_clk.c, 60000000);
/*
* Set the CSI rates to a safe default to avoid warnings when
* switching csi pix and rdi clocks.
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index e53d441..d3f5396 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -318,14 +318,13 @@
static struct clk_ops clk_ops_pxo = {
.enable = pxo_clk_enable,
.disable = pxo_clk_disable,
- .get_rate = fixed_clk_get_rate,
.is_local = xo_clk_is_local,
};
static struct fixed_clk pxo_clk = {
- .rate = 27000000,
.c = {
.dbg_name = "pxo_clk",
+ .rate = 27000000,
.ops = &clk_ops_pxo,
CLK_INIT(pxo_clk.c),
},
@@ -344,49 +343,48 @@
static struct clk_ops clk_ops_cxo = {
.enable = cxo_clk_enable,
.disable = cxo_clk_disable,
- .get_rate = fixed_clk_get_rate,
.is_local = xo_clk_is_local,
};
static struct fixed_clk cxo_clk = {
- .rate = 19200000,
.c = {
.dbg_name = "cxo_clk",
+ .rate = 19200000,
.ops = &clk_ops_cxo,
CLK_INIT(cxo_clk.c),
},
};
static struct pll_vote_clk pll8_clk = {
- .rate = 384000000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(8),
.status_reg = BB_PLL8_STATUS_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll8_clk",
+ .rate = 384000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll8_clk.c),
},
};
static struct pll_clk pll2_clk = {
- .rate = 800000000,
.mode_reg = MM_PLL1_MODE_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll2_clk",
+ .rate = 800000000,
.ops = &clk_ops_pll,
CLK_INIT(pll2_clk.c),
},
};
static struct pll_clk pll3_clk = {
- .rate = 0, /* TODO: Detect rate dynamically */
.mode_reg = MM_PLL2_MODE_REG,
.parent = &pxo_clk.c,
.c = {
.dbg_name = "pll3_clk",
+ .rate = 0, /* TODO: Detect rate dynamically */
.ops = &clk_ops_pll,
CLK_INIT(pll3_clk.c),
},
@@ -417,15 +415,14 @@
static struct clk_ops clk_ops_pll4 = {
.enable = pll4_clk_enable,
.disable = pll4_clk_disable,
- .get_rate = fixed_clk_get_rate,
.get_parent = pll4_clk_get_parent,
.is_local = pll4_clk_is_local,
};
static struct fixed_clk pll4_clk = {
- .rate = 540672000,
.c = {
.dbg_name = "pll4_clk",
+ .rate = 540672000,
.ops = &clk_ops_pll4,
CLK_INIT(pll4_clk.c),
},
@@ -1014,6 +1011,7 @@
.md_reg = GPn_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gp, \
.current_freq = &rcg_dummy_freq, \
@@ -1030,7 +1028,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gp[] = {
F_GP( 0, gnd, 1, 0, 0),
@@ -1059,6 +1056,7 @@
.md_reg = GSBIn_UART_APPS_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(31, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gsbi_uart, \
.current_freq = &rcg_dummy_freq, \
@@ -1075,7 +1073,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
F_GSBI_UART( 0, gnd, 1, 0, 0),
@@ -1123,6 +1120,7 @@
.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gsbi_qup, \
.current_freq = &rcg_dummy_freq, \
@@ -1139,7 +1137,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
F_GSBI_QUP( 0, gnd, 1, 0, 0),
@@ -1260,6 +1257,7 @@
.md_reg = SDCn_APPS_CLK_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_sdc, \
.current_freq = &rcg_dummy_freq, \
@@ -1276,7 +1274,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_sdc[] = {
F_SDC( 0, gnd, 1, 0, 0),
@@ -1302,7 +1299,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_tsif_ref[] = {
F_TSIF_REF( 0, gnd, 1, 0, 0),
@@ -1321,6 +1317,7 @@
.md_reg = TSIF_REF_CLK_MD_REG,
.root_en_mask = BIT(11),
.ns_mask = (BM(31, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_tsif_ref,
.current_freq = &rcg_dummy_freq,
@@ -1369,7 +1366,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_usb[] = {
F_USB( 0, gnd, 1, 0, 0),
@@ -1390,6 +1386,7 @@
.md_reg = USB_HS1_XCVR_FS_CLK_MD_REG,
.root_en_mask = BIT(11),
.ns_mask = (BM(23, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_usb,
.current_freq = &rcg_dummy_freq,
@@ -1423,6 +1420,7 @@
.md_reg = USB_FSn_XCVR_FS_CLK_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_usb, \
.current_freq = &rcg_dummy_freq, \
@@ -2033,7 +2031,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_cam[] = {
F_CAM( 0, gnd, 1, 0, 0),
@@ -2061,6 +2058,7 @@
.md_reg = CAMCLK_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(31, 24) | BM(15, 14) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd_8,
.freq_tbl = clk_tbl_cam,
@@ -2199,7 +2197,6 @@
.md_val = MD4(4, m, 0, n), \
.ns_val = NS_MND_BANKED4(20, 16, n, m, 3, 0, s##_to_mm_mux), \
.ctl_val = CC_BANKED(9, 6, n), \
- .mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gfx2d[] = {
F_GFX2D( 0, gnd, 0, 0),
@@ -2313,7 +2310,6 @@
.md_val = MD4(4, m, 0, n), \
.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
.ctl_val = CC_BANKED(9, 6, n), \
- .mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gfx3d[] = {
F_GFX3D( 0, gnd, 0, 0),
@@ -2386,7 +2382,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(23, 16, n, m, 15, 12, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!n, \
}
static struct clk_freq_tbl clk_tbl_ijpeg[] = {
F_IJPEG( 0, gnd, 1, 0, 0),
@@ -2417,6 +2412,7 @@
.md_reg = IJPEG_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(23, 16) | BM(15, 12) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_ijpeg,
@@ -2479,7 +2475,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MND_BANKED8(22, 14, n, m, 3, 0, s##_to_mm_mux), \
.ctl_val = CC_BANKED(9, 6, n), \
- .mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_mdp[] = {
F_MDP( 0, gnd, 0, 0),
@@ -2585,7 +2580,6 @@
.md_val = MD16(m, n), \
.ns_val = NS_MM(31, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_pixel_mdp[] = {
F_PIXEL_MDP( 0, gnd, 1, 0, 0),
@@ -2618,6 +2612,7 @@
},
.root_en_mask = BIT(2),
.ns_mask = (BM(31, 16) | BM(15, 14) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_pixel_mdp,
@@ -2713,7 +2708,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
.extra_freq_data = p_r, \
}
/* Switching TV freqs requires PLL reconfiguration. */
@@ -2745,6 +2739,7 @@
.md_reg = TV_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(23, 16) | BM(15, 14) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_tv,
.freq_tbl = clk_tbl_tv,
@@ -2846,7 +2841,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(18, 11, n, m, 0, 0, 1, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_vcodec[] = {
F_VCODEC( 0, gnd, 0, 0),
@@ -2876,6 +2870,7 @@
.md_reg = VCODEC_MD0_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(18, 11) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_vcodec,
@@ -2944,7 +2939,6 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS_MM(23, 16, n, m, 11, 10, d, 2, 0, s##_to_mm_mux), \
.ctl_val = CC(6, n), \
- .mnd_en_mask = BIT(5) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_vfe[] = {
F_VFE( 0, gnd, 1, 0, 0),
@@ -2982,6 +2976,7 @@
.md_reg = VFE_MD_REG,
.root_en_mask = BIT(2),
.ns_mask = (BM(23, 16) | BM(11, 10) | BM(2, 0)),
+ .mnd_en_mask = BIT(5),
.ctl_mask = BM(7, 6),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_vfe,
@@ -3039,7 +3034,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(8, m, 0, n), \
.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_aif_osr[] = {
F_AIF_OSR( 0, gnd, 1, 0, 0),
@@ -3071,6 +3065,7 @@
.md_reg = md, \
.root_en_mask = BIT(9), \
.ns_mask = (BM(31, 24) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_aif_osr, \
.current_freq = &rcg_dummy_freq, \
@@ -3131,7 +3126,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_pcm[] = {
F_PCM( 0, gnd, 1, 0, 0),
@@ -3163,6 +3157,7 @@
.md_reg = LCC_PCM_MD_REG,
.root_en_mask = BIT(9),
.ns_mask = (BM(31, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_pcm,
.current_freq = &rcg_dummy_freq,
@@ -3900,11 +3895,6 @@
}
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- /* Copy gfx2d's frequency table because it's modified by both clocks */
- gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
- sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
- GFP_KERNEL);
-
/* Initialize clock registers. */
reg_init();
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 0bdacec..9e4268f 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -223,14 +223,13 @@
static struct clk_ops clk_ops_cxo = {
.enable = cxo_clk_enable,
.disable = cxo_clk_disable,
- .get_rate = fixed_clk_get_rate,
.is_local = local_clk_is_local,
};
static struct fixed_clk cxo_clk = {
- .rate = 19200000,
.c = {
.dbg_name = "cxo_clk",
+ .rate = 19200000,
.ops = &clk_ops_cxo,
CLK_INIT(cxo_clk.c),
},
@@ -274,7 +273,6 @@
.disable = pll_acpu_vote_clk_disable,
.auto_off = pll_acpu_vote_clk_disable,
.is_enabled = pll_vote_clk_is_enabled,
- .get_rate = pll_vote_clk_get_rate,
.get_parent = pll_vote_clk_get_parent,
.is_local = local_clk_is_local,
};
@@ -285,7 +283,6 @@
static unsigned int soft_vote_pll0;
static struct pll_vote_clk pll0_clk = {
- .rate = 276000000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(0),
.status_reg = BB_PLL0_STATUS_REG,
@@ -294,13 +291,13 @@
.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
.c = {
.dbg_name = "pll0_clk",
+ .rate = 276000000,
.ops = &clk_ops_pll_acpu_vote,
CLK_INIT(pll0_clk.c),
},
};
static struct pll_vote_clk pll0_acpu_clk = {
- .rate = 276000000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(0),
.status_reg = BB_PLL0_STATUS_REG,
@@ -308,19 +305,20 @@
.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
.c = {
.dbg_name = "pll0_acpu_clk",
+ .rate = 276000000,
.ops = &clk_ops_pll_acpu_vote,
CLK_INIT(pll0_acpu_clk.c),
},
};
static struct pll_vote_clk pll4_clk = {
- .rate = 393216000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(4),
.status_reg = LCC_PLL0_STATUS_REG,
.parent = &cxo_clk.c,
.c = {
.dbg_name = "pll4_clk",
+ .rate = 393216000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll4_clk.c),
},
@@ -329,7 +327,6 @@
static unsigned int soft_vote_pll8;
static struct pll_vote_clk pll8_clk = {
- .rate = 384000000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(8),
.status_reg = BB_PLL8_STATUS_REG,
@@ -338,13 +335,13 @@
.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
.c = {
.dbg_name = "pll8_clk",
+ .rate = 384000000,
.ops = &clk_ops_pll_acpu_vote,
CLK_INIT(pll8_clk.c),
},
};
static struct pll_vote_clk pll8_acpu_clk = {
- .rate = 384000000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(8),
.status_reg = BB_PLL8_STATUS_REG,
@@ -352,29 +349,30 @@
.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
.c = {
.dbg_name = "pll8_acpu_clk",
+ .rate = 384000000,
.ops = &clk_ops_pll_acpu_vote,
CLK_INIT(pll8_acpu_clk.c),
},
};
static struct pll_clk pll9_acpu_clk = {
- .rate = 440000000,
.mode_reg = SC_PLL0_MODE_REG,
.c = {
.dbg_name = "pll9_acpu_clk",
+ .rate = 440000000,
.ops = &clk_ops_pll,
CLK_INIT(pll9_acpu_clk.c),
},
};
static struct pll_vote_clk pll14_clk = {
- .rate = 480000000,
.en_reg = BB_PLL_ENA_SC0_REG,
.en_mask = BIT(11),
.status_reg = BB_PLL14_STATUS_REG,
.parent = &cxo_clk.c,
.c = {
.dbg_name = "pll14_clk",
+ .rate = 480000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll14_clk.c),
},
@@ -428,6 +426,7 @@
.md_reg = GPn_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gp, \
.current_freq = &rcg_dummy_freq, \
@@ -444,7 +443,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gp[] = {
F_GP( 0, gnd, 1, 0, 0),
@@ -471,6 +469,7 @@
.md_reg = GSBIn_UART_APPS_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(31, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gsbi_uart, \
.current_freq = &rcg_dummy_freq, \
@@ -487,7 +486,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
F_GSBI_UART( 0, gnd, 1, 0, 0),
@@ -527,6 +525,7 @@
.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_gsbi_qup, \
.current_freq = &rcg_dummy_freq, \
@@ -543,7 +542,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
F_GSBI_QUP( 0, gnd, 1, 0, 0),
@@ -658,13 +656,14 @@
.md_reg = SDCn_APPS_CLK_MD_REG(n), \
.root_en_mask = BIT(11), \
.ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = f_table, \
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #name, \
.ops = &clk_ops_rcg_9615, \
- VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000), \
+ VDD_DIG_FMAX_MAP2(LOW, 26000000, NOMINAL, 52000000), \
CLK_INIT(name.c), \
}, \
}
@@ -674,7 +673,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_sdc1_2[] = {
F_SDC( 0, gnd, 1, 0, 0),
@@ -684,7 +682,10 @@
F_SDC( 17070000, pll8, 1, 2, 45),
F_SDC( 20210000, pll8, 1, 1, 19),
F_SDC( 24000000, pll8, 4, 1, 4),
+ F_SDC( 38400000, pll8, 2, 1, 5),
F_SDC( 48000000, pll8, 4, 1, 2),
+ F_SDC( 64000000, pll8, 3, 1, 2),
+ F_SDC( 76800000, pll8, 1, 1, 5),
F_END
};
@@ -697,7 +698,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(16, m, 0, n), \
.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_usb[] = {
F_USB( 0, gnd, 1, 0, 0),
@@ -724,6 +724,7 @@
.md_reg = USB_HS1_XCVR_FS_CLK_MD_REG,
.root_en_mask = BIT(11),
.ns_mask = (BM(23, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_usb,
.current_freq = &rcg_dummy_freq,
@@ -748,6 +749,7 @@
.md_reg = USB_HS1_SYS_CLK_MD_REG,
.root_en_mask = BIT(11),
.ns_mask = (BM(23, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_usb,
.current_freq = &rcg_dummy_freq,
@@ -772,6 +774,7 @@
.md_reg = USB_HSIC_XCVR_FS_CLK_MD_REG,
.root_en_mask = BIT(11),
.ns_mask = (BM(23, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_usb,
.current_freq = &rcg_dummy_freq,
@@ -796,6 +799,7 @@
.md_reg = USB_HSIC_SYSTEM_CLK_MD_REG,
.root_en_mask = BIT(11),
.ns_mask = (BM(23, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_usb_hsic_sys,
.current_freq = &rcg_dummy_freq,
@@ -1129,7 +1133,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD8(8, m, 0, n), \
.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_aif_osr[] = {
F_AIF_OSR( 0, gnd, 1, 0, 0),
@@ -1162,6 +1165,7 @@
.md_reg = md, \
.root_en_mask = BIT(9), \
.ns_mask = (BM(31, 24) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_aif_osr, \
.current_freq = &rcg_dummy_freq, \
@@ -1186,6 +1190,7 @@
.md_reg = md, \
.root_en_mask = BIT(9), \
.ns_mask = (BM(31, 24) | BM(6, 0)), \
+ .mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
.freq_tbl = clk_tbl_aif_osr, \
.current_freq = &rcg_dummy_freq, \
@@ -1264,7 +1269,6 @@
.src_clk = &s##_clk.c, \
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
- .mnd_en_mask = BIT(8) * !!(n), \
}
static struct clk_freq_tbl clk_tbl_pcm[] = {
F_PCM( 0, gnd, 1, 0, 0),
@@ -1296,6 +1300,7 @@
.md_reg = LCC_PCM_MD_REG,
.root_en_mask = BIT(9),
.ns_mask = (BM(31, 16) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_pcm,
.current_freq = &rcg_dummy_freq,
@@ -1321,6 +1326,7 @@
.md_reg = LCC_SLIMBUS_MD_REG,
.root_en_mask = BIT(9),
.ns_mask = (BM(31, 24) | BM(6, 0)),
+ .mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
.freq_tbl = clk_tbl_aif_osr,
.current_freq = &rcg_dummy_freq,
@@ -1619,6 +1625,7 @@
static struct clk_lookup msm_clocks_9615[] = {
CLK_LOOKUP("xo", cxo_clk.c, "msm_otg"),
+ CLK_LOOKUP("xo", cxo_clk.c, "BAM_RMNT"),
CLK_LOOKUP("pll0", pll0_clk.c, NULL),
CLK_LOOKUP("pll8", pll8_clk.c, NULL),
CLK_LOOKUP("pll14", pll14_clk.c, NULL),
@@ -1689,21 +1696,29 @@
CLK_LOOKUP("iface_clk", pmic_arb1_p_clk.c, ""),
CLK_LOOKUP("core_clk", pmic_ssbi2_clk.c, ""),
CLK_LOOKUP("mem_clk", rpm_msg_ram_p_clk.c, ""),
- CLK_LOOKUP("mi2s_bit_clk", mi2s_bit_clk.c, NULL),
- CLK_LOOKUP("mi2s_osr_clk", mi2s_osr_clk.c, NULL),
+ CLK_LOOKUP("bit_clk", mi2s_bit_clk.c, "msm-dai-q6.6"),
+ CLK_LOOKUP("osr_clk", mi2s_osr_clk.c, "msm-dai-q6.6"),
- CLK_LOOKUP("i2s_mic_bit_clk", codec_i2s_mic_bit_clk.c, NULL),
- CLK_LOOKUP("i2s_mic_osr_clk", codec_i2s_mic_osr_clk.c, NULL),
- CLK_LOOKUP("i2s_mic_bit_clk", spare_i2s_mic_bit_clk.c, NULL),
- CLK_LOOKUP("i2s_mic_osr_clk", spare_i2s_mic_osr_clk.c, NULL),
- CLK_LOOKUP("i2s_spkr_bit_clk", codec_i2s_spkr_bit_clk.c, NULL),
- CLK_LOOKUP("i2s_spkr_osr_clk", codec_i2s_spkr_osr_clk.c, NULL),
- CLK_LOOKUP("i2s_spkr_bit_clk", spare_i2s_spkr_bit_clk.c, NULL),
- CLK_LOOKUP("i2s_spkr_osr_clk", spare_i2s_spkr_osr_clk.c, NULL),
- CLK_LOOKUP("pcm_clk", pcm_clk.c, NULL),
+ CLK_LOOKUP("bit_clk", codec_i2s_mic_bit_clk.c,
+ "msm-dai-q6.1"),
+ CLK_LOOKUP("osr_clk", codec_i2s_mic_osr_clk.c,
+ "msm-dai-q6.1"),
+ CLK_LOOKUP("bit_clk", spare_i2s_mic_bit_clk.c,
+ "msm-dai-q6.5"),
+ CLK_LOOKUP("osr_clk", spare_i2s_mic_osr_clk.c,
+ "msm-dai-q6.5"),
+ CLK_LOOKUP("bit_clk", codec_i2s_spkr_bit_clk.c,
+ "msm-dai-q6.16384"),
+ CLK_LOOKUP("osr_clk", codec_i2s_spkr_osr_clk.c,
+ "msm-dai-q6.16384"),
+ CLK_LOOKUP("bit_clk", spare_i2s_spkr_bit_clk.c,
+ "msm-dai-q6.4"),
+ CLK_LOOKUP("osr_clk", spare_i2s_spkr_osr_clk.c,
+ "msm-dai-q6.4"),
+ CLK_LOOKUP("pcm_clk", pcm_clk.c, "msm-dai-q6.2"),
CLK_LOOKUP("sps_slimbus_clk", sps_slimbus_clk.c, NULL),
- CLK_LOOKUP("audio_slimbus_clk", audio_slimbus_clk.c, NULL),
+ CLK_LOOKUP("core_clk", audio_slimbus_clk.c, "msm_slim_ctrl.1"),
CLK_LOOKUP("core_clk", dfab_usb_hs_clk.c, "msm_otg"),
CLK_LOOKUP("bus_clk", dfab_sdc1_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("bus_clk", dfab_sdc2_clk.c, "msm_sdcc.2"),
@@ -1821,7 +1836,7 @@
pll9_lval = readl_relaxed(SC_PLL0_L_VAL_REG);
if (pll9_lval == 0x1C)
- pll9_acpu_clk.rate = 550000000;
+ pll9_acpu_clk.c.rate = 550000000;
/* Enable PLL4 source on the LPASS Primary PLL Mux */
regval = readl_relaxed(LCC_PRI_PLL_CLK_CTL_REG);
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index c02c6f3..4f68fb4 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -192,13 +192,8 @@
writel_relaxed(ns_reg_val, clk->ns_reg);
}
- /*
- * If this freq requires the MN counter to be enabled,
- * update the enable mask to match the current bank.
- */
- if (nf->mnd_en_mask)
- nf->mnd_en_mask = new_bank_masks->mnd_en_mask;
- /* Update the NS mask to match the current bank. */
+ /* Update the MND_EN and NS masks to match the current bank. */
+ clk->mnd_en_mask = new_bank_masks->mnd_en_mask;
clk->ns_mask = new_bank_masks->ns_mask;
}
@@ -343,8 +338,8 @@
/* Enable MN counter, if applicable. */
reg_val = readl_relaxed(reg);
- if (clk->current_freq->mnd_en_mask) {
- reg_val |= clk->current_freq->mnd_en_mask;
+ if (clk->current_freq->md_val) {
+ reg_val |= clk->mnd_en_mask;
writel_relaxed(reg_val, reg);
}
/* Enable root. */
@@ -408,8 +403,8 @@
writel_relaxed(reg_val, reg);
}
/* Disable MN counter, if applicable. */
- if (clk->current_freq->mnd_en_mask) {
- reg_val &= ~(clk->current_freq->mnd_en_mask);
+ if (clk->current_freq->md_val) {
+ reg_val &= ~(clk->mnd_en_mask);
writel_relaxed(reg_val, reg);
}
/*
@@ -641,7 +636,7 @@
ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
if ((freq->ns_val & ns_mask) == ns_val &&
- (!freq->mnd_en_mask || freq->md_val == md_val)) {
+ (!freq->md_val || freq->md_val == md_val)) {
pr_info("%s rate=%d\n", clk->c.dbg_name, freq->freq_hz);
break;
}
@@ -686,12 +681,6 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-unsigned long pll_vote_clk_get_rate(struct clk *clk)
-{
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
- return pll->rate;
-}
-
struct clk *pll_vote_clk_get_parent(struct clk *clk)
{
struct pll_vote_clk *pll = to_pll_vote_clk(clk);
@@ -709,7 +698,6 @@
.disable = pll_vote_clk_disable,
.auto_off = pll_vote_clk_disable,
.is_enabled = pll_vote_clk_is_enabled,
- .get_rate = pll_vote_clk_get_rate,
.get_parent = pll_vote_clk_get_parent,
.is_local = local_clk_is_local,
};
@@ -766,12 +754,6 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-static unsigned long pll_clk_get_rate(struct clk *clk)
-{
- struct pll_clk *pll = to_pll_clk(clk);
- return pll->rate;
-}
-
static struct clk *pll_clk_get_parent(struct clk *clk)
{
struct pll_clk *pll = to_pll_clk(clk);
@@ -817,13 +799,11 @@
.enable = pll_clk_enable,
.disable = pll_clk_disable,
.auto_off = pll_clk_disable,
- .get_rate = pll_clk_get_rate,
.get_parent = pll_clk_get_parent,
.is_local = local_clk_is_local,
};
struct clk_ops clk_ops_gnd = {
- .get_rate = fixed_clk_get_rate,
.is_local = local_clk_is_local,
};
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index d312f24..c587b43 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -27,10 +27,12 @@
/* MD Registers */
#define MD4(m_lsb, m, n_lsb, n) \
- (BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
+ ((BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n))) \
+ * !!(n))
#define MD8(m_lsb, m, n_lsb, n) \
- (BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
-#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
+ ((BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n))) \
+ * !!(n))
+#define MD16(m, n) ((BVAL(31, 16, m) | BVAL(15, 0, ~(n))) * !!(n))
/* NS Registers */
#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
@@ -101,11 +103,10 @@
*/
struct clk_freq_tbl {
const uint32_t freq_hz;
- struct clk *src_clk;
+ struct clk *const src_clk;
const uint32_t md_val;
const uint32_t ns_val;
const uint32_t ctl_val;
- uint32_t mnd_en_mask;
void *const extra_freq_data;
};
@@ -126,13 +127,12 @@
const struct bank_mask_info bank1_mask;
};
-#define F_RAW(f, sc, m_v, n_v, c_v, m_m, e) { \
+#define F_RAW(f, sc, m_v, n_v, c_v, e) { \
.freq_hz = f, \
.src_clk = sc, \
.md_val = m_v, \
.ns_val = n_v, \
.ctl_val = c_v, \
- .mnd_en_mask = m_m, \
.extra_freq_data = e, \
}
#define FREQ_END (UINT_MAX-1)
@@ -185,6 +185,7 @@
const uint32_t root_en_mask;
uint32_t ns_mask;
const uint32_t ctl_mask;
+ uint32_t mnd_en_mask;
void *bank_info;
void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
@@ -249,29 +250,14 @@
/**
* struct fixed_clk - fixed rate clock (used for crystal oscillators)
- * @rate: output rate
* @c: clk
*/
struct fixed_clk {
- unsigned long rate;
struct clk c;
};
-static inline struct fixed_clk *to_fixed_clk(struct clk *clk)
-{
- return container_of(clk, struct fixed_clk, c);
-}
-
-static inline unsigned long fixed_clk_get_rate(struct clk *clk)
-{
- struct fixed_clk *f = to_fixed_clk(clk);
- return f->rate;
-}
-
-
/**
* struct pll_vote_clk - phase locked loop (HW voteable)
- * @rate: output rate
* @soft_vote: soft voting variable for multiple PLL software instances
* @soft_vote_mask: soft voting mask for multiple PLL software instances
* @en_reg: enable register
@@ -281,8 +267,6 @@
* @c: clk
*/
struct pll_vote_clk {
- unsigned long rate;
-
u32 *soft_vote;
const u32 soft_vote_mask;
void __iomem *const en_reg;
@@ -303,14 +287,11 @@
/**
* struct pll_clk - phase locked loop
- * @rate: output rate
* @mode_reg: enable register
* @parent: clock source
* @c: clk
*/
struct pll_clk {
- unsigned long rate;
-
void __iomem *const mode_reg;
struct clk *parent;
@@ -394,7 +375,6 @@
*/
int pll_vote_clk_enable(struct clk *clk);
void pll_vote_clk_disable(struct clk *clk);
-unsigned long pll_vote_clk_get_rate(struct clk *clk);
struct clk *pll_vote_clk_get_parent(struct clk *clk);
int pll_vote_clk_is_enabled(struct clk *clk);
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 4757f7d..ae87bb7 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,9 +23,9 @@
static int rpm_clk_enable(struct clk *clk)
{
unsigned long flags;
- struct msm_rpm_iv_pair iv;
- int rc = 0;
struct rpm_clk *r = to_rpm_clk(clk);
+ struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
+ int rc = 0;
unsigned long this_khz, this_sleep_khz;
unsigned long peer_khz = 0, peer_sleep_khz = 0;
struct rpm_clk *peer = r->peer;
@@ -39,8 +39,6 @@
this_sleep_khz = r->last_set_sleep_khz;
- iv.id = r->rpm_clk_id;
-
/* Take peer clock's rate into account only if it's enabled. */
if (peer->enabled) {
peer_khz = peer->last_set_khz;
@@ -48,11 +46,16 @@
}
iv.value = max(this_khz, peer_khz);
+ if (r->branch)
+ iv.value = !!iv.value;
+
rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
if (rc)
goto out;
iv.value = max(this_sleep_khz, peer_sleep_khz);
+ if (r->branch)
+ iv.value = !!iv.value;
rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
if (rc) {
iv.value = peer_khz;
@@ -76,25 +79,23 @@
spin_lock_irqsave(&rpm_clock_lock, flags);
if (r->last_set_khz) {
- struct msm_rpm_iv_pair iv;
+ struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
struct rpm_clk *peer = r->peer;
unsigned long peer_khz = 0, peer_sleep_khz = 0;
int rc;
- iv.id = r->rpm_clk_id;
-
/* Take peer clock's rate into account only if it's enabled. */
if (peer->enabled) {
peer_khz = peer->last_set_khz;
peer_sleep_khz = peer->last_set_sleep_khz;
}
- iv.value = peer_khz;
+ iv.value = r->branch ? !!peer_khz : peer_khz;
rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
if (rc)
goto out;
- iv.value = peer_sleep_khz;
+ iv.value = r->branch ? !!peer_sleep_khz : peer_sleep_khz;
rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
}
r->enabled = false;
@@ -195,3 +196,9 @@
.round_rate = rpm_clk_round_rate,
.is_local = rpm_clk_is_local,
};
+
+struct clk_ops clk_ops_rpm_branch = {
+ .enable = rpm_clk_enable,
+ .disable = rpm_clk_disable,
+ .is_local = rpm_clk_is_local,
+};
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index 24df9b6..2f4a17c 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
struct clk_ops;
extern struct clk_ops clk_ops_rpm;
+extern struct clk_ops clk_ops_rpm_branch;
struct rpm_clk {
const int rpm_clk_id;
@@ -27,6 +28,7 @@
/* 0 if active_only. Otherwise, same as last_set_khz. */
unsigned last_set_sleep_khz;
bool enabled;
+ bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
struct rpm_clk *peer;
struct clk c;
@@ -65,4 +67,37 @@
}, \
};
+#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, rate) \
+ static struct rpm_clk active; \
+ static struct rpm_clk name = { \
+ .rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
+ .rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+ .peer = &active, \
+ .last_set_khz = ((rate) / 1000), \
+ .last_set_sleep_khz = ((rate) / 1000), \
+ .branch = true, \
+ .c = { \
+ .ops = &clk_ops_rpm_branch, \
+ .flags = CLKFLAG_SKIP_AUTO_OFF, \
+ .dbg_name = #name, \
+ .rate = (rate), \
+ CLK_INIT(name.c), \
+ }, \
+ }; \
+ static struct rpm_clk active = { \
+ .rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
+ .rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+ .peer = &name, \
+ .last_set_khz = ((rate) / 1000), \
+ .active_only = true, \
+ .branch = true, \
+ .c = { \
+ .ops = &clk_ops_rpm_branch, \
+ .flags = CLKFLAG_SKIP_AUTO_OFF, \
+ .dbg_name = #active, \
+ .rate = (rate), \
+ CLK_INIT(active.c), \
+ }, \
+ };
+
#endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 57fd749..5b89fa9 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/clock.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -222,7 +222,7 @@
unsigned long clk_get_rate(struct clk *clk)
{
if (!clk->ops->get_rate)
- return 0;
+ return clk->rate;
return clk->ops->get_rate(clk);
}
diff --git a/arch/arm/mach-msm/cp14.h b/arch/arm/mach-msm/cp14.h
index 9f7241e..d640412 100644
--- a/arch/arm/mach-msm/cp14.h
+++ b/arch/arm/mach-msm/cp14.h
@@ -325,21 +325,21 @@
#define RCP14_ETMACTR14() MRC14(1, c0, c14, 2)
#define RCP14_ETMACTR15() MRC14(1, c0, c15, 2)
#define RCP14_ETMDCVR0() MRC14(1, c0, c0, 3)
-#define RCP14_ETMDCVR1() MRC14(1, c0, c1, 3)
#define RCP14_ETMDCVR2() MRC14(1, c0, c2, 3)
-#define RCP14_ETMDCVR3() MRC14(1, c0, c3, 3)
#define RCP14_ETMDCVR4() MRC14(1, c0, c4, 3)
-#define RCP14_ETMDCVR5() MRC14(1, c0, c5, 3)
#define RCP14_ETMDCVR6() MRC14(1, c0, c6, 3)
-#define RCP14_ETMDCVR7() MRC14(1, c0, c7, 3)
+#define RCP14_ETMDCVR8() MRC14(1, c0, c8, 3)
+#define RCP14_ETMDCVR10() MRC14(1, c0, c10, 3)
+#define RCP14_ETMDCVR12() MRC14(1, c0, c12, 3)
+#define RCP14_ETMDCVR14() MRC14(1, c0, c14, 3)
#define RCP14_ETMDCMR0() MRC14(1, c0, c0, 4)
-#define RCP14_ETMDCMR1() MRC14(1, c0, c1, 4)
#define RCP14_ETMDCMR2() MRC14(1, c0, c2, 4)
-#define RCP14_ETMDCMR3() MRC14(1, c0, c3, 4)
#define RCP14_ETMDCMR4() MRC14(1, c0, c4, 4)
-#define RCP14_ETMDCMR5() MRC14(1, c0, c5, 4)
#define RCP14_ETMDCMR6() MRC14(1, c0, c6, 4)
-#define RCP14_ETMDCMR7() MRC14(1, c0, c7, 4)
+#define RCP14_ETMDCMR8() MRC14(1, c0, c8, 4)
+#define RCP14_ETMDCMR10() MRC14(1, c0, c10, 4)
+#define RCP14_ETMDCMR12() MRC14(1, c0, c12, 4)
+#define RCP14_ETMDCMR14() MRC14(1, c0, c14, 4)
#define RCP14_ETMCNTRLDVR0() MRC14(1, c0, c0, 5)
#define RCP14_ETMCNTRLDVR1() MRC14(1, c0, c1, 5)
#define RCP14_ETMCNTRLDVR2() MRC14(1, c0, c2, 5)
@@ -389,7 +389,7 @@
#define RCP14_ETMAUXCR() MRC14(1, c0, c15, 7)
#define RCP14_ETMTRACEIDR() MRC14(1, c1, c0, 0)
#define RCP14_ETMIDR2() MRC14(1, c1, c2, 0)
-#define RCP14_ETMVMIDCVR() MRC14(1, c1, c1, 0)
+#define RCP14_ETMVMIDCVR() MRC14(1, c1, c0, 1)
#define RCP14_ETMOSLSR() MRC14(1, c1, c1, 4)
/* not available in PFTv1.1 */
#define RCP14_ETMOSSRR() MRC14(1, c1, c2, 4)
@@ -462,21 +462,21 @@
#define WCP14_ETMACTR14(val) MCR14(val, 1, c0, c14, 2)
#define WCP14_ETMACTR15(val) MCR14(val, 1, c0, c15, 2)
#define WCP14_ETMDCVR0(val) MCR14(val, 1, c0, c0, 3)
-#define WCP14_ETMDCVR1(val) MCR14(val, 1, c0, c1, 3)
#define WCP14_ETMDCVR2(val) MCR14(val, 1, c0, c2, 3)
-#define WCP14_ETMDCVR3(val) MCR14(val, 1, c0, c3, 3)
#define WCP14_ETMDCVR4(val) MCR14(val, 1, c0, c4, 3)
-#define WCP14_ETMDCVR5(val) MCR14(val, 1, c0, c5, 3)
#define WCP14_ETMDCVR6(val) MCR14(val, 1, c0, c6, 3)
-#define WCP14_ETMDCVR7(val) MCR14(val, 1, c0, c7, 3)
+#define WCP14_ETMDCVR8(val) MCR14(val, 1, c0, c8, 3)
+#define WCP14_ETMDCVR10(val) MCR14(val, 1, c0, c10, 3)
+#define WCP14_ETMDCVR12(val) MCR14(val, 1, c0, c12, 3)
+#define WCP14_ETMDCVR14(val) MCR14(val, 1, c0, c14, 3)
#define WCP14_ETMDCMR0(val) MCR14(val, 1, c0, c0, 4)
-#define WCP14_ETMDCMR1(val) MCR14(val, 1, c0, c1, 4)
#define WCP14_ETMDCMR2(val) MCR14(val, 1, c0, c2, 4)
-#define WCP14_ETMDCMR3(val) MCR14(val, 1, c0, c3, 4)
#define WCP14_ETMDCMR4(val) MCR14(val, 1, c0, c4, 4)
-#define WCP14_ETMDCMR5(val) MCR14(val, 1, c0, c5, 4)
#define WCP14_ETMDCMR6(val) MCR14(val, 1, c0, c6, 4)
-#define WCP14_ETMDCMR7(val) MCR14(val, 1, c0, c7, 4)
+#define WCP14_ETMDCMR8(val) MCR14(val, 1, c0, c8, 4)
+#define WCP14_ETMDCMR10(val) MCR14(val, 1, c0, c10, 4)
+#define WCP14_ETMDCMR12(val) MCR14(val, 1, c0, c12, 4)
+#define WCP14_ETMDCMR14(val) MCR14(val, 1, c0, c14, 4)
#define WCP14_ETMCNTRLDVR0(val) MCR14(val, 1, c0, c0, 5)
#define WCP14_ETMCNTRLDVR1(val) MCR14(val, 1, c0, c1, 5)
#define WCP14_ETMCNTRLDVR2(val) MCR14(val, 1, c0, c2, 5)
@@ -525,7 +525,7 @@
#define WCP14_ETMAUXCR(val) MCR14(val, 1, c0, c15, 7)
#define WCP14_ETMTRACEIDR(val) MCR14(val, 1, c1, c0, 0)
#define WCP14_ETMIDR2(val) MCR14(val, 1, c1, c2, 0)
-#define WCP14_ETMVMIDCVR(val) MCR14(val, 1, c1, c1, 0)
+#define WCP14_ETMVMIDCVR(val) MCR14(val, 1, c1, c0, 1)
#define WCP14_ETMOSLAR(val) MCR14(val, 1, c1, c0, 4)
/* not available in PFTv1.1 */
#define WCP14_ETMOSSRR(val) MCR14(val, 1, c1, c2, 4)
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 56778e2..107598a 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -50,21 +50,13 @@
static DEFINE_PER_CPU(struct cpufreq_suspend_t, cpufreq_suspend);
-static int override_cpu;
-
static int set_cpu_freq(struct cpufreq_policy *policy, unsigned int new_freq)
{
int ret = 0;
struct cpufreq_freqs freqs;
freqs.old = policy->cur;
- if (override_cpu) {
- if (policy->cur == policy->max)
- return 0;
- else
- freqs.new = policy->max;
- } else
- freqs.new = new_freq;
+ freqs.new = new_freq;
freqs.cpu = policy->cpu;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
ret = acpuclk_set_rate(policy->cpu, new_freq, SETRATE_CPUFREQ);
@@ -268,25 +260,6 @@
}
}
-static ssize_t store_mfreq(struct sysdev_class *class,
- struct sysdev_class_attribute *attr,
- const char *buf, size_t count)
-{
- u64 val;
-
- if (strict_strtoull(buf, 0, &val) < 0) {
- pr_err("Invalid parameter to mfreq\n");
- return 0;
- }
- if (val)
- override_cpu = 1;
- else
- override_cpu = 0;
- return count;
-}
-
-static SYSDEV_CLASS_ATTR(mfreq, 0200, NULL, store_mfreq);
-
static struct freq_attr *msm_freq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
@@ -310,11 +283,6 @@
{
int cpu;
- int err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
- &attr_mfreq.attr);
- if (err)
- pr_err("Failed to create sysfs mfreq\n");
-
for_each_possible_cpu(cpu) {
mutex_init(&(per_cpu(cpufreq_suspend, cpu).suspend_mutex));
per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 9328143..ca85a0a 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -31,6 +31,7 @@
#include <linux/ion.h>
#include "clock.h"
#include "devices.h"
+#include "footswitch.h"
#include "msm_watchdog.h"
#include "rpm_stats.h"
#include "rpm_log.h"
@@ -50,6 +51,7 @@
#define MSM_UART7DM_PHYS (MSM_GSBI7_PHYS + 0x40000)
/* GSBI QUP devices */
+#define MSM_GSBI1_QUP_PHYS (MSM_GSBI1_PHYS + 0x20000)
#define MSM_GSBI3_QUP_PHYS (MSM_GSBI3_PHYS + 0x80000)
#define MSM_GSBI4_QUP_PHYS (MSM_GSBI4_PHYS + 0x80000)
#define MSM_GSBI5_QUP_PHYS (MSM_GSBI5_PHYS + 0x80000)
@@ -66,6 +68,10 @@
#define MSM_HSUSB1_PHYS 0x12500000
#define MSM_HSUSB1_SIZE SZ_4K
+/* Address of HS USB3 */
+#define MSM_HSUSB3_PHYS 0x12520000
+#define MSM_HSUSB3_SIZE SZ_4K
+
static struct msm_watchdog_pdata msm_watchdog_pdata = {
.pet_time = 10000,
.bark_time = 11000,
@@ -195,6 +201,46 @@
},
};
+static struct resource resources_qup_i2c_gsbi1[] = {
+ {
+ .name = "gsbi_qup_i2c_addr",
+ .start = MSM_GSBI1_PHYS,
+ .end = MSM_GSBI1_PHYS + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "qup_phys_addr",
+ .start = MSM_GSBI1_QUP_PHYS,
+ .end = MSM_GSBI1_QUP_PHYS + MSM_QUP_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "qup_err_intr",
+ .start = APQ8064_GSBI1_QUP_IRQ,
+ .end = APQ8064_GSBI1_QUP_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "i2c_clk",
+ .start = 21,
+ .end = 21,
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .name = "i2c_sda",
+ .start = 20,
+ .end = 20,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+struct platform_device apq8064_device_qup_i2c_gsbi1 = {
+ .name = "qup_i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(resources_qup_i2c_gsbi1),
+ .resource = resources_qup_i2c_gsbi1,
+};
+
struct platform_device apq8064_device_qup_i2c_gsbi3 = {
.name = "qup_i2c",
.id = 3,
@@ -221,6 +267,18 @@
.end = GSBI4_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
+ {
+ .name = "i2c_clk",
+ .start = 11,
+ .end = 11,
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .name = "i2c_sda",
+ .start = 10,
+ .end = 10,
+ .flags = IORESOURCE_IO,
+ },
};
struct platform_device apq8064_device_qup_i2c_gsbi4 = {
@@ -306,7 +364,7 @@
};
struct platform_device apq_cpudai_hdmi_rx = {
- .name = "msm-dai-q6",
+ .name = "msm-dai-q6-hdmi",
.id = 8,
};
@@ -413,6 +471,11 @@
.id = -1,
};
+struct platform_device apq_cpudai_stub = {
+ .name = "msm-dai-stub",
+ .id = -1,
+};
+
static struct resource resources_ssbi_pmic1[] = {
{
.start = MSM_PMIC1_SSBI_CMD_PHYS,
@@ -591,6 +654,30 @@
},
};
+static struct resource resources_ehci_host3[] = {
+{
+ .start = MSM_HSUSB3_PHYS,
+ .end = MSM_HSUSB3_PHYS + MSM_HSUSB3_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USB3_HS_IRQ,
+ .end = USB3_HS_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device apq8064_device_ehci_host3 = {
+ .name = "msm_ehci_host",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(resources_ehci_host3),
+ .resource = resources_ehci_host3,
+ .dev = {
+ .dma_mask = &dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
/* MSM Video core device */
#ifdef CONFIG_MSM_BUS_SCALING
static struct msm_bus_vectors vidc_init_vectors[] = {
@@ -1172,6 +1259,17 @@
.resource = msm_gss_resources,
};
+struct platform_device *apq8064_fs_devices[] = {
+ FS_8X60(FS_ROT, "fs_rot"),
+ FS_8X60(FS_IJPEG, "fs_ijpeg"),
+ FS_8X60(FS_VFE, "fs_vfe"),
+ FS_8X60(FS_VPE, "fs_vpe"),
+ FS_8X60(FS_GFX3D, "fs_gfx3d"),
+ FS_8X60(FS_VED, "fs_ved"),
+ FS_8X60(FS_VCAP, "fs_vcap"),
+};
+unsigned apq8064_num_fs_devices = ARRAY_SIZE(apq8064_fs_devices);
+
static struct clk_lookup msm_clocks_8064_dummy[] = {
CLK_DUMMY("pll2", PLL2, NULL, 0),
CLK_DUMMY("pll8", PLL8, NULL, 0),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 4525bab..19a8db7 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1134,27 +1134,27 @@
};
#ifdef CONFIG_MSM_CAMERA
-struct resource msm_camera_resources[] = {
+static struct resource msm_cam_gsbi4_i2c_mux_resources[] = {
{
- .name = "s3d_rw",
+ .name = "i2c_mux_rw",
.start = 0x008003E0,
- .end = 0x008003E0 + SZ_16 - 1,
+ .end = 0x008003E0 + SZ_8 - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "s3d_ctl",
+ .name = "i2c_mux_ctl",
.start = 0x008020B8,
- .end = 0x008020B8 + SZ_16 - 1,
+ .end = 0x008020B8 + SZ_4 - 1,
.flags = IORESOURCE_MEM,
},
};
-int __init msm_get_cam_resources(struct msm_camera_sensor_info *s_info)
-{
- s_info->resource = msm_camera_resources;
- s_info->num_resources = ARRAY_SIZE(msm_camera_resources);
- return 0;
-}
+struct platform_device msm8960_device_i2c_mux_gsbi4 = {
+ .name = "msm_cam_i2c_mux",
+ .id = 0,
+ .resource = msm_cam_gsbi4_i2c_mux_resources,
+ .num_resources = ARRAY_SIZE(msm_cam_gsbi4_i2c_mux_resources),
+};
static struct resource msm_csiphy0_resources[] = {
{
@@ -1186,6 +1186,21 @@
},
};
+static struct resource msm_csiphy2_resources[] = {
+ {
+ .name = "csiphy",
+ .start = 0x04801400,
+ .end = 0x04801400 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csiphy",
+ .start = MSM8960_CSIPHY_2_2LN_IRQ,
+ .end = MSM8960_CSIPHY_2_2LN_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
struct platform_device msm8960_device_csiphy0 = {
.name = "msm_csiphy",
.id = 0,
@@ -1200,6 +1215,13 @@
.num_resources = ARRAY_SIZE(msm_csiphy1_resources),
};
+struct platform_device msm8960_device_csiphy2 = {
+ .name = "msm_csiphy",
+ .id = 2,
+ .resource = msm_csiphy2_resources,
+ .num_resources = ARRAY_SIZE(msm_csiphy2_resources),
+};
+
static struct resource msm_csid0_resources[] = {
{
.name = "csid",
@@ -1230,6 +1252,21 @@
},
};
+static struct resource msm_csid2_resources[] = {
+ {
+ .name = "csid",
+ .start = 0x04801800,
+ .end = 0x04801800 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csid",
+ .start = CSI_2_IRQ,
+ .end = CSI_2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
struct platform_device msm8960_device_csid0 = {
.name = "msm_csid",
.id = 0,
@@ -1244,6 +1281,13 @@
.num_resources = ARRAY_SIZE(msm_csid1_resources),
};
+struct platform_device msm8960_device_csid2 = {
+ .name = "msm_csid",
+ .id = 2,
+ .resource = msm_csid2_resources,
+ .num_resources = ARRAY_SIZE(msm_csid2_resources),
+};
+
struct resource msm_ispif_resources[] = {
{
.name = "ispif",
@@ -2247,6 +2291,20 @@
},
};
+static const char *kgsl_3d0_iommu_ctx_names[] = {
+ "gfx3d_user",
+ /* priv_ctx goes here */
+};
+
+static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = {
+ {
+ .iommu_ctx_names = kgsl_3d0_iommu_ctx_names,
+ .iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu_ctx_names),
+ .physstart = 0x07C00000,
+ .physend = 0x07C00000 + SZ_1M - 1,
+ },
+};
+
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
@@ -2283,8 +2341,8 @@
#ifdef CONFIG_MSM_BUS_SCALING
.bus_scale_table = &grp3d_bus_scale_pdata,
#endif
- .iommu_user_ctx_name = "gfx3d_user",
- .iommu_priv_ctx_name = NULL,
+ .iommu_data = kgsl_3d0_iommu_data,
+ .iommu_count = ARRAY_SIZE(kgsl_3d0_iommu_data),
};
struct platform_device msm_kgsl_3d0 = {
@@ -2312,6 +2370,19 @@
},
};
+static const char *kgsl_2d0_iommu_ctx_names[] = {
+ "gfx2d0_2d0",
+};
+
+static struct kgsl_device_iommu_data kgsl_2d0_iommu_data[] = {
+ {
+ .iommu_ctx_names = kgsl_2d0_iommu_ctx_names,
+ .iommu_ctx_count = ARRAY_SIZE(kgsl_2d0_iommu_ctx_names),
+ .physstart = 0x07D00000,
+ .physend = 0x07D00000 + SZ_1M - 1,
+ },
+};
+
static struct kgsl_device_platform_data kgsl_2d0_pdata = {
.pwrlevel = {
{
@@ -2336,8 +2407,8 @@
#ifdef CONFIG_MSM_BUS_SCALING
.bus_scale_table = &grp2d0_bus_scale_pdata,
#endif
- .iommu_user_ctx_name = "gfx2d0_2d0",
- .iommu_priv_ctx_name = NULL,
+ .iommu_data = kgsl_2d0_iommu_data,
+ .iommu_count = ARRAY_SIZE(kgsl_2d0_iommu_data),
};
struct platform_device msm_kgsl_2d0 = {
@@ -2350,6 +2421,19 @@
},
};
+static const char *kgsl_2d1_iommu_ctx_names[] = {
+ "gfx2d1_2d1",
+};
+
+static struct kgsl_device_iommu_data kgsl_2d1_iommu_data[] = {
+ {
+ .iommu_ctx_names = kgsl_2d1_iommu_ctx_names,
+ .iommu_ctx_count = ARRAY_SIZE(kgsl_2d1_iommu_ctx_names),
+ .physstart = 0x07E00000,
+ .physend = 0x07E00000 + SZ_1M - 1,
+ },
+};
+
static struct resource kgsl_2d1_resources[] = {
{
.name = KGSL_2D1_REG_MEMORY,
@@ -2389,8 +2473,8 @@
#ifdef CONFIG_MSM_BUS_SCALING
.bus_scale_table = &grp2d1_bus_scale_pdata,
#endif
- .iommu_user_ctx_name = "gfx2d1_2d1",
- .iommu_priv_ctx_name = NULL,
+ .iommu_data = kgsl_2d1_iommu_data,
+ .iommu_count = ARRAY_SIZE(kgsl_2d1_iommu_data),
};
struct platform_device msm_kgsl_2d1 = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 3944a93..18acb36 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -234,6 +234,30 @@
},
};
+static struct resource resources_hsic_host[] = {
+ {
+ .start = MSM9615_HSIC_PHYS,
+ .end = MSM9615_HSIC_PHYS + MSM9615_HSIC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USB_HSIC_IRQ,
+ .end = USB_HSIC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_device_hsic_host = {
+ .name = "msm_hsic_host",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_hsic_host),
+ .resource = resources_hsic_host,
+ .dev = {
+ .dma_mask = &dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
static struct resource resources_uart_gsbi4[] = {
{
.start = GSBI4_UARTDM_IRQ,
@@ -419,7 +443,7 @@
};
static struct tsens_platform_data msm_tsens_pdata = {
- .slope = 910,
+ .slope = {872, 872, 872, 872, 872},
.tsens_factor = 1000,
.hw_type = MSM_9615,
.tsens_num_sensor = 5,
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 31eee43..c18b6b2 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -178,17 +178,6 @@
&msm_device_hsusb_host,
};
-int msm_add_host(unsigned int host, struct msm_usb_host_platform_data *plat)
-{
- struct platform_device *pdev;
-
- pdev = msm_host_devices[host];
- if (!pdev)
- return -ENODEV;
- pdev->dev.platform_data = plat;
- return platform_device_register(pdev);
-}
-
static struct resource msm_dmov_resource[] = {
{
.start = INT_ADM_AARM,
@@ -513,18 +502,6 @@
&msm_device_sdc4,
};
-int __init msm_add_sdcc(unsigned int controller, struct mmc_platform_data *plat)
-{
- struct platform_device *pdev;
-
- if (controller < 1 || controller > 4)
- return -EINVAL;
-
- pdev = msm_sdcc_devices[controller-1];
- pdev->dev.platform_data = plat;
- return platform_device_register(pdev);
-}
-
#ifdef CONFIG_MSM_CAMERA_V4L2
static struct resource msm_csic0_resources[] = {
{
@@ -715,17 +692,6 @@
__func__, ret);
}
-void __init msm_fb_register_device(char *name, void *data)
-{
- if (!strncmp(name, "mdp", 3))
- msm_register_device(&msm_mdp_device, data);
- else if (!strncmp(name, "mipi_dsi", 8))
- msm_register_device(&msm_mipi_dsi_device, data);
- else if (!strncmp(name, "lcdc", 4))
- msm_register_device(&msm_lcdc_device, data);
- else
- printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
-}
#define PERPH_WEB_BLOCK_ADDR (0xA9D00040)
#define PDM0_CTL_OFFSET (0x04)
@@ -815,6 +781,68 @@
.resource = msm8625_resources_uart1,
};
+static struct resource msm8625_uart1_dm_resources[] = {
+ {
+ .start = MSM_UART1DM_PHYS,
+ .end = MSM_UART1DM_PHYS + PAGE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_UART1DM_IRQ,
+ .end = MSM8625_INT_UART1DM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM8625_INT_UART1DM_RX,
+ .end = MSM8625_INT_UART1DM_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = DMOV_HSUART1_TX_CHAN,
+ .end = DMOV_HSUART1_RX_CHAN,
+ .name = "uartdm_channels",
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = DMOV_HSUART1_TX_CRCI,
+ .end = DMOV_HSUART1_RX_CRCI,
+ .name = "uartdm_crci",
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+struct platform_device msm8625_device_uart_dm1 = {
+ .name = "msm_serial_hs",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm8625_uart1_dm_resources),
+ .resource = msm8625_uart1_dm_resources,
+ .dev = {
+ .dma_mask = &msm_uart_dm1_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static struct resource msm8625_uart2dm_resources[] = {
+ {
+ .start = MSM_UART2DM_PHYS,
+ .end = MSM_UART2DM_PHYS + PAGE_SIZE - 1,
+ .name = "uartdm_resource",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_UART2DM_IRQ,
+ .end = MSM8625_INT_UART2DM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8625_device_uart_dm2 = {
+ .name = "msm_serial_hsl",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm8625_uart2dm_resources),
+ .resource = msm8625_uart2dm_resources,
+};
+
static struct resource msm8625_dmov_resource[] = {
{
.start = MSM8625_INT_ADM_AARM,
@@ -866,6 +894,35 @@
.resource = gsbi0_msm8625_qup_resources,
};
+static struct resource gsbi1_msm8625_qup_i2c_resources[] = {
+ {
+ .name = "qup_phys_addr",
+ .start = MSM_GSBI1_QUP_PHYS,
+ .end = MSM_GSBI1_QUP_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "gsbi_qup_i2c_addr",
+ .start = MSM_GSBI1_PHYS,
+ .end = MSM_GSBI1_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "qup_err_intr",
+ .start = MSM8625_INT_ARM11_DMA,
+ .end = MSM8625_INT_ARM11_DMA,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* Use GSBI1 QUP for /dev/i2c-1 */
+struct platform_device msm8625_device_qup_i2c_gsbi1 = {
+ .name = "qup_i2c",
+ .id = MSM_GSBI1_QUP_I2C_BUS_ID,
+ .num_resources = ARRAY_SIZE(gsbi1_qup_i2c_resources),
+ .resource = gsbi1_msm8625_qup_i2c_resources,
+};
+
static struct resource msm8625_gpio_resources[] = {
{
.start = MSM8625_INT_GPIO_GROUP1,
@@ -884,6 +941,391 @@
.num_resources = ARRAY_SIZE(msm8625_gpio_resources),
};
+static struct resource msm8625_resources_sdc1[] = {
+ {
+ .start = MSM_SDC1_BASE,
+ .end = MSM_SDC1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_SDC1_0,
+ .end = MSM8625_INT_SDC1_1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "sdcc_dma_chnl",
+ .start = DMOV_SDC1_CHAN,
+ .end = DMOV_SDC1_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "sdcc_dma_crci",
+ .start = DMOV_SDC1_CRCI,
+ .end = DMOV_SDC1_CRCI,
+ .flags = IORESOURCE_DMA,
+ }
+};
+
+static struct resource msm8625_resources_sdc2[] = {
+ {
+ .start = MSM_SDC2_BASE,
+ .end = MSM_SDC2_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_SDC2_0,
+ .end = MSM8625_INT_SDC2_1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "sdcc_dma_chnl",
+ .start = DMOV_SDC2_CHAN,
+ .end = DMOV_SDC2_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "sdcc_dma_crci",
+ .start = DMOV_SDC2_CRCI,
+ .end = DMOV_SDC2_CRCI,
+ .flags = IORESOURCE_DMA,
+ }
+};
+
+static struct resource msm8625_resources_sdc3[] = {
+ {
+ .start = MSM_SDC3_BASE,
+ .end = MSM_SDC3_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_SDC3_0,
+ .end = MSM8625_INT_SDC3_1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "sdcc_dma_chnl",
+ .start = DMOV_SDC3_CHAN,
+ .end = DMOV_SDC3_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "sdcc_dma_crci",
+ .start = DMOV_SDC3_CRCI,
+ .end = DMOV_SDC3_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct resource msm8625_resources_sdc4[] = {
+ {
+ .start = MSM_SDC4_BASE,
+ .end = MSM_SDC4_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_SDC4_0,
+ .end = MSM8625_INT_SDC4_1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "sdcc_dma_chnl",
+ .start = DMOV_SDC4_CHAN,
+ .end = DMOV_SDC4_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "sdcc_dma_crci",
+ .start = DMOV_SDC4_CRCI,
+ .end = DMOV_SDC4_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+struct platform_device msm8625_device_sdc1 = {
+ .name = "msm_sdcc",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(msm8625_resources_sdc1),
+ .resource = msm8625_resources_sdc1,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+struct platform_device msm8625_device_sdc2 = {
+ .name = "msm_sdcc",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(msm8625_resources_sdc2),
+ .resource = msm8625_resources_sdc2,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+struct platform_device msm8625_device_sdc3 = {
+ .name = "msm_sdcc",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(msm8625_resources_sdc3),
+ .resource = msm8625_resources_sdc3,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+struct platform_device msm8625_device_sdc4 = {
+ .name = "msm_sdcc",
+ .id = 4,
+ .num_resources = ARRAY_SIZE(msm8625_resources_sdc4),
+ .resource = msm8625_resources_sdc4,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+static struct platform_device *msm8625_sdcc_devices[] __initdata = {
+ &msm8625_device_sdc1,
+ &msm8625_device_sdc2,
+ &msm8625_device_sdc3,
+ &msm8625_device_sdc4,
+};
+
+int __init msm_add_sdcc(unsigned int controller, struct mmc_platform_data *plat)
+{
+ struct platform_device *pdev;
+
+ if (controller < 1 || controller > 4)
+ return -EINVAL;
+
+ if (cpu_is_msm8625())
+ pdev = msm8625_sdcc_devices[controller-1];
+ else
+ pdev = msm_sdcc_devices[controller-1];
+
+ pdev->dev.platform_data = plat;
+ return platform_device_register(pdev);
+}
+
+static struct resource msm8625_resources_hsusb_otg[] = {
+ {
+ .start = MSM_HSUSB_PHYS,
+ .end = MSM_HSUSB_PHYS + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_USB_HS,
+ .end = MSM8625_INT_USB_HS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8625_device_otg = {
+ .name = "msm_otg",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(msm8625_resources_hsusb_otg),
+ .resource = msm8625_resources_hsusb_otg,
+ .dev = {
+ .dma_mask = &dma_mask,
+ .coherent_dma_mask = 0xffffffffULL,
+ },
+};
+
+static struct resource msm8625_resources_gadget_peripheral[] = {
+ {
+ .start = MSM_HSUSB_PHYS,
+ .end = MSM_HSUSB_PHYS + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_USB_HS,
+ .end = MSM8625_INT_USB_HS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8625_device_gadget_peripheral = {
+ .name = "msm_hsusb",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(msm8625_resources_gadget_peripheral),
+ .resource = msm8625_resources_gadget_peripheral,
+ .dev = {
+ .dma_mask = &dma_mask,
+ .coherent_dma_mask = 0xffffffffULL,
+ },
+};
+
+static struct resource msm8625_resources_hsusb_host[] = {
+ {
+ .start = MSM_HSUSB_PHYS,
+ .end = MSM_HSUSB_PHYS + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_USB_HS,
+ .end = MSM8625_INT_USB_HS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8625_device_hsusb_host = {
+ .name = "msm_hsusb_host",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm8625_resources_hsusb_host),
+ .resource = msm8625_resources_hsusb_host,
+ .dev = {
+ .dma_mask = &dma_mask,
+ .coherent_dma_mask = 0xffffffffULL,
+ },
+};
+
+static struct platform_device *msm8625_host_devices[] = {
+ &msm8625_device_hsusb_host,
+};
+
+int msm_add_host(unsigned int host, struct msm_usb_host_platform_data *plat)
+{
+ struct platform_device *pdev;
+
+ if (cpu_is_msm8625())
+ pdev = msm8625_host_devices[host];
+ else
+ pdev = msm_host_devices[host];
+ if (!pdev)
+ return -ENODEV;
+ pdev->dev.platform_data = plat;
+ return platform_device_register(pdev);
+}
+
+#ifdef CONFIG_MSM_CAMERA_V4L2
+static struct resource msm8625_csic0_resources[] = {
+ {
+ .name = "csic",
+ .start = 0xA0F00000,
+ .end = 0xA0F00000 + 0x00100000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csic",
+ .start = MSM8625_INT_CSI_IRQ_0,
+ .end = MSM8625_INT_CSI_IRQ_0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm8625_csic1_resources[] = {
+ {
+ .name = "csic",
+ .start = 0xA1000000,
+ .end = 0xA1000000 + 0x00100000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csic",
+ .start = MSM8625_INT_CSI_IRQ_1,
+ .end = MSM8625_INT_CSI_IRQ_1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8625_device_csic0 = {
+ .name = "msm_csic",
+ .id = 0,
+ .resource = msm8625_csic0_resources,
+ .num_resources = ARRAY_SIZE(msm8625_csic0_resources),
+};
+
+struct platform_device msm8625_device_csic1 = {
+ .name = "msm_csic",
+ .id = 1,
+ .resource = msm8625_csic1_resources,
+ .num_resources = ARRAY_SIZE(msm8625_csic1_resources),
+};
+#endif
+
+static struct resource msm8625_mipi_dsi_resources[] = {
+ {
+ .name = "mipi_dsi",
+ .start = MIPI_DSI_HW_BASE,
+ .end = MIPI_DSI_HW_BASE + 0x000F0000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_DSI_IRQ,
+ .end = MSM8625_INT_DSI_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device msm8625_mipi_dsi_device = {
+ .name = "mipi_dsi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(msm8625_mipi_dsi_resources),
+ .resource = msm8625_mipi_dsi_resources,
+};
+
+static struct resource msm8625_mdp_resources[] = {
+ {
+ .name = "mdp",
+ .start = MDP_BASE,
+ .end = MDP_BASE + 0x000F1008 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM8625_INT_MDP,
+ .end = MSM8625_INT_MDP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device msm8625_mdp_device = {
+ .name = "mdp",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm8625_mdp_resources),
+ .resource = msm8625_mdp_resources,
+};
+
+void __init msm_fb_register_device(char *name, void *data)
+{
+ if (!strncmp(name, "mdp", 3)) {
+ if (cpu_is_msm8625())
+ msm_register_device(&msm8625_mdp_device, data);
+ else
+ msm_register_device(&msm_mdp_device, data);
+ } else if (!strncmp(name, "mipi_dsi", 8)) {
+ if (cpu_is_msm8625())
+ msm_register_device(&msm8625_mipi_dsi_device, data);
+ else
+ msm_register_device(&msm_mipi_dsi_device, data);
+ } else if (!strncmp(name, "lcdc", 4)) {
+ msm_register_device(&msm_lcdc_device, data);
+ } else {
+ printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
+ }
+}
+
+static struct resource msm8625_kgsl_3d0_resources[] = {
+ {
+ .name = KGSL_3D0_REG_MEMORY,
+ .start = 0xA0000000,
+ .end = 0xA001ffff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = KGSL_3D0_IRQ,
+ .start = MSM8625_INT_GRAPHICS,
+ .end = MSM8625_INT_GRAPHICS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8625_kgsl_3d0 = {
+ .name = "kgsl-3d0",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm8625_kgsl_3d0_resources),
+ .resource = msm8625_kgsl_3d0_resources,
+ .dev = {
+ .platform_data = &kgsl_3d0_pdata,
+ },
+};
+
static struct clk_lookup msm_clock_8625_dummy[] = {
CLK_DUMMY("core_clk", adm_clk.c, "msm_dmov", 0),
CLK_DUMMY("adsp_clk", adsp_clk.c, NULL, 0),
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index be6a645..c2383c6 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -23,6 +23,10 @@
extern struct platform_device msm7x27a_device_csic0;
extern struct platform_device msm7x27a_device_csic1;
extern struct platform_device msm7x27a_device_clkctl;
+
+extern struct platform_device msm8625_device_csic0;
+extern struct platform_device msm8625_device_csic1;
+
void __init msm8625_init_irq(void);
void __init msm8625_map_io(void);
int ar600x_wlan_power(bool on);
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index fc732da..e9b94f6 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -1181,6 +1181,7 @@
.set_grp_async = set_grp3d_async,
.idle_timeout = HZ/20,
.nap_allowed = true,
+ .idle_needed = true,
.clk_map = KGSL_CLK_SRC | KGSL_CLK_CORE |
KGSL_CLK_IFACE | KGSL_CLK_MEM,
};
@@ -1223,6 +1224,7 @@
.set_grp_async = NULL,
.idle_timeout = HZ/10,
.nap_allowed = true,
+ .idle_needed = true,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
};
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index c4f57ab..6da7b8f 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -59,10 +59,13 @@
extern struct platform_device msm8960_device_qup_i2c_gsbi12;
extern struct platform_device msm8960_device_qup_spi_gsbi1;
extern struct platform_device msm8960_gemini_device;
+extern struct platform_device msm8960_device_i2c_mux_gsbi4;
extern struct platform_device msm8960_device_csiphy0;
extern struct platform_device msm8960_device_csiphy1;
+extern struct platform_device msm8960_device_csiphy2;
extern struct platform_device msm8960_device_csid0;
extern struct platform_device msm8960_device_csid1;
+extern struct platform_device msm8960_device_csid2;
extern struct platform_device msm8960_device_ispif;
extern struct platform_device msm8960_device_vfe;
extern struct platform_device msm8960_device_vpe;
@@ -70,6 +73,7 @@
extern struct platform_device apq8064_device_uart_gsbi1;
extern struct platform_device apq8064_device_uart_gsbi3;
extern struct platform_device apq8064_device_uart_gsbi7;
+extern struct platform_device apq8064_device_qup_i2c_gsbi1;
extern struct platform_device apq8064_device_qup_i2c_gsbi3;
extern struct platform_device apq8064_device_qup_i2c_gsbi4;
extern struct platform_device apq8064_device_qup_spi_gsbi5;
@@ -106,6 +110,7 @@
extern struct platform_device apq8064_device_gadget_peripheral;
extern struct platform_device apq8064_device_hsusb_host;
extern struct platform_device apq8064_device_hsic_host;
+extern struct platform_device apq8064_device_ehci_host3;
extern struct platform_device msm_device_i2c;
@@ -123,6 +128,17 @@
extern struct platform_device msm_gsbi12_qup_i2c_device;
extern struct platform_device msm8625_device_qup_i2c_gsbi0;
+extern struct platform_device msm8625_device_qup_i2c_gsbi1;
+extern struct platform_device msm8625_device_uart_dm1;
+extern struct platform_device msm8625_device_uart_dm2;
+extern struct platform_device msm8625_device_sdc1;
+extern struct platform_device msm8625_device_sdc2;
+extern struct platform_device msm8625_device_sdc3;
+extern struct platform_device msm8625_device_sdc4;
+extern struct platform_device msm8625_device_gadget_peripheral;
+extern struct platform_device msm8625_device_hsusb_host;
+extern struct platform_device msm8625_device_otg;
+extern struct platform_device msm8625_kgsl_3d0;
extern struct platform_device msm_slim_ctrl;
extern struct platform_device msm_device_sps;
@@ -222,9 +238,12 @@
extern struct platform_device apq_cpudai_afe_02_rx;
extern struct platform_device apq_cpudai_afe_02_tx;
extern struct platform_device apq_pcm_afe;
+extern struct platform_device apq_cpudai_stub;
extern struct platform_device *msm_footswitch_devices[];
extern unsigned msm_num_footswitch_devices;
+extern struct platform_device *apq8064_fs_devices[];
+extern unsigned apq8064_num_fs_devices;
extern struct platform_device fsm_qfp_fuse_device;
diff --git a/arch/arm/mach-msm/etm.c b/arch/arm/mach-msm/etm.c
index bee0975..9d04a58 100644
--- a/arch/arm/mach-msm/etm.c
+++ b/arch/arm/mach-msm/etm.c
@@ -377,9 +377,9 @@
etm_write(etm_config.etm_addr_access_type[6], ETMACTR6);
etm_write(etm_config.etm_addr_access_type[7], ETMACTR7);
etm_write(etm_config.etm_data_comp_value[0], ETMDCVR0);
- etm_write(etm_config.etm_data_comp_value[1], ETMDCVR1);
+ etm_write(etm_config.etm_data_comp_value[1], ETMDCVR2);
etm_write(etm_config.etm_data_comp_mask[0], ETMDCMR0);
- etm_write(etm_config.etm_data_comp_mask[1], ETMDCMR1);
+ etm_write(etm_config.etm_data_comp_mask[1], ETMDCMR2);
etm_write(etm_config.etm_counter_reload_value[0], ETMCNTRLDVR0);
etm_write(etm_config.etm_counter_reload_value[1], ETMCNTRLDVR1);
etm_write(etm_config.etm_counter_enable[0], ETMCNTENR0);
@@ -564,9 +564,9 @@
emit_log_word(etm_read(ETMACTR6));
emit_log_word(etm_read(ETMACTR7));
emit_log_word(etm_read(ETMDCVR0));
- emit_log_word(etm_read(ETMDCVR1));
+ emit_log_word(etm_read(ETMDCVR2));
emit_log_word(etm_read(ETMDCMR0));
- emit_log_word(etm_read(ETMDCMR1));
+ emit_log_word(etm_read(ETMDCMR2));
emit_log_word(etm_read(ETMCNTRLDVR0));
emit_log_word(etm_read(ETMCNTRLDVR1));
emit_log_word(etm_read(ETMCNTENR0));
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index 5c10463..4609a4b 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -99,8 +99,8 @@
clock->reset_rate : DEFAULT_RATE;
rc = clk_set_rate(clock->clk, rate);
if (rc && rc != -ENOSYS) {
- pr_err("Failed to set %s rate to %lu Hz.\n",
- clock->name, clock->rate);
+ pr_err("Failed to set %s %s rate to %lu Hz.\n",
+ fs->desc.name, clock->name, clock->rate);
for (clock--; clock >= fs->clk_data; clock--) {
if (clock->enabled)
clk_disable_unprepare(
@@ -131,8 +131,8 @@
if (clock->enabled)
clk_disable_unprepare(clock->clk);
if (clock->rate && clk_set_rate(clock->clk, clock->rate))
- pr_err("Failed to restore %s rate to %lu Hz.\n",
- clock->name, clock->rate);
+ pr_err("Failed to restore %s %s rate to %lu Hz.\n",
+ fs->desc.name, clock->name, clock->rate);
}
}
@@ -167,14 +167,14 @@
if (fs->bus_port0) {
rc = msm_bus_axi_portunhalt(fs->bus_port0);
if (rc) {
- pr_err("Port 0 unhalt failed.\n");
+ pr_err("%s port 0 unhalt failed.\n", fs->desc.name);
goto err;
}
}
if (fs->bus_port1) {
rc = msm_bus_axi_portunhalt(fs->bus_port1);
if (rc) {
- pr_err("Port 1 unhalt failed.\n");
+ pr_err("%s port 1 unhalt failed.\n", fs->desc.name);
goto err_port2_halt;
}
}
@@ -252,14 +252,14 @@
if (fs->bus_port0) {
rc = msm_bus_axi_porthalt(fs->bus_port0);
if (rc) {
- pr_err("Port 0 halt failed.\n");
+ pr_err("%s port 0 halt failed.\n", fs->desc.name);
goto err;
}
}
if (fs->bus_port1) {
rc = msm_bus_axi_porthalt(fs->bus_port1);
if (rc) {
- pr_err("Port 1 halt failed.\n");
+ pr_err("%s port 1 halt failed.\n", fs->desc.name);
goto err_port2_halt;
}
}
@@ -329,7 +329,7 @@
if (fs->bus_port0) {
rc = msm_bus_axi_portunhalt(fs->bus_port0);
if (rc) {
- pr_err("Port 0 unhalt failed.\n");
+ pr_err("%s port 0 unhalt failed.\n", fs->desc.name);
goto err;
}
}
@@ -404,7 +404,7 @@
if (fs->bus_port0) {
rc = msm_bus_axi_porthalt(fs->bus_port0);
if (rc) {
- pr_err("Port 0 halt failed.\n");
+ pr_err("%s port 0 halt failed.\n", fs->desc.name);
goto err;
}
}
@@ -635,7 +635,8 @@
clock->clk = clk_get(&pdev->dev, clock->name);
if (IS_ERR(clock->clk)) {
rc = PTR_ERR(clock->clk);
- pr_err("clk_get(%s) failed\n", clock->name);
+ pr_err("%s clk_get(%s) failed\n", fs->desc.name,
+ clock->name);
goto err;
}
if (!strncmp(clock->name, "core_clk", 8))
diff --git a/arch/arm/mach-msm/footswitch-pcom.c b/arch/arm/mach-msm/footswitch-pcom.c
index 340f19b..f8e84fc 100644
--- a/arch/arm/mach-msm/footswitch-pcom.c
+++ b/arch/arm/mach-msm/footswitch-pcom.c
@@ -205,14 +205,14 @@
fs->src_clk = clk_get(dev, "core_clk");
}
if (IS_ERR(fs->src_clk)) {
- pr_err("clk_get(src_clk) failed\n");
+ pr_err("%s clk_get(src_clk) failed\n", fs->desc.name);
rc = PTR_ERR(fs->src_clk);
goto err_src_clk;
}
fs->core_clk = clk_get(dev, "core_clk");
if (IS_ERR(fs->core_clk)) {
- pr_err("clk_get(core_clk) failed\n");
+ pr_err("%s clk_get(core_clk) failed\n", fs->desc.name);
rc = PTR_ERR(fs->core_clk);
goto err_core_clk;
}
@@ -220,7 +220,7 @@
if (fs->has_ahb_clk) {
fs->ahb_clk = clk_get(dev, "iface_clk");
if (IS_ERR(fs->ahb_clk)) {
- pr_err("clk_get(iface_clk) failed\n");
+ pr_err("%s clk_get(iface_clk) failed\n", fs->desc.name);
rc = PTR_ERR(fs->ahb_clk);
goto err_ahb_clk;
}
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 26adec6..8d40908 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -10,10 +10,13 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
+#include <linux/cpu.h>
#include <asm/cacheflush.h>
#include <asm/vfp.h>
+#include <mach/msm_rtb.h>
+
#include "pm.h"
#include "qdss.h"
#include "spm.h"
@@ -49,6 +52,9 @@
/*
* OK, proper wakeup, we're done
*/
+ pen_release = -1;
+ dmac_flush_range((void *)&pen_release,
+ (void *)(&pen_release + sizeof(pen_release)));
break;
}
@@ -60,6 +66,8 @@
* possible, since we are currently running incoherently, and
* therefore cannot safely call printk() or anything else
*/
+ dmac_inv_range((void *)&pen_release,
+ (void *)(&pen_release + sizeof(pen_release)));
pr_debug("CPU%u: spurious wakeup call\n", cpu);
}
}
@@ -109,6 +117,45 @@
return cpu == 0 ? -EPERM : 0;
}
+#define CPU_SHIFT 0
+#define CPU_MASK 0xF
+#define CPU_OF(n) (((n) & CPU_MASK) << CPU_SHIFT)
+#define CPUSET_SHIFT 4
+#define CPUSET_MASK 0xFFFF
+#define CPUSET_OF(n) (((n) & CPUSET_MASK) << CPUSET_SHIFT)
+
+static int hotplug_rtb_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ /*
+ * Bits [19:4] of the data are the online mask, lower 4 bits are the
+ * cpu number that is being changed. Additionally, changes to the
+ * online_mask that will be done by the current hotplug will be made
+ * even though they aren't necessarily in the online mask yet.
+ *
+ * XXX: This design is limited to supporting at most 16 cpus
+ */
+ int this_cpumask = CPUSET_OF(1 << (int)hcpu);
+ int cpumask = CPUSET_OF(cpumask_bits(cpu_online_mask)[0]);
+ int cpudata = CPU_OF((int)hcpu) | cpumask;
+
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_STARTING:
+ uncached_logk(LOGK_HOTPLUG, (void *)(cpudata | this_cpumask));
+ break;
+ case CPU_DYING:
+ uncached_logk(LOGK_HOTPLUG, (void *)(cpudata & ~this_cpumask));
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+static struct notifier_block hotplug_rtb_notifier = {
+ .notifier_call = hotplug_rtb_callback,
+};
+
int msm_platform_secondary_init(unsigned int cpu)
{
int ret;
@@ -127,3 +174,9 @@
return ret;
}
+
+static int __init init_hotplug_notifier(void)
+{
+ return register_hotcpu_notifier(&hotplug_rtb_notifier);
+}
+early_initcall(init_hotplug_notifier);
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index c274899..32d162d 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -100,12 +100,14 @@
cmp r1, #1
bne skip
bl v7_flush_dcache_all
+ b skip2
skip: ldr r0, =saved_state
ldr r1, =saved_state_end
sub r1, r1, r0
bl v7_flush_kern_dcache_area
+skip2:
#ifdef CONFIG_ARCH_MSM_KRAIT
ldr r0, =SCM_SVC_BOOT
ldr r1, =SCM_CMD_TERMINATE_PC
@@ -136,7 +138,9 @@
#if (NR_CPUS >= 2)
mrc p15, 0, r1, c0, c0, 5 /* MPIDR */
ands r1, r1, #15 /* What CPU am I */
- addne r0, r0, #CPU_SAVED_STATE_SIZE
+ mov r2, #CPU_SAVED_STATE_SIZE
+ mul r2, r2, r1
+ add r0, r0, r2
#endif
ldmfd r0, {r4-r14}
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index ba9fc70..96b0083 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -202,6 +202,18 @@
uint8_t cam_gpio_set_tbl_size;
};
+enum msm_camera_i2c_mux_mode {
+ MODE_R,
+ MODE_L,
+ MODE_DUAL
+};
+
+struct msm_camera_i2c_conf {
+ uint8_t use_i2c_mux;
+ struct platform_device *mux_dev;
+ enum msm_camera_i2c_mux_mode i2c_mux_mode;
+};
+
struct msm_camera_sensor_platform_info {
int mount_angle;
int sensor_reset;
@@ -209,6 +221,7 @@
int num_vreg;
int32_t (*ext_power_ctrl) (int enable);
struct msm_camera_gpio_conf *gpio_conf;
+ struct msm_camera_i2c_conf *i2c_conf;
};
struct msm_actuator_info {
@@ -238,6 +251,7 @@
char *eeprom_data;
enum msm_camera_type camera_type;
struct msm_actuator_info *actuator_info;
+ int pmic_gpio_enable;
};
struct msm_camera_board_info {
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 530d2c1..ef7be45 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -52,6 +52,7 @@
VFE_MODE_OF_OPERATION_VIDEO,
VFE_MODE_OF_OPERATION_RAW_SNAPSHOT,
VFE_MODE_OF_OPERATION_ZSL,
+ VFE_MODE_OF_OPERATION_JPEG_SNAPSHOT,
VFE_LAST_MODE_OF_OPERATION_ENUM
};
@@ -87,6 +88,7 @@
VFE_MSG_V32_START,
VFE_MSG_V32_START_RECORDING, /* 20 */
VFE_MSG_V32_CAPTURE,
+ VFE_MSG_V32_JPEG_CAPTURE,
VFE_MSG_OUTPUT_IRQ,
VFE_MSG_V2X_PREVIEW,
VFE_MSG_V2X_CAPTURE,
@@ -629,12 +631,6 @@
S_EXIT
};
-enum msm_cam_mode {
- MODE_R,
- MODE_L,
- MODE_DUAL
-};
-
struct msm_cam_clk_info {
const char *clk_name;
long clk_rate;
@@ -646,7 +642,7 @@
int msm_camio_vpe_clk_enable(uint32_t);
int msm_camio_vpe_clk_disable(void);
-void msm_camio_mode_config(enum msm_cam_mode mode);
+void msm_camio_mode_config(enum msm_camera_i2c_mux_mode mode);
int msm_camio_clk_enable(enum msm_camio_clk_type clk);
int msm_camio_clk_disable(enum msm_camio_clk_type clk);
int msm_camio_clk_config(uint32_t freq);
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 48eae0c..2d2d2fb 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -20,8 +20,9 @@
enum {
VIDEO_FIRMWARE_POOL,
- LOW_256MB_POOL,
- HIGH_POOL,
+ VIDEO_MAIN_POOL,
+ VIDEO_MFC_POOL,
+ GEN_POOL,
};
diff --git a/arch/arm/mach-msm/include/mach/irqs-8960.h b/arch/arm/mach-msm/include/mach/irqs-8960.h
index dae0f47..012dd74 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8960.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8960.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -268,6 +268,8 @@
#define PM8921_SEC_IRQ_104 (GIC_SPI_START + 225)
#define PM8018_SEC_IRQ_107 (GIC_SPI_START + 226)
#define USB_HSIC_IRQ (GIC_SPI_START + 229)
+#define MSM8960_CSIPHY_2_2LN_IRQ (GIC_SPI_START + 228)
+#define CSI_2_IRQ (GIC_SPI_START + 227)
/* Backwards compatible IRQ macros. */
#define INT_ADM_AARM ADM_0_SCSS_0_IRQ
diff --git a/arch/arm/mach-msm/include/mach/msm_adsp.h b/arch/arm/mach-msm/include/mach/msm_adsp.h
index bbae6c1..e40c07d 100644
--- a/arch/arm/mach-msm/include/mach/msm_adsp.h
+++ b/arch/arm/mach-msm/include/mach/msm_adsp.h
@@ -1,7 +1,7 @@
/* include/asm-arm/arch-msm/msm_adsp.h
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2010, 2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -52,6 +52,14 @@
unsigned queue_id,
void *data, size_t len);
+/*Explicitly gererate adsp event */
+int msm_adsp_generate_event(void *data,
+ struct msm_adsp_module *mod,
+ unsigned event_id,
+ unsigned event_length,
+ unsigned event_size,
+ void *msg);
+
#define ADSP_MESSAGE_ID 0xFFFF
/* Command Queue Indexes */
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8625.h b/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
index 8088a4c..3435c2a 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
@@ -48,11 +48,11 @@
#define MSM8625_SCU_PHYS 0xC0600000
#define MSM8625_SCU_SIZE SZ_256
-#define MSM8625_SPM0_PHYS 0xC0200000
-#define MSM8625_SPM0_SIZE SZ_4K
+#define MSM8625_SAW0_PHYS 0xC0200000
+#define MSM8625_SAW0_SIZE SZ_4K
-#define MSM8625_SPM1_PHYS 0xC0700000
-#define MSM8625_SPM1_SIZE SZ_4K
+#define MSM8625_SAW1_PHYS 0xC0700000
+#define MSM8625_SAW1_SIZE SZ_4K
#define MSM8625_CFG_CTL_PHYS 0xA9800000
#define MSM8625_CFG_CTL_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-copper.h b/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
index a3c9da8..6311dbe 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -23,12 +23,17 @@
*
*/
+#define COPPER_MSM_SHARED_RAM_PHYS 0x18D00000
+
#define COPPER_QGIC_DIST_PHYS 0xF9000000
#define COPPER_QGIC_DIST_SIZE SZ_4K
#define COPPER_QGIC_CPU_PHYS 0xF9002000
#define COPPER_QGIC_CPU_SIZE SZ_4K
+#define COPPER_APCS_GCC_PHYS 0xF9011000
+#define COPPER_APCS_GCC_SIZE SZ_4K
+
#define COPPER_TLMM_PHYS 0xFD400000
#define COPPER_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index d53910d..27965d3 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,7 +47,9 @@
#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
- defined(CONFIG_ARCH_MSMCOPPER)
+ defined(CONFIG_ARCH_MSMCOPPER) || defined(CONFIG_ARCH_MSM7X27) || \
+ defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
+ defined(CONFIG_ARCH_MSM8625)
/* Unified iomap */
@@ -80,13 +82,28 @@
#define MSM_APCS_GLB_BASE IOMEM(0xFA702000) /* 4K */
#define MSM_SAW2_BASE IOMEM(0xFA703000) /* 4k */
#define MSM_SAW3_BASE IOMEM(0xFA704000) /* 4k */
+#define MSM_VIC_BASE IOMEM(0xFA100000) /* 4K */
+#define MSM_CSR_BASE IOMEM(0xFA101000) /* 4K */
+#define MSM_GPIO1_BASE IOMEM(0xFA102000) /* 4K */
+#define MSM_GPIO2_BASE IOMEM(0xFA103000) /* 4K */
+#define MSM_SCU_BASE IOMEM(0xFA104000) /* 4K */
+#define MSM_CFG_CTL_BASE IOMEM(0xFA105000) /* 4K */
+#define MSM_MDC_BASE IOMEM(0xFA400000) /* 1M */
+#define MSM_AD5_BASE IOMEM(0xFA900000) /* 13M (D00000)
+ 0xFB600000 */
-#if defined(CONFIG_ARCH_MSM9615)
+#define MSM_STRONGLY_ORDERED_PAGE 0xFA0F0000
+#define MSM8625_SECONDARY_PHYS 0x0FE00000
+
+
+#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27)
#define MSM_SHARED_RAM_SIZE SZ_1M
#else
#define MSM_SHARED_RAM_SIZE SZ_2M
#endif
+#include "msm_iomap-7xxx.h"
+#include "msm_iomap-8625.h"
#include "msm_iomap-8960.h"
#include "msm_iomap-8930.h"
#include "msm_iomap-8064.h"
@@ -105,29 +122,7 @@
#elif defined(CONFIG_ARCH_FSM9XXX)
#include "msm_iomap-fsm9xxx.h"
#else
-#define MSM_VIC_BASE IOMEM(0xFA000000) /* 4K */
-#define MSM_CSR_BASE IOMEM(0xFA001000) /* 4K */
-#define MSM_TMR_BASE MSM_CSR_BASE /* 4K */
-#define MSM_TMR0_BASE IOMEM(0xFA002000) /* 4K */
-#define MSM_GPIO1_BASE IOMEM(0xFA003000) /* 4K */
-#define MSM_GPIO2_BASE IOMEM(0xFA004000) /* 4K */
-#define MSM_CLK_CTL_BASE IOMEM(0xFA005000) /* 4K */
-#define MSM_L2CC_BASE IOMEM(0xFA006000) /* 4K */
-#define MSM_QGIC_DIST_BASE IOMEM(0xFA007000) /* 4K */
-#define MSM_QGIC_CPU_BASE IOMEM(0xFA008000) /* 4K */
-#define MSM_SCU_BASE IOMEM(0xFA009000) /* 4K */
-#define MSM_SPM0_BASE IOMEM(0xFA00A000) /* 4K */
-#define MSM_SPM1_BASE IOMEM(0xFA00B000) /* 4K */
-#define MSM_CFG_CTL_BASE IOMEM(0xFA00C000) /* 4K */
-#define MSM_SHARED_RAM_BASE IOMEM(0xFA100000) /* 4K */
-#define MSM_MDC_BASE IOMEM(0xFA200000) /* 4K */
-#define MSM_AD5_BASE IOMEM(0xFA300000) /* 4K */
-#define MSM_STRONGLY_ORDERED_PAGE 0xFA0F0000
-#define MSM8625_SECONDARY_PHYS 0x0FE00000
-#define MSM_SHARED_RAM_SIZE SZ_1M
-
-#include "msm_iomap-7xxx.h"
-#include "msm_iomap-8625.h"
+#error "Target compiled without IO map\n"
#endif
#if defined(CONFIG_DEBUG_MSM_UART1)
diff --git a/arch/arm/mach-msm/include/mach/msm_rtb.h b/arch/arm/mach-msm/include/mach/msm_rtb.h
index ac45cbd..59352d1 100644
--- a/arch/arm/mach-msm/include/mach/msm_rtb.h
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -18,9 +18,15 @@
LOGK_READL,
LOGK_WRITEL,
LOGK_LOGBUF,
+ LOGK_HOTPLUG,
+ LOGK_CTXID,
LOGK_OTHER,
};
+struct msm_rtb_platform_data {
+ unsigned int size;
+};
+
#if defined(CONFIG_MSM_RTB)
/*
* returns 1 if data was logged, 0 otherwise
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 d50fe2b..92dfe12 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
@@ -132,6 +132,8 @@
unsigned int minor_no;
struct codec_operations codec_ops;
+ uint32_t buffer_size;
+ uint32_t buffer_count;
};
#endif /* !CODEC_UTILS_H */
diff --git a/arch/arm/mach-msm/include/mach/qpnp.h b/arch/arm/mach-msm/include/mach/qpnp.h
new file mode 100644
index 0000000..1d2e440
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qpnp.h
@@ -0,0 +1,19 @@
+ /* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/spmi.h>
+
+struct resource *qpnp_get_resource(struct spmi_device *dev,
+ unsigned int node_idx, unsigned int type,
+ unsigned int res_num);
+int qpnp_get_irq(struct spmi_device *dev, unsigned int node_idx,
+ unsigned int res_num);
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index 80ec683..bcb1240 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -117,8 +117,8 @@
MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_2,
MSM_RPM_ID_SYS_FABRIC_CFG_IOCTL,
MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
- MSM_RPM_ID_SYSTEM_FABRIC_ARB_28 =
- MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 28,
+ MSM_RPM_ID_SYSTEM_FABRIC_ARB_29 =
+ MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 29,
MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
MSM_RPM_ID_MM_FABRIC_HALT_0 =
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index e1d4459..215fdb3 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -103,7 +103,7 @@
static inline int cpu_is_msm7x27(void)
{
-#ifdef CONFIG_ARCH_MSM7X27
+#if defined(CONFIG_ARCH_MSM7X27) && !defined(CONFIG_ARCH_MSM7X27A)
enum msm_cpu cpu = socinfo_get_msm_cpu();
BUG_ON(cpu == MSM_CPU_UNKNOWN);
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 830db1f..8e74238 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -43,7 +43,7 @@
*/
unsigned int msm_shared_ram_phys = 0x00100000;
-static void msm_map_io(struct map_desc *io_desc, int size)
+static void __init msm_map_io(struct map_desc *io_desc, int size)
{
int i;
@@ -292,7 +292,13 @@
static struct map_desc msm_copper_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, COPPER),
MSM_CHIP_DEVICE(QGIC_CPU, COPPER),
+ MSM_CHIP_DEVICE(APCS_GCC, COPPER),
MSM_CHIP_DEVICE(TLMM, COPPER),
+ {
+ .virtual = (unsigned long) MSM_SHARED_RAM_BASE,
+ .length = MSM_SHARED_RAM_SIZE,
+ .type = MT_DEVICE,
+ },
#ifdef CONFIG_DEBUG_MSMCOPPER_UART
MSM_DEVICE(DEBUG_UART),
#endif
@@ -300,6 +306,7 @@
void __init msm_map_copper_io(void)
{
+ msm_shared_ram_phys = COPPER_MSM_SHARED_RAM_PHYS;
msm_map_io(msm_copper_io_desc, ARRAY_SIZE(msm_copper_io_desc));
}
#endif /* CONFIG_ARCH_MSMCOPPER */
@@ -410,8 +417,8 @@
MSM_CHIP_DEVICE(SCU, MSM8625),
MSM_CHIP_DEVICE(CFG_CTL, MSM8625),
MSM_CHIP_DEVICE(CLK_CTL, MSM8625),
- MSM_CHIP_DEVICE(SPM0, MSM8625),
- MSM_CHIP_DEVICE(SPM1, MSM8625),
+ MSM_CHIP_DEVICE(SAW0, MSM8625),
+ MSM_CHIP_DEVICE(SAW1, MSM8625),
#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
defined(CONFIG_DEBUG_MSM_UART3)
MSM_CHIP_DEVICE(DEBUG_UART, MSM7XXX),
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index c856455..727b729 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -103,11 +103,11 @@
case MSM_SUBSYSTEM_VIDEO_FWARE:
return VIDEO_FIRMWARE_POOL;
case MSM_SUBSYSTEM_VIDEO:
- return LOW_256MB_POOL;
+ return VIDEO_MAIN_POOL;
case MSM_SUBSYSTEM_CAMERA:
case MSM_SUBSYSTEM_DISPLAY:
case MSM_SUBSYSTEM_ROTATOR:
- return HIGH_POOL;
+ return GEN_POOL;
default:
return 0xFFFFFFFF;
}
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index f720fa9..a2ec89b 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.c
@@ -22,8 +22,10 @@
#include "qdss.h"
#include "cp14.h"
+ /* no of dbg regs + 1 (for storing the reg count) */
#define MAX_DBG_REGS (90)
#define MAX_DBG_STATE_SIZE (MAX_DBG_REGS * num_possible_cpus())
+ /* no of etm regs + 1 (for storing the reg count) */
#define MAX_ETM_REGS (78)
#define MAX_ETM_STATE_SIZE (MAX_ETM_REGS * num_possible_cpus())
@@ -31,6 +33,9 @@
#define CPMR_ETMCLKEN (0x8)
+uint32_t msm_jtag_save_cntr[NR_CPUS];
+uint32_t msm_jtag_restore_cntr[NR_CPUS];
+
struct dbg_ctx {
uint8_t arch;
bool arch_supported;
@@ -70,7 +75,7 @@
break;
case 3:
state[i++] = dbg_read(DBGBVR3);
- state[i++] = dbg_read(DBGBVR3);
+ state[i++] = dbg_read(DBGBCR3);
break;
case 4:
state[i++] = dbg_read(DBGBVR4);
@@ -78,7 +83,7 @@
break;
case 5:
state[i++] = dbg_read(DBGBVR5);
- state[i++] = dbg_read(DBGBVR5);
+ state[i++] = dbg_read(DBGBCR5);
break;
case 6:
state[i++] = dbg_read(DBGBVR6);
@@ -143,7 +148,7 @@
break;
case 3:
dbg_write(state[i++], DBGBVR3);
- dbg_write(state[i++], DBGBVR3);
+ dbg_write(state[i++], DBGBCR3);
break;
case 4:
dbg_write(state[i++], DBGBVR4);
@@ -151,7 +156,7 @@
break;
case 5:
dbg_write(state[i++], DBGBVR5);
- dbg_write(state[i++], DBGBVR5);
+ dbg_write(state[i++], DBGBCR5);
break;
case 6:
dbg_write(state[i++], DBGBVR6);
@@ -937,9 +942,9 @@
etm_write(etm.state[i++], ETMSQ12EVR);
etm_write(etm.state[i++], ETMSQ21EVR);
etm_write(etm.state[i++], ETMSQ23EVR);
+ etm_write(etm.state[i++], ETMSQ31EVR);
etm_write(etm.state[i++], ETMSQ32EVR);
etm_write(etm.state[i++], ETMSQ13EVR);
- etm_write(etm.state[i++], ETMSQ31EVR);
etm_write(etm.state[i++], ETMSQR);
for (j = 0; j < etm.nr_ext_out; j++)
i = etm_write_extoutevr(etm.state, i, j);
@@ -1013,6 +1018,10 @@
cpu = raw_smp_processor_id();
+ msm_jtag_save_cntr[cpu]++;
+ /* ensure counter is updated before moving forward */
+ mb();
+
if (dbg.arch_supported)
dbg_save_state(cpu);
if (etm.arch_supported)
@@ -1025,6 +1034,10 @@
cpu = raw_smp_processor_id();
+ msm_jtag_restore_cntr[cpu]++;
+ /* ensure counter is updated before moving forward */
+ mb();
+
if (dbg.arch_supported)
dbg_restore_state(cpu);
if (etm.arch_supported)
@@ -1046,9 +1059,9 @@
pr_info("dbg arch %u not supported\n", dbg.arch);
goto dbg_out;
}
- dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23);
- dbg.nr_bp = BMVAL(dbgdidr, 24, 27);
- dbg.nr_wp = BMVAL(dbgdidr, 28, 31);
+ dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23) + 1;
+ dbg.nr_bp = BMVAL(dbgdidr, 24, 27) + 1;
+ dbg.nr_wp = BMVAL(dbgdidr, 28, 31) + 1;
/* Allocate dbg state save space */
dbg.state = kzalloc(MAX_DBG_STATE_SIZE * sizeof(uint32_t), GFP_KERNEL);
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 5db8b40..7e538b4 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -48,7 +48,7 @@
static int mdm_debug_on;
static int first_power_on = 1;
-static int hsic_peripheral_status = 1;
+static int hsic_peripheral_status;
static DEFINE_MUTEX(hsic_status_lock);
static void mdm_peripheral_connect(struct mdm_modem_drv *mdm_drv)
@@ -82,7 +82,7 @@
/* Pull RESET gpio low and wait for it to settle. */
pr_debug("Pulling RESET gpio low\n");
gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
- usleep(1000);
+ usleep_range(5000, 10000);
/* Deassert RESET first and wait for ir to settle. */
pr_debug("%s: Pulling RESET gpio high\n", __func__);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 3b064ff..d26d76b 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/memory.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -226,6 +226,25 @@
return unstable_limit - mb->start;
}
+/* stable size of all memory banks contiguous to and below this one */
+static unsigned long total_stable_size(unsigned long bank)
+{
+ int i;
+ struct membank *mb = &meminfo.bank[bank];
+ int memtype = reserve_info->paddr_to_memtype(mb->start);
+ unsigned long size;
+
+ size = stable_size(mb, reserve_info->low_unstable_address);
+ for (i = bank - 1, mb = &meminfo.bank[bank - 1]; i >= 0; i--, mb--) {
+ if (mb->start + mb->size != (mb + 1)->start)
+ break;
+ if (reserve_info->paddr_to_memtype(mb->start) != memtype)
+ break;
+ size += stable_size(mb, reserve_info->low_unstable_address);
+ }
+ return size;
+}
+
static void __init calculate_reserve_limits(void)
{
int i;
@@ -242,7 +261,7 @@
continue;
}
mt = &reserve_info->memtype_reserve_table[memtype];
- size = stable_size(mb, reserve_info->low_unstable_address);
+ size = total_stable_size(i);
mt->limit = max(mt->limit, size);
}
}
@@ -277,10 +296,11 @@
if (mt->flags & MEMTYPE_FLAGS_FIXED || !mt->size)
continue;
- /* We know we will find a memory bank of the proper size
+ /* We know we will find memory bank(s) of the proper size
* as we have limited the size of the memory pool for
- * each memory type to the size of the largest memory
- * bank. Choose the memory bank with the highest physical
+ * each memory type to the largest total size of the memory
+ * banks which are contiguous and of the correct memory type.
+ * Choose the memory bank with the highest physical
* address which is large enough, so that we will not
* take memory from the lowest memory bank which the kernel
* is in (and cause boot problems) and so that we might
@@ -293,9 +313,14 @@
reserve_info->paddr_to_memtype(mb->start);
if (memtype != membank_type)
continue;
- size = stable_size(mb,
- reserve_info->low_unstable_address);
+ size = total_stable_size(i);
if (size >= mt->size) {
+ size = stable_size(mb,
+ reserve_info->low_unstable_address);
+ /* mt->size may be larger than size, all this
+ * means is that we are carving the memory pool
+ * out of multiple contiguous memory banks.
+ */
mt->start = mb->start + (size - mt->size);
ret = memblock_remove(mt->start, mt->size);
BUG_ON(ret);
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index 018e2a6..061998c 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -6,4 +6,5 @@
obj-$(CONFIG_ARCH_MSM8960) += msm_bus_board_8960.o
obj-$(CONFIG_ARCH_MSM9615) += msm_bus_board_9615.o
obj-$(CONFIG_ARCH_APQ8064) += msm_bus_board_8064.o
+obj-$(CONFIG_ARCH_MSM8930) += msm_bus_board_8930.o
obj-$(CONFIG_DEBUG_FS) += msm_bus_dbg.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
new file mode 100644
index 0000000..36fe156
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
@@ -0,0 +1,878 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/rpm.h>
+#include "msm_bus_core.h"
+
+#define NMASTERS 45
+#define NSLAVES 75
+#define NFAB_8930 5
+
+enum msm_bus_fabric_tiered_slave_type {
+ MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS_0 = 1,
+ MSM_BUS_TIERED_SLAVE_SYSTEM_IMEM,
+
+ MSM_BUS_TIERED_SLAVE_MM_IMEM = 1,
+ MSM_BUS_MMSS_TIERED_SLAVE_FAB_APPS_0,
+
+ MSM_BUS_TIERED_SLAVE_EBI1_CH0 = 1,
+ MSM_BUS_TIERED_SLAVE_KMPSS_L2,
+};
+
+enum msm_bus_8930_master_ports_type {
+ MSM_BUS_SYSTEM_MASTER_PORT_APPSS_FAB = 0,
+ MSM_BUS_MASTER_PORT_SPS,
+ MSM_BUS_MASTER_PORT_ADM_PORT0,
+ MSM_BUS_MASTER_PORT_ADM_PORT1,
+ MSM_BUS_MASTER_PORT_LPASS_PROC,
+ MSM_BUS_MASTER_PORT_MSS,
+ MSM_BUS_MASTER_PORT_RIVA,
+ MSM_BUS_MASTER_PORT_MSS_SW_PROC,
+ MSM_BUS_MASTER_PORT_MSS_FW_PROC,
+ MSM_BUS_MASTER_PORT_LPASS,
+ MSM_BUS_SYSTEM_MASTER_PORT_CPSS_FPB,
+ MSM_BUS_SYSTEM_MASTER_PORT_SYSTEM_FPB,
+ MSM_BUS_SYSTEM_MASTER_PORT_MMSS_FPB,
+ MSM_BUS_SYSTEM_MASTER_PORT_ADM_AHB_CI,
+
+ MSM_BUS_MASTER_PORT_MDP_PORT0 = 0,
+ MSM_BUS_MASTER_PORT_MDP_PORT1,
+ MSM_BUS_MASTER_PORT_GRAPHICS_3D,
+ MSM_BUS_MASTER_PORT_ROTATOR,
+ MSM_BUS_MASTER_PORT_VFE,
+ MSM_BUS_MASTER_PORT_VPE,
+ MSM_BUS_MASTER_PORT_JPEG_ENC,
+ MSM_BUS_MMSS_MASTER_PORT_APPS_FAB,
+ MSM_BUS_MASTER_PORT_HD_CODEC_PORT0,
+ MSM_BUS_MASTER_PORT_HD_CODEC_PORT1,
+
+ MSM_BUS_MASTER_PORT_KMPSS_M0 = 0,
+ MSM_BUS_MASTER_PORT_KMPSS_M1,
+ MSM_BUS_APPSS_MASTER_PORT_FAB_MMSS_0,
+ MSM_BUS_APPSS_MASTER_PORT_FAB_SYSTEM_0,
+};
+
+enum msm_bus_8930_slave_ports_type {
+ MSM_BUS_SLAVE_PORT_MM_IMEM = 0,
+ MSM_BUS_MMSS_SLAVE_PORT_APPS_FAB_0,
+
+ MSM_BUS_SLAVE_PORT_EBI1_CH0 = 0,
+ MSM_BUS_SLAVE_PORT_KMPSS_L2,
+ MSM_BUS_APPSS_SLAVE_PORT_MMSS_FAB,
+ MSM_BUS_SLAVE_PORT_SYSTEM_FAB,
+
+ MSM_BUS_SYSTEM_SLAVE_PORT_APPSS_FAB_0 = 0,
+ MSM_BUS_SLAVE_PORT_SPS,
+ MSM_BUS_SLAVE_PORT_SYSTEM_IMEM,
+ MSM_BUS_SLAVE_PORT_CORESIGHT,
+ MSM_BUS_SLAVE_PORT_KMPSS,
+ MSM_BUS_SLAVE_PORT_MSS,
+ MSM_BUS_SLAVE_PORT_LPASS,
+ MSM_BUS_SYSTEM_SLAVE_PORT_CPSS_FPB,
+ MSM_BUS_SYSTEM_SLAVE_PORT_SYSTEM_FPB,
+ MSM_BUS_SYSTEM_SLAVE_PORT_MMSS_FPB,
+ MSM_BUS_SLAVE_PORT_RIVA,
+};
+
+static int tier2[] = {MSM_BUS_BW_TIER2,};
+static uint32_t master_iids[NMASTERS];
+static uint32_t slave_iids[NSLAVES];
+
+static int mport_kmpss_m0[] = {MSM_BUS_MASTER_PORT_KMPSS_M0,};
+static int mport_kmpss_m1[] = {MSM_BUS_MASTER_PORT_KMPSS_M1,};
+
+static int mmss_mport_apps_fab[] = {MSM_BUS_MMSS_MASTER_PORT_APPS_FAB,};
+static int system_mport_appss_fab[] = {MSM_BUS_SYSTEM_MASTER_PORT_APPSS_FAB,};
+static int sport_ebi1_ch0[] = {
+ MSM_BUS_SLAVE_PORT_EBI1_CH0,
+};
+static int sport_kmpss_l2[] = {MSM_BUS_SLAVE_PORT_KMPSS_L2,};
+static int appss_sport_mmss_fab[] = {MSM_BUS_APPSS_SLAVE_PORT_MMSS_FAB,};
+static int sport_system_fab[] = {MSM_BUS_SLAVE_PORT_SYSTEM_FAB,};
+
+static int tiered_slave_ebi1_ch0[] = {
+ MSM_BUS_TIERED_SLAVE_EBI1_CH0,
+};
+
+static int tiered_slave_kmpss[] = {MSM_BUS_TIERED_SLAVE_KMPSS_L2,};
+
+static struct msm_bus_node_info apps_fabric_info[] = {
+ {
+ .id = MSM_BUS_MASTER_AMPSS_M0,
+ .masterp = mport_kmpss_m0,
+ .num_mports = ARRAY_SIZE(mport_kmpss_m0),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_AMPSS_M1,
+ .masterp = mport_kmpss_m1,
+ .num_mports = ARRAY_SIZE(mport_kmpss_m1),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_SLAVE_EBI_CH0,
+ .slavep = sport_ebi1_ch0,
+ .num_sports = ARRAY_SIZE(sport_ebi1_ch0),
+ .tier = tiered_slave_ebi1_ch0,
+ .num_tiers = ARRAY_SIZE(tiered_slave_ebi1_ch0),
+ .buswidth = 8,
+ .slaveclk[DUAL_CTX] = "mem_clk",
+ .slaveclk[ACTIVE_CTX] = "mem_a_clk",
+ },
+ {
+ .id = MSM_BUS_SLAVE_AMPSS_L2,
+ .slavep = sport_kmpss_l2,
+ .num_sports = ARRAY_SIZE(sport_kmpss_l2),
+ .tier = tiered_slave_kmpss,
+ .num_tiers = ARRAY_SIZE(tiered_slave_kmpss),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_FAB_MMSS,
+ .gateway = 1,
+ .slavep = appss_sport_mmss_fab,
+ .num_sports = ARRAY_SIZE(appss_sport_mmss_fab),
+ .masterp = mmss_mport_apps_fab,
+ .num_mports = ARRAY_SIZE(mmss_mport_apps_fab),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_FAB_SYSTEM,
+ .gateway = 1,
+ .slavep = sport_system_fab,
+ .num_sports = ARRAY_SIZE(sport_system_fab),
+ .masterp = system_mport_appss_fab,
+ .num_mports = ARRAY_SIZE(system_mport_appss_fab),
+ .buswidth = 8,
+ },
+};
+
+static int mport_sps[] = {MSM_BUS_MASTER_PORT_SPS,};
+static int mport_adm_port0[] = {MSM_BUS_MASTER_PORT_ADM_PORT0,};
+static int mport_adm_port1[] = {MSM_BUS_MASTER_PORT_ADM_PORT1,};
+static int mport_mss[] = {MSM_BUS_MASTER_PORT_MSS,};
+static int mport_lpass_proc[] = {MSM_BUS_MASTER_PORT_LPASS_PROC,};
+static int mport_riva[] = {MSM_BUS_MASTER_PORT_RIVA,};
+static int mport_mss_sw_proc[] = {MSM_BUS_MASTER_PORT_MSS_SW_PROC,};
+static int mport_mss_fw_proc[] = {MSM_BUS_MASTER_PORT_MSS_FW_PROC,};
+static int mport_lpass[] = {MSM_BUS_MASTER_PORT_LPASS,};
+static int system_mport_mmss_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_MMSS_FPB,};
+static int system_mport_adm_ahb_ci[] = {MSM_BUS_SYSTEM_MASTER_PORT_ADM_AHB_CI,};
+static int appss_mport_fab_system[] = {
+ MSM_BUS_APPSS_MASTER_PORT_FAB_SYSTEM_0,
+};
+static int mport_system_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_SYSTEM_FPB,};
+static int system_mport_cpss_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_CPSS_FPB,};
+
+static int system_sport_appss_fab[] = {
+ MSM_BUS_SYSTEM_SLAVE_PORT_APPSS_FAB_0,
+};
+static int system_sport_system_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_SYSTEM_FPB,};
+static int system_sport_cpss_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_CPSS_FPB,};
+static int sport_sps[] = {MSM_BUS_SLAVE_PORT_SPS,};
+static int sport_system_imem[] = {MSM_BUS_SLAVE_PORT_SYSTEM_IMEM,};
+static int sport_coresight[] = {MSM_BUS_SLAVE_PORT_CORESIGHT,};
+static int sport_riva[] = {MSM_BUS_SLAVE_PORT_RIVA,};
+static int sport_kmpss[] = {MSM_BUS_SLAVE_PORT_KMPSS,};
+static int sport_mss[] = {MSM_BUS_SLAVE_PORT_MSS,};
+static int sport_lpass[] = {MSM_BUS_SLAVE_PORT_LPASS,};
+static int sport_mmss_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_MMSS_FPB,};
+
+static int tiered_slave_system_imem[] = {MSM_BUS_TIERED_SLAVE_SYSTEM_IMEM,};
+static int system_tiered_slave_fab_appss[] = {
+ MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS_0,
+};
+
+static struct msm_bus_node_info system_fabric_info[] = {
+ {
+ .id = MSM_BUS_MASTER_SPS,
+ .masterp = mport_sps,
+ .num_mports = ARRAY_SIZE(mport_sps),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_ADM_PORT0,
+ .masterp = mport_adm_port0,
+ .num_mports = ARRAY_SIZE(mport_adm_port0),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_ADM_PORT1,
+ .masterp = mport_adm_port1,
+ .num_mports = ARRAY_SIZE(mport_adm_port1),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_LPASS_PROC,
+ .masterp = mport_lpass_proc,
+ .num_mports = ARRAY_SIZE(mport_lpass_proc),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_MSS,
+ .masterp = mport_mss,
+ .num_mports = ARRAY_SIZE(mport_mss),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_RIVA,
+ .masterp = mport_riva,
+ .num_mports = ARRAY_SIZE(mport_riva),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_MSS_SW_PROC,
+ .masterp = mport_mss_sw_proc,
+ .num_mports = ARRAY_SIZE(mport_mss_sw_proc),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_MSS_FW_PROC,
+ .masterp = mport_mss_fw_proc,
+ .num_mports = ARRAY_SIZE(mport_mss_fw_proc),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_LPASS,
+ .masterp = mport_lpass,
+ .num_mports = ARRAY_SIZE(mport_lpass),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_SYSTEM_MASTER_MMSS_FPB,
+ .masterp = system_mport_mmss_fpb,
+ .num_mports = ARRAY_SIZE(system_mport_mmss_fpb),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_ADM0_CI,
+ .masterp = system_mport_adm_ahb_ci,
+ .num_mports = ARRAY_SIZE(system_mport_adm_ahb_ci),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_FAB_APPSS,
+ .gateway = 1,
+ .slavep = system_sport_appss_fab,
+ .num_sports = ARRAY_SIZE(system_sport_appss_fab),
+ .masterp = appss_mport_fab_system,
+ .num_mports = ARRAY_SIZE(appss_mport_fab_system),
+ .tier = system_tiered_slave_fab_appss,
+ .num_tiers = ARRAY_SIZE(system_tiered_slave_fab_appss),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_FAB_SYSTEM_FPB,
+ .gateway = 1,
+ .slavep = system_sport_system_fpb,
+ .num_sports = ARRAY_SIZE(system_sport_system_fpb),
+ .masterp = mport_system_fpb,
+ .num_mports = ARRAY_SIZE(mport_system_fpb),
+ .buswidth = 4,
+ },
+ {
+ .id = MSM_BUS_FAB_CPSS_FPB,
+ .gateway = 1,
+ .slavep = system_sport_cpss_fpb,
+ .num_sports = ARRAY_SIZE(system_sport_cpss_fpb),
+ .masterp = system_mport_cpss_fpb,
+ .num_mports = ARRAY_SIZE(system_mport_cpss_fpb),
+ .buswidth = 4,
+ },
+ {
+ .id = MSM_BUS_SLAVE_SPS,
+ .slavep = sport_sps,
+ .num_sports = ARRAY_SIZE(sport_sps),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_SLAVE_SYSTEM_IMEM,
+ .slavep = sport_system_imem,
+ .num_sports = ARRAY_SIZE(sport_system_imem),
+ .tier = tiered_slave_system_imem,
+ .num_tiers = ARRAY_SIZE(tiered_slave_system_imem),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_SLAVE_CORESIGHT,
+ .slavep = sport_coresight,
+ .num_sports = ARRAY_SIZE(sport_coresight),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_SLAVE_RIVA,
+ .slavep = sport_riva,
+ .num_sports = ARRAY_SIZE(sport_riva),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_SLAVE_AMPSS,
+ .slavep = sport_kmpss,
+ .num_sports = ARRAY_SIZE(sport_kmpss),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_SLAVE_MSS,
+ .slavep = sport_mss,
+ .num_sports = ARRAY_SIZE(sport_mss),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_SLAVE_LPASS,
+ .slavep = sport_lpass,
+ .num_sports = ARRAY_SIZE(sport_lpass),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ .buswidth = 8,
+ },
+ {
+ .id = MSM_BUS_SYSTEM_SLAVE_MMSS_FPB,
+ .slavep = sport_mmss_fpb,
+ .num_sports = ARRAY_SIZE(sport_mmss_fpb),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ .buswidth = 8,
+ },
+};
+
+static int mport_mdp[] = {
+ MSM_BUS_MASTER_PORT_MDP_PORT0,
+ MSM_BUS_MASTER_PORT_MDP_PORT1,
+};
+static int mport_mdp1[] = {MSM_BUS_MASTER_PORT_MDP_PORT1,};
+static int mport_rotator[] = {MSM_BUS_MASTER_PORT_ROTATOR,};
+static int mport_graphics_3d[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D,};
+static int mport_vfe[] = {MSM_BUS_MASTER_PORT_VFE,};
+static int mport_vpe[] = {MSM_BUS_MASTER_PORT_VPE,};
+static int mport_jpeg_enc[] = {MSM_BUS_MASTER_PORT_JPEG_ENC,};
+static int mport_hd_codec_port0[] = {MSM_BUS_MASTER_PORT_HD_CODEC_PORT0,};
+static int mport_hd_codec_port1[] = {MSM_BUS_MASTER_PORT_HD_CODEC_PORT1,};
+static int appss_mport_fab_mmss[] = {
+ MSM_BUS_APPSS_MASTER_PORT_FAB_MMSS_0,
+};
+
+static int mmss_sport_apps_fab[] = {
+ MSM_BUS_MMSS_SLAVE_PORT_APPS_FAB_0,
+};
+static int sport_mm_imem[] = {MSM_BUS_SLAVE_PORT_MM_IMEM,};
+
+static int mmss_tiered_slave_fab_apps[] = {
+ MSM_BUS_MMSS_TIERED_SLAVE_FAB_APPS_0,
+};
+static int tiered_slave_mm_imem[] = {MSM_BUS_TIERED_SLAVE_MM_IMEM,};
+
+
+static struct msm_bus_node_info mmss_fabric_info[] = {
+ {
+ .id = MSM_BUS_MASTER_MDP_PORT0,
+ .masterp = mport_mdp,
+ .num_mports = ARRAY_SIZE(mport_mdp),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_MDP_PORT1,
+ .masterp = mport_mdp1,
+ .num_mports = ARRAY_SIZE(mport_mdp1),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_ROTATOR,
+ .masterp = mport_rotator,
+ .num_mports = ARRAY_SIZE(mport_rotator),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_GRAPHICS_3D,
+ .masterp = mport_graphics_3d,
+ .num_mports = ARRAY_SIZE(mport_graphics_3d),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_VFE,
+ .masterp = mport_vfe,
+ .num_mports = ARRAY_SIZE(mport_vfe),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_VPE,
+ .masterp = mport_vpe,
+ .num_mports = ARRAY_SIZE(mport_vpe),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_JPEG_ENC,
+ .masterp = mport_jpeg_enc,
+ .num_mports = ARRAY_SIZE(mport_jpeg_enc),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_HD_CODEC_PORT0,
+ .masterp = mport_hd_codec_port0,
+ .num_mports = ARRAY_SIZE(mport_hd_codec_port0),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_HD_CODEC_PORT1,
+ .masterp = mport_hd_codec_port1,
+ .num_mports = ARRAY_SIZE(mport_hd_codec_port1),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_FAB_APPSS,
+ .gateway = 1,
+ .slavep = mmss_sport_apps_fab,
+ .num_sports = ARRAY_SIZE(mmss_sport_apps_fab),
+ .masterp = appss_mport_fab_mmss,
+ .num_mports = ARRAY_SIZE(appss_mport_fab_mmss),
+ .tier = mmss_tiered_slave_fab_apps,
+ .num_tiers = ARRAY_SIZE(mmss_tiered_slave_fab_apps),
+ .buswidth = 16,
+ },
+ {
+ .id = MSM_BUS_SLAVE_MM_IMEM,
+ .slavep = sport_mm_imem,
+ .num_sports = ARRAY_SIZE(sport_mm_imem),
+ .tier = tiered_slave_mm_imem,
+ .num_tiers = ARRAY_SIZE(tiered_slave_mm_imem),
+ .buswidth = 8,
+ },
+};
+
+static struct msm_bus_node_info sys_fpb_fabric_info[] = {
+ {
+ .id = MSM_BUS_FAB_SYSTEM,
+ .gateway = 1,
+ .slavep = system_sport_system_fpb,
+ .num_sports = ARRAY_SIZE(system_sport_system_fpb),
+ .masterp = mport_system_fpb,
+ .num_mports = ARRAY_SIZE(mport_system_fpb),
+ .buswidth = 4,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_MASTER_SPDM,
+ .ahb = 1,
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_MASTER_RPM,
+ .ahb = 1,
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
+ .id = MSM_BUS_SLAVE_SPDM,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_RPM,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_RPM_MSG_RAM,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_MPM,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_PMIC1_SSBI1_A,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_PMIC1_SSBI1_B,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_PMIC1_SSBI1_C,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_PMIC2_SSBI2_A,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_PMIC2_SSBI2_B,
+ .buswidth = 4,
+ .ahb = 1,
+ },
+};
+
+static struct msm_bus_node_info cpss_fpb_fabric_info[] = {
+ {
+ .id = MSM_BUS_FAB_SYSTEM,
+ .gateway = 1,
+ .slavep = system_sport_cpss_fpb,
+ .num_sports = ARRAY_SIZE(system_sport_cpss_fpb),
+ .masterp = system_mport_cpss_fpb,
+ .num_mports = ARRAY_SIZE(system_mport_cpss_fpb),
+ .buswidth = 4,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI1_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI2_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI3_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI4_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI5_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI6_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI7_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI8_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI9_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI10_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI11_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI12_UART,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI1_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI2_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI3_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI4_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI5_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI6_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI7_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI8_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI9_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI10_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI11_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_GSBI12_QUP,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_EBI2_NAND,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_EBI2_CS0,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_EBI2_CS1,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_EBI2_CS2,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_EBI2_CS3,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_EBI2_CS4,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_EBI2_CS5,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_USB_FS1,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_USB_FS2,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_TSIF,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_MSM_TSSC,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_MSM_PDM,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_MSM_DIMEM,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_MSM_TCSR,
+ .buswidth = 8,
+ .ahb = 1,
+ },
+ {
+ .id = MSM_BUS_SLAVE_MSM_PRNG,
+ .buswidth = 4,
+ .ahb = 1,
+ },
+};
+
+static void msm_bus_board_assign_iids(struct msm_bus_fabric_registration
+ *fabreg, int fabid)
+{
+ int i;
+ for (i = 0; i < fabreg->len; i++) {
+ if (!fabreg->info[i].gateway) {
+ fabreg->info[i].priv_id = fabid + fabreg->info[i].id;
+ if (fabreg->info[i].id < SLAVE_ID_KEY)
+ master_iids[fabreg->info[i].id] =
+ fabreg->info[i].priv_id;
+ else
+ slave_iids[fabreg->info[i].id - (SLAVE_ID_KEY)]
+ = fabreg->info[i].priv_id;
+ } else
+ fabreg->info[i].priv_id = fabreg->info[i].id;
+ }
+}
+
+static int msm_bus_board_8930_get_iid(int id)
+{
+ if ((id < SLAVE_ID_KEY && id >= NMASTERS) ||
+ id >= (SLAVE_ID_KEY + NSLAVES)) {
+ MSM_BUS_ERR("Cannot get iid. Invalid id %d passed\n", id);
+ return -EINVAL;
+ }
+
+ return CHECK_ID(((id < SLAVE_ID_KEY) ? master_iids[id] :
+ slave_iids[id - SLAVE_ID_KEY]), id);
+}
+
+static struct msm_bus_board_algorithm msm_bus_board_algo = {
+ .board_nfab = NFAB_8930,
+ .get_iid = msm_bus_board_8930_get_iid,
+ .assign_iids = msm_bus_board_assign_iids,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_apps_fabric_pdata = {
+ .id = MSM_BUS_FAB_APPSS,
+ .name = "msm_apps_fab",
+ .info = apps_fabric_info,
+ .len = ARRAY_SIZE(apps_fabric_info),
+ .ahb = 0,
+ .fabclk[DUAL_CTX] = "bus_clk",
+ .fabclk[ACTIVE_CTX] = "bus_a_clk",
+ .haltid = MSM_RPM_ID_APPS_FABRIC_CFG_HALT_0,
+ .offset = MSM_RPM_ID_APPS_FABRIC_ARB_0,
+ .nmasters = 4,
+ .nslaves = 4,
+ .ntieredslaves = 2,
+ .board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_sys_fabric_pdata = {
+ .id = MSM_BUS_FAB_SYSTEM,
+ .name = "msm_sys_fab",
+ system_fabric_info,
+ ARRAY_SIZE(system_fabric_info),
+ .ahb = 0,
+ .fabclk[DUAL_CTX] = "bus_clk",
+ .fabclk[ACTIVE_CTX] = "bus_a_clk",
+ .haltid = MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0,
+ .offset = MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
+ .nmasters = 14,
+ .nslaves = 11,
+ .ntieredslaves = 2,
+ .board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_mm_fabric_pdata = {
+ .id = MSM_BUS_FAB_MMSS,
+ .name = "msm_mm_fab",
+ mmss_fabric_info,
+ ARRAY_SIZE(mmss_fabric_info),
+ .ahb = 0,
+ .fabclk[DUAL_CTX] = "bus_clk",
+ .fabclk[ACTIVE_CTX] = "bus_a_clk",
+ .haltid = MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
+ .offset = MSM_RPM_ID_MM_FABRIC_ARB_0,
+ .nmasters = 10,
+ .nslaves = 2,
+ .ntieredslaves = 2,
+ .board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_sys_fpb_pdata = {
+ .id = MSM_BUS_FAB_SYSTEM_FPB,
+ .name = "msm_sys_fpb",
+ sys_fpb_fabric_info,
+ ARRAY_SIZE(sys_fpb_fabric_info),
+ .ahb = 1,
+ .fabclk[DUAL_CTX] = "bus_clk",
+ .fabclk[ACTIVE_CTX] = "bus_a_clk",
+ .nmasters = 0,
+ .nslaves = 0,
+ .ntieredslaves = 0,
+ .board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_cpss_fpb_pdata = {
+ .id = MSM_BUS_FAB_CPSS_FPB,
+ .name = "msm_cpss_fpb",
+ cpss_fpb_fabric_info,
+ ARRAY_SIZE(cpss_fpb_fabric_info),
+ .ahb = 1,
+ .fabclk[DUAL_CTX] = "bus_clk",
+ .fabclk[ACTIVE_CTX] = "bus_a_clk",
+ .nmasters = 0,
+ .nslaves = 0,
+ .ntieredslaves = 0,
+ .board_algo = &msm_bus_board_algo,
+};
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index f93a79b..6e79dfe 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/memory_alloc.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -64,7 +65,6 @@
#endif
struct msm_rtb_state msm_rtb = {
- .size = SZ_1M,
.filter = 1 << LOGK_LOGBUF,
};
@@ -107,16 +107,6 @@
start->data = data;
}
-static int __init msm_rtb_set_buffer_size(char *p)
-{
- int s;
-
- s = memparse(p, NULL);
- msm_rtb.size = ALIGN(s, SZ_4K);
- return 0;
-}
-early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-
#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
static int msm_rtb_get_idx(void)
{
@@ -178,12 +168,15 @@
}
EXPORT_SYMBOL(uncached_logk);
-int msm_rtb_init(void)
+int msm_rtb_probe(struct platform_device *pdev)
{
+ struct msm_rtb_platform_data *d = pdev->dev.platform_data;
#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
unsigned int cpu;
#endif
+ msm_rtb.size = d->size;
+
if (msm_rtb.size <= 0 || msm_rtb.size > SZ_1M)
return -EINVAL;
@@ -227,4 +220,22 @@
msm_rtb.enabled = 1;
return 0;
}
+
+static struct platform_driver msm_rtb_driver = {
+ .driver = {
+ .name = "msm_rtb",
+ .owner = THIS_MODULE
+ },
+};
+
+static int __init msm_rtb_init(void)
+{
+ return platform_driver_probe(&msm_rtb_driver, msm_rtb_probe);
+}
+
+static void __exit msm_rtb_exit(void)
+{
+ platform_driver_unregister(&msm_rtb_driver);
+}
module_init(msm_rtb_init)
+module_exit(msm_rtb_exit)
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 6ec9b5d..26b97fa 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -25,6 +25,7 @@
#include <mach/msm_iomap.h>
#include <mach/msm_xo.h>
+#include <mach/socinfo.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
@@ -42,14 +43,8 @@
#define GSS_CLAMP_ENA (MSM_CLK_CTL_BASE + 0x2C68)
#define GSS_CXO_SRC_CTL (MSM_CLK_CTL_BASE + 0x2C74)
-#define PLL5_MODE (MSM_CLK_CTL_BASE + 0x30E0)
-#define PLL5_L_VAL (MSM_CLK_CTL_BASE + 0x30E4)
-#define PLL5_M_VAL (MSM_CLK_CTL_BASE + 0x30E8)
-#define PLL5_N_VAL (MSM_CLK_CTL_BASE + 0x30EC)
-#define PLL5_CONFIG (MSM_CLK_CTL_BASE + 0x30F4)
#define PLL5_STATUS (MSM_CLK_CTL_BASE + 0x30F8)
#define PLL_ENA_GSS (MSM_CLK_CTL_BASE + 0x3480)
-#define PLL_ENA_RPM (MSM_CLK_CTL_BASE + 0x34A0)
#define PLL5_VOTE BIT(5)
#define PLL_STATUS BIT(16)
@@ -142,13 +137,17 @@
writel_relaxed(A5_RESET, base + GSS_CSR_RESET);
}
-static void setup_qgic2_bus_access(void *data)
+static void cfg_qgic2_bus_access(void *data)
{
struct gss_data *drv = data;
- void __iomem *base = drv->base;
int i;
- writel_relaxed(0x2, base + GSS_CSR_CFG_HID);
+ /*
+ * Apply a 8064 v1.0 workaround to configure QGIC bus access.
+ * This must be done from Krait 0 to configure the Master ID
+ * correctly.
+ */
+ writel_relaxed(0x2, drv->base + GSS_CSR_CFG_HID);
for (i = 0; i <= 3; i++)
readl_relaxed(drv->qgic2_base);
}
@@ -233,15 +232,15 @@
while (!(readl_relaxed(base + GSS_CSR_POWER_UP_DOWN) & A5_POWER_STATUS))
cpu_relax();
- /*
- * Apply a 8064 v1.0 workaround to configure QGIC bus access. This must
- * be done from Krait 0 to configure the Master ID correctly.
- */
- ret = smp_call_function_single(0, setup_qgic2_bus_access, drv, 1);
- if (ret) {
- pr_err("Failed to configure QGIC2 bus access\n");
- pil_gss_shutdown(pil);
- return ret;
+ if (cpu_is_apq8064() &&
+ ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) &&
+ (SOCINFO_VERSION_MINOR(socinfo_get_version()) == 0))) {
+ ret = smp_call_function_single(0, cfg_qgic2_bus_access, drv, 1);
+ if (ret) {
+ pr_err("Failed to configure QGIC2 bus access\n");
+ pil_gss_shutdown(pil);
+ return ret;
+ }
}
/* Release A5 from reset. */
@@ -263,6 +262,28 @@
return pas_init_image(PAS_GSS, metadata, size);
}
+static int pil_gss_shutdown_trusted(struct pil_desc *pil)
+{
+ struct gss_data *drv = dev_get_drvdata(pil->dev);
+ int ret;
+
+ /*
+ * CXO is used in the secure shutdown code to configure the processor
+ * for low power mode.
+ */
+ ret = clk_prepare_enable(drv->xo);
+ if (ret) {
+ dev_err(pil->dev, "Failed to enable XO\n");
+ return ret;
+ }
+
+ ret = pas_shutdown(PAS_GSS);
+ clk_disable_unprepare(drv->xo);
+ remove_gss_proxy_votes_now(drv);
+
+ return ret;
+}
+
static int pil_gss_reset_trusted(struct pil_desc *pil)
{
struct gss_data *drv = dev_get_drvdata(pil->dev);
@@ -276,23 +297,26 @@
if (err)
remove_gss_proxy_votes_now(drv);
+ if (cpu_is_apq8064() &&
+ ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) &&
+ (SOCINFO_VERSION_MINOR(socinfo_get_version()) == 0))) {
+ err = smp_call_function_single(0, cfg_qgic2_bus_access, drv, 1);
+ if (err) {
+ pr_err("Failed to configure QGIC2 bus access\n");
+ pil_gss_shutdown_trusted(pil);
+ return err;
+ }
+ /*
+ * On 8064v1.0, pas_auth_and_reset() will not release the A5
+ * from reset. Linux must do this after cfg_qgic2_bus_access()
+ * is called on CPU0.
+ */
+ writel_relaxed(0x0, drv->base + GSS_CSR_RESET);
+ }
+
return err;
}
-static int pil_gss_shutdown_trusted(struct pil_desc *pil)
-{
- struct gss_data *drv = dev_get_drvdata(pil->dev);
- int ret;
-
- ret = pas_shutdown(PAS_GSS);
- if (ret)
- return ret;
-
- remove_gss_proxy_votes_now(drv);
-
- return ret;
-}
-
static struct pil_reset_ops pil_gss_ops_trusted = {
.init_image = pil_gss_init_image_trusted,
.verify_blob = nop_verify_blob,
@@ -300,63 +324,6 @@
.shutdown = pil_gss_shutdown_trusted,
};
-static void configure_gss_pll(struct gss_data *drv)
-{
- u32 regval, is_pll_enabled;
-
- /* Check if PLL5 is enabled by FSM. */
- is_pll_enabled = readl_relaxed(PLL5_STATUS) & PLL_STATUS;
- if (!is_pll_enabled) {
- /* Enable XO reference for PLL5 */
- clk_prepare_enable(drv->xo);
-
- /*
- * Assert a vote to hold PLL5 on in RPM register until other
- * voters are in place.
- */
- regval = readl_relaxed(PLL_ENA_RPM);
- regval |= PLL5_VOTE;
- writel_relaxed(regval, PLL_ENA_RPM);
-
- /* Ref clk = 27MHz and program pll5 to 288MHz */
- writel_relaxed(0xF, PLL5_L_VAL);
- writel_relaxed(0x0, PLL5_M_VAL);
- writel_relaxed(0x1, PLL5_N_VAL);
-
- regval = readl_relaxed(PLL5_CONFIG);
- /* Disable the MN accumulator and enable the main output. */
- regval &= ~BIT(22);
- regval |= BIT(23);
-
- /* Set pre-divider and post-divider values to 1 and 1 */
- regval &= ~BIT(19);
- regval &= ~(BIT(21)|BIT(20));
-
- /* Set VCO frequency */
- regval &= ~(BIT(17)|BIT(16));
- writel_relaxed(regval, PLL5_CONFIG);
-
- regval = readl_relaxed(PLL5_MODE);
- /* De-assert reset to FSM */
- regval &= ~BIT(21);
- writel_relaxed(regval, PLL5_MODE);
-
- /* Program bias count */
- regval &= ~(0x3F << 14);
- regval |= (0x1 << 14);
- writel_relaxed(regval, PLL5_MODE);
-
- /* Program lock count */
- regval &= ~(0x3F << 8);
- regval |= (0x8 << 8);
- writel_relaxed(regval, PLL5_MODE);
-
- /* Enable PLL FSM voting */
- regval |= BIT(20);
- writel_relaxed(regval, PLL5_MODE);
- }
-}
-
static int __devinit pil_gss_probe(struct platform_device *pdev)
{
struct gss_data *drv;
@@ -407,9 +374,6 @@
INIT_DELAYED_WORK(&drv->work, remove_gss_proxy_votes);
- /* FIXME: Remove when PLL is configured by bootloaders. */
- configure_gss_pll(drv);
-
ret = msm_pil_register(desc);
if (ret) {
flush_delayed_work_sync(&drv->work);
diff --git a/arch/arm/mach-msm/pil-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
index 511377d..b0bce02 100644
--- a/arch/arm/mach-msm/pil-q6v4.c
+++ b/arch/arm/mach-msm/pil-q6v4.c
@@ -29,11 +29,10 @@
#include "pil-q6v4.h"
#include "scm-pas.h"
-#define PROXY_VOTE_TIMEOUT 40000
+#define PROXY_VOTE_TIMEOUT 10000
#define QDSP6SS_RST_EVB 0x0
#define QDSP6SS_RESET 0x04
-#define QDSP6SS_CGC_OVERRIDE 0x18
#define QDSP6SS_STRAP_TCM 0x1C
#define QDSP6SS_STRAP_AHB 0x20
#define QDSP6SS_GFMUX_CTL 0x30
@@ -62,7 +61,6 @@
#define Q6SS_CLK_ENA BIT(1)
#define Q6SS_SRC_SWITCH_CLK_OVR BIT(8)
-#define Q6SS_AXIS_ACLK_EN BIT(9)
struct q6v4_data {
void __iomem *base;
@@ -220,15 +218,6 @@
if (err)
dev_err(pil->dev, "Failed to unhalt bus port\n");
- /*
- * Assert AXIS_ACLK_EN override to allow for correct updating of the
- * QDSP6_CORE_STATE status bit. This is mandatory only for the SW Q6
- * in 8960v1 and optional elsewhere.
- */
- reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
- reg |= Q6SS_AXIS_ACLK_EN;
- writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);
-
/* Deassert Q6SS_SS_ARES */
reg = readl_relaxed(drv->base + QDSP6SS_RESET);
reg &= ~(Q6SS_SS_ARES);
@@ -278,16 +267,6 @@
/* Bring Q6 core out of reset and start execution. */
writel_relaxed(0x0, drv->base + QDSP6SS_RESET);
- /*
- * Re-enable auto-gating of AXIS_ACLK at lease one AXI clock cycle
- * after resets are de-asserted.
- */
- mb();
- usleep_range(1, 10);
- reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
- reg &= ~Q6SS_AXIS_ACLK_EN;
- writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);
-
return 0;
}
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
new file mode 100644
index 0000000..534fc0e
--- /dev/null
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -0,0 +1,202 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/smp_scu.h>
+#include <asm/unified.h>
+#include <mach/msm_iomap.h>
+#include <mach/smp.h>
+#include "pm.h"
+
+#define MSM_CORE1_RESET 0xA8600590
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+int pen_release = -1;
+
+static bool cold_boot_done;
+
+static uint32_t *msm8625_boot_vector;
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not. This is necessary for the hotplug code to work reliably.
+ */
+static void __cpuinit write_pen_release(int val)
+{
+ pen_release = val;
+ smp_wmb();
+ __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+ outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static void __iomem *scu_base_addr(void)
+{
+ return MSM_SCU_BASE;
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+ /*
+ * if any interrupts are already enabled for the primary
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+ gic_secondary_init(0);
+
+ /*
+ * let the primary processor know we're out of the
+ * pen, then head off into the C entry point
+ */
+ write_pen_release(-1);
+
+ /*
+ * Synchronise with the boot thread.
+ */
+ spin_lock(&boot_lock);
+ spin_unlock(&boot_lock);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned long timeout;
+ void __iomem *base_ptr;
+
+ if (cold_boot_done == false) {
+ base_ptr = ioremap_nocache(MSM_CORE1_RESET, SZ_4);
+ if (!base_ptr)
+ return -ENODEV;
+ /* Reset core 1 out of reset */
+ __raw_writel(0x0, base_ptr);
+ mb();
+ cold_boot_done = true;
+ iounmap(base_ptr);
+ }
+
+ /*
+ * Set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ spin_lock(&boot_lock);
+
+ /*
+ * This is really belt and braces; we hold unintended secondary
+ * CPUs in the holding pen until we're ready for them. However,
+ * since we haven't sent them a soft interrupt, they shouldn't
+ * be there.
+ */
+ write_pen_release(cpu);
+
+ /*
+ * Send the secondary CPU a soft interrupt, thereby causing
+ * the boot monitor to read the system wide flags register,
+ * and branch to the address found there.
+ */
+ gic_raise_softirq(cpumask_of(cpu), 1);
+
+ timeout = jiffies + (1 * HZ);
+ while (time_before(jiffies, timeout)) {
+ smp_rmb();
+ if (pen_release == -1)
+ break;
+
+ udelay(10);
+ }
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ spin_unlock(&boot_lock);
+
+ return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+ void __iomem *scu_base = scu_base_addr();
+
+ unsigned int i, ncores;
+
+ ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+
+ set_smp_cross_call(gic_raise_softirq);
+}
+
+static void __init msm8625_boot_vector_init(uint32_t *boot_vector,
+ unsigned long entry)
+{
+ if (!boot_vector)
+ return;
+ msm8625_boot_vector = boot_vector;
+
+ msm8625_boot_vector[0] = 0xE51FF004; /* ldr pc, 4 */
+ msm8625_boot_vector[1] = entry;
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+ int i, value;
+ void __iomem *second_ptr;
+
+ /*
+ * Initialise the present map, which describes the set of CPUs
+ * actually populated at the present time.
+ */
+ for (i = 0; i < max_cpus; i++)
+ set_cpu_present(i, true);
+
+ scu_enable(scu_base_addr());
+
+ /*
+ * Write the address of secondary startup into the
+ * boot remapper register. The secondary CPU branches to this address.
+ */
+ __raw_writel(MSM8625_SECONDARY_PHYS, (MSM_CFG_CTL_BASE + 0x34));
+ mb();
+
+ second_ptr = ioremap_nocache(MSM8625_SECONDARY_PHYS, SZ_8);
+ if (!second_ptr) {
+ pr_err("failed to ioremap for secondary core\n");
+ return;
+ }
+
+ msm8625_boot_vector_init(second_ptr,
+ virt_to_phys(msm_secondary_startup));
+ iounmap(second_ptr);
+
+ /* Enable boot remapper address: bit 26 for core1 */
+ value = __raw_readl(MSM_CFG_CTL_BASE + 0x30);
+ __raw_writel(value | (0x4 << 24), MSM_CFG_CTL_BASE + 0x30) ;
+ mb();
+}
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index b3c6d1e..ad235de 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -655,6 +655,10 @@
void *entry;
bool collapsed = 0;
int ret;
+ unsigned int saved_gic_cpu_ctrl;
+
+ saved_gic_cpu_ctrl = readl_relaxed(MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+ mb();
if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
pr_info("CPU%u: %s: notify_rpm %d\n",
@@ -686,7 +690,9 @@
#endif
cpu_init();
writel(0xF0, MSM_QGIC_CPU_BASE + GIC_CPU_PRIMASK);
- writel(1, MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+ writel_relaxed(saved_gic_cpu_ctrl,
+ MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+ mb();
local_fiq_enable();
}
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index e1934bb..7977d22 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1668,6 +1668,13 @@
.valid = suspend_valid_only_mem,
};
+/* Hotplug the "non boot" CPU's and put
+ * the cores into low power mode
+ */
+void msm_pm_cpu_enter_lowpower(unsigned int cpu)
+{
+ return;
+}
/******************************************************************************
* Restart Definitions
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index 81d4e5b..1f82468 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,24 +14,28 @@
#include <asm/pmu.h>
#include <mach/irqs.h>
-static struct resource cpu_pmu_resource = {
- .start = INT_ARMQC_PERFMON,
- .end = INT_ARMQC_PERFMON,
- .flags = IORESOURCE_IRQ,
+static struct resource cpu_pmu_resource[] = {
+ {
+ .start = INT_ARMQC_PERFMON,
+ .end = INT_ARMQC_PERFMON,
+ .flags = IORESOURCE_IRQ,
+ },
};
#ifdef CONFIG_CPU_HAS_L2_PMU
-static struct resource l2_pmu_resource = {
- .start = SC_SICL2PERFMONIRPTREQ,
- .end = SC_SICL2PERFMONIRPTREQ,
- .flags = IORESOURCE_IRQ,
+static struct resource l2_pmu_resource[] = {
+ {
+ .start = SC_SICL2PERFMONIRPTREQ,
+ .end = SC_SICL2PERFMONIRPTREQ,
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct platform_device l2_pmu_device = {
.name = "l2-arm-pmu",
.id = ARM_PMU_DEVICE_L2,
- .resource = &l2_pmu_resource,
- .num_resources = 1,
+ .resource = l2_pmu_resource,
+ .num_resources = ARRAY_SIZE(l2_pmu_resource),
};
#endif
@@ -39,8 +43,8 @@
static struct platform_device cpu_pmu_device = {
.name = "cpu-arm-pmu",
.id = ARM_PMU_DEVICE_CPU,
- .resource = &cpu_pmu_resource,
- .num_resources = 1,
+ .resource = cpu_pmu_resource,
+ .num_resources = ARRAY_SIZE(cpu_pmu_resource),
};
static struct platform_device *pmu_devices[] = {
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index 33c5a53..1bf2a55 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -3,7 +3,7 @@
* Register/Interrupt access for userspace aDSP library.
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
* Author: Iliyan Malchev <ibm@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -280,6 +280,7 @@
int rc = 0;
static uint32_t init_info_cmd_sent;
+ mutex_lock(&adsp_info.lock);
if (!init_info_cmd_sent) {
init_waitqueue_head(&adsp_info.init_info_wait);
msm_get_init_info();
@@ -288,10 +289,13 @@
5 * HZ);
if (!rc) {
MM_ERR("INIT_INFO failed\n");
+ mutex_unlock(&adsp_info.lock);
return -ETIMEDOUT;
+
}
init_info_cmd_sent++;
}
+ mutex_unlock(&adsp_info.lock);
module = find_adsp_module_by_name(&adsp_info, name);
if (!module)
@@ -1016,16 +1020,49 @@
int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate)
{
+ if (!module)
+ return -EINVAL;
+
if (module->clk && clk_rate)
return clk_set_rate(module->clk, clk_rate);
return -EINVAL;
}
+int msm_adsp_generate_event(void *data,
+ struct msm_adsp_module *mod,
+ unsigned event_id,
+ unsigned event_length,
+ unsigned event_size,
+ void *msg)
+{
+ unsigned long flags;
+ void (*func)(void *, size_t);
+
+ if (!mod)
+ return -EINVAL;
+
+ if (event_size == sizeof(uint32_t))
+ func = read_event_32;
+ else if (event_size == sizeof(uint16_t))
+ func = read_event_16;
+ else
+ return -EINVAL;
+
+ spin_lock_irqsave(&adsp_cmd_lock, flags);
+ read_event_addr = msg;
+ mod->ops->event(data, event_id, event_length, func);
+ spin_unlock_irqrestore(&adsp_cmd_lock, flags);
+ return 0;
+}
+
int msm_adsp_enable(struct msm_adsp_module *module)
{
int rc = 0;
+ if (!module)
+ return -EINVAL;
+
MM_INFO("enable '%s'state[%d] id[%d]\n",
module->name, module->state, module->id);
@@ -1078,6 +1115,9 @@
{
int rc = 0;
+ if (!module)
+ return -EINVAL;
+
mutex_lock(&module->lock);
rc = rpc_adsp_rtos_app_to_modem(RPC_ADSP_RTOS_CMD_DISABLE_EVENT_RSP,
@@ -1092,6 +1132,9 @@
{
int rc = 0;
+ if (!module)
+ return -EINVAL;
+
switch (module->state) {
case ADSP_STATE_DISABLED:
MM_DBG("module '%s' already disabled\n", module->name);
@@ -1117,6 +1160,10 @@
int msm_adsp_disable(struct msm_adsp_module *module)
{
int rc;
+
+ if (!module)
+ return -EINVAL;
+
MM_INFO("disable '%s'\n", module->name);
mutex_lock(&module->lock);
rc = msm_adsp_disable_locked(module);
@@ -1157,6 +1204,7 @@
spin_lock_init(&adsp_cmd_lock);
spin_lock_init(&adsp_write_lock);
+ mutex_init(&adsp_info.lock);
rc = request_irq(INT_ADSP, adsp_irq_handler, IRQF_TRIGGER_RISING,
"adsp", 0);
diff --git a/arch/arm/mach-msm/qdsp5/adsp.h b/arch/arm/mach-msm/qdsp5/adsp.h
index 0ef27b9..8e5a4f3 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.h
+++ b/arch/arm/mach-msm/qdsp5/adsp.h
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/qdsp5/adsp.h
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2010, 2012 Code Aurora Forum. All rights reserved.
* Author: Iliyan Malchev <ibm@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -117,6 +117,7 @@
struct adsp_rtos_mp_mtoa_init_info_type *init_info_ptr;
wait_queue_head_t init_info_wait;
unsigned init_info_state;
+ struct mutex lock;
};
#define RPC_ADSP_RTOS_ATOM_NULL_PROC 0
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac.c b/arch/arm/mach-msm/qdsp5/audio_aac.c
index 5e1e655..de756eb 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -298,6 +298,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
@@ -672,24 +673,31 @@
static void audio_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->reserved = 0;
audio->out_needed = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
atomic_set(&audio->out_bytes, 0);
}
static void audio_flush_pcm_buf(struct audio *audio)
{
uint8_t index;
+ unsigned long flags;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
audio->in[index].used = 0;
audio->buf_refresh = 0;
audio->read_next = 0;
audio->fill_next = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static int audaac_validate_usr_config(struct msm_audio_aac_config *config)
@@ -990,7 +998,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audio_disable(audio);
- audio->stopped = 1;
audio_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac_in.c b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
index c9e60d8..456a8ff 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
@@ -2,7 +2,7 @@
*
* aac audio input device
*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_aac_in.c,
* Copyright (C) 2008 Google, Inc.
@@ -320,9 +320,10 @@
audaac_in_dsp_enable(audio, 0);
- wake_up(&audio->wait);
wait_event_interruptible_timeout(audio->wait_enable,
audio->running == 0, 1*HZ);
+ audio->stopped = 1;
+ wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
msm_adsp_disable(audio->audpre);
@@ -697,21 +698,23 @@
* sleep and knowing that system is not able
* to process io request at the moment
*/
- wake_up(&audio->write_wait);
- mutex_lock(&audio->write_lock);
- audaac_in_flush(audio);
- mutex_unlock(&audio->write_lock);
wake_up(&audio->wait);
mutex_lock(&audio->read_lock);
- audaac_out_flush(audio);
+ audaac_in_flush(audio);
mutex_unlock(&audio->read_lock);
+ wake_up(&audio->write_wait);
+ mutex_lock(&audio->write_lock);
+ audaac_out_flush(audio);
+ mutex_unlock(&audio->write_lock);
}
static void audaac_in_flush(struct audio_aac_in *audio)
{
int i;
+ unsigned long flags;
audio->dsp_cnt = 0;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->in_head = 0;
audio->in_tail = 0;
audio->in_count = 0;
@@ -720,6 +723,7 @@
audio->in[i].size = 0;
audio->in[i].read = 0;
}
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
atomic_set(&audio->in_bytes, 0);
@@ -729,15 +733,18 @@
static void audaac_out_flush(struct audio_aac_in *audio)
{
int i;
+ unsigned long flags;
audio->out_head = 0;
- audio->out_tail = 0;
audio->out_count = 0;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
+ audio->out_tail = 0;
for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
audio->out[i].size = 0;
audio->out[i].read = 0;
audio->out[i].used = 0;
}
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
/* ------------------- device --------------------- */
@@ -777,7 +784,6 @@
}
case AUDIO_STOP: {
rc = audaac_in_disable(audio);
- audio->stopped = 1;
break;
}
case AUDIO_FLUSH: {
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 476a63d..d66a270 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -2,7 +2,7 @@
*
* amrnb audio decoder device
*
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
*
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
*
@@ -302,6 +302,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
@@ -628,24 +629,31 @@
static void audamrnb_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->out_needed = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
atomic_set(&audio->out_bytes, 0);
}
static void audamrnb_flush_pcm_buf(struct audio *audio)
{
uint8_t index;
+ unsigned long flags;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
audio->in[index].used = 0;
audio->buf_refresh = 0;
audio->read_next = 0;
audio->fill_next = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static void audamrnb_ioport_reset(struct audio *audio)
@@ -876,7 +884,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audamrnb_disable(audio);
- audio->stopped = 1;
audamrnb_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrwb.c b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
index e811731..b566c60 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
@@ -6,7 +6,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2011-2012 Code Aurora Forum. All rights reserved.
*
* All source code in this file is licensed under the following license except
* where indicated.
@@ -299,6 +299,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
@@ -616,25 +617,32 @@
static void audamrwb_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->reserved = 0;
audio->out_needed = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
atomic_set(&audio->out_bytes, 0);
}
static void audamrwb_flush_pcm_buf(struct audio *audio)
{
uint8_t index;
+ unsigned long flags;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
audio->in[index].used = 0;
audio->buf_refresh = 0;
audio->read_next = 0;
audio->fill_next = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static void audamrwb_ioport_reset(struct audio *audio)
@@ -865,7 +873,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audamrwb_disable(audio);
- audio->stopped = 1;
audamrwb_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc.c b/arch/arm/mach-msm/qdsp5/audio_evrc.c
index 3c39b6d..86035db 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc.c
@@ -1,6 +1,6 @@
/* arch/arm/mach-msm/audio_evrc.c
*
- * Copyright (c) 2008-2009, 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
*
* This code also borrows from audio_aac.c, which is
* Copyright (C) 2008 Google, Inc.
@@ -291,6 +291,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
@@ -615,24 +616,30 @@
static void audevrc_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->out_needed = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
atomic_set(&audio->out_bytes, 0);
}
static void audevrc_flush_pcm_buf(struct audio *audio)
{
uint8_t index;
+ unsigned long flags;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
audio->in[index].used = 0;
-
audio->buf_refresh = 0;
audio->read_next = 0;
audio->fill_next = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static void audevrc_ioport_reset(struct audio *audio)
@@ -863,7 +870,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audevrc_disable(audio);
- audio->stopped = 1;
audevrc_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
index 7a5536a..0bdbf5d 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
@@ -2,7 +2,7 @@
*
* evrc audio input device
*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c,
* Copyright (C) 2008 Google, Inc.
@@ -281,6 +281,8 @@
wake_up(&audio->wait);
wait_event_interruptible_timeout(audio->wait_enable,
audio->running == 0, 1*HZ);
+ audio->stopped = 1;
+ wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
msm_adsp_disable(audio->audpre);
@@ -655,21 +657,23 @@
* sleep and knowing that system is not able
* to process io request at the moment
*/
- wake_up(&audio->write_wait);
- mutex_lock(&audio->write_lock);
- audevrc_in_flush(audio);
- mutex_unlock(&audio->write_lock);
wake_up(&audio->wait);
mutex_lock(&audio->read_lock);
- audevrc_out_flush(audio);
+ audevrc_in_flush(audio);
mutex_unlock(&audio->read_lock);
+ wake_up(&audio->write_wait);
+ mutex_lock(&audio->write_lock);
+ audevrc_out_flush(audio);
+ mutex_unlock(&audio->write_lock);
}
static void audevrc_in_flush(struct audio_evrc_in *audio)
{
int i;
+ unsigned long flags;
audio->dsp_cnt = 0;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->in_head = 0;
audio->in_tail = 0;
audio->in_count = 0;
@@ -678,6 +682,7 @@
audio->in[i].size = 0;
audio->in[i].read = 0;
}
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
atomic_set(&audio->in_bytes, 0);
@@ -687,15 +692,18 @@
static void audevrc_out_flush(struct audio_evrc_in *audio)
{
int i;
+ unsigned long flags;
audio->out_head = 0;
- audio->out_tail = 0;
audio->out_count = 0;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
+ audio->out_tail = 0;
for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
audio->out[i].size = 0;
audio->out[i].read = 0;
audio->out[i].used = 0;
}
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
/* ------------------- device --------------------- */
@@ -735,7 +743,6 @@
}
case AUDIO_STOP: {
rc = audevrc_in_disable(audio);
- audio->stopped = 1;
break;
}
case AUDIO_FLUSH: {
diff --git a/arch/arm/mach-msm/qdsp5/audio_mp3.c b/arch/arm/mach-msm/qdsp5/audio_mp3.c
index c4b464a..f6fa62a 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mp3.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -368,6 +368,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
@@ -853,12 +854,16 @@
static void audio_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->reserved = 0;
audio->out_needed = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
atomic_set(&audio->out_bytes, 0);
}
@@ -885,13 +890,15 @@
static void audio_flush_pcm_buf(struct audio *audio)
{
uint8_t index;
+ unsigned long flags;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
audio->in[index].used = 0;
-
audio->buf_refresh = 0;
audio->read_next = 0;
audio->fill_next = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static void audio_ioport_reset(struct audio *audio)
@@ -1366,7 +1373,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audio_disable(audio);
- audio->stopped = 1;
audio_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_mvs.c b/arch/arm/mach-msm/qdsp5/audio_mvs.c
index 9c27485..5ccd18b 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mvs.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mvs.c
@@ -25,7 +25,7 @@
#define MVS_PROG 0x30000014
#define MVS_VERS 0x00030001
-#define MVS_VERS_COMP_VER2 0x00020001
+#define MVS_VERS_COMP_VER2 0x00060001
#define MVS_VERS_COMP_VER3 0x00030001
@@ -67,6 +67,8 @@
#define MVS_FRAME_MODE_G711_DL 10
#define MVS_FRAME_MODE_PCM_UL 13
#define MVS_FRAME_MODE_PCM_DL 14
+#define MVS_FRAME_MODE_PCM_WB_UL 23
+#define MVS_FRAME_MODE_PCM_WB_DL 24
#define MVS_FRAME_MODE_G729A_UL 17
#define MVS_FRAME_MODE_G729A_DL 18
#define MVS_FRAME_MODE_G711A_UL 19
@@ -404,6 +406,11 @@
audio->frame_mode = MVS_FRAME_MODE_PCM_DL;
break;
}
+ case MVS_MODE_PCM_WB: {
+ audio->rate_type = MVS_AMR_MODE_UNDEF;
+ audio->frame_mode = MVS_FRAME_MODE_PCM_WB_DL;
+ break;
+ }
case MVS_MODE_IS127:
case MVS_MODE_IS733:
case MVS_MODE_4GV_NB:
diff --git a/arch/arm/mach-msm/qdsp5/audio_out.c b/arch/arm/mach-msm/qdsp5/audio_out.c
index 7c56037..7d33e05 100644
--- a/arch/arm/mach-msm/qdsp5/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5/audio_out.c
@@ -247,6 +247,7 @@
audpp_disable(-1, audio);
+ audio->stopped = 1;
wake_up(&audio->wait);
audmgr_disable(&audio->audmgr);
audio->out_needed = 0;
@@ -519,7 +520,6 @@
break;
case AUDIO_STOP:
rc = audio_disable(audio);
- audio->stopped = 1;
break;
case AUDIO_FLUSH:
if (audio->stopped) {
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm.c b/arch/arm/mach-msm/qdsp5/audio_pcm.c
index 02103fc..6468e93 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm.c
@@ -1,7 +1,7 @@
/* audio_pcm.c - pcm audio decoder driver
*
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* Based on the mp3 decoder driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
*
@@ -336,6 +336,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
msm_adsp_disable(audio->audplay);
audpp_disable(audio->dec_id, audio);
@@ -639,12 +640,16 @@
static void audio_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->reserved = 0;
audio->out_needed = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
atomic_set(&audio->out_bytes, 0);
}
@@ -1041,7 +1046,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audio_disable(audio);
- audio->stopped = 1;
audio_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 81813a0..16c70ce 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -218,6 +218,7 @@
audpcm_in_dsp_enable(audio, 0);
+ audio->stopped = 1;
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
@@ -613,7 +614,6 @@
}
case AUDIO_STOP:
rc = audpcm_in_disable(audio);
- audio->stopped = 1;
break;
case AUDIO_FLUSH:
if (audio->stopped) {
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp.c b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
index b12e713..2be5144 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
@@ -2,7 +2,7 @@
*
* qcelp 13k audio decoder device
*
- * Copyright (c) 2008-2009, 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2012 Code Aurora Forum. All rights reserved.
*
* This code is based in part on audio_mp3.c, which is
* Copyright (C) 2008 Google, Inc.
@@ -288,6 +288,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
@@ -612,23 +613,30 @@
static void audqcelp_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->out_needed = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static void audqcelp_flush_pcm_buf(struct audio *audio)
{
uint8_t index;
+ unsigned long flags;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
audio->in[index].used = 0;
audio->buf_refresh = 0;
audio->read_next = 0;
audio->fill_next = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static void audqcelp_ioport_reset(struct audio *audio)
@@ -859,7 +867,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audqcelp_disable(audio);
- audio->stopped = 1;
audqcelp_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
index a339825..a79f721 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
@@ -2,7 +2,7 @@
*
* qcelp audio input device
*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c,
* Copyright (C) 2008 Google, Inc.
@@ -279,9 +279,10 @@
audqcelp_in_dsp_enable(audio, 0);
- wake_up(&audio->wait);
wait_event_interruptible_timeout(audio->wait_enable,
audio->running == 0, 1*HZ);
+ audio->stopped = 1;
+ wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
msm_adsp_disable(audio->audpre);
@@ -657,29 +658,32 @@
* sleep and knowing that system is not able
* to process io request at the moment
*/
- wake_up(&audio->write_wait);
- mutex_lock(&audio->write_lock);
- audqcelp_in_flush(audio);
- mutex_unlock(&audio->write_lock);
wake_up(&audio->wait);
mutex_lock(&audio->read_lock);
- audqcelp_out_flush(audio);
+ audqcelp_in_flush(audio);
mutex_unlock(&audio->read_lock);
+ wake_up(&audio->write_wait);
+ mutex_lock(&audio->write_lock);
+ audqcelp_out_flush(audio);
+ mutex_unlock(&audio->write_lock);
}
static void audqcelp_in_flush(struct audio_qcelp_in *audio)
{
int i;
+ unsigned long flags;
+ audio->eos_ack = 0;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->dsp_cnt = 0;
audio->in_head = 0;
audio->in_tail = 0;
audio->in_count = 0;
- audio->eos_ack = 0;
for (i = FRAME_NUM-1; i >= 0; i--) {
audio->in[i].size = 0;
audio->in[i].read = 0;
}
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
atomic_set(&audio->in_bytes, 0);
@@ -689,15 +693,18 @@
static void audqcelp_out_flush(struct audio_qcelp_in *audio)
{
int i;
+ unsigned long flags;
audio->out_head = 0;
- audio->out_tail = 0;
audio->out_count = 0;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
+ audio->out_tail = 0;
for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
audio->out[i].size = 0;
audio->out[i].read = 0;
audio->out[i].used = 0;
}
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
/* ------------------- device --------------------- */
@@ -737,7 +744,6 @@
}
case AUDIO_STOP: {
rc = audqcelp_in_disable(audio);
- audio->stopped = 1;
break;
}
case AUDIO_FLUSH: {
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
index b7e8e1c..7a962b2 100644
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
@@ -266,7 +266,9 @@
audio->in[index].used = 0;
audio->read_next = 0;
+ mutex_lock(&audio->dsp_lock);
audio->fill_next = 0;
+ mutex_unlock(&audio->dsp_lock);
}
static void audvoicememo_ioport_reset(struct audio_voicememo *audio)
@@ -387,6 +389,7 @@
rc = msm_rpc_write(audio->sndept, &rhdr, sizeof(rhdr));
wait_event_timeout(audio->wait, audio->stopped == 0,
1 * HZ);
+ audio->stopped = 1;
wake_up(&audio->read_wait);
audmgr_disable(&audio->audmgr);
audio->enabled = 0;
@@ -536,12 +539,14 @@
callback time\n");
else if (rec_status == RPC_VOC_REC_STAT_AUTO_STOP) {
MM_DBG(" Voice Record AUTO STOP\n");
+ mutex_lock(&audio->lock);
+ audio->stopped = 1;
wake_up(&audio->read_wait);
audmgr_disable(&audio->audmgr);
- audio->stopped = 1;
audvoicememo_ioport_reset(audio);
audio->stopped = 0;
audio->enabled = 0;
+ mutex_unlock(&audio->lock);
}
break;
}
@@ -648,7 +653,6 @@
case AUDIO_STOP: {
MM_DBG("AUDIO_STOP\n");
rc = audvoicememo_disable(audio);
- audio->stopped = 1;
audvoicememo_ioport_reset(audio);
audio->stopped = 0;
MM_DBG("AUDIO_STOP rc %d\n", rc);
diff --git a/arch/arm/mach-msm/qdsp5/audio_wma.c b/arch/arm/mach-msm/qdsp5/audio_wma.c
index cf2ade4..674ee4f 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wma.c
@@ -1,6 +1,6 @@
/* audio_wma.c - wma audio decoder driver
*
- * Copyright (c) 2009, 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2011-2012, Code Aurora Forum. All rights reserved.
*
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
*
@@ -306,6 +306,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
@@ -659,11 +660,15 @@
static void audio_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->reserved = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
atomic_set(&audio->out_bytes, 0);
}
@@ -671,11 +676,15 @@
{
uint8_t index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
audio->in[index].used = 0;
audio->buf_refresh = 0;
audio->read_next = 0;
audio->fill_next = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static void audio_ioport_reset(struct audio *audio)
@@ -905,7 +914,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audio_disable(audio);
- audio->stopped = 1;
audio_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audio_wmapro.c b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
index d9b384a..c2a0b93 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* All source code in this file is licensed under the following license except
* where indicated.
@@ -301,6 +301,7 @@
rc = -EFAULT;
else
rc = 0;
+ audio->stopped = 1;
wake_up(&audio->write_wait);
wake_up(&audio->read_wait);
msm_adsp_disable(audio->audplay);
@@ -648,23 +649,30 @@
static void audio_flush(struct audio *audio)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&audio->dsp_lock, flags);
audio->out[0].used = 0;
audio->out[1].used = 0;
audio->out_head = 0;
audio->out_tail = 0;
audio->reserved = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
atomic_set(&audio->out_bytes, 0);
}
static void audio_flush_pcm_buf(struct audio *audio)
{
uint8_t index;
+ unsigned long flags;
+ spin_lock_irqsave(&audio->dsp_lock, flags);
for (index = 0; index < PCM_BUF_MAX_COUNT; index++)
audio->in[index].used = 0;
audio->buf_refresh = 0;
audio->read_next = 0;
audio->fill_next = 0;
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
}
static void audio_ioport_reset(struct audio *audio)
@@ -894,7 +902,6 @@
case AUDIO_STOP:
MM_DBG("AUDIO_STOP\n");
rc = audio_disable(audio);
- audio->stopped = 1;
audio_ioport_reset(audio);
audio->stopped = 0;
break;
diff --git a/arch/arm/mach-msm/qdsp5/audpp.c b/arch/arm/mach-msm/qdsp5/audpp.c
index 3e834d8..2dbb5dc0 100644
--- a/arch/arm/mach-msm/qdsp5/audpp.c
+++ b/arch/arm/mach-msm/qdsp5/audpp.c
@@ -4,7 +4,7 @@
* common code to deal with the AUDPP dsp task (audio postproc)
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2010, 2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -124,6 +124,8 @@
uint16_t avsync[CH_COUNT * AUDPP_CLNT_MAX_COUNT + 1];
struct audpp_event_callback *cb_tbl[MAX_EVENT_CALLBACK_CLIENTS];
+ spinlock_t avsync_lock;
+
wait_queue_head_t event_wait;
};
@@ -237,13 +239,24 @@
}
}
+static void audpp_fake_event(struct audpp_state *audpp, int id,
+ unsigned event, unsigned arg)
+{
+ uint16_t msg[1];
+ msg[0] = arg;
+ audpp->func[id] (audpp->private[id], event, msg);
+}
+
static void audpp_dsp_event(void *data, unsigned id, size_t len,
void (*getevent) (void *ptr, size_t len))
{
struct audpp_state *audpp = data;
+ unsigned long flags;
uint16_t msg[8];
+ int cid = 0;
if (id == AUDPP_MSG_AVSYNC_MSG) {
+ spin_lock_irqsave(&audpp->avsync_lock, flags);
getevent(audpp->avsync, sizeof(audpp->avsync));
/* mask off any channels we're not watching to avoid
@@ -252,6 +265,7 @@
* we next read...
*/
audpp->avsync[0] &= audpp->avsync_mask;
+ spin_unlock_irqrestore(&audpp->avsync_lock, flags);
return;
}
@@ -278,13 +292,28 @@
case AUDPP_MSG_CFG_MSG:
if (msg[0] == AUDPP_MSG_ENA_ENA) {
MM_INFO("ENABLE\n");
- audpp->enabled = 1;
- audpp_broadcast(audpp, id, msg);
+ if (!audpp->enabled) {
+ audpp->enabled = 1;
+ audpp_broadcast(audpp, id, msg);
+ } else {
+ cid = msg[1];
+ audpp_fake_event(audpp, cid,
+ id, AUDPP_MSG_ENA_ENA);
+ }
+
} else if (msg[0] == AUDPP_MSG_ENA_DIS) {
- MM_INFO("DISABLE\n");
- audpp->enabled = 0;
- wake_up(&audpp->event_wait);
- audpp_broadcast(audpp, id, msg);
+ if (audpp->open_count == 0) {
+ MM_INFO("DISABLE\n");
+ audpp->enabled = 0;
+ wake_up(&audpp->event_wait);
+ audpp_broadcast(audpp, id, msg);
+ } else {
+ cid = msg[1];
+ audpp_fake_event(audpp, cid,
+ id, AUDPP_MSG_ENA_DIS);
+ audpp->func[cid] = NULL;
+ audpp->private[cid] = NULL;
+ }
} else {
MM_ERR("invalid config msg %d\n", msg[0]);
}
@@ -307,17 +336,10 @@
.event = audpp_dsp_event,
};
-static void audpp_fake_event(struct audpp_state *audpp, int id,
- unsigned event, unsigned arg)
-{
- uint16_t msg[1];
- msg[0] = arg;
- audpp->func[id] (audpp->private[id], event, msg);
-}
-
int audpp_enable(int id, audpp_event_func func, void *private)
{
struct audpp_state *audpp = &the_audpp_state;
+ uint16_t msg[8];
int res = 0;
if (id < -1 || id > 4)
@@ -350,12 +372,15 @@
msm_adsp_enable(audpp->mod);
audpp_dsp_config(1);
} else {
- unsigned long flags;
- local_irq_save(flags);
- if (audpp->enabled)
- audpp_fake_event(audpp, id,
- AUDPP_MSG_CFG_MSG, AUDPP_MSG_ENA_ENA);
- local_irq_restore(flags);
+ if (audpp->enabled) {
+ msg[0] = AUDPP_MSG_ENA_ENA;
+ msg[1] = id;
+ res = msm_adsp_generate_event(audpp, audpp->mod,
+ AUDPP_MSG_CFG_MSG, sizeof(msg),
+ sizeof(uint16_t), (void *)msg);
+ if (res < 0)
+ goto out;
+ }
}
res = 0;
@@ -368,7 +393,7 @@
void audpp_disable(int id, void *private)
{
struct audpp_state *audpp = &the_audpp_state;
- unsigned long flags;
+ uint16_t msg[8];
int rc;
if (id < -1 || id > 4)
@@ -384,11 +409,13 @@
if (audpp->private[id] != private)
goto out;
- local_irq_save(flags);
- audpp_fake_event(audpp, id, AUDPP_MSG_CFG_MSG, AUDPP_MSG_ENA_DIS);
- audpp->func[id] = NULL;
- audpp->private[id] = NULL;
- local_irq_restore(flags);
+ msg[0] = AUDPP_MSG_ENA_DIS;
+ msg[1] = id;
+ rc = msm_adsp_generate_event(audpp, audpp->mod,
+ AUDPP_MSG_CFG_MSG, sizeof(msg),
+ sizeof(uint16_t), (void *)msg);
+ if (rc < 0)
+ goto out;
if (--audpp->open_count == 0) {
MM_DBG("disable\n");
@@ -420,13 +447,13 @@
if (BAD_ID(id))
return;
- local_irq_save(flags);
+ spin_lock_irqsave(&the_audpp_state.avsync_lock, flags);
if (rate)
the_audpp_state.avsync_mask |= (1 << id);
else
the_audpp_state.avsync_mask &= (~(1 << id));
the_audpp_state.avsync[0] &= the_audpp_state.avsync_mask;
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&the_audpp_state.avsync_lock, flags);
cmd.cmd_id = AUDPP_CMD_AVSYNC;
cmd.object_number = id;
@@ -438,7 +465,8 @@
unsigned audpp_avsync_sample_count(int id)
{
- uint16_t *avsync = the_audpp_state.avsync;
+ struct audpp_state *audpp = &the_audpp_state;
+ uint16_t *avsync = audpp->avsync;
unsigned val;
unsigned long flags;
unsigned mask;
@@ -448,12 +476,12 @@
mask = 1 << id;
id = id * AUDPP_AVSYNC_INFO_SIZE + 2;
- local_irq_save(flags);
+ spin_lock_irqsave(&audpp->avsync_lock, flags);
if (avsync[0] & mask)
val = (avsync[id] << 16) | avsync[id + 1];
else
val = 0;
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&audpp->avsync_lock, flags);
return val;
}
@@ -461,7 +489,8 @@
unsigned audpp_avsync_byte_count(int id)
{
- uint16_t *avsync = the_audpp_state.avsync;
+ struct audpp_state *audpp = &the_audpp_state;
+ uint16_t *avsync = audpp->avsync;
unsigned val;
unsigned long flags;
unsigned mask;
@@ -471,12 +500,12 @@
mask = 1 << id;
id = id * AUDPP_AVSYNC_INFO_SIZE + 5;
- local_irq_save(flags);
+ spin_lock_irqsave(&audpp->avsync_lock, flags);
if (avsync[0] & mask)
val = (avsync[id] << 16) | avsync[id + 1];
else
val = 0;
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&audpp->avsync_lock, flags);
return val;
}
@@ -826,6 +855,8 @@
init_waitqueue_head(&audpp->event_wait);
+ spin_lock_init(&audpp->avsync_lock);
+
for (idx = 0; idx < audpp->dec_database->num_dec; idx++) {
audpp->dec_info_table[idx].codec = -1;
audpp->dec_info_table[idx].pid = 0;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c b/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
index c38fefc..d43c961 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) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -76,6 +76,9 @@
#define MASK_32BITS 0xFFFFFFFF
+#define MAX_BUF 4
+#define BUFSZ (524288)
+
#define __CONTAINS(r, v, l) ({ \
typeof(r) __r = r; \
typeof(v) __v = v; \
@@ -1192,6 +1195,8 @@
audio->out_sample_rate = config.sample_rate;
audio->out_channel_mode = config.channel_count;
audio->out_bits = config.bits;
+ audio->buffer_count = config.buffer_count;
+ audio->buffer_size = config.buffer_size;
MM_DBG("AUDIO_SET_CONFIG: config.bits = %d\n", config.bits);
rc = 0;
break;
@@ -1199,7 +1204,8 @@
case AUDIO_GET_CONFIG:{
struct msm_audio_config config;
- config.buffer_count = 2;
+ config.buffer_count = audio->buffer_count;
+ config.buffer_size = audio->buffer_size;
config.sample_rate = audio->out_sample_rate;
if (audio->out_channel_mode == AUDPP_CMD_PCM_INTF_MONO_V)
config.channel_count = 1;
@@ -1518,6 +1524,8 @@
dec_attrb |= audlpa_decs[audio->minor_no].dec_attrb;
audio->codec_ops.ioctl = audlpa_decs[audio->minor_no].ioctl;
audio->codec_ops.adec_params = audlpa_decs[audio->minor_no].adec_params;
+ audio->buffer_size = BUFSZ;
+ audio->buffer_count = MAX_BUF;
dec_attrb |= MSM_AUD_MODE_LP;
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 37428da..541f62f 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -505,12 +505,19 @@
return;
pr_debug("%s: handle[%p]\n", __func__, handle);
+ if (apr_reset_workqueue == NULL) {
+ pr_err("%s: apr_reset_workqueue is NULL\n", __func__);
+ return;
+ }
+
apr_reset_worker = kzalloc(sizeof(struct apr_reset_work),
- GFP_ATOMIC);
- if (apr_reset_worker == NULL || apr_reset_workqueue == NULL) {
+ GFP_ATOMIC);
+
+ if (apr_reset_worker == NULL) {
pr_err("%s: mem failure\n", __func__);
return;
}
+
apr_reset_worker->handle = handle;
INIT_WORK(&apr_reset_worker->work, apr_reset_deregister);
queue_work(apr_reset_workqueue, &apr_reset_worker->work);
diff --git a/arch/arm/mach-msm/qdss-ptm.c b/arch/arm/mach-msm/qdss-ptm.c
index 96a727a..c0dc58e 100644
--- a/arch/arm/mach-msm/qdss-ptm.c
+++ b/arch/arm/mach-msm/qdss-ptm.c
@@ -67,9 +67,9 @@
#define ETMSQ12EVR (0x180)
#define ETMSQ21EVR (0x184)
#define ETMSQ23EVR (0x188)
-#define ETMSQ32EVR (0x18C)
-#define ETMSQ13EVR (0x190)
-#define ETMSQ31EVR (0x194)
+#define ETMSQ31EVR (0x18C)
+#define ETMSQ32EVR (0x190)
+#define ETMSQ13EVR (0x194)
#define ETMSQR (0x19C)
#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
@@ -91,7 +91,7 @@
#define ETMTSEVR (0x1F8)
#define ETMAUXCR (0x1FC)
#define ETMTRACEIDR (0x200)
-#define ETMVMIDCVR (0x204)
+#define ETMVMIDCVR (0x240)
/* Management registers (0x300-0x314) */
#define ETMOSLAR (0x300)
#define ETMOSLSR (0x304)
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 747b585..e0d0dd8 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -190,10 +190,7 @@
static int __init scm_pas_init(void)
{
- /* TODO: Remove once bus scaling driver is in place */
- if (!cpu_is_apq8064())
- scm_perf_client = msm_bus_scale_register_client(
- &scm_pas_bus_pdata);
+ scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
if (!scm_perf_client)
pr_warn("unable to register bus client\n");
scm_bus_clk = clk_get_sys("scm", "bus_clk");
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index b95c3aa..bca1e0c 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -273,6 +273,38 @@
#define MSM_TRIG_A2WCNSS_SMSM_INT
#endif
+/*
+ * stub out legacy macros if they are not being used so that the legacy
+ * code compiles even though it is not used
+ *
+ * these definitions should not be used in active code and will cause
+ * an early failure
+ */
+#ifndef INT_A9_M2A_0
+#define INT_A9_M2A_0 -1
+#endif
+#ifndef INT_A9_M2A_5
+#define INT_A9_M2A_5 -1
+#endif
+#ifndef INT_ADSP_A11
+#define INT_ADSP_A11 -1
+#endif
+#ifndef INT_ADSP_A11_SMSM
+#define INT_ADSP_A11_SMSM -1
+#endif
+#ifndef INT_DSPS_A11
+#define INT_DSPS_A11 -1
+#endif
+#ifndef INT_DSPS_A11_SMSM
+#define INT_DSPS_A11_SMSM -1
+#endif
+#ifndef INT_WCNSS_A11
+#define INT_WCNSS_A11 -1
+#endif
+#ifndef INT_WCNSS_A11_SMSM
+#define INT_WCNSS_A11_SMSM -1
+#endif
+
#define SMD_LOOPBACK_CID 100
#define SMEM_SPINLOCK_SMEM_ALLOC "S:3"
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 0ec88d5..9b10ffd 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -218,6 +218,7 @@
/* 8064 IDs */
[109] = MSM_CPU_8064,
+ [130] = MSM_CPU_8064,
/* 8930 IDs */
[116] = MSM_CPU_8930,
@@ -603,7 +604,7 @@
arch_initcall(socinfo_init_sysdev);
-void *setup_dummy_socinfo(void)
+static void * __init setup_dummy_socinfo(void)
{
if (machine_is_msm8960_rumi3() || machine_is_msm8960_sim() ||
machine_is_msm8960_cdp())
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index 78fd922..b155781 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -65,12 +65,7 @@
#elif defined(CONFIG_MSM_SPM_V2)
enum {
- MSM_SPM_REG_SAW2_SECURE,
- MSM_SPM_REG_SAW2_ID,
MSM_SPM_REG_SAW2_CFG,
- MSM_SPM_REG_SAW2_STS0,
- MSM_SPM_REG_SAW2_STS1,
- MSM_SPM_REG_SAW2_VCTL,
MSM_SPM_REG_SAW2_AVS_CTL,
MSM_SPM_REG_SAW2_AVS_HYSTERESIS,
MSM_SPM_REG_SAW2_SPM_CTL,
@@ -79,8 +74,13 @@
MSM_SPM_REG_SAW2_PMIC_DATA_1,
MSM_SPM_REG_SAW2_RST,
- MSM_SPM_REG_NR_INITIALIZE,
- MSM_SPM_REG_SAW2_SEQ_ENTRY = MSM_SPM_REG_NR_INITIALIZE,
+ MSM_SPM_REG_NR_INITIALIZE = MSM_SPM_REG_SAW2_RST,
+ MSM_SPM_REG_SAW2_ID,
+ MSM_SPM_REG_SAW2_SECURE,
+ MSM_SPM_REG_SAW2_STS0,
+ MSM_SPM_REG_SAW2_STS1,
+ MSM_SPM_REG_SAW2_VCTL,
+ MSM_SPM_REG_SAW2_SEQ_ENTRY ,
MSM_SPM_REG_NR
};
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 07a9241..9970c90 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -122,9 +122,13 @@
if (pdev && pwlanconfig)
ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
WCNSS_WLAN_SWITCH_ON);
- if (!ret)
+ /* delay PIL operation, this SSR may be happening soon after kernel
+ * resumes because of a SMSM RESET by Riva when APPS was suspended.
+ * PIL fails to locate the images without this delay */
+ if (!ret) {
+ msleep(1000);
pil_force_boot("wcnss");
-
+ }
ss_restart_inprogress = false;
enable_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 14536f6..946899d 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -17,6 +17,8 @@
#include <asm/thread_notify.h>
#include <asm/tlbflush.h>
+#include <mach/msm_rtb.h>
+
static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
unsigned int cpu_last_asid = ASID_FIRST_VERSION;
#ifdef CONFIG_SMP
@@ -25,6 +27,7 @@
static void write_contextidr(u32 contextidr)
{
+ uncached_logk(LOGK_CTXID, (void *)contextidr);
asm("mcr p15, 0, %0, c13, c0, 1" : : "r" (contextidr));
isb();
}
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
old mode 100644
new mode 100755
index 7d2e44f..8dcce03
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1136,4 +1136,6 @@
apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
+mpq8064_hrd MACH_MPQ8064_HRD MPQ8064_HRD 3994
+mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995
msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 851189d..58bf45d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@
source "drivers/spi/Kconfig"
+source "drivers/spmi/Kconfig"
+
source "drivers/slimbus/Kconfig"
source "drivers/pps/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index e18822cd..82008ed 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -51,6 +51,7 @@
obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
+obj-$(CONFIG_SPMI) += spmi/
obj-$(CONFIG_SLIMBUS) += slimbus/
obj-y += net/
obj-$(CONFIG_ATM) += atm/
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index a9faff0..371d319 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -52,8 +52,8 @@
#define MAX_EQUIP_ID 12
/* Maximum number of pkt reg supported at initialization*/
-extern unsigned int diag_max_registration;
-extern unsigned int diag_threshold_registration;
+extern unsigned int diag_max_reg;
+extern unsigned int diag_threshold_reg;
#define APPEND_DEBUG(ch) \
do { \
@@ -128,6 +128,7 @@
struct diag_client_map *client_map;
int *data_ready;
int num_clients;
+ int polling_reg_flag;
struct diag_write_device *buf_tbl;
/* Memory pool parameters */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index a703148..efba92b 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -60,8 +60,8 @@
static unsigned int max_clients = 15;
static unsigned int threshold_client_limit = 30;
/* This is the maximum number of pkt registrations supported at initialization*/
-unsigned int diag_max_registration = 500;
-unsigned int diag_threshold_registration = 650;
+unsigned int diag_max_reg = 600;
+unsigned int diag_threshold_reg = 750;
/* Timer variables */
static struct timer_list drain_timer;
@@ -230,7 +230,7 @@
}
#endif /* DIAG over USB */
/* Delete the pkt response table entry for the exiting process */
- for (i = 0; i < diag_max_registration; i++)
+ for (i = 0; i < diag_max_reg; i++)
if (driver->table[i].process_id == current->tgid)
driver->table[i].process_id = 0;
@@ -256,15 +256,49 @@
return -ENOMEM;
}
+int diag_find_polling_reg(int i)
+{
+ uint16_t subsys_id, cmd_code_lo, cmd_code_hi;
+
+ subsys_id = driver->table[i].subsys_id;
+ cmd_code_lo = driver->table[i].cmd_code_lo;
+ cmd_code_hi = driver->table[i].cmd_code_hi;
+ if (driver->table[i].cmd_code == 0x0C)
+ return 1;
+ else if (driver->table[i].cmd_code == 0xFF) {
+ if (subsys_id == 0x04 && cmd_code_hi == 0x0E &&
+ cmd_code_lo == 0x0E)
+ return 1;
+ else if (subsys_id == 0x08 && cmd_code_hi == 0x02 &&
+ cmd_code_lo == 0x02)
+ return 1;
+ else if (subsys_id == 0x32 && cmd_code_hi == 0x03 &&
+ cmd_code_lo == 0x03)
+ return 1;
+ }
+ return 0;
+}
+
void diag_clear_reg(int proc_num)
{
int i;
- for (i = 0; i < diag_max_registration; i++) {
+ mutex_lock(&driver->diagchar_mutex);
+ /* reset polling flag */
+ driver->polling_reg_flag = 0;
+ for (i = 0; i < diag_max_reg; i++) {
if (driver->table[i].client_id == proc_num) {
driver->table[i].process_id = 0;
}
}
+ /* re-scan the registration table */
+ for (i = 0; i < diag_max_reg; i++) {
+ if (diag_find_polling_reg(i) == 1) {
+ driver->polling_reg_flag = 1;
+ break;
+ }
+ }
+ mutex_unlock(&driver->diagchar_mutex);
}
void diag_add_reg(int j, struct bindpkt_params *params,
@@ -275,6 +309,11 @@
driver->table[j].subsys_id = params->subsys_id;
driver->table[j].cmd_code_lo = params->cmd_code_lo;
driver->table[j].cmd_code_hi = params->cmd_code_hi;
+
+ /* check if incoming reg is polling & polling is yet not registered */
+ if (driver->polling_reg_flag == 0)
+ if (diag_find_polling_reg(j) == 1)
+ driver->polling_reg_flag = 1;
if (params->proc_id == APPS_PROC) {
driver->table[j].process_id = current->tgid;
driver->table[j].client_id = APPS_PROC;
@@ -296,7 +335,7 @@
struct bindpkt_params_per_process *pkt_params =
(struct bindpkt_params_per_process *) ioarg;
mutex_lock(&driver->diagchar_mutex);
- for (i = 0; i < diag_max_registration; i++) {
+ for (i = 0; i < diag_max_reg; i++) {
if (driver->table[i].process_id == 0) {
diag_add_reg(i, pkt_params->params,
&success, &count_entries);
@@ -308,19 +347,20 @@
}
}
}
- if (i < diag_threshold_registration) {
+ if (i < diag_threshold_reg) {
/* Increase table size by amount required */
- diag_max_registration += pkt_params->count -
+ diag_max_reg += pkt_params->count -
count_entries;
/* Make sure size doesnt go beyond threshold */
- if (diag_max_registration > diag_threshold_registration)
- diag_max_registration =
- diag_threshold_registration;
+ if (diag_max_reg > diag_threshold_reg) {
+ diag_max_reg = diag_threshold_reg;
+ pr_info("diag: best case memory allocation\n");
+ }
temp_buf = krealloc(driver->table,
- diag_max_registration*sizeof(struct
+ diag_max_reg*sizeof(struct
diag_master_table), GFP_KERNEL);
if (!temp_buf) {
- diag_max_registration -= pkt_params->count -
+ diag_max_reg -= pkt_params->count -
count_entries;
pr_alert("diag: Insufficient memory for reg.");
mutex_unlock(&driver->diagchar_mutex);
@@ -328,7 +368,7 @@
} else {
driver->table = temp_buf;
}
- for (j = i; j < diag_max_registration; j++) {
+ for (j = i; j < diag_max_reg; j++) {
diag_add_reg(j, pkt_params->params,
&success, &count_entries);
if (pkt_params->count > count_entries) {
@@ -338,6 +378,7 @@
return success;
}
}
+ mutex_unlock(&driver->diagchar_mutex);
} else {
mutex_unlock(&driver->diagchar_mutex);
pr_err("Max size reached, Pkt Registration failed for"
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 07322cd..7f26856 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -598,7 +598,7 @@
}
pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
- for (i = 0; i < diag_max_registration; i++) {
+ for (i = 0; i < diag_max_reg; i++) {
entry = driver->table[i];
if (entry.process_id != NO_PROCESS) {
if (entry.cmd_code == cmd_code && entry.subsys_id ==
@@ -891,8 +891,8 @@
/* Check for polling for Apps only DIAG */
else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
(*(buf+2) == 0x03)) {
- /* If there is NO MODEM present */
- if (!(driver->ch)) {
+ /* If no one has registered for polling */
+ if (!(driver->polling_reg_flag)) {
/* Respond to polling for Apps only DIAG */
for (i = 0; i < 3; i++)
driver->apps_rsp_buf[i] = *(buf+i);
@@ -901,13 +901,10 @@
ENCODE_RSP_AND_SEND(15);
return 0;
- } else {
- /* Since Modem is present, send error response */
- return 1;
}
}
/* Check for ID for NO MODEM present */
- else if (!(driver->ch)) {
+ else if (!(driver->polling_reg_flag)) {
/* respond to 0x0 command */
if (*buf == 0x00) {
for (i = 0; i < 55; i++)
@@ -1041,9 +1038,9 @@
queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
/* Poll SMD CNTL channels to check for data */
- queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
- queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_cntl_work));
- queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_cntl_work));
+ diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
+ diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
+ diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
/* Poll USB channel to check for data*/
queue_work(driver->diag_wq, &(driver->diag_read_work));
#ifdef CONFIG_DIAG_SDIO_PIPE
@@ -1377,7 +1374,7 @@
, GFP_KERNEL)) == NULL)
goto err;
if (driver->table == NULL &&
- (driver->table = kzalloc(diag_max_registration*
+ (driver->table = kzalloc(diag_max_reg*
sizeof(struct diag_master_table),
GFP_KERNEL)) == NULL)
goto err;
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index df2cd65..2c3dc54 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -19,6 +19,66 @@
#define HDR_SIZ 8
+void diag_smd_cntl_notify(void *ctxt, unsigned event)
+{
+ int r1, r2;
+
+ if (!(driver->ch_cntl))
+ return;
+
+ switch (event) {
+ case SMD_EVENT_DATA:
+ r1 = smd_read_avail(driver->ch_cntl);
+ r2 = smd_cur_packet_size(driver->ch_cntl);
+ if (r1 > 0 && r1 == r2)
+ queue_work(driver->diag_wq,
+ &(driver->diag_read_smd_cntl_work));
+ else
+ pr_debug("diag: incomplete pkt on Modem CNTL ch\n");
+ break;
+ }
+}
+
+void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event)
+{
+ int r1, r2;
+
+ if (!(driver->chqdsp_cntl))
+ return;
+
+ switch (event) {
+ case SMD_EVENT_DATA:
+ r1 = smd_read_avail(driver->chqdsp_cntl);
+ r2 = smd_cur_packet_size(driver->chqdsp_cntl);
+ if (r1 > 0 && r1 == r2)
+ queue_work(driver->diag_wq,
+ &(driver->diag_read_smd_qdsp_cntl_work));
+ else
+ pr_debug("diag: incomplete pkt on LPASS CNTL ch\n");
+ break;
+ }
+}
+
+void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event)
+{
+ int r1, r2;
+
+ if (!(driver->ch_wcnss_cntl))
+ return;
+
+ switch (event) {
+ case SMD_EVENT_DATA:
+ r1 = smd_read_avail(driver->ch_wcnss_cntl);
+ r2 = smd_cur_packet_size(driver->ch_wcnss_cntl);
+ if (r1 > 0 && r1 == r2)
+ queue_work(driver->diag_wq,
+ &(driver->diag_read_smd_wcnss_cntl_work));
+ else
+ pr_debug("diag: incomplete pkt on WCNSS CNTL ch\n");
+ break;
+ }
+}
+
static void diag_smd_cntl_send_req(int proc_num)
{
int data_len = 0, type = -1, count_bytes = 0, j, r, flag = 0;
@@ -30,6 +90,11 @@
void *buf = NULL;
smd_channel_t *smd_ch = NULL;
+ if (pkt_params == NULL) {
+ pr_alert("diag: Memory allocation failure\n");
+ return;
+ }
+
if (proc_num == MODEM_PROC) {
buf = driver->buf_in_cntl;
smd_ch = driver->ch_cntl;
@@ -62,6 +127,17 @@
while (count_bytes + HDR_SIZ <= r) {
type = *(uint32_t *)(buf);
data_len = *(uint32_t *)(buf + 4);
+ if (type < DIAG_CTRL_MSG_REG ||
+ type > DIAG_CTRL_MSG_F3_MASK_V2) {
+ pr_alert("diag: Invalid Msg type %d proc %d",
+ type, proc_num);
+ break;
+ }
+ if (data_len < 0 || data_len > r) {
+ pr_alert("diag: Invalid data len %d proc %d",
+ data_len, proc_num);
+ break;
+ }
count_bytes = count_bytes+HDR_SIZ+data_len;
if (type == DIAG_CTRL_MSG_REG && r >= count_bytes) {
msg = buf+HDR_SIZ;
@@ -70,6 +146,10 @@
pkt_params->count = msg->count_entries;
temp = kzalloc(pkt_params->count * sizeof(struct
bindpkt_params), GFP_KERNEL);
+ if (temp == NULL) {
+ pr_alert("diag: Memory alloc fail\n");
+ return;
+ }
for (j = 0; j < pkt_params->count; j++) {
temp->cmd_code = msg->cmd_code;
temp->subsys_id = msg->subsysid;
@@ -93,11 +173,12 @@
kfree(pkt_params);
if (flag) {
/* Poll SMD CNTL channels to check for data */
- queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_qdsp_cntl_work));
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_wcnss_cntl_work));
+ if (proc_num == MODEM_PROC)
+ diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
+ else if (proc_num == QDSP_PROC)
+ diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
+ else if (proc_num == WCNSS_PROC)
+ diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
}
}
@@ -116,21 +197,6 @@
diag_smd_cntl_send_req(WCNSS_PROC);
}
-static void diag_smd_cntl_notify(void *ctxt, unsigned event)
-{
- queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
-}
-
-static void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event)
-{
- queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_cntl_work));
-}
-
-static void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event)
-{
- queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_cntl_work));
-}
-
static int diag_smd_cntl_probe(struct platform_device *pdev)
{
int r = 0;
@@ -192,6 +258,7 @@
void diagfwd_cntl_init(void)
{
+ driver->polling_reg_flag = 0;
if (driver->buf_in_cntl == NULL) {
driver->buf_in_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
if (driver->buf_in_cntl == NULL)
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 542138d..a76d36d 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,26 @@
#ifndef DIAGFWD_CNTL_H
#define DIAGFWD_CNTL_H
-#define DIAG_CTRL_MSG_REG 1 /* Message registration commands */
+/* Message registration commands */
+#define DIAG_CTRL_MSG_REG 1
+/* Message passing for DTR events */
+#define DIAG_CTRL_MSG_DTR 2
+/* Control Diag sleep vote, buffering etc */
+#define DIAG_CTRL_MSG_DIAGMODE 3
+/* Diag data based on "light" diag mask */
+#define DIAG_CTRL_MSG_DIAGDATA 4
+/* Deprecated */
+#define DIAG_CTRL_MSG_LOG_MASK 5
+#define DIAG_CTRL_MSG_EVENT_MASK 6
+#define DIAG_CTRL_MSG_F3_MASK 7
+/* Send diag internal feature mask 'diag_int_feature_mask' */
+#define DIAG_CTRL_MSG_FEATURE 8
+/* Send Diag log mask for a particular equip id */
+#define DIAG_CTRL_MSG_EQUIP_LOG_MASK 9
+/* Send Diag event mask */
+#define DIAG_CTRL_MSG_EVENT_MASK_V2 10
+/* Send Diag F3 mask */
+#define DIAG_CTRL_MSG_F3_MASK_V2 11
struct cmd_code_range {
uint16_t cmd_code_lo;
@@ -34,5 +53,8 @@
void diag_read_smd_cntl_work_fn(struct work_struct *);
void diag_read_smd_qdsp_cntl_work_fn(struct work_struct *);
void diag_read_smd_wcnss_cntl_work_fn(struct work_struct *);
+void diag_smd_cntl_notify(void *ctxt, unsigned event);
+void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event);
+void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event);
#endif
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index f5367ef..d1a9fe6 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -122,19 +122,19 @@
"failed to enable clock in probe\n");
return -EPERM;
}
- val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET) &
- PRNG_LFSR_CFG_MASK;
- val |= PRNG_LFSR_CFG_MASK;
- writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
-
- /* The PRNG CONFIG register should be first written before reading */
- mb();
-
/* Enable PRNG h/w only if it is NOT ON */
val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET) &
PRNG_HW_ENABLE;
/* PRNG H/W is not ON */
if (val != PRNG_HW_ENABLE) {
+ val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET) &
+ PRNG_LFSR_CFG_MASK;
+ val |= PRNG_LFSR_CFG_MASK;
+ writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
+
+ /* The PRNG CONFIG register should be first written */
+ mb();
+
reg_val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET)
& PRNG_CONFIG_MASK;
reg_val |= PRNG_HW_ENABLE;
@@ -242,9 +242,6 @@
static int __init msm_rng_init(void)
{
- if (cpu_is_apq8064())
- return -ENODEV;
-
return platform_driver_register(&rng_driver);
}
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index d725851..5276bcc 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -1,6 +1,6 @@
/* Qualcomm Crypto Engine driver.
*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011 - 2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@
#define DST_INDEX_SG_CMD(index) (index & 0x3fff)
#define ADM_DESC_LAST (1 << 31)
#define QCE_FIFO_SIZE 0x8000
+
/*
* CE HW device structure.
* Each engine has an instance of the structure.
@@ -128,6 +129,7 @@
{
unsigned int val;
unsigned int rev;
+ unsigned int ret;
val = (uint32_t)(*((uint32_t *)pce_dev->ce_dm.buffer.version));
if (((val & 0xfffffff) != 0x0000043) &&
@@ -144,6 +146,23 @@
"Qualcomm Crypto 4.2 device found at 0x%x\n",
pce_dev->phy_iobase);
pce_dev->ce_dm.ce_block_size = 64;
+
+ /* Configure the crypto register to support 64byte CRCI if it
+ * is not XPU protected and the HW version of device is greater
+ * than 0x42.
+ * Crypto config register returns a 0 when it is XPU protected.
+ */
+
+ ret = readl_relaxed(pce_dev->iobase + CRYPTO_CONFIG_REG);
+ if (ret) {
+ val = (CRYPTO_REQ_SIZE_ENUM_64_BYTES <<
+ CRYPTO_REQ_SIZE) |
+ (CRYPTO_FIFO_ENUM_64_BYTES <<
+ CRYPTO_FIFO_THRESHOLD);
+
+ writel_relaxed(val, pce_dev->iobase +
+ CRYPTO_CONFIG_REG);
+ } /* end of if (ret) */
} else {
if (rev == 0x40) {
dev_info(pce_dev->pdev,
@@ -152,12 +171,6 @@
pce_dev->ce_dm.ce_block_size = 16;
}
}
- /*
- * This is a temporary change - until Data Mover changes its
- * configuration from 16 byte crci to 64 byte crci.
- */
- if (cpu_is_msm9615())
- pce_dev->ce_dm.ce_block_size = 16;
dev_info(pce_dev->pdev,
"IO base 0x%x\n, ce_in channel %d , "
@@ -2609,4 +2622,4 @@
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Mona Hossain <mhossain@codeaurora.org>");
MODULE_DESCRIPTION("Crypto Engine driver");
-MODULE_VERSION("2.14");
+MODULE_VERSION("2.15");
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index ad0c7b1..347ab88 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -206,16 +206,13 @@
if (ion_carveout_request_region(carveout_heap))
return -EINVAL;
- if (ION_IS_CACHED(flags))
- ret_value = remap_pfn_range(vma, vma->vm_start,
- __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
- else
- ret_value = remap_pfn_range(vma, vma->vm_start,
- __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- pgprot_noncached(vma->vm_page_prot));
+ if (!ION_IS_CACHED(flags))
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ ret_value = remap_pfn_range(vma, vma->vm_start,
+ __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
if (ret_value)
ion_carveout_release_region(carveout_heap);
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index a6b0cf6..ff561dc 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -450,18 +450,14 @@
return -EINVAL;
}
- if (ION_IS_CACHED(flags))
- ret_value = remap_pfn_range(vma, vma->vm_start,
- __phys_to_pfn(buffer->priv_phys) +
- vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
- else
- ret_value = remap_pfn_range(vma, vma->vm_start,
- __phys_to_pfn(buffer->priv_phys) +
- vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- pgprot_noncached(vma->vm_page_prot));
+ if (!ION_IS_CACHED(flags))
+ vma->vm_page_prot = pgprot_writecombine(
+ vma->vm_page_prot);
+
+ ret_value = remap_pfn_range(vma, vma->vm_start,
+ __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
if (ret_value)
ion_cp_release_region(cp_heap);
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index d37a811..2f9e80c 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -136,7 +136,7 @@
return -EINVAL;
if (!ION_IS_CACHED(flags))
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
for (i = 0; i < data->nrpages; i++)
if (vm_insert_page(vma, vma->vm_start + i * PAGE_SIZE,
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 2a2892e..a81dbd3 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -91,7 +91,7 @@
const struct fmem_data *fmem_info =
fmem_get_info();
heap->base = fmem_info->phys -
- fmem_info->reserved_size;
+ fmem_info->reserved_size_low;
cp_data->virt_addr = fmem_info->virt;
pr_info("ION heap %s using FMEM\n",
shared_heap->name);
@@ -159,6 +159,10 @@
heap->base = fmem_info->phys;
data->virt_addr = fmem_info->virt;
pr_info("ION heap %s using FMEM\n", heap->name);
+ } else if (data->mem_is_fmem) {
+ const struct fmem_data *fmem_info =
+ fmem_get_info();
+ heap->base = fmem_info->phys + fmem_info->size;
}
align = data->align;
break;
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 1806886..7e684c0 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -229,6 +229,19 @@
#define A3XX_VBIF_FIXED_SORT_EN 0x300C
#define A3XX_VBIF_FIXED_SORT_SEL0 0x300D
#define A3XX_VBIF_FIXED_SORT_SEL1 0x300E
+#define A3XX_VBIF_ABIT_SORT 0x301C
+#define A3XX_VBIF_ABIT_SORT_CONF 0x301D
+#define A3XX_VBIF_GATE_OFF_WRREQ_EN 0x302A
+#define A3XX_VBIF_IN_RD_LIM_CONF0 0x302C
+#define A3XX_VBIF_IN_RD_LIM_CONF1 0x302D
+#define A3XX_VBIF_IN_WR_LIM_CONF0 0x3030
+#define A3XX_VBIF_IN_WR_LIM_CONF1 0x3031
+#define A3XX_VBIF_OUT_RD_LIM_CONF0 0x3034
+#define A3XX_VBIF_OUT_WR_LIM_CONF0 0x3035
+#define A3XX_VBIF_DDR_OUT_MAX_BURST 0x3036
+#define A3XX_VBIF_ARB_CTL 0x303C
+#define A3XX_VBIF_OUT_AXI_AOOO_EN 0x305E
+#define A3XX_VBIF_OUT_AXI_AOOO 0x305F
/* Bit flags for RBBM_CTL */
#define RBBM_RBBM_CTL_RESET_PWR_CTR1 (1 << 1)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 06f4a14..73d00b3 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -581,6 +581,7 @@
device->ftbl->irqctrl(device, 0);
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
+ del_timer_sync(&device->idle_timer);
/* Power down the device */
kgsl_pwrctrl_disable(device);
@@ -978,15 +979,6 @@
}
mutex_unlock(&kgsl_driver.process_mutex);
- BUG_ON(!mutex_is_locked(&device->mutex));
- list_for_each_entry(entry, &device->memqueue, list) {
- if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, size)) {
- result = &entry->memdesc;
- return result;
- }
-
- }
-
while (1) {
struct adreno_context *adreno_context = NULL;
context = idr_get_next(&device->context_idr, &next);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index f68bc41..6525d9b 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -130,7 +130,7 @@
/* Use shadow RAM */
#define HLSQ_SHADOW_BASE (0x10000+SSIZE*2)
-#define REG_TO_MEM_LOOP_COUNT_SHIFT 15
+#define REG_TO_MEM_LOOP_COUNT_SHIFT 18
#define BUILD_PC_DRAW_INITIATOR(prim_type, source_select, index_size, \
vis_cull_mode) \
@@ -1109,11 +1109,13 @@
/* Constant save */
cmd = rmw_regtomem(cmd, A3XX_SP_VS_CTRL_REG1, 0x000003ff,
- 17, (HLSQ_SHADOW_BASE + 0x2000) / 4,
+ 2 + REG_TO_MEM_LOOP_COUNT_SHIFT,
+ (HLSQ_SHADOW_BASE + 0x2000) / 4,
drawctxt->constant_save_commands[1].gpuaddr);
cmd = rmw_regtomem(cmd, A3XX_SP_FS_CTRL_REG1, 0x000003ff,
- 17, (HLSQ_SHADOW_BASE + 0x2000 + SSIZE) / 4,
+ 2 + REG_TO_MEM_LOOP_COUNT_SHIFT,
+ (HLSQ_SHADOW_BASE + 0x2000 + SSIZE) / 4,
drawctxt->constant_save_commands[2].gpuaddr);
cmd = rmw_regtomem(cmd, A3XX_SP_FS_OBJ_OFFSET_REG, 0x00ff0000,
@@ -2546,14 +2548,29 @@
0x00000001);
msleep(20);
- /*
- * enable fixed master AXI port of 0x0 for all clients to keep
- * traffic from going to random places
- */
+ /* Set up 16 deep read/write request queues */
- adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_EN, 0x0001003F);
- adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_SEL0, 0x00000000);
- adreno_regwrite(device, A3XX_VBIF_FIXED_SORT_SEL1, 0x00000000);
+ adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
+ adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
+ adreno_regwrite(device, A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
+ adreno_regwrite(device, A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
+ adreno_regwrite(device, A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000303);
+ adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
+ adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
+
+ /* Enable WR-REQ */
+ adreno_regwrite(device, A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x000000FF);
+
+ /* Set up round robin arbitration between both AXI ports */
+ adreno_regwrite(device, A3XX_VBIF_ARB_CTL, 0x00000030);
+
+ /* Set up AOOO */
+ adreno_regwrite(device, A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003C);
+ adreno_regwrite(device, A3XX_VBIF_OUT_AXI_AOOO, 0x003C003C);
+
+ /* Enable 1K sort */
+ adreno_regwrite(device, A3XX_VBIF_ABIT_SORT, 0x000000FF);
+ adreno_regwrite(device, A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
/* Make all blocks contribute to the GPU BUSY perf counter */
adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 98e3810..7902f30 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -876,6 +876,7 @@
int adreno_postmortem_dump(struct kgsl_device *device, int manual)
{
+ bool saved_nap;
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
BUG_ON(device == NULL);
@@ -907,17 +908,28 @@
KGSL_LOG_DUMP(device, "BUS CLK = %lu ",
kgsl_get_clkrate(pwr->ebi1_clk));
- /*
- * Disable the irq, idle timer, and workqueue so we don't
- * get interrupted
- */
- kgsl_pwrctrl_stop_work(device);
+ /* Disable the idle timer so we don't get interrupted */
+ del_timer_sync(&device->idle_timer);
+ mutex_unlock(&device->mutex);
+ flush_workqueue(device->work_queue);
+ mutex_lock(&device->mutex);
+
+ /* Turn off napping to make sure we have the clocks full
+ attention through the following process */
+ saved_nap = device->pwrctrl.nap_allowed;
+ device->pwrctrl.nap_allowed = false;
/* Force on the clocks */
- kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON);
+ kgsl_pwrctrl_wake(device);
+
+ /* Disable the irq */
+ kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
adreno_dump(device);
+ /* Restore nap mode */
+ device->pwrctrl.nap_allowed = saved_nap;
+
/* On a manual trigger, turn on the interrupts and put
the clocks to sleep. They will recover themselves
on the next event. For a hang, leave things as they
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index caedf26..0361387 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -64,7 +64,7 @@
#define GSL_RB_WRITE(ring, gpuaddr, data) \
do { \
- writel_relaxed(data, ring); \
+ *ring = data; \
wmb(); \
kgsl_cffdump_setmem(gpuaddr, data, 4); \
ring++; \
@@ -93,7 +93,7 @@
#define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */
#define GSL_RB_GET_READPTR(rb, data) \
do { \
- *(data) = readl_relaxed(&(rb)->memptrs->rptr); \
+ *(data) = rb->memptrs->rptr; \
} while (0)
#else
#define GSL_RB_CNTL_NO_UPDATE 0x1 /* disable */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1a0a17d..9333dca 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -49,20 +49,20 @@
static struct ion_client *kgsl_ion_client;
-#ifdef CONFIG_GENLOCK
-
/**
* kgsl_add_event - Add a new timstamp event for the KGSL device
* @device - KGSL device for the new event
* @ts - the timestamp to trigger the event on
* @cb - callback function to call when the timestamp expires
* @priv - private data for the specific event type
+ * @owner - driver instance that owns this event
*
* @returns - 0 on success or error code on failure
*/
static int kgsl_add_event(struct kgsl_device *device, u32 ts,
- void (*cb)(struct kgsl_device *, void *, u32), void *priv)
+ void (*cb)(struct kgsl_device *, void *, u32), void *priv,
+ struct kgsl_device_private *owner)
{
struct kgsl_event *event;
struct list_head *n;
@@ -86,6 +86,7 @@
event->timestamp = ts;
event->priv = priv;
event->func = cb;
+ event->owner = owner;
/* Add the event in order to the list */
@@ -105,7 +106,36 @@
queue_work(device->work_queue, &device->ts_expired_ws);
return 0;
}
-#endif
+
+/**
+ * kgsl_cancel_events - Cancel all events for a process
+ * @device - KGSL device for the events to cancel
+ * @owner - driver instance that owns the events to cancel
+ *
+ */
+static void kgsl_cancel_events(struct kgsl_device *device,
+ struct kgsl_device_private *owner)
+{
+ struct kgsl_event *event, *event_tmp;
+ unsigned int cur = device->ftbl->readtimestamp(device,
+ KGSL_TIMESTAMP_RETIRED);
+
+ list_for_each_entry_safe(event, event_tmp, &device->events, list) {
+ if (event->owner != owner)
+ continue;
+ /*
+ * "cancel" the events by calling their callback.
+ * Currently, events are used for lock and memory
+ * management, so if the process is dying the right
+ * thing to do is release or free.
+ */
+ if (event->func)
+ event->func(device, event->priv, cur);
+
+ list_del(&event->list);
+ kfree(event);
+ }
+}
static inline struct kgsl_mem_entry *
kgsl_mem_entry_create(void)
@@ -227,44 +257,10 @@
idr_remove(&dev_priv->device->context_idr, id);
}
-/* to be called when a process is destroyed, this walks the memqueue and
- * frees any entryies that belong to the dying process
- */
-static void kgsl_memqueue_cleanup(struct kgsl_device *device,
- struct kgsl_process_private *private)
-{
- struct kgsl_mem_entry *entry, *entry_tmp;
-
- if (!private)
- return;
-
- BUG_ON(!mutex_is_locked(&device->mutex));
-
- list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) {
- if (entry->priv == private) {
- list_del(&entry->list);
- kgsl_mem_entry_put(entry);
- }
- }
-}
-
-static void kgsl_memqueue_freememontimestamp(struct kgsl_device *device,
- struct kgsl_mem_entry *entry,
- uint32_t timestamp,
- enum kgsl_timestamp_type type)
-{
- BUG_ON(!mutex_is_locked(&device->mutex));
-
- entry->free_timestamp = timestamp;
-
- list_add_tail(&entry->list, &device->memqueue);
-}
-
static void kgsl_timestamp_expired(struct work_struct *work)
{
struct kgsl_device *device = container_of(work, struct kgsl_device,
ts_expired_ws);
- struct kgsl_mem_entry *entry, *entry_tmp;
struct kgsl_event *event, *event_tmp;
uint32_t ts_processed;
@@ -274,15 +270,6 @@
ts_processed = device->ftbl->readtimestamp(device,
KGSL_TIMESTAMP_RETIRED);
- /* Flush the freememontimestamp queue */
- list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) {
- if (timestamp_cmp(ts_processed, entry->free_timestamp) < 0)
- break;
-
- list_del(&entry->list);
- kgsl_mem_entry_put(entry);
- }
-
/* Process expired events */
list_for_each_entry_safe(event, event_tmp, &device->events, list) {
if (timestamp_cmp(ts_processed, event->timestamp) < 0)
@@ -404,6 +391,8 @@
wait_for_completion(&device->suspend_gate);
mutex_lock(&device->mutex);
}
+ /* Don't let the timer wake us during suspended sleep. */
+ del_timer_sync(&device->idle_timer);
switch (device->state) {
case KGSL_STATE_INIT:
break;
@@ -415,7 +404,6 @@
/* Get the completion ready to be waited upon. */
INIT_COMPLETION(device->hwaccess_gate);
device->ftbl->suspend_context(device);
- kgsl_pwrctrl_stop_work(device);
device->ftbl->stop(device);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND);
break;
@@ -498,7 +486,6 @@
struct kgsl_device, display_off);
KGSL_PWR_WARN(device, "early suspend start\n");
mutex_lock(&device->mutex);
- kgsl_pwrctrl_stop_work(device);
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
kgsl_pwrctrl_sleep(device);
mutex_unlock(&device->mutex);
@@ -645,14 +632,13 @@
device->open_count--;
if (device->open_count == 0) {
- kgsl_pwrctrl_stop_work(device);
result = device->ftbl->stop(device);
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
}
/* clean up any to-be-freed entries that belong to this
* process and this device
*/
- kgsl_memqueue_cleanup(device, private);
+ kgsl_cancel_events(device, dev_priv);
mutex_unlock(&device->mutex);
kfree(dev_priv);
@@ -997,6 +983,16 @@
return 0;
}
+static void kgsl_freemem_event_cb(struct kgsl_device *device,
+ void *priv, u32 timestamp)
+{
+ struct kgsl_mem_entry *entry = priv;
+ spin_lock(&entry->priv->mem_lock);
+ list_del(&entry->list);
+ spin_unlock(&entry->priv->mem_lock);
+ kgsl_mem_entry_put(entry);
+}
+
static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private
*dev_priv, unsigned int cmd,
void *data)
@@ -1007,13 +1003,11 @@
spin_lock(&dev_priv->process_priv->mem_lock);
entry = kgsl_sharedmem_find(dev_priv->process_priv, param->gpuaddr);
- if (entry)
- list_del(&entry->list);
spin_unlock(&dev_priv->process_priv->mem_lock);
if (entry) {
- kgsl_memqueue_freememontimestamp(dev_priv->device, entry,
- param->timestamp, param->type);
+ result = kgsl_add_event(dev_priv->device, param->timestamp,
+ kgsl_freemem_event_cb, entry, dev_priv);
} else {
KGSL_DRV_ERR(dev_priv->device,
"invalid gpuaddr %08x\n", param->gpuaddr);
@@ -1763,6 +1757,7 @@
* @timestamp - Timestamp to trigger the event
* @data - User space buffer containing struct kgsl_genlock_event_priv
* @len - length of the userspace buffer
+ * @owner - driver instance that owns this event
* @returns 0 on success or error code on error
*
* Attack to a genlock handle and register an event to release the
@@ -1770,7 +1765,8 @@
*/
static int kgsl_add_genlock_event(struct kgsl_device *device,
- u32 timestamp, void __user *data, int len)
+ u32 timestamp, void __user *data, int len,
+ struct kgsl_device_private *owner)
{
struct kgsl_genlock_event_priv *event;
struct kgsl_timestamp_event_genlock priv;
@@ -1795,7 +1791,8 @@
return ret;
}
- ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event);
+ ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event,
+ owner);
if (ret)
kfree(event);
@@ -1803,7 +1800,8 @@
}
#else
static long kgsl_add_genlock_event(struct kgsl_device *device,
- u32 timestamp, void __user *data, int len)
+ u32 timestamp, void __user *data, int len,
+ struct kgsl_device_private *owner)
{
return -EINVAL;
}
@@ -1826,7 +1824,8 @@
switch (param->type) {
case KGSL_TIMESTAMP_EVENT_GENLOCK:
ret = kgsl_add_genlock_event(dev_priv->device,
- param->timestamp, param->priv, param->len);
+ param->timestamp, param->priv, param->len,
+ dev_priv);
break;
default:
ret = -EINVAL;
@@ -2183,7 +2182,6 @@
INIT_WORK(&device->idle_check_ws, kgsl_idle_check);
INIT_WORK(&device->ts_expired_ws, kgsl_timestamp_expired);
- INIT_LIST_HEAD(&device->memqueue);
INIT_LIST_HEAD(&device->events);
ret = kgsl_mmu_init(device);
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 1135adb..3e8aac3 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -199,7 +199,7 @@
if (ts_diff == 0)
return 0;
- return ((ts_diff > 0) || (ts_diff < -20000)) ? 1 : -1;
+ return ((ts_diff > 0) || (ts_diff < -25000)) ? 1 : -1;
}
static inline void
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 8ea5279..2fb1e43 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -126,6 +126,7 @@
void (*func)(struct kgsl_device *, void *, u32);
void *priv;
struct list_head list;
+ struct kgsl_device_private *owner;
};
@@ -154,7 +155,6 @@
uint32_t state;
uint32_t requested_state;
- struct list_head memqueue;
unsigned int active_cnt;
struct completion suspend_gate;
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index fe5677e..97b5ef1 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -382,26 +382,27 @@
kgsl_pt_map_set(struct kgsl_gpummu_pt *pt, uint32_t pte, uint32_t val)
{
uint32_t *baseptr = (uint32_t *)pt->base.hostptr;
-
- writel_relaxed(val, &baseptr[pte]);
+ BUG_ON(pte*sizeof(uint32_t) >= pt->base.size);
+ baseptr[pte] = val;
}
static inline uint32_t
kgsl_pt_map_get(struct kgsl_gpummu_pt *pt, uint32_t pte)
{
uint32_t *baseptr = (uint32_t *)pt->base.hostptr;
- return readl_relaxed(&baseptr[pte]) & GSL_PT_PAGE_ADDR_MASK;
+ BUG_ON(pte*sizeof(uint32_t) >= pt->base.size);
+ return baseptr[pte] & GSL_PT_PAGE_ADDR_MASK;
}
static unsigned int kgsl_gpummu_pt_get_flags(struct kgsl_pagetable *pt,
enum kgsl_deviceid id)
{
unsigned int result = 0;
- struct kgsl_gpummu_pt *gpummu_pt = (struct kgsl_gpummu_pt *)
- pt->priv;
+ struct kgsl_gpummu_pt *gpummu_pt;
if (pt == NULL)
return 0;
+ gpummu_pt = pt->priv;
spin_lock(&pt->lock);
if (gpummu_pt->tlb_flags && (1<<id)) {
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index e4e561c..194067b 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -24,11 +24,23 @@
#include "kgsl_mmu.h"
#include "kgsl_sharedmem.h"
+/*
+ * On APQ8064, KGSL can control a maximum of 4 IOMMU devices: 2 user and 2
+ * priv domains, 1 each for each of the AXI ports attached to the GPU. 8660
+ * and 8960 have only one AXI port, so maximum allowable IOMMU devices for those
+ * chips is 2.
+ */
+
+#define KGSL_IOMMU_MAX_DEV 4
+
+struct kgsl_iommu_device {
+ struct device *dev;
+ int attached;
+};
+
struct kgsl_iommu {
- struct device *iommu_user_dev;
- int iommu_user_dev_attached;
- struct device *iommu_priv_dev;
- int iommu_priv_dev_attached;
+ struct kgsl_iommu_device dev[KGSL_IOMMU_MAX_DEV];
+ int dev_count;
};
static int kgsl_iommu_pt_equal(struct kgsl_pagetable *pt,
@@ -58,89 +70,101 @@
{
struct iommu_domain *domain;
struct kgsl_iommu *iommu = mmu->priv;
+ int i;
BUG_ON(mmu->hwpagetable == NULL);
BUG_ON(mmu->hwpagetable->priv == NULL);
domain = mmu->hwpagetable->priv;
- if (iommu->iommu_user_dev_attached) {
- iommu_detach_device(domain, iommu->iommu_user_dev);
- iommu->iommu_user_dev_attached = 0;
+ for (i = 0; i < iommu->dev_count; i++) {
+ iommu_detach_device(domain, iommu->dev[i].dev);
+ iommu->dev[i].attached = 0;
KGSL_MEM_INFO(mmu->device,
- "iommu %p detached from user dev of MMU: %p\n",
- domain, mmu);
- }
- if (iommu->iommu_priv_dev_attached) {
- iommu_detach_device(domain, iommu->iommu_priv_dev);
- iommu->iommu_priv_dev_attached = 0;
- KGSL_MEM_INFO(mmu->device,
- "iommu %p detached from priv dev of MMU: %p\n",
- domain, mmu);
+ "iommu %p detached from user dev of MMU: %p\n",
+ domain, mmu);
}
}
static int kgsl_attach_pagetable_iommu_domain(struct kgsl_mmu *mmu)
{
struct iommu_domain *domain;
- int ret = 0;
struct kgsl_iommu *iommu = mmu->priv;
+ int i, ret = 0;
BUG_ON(mmu->hwpagetable == NULL);
BUG_ON(mmu->hwpagetable->priv == NULL);
domain = mmu->hwpagetable->priv;
- if (iommu->iommu_user_dev && !iommu->iommu_user_dev_attached) {
- ret = iommu_attach_device(domain, iommu->iommu_user_dev);
- if (ret) {
- KGSL_MEM_ERR(mmu->device,
- "Failed to attach device, err %d\n", ret);
- goto done;
- }
- iommu->iommu_user_dev_attached = 1;
- KGSL_MEM_INFO(mmu->device,
- "iommu %p attached to user dev of MMU: %p\n",
+ for (i = 0; i < iommu->dev_count; i++) {
+ if (iommu->dev[i].attached == 0) {
+ ret = iommu_attach_device(domain, iommu->dev[i].dev);
+ if (ret) {
+ KGSL_MEM_ERR(mmu->device,
+ "Failed to attach device, err %d\n",
+ ret);
+ goto done;
+ }
+
+ iommu->dev[i].attached = 1;
+ KGSL_MEM_INFO(mmu->device,
+ "iommu %p detached from user dev of MMU: %p\n",
domain, mmu);
- }
- if (iommu->iommu_priv_dev && !iommu->iommu_priv_dev_attached) {
- ret = iommu_attach_device(domain, iommu->iommu_priv_dev);
- if (ret) {
- KGSL_MEM_ERR(mmu->device,
- "Failed to attach device, err %d\n", ret);
- iommu_detach_device(domain, iommu->iommu_user_dev);
- iommu->iommu_user_dev_attached = 0;
- goto done;
}
- iommu->iommu_priv_dev_attached = 1;
- KGSL_MEM_INFO(mmu->device,
- "iommu %p attached to priv dev of MMU: %p\n",
- domain, mmu);
}
+
done:
return ret;
}
+static int _get_iommu_ctxs(struct kgsl_iommu *iommu, struct kgsl_device *device,
+ struct kgsl_device_iommu_data *data)
+{
+ int i;
+
+ for (i = 0; i < data->iommu_ctx_count; i++) {
+ if (iommu->dev_count >= KGSL_IOMMU_MAX_DEV) {
+ KGSL_CORE_ERR("Tried to attach too many IOMMU "
+ "devices\n");
+ return -ENOMEM;
+ }
+
+ if (!data->iommu_ctx_names[i])
+ continue;
+
+ iommu->dev[iommu->dev_count].dev =
+ msm_iommu_get_ctx(data->iommu_ctx_names[i]);
+ if (iommu->dev[iommu->dev_count].dev == NULL) {
+ KGSL_CORE_ERR("Failed to iommu dev handle for "
+ "device %s\n", data->iommu_ctx_names[i]);
+ return -EINVAL;
+ }
+
+ iommu->dev_count++;
+ }
+
+ return 0;
+}
+
static int kgsl_get_iommu_ctxt(struct kgsl_iommu *iommu,
struct kgsl_device *device)
{
- int status = 0;
struct platform_device *pdev =
container_of(device->parentdev, struct platform_device, dev);
struct kgsl_device_platform_data *pdata_dev = pdev->dev.platform_data;
- if (pdata_dev->iommu_user_ctx_name)
- iommu->iommu_user_dev = msm_iommu_get_ctx(
- pdata_dev->iommu_user_ctx_name);
- if (pdata_dev->iommu_priv_ctx_name)
- iommu->iommu_priv_dev = msm_iommu_get_ctx(
- pdata_dev->iommu_priv_ctx_name);
- if (!iommu->iommu_user_dev) {
- KGSL_CORE_ERR("Failed to get user iommu dev handle for "
- "device %s\n",
- pdata_dev->iommu_user_ctx_name);
- status = -EINVAL;
+ int i, ret = 0;
+
+ /* Go through the IOMMU data and attach all the domains */
+
+ for (i = 0; i < pdata_dev->iommu_count; i++) {
+ ret = _get_iommu_ctxs(iommu, device,
+ &pdata_dev->iommu_data[i]);
+ if (ret)
+ break;
}
- return status;
+
+ return ret;
}
static void kgsl_iommu_setstate(struct kgsl_device *device,
@@ -182,8 +206,6 @@
return -ENOMEM;
}
- iommu->iommu_priv_dev_attached = 0;
- iommu->iommu_user_dev_attached = 0;
status = kgsl_get_iommu_ctxt(iommu, device);
if (status) {
kfree(iommu);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 1ef71a4..b671f86 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -66,8 +66,17 @@
struct kgsl_pwrlevel *pwrlevel = &pwr->pwrlevels[new_level];
pwr->active_pwrlevel = new_level;
if ((test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags)) ||
- (device->state == KGSL_STATE_NAP))
+ (device->state == KGSL_STATE_NAP)) {
+ /*
+ * On some platforms, instability is caused on
+ * changing clock freq when the core is busy.
+ * Idle the gpu core before changing the clock freq.
+ */
+ if (pwr->idle_needed == true)
+ device->ftbl->idle(device,
+ KGSL_TIMEOUT_DEFAULT);
clk_set_rate(pwr->grp_clks[0], pwrlevel->gpu_freq);
+ }
if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) {
if (pwr->pcl)
msm_bus_scale_client_update_request(pwr->pcl,
@@ -362,7 +371,6 @@
}
}
}
-EXPORT_SYMBOL(kgsl_pwrctrl_clk);
void kgsl_pwrctrl_axi(struct kgsl_device *device, int state)
{
@@ -499,6 +507,7 @@
pwr->power_flags = 0;
pwr->nap_allowed = pdata->nap_allowed;
+ pwr->idle_needed = pdata->idle_needed;
pwr->interval_timeout = pdata->idle_timeout;
pwr->ebi1_clk = clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(pwr->ebi1_clk))
@@ -870,16 +879,6 @@
}
EXPORT_SYMBOL(kgsl_pwrctrl_disable);
-void kgsl_pwrctrl_stop_work(struct kgsl_device *device)
-{
- del_timer_sync(&device->idle_timer);
- kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
- mutex_unlock(&device->mutex);
- flush_workqueue(device->work_queue);
- mutex_lock(&device->mutex);
-}
-EXPORT_SYMBOL(kgsl_pwrctrl_stop_work);
-
void kgsl_pwrctrl_set_state(struct kgsl_device *device, unsigned int state)
{
trace_kgsl_pwr_set_state(device, state);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 23e2bd1..f474c21 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -50,6 +50,7 @@
struct regulator *gpu_reg;
uint32_t pcl;
unsigned int nap_allowed;
+ unsigned int idle_needed;
const char *regulator_name;
const char *irq_name;
s64 time;
@@ -58,7 +59,6 @@
};
void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
-void kgsl_pwrctrl_clk(struct kgsl_device *device, int state);
int kgsl_pwrctrl_init(struct kgsl_device *device);
void kgsl_pwrctrl_close(struct kgsl_device *device);
void kgsl_timer(unsigned long data);
@@ -73,7 +73,6 @@
void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device);
void kgsl_pwrctrl_enable(struct kgsl_device *device);
void kgsl_pwrctrl_disable(struct kgsl_device *device);
-void kgsl_pwrctrl_stop_work(struct kgsl_device *device);
static inline unsigned long kgsl_get_clkrate(struct clk *clk)
{
return (clk != NULL) ? clk_get_rate(clk) : 0;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 7211879..389ed6d 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -636,13 +636,17 @@
uint32_t *dst,
unsigned int offsetbytes)
{
+ uint32_t *src;
BUG_ON(memdesc == NULL || memdesc->hostptr == NULL || dst == NULL);
- WARN_ON(offsetbytes + sizeof(unsigned int) > memdesc->size);
+ WARN_ON(offsetbytes % sizeof(uint32_t) != 0);
+ if (offsetbytes % sizeof(uint32_t) != 0)
+ return -EINVAL;
- if (offsetbytes + sizeof(unsigned int) > memdesc->size)
+ WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
+ if (offsetbytes + sizeof(uint32_t) > memdesc->size)
return -ERANGE;
-
- *dst = readl_relaxed(memdesc->hostptr + offsetbytes);
+ src = (uint32_t *)(memdesc->hostptr + offsetbytes);
+ *dst = *src;
return 0;
}
EXPORT_SYMBOL(kgsl_sharedmem_readl);
@@ -652,12 +656,19 @@
unsigned int offsetbytes,
uint32_t src)
{
+ uint32_t *dst;
BUG_ON(memdesc == NULL || memdesc->hostptr == NULL);
- BUG_ON(offsetbytes + sizeof(unsigned int) > memdesc->size);
+ WARN_ON(offsetbytes % sizeof(uint32_t) != 0);
+ if (offsetbytes % sizeof(uint32_t) != 0)
+ return -EINVAL;
+ WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
+ if (offsetbytes + sizeof(uint32_t) > memdesc->size)
+ return -ERANGE;
kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes,
- src, sizeof(uint));
- writel_relaxed(src, memdesc->hostptr + offsetbytes);
+ src, sizeof(uint32_t));
+ dst = (uint32_t *)(memdesc->hostptr + offsetbytes);
+ *dst = src;
return 0;
}
EXPORT_SYMBOL(kgsl_sharedmem_writel);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 718fac9..cb3da90 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -584,6 +584,8 @@
device->ftbl->irqctrl(device, 0);
z180_idle(device, KGSL_TIMEOUT_DEFAULT);
+ del_timer_sync(&device->idle_timer);
+
kgsl_mmu_stop(device);
/* Disable the clocks before the power rail. */
diff --git a/drivers/hwmon/msm_adc.c b/drivers/hwmon/msm_adc.c
index b8d581e..39bfc3a 100644
--- a/drivers/hwmon/msm_adc.c
+++ b/drivers/hwmon/msm_adc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1380,7 +1380,7 @@
},
};
-static int msm_adc_probe(struct platform_device *pdev)
+static int __devinit msm_adc_probe(struct platform_device *pdev)
{
struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
struct msm_adc_drv *msm_adc;
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 5f8faee..0902c61 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -165,6 +165,7 @@
};
static struct pm8xxx_adc *pmic_adc;
+static struct regulator *pa_therm;
static struct pm8xxx_adc_scale_fn adc_scale_fn[] = {
[ADC_SCALE_DEFAULT] = {pm8xxx_adc_scale_default},
@@ -238,26 +239,21 @@
static int32_t pm8xxx_adc_patherm_power(bool on)
{
- static struct regulator *pa_therm;
- struct pm8xxx_adc *adc_pmic = pmic_adc;
int rc = 0;
- if (on) {
- pa_therm = regulator_get(adc_pmic->dev,
- "pa_therm");
- if (IS_ERR(pa_therm)) {
- rc = PTR_ERR(pa_therm);
- pr_err("failed to request pa_therm vreg "
- "with error %d\n", rc);
- return rc;
- }
+ if (!pa_therm) {
+ pr_err("pm8xxx adc pa_therm not valid\n");
+ return -EINVAL;
+ }
+
+ if (on) {
rc = regulator_set_voltage(pa_therm,
PM8XXX_ADC_PA_THERM_VREG_UV_MIN,
PM8XXX_ADC_PA_THERM_VREG_UV_MAX);
if (rc < 0) {
pr_err("failed to set the voltage for "
"pa_therm with error %d\n", rc);
- goto fail;
+ return rc;
}
rc = regulator_set_optimum_mode(pa_therm,
@@ -265,25 +261,25 @@
if (rc < 0) {
pr_err("failed to set optimum mode for "
"pa_therm with error %d\n", rc);
- goto fail;
+ return rc;
}
- if (regulator_enable(pa_therm)) {
- pr_err("failed to enable pa_therm vreg with "
- "error %d\n", rc);
- goto fail;
+ rc = regulator_enable(pa_therm);
+ if (rc < 0) {
+ pr_err("failed to enable pa_therm vreg "
+ "with error %d\n", rc);
+ return rc;
}
} else {
- if (pa_therm != NULL) {
- regulator_disable(pa_therm);
- regulator_put(pa_therm);
+ rc = regulator_disable(pa_therm);
+ if (rc < 0) {
+ pr_err("failed to disable pa_therm vreg "
+ "with error %d\n", rc);
+ return rc;
}
}
return rc;
-fail:
- regulator_put(pa_therm);
- return rc;
}
static int32_t pm8xxx_adc_channel_power_enable(uint32_t channel,
@@ -293,7 +289,7 @@
switch (channel)
case ADC_MPP_1_AMUX8:
- pm8xxx_adc_patherm_power(power_cntrl);
+ rc = pm8xxx_adc_patherm_power(power_cntrl);
return rc;
}
@@ -769,6 +765,9 @@
struct pm8xxx_adc *adc_pmic = pmic_adc;
int rc = 0;
+ if (!pm8xxx_adc_initialized)
+ return -ENODEV;
+
if (!adc_pmic->mpp_base) {
rc = -EINVAL;
pr_info("PM8xxx MPP base invalid with error %d\n", rc);
@@ -1138,6 +1137,10 @@
wake_lock_destroy(&adc_pmic->adc_wakelock);
platform_set_drvdata(pdev, NULL);
pmic_adc = NULL;
+ if (!pa_therm) {
+ regulator_put(pa_therm);
+ pa_therm = NULL;
+ }
for (i = 0; i < adc_pmic->adc_num_board_channel; i++)
device_remove_file(adc_pmic->dev,
&adc_pmic->sens_attr[i].dev_attr);
@@ -1252,6 +1255,13 @@
dev_err(&pdev->dev, "failed to initialize pm8xxx hwmon adc\n");
}
adc_pmic->hwmon = hwmon_device_register(adc_pmic->dev);
+
+ pa_therm = regulator_get(adc_pmic->dev, "pa_therm");
+ if (IS_ERR(pa_therm)) {
+ rc = PTR_ERR(pa_therm);
+ pr_err("failed to request pa_therm vreg with error %d\n", rc);
+ pa_therm = NULL;
+ }
return 0;
}
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index c8b4707..4988313 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -324,13 +324,13 @@
{
dev->clk_state = state;
if (state != 0) {
- clk_prepare_enable(dev->clk);
- clk_prepare_enable(dev->pclk);
+ clk_enable(dev->clk);
+ clk_enable(dev->pclk);
} else {
qup_update_state(dev, QUP_RESET_STATE);
- clk_disable_unprepare(dev->clk);
+ clk_disable(dev->clk);
qup_config_core_on_en(dev);
- clk_disable_unprepare(dev->pclk);
+ clk_disable(dev->pclk);
}
}
@@ -1285,6 +1285,8 @@
dev->suspended = 0;
mutex_init(&dev->mlock);
dev->clk_state = 0;
+ clk_prepare(dev->clk);
+ clk_prepare(dev->pclk);
setup_timer(&dev->pwr_timer, qup_i2c_pwr_timer, (unsigned long) dev);
pm_runtime_set_active(&pdev->dev);
@@ -1344,6 +1346,8 @@
}
free_irq(dev->err_irq, dev);
i2c_del_adapter(&dev->adapter);
+ clk_unprepare(dev->clk);
+ clk_unprepare(dev->pclk);
clk_put(dev->clk);
clk_put(dev->pclk);
qup_i2c_free_gpios(dev);
@@ -1378,6 +1382,8 @@
del_timer_sync(&dev->pwr_timer);
if (dev->clk_state != 0)
qup_i2c_pwr_mgmt(dev, 0);
+ clk_unprepare(dev->clk);
+ clk_unprepare(dev->pclk);
qup_i2c_free_gpios(dev);
return 0;
}
@@ -1387,6 +1393,8 @@
struct platform_device *pdev = to_platform_device(device);
struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
BUG_ON(qup_i2c_request_gpios(dev) != 0);
+ clk_prepare(dev->clk);
+ clk_prepare(dev->pclk);
dev->suspended = 0;
return 0;
}
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index d2a8879..40aae69 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -18,7 +18,7 @@
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/gpio.h>
@@ -611,22 +611,23 @@
if (!finger[id].status)
continue;
- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
- finger[id].status != MXT_RELEASE ?
- finger[id].area : 0);
- input_report_abs(input_dev, ABS_MT_POSITION_X,
- finger[id].x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y,
- finger[id].y);
- input_report_abs(input_dev, ABS_MT_PRESSURE,
- finger[id].status != MXT_RELEASE ?
- finger[id].pressure : 0);
- input_mt_sync(input_dev);
+ input_mt_slot(input_dev, id);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+ finger[id].status != MXT_RELEASE);
- if (finger[id].status == MXT_RELEASE)
- finger[id].status = 0;
- else
+ if (finger[id].status != MXT_RELEASE) {
finger_num++;
+ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+ finger[id].area);
+ input_report_abs(input_dev, ABS_MT_POSITION_X,
+ finger[id].x);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y,
+ finger[id].y);
+ input_report_abs(input_dev, ABS_MT_PRESSURE,
+ finger[id].area);
+ } else {
+ finger[id].status = 0;
+ }
}
input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
@@ -1841,6 +1842,7 @@
0, 255, 0, 0);
/* For multi touch */
+ input_mt_init_slots(input_dev, MXT_MAX_FINGER);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, MXT_MAX_AREA, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
diff --git a/drivers/input/touchscreen/cyttsp-i2c.c b/drivers/input/touchscreen/cyttsp-i2c.c
index a60dbf5..267e481 100644
--- a/drivers/input/touchscreen/cyttsp-i2c.c
+++ b/drivers/input/touchscreen/cyttsp-i2c.c
@@ -710,25 +710,26 @@
else if (!(g_bl_data.bl_status & BL_CHECKSUM_MASK) &&
(appid_lo == ts->platform_data->correct_fw_ver))
fw_upgrade = 1;
- else
- if ((appid_hi == g_bl_data.appid_hi) &&
- (appid_lo == g_bl_data.appid_lo)) {
- if (appver_hi > g_bl_data.appver_hi) {
+ else if ((appid_hi == g_bl_data.appid_hi) &&
+ (appid_lo == g_bl_data.appid_lo))
+ if (appver_hi > g_bl_data.appver_hi)
fw_upgrade = 1;
- } else if ((appver_hi == g_bl_data.appver_hi) &&
- (appver_lo > g_bl_data.appver_lo)) {
- fw_upgrade = 1;
- } else {
- fw_upgrade = 0;
- pr_info("%s: Firmware version "
- "lesser/equal to existing firmware, "
- "upgrade not needed\n", __func__);
- }
- } else {
- fw_upgrade = 0;
- pr_info("%s: Firware versions do not match, "
- "cannot upgrade\n", __func__);
- }
+ else if ((appver_hi == g_bl_data.appver_hi) &&
+ (appver_lo > g_bl_data.appver_lo))
+ fw_upgrade = 1;
+ else {
+ fw_upgrade = 0;
+ pr_info("%s: Firmware version "
+ "lesser/equal to existing firmware, "
+ "upgrade not needed\n", __func__);
+ }
+ else if (appid_lo == ts->platform_data->correct_fw_ver)
+ fw_upgrade = 1;
+ else {
+ fw_upgrade = 0;
+ pr_info("%s: Firmware versions do not match, "
+ "cannot upgrade\n", __func__);
+ }
if (fw_upgrade) {
pr_info("%s: Starting firmware upgrade\n", __func__);
diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c
index 57b11c9..ed6ab4d 100644
--- a/drivers/media/radio/radio-iris-transport.c
+++ b/drivers/media/radio/radio-iris-transport.c
@@ -4,7 +4,7 @@
* FM HCI_SMD ( FM HCI Shared Memory Driver) is Qualcomm's Shared memory driver
* for the HCI protocol. This file is based on drivers/bluetooth/hci_vhci.c
*
- * Copyright (c) 2000-2001, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2000-2001, 2011-2012 Code Aurora Forum. All rights reserved.
*
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
@@ -25,6 +25,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/skbuff.h>
+#include <linux/workqueue.h>
#include <mach/msm_smd.h>
#include <media/radio-iris.h>
@@ -35,6 +36,8 @@
};
struct radio_data hs;
+static struct work_struct *reset_worker;
+
static void radio_hci_smd_destruct(struct radio_hci_dev *hdev)
{
radio_hci_unregister_dev(hs.hdev);
@@ -92,6 +95,30 @@
return 0;
}
+
+static void send_disable_event(struct work_struct *worker)
+{
+ struct sk_buff *skb;
+ unsigned char buf[6] = { 0x0f, 0x04, 0x01, 0x02, 0x4c, 0x00 };
+ int len = sizeof(buf);
+
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (!skb) {
+ FMDERR("Memory not allocated for the socket");
+ return;
+ }
+
+ FMDERR("FM INSERT DISABLE Rx Event");
+
+ memcpy(skb_put(skb, len), buf, len);
+
+ skb_orphan(skb);
+ skb->dev = (struct net_device *)hs.hdev;
+
+ radio_hci_recv_frame(skb);
+ kfree(worker);
+}
+
static void radio_hci_smd_notify_cmd(void *data, unsigned int event)
{
struct radio_hci_dev *hdev = hs.hdev;
@@ -106,7 +133,15 @@
tasklet_schedule(&hs.rx_task);
break;
case SMD_EVENT_OPEN:
+ break;
case SMD_EVENT_CLOSE:
+ reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC);
+ if (!reset_worker) {
+ FMDERR("Out of memory");
+ break;
+ }
+ INIT_WORK(reset_worker, send_disable_event);
+ schedule_work(reset_worker);
break;
default:
break;
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 545c61c..793f063 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -1589,7 +1589,7 @@
if (status)
return;
- iris_q_event(radio, IRIS_EVT_RADIO_READY);
+ iris_q_event(radio, IRIS_EVT_RADIO_DISABLED);
radio_hci_req_complete(hdev, status);
}
@@ -2609,7 +2609,7 @@
} else
retval = -EINVAL;
-
+ break;
case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
if (retval < 0) {
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index ca44c34..e70a0a5 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -33,8 +33,7 @@
MICRON 2M YUV Sensor
config IMX074
bool "Sensor IMX074 (BAYER 13.5M)"
- depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM8960)
- default y
+ depends on MSM_CAMERA
---help---
SONY 13.5 MP Bayer Sensor
config OV5640
@@ -43,6 +42,12 @@
default n
---help---
Omni 5M YUV Sensor
+
+config OV5647
+ bool "Sensor ov5647 (BAYER 5M)"
+ depends on MSM_CAMERA
+ ---help---
+ OV 5M Bayer Sensor with AutoFocus
config WEBCAM_OV7692_QRD
bool "Sensor OV7692 QRD(VGA YUV)"
depends on MSM_CAMERA && ARCH_MSM7X27A && !MSM_CAMERA_V4L2
@@ -51,7 +56,7 @@
Omni Vision VGA YUV Sensor for QRD Devices
config MT9M114
bool "Sensor MT9M114 (YUV 1.26M)"
- depends on MSM_CAMERA && ARCH_MSM8960
+ depends on MSM_CAMERA
---help---
APTINA 1.26 MP yuv Sensor
config WEBCAM_OV7692
@@ -120,8 +125,7 @@
config IMX074_ACT
bool "Actuator IMX074 (BAYER 13.5M)"
- depends on MSM_CAMERA && ARCH_MSM8960
- default y
+ depends on MSM_CAMERA
---help---
Actuator for SONY 13.5 MP Bayer Sensor
@@ -177,8 +181,7 @@
config OV2720
bool "Sensor ov2720 (Omnivision 2MP)"
- depends on MSM_CAMERA && ARCH_MSM8960
- default y
+ depends on MSM_CAMERA
config VB6801
bool "Sensor vb6801"
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index b91449a..8703669 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -44,6 +44,8 @@
obj-$(CONFIG_QS_S5K4E1) += qs_s5k4e1.o qs_s5k4e1_reg.o
obj-$(CONFIG_VB6801) += vb6801.o
obj-$(CONFIG_IMX072) += imx072.o imx072_reg.o
+obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
+obj-$(CONFIG_OV5647) += ov5647.o ov5647_reg.o
obj-$(CONFIG_WEBCAM_OV7692) += ov7692.o
obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd.o
obj-$(CONFIG_OV5640) += ov5640.o
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
index e4d340d4..78eef72 100644
--- a/drivers/media/video/msm/actuators/imx074_act.c
+++ b/drivers/media/video/msm/actuators/imx074_act.c
@@ -197,6 +197,11 @@
(struct v4l2_subdev *)sdev);
}
+static int imx074_act_power_down(void *act_info)
+{
+ return (int) msm_actuator_af_power_down(&imx074_act_t);
+}
+
static struct msm_actuator_ctrl_t imx074_act_t = {
.i2c_driver = &imx074_act_i2c_driver,
.i2c_addr = 0xE4,
@@ -205,6 +210,7 @@
.a_init_table = imx074_i2c_add_driver_table,
.a_create_subdevice = imx074_act_create_subdevice,
.a_config = imx074_act_config,
+ .a_power_down = imx074_act_power_down,
},
.i2c_client = {
@@ -238,6 +244,10 @@
.f_pix_den = 10,
.total_f_dist_num = 197681,
.total_f_dist_den = 1000,
+ .hor_view_angle_num = 548,
+ .hor_view_angle_den = 10,
+ .ver_view_angle_num = 425,
+ .ver_view_angle_den = 10,
},
/* Initialize scenario */
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 7a0ee4d..d247467 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -138,6 +138,10 @@
{"csi_pclk", -1},
};
+static struct camera_vreg_t csid_vreg_info[] = {
+ {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+};
+
static int msm_csid_init(struct v4l2_subdev *sd, uint32_t *csid_version)
{
int rc = 0;
@@ -155,11 +159,25 @@
return rc;
}
+ rc = msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+ ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator on failed\n", __func__);
+ goto vreg_config_failed;
+ }
+
+ rc = msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+ ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto vreg_enable_failed;
+ }
+
rc = msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 1);
if (rc < 0) {
- iounmap(csid_dev->base);
- return rc;
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto clk_enable_failed;
}
#if DBG_CSID
@@ -167,8 +185,17 @@
#endif
*csid_version = csid_dev->hw_version;
-
return 0;
+
+clk_enable_failed:
+ msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+ ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+vreg_enable_failed:
+ msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+ ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+vreg_config_failed:
+ iounmap(csid_dev->base);
+ return rc;
}
static int msm_csid_release(struct v4l2_subdev *sd)
@@ -183,6 +210,12 @@
msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
+ msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+ ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+
+ msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
+ ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+
iounmap(csid_dev->base);
return 0;
}
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/video/msm/csi/msm_csid.h
index f90abf2..105cd49 100644
--- a/drivers/media/video/msm/csi/msm_csid.h
+++ b/drivers/media/video/msm/csi/msm_csid.h
@@ -23,6 +23,7 @@
struct resource *mem;
struct resource *irq;
struct resource *io;
+ struct regulator *csi_vdd;
void __iomem *base;
struct mutex mutex;
uint32_t hw_version;
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index 109b3dd..315cca7 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -79,21 +79,14 @@
msm_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
for (i = 0; i < csiphy_params->lane_cnt; i++) {
- msm_io_w(0x00, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
- msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+ msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
msm_io_w(csiphy_params->settle_cnt,
csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*i);
- msm_io_w(0x00000052,
- csiphybase + MIPI_CSIPHY_LNn_CFG5_ADDR + 0x40*i);
}
- msm_io_w(0x00000000, csiphybase + MIPI_CSIPHY_LNCK_CFG1_ADDR);
- msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+ msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
msm_io_w(csiphy_params->settle_cnt,
csiphybase + MIPI_CSIPHY_LNCK_CFG3_ADDR);
- msm_io_w(0x5, csiphybase + MIPI_CSIPHY_LNCK_CFG4_ADDR);
- msm_io_w(0x2, csiphybase + MIPI_CSIPHY_LNCK_CFG5_ADDR);
- msm_io_w(0x0, csiphybase + 0x128);
msm_io_w(0x24,
csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR);
diff --git a/drivers/media/video/msm/io/Makefile b/drivers/media/video/msm/io/Makefile
index 584738d..c567be2 100644
--- a/drivers/media/video/msm/io/Makefile
+++ b/drivers/media/video/msm/io/Makefile
@@ -1,3 +1,4 @@
GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_eeprom.o
+EXTRA_CFLAGS += -Idrivers/media/video/msm
+obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_eeprom.o msm_camera_i2c_mux.o
obj-$(CONFIG_MSM_CAMERA) += msm_io_util.o
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.c b/drivers/media/video/msm/io/msm_camera_i2c_mux.c
new file mode 100644
index 0000000..ad3128b
--- /dev/null
+++ b/drivers/media/video/msm/io/msm_camera_i2c_mux.c
@@ -0,0 +1,186 @@
+/* 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/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include "msm.h"
+#include "msm_camera_i2c_mux.h"
+
+static int msm_i2c_mux_config(struct i2c_mux_device *mux_device, uint8_t *mode)
+{
+ uint32_t val;
+ val = msm_io_r(mux_device->ctl_base);
+ if (*mode == MODE_DUAL) {
+ msm_io_w(val | 0x3, mux_device->ctl_base);
+ } else if (*mode == MODE_L) {
+ msm_io_w(((val | 0x2) & ~(0x1)), mux_device->ctl_base);
+ val = msm_io_r(mux_device->ctl_base);
+ CDBG("the camio mode config left value is %d\n", val);
+ } else {
+ msm_io_w(((val | 0x1) & ~(0x2)), mux_device->ctl_base);
+ val = msm_io_r(mux_device->ctl_base);
+ CDBG("the camio mode config right value is %d\n", val);
+ }
+ return 0;
+}
+
+static int msm_i2c_mux_init(struct i2c_mux_device *mux_device)
+{
+ int rc = 0, val = 0;
+ if (mux_device->use_count == 0) {
+ mux_device->ctl_base = ioremap(mux_device->ctl_mem->start,
+ resource_size(mux_device->ctl_mem));
+ if (!mux_device->ctl_base) {
+ rc = -ENOMEM;
+ return rc;
+ }
+ mux_device->rw_base = ioremap(mux_device->rw_mem->start,
+ resource_size(mux_device->rw_mem));
+ if (!mux_device->rw_base) {
+ rc = -ENOMEM;
+ iounmap(mux_device->ctl_base);
+ return rc;
+ }
+ val = msm_io_r(mux_device->rw_base);
+ msm_io_w((val | 0x200), mux_device->rw_base);
+ }
+ mux_device->use_count++;
+ return 0;
+};
+
+static int msm_i2c_mux_release(struct i2c_mux_device *mux_device)
+{
+ int val = 0;
+ mux_device->use_count--;
+ if (mux_device->use_count == 0) {
+ val = msm_io_r(mux_device->rw_base);
+ msm_io_w((val & ~0x200), mux_device->rw_base);
+ iounmap(mux_device->rw_base);
+ iounmap(mux_device->ctl_base);
+ }
+ return 0;
+}
+
+static long msm_i2c_mux_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct i2c_mux_device *mux_device;
+ int rc = 0;
+ mux_device = v4l2_get_subdevdata(sd);
+ if (mux_device == NULL) {
+ rc = -ENOMEM;
+ return rc;
+ }
+ mutex_lock(&mux_device->mutex);
+ switch (cmd) {
+ case VIDIOC_MSM_I2C_MUX_CFG:
+ rc = msm_i2c_mux_config(mux_device, (uint8_t *) arg);
+ break;
+ case VIDIOC_MSM_I2C_MUX_INIT:
+ rc = msm_i2c_mux_init(mux_device);
+ break;
+ case VIDIOC_MSM_I2C_MUX_RELEASE:
+ rc = msm_i2c_mux_release(mux_device);
+ break;
+ default:
+ rc = -ENOIOCTLCMD;
+ }
+ mutex_unlock(&mux_device->mutex);
+ return rc;
+}
+
+static struct v4l2_subdev_core_ops msm_i2c_mux_subdev_core_ops = {
+ .ioctl = &msm_i2c_mux_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_i2c_mux_subdev_ops = {
+ .core = &msm_i2c_mux_subdev_core_ops,
+};
+
+static int __devinit i2c_mux_probe(struct platform_device *pdev)
+{
+ struct i2c_mux_device *mux_device;
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ mux_device = kzalloc(sizeof(struct i2c_mux_device), GFP_KERNEL);
+ if (!mux_device) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&mux_device->subdev, &msm_i2c_mux_subdev_ops);
+ v4l2_set_subdevdata(&mux_device->subdev, mux_device);
+ platform_set_drvdata(pdev, &mux_device->subdev);
+ mutex_init(&mux_device->mutex);
+
+ mux_device->ctl_mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "i2c_mux_ctl");
+ if (!mux_device->ctl_mem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto i2c_mux_no_resource;
+ }
+ mux_device->ctl_io = request_mem_region(mux_device->ctl_mem->start,
+ resource_size(mux_device->ctl_mem), pdev->name);
+ if (!mux_device->ctl_io) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto i2c_mux_no_resource;
+ }
+ mux_device->rw_mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "i2c_mux_rw");
+ if (!mux_device->rw_mem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto i2c_mux_no_resource;
+ }
+ mux_device->rw_io = request_mem_region(mux_device->rw_mem->start,
+ resource_size(mux_device->rw_mem), pdev->name);
+ if (!mux_device->rw_io) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto i2c_mux_no_resource;
+ }
+ mux_device->pdev = pdev;
+ return 0;
+
+i2c_mux_no_resource:
+ mutex_destroy(&mux_device->mutex);
+ kfree(mux_device);
+ return 0;
+}
+
+static struct platform_driver i2c_mux_driver = {
+ .probe = i2c_mux_probe,
+ .driver = {
+ .name = MSM_I2C_MUX_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_camera_i2c_mux_init_module(void)
+{
+ return platform_driver_register(&i2c_mux_driver);
+}
+
+static void __exit msm_camera_i2c_mux_exit_module(void)
+{
+ platform_driver_unregister(&i2c_mux_driver);
+}
+
+module_init(msm_camera_i2c_mux_init_module);
+module_exit(msm_camera_i2c_mux_exit_module);
+MODULE_DESCRIPTION("MSM Camera I2C mux driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.h b/drivers/media/video/msm/io/msm_camera_i2c_mux.h
new file mode 100644
index 0000000..94394fc
--- /dev/null
+++ b/drivers/media/video/msm/io/msm_camera_i2c_mux.h
@@ -0,0 +1,46 @@
+/* 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.
+ */
+
+#ifndef MSM_I2C_MUX_H
+#define MSM_I2C_MUX_H
+
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct i2c_mux_device {
+ struct platform_device *pdev;
+ struct v4l2_subdev subdev;
+ struct resource *ctl_mem;
+ struct resource *ctl_io;
+ void __iomem *ctl_base;
+ struct resource *rw_mem;
+ struct resource *rw_io;
+ void __iomem *rw_base;
+ struct mutex mutex;
+ unsigned use_count;
+};
+
+struct i2c_mux_cfg_params {
+ struct v4l2_subdev *subdev;
+ void *parms;
+};
+
+#define VIDIOC_MSM_I2C_MUX_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct i2c_mux_cfg_params)
+
+#define VIDIOC_MSM_I2C_MUX_INIT \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 14, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_I2C_MUX_RELEASE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct v4l2_subdev*)
+
+#endif
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index ed77185..84d441d 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -157,7 +157,7 @@
D("Waiting for config status\n");
rc = wait_event_interruptible_timeout(queue->wait,
!list_empty_careful(&queue->list),
- out->timeout_ms);
+ msecs_to_jiffies(out->timeout_ms));
D("Waiting is over for config status\n");
if (list_empty_careful(&queue->list)) {
if (!rc)
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 40bc160..55c0da1 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -48,6 +48,7 @@
#define MSM_VFE_DRV_NAME "msm_vfe"
#define MSM_VPE_DRV_NAME "msm_vpe"
#define MSM_GEMINI_DRV_NAME "msm_gemini"
+#define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
/* msm queue management APIs*/
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index d111452..ea969cf 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -32,11 +32,6 @@
static struct clk *camio_imem_clk;
static struct regulator *fs_ijpeg;
-static struct platform_device *camio_dev;
-static struct resource *s3drw_io, *s3dctl_io;
-static struct resource *s3drw_mem, *s3dctl_mem;
-void __iomem *s3d_rw, *s3d_ctl;
-
void msm_io_w(u32 data, void __iomem *addr)
{
CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
@@ -234,89 +229,6 @@
return rc;
}
-int32_t msm_camio_3d_enable(const struct msm_camera_sensor_info *s_info)
-{
- int32_t val = 0, rc = 0;
- char s3drw[] = "s3d_rw";
- char s3dctl[] = "s3d_ctl";
- struct platform_device *pdev = camio_dev;
- pdev->resource = s_info->resource;
- pdev->num_resources = s_info->num_resources;
-
- s3drw_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, s3drw);
- if (!s3drw_mem) {
- pr_err("%s: no mem resource?\n", __func__);
- return -ENODEV;
- }
- s3dctl_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, s3dctl);
- if (!s3dctl_mem) {
- pr_err("%s: no mem resource?\n", __func__);
- return -ENODEV;
- }
- s3drw_io = request_mem_region(s3drw_mem->start,
- resource_size(s3drw_mem), pdev->name);
- if (!s3drw_io)
- return -EBUSY;
-
- s3d_rw = ioremap(s3drw_mem->start,
- resource_size(s3drw_mem));
- if (!s3d_rw) {
- rc = -ENOMEM;
- goto s3drw_nomem;
- }
- s3dctl_io = request_mem_region(s3dctl_mem->start,
- resource_size(s3dctl_mem), pdev->name);
- if (!s3dctl_io) {
- rc = -EBUSY;
- goto s3dctl_busy;
- }
- s3d_ctl = ioremap(s3dctl_mem->start,
- resource_size(s3dctl_mem));
- if (!s3d_ctl) {
- rc = -ENOMEM;
- goto s3dctl_nomem;
- }
-
- val = msm_io_r(s3d_rw);
- msm_io_w((val | 0x200), s3d_rw);
- return rc;
-
-s3dctl_nomem:
- release_mem_region(s3dctl_mem->start, resource_size(s3dctl_mem));
-s3dctl_busy:
- iounmap(s3d_rw);
-s3drw_nomem:
- release_mem_region(s3drw_mem->start, resource_size(s3drw_mem));
-return rc;
-}
-
-void msm_camio_3d_disable(void)
-{
- int32_t val = 0;
- msm_io_w((val & ~0x200), s3d_rw);
- iounmap(s3d_ctl);
- release_mem_region(s3dctl_mem->start, resource_size(s3dctl_mem));
- iounmap(s3d_rw);
- release_mem_region(s3drw_mem->start, resource_size(s3drw_mem));
-}
-
-void msm_camio_mode_config(enum msm_cam_mode mode)
-{
- uint32_t val;
- val = msm_io_r(s3d_ctl);
- if (mode == MODE_DUAL) {
- msm_io_w(val | 0x3, s3d_ctl);
- } else if (mode == MODE_L) {
- msm_io_w(((val | 0x2) & ~(0x1)), s3d_ctl);
- val = msm_io_r(s3d_ctl);
- CDBG("the camio mode config left value is %d\n", val);
- } else {
- msm_io_w(((val | 0x1) & ~(0x2)), s3d_ctl);
- val = msm_io_r(s3d_ctl);
- CDBG("the camio mode config right value is %d\n", val);
- }
-}
-
void msm_camio_bus_scale_cfg(struct msm_bus_scale_pdata *cam_bus_scale_table,
enum msm_bus_perf_setting perf_setting)
{
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index c9a9f1b..fdd1f0e 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -199,6 +199,19 @@
vfe_params.data = (void *)&free_buf;
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
break;
+ case VFE_MSG_V32_JPEG_CAPTURE:
+ free_buf.num_planes = 1;
+ free_buf.ch_paddr[0] = IMEM_Y_OFFSET;
+ free_buf.ch_paddr[1] = IMEM_CBCR_OFFSET;
+ cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
+ cfgcmd.value = &vfe_id;
+ vfe_params.vfe_cfg = &cfgcmd;
+ vfe_params.data = (void *)&free_buf;
+ rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+ /* Write the same buffer into PONG */
+ cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
+ rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
+ break;
case VFE_MSG_OUTPUT_IRQ:
D("%s Got OUTPUT_IRQ: Getting free buf id = %d",
__func__, vfe_id);
@@ -349,6 +362,35 @@
stats.buffer = msm_pmem_stats_ptov_lookup(&pmctl->sync,
isp_stats->buffer,
&(stats.fd));
+ switch (isp_stats->id) {
+ case MSG_ID_STATS_AEC:
+ stats.aec.buff = stats.buffer;
+ stats.aec.fd = stats.fd;
+ break;
+ case MSG_ID_STATS_AF:
+ stats.af.buff = stats.buffer;
+ stats.af.fd = stats.fd;
+ break;
+ case MSG_ID_STATS_AWB:
+ stats.awb.buff = stats.buffer;
+ stats.awb.fd = stats.fd;
+ break;
+ case MSG_ID_STATS_IHIST:
+ stats.ihist.buff = stats.buffer;
+ stats.ihist.fd = stats.fd;
+ break;
+ case MSG_ID_STATS_RS:
+ stats.rs.buff = stats.buffer;
+ stats.rs.fd = stats.fd;
+ break;
+ case MSG_ID_STATS_CS:
+ stats.cs.buff = stats.buffer;
+ stats.cs.fd = stats.fd;
+ break;
+ default:
+ pr_err("%s: Invalid msg type", __func__);
+ break;
+ }
if (!stats.buffer) {
pr_err("%s: msm_pmem_stats_ptov_lookup error\n",
__func__);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 99d9911..b539d19 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -598,6 +598,14 @@
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CFG);
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_MODULE_CFG);
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_PIXEL_IF_CFG);
+ if (msm_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
+ VFE33_HW_NUMBER) {
+ msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI0_CFG);
+ msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI1_CFG);
+ } else {
+ ++p;
+ ++p;
+ }
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_REALIGN_BUF);
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CHROMA_UP);
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_STATS_CFG);
@@ -702,8 +710,6 @@
msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
- msm_io_dump(vfe32_ctrl->vfebase, vfe32_ctrl->register_total * 4);
-
/* Ensure the write order while writing
to the command register using the barrier */
msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
@@ -851,7 +857,9 @@
/* capture command is valid for both idle and active state. */
vfe32_ctrl->outpath.out1.capture_cnt = num_frames_capture;
if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+ vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
+ vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
vfe32_ctrl->outpath.out0.capture_cnt =
num_frames_capture;
}
@@ -887,6 +895,9 @@
vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
}
}
+
+ vfe32_ctrl->vfe_capture_count = num_frames_capture;
+
msm_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
@@ -1286,16 +1297,31 @@
rc = vfe32_capture_raw(snapshot_cnt);
break;
case VFE_CMD_CAPTURE:
- pr_info("vfe32_proc_general: cmdID = %s\n",
- vfe32_general_cmd[cmd->id]);
+ CDBG("vfe32_proc_general: cmdID = %s op mode = %d\n",
+ vfe32_general_cmd[cmd->id], vfe32_ctrl->operation_mode);
if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
sizeof(uint32_t))) {
rc = -EFAULT;
goto proc_general_done;
}
- /* Configure primary channel */
- rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY);
+
+ if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
+ if (snapshot_cnt != 1) {
+ pr_err("only support 1 inline snapshot\n");
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ /* Configure primary channel for JPEG */
+ rc = vfe32_configure_pingpong_buffers(
+ VFE_MSG_V32_JPEG_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY);
+ } else {
+ /* Configure primary channel */
+ rc = vfe32_configure_pingpong_buffers(
+ VFE_MSG_V32_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY);
+ }
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for primary output", __func__);
@@ -2610,7 +2636,9 @@
}
if ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
- (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB)) {
+ (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) ||
+ (vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) ||
+ (vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) {
/* in snapshot mode */
/* later we need to add check for live snapshot mode. */
if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
@@ -2858,6 +2886,8 @@
*/
out_bool = ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG ||
+ vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
vfe32_ctrl->operation_mode == VFE_OUTPUTS_RAW ||
vfe32_ctrl->liveshot_state == VFE_STATE_STARTED ||
vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED ||
@@ -2899,6 +2929,10 @@
vfe32_ctrl->operation_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
vfe32_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_JPEG ||
+ vfe32_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe32_ctrl->operation_mode ==
VFE_OUTPUTS_RAW ||
vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED)
vfe32_ctrl->outpath.out0.capture_cnt--;
@@ -3392,6 +3426,10 @@
vfe32_ctrl->operation_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
vfe32_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_JPEG ||
+ vfe32_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe32_ctrl->operation_mode ==
VFE_OUTPUTS_RAW) {
if ((vfe32_ctrl->outpath.out0.capture_cnt == 0)
&& (vfe32_ctrl->outpath.out1.
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 62c3639..0d8be58 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -223,7 +223,7 @@
#define V32_OUT_CLAMP_OFF 0x00000524
#define V32_OUT_CLAMP_LEN 8
-#define V32_OPERATION_CFG_LEN 36
+#define V32_OPERATION_CFG_LEN 44
#define V32_AXI_OUT_OFF 0x00000038
#define V32_AXI_OUT_LEN 216
@@ -875,6 +875,9 @@
#define VFE_DMI_DATA_LO 0x000005A4
#define VFE_BUS_IO_FORMAT_CFG 0x000006F8
#define VFE_PIXEL_IF_CFG 0x000006FC
+#define VFE_RDI0_CFG 0x00000734
+#define VFE_RDI1_CFG 0x000007A4
+
#define VFE_VIOLATION_STATUS 0x000007B4
#define VFE33_DMI_DATA_HI 0x000005A0
diff --git a/drivers/media/video/msm/ov5647.c b/drivers/media/video/msm/ov5647.c
new file mode 100644
index 0000000..2a6e7be
--- /dev/null
+++ b/drivers/media/video/msm/ov5647.c
@@ -0,0 +1,1201 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/bitops.h>
+#include <linux/leds.h>
+#include <mach/camera.h>
+#include <media/msm_camera.h>
+#include "ov5647.h"
+
+/* 16bit address - 8 bit context register structure */
+#define Q8 0x00000100
+#define Q10 0x00000400
+
+#define REG_OV5647_GAIN_MSB 0x350A
+#define REG_OV5647_GAIN_LSB 0x350B
+#define REG_OV5647_LINE_HSB 0x3500
+#define REG_OV5647_LINE_MSB 0x3501
+#define REG_OV5647_LINE_LSB 0x3502
+
+/* MCLK */
+#define OV5647_MASTER_CLK_RATE 24000000
+
+/* AF Total steps parameters */
+#define OV5647_TOTAL_STEPS_NEAR_TO_FAR 32
+
+#define OV5647_REG_PREV_FRAME_LEN_1 31
+#define OV5647_REG_PREV_FRAME_LEN_2 32
+#define OV5647_REG_PREV_LINE_LEN_1 33
+#define OV5647_REG_PREV_LINE_LEN_2 34
+
+#define OV5647_REG_SNAP_FRAME_LEN_1 15
+#define OV5647_REG_SNAP_FRAME_LEN_2 16
+#define OV5647_REG_SNAP_LINE_LEN_1 17
+#define OV5647_REG_SNAP_LINE_LEN_2 18
+#define MSB 1
+#define LSB 0
+
+/* Debug switch */
+#ifdef CDBG
+#undef CDBG
+#endif
+#ifdef CDBG_HIGH
+#undef CDBG_HIGH
+#endif
+
+/*#define OV5647_VERBOSE_DGB*/
+
+#ifdef OV5647_VERBOSE_DGB
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#define CDBG_HIGH(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#define CDBG_HIGH(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+/*for debug*/
+#ifdef CDBG
+#undef CDBG
+#endif
+#define CDBG(fmt, args...) printk(fmt, ##args)
+
+static uint8_t mode_mask = 0x09;
+struct ov5647_work_t {
+ struct work_struct work;
+};
+
+static struct ov5647_work_t *ov5647_sensorw;
+static struct ov5647_work_t *ov5647_af_sensorw;
+static struct i2c_client *ov5647_af_client;
+static struct i2c_client *ov5647_client;
+
+struct ov5647_ctrl_t {
+ const struct msm_camera_sensor_info *sensordata;
+
+ uint32_t sensormode;
+ uint32_t fps_divider;/* init to 1 * 0x00000400 */
+ uint32_t pict_fps_divider;/* init to 1 * 0x00000400 */
+ uint16_t fps;
+
+ uint16_t curr_lens_pos;
+ uint16_t curr_step_pos;
+ uint16_t my_reg_gain;
+ uint32_t my_reg_line_count;
+ uint16_t total_lines_per_frame;
+
+ enum ov5647_resolution_t prev_res;
+ enum ov5647_resolution_t pict_res;
+ enum ov5647_resolution_t curr_res;
+ enum ov5647_test_mode_t set_test;
+};
+
+static bool CSI_CONFIG;
+static struct ov5647_ctrl_t *ov5647_ctrl;
+
+static DECLARE_WAIT_QUEUE_HEAD(ov5647_wait_queue);
+static DECLARE_WAIT_QUEUE_HEAD(ov5647_af_wait_queue);
+DEFINE_MUTEX(ov5647_mut);
+
+static uint16_t prev_line_length_pck;
+static uint16_t prev_frame_length_lines;
+static uint16_t snap_line_length_pck;
+static uint16_t snap_frame_length_lines;
+
+static int ov5647_i2c_rxdata(unsigned short saddr,
+ unsigned char *rxdata, int length)
+{
+ struct i2c_msg msgs[] = {
+ {
+ .addr = saddr,
+ .flags = 0,
+ .len = 2,
+ .buf = rxdata,
+ },
+ {
+ .addr = saddr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = rxdata,
+ },
+ };
+ if (i2c_transfer(ov5647_client->adapter, msgs, 2) < 0) {
+ CDBG("ov5647_i2c_rxdata faild 0x%x\n", saddr);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int32_t ov5647_i2c_txdata(unsigned short saddr,
+ unsigned char *txdata, int length)
+{
+ struct i2c_msg msg[] = {
+ {
+ .addr = saddr,
+ .flags = 0,
+ .len = length,
+ .buf = txdata,
+ },
+ };
+ if (i2c_transfer(ov5647_client->adapter, msg, 1) < 0) {
+ CDBG("ov5647_i2c_txdata faild 0x%x\n", saddr);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int32_t ov5647_i2c_read(unsigned short raddr,
+ unsigned short *rdata)
+{
+ int32_t rc = 0;
+ unsigned char buf[2];
+
+ if (!rdata)
+ return -EIO;
+ CDBG("%s:saddr:0x%x raddr:0x%x data:0x%x",
+ __func__, ov5647_client->addr, raddr, *rdata);
+ memset(buf, 0, sizeof(buf));
+ buf[0] = (raddr & 0xFF00) >> 8;
+ buf[1] = (raddr & 0x00FF);
+ rc = ov5647_i2c_rxdata(ov5647_client->addr >> 1, buf, 1);
+ if (rc < 0) {
+ CDBG("ov5647_i2c_read 0x%x failed!\n", raddr);
+ return rc;
+ }
+ *rdata = buf[0];
+ CDBG("ov5647_i2c_read 0x%x val = 0x%x!\n", raddr, *rdata);
+
+ return rc;
+}
+
+static int32_t ov5647_i2c_write_b_sensor(unsigned short waddr, uint8_t bdata)
+{
+ int32_t rc = -EFAULT;
+ unsigned char buf[3];
+
+ memset(buf, 0, sizeof(buf));
+ buf[0] = (waddr & 0xFF00) >> 8;
+ buf[1] = (waddr & 0x00FF);
+ buf[2] = bdata;
+ CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
+ rc = ov5647_i2c_txdata(ov5647_client->addr >> 1, buf, 3);
+ if (rc < 0) {
+ pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+ waddr, bdata);
+ }
+ return rc;
+}
+
+static int32_t ov5647_i2c_write_b_table(struct ov5647_i2c_reg_conf const
+ *reg_conf_tbl, int num)
+{
+ int i;
+ int32_t rc = -EIO;
+
+ for (i = 0; i < num; i++) {
+ rc = ov5647_i2c_write_b_sensor(reg_conf_tbl->waddr,
+ reg_conf_tbl->wdata);
+ if (rc < 0)
+ break;
+ reg_conf_tbl++;
+ }
+ return rc;
+}
+
+static int32_t ov5647_af_i2c_txdata(unsigned short saddr,
+ unsigned char *txdata, int length)
+{
+ struct i2c_msg msg[] = {
+ {
+ .addr = saddr,
+ .flags = 0,
+ .len = length,
+ .buf = txdata,
+ },
+ };
+ if (i2c_transfer(ov5647_af_client->adapter, msg, 1) < 0) {
+ pr_err("ov5647_af_i2c_txdata faild 0x%x\n", saddr);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int32_t ov5647_af_i2c_write_b_sensor(uint8_t waddr, uint8_t bdata)
+{
+ int32_t rc = -EFAULT;
+ unsigned char buf[2];
+
+ memset(buf, 0, sizeof(buf));
+ buf[0] = waddr;
+ buf[1] = bdata;
+ CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
+ rc = ov5647_af_i2c_txdata(ov5647_af_client->addr, buf, 2);
+ if (rc < 0) {
+ pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+ waddr, bdata);
+ }
+ return rc;
+}
+
+static void ov5647_start_stream(void)
+{
+ CDBG("CAMERA_DBG: 0x4202 0x0, stream on...\r\n");
+ ov5647_i2c_write_b_sensor(0x4202, 0x00);/* streaming on */
+}
+
+static void ov5647_stop_stream(void)
+{
+ CDBG("CAMERA_DBG: 0x4202 0xf, stream off...\r\n");
+ ov5647_i2c_write_b_sensor(0x4202, 0x0f);/* streaming off */
+}
+
+static void ov5647_group_hold_on(void)
+{
+ ov5647_i2c_write_b_sensor(0x0104, 0x01);
+}
+
+static void ov5647_group_hold_off(void)
+{
+ ov5647_i2c_write_b_sensor(0x0104, 0x0);
+}
+
+static void ov5647_get_pict_fps(uint16_t fps, uint16_t *pfps)
+{
+ /* input fps is preview fps in Q8 format */
+ uint32_t divider, d1, d2;
+ uint32_t preview_pclk = 0x37, snapshot_pclk = 0x4f;
+
+ d1 = (prev_frame_length_lines * 0x00000400) / snap_frame_length_lines;
+ d2 = (prev_line_length_pck * 0x00000400) / snap_line_length_pck;
+ divider = (d1 * d2*preview_pclk/snapshot_pclk) / 0x400;
+ CDBG(KERN_ERR "ov5647_get_pict_fps divider = %d", divider);
+ /*Verify PCLK settings and frame sizes.*/
+ *pfps = (uint16_t) (fps * divider / 0x400);
+}
+
+static uint16_t ov5647_get_prev_lines_pf(void)
+{
+ if (ov5647_ctrl->prev_res == QTR_SIZE)
+ return prev_frame_length_lines;
+ else
+ return snap_frame_length_lines;
+}
+
+static uint16_t ov5647_get_prev_pixels_pl(void)
+{
+ if (ov5647_ctrl->prev_res == QTR_SIZE)
+ return prev_line_length_pck;
+ else
+ return snap_line_length_pck;
+}
+
+static uint16_t ov5647_get_pict_lines_pf(void)
+{
+ if (ov5647_ctrl->pict_res == QTR_SIZE)
+ return prev_frame_length_lines;
+ else
+ return snap_frame_length_lines;
+}
+
+static uint16_t ov5647_get_pict_pixels_pl(void)
+{
+ if (ov5647_ctrl->pict_res == QTR_SIZE)
+ return prev_line_length_pck;
+ else
+ return snap_line_length_pck;
+}
+
+static uint32_t ov5647_get_pict_max_exp_lc(void)
+{
+ return snap_frame_length_lines * 24;
+}
+
+static int32_t ov5647_set_fps(struct fps_cfg *fps)
+{
+ uint16_t total_lines_per_frame;
+ int32_t rc = 0;
+
+ ov5647_ctrl->fps_divider = fps->fps_div;
+ ov5647_ctrl->pict_fps_divider = fps->pict_fps_div;
+
+ if (ov5647_ctrl->sensormode == SENSOR_PREVIEW_MODE) {
+ total_lines_per_frame = (uint16_t)
+ ((prev_frame_length_lines * ov5647_ctrl->fps_divider) / 0x400);
+ } else {
+ total_lines_per_frame = (uint16_t)
+ ((snap_frame_length_lines * ov5647_ctrl->fps_divider) / 0x400);
+ }
+
+ ov5647_group_hold_on();
+ rc = ov5647_i2c_write_b_sensor(0x0340,
+ ((total_lines_per_frame & 0xFF00) >> 8));
+ rc = ov5647_i2c_write_b_sensor(0x0341,
+ (total_lines_per_frame & 0x00FF));
+ ov5647_group_hold_off();
+
+ return rc;
+}
+
+static inline uint8_t ov5647_byte(uint16_t word, uint8_t offset)
+{
+ return word >> (offset * BITS_PER_BYTE);
+}
+
+static int32_t ov5647_write_exp_gain(uint16_t gain, uint32_t line)
+{
+ int rc = 0;
+ uint16_t max_line;
+ u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
+ uint8_t gain_lsb, gain_hsb;
+ ov5647_ctrl->my_reg_gain = gain;
+ ov5647_ctrl->my_reg_line_count = (uint16_t)line;
+
+ CDBG(KERN_ERR "preview exposure setting 0x%x, 0x%x, %d",
+ gain, line, line);
+
+ gain_lsb = (uint8_t) (ov5647_ctrl->my_reg_gain);
+ gain_hsb = (uint8_t)((ov5647_ctrl->my_reg_gain & 0x300)>>8);
+ /* adjust frame rate */
+ if (line > 980) {
+ rc = ov5647_i2c_write_b_sensor(0x380E,
+ (uint8_t)((line+4) >> 8)) ;
+ rc = ov5647_i2c_write_b_sensor(0x380F,
+ (uint8_t)((line+4) & 0x00FF)) ;
+ max_line = line + 4;
+ } else if (max_line > 984) {
+ rc = ov5647_i2c_write_b_sensor(0x380E,
+ (uint8_t)(984 >> 8)) ;
+ rc = ov5647_i2c_write_b_sensor(0x380F,
+ (uint8_t)(984 & 0x00FF)) ;
+ max_line = 984;
+ }
+
+ line = line<<4;
+ /* ov5647 need this operation */
+ intg_time_hsb = (u8)(line>>16);
+ intg_time_msb = (u8) ((line & 0xFF00) >> 8);
+ intg_time_lsb = (u8) (line & 0x00FF);
+
+ ov5647_group_hold_on();
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb) ;
+ ov5647_group_hold_off();
+
+ return rc;
+}
+
+
+static int32_t ov5647_set_pict_exp_gain(uint16_t gain, uint32_t line)
+{
+ uint16_t max_line;
+ int rc = 0;
+ uint8_t gain_lsb, gain_hsb;
+ u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
+
+ ov5647_ctrl->my_reg_gain = gain;
+ ov5647_ctrl->my_reg_line_count = (uint16_t)line;
+
+ gain_lsb = (uint8_t) (ov5647_ctrl->my_reg_gain);
+ gain_hsb = (uint8_t)((ov5647_ctrl->my_reg_gain & 0x300)>>8);
+
+ CDBG(KERN_ERR "snapshot exposure seting 0x%x, 0x%x, %d"
+ , gain, line, line);
+
+ if (line > 1964) {
+ rc = ov5647_i2c_write_b_sensor(0x380E,
+ (uint8_t)((line+4) >> 8)) ;
+ rc = ov5647_i2c_write_b_sensor(0x380F,
+ (uint8_t)((line+4) & 0x00FF)) ;
+ max_line = line + 4;
+ } else if (max_line > 1968) {
+ rc = ov5647_i2c_write_b_sensor(0x380E,
+ (uint8_t)(1968 >> 8)) ;
+ rc = ov5647_i2c_write_b_sensor(0x380F,
+ (uint8_t)(1968 & 0x00FF)) ;
+ max_line = 1968;
+ }
+ line = line<<4;
+ /* ov5647 need this operation */
+ intg_time_hsb = (u8)(line>>16);
+ intg_time_msb = (u8) ((line & 0xFF00) >> 8);
+ intg_time_lsb = (u8) (line & 0x00FF);
+
+ /* FIXME for BLC trigger */
+ ov5647_group_hold_on();
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb - 1) ;
+
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+ rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb) ;
+ ov5647_group_hold_off();
+
+ msleep(500);
+ return rc;
+
+}
+
+static int32_t ov5647_move_focus(int direction, int32_t num_steps)
+{
+ uint8_t code_val_msb = 0;
+ uint8_t code_val_lsb = 0;
+ int16_t step_direction, actual_step, next_position;
+ int rc;
+
+ if (num_steps == 0)
+ return 0;
+
+ if (direction == MOVE_NEAR)
+ step_direction = 20;
+ else if (direction == MOVE_FAR)
+ step_direction = -20;
+ else
+ return -EINVAL;
+
+ actual_step = (int16_t)(step_direction * num_steps);
+ next_position = (int16_t)ov5647_ctrl->curr_lens_pos + actual_step;
+ if (next_position < 0) {
+ CDBG(KERN_ERR "%s: OV5647 position(=%d) out of range",
+ __func__, next_position);
+ next_position = 0;
+ }
+ if (next_position > 0x3FF) {
+ CDBG(KERN_ERR "%s: OV5647 position(=%d) out of range",
+ __func__, next_position);
+ next_position = 0x3FF;
+ }
+ ov5647_ctrl->curr_lens_pos = next_position;
+
+ code_val_msb = (uint8_t)((ov5647_ctrl->curr_lens_pos & 0x03FF) >> 4);
+ code_val_lsb = (uint8_t)((ov5647_ctrl->curr_lens_pos & 0x000F) << 4);
+ code_val_lsb |= mode_mask;
+
+ rc = ov5647_af_i2c_write_b_sensor(code_val_msb, code_val_lsb);
+ /* DAC Setting */
+ if (rc != 0) {
+ CDBG(KERN_ERR "%s: WRITE ERROR lsb = 0x%x, msb = 0x%x",
+ __func__, code_val_lsb, code_val_msb);
+ } else {
+ CDBG(KERN_ERR "%s: Successful lsb = 0x%x, msb = 0x%x",
+ __func__, code_val_lsb, code_val_msb);
+ /* delay may set based on the steps moved
+ when I2C write successful */
+ msleep(100);
+ }
+ return 0;
+}
+
+static int32_t ov5647_set_default_focus(uint8_t af_step)
+{
+ uint8_t code_val_msb = 0;
+ uint8_t code_val_lsb = 0;
+ int rc = 0;
+
+ ov5647_ctrl->curr_lens_pos = 200;
+
+
+ code_val_msb = (ov5647_ctrl->curr_lens_pos & 0x03FF) >> 4;
+ code_val_lsb = (ov5647_ctrl->curr_lens_pos & 0x000F) << 4;
+ code_val_lsb |= mode_mask;
+
+ CDBG(KERN_ERR "ov5647_set_default_focus:lens pos = %d",
+ ov5647_ctrl->curr_lens_pos);
+ rc = ov5647_af_i2c_write_b_sensor(code_val_msb, code_val_lsb);
+ /* DAC Setting */
+ if (rc != 0)
+ CDBG(KERN_ERR "%s: WRITE ERROR lsb = 0x%x, msb = 0x%x",
+ __func__, code_val_lsb, code_val_msb);
+ else
+ CDBG(KERN_ERR "%s: WRITE successful lsb = 0x%x, msb = 0x%x",
+ __func__, code_val_lsb, code_val_msb);
+
+ usleep_range(10000, 11000);
+ return 0;
+}
+
+static int32_t ov5647_test(enum ov5647_test_mode_t mo)
+{
+ int32_t rc = 0;
+
+ if (mo != TEST_OFF)
+ rc = ov5647_i2c_write_b_sensor(0x0601, (uint8_t) mo);
+
+ return rc;
+}
+
+static void ov5647_reset_sensor(void)
+{
+ ov5647_i2c_write_b_sensor(0x103, 0x1);
+}
+
+
+static int32_t ov5647_sensor_setting(int update_type, int rt)
+{
+
+ int32_t rc = 0;
+ struct msm_camera_csi_params ov5647_csi_params;
+
+ ov5647_stop_stream();
+
+ /* wait for clk/data really stop */
+ if ((rt == RES_CAPTURE) || (CSI_CONFIG == 0))
+ msleep(66);
+ else
+ msleep(266);
+
+ CDBG("CAMERA_DBG1: 0x4800 regVal:0x25\r\n");
+ ov5647_i2c_write_b_sensor(0x4800, 0x25);/* streaming off */
+
+ usleep_range(10000, 11000);
+
+ if (update_type == REG_INIT) {
+ ov5647_reset_sensor();
+ ov5647_i2c_write_b_table(ov5647_regs.rec_settings,
+ ov5647_regs.rec_size);
+ CSI_CONFIG = 0;
+ } else if (update_type == UPDATE_PERIODIC) {
+ /* turn off flash when preview */
+
+ if (rt == RES_PREVIEW) {
+ ov5647_i2c_write_b_table(ov5647_regs.reg_prev,
+ ov5647_regs.reg_prev_size);
+ CDBG("CAMERA_DBG:preview settings...\r\n");
+ } else {
+ ov5647_i2c_write_b_table(ov5647_regs.reg_snap,
+ ov5647_regs.reg_snap_size);
+ CDBG("CAMERA_DBG:snapshot settings...\r\n");
+ }
+
+ msleep(20);
+ if (!CSI_CONFIG) {
+ msm_camio_vfe_clk_rate_set(192000000);
+ ov5647_csi_params.data_format = CSI_8BIT;
+ ov5647_csi_params.lane_cnt = 2;
+ ov5647_csi_params.lane_assign = 0xe4;
+ ov5647_csi_params.dpcm_scheme = 0;
+ ov5647_csi_params.settle_cnt = 10;
+ rc = msm_camio_csi_config(&ov5647_csi_params);
+ msleep(20);
+ CSI_CONFIG = 1;
+ /* exit powerdown state */
+ ov5647_i2c_write_b_sensor(0x0100, 0x01);
+ }
+ CDBG("CAMERA_DBG: 0x4800 regVal:0x04\r\n");
+ /* streaming on */
+ ov5647_i2c_write_b_sensor(0x4800, 0x04);
+ msleep(266);
+ ov5647_start_stream();
+ msleep(30);
+ }
+ return rc;
+}
+
+static int32_t ov5647_video_config(int mode)
+{
+ int32_t rc = 0;
+ int rt;
+ CDBG("video config\n");
+ /* change sensor resolution if needed */
+ if (ov5647_ctrl->prev_res == QTR_SIZE)
+ rt = RES_PREVIEW;
+ else
+ rt = RES_CAPTURE;
+ if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+ return rc;
+ if (ov5647_ctrl->set_test) {
+ if (ov5647_test(ov5647_ctrl->set_test) < 0)
+ return rc;
+ }
+
+ ov5647_ctrl->curr_res = ov5647_ctrl->prev_res;
+ ov5647_ctrl->sensormode = mode;
+ return rc;
+}
+
+static int32_t ov5647_snapshot_config(int mode)
+{
+ int32_t rc = 0;
+ int rt;
+
+ /*change sensor resolution if needed */
+ if (ov5647_ctrl->curr_res != ov5647_ctrl->pict_res) {
+ if (ov5647_ctrl->pict_res == QTR_SIZE)
+ rt = RES_PREVIEW;
+ else
+ rt = RES_CAPTURE;
+ if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+ return rc;
+ }
+
+ ov5647_ctrl->curr_res = ov5647_ctrl->pict_res;
+ ov5647_ctrl->sensormode = mode;
+ return rc;
+}
+
+static int32_t ov5647_raw_snapshot_config(int mode)
+{
+ int32_t rc = 0;
+ int rt;
+
+ /* change sensor resolution if needed */
+ if (ov5647_ctrl->curr_res != ov5647_ctrl->pict_res) {
+ if (ov5647_ctrl->pict_res == QTR_SIZE)
+ rt = RES_PREVIEW;
+ else
+ rt = RES_CAPTURE;
+ if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+ return rc;
+ }
+
+ ov5647_ctrl->curr_res = ov5647_ctrl->pict_res;
+ ov5647_ctrl->sensormode = mode;
+ return rc;
+}
+
+static int32_t ov5647_set_sensor_mode(int mode,
+ int res)
+{
+ int32_t rc = 0;
+
+ switch (mode) {
+ case SENSOR_PREVIEW_MODE:
+ rc = ov5647_video_config(mode);
+ break;
+ case SENSOR_SNAPSHOT_MODE:
+ rc = ov5647_snapshot_config(mode);
+ break;
+ case SENSOR_RAW_SNAPSHOT_MODE:
+ rc = ov5647_raw_snapshot_config(mode);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
+static int32_t ov5647_power_down(void)
+{
+ ov5647_stop_stream();
+ return 0;
+}
+
+static int ov5647_probe_init_done(const struct msm_camera_sensor_info *data)
+{
+ CDBG("probe done\n");
+ gpio_direction_output(data->sensor_pwd, 1);
+ return 0;
+}
+
+static int ov5647_probe_init_sensor(const struct msm_camera_sensor_info *data)
+{
+ int32_t rc = 0;
+ uint16_t regaddress1 = 0x300a;
+ uint16_t regaddress2 = 0x300b;
+ uint16_t chipid1 = 0;
+ uint16_t chipid2 = 0;
+
+ CDBG("%s: %d\n", __func__, __LINE__);
+
+ gpio_direction_output(data->sensor_pwd, 0);
+ usleep_range(4000, 4100);
+ gpio_direction_output(data->sensor_reset, 1);
+ usleep_range(2000, 2100);
+
+ ov5647_i2c_read(regaddress1, &chipid1);
+ if (chipid1 != 0x56) {
+ rc = -ENODEV;
+ pr_err("ov5647_probe_init_sensor fail chip id doesnot match\n");
+ goto init_probe_fail;
+ }
+
+ ov5647_i2c_read(regaddress2, &chipid2);
+ if (chipid2 != 0x47) {
+ rc = -ENODEV;
+ pr_err("ov5647_probe_init_sensor fail chip id doesnot match\n");
+ goto init_probe_fail;
+ }
+
+ pr_err("ID1: 0x%x\n", chipid1);
+ pr_err("ID2: 0x%x\n", chipid2);
+ goto init_probe_done;
+
+init_probe_fail:
+ pr_err(" ov5647_probe_init_sensor fails\n");
+ ov5647_probe_init_done(data);
+ return rc;
+init_probe_done:
+ pr_debug(" ov5647_probe_init_sensor finishes\n");
+ gpio_direction_output(data->sensor_pwd, 1);
+ return rc;
+}
+
+
+static int ov5647_sensor_open_init(const struct msm_camera_sensor_info *data)
+{
+ int32_t rc = 0;
+
+ CDBG("%s: %d\n", __func__, __LINE__);
+ CDBG("Calling ov5647_sensor_open_init\n");
+
+ ov5647_ctrl = kzalloc(sizeof(struct ov5647_ctrl_t), GFP_KERNEL);
+ if (!ov5647_ctrl) {
+ CDBG("ov5647_init failed!\n");
+ rc = -ENOMEM;
+ goto init_done;
+ }
+ ov5647_ctrl->fps_divider = 1 * 0x00000400;
+ ov5647_ctrl->pict_fps_divider = 1 * 0x00000400;
+ ov5647_ctrl->set_test = TEST_OFF;
+ ov5647_ctrl->prev_res = QTR_SIZE;
+ ov5647_ctrl->pict_res = FULL_SIZE;
+
+ if (data)
+ ov5647_ctrl->sensordata = data;
+
+ prev_frame_length_lines = 0x3d8;
+
+ prev_line_length_pck = 0x768*2;
+
+ snap_frame_length_lines = 0x7b0;
+
+ snap_line_length_pck = 0xa8c;
+
+ /* enable mclk first */
+ msm_camio_clk_rate_set(OV5647_MASTER_CLK_RATE);
+
+ gpio_direction_output(data->sensor_pwd, 1);
+ gpio_direction_output(data->sensor_reset, 0);
+ usleep_range(10000, 11000);
+ /* power on camera ldo and vreg */
+ if (ov5647_ctrl->sensordata->pmic_gpio_enable)
+ lcd_camera_power_onoff(1);
+ usleep_range(10000, 11000); /*waiting for ldo stable*/
+ gpio_direction_output(data->sensor_pwd, 0);
+ msleep(20);
+ gpio_direction_output(data->sensor_reset, 1);
+ msleep(25);
+
+ CDBG("init settings\n");
+ if (ov5647_ctrl->prev_res == QTR_SIZE)
+ rc = ov5647_sensor_setting(REG_INIT, RES_PREVIEW);
+ else
+ rc = ov5647_sensor_setting(REG_INIT, RES_CAPTURE);
+ ov5647_ctrl->fps = 30 * Q8;
+
+ /* enable AF actuator */
+ if (ov5647_ctrl->sensordata->vcm_enable) {
+ CDBG("enable AF actuator, gpio = %d\n",
+ ov5647_ctrl->sensordata->vcm_pwd);
+ rc = gpio_request(ov5647_ctrl->sensordata->vcm_pwd,
+ "ov5647_af");
+ if (!rc)
+ gpio_direction_output(
+ ov5647_ctrl->sensordata->vcm_pwd,
+ 1);
+ else {
+ pr_err("ov5647_ctrl gpio request failed!\n");
+ goto init_fail;
+ }
+ msleep(20);
+ rc = ov5647_set_default_focus(0);
+ if (rc < 0) {
+ gpio_direction_output(ov5647_ctrl->sensordata->vcm_pwd,
+ 0);
+ gpio_free(ov5647_ctrl->sensordata->vcm_pwd);
+ }
+ }
+ if (rc < 0)
+ goto init_fail;
+ else
+ goto init_done;
+init_fail:
+ CDBG("init_fail\n");
+ ov5647_probe_init_done(data);
+ /* No need to power OFF camera ldo and vreg
+ affects Display while resume */
+init_done:
+ CDBG("init_done\n");
+ return rc;
+}
+
+static int ov5647_i2c_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static int ov5647_init_client(struct i2c_client *client)
+{
+ /* Initialize the MSM_CAMI2C Chip */
+ init_waitqueue_head(&ov5647_wait_queue);
+ return 0;
+}
+
+static int ov5647_af_init_client(struct i2c_client *client)
+{
+ /* Initialize the MSM_CAMI2C Chip */
+ init_waitqueue_head(&ov5647_af_wait_queue);
+ return 0;
+}
+
+static const struct i2c_device_id ov5647_af_i2c_id[] = {
+ {"ov5647_af", 0},
+ { }
+};
+
+static int ov5647_af_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ CDBG("ov5647_af_probe called!\n");
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ CDBG("i2c_check_functionality failed\n");
+ goto probe_failure;
+ }
+
+ ov5647_af_sensorw = kzalloc(sizeof(struct ov5647_work_t), GFP_KERNEL);
+ if (!ov5647_af_sensorw) {
+ CDBG("kzalloc failed.\n");
+ rc = -ENOMEM;
+ goto probe_failure;
+ }
+
+ i2c_set_clientdata(client, ov5647_af_sensorw);
+ ov5647_af_init_client(client);
+ ov5647_af_client = client;
+
+ msleep(50);
+
+ CDBG("ov5647_af_probe successed! rc = %d\n", rc);
+ return 0;
+
+probe_failure:
+ CDBG("ov5647_af_probe failed! rc = %d\n", rc);
+ return rc;
+}
+
+static const struct i2c_device_id ov5647_i2c_id[] = {
+ {"ov5647", 0}, {}
+};
+
+static int ov5647_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ CDBG("ov5647_probe called!\n");
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ CDBG("i2c_check_functionality failed\n");
+ goto probe_failure;
+ }
+
+ ov5647_sensorw = kzalloc(sizeof(struct ov5647_work_t), GFP_KERNEL);
+ if (!ov5647_sensorw) {
+ CDBG("kzalloc failed.\n");
+ rc = -ENOMEM;
+ goto probe_failure;
+ }
+
+ i2c_set_clientdata(client, ov5647_sensorw);
+ ov5647_init_client(client);
+ ov5647_client = client;
+
+ msleep(50);
+
+ CDBG("ov5647_probe successed! rc = %d\n", rc);
+ return 0;
+
+probe_failure:
+ CDBG("ov5647_probe failed! rc = %d\n", rc);
+ return rc;
+}
+
+static int __devexit ov5647_remove(struct i2c_client *client)
+{
+ struct ov5647_work_t *sensorw = i2c_get_clientdata(client);
+ free_irq(client->irq, sensorw);
+ ov5647_client = NULL;
+ kfree(sensorw);
+ return 0;
+}
+
+static int __devexit ov5647_af_remove(struct i2c_client *client)
+{
+ struct ov5647_work_t *ov5647_af = i2c_get_clientdata(client);
+ free_irq(client->irq, ov5647_af);
+ ov5647_af_client = NULL;
+ kfree(ov5647_af);
+ return 0;
+}
+
+static struct i2c_driver ov5647_i2c_driver = {
+ .id_table = ov5647_i2c_id,
+ .probe = ov5647_i2c_probe,
+ .remove = ov5647_i2c_remove,
+ .driver = {
+ .name = "ov5647",
+ },
+};
+
+static struct i2c_driver ov5647_af_i2c_driver = {
+ .id_table = ov5647_af_i2c_id,
+ .probe = ov5647_af_i2c_probe,
+ .remove = __exit_p(ov5647_af_i2c_remove),
+ .driver = {
+ .name = "ov5647_af",
+ },
+};
+
+int ov5647_sensor_config(void __user *argp)
+{
+ struct sensor_cfg_data cdata;
+ long rc = 0;
+ if (copy_from_user(&cdata,
+ (void *)argp,
+ sizeof(struct sensor_cfg_data)))
+ return -EFAULT;
+ mutex_lock(&ov5647_mut);
+ CDBG("ov5647_sensor_config: cfgtype = %d\n",
+ cdata.cfgtype);
+ switch (cdata.cfgtype) {
+ case CFG_GET_PICT_FPS:
+ ov5647_get_pict_fps(
+ cdata.cfg.gfps.prevfps,
+ &(cdata.cfg.gfps.pictfps));
+
+ if (copy_to_user((void *)argp,
+ &cdata,
+ sizeof(struct sensor_cfg_data)))
+ rc = -EFAULT;
+ break;
+ case CFG_GET_PREV_L_PF:
+ cdata.cfg.prevl_pf =
+ ov5647_get_prev_lines_pf();
+
+ if (copy_to_user((void *)argp,
+ &cdata,
+ sizeof(struct sensor_cfg_data)))
+ rc = -EFAULT;
+ break;
+ case CFG_GET_PREV_P_PL:
+ cdata.cfg.prevp_pl =
+ ov5647_get_prev_pixels_pl();
+
+ if (copy_to_user((void *)argp,
+ &cdata,
+ sizeof(struct sensor_cfg_data)))
+ rc = -EFAULT;
+ break;
+ case CFG_GET_PICT_L_PF:
+ cdata.cfg.pictl_pf =
+ ov5647_get_pict_lines_pf();
+
+ if (copy_to_user((void *)argp,
+ &cdata,
+ sizeof(struct sensor_cfg_data)))
+ rc = -EFAULT;
+ break;
+ case CFG_GET_PICT_P_PL:
+ cdata.cfg.pictp_pl =
+ ov5647_get_pict_pixels_pl();
+ if (copy_to_user((void *)argp,
+ &cdata,
+ sizeof(struct sensor_cfg_data)))
+ rc = -EFAULT;
+ break;
+ case CFG_GET_PICT_MAX_EXP_LC:
+ cdata.cfg.pict_max_exp_lc =
+ ov5647_get_pict_max_exp_lc();
+
+ if (copy_to_user((void *)argp,
+ &cdata,
+ sizeof(struct sensor_cfg_data)))
+ rc = -EFAULT;
+ break;
+ case CFG_SET_FPS:
+ case CFG_SET_PICT_FPS:
+ rc = ov5647_set_fps(&(cdata.cfg.fps));
+ break;
+ case CFG_SET_EXP_GAIN:
+ rc = ov5647_write_exp_gain(cdata.cfg.exp_gain.gain,
+ cdata.cfg.exp_gain.line);
+ break;
+ case CFG_SET_PICT_EXP_GAIN:
+ rc = ov5647_set_pict_exp_gain(cdata.cfg.exp_gain.gain,
+ cdata.cfg.exp_gain.line);
+ break;
+ case CFG_SET_MODE:
+ rc = ov5647_set_sensor_mode(cdata.mode, cdata.rs);
+ break;
+ case CFG_PWR_DOWN:
+ rc = ov5647_power_down();
+ break;
+ case CFG_MOVE_FOCUS:
+ rc = ov5647_move_focus(cdata.cfg.focus.dir,
+ cdata.cfg.focus.steps);
+ break;
+ case CFG_SET_DEFAULT_FOCUS:
+ rc = ov5647_set_default_focus(cdata.cfg.focus.steps);
+ break;
+
+ case CFG_GET_AF_MAX_STEPS:
+ cdata.max_steps = OV5647_TOTAL_STEPS_NEAR_TO_FAR;
+ if (copy_to_user((void *)argp,
+ &cdata,
+ sizeof(struct sensor_cfg_data)))
+ rc = -EFAULT;
+ break;
+ case CFG_SET_EFFECT:
+ rc = ov5647_set_default_focus(cdata.cfg.effect);
+ break;
+ default:
+ rc = -EFAULT;
+ break;
+ }
+ mutex_unlock(&ov5647_mut);
+
+ return rc;
+}
+
+static int ov5647_sensor_release(void)
+{
+ int rc = -EBADF;
+ unsigned short rdata;
+
+ mutex_lock(&ov5647_mut);
+ ov5647_power_down();
+ msleep(20);
+ ov5647_i2c_read(0x3018, &rdata);
+ rdata |= 0x18; /*set bit 3 bit 4 to 1*/
+ ov5647_i2c_write_b_sensor(0x3018, rdata);/*write back*/
+ msleep(20);
+
+ gpio_set_value(ov5647_ctrl->sensordata->sensor_pwd, 1);
+ usleep_range(5000, 5100);
+ if (ov5647_ctrl->sensordata->vcm_enable) {
+ gpio_direction_output(ov5647_ctrl->sensordata->vcm_pwd, 0);
+ gpio_free(ov5647_ctrl->sensordata->vcm_pwd);
+ }
+
+ /* No need to power OFF camera ldo and vreg
+ affects Display while resume */
+
+ kfree(ov5647_ctrl);
+ ov5647_ctrl = NULL;
+ CDBG("ov5647_release completed\n");
+ mutex_unlock(&ov5647_mut);
+
+ return rc;
+}
+
+static int ov5647_sensor_probe(const struct msm_camera_sensor_info *info,
+ struct msm_sensor_ctrl *s)
+{
+ int rc = 0;
+
+ CDBG("%s E\n", __func__);
+
+ gpio_direction_output(info->sensor_pwd, 1);
+ gpio_direction_output(info->sensor_reset, 0);
+ usleep_range(1000, 1100);
+ /* turn on ldo and vreg */
+ if (info->pmic_gpio_enable)
+ lcd_camera_power_onoff(1);
+
+ rc = i2c_add_driver(&ov5647_i2c_driver);
+ if (rc < 0 || ov5647_client == NULL) {
+ rc = -ENOTSUPP;
+ CDBG("I2C add driver ov5647 failed");
+ goto probe_fail_2;
+ }
+ if (info->vcm_enable) {
+ rc = i2c_add_driver(&ov5647_af_i2c_driver);
+ if (rc < 0 || ov5647_af_client == NULL) {
+ rc = -ENOTSUPP;
+ CDBG("I2C add driver ov5647 af failed");
+ goto probe_fail_3;
+ }
+ }
+ msm_camio_clk_rate_set(OV5647_MASTER_CLK_RATE);
+
+ rc = ov5647_probe_init_sensor(info);
+ if (rc < 0)
+ goto probe_fail_1;
+
+ s->s_init = ov5647_sensor_open_init;
+ s->s_release = ov5647_sensor_release;
+ s->s_config = ov5647_sensor_config;
+ s->s_mount_angle = info->sensor_platform_info->mount_angle;
+ gpio_set_value(info->sensor_pwd, 1);
+ ov5647_probe_init_done(info);
+ /* turn off ldo and vreg */
+ if (info->pmic_gpio_enable)
+ lcd_camera_power_onoff(0);
+
+ CDBG("%s X", __func__);
+ return rc;
+
+probe_fail_3:
+ i2c_del_driver(&ov5647_af_i2c_driver);
+probe_fail_2:
+ i2c_del_driver(&ov5647_i2c_driver);
+probe_fail_1:
+ /* turn off ldo and vreg */
+ if (info->pmic_gpio_enable)
+ lcd_camera_power_onoff(0);
+ CDBG("ov5647_sensor_probe: SENSOR PROBE FAILS!\n");
+ CDBG("%s X", __func__);
+ return rc;
+}
+
+static int __devinit ov5647_probe(struct platform_device *pdev)
+{
+ return msm_camera_drv_start(pdev, ov5647_sensor_probe);
+}
+
+static struct platform_driver msm_camera_driver = {
+ .probe = ov5647_probe,
+ .driver = {
+ .name = "msm_camera_ov5647",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ov5647_init(void)
+{
+ return platform_driver_register(&msm_camera_driver);
+}
+
+module_init(ov5647_init);
+MODULE_DESCRIPTION("Omnivision 5 MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/ov5647.h b/drivers/media/video/msm/ov5647.h
new file mode 100644
index 0000000..b43f15c
--- /dev/null
+++ b/drivers/media/video/msm/ov5647.h
@@ -0,0 +1,92 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef OV5647_H
+#define OV5647_H
+#include <linux/types.h>
+#include <mach/board.h>
+
+extern struct ov5647_reg ov5647_regs;
+extern int lcd_camera_power_onoff(int on);
+extern struct rw_semaphore leds_list_lock;
+extern struct list_head leds_list;
+
+struct ov5647_i2c_reg_conf {
+ unsigned short waddr;
+ unsigned short wdata;
+};
+
+enum ov5647_test_mode_t {
+ TEST_OFF,
+ TEST_1,
+ TEST_2,
+ TEST_3
+};
+
+enum ov5647_resolution_t {
+ QTR_SIZE,
+ FULL_SIZE,
+ INVALID_SIZE
+};
+enum ov5647_setting {
+ RES_PREVIEW,
+ RES_CAPTURE
+};
+enum ov5647_reg_update {
+ /* Sensor egisters that need to be updated during initialization */
+ REG_INIT,
+ /* Sensor egisters that needs periodic I2C writes */
+ UPDATE_PERIODIC,
+ /* All the sensor Registers will be updated */
+ UPDATE_ALL,
+ /* Not valid update */
+ UPDATE_INVALID
+};
+
+enum ov5647_reg_pll {
+ E013_VT_PIX_CLK_DIV,
+ E013_VT_SYS_CLK_DIV,
+ E013_PRE_PLL_CLK_DIV,
+ E013_PLL_MULTIPLIER,
+ E013_OP_PIX_CLK_DIV,
+ E013_OP_SYS_CLK_DIV
+};
+
+enum ov5647_reg_mode {
+ E013_X_ADDR_START,
+ E013_X_ADDR_END,
+ E013_Y_ADDR_START,
+ E013_Y_ADDR_END,
+ E013_X_OUTPUT_SIZE,
+ E013_Y_OUTPUT_SIZE,
+ E013_DATAPATH_SELECT,
+ E013_READ_MODE,
+ E013_ANALOG_CONTROL5,
+ E013_DAC_LD_4_5,
+ E013_SCALING_MODE,
+ E013_SCALE_M,
+ E013_LINE_LENGTH_PCK,
+ E013_FRAME_LENGTH_LINES,
+ E013_COARSE_INTEGRATION_TIME,
+ E013_FINE_INTEGRATION_TIME,
+ E013_FINE_CORRECTION
+};
+
+struct ov5647_reg {
+ const struct ov5647_i2c_reg_conf *rec_settings;
+ const unsigned short rec_size;
+ const struct ov5647_i2c_reg_conf *reg_prev;
+ const unsigned short reg_prev_size;
+ const struct ov5647_i2c_reg_conf *reg_snap;
+ const unsigned short reg_snap_size;
+};
+#endif /* OV5647_H */
diff --git a/drivers/media/video/msm/ov5647_reg.c b/drivers/media/video/msm/ov5647_reg.c
new file mode 100644
index 0000000..4a0fed4
--- /dev/null
+++ b/drivers/media/video/msm/ov5647_reg.c
@@ -0,0 +1,219 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include "ov5647.h"
+struct ov5647_i2c_reg_conf ov5647_prev_settings[] = {
+ /*1280*960 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps
+ for back to preview*/
+ {0x3035, 0x21},
+ {0x3036, 0x37},
+ {0x3821, 0x07},
+ {0x3820, 0x41},
+ {0x3612, 0x09},
+ {0x3618, 0x00},
+ {0x380c, 0x07},
+ {0x380d, 0x68},
+ {0x380e, 0x03},
+ {0x380f, 0xd8},
+ {0x3814, 0x31},
+ {0x3815, 0x31},
+ {0x3709, 0x52},
+ {0x3808, 0x05},
+ {0x3809, 0x00},
+ {0x380a, 0x03},
+ {0x380b, 0xc0},
+ {0x3800, 0x00},
+ {0x3801, 0x18},
+ {0x3802, 0x00},
+ {0x3803, 0x0e},
+ {0x3804, 0x0a},
+ {0x3805, 0x27},
+ {0x3806, 0x07},
+ {0x3807, 0x95},
+ {0x4004, 0x02},
+};
+
+struct ov5647_i2c_reg_conf ov5647_snap_settings[] = {
+ /*2608*1952 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps*/
+ {0x3035, 0x21},
+ {0x3036, 0x4f},
+ {0x3821, 0x06},
+ {0x3820, 0x00},
+ {0x3612, 0x0b},
+ {0x3618, 0x04},
+ {0x380c, 0x0a},
+ {0x380d, 0x8c},
+ {0x380e, 0x07},
+ {0x380f, 0xb0},
+ {0x3814, 0x11},
+ {0x3815, 0x11},
+ {0x3709, 0x12},
+ {0x3808, 0x0a},
+ {0x3809, 0x30},
+ {0x380a, 0x07},
+ {0x380b, 0xa0},
+ {0x3800, 0x00},
+ {0x3801, 0x04},
+ {0x3802, 0x00},
+ {0x3803, 0x00},
+ {0x3804, 0x0a},
+ {0x3805, 0x3b},
+ {0x3806, 0x07},
+ {0x3807, 0xa3},
+ {0x4004, 0x04},
+};
+
+struct ov5647_i2c_reg_conf ov5647_recommend_settings[] = {
+ {0x3035, 0x11},
+ {0x303c, 0x11},
+ {0x370c, 0x03},
+ {0x5000, 0x06},
+ {0x5003, 0x08},
+ {0x5a00, 0x08},
+ {0x3000, 0xff},
+ {0x3001, 0xff},
+ {0x3002, 0xff},
+ {0x301d, 0xf0},
+ {0x3a18, 0x00},
+ {0x3a19, 0xf8},
+ {0x3c01, 0x80},
+ {0x3b07, 0x0c},
+ {0x3708, 0x64},
+ {0x3630, 0x2e},
+ {0x3632, 0xe2},
+ {0x3633, 0x23},
+ {0x3634, 0x44},
+ {0x3620, 0x64},
+ {0x3621, 0xe0},
+ {0x3600, 0x37},
+ {0x3704, 0xa0},
+ {0x3703, 0x5a},
+ {0x3715, 0x78},
+ {0x3717, 0x01},
+ {0x3731, 0x02},
+ {0x370b, 0x60},
+ {0x3705, 0x1a},
+ {0x3f05, 0x02},
+ {0x3f06, 0x10},
+ {0x3f01, 0x0a},
+ {0x3a08, 0x01},
+ {0x3a0f, 0x58},
+ {0x3a10, 0x50},
+ {0x3a1b, 0x58},
+ {0x3a1e, 0x50},
+ {0x3a11, 0x60},
+ {0x3a1f, 0x28},
+ {0x4001, 0x02},
+ {0x4000, 0x09},
+ {0x3000, 0x00},
+ {0x3001, 0x00},
+ {0x3002, 0x00},
+ {0x3017, 0xe0},
+ {0x301c, 0xfc},
+ {0x3636, 0x06},
+ {0x3016, 0x08},
+ {0x3827, 0xec},
+ {0x3018, 0x44},
+ {0x3035, 0x21},
+ {0x3106, 0xf5},
+ {0x3034, 0x18},
+ {0x301c, 0xf8},
+ /*lens setting*/
+ {0x5000, 0x86},
+ {0x5800, 0x11},
+ {0x5801, 0x0c},
+ {0x5802, 0x0a},
+ {0x5803, 0x0b},
+ {0x5804, 0x0d},
+ {0x5805, 0x13},
+ {0x5806, 0x09},
+ {0x5807, 0x05},
+ {0x5808, 0x03},
+ {0x5809, 0x03},
+ {0x580a, 0x06},
+ {0x580b, 0x08},
+ {0x580c, 0x05},
+ {0x580d, 0x01},
+ {0x580e, 0x00},
+ {0x580f, 0x00},
+ {0x5810, 0x02},
+ {0x5811, 0x06},
+ {0x5812, 0x05},
+ {0x5813, 0x01},
+ {0x5814, 0x00},
+ {0x5815, 0x00},
+ {0x5816, 0x02},
+ {0x5817, 0x06},
+ {0x5818, 0x09},
+ {0x5819, 0x05},
+ {0x581a, 0x04},
+ {0x581b, 0x04},
+ {0x581c, 0x06},
+ {0x581d, 0x09},
+ {0x581e, 0x11},
+ {0x581f, 0x0c},
+ {0x5820, 0x0b},
+ {0x5821, 0x0b},
+ {0x5822, 0x0d},
+ {0x5823, 0x13},
+ {0x5824, 0x22},
+ {0x5825, 0x26},
+ {0x5826, 0x26},
+ {0x5827, 0x24},
+ {0x5828, 0x24},
+ {0x5829, 0x24},
+ {0x582a, 0x22},
+ {0x582b, 0x20},
+ {0x582c, 0x22},
+ {0x582d, 0x26},
+ {0x582e, 0x22},
+ {0x582f, 0x22},
+ {0x5830, 0x42},
+ {0x5831, 0x22},
+ {0x5832, 0x02},
+ {0x5833, 0x24},
+ {0x5834, 0x22},
+ {0x5835, 0x22},
+ {0x5836, 0x22},
+ {0x5837, 0x26},
+ {0x5838, 0x42},
+ {0x5839, 0x26},
+ {0x583a, 0x06},
+ {0x583b, 0x26},
+ {0x583c, 0x24},
+ {0x583d, 0xce},
+ /* manual AWB,manual AE,close Lenc,open WBC*/
+ {0x3503, 0x03}, /*manual AE*/
+ {0x3501, 0x10},
+ {0x3502, 0x80},
+ {0x350a, 0x00},
+ {0x350b, 0x7f},
+ {0x5001, 0x01}, /*manual AWB*/
+ {0x5180, 0x08},
+ {0x5186, 0x04},
+ {0x5187, 0x00},
+ {0x5188, 0x04},
+ {0x5189, 0x00},
+ {0x518a, 0x04},
+ {0x518b, 0x00},
+ {0x5000, 0x06}, /*No lenc,WBC on*/
+};
+
+struct ov5647_reg ov5647_regs = {
+ .rec_settings = &ov5647_recommend_settings[0],
+ .rec_size = ARRAY_SIZE(ov5647_recommend_settings),
+ .reg_prev = &ov5647_prev_settings[0],
+ .reg_prev_size = ARRAY_SIZE(ov5647_prev_settings),
+ .reg_snap = &ov5647_snap_settings[0],
+ .reg_snap_size = ARRAY_SIZE(ov5647_snap_settings),
+};
diff --git a/drivers/media/video/msm/ov7692.h b/drivers/media/video/msm/ov7692.h
index e43a17d..fc9cf1c 100644
--- a/drivers/media/video/msm/ov7692.h
+++ b/drivers/media/video/msm/ov7692.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,11 @@
#include <linux/types.h>
#include <mach/board.h>
+#define INVMASK(v) (0xff-v)
+#define OV7692Core_WritePREG(pTbl) OV7692_WritePRegs \
+ (pTbl, sizeof(pTbl)/sizeof(pTbl[0]))
+
+extern int lcd_camera_power_onoff(int on);
struct reg_addr_val_pair_struct {
uint8_t reg_addr;
uint8_t reg_val;
@@ -46,5 +51,616 @@
/* Not valid update */
UPDATE_INVALID
};
+
+/*OV SENSOR SCCB*/
+struct OV7692_WREG {
+ uint8_t addr;
+ uint8_t data;
+ uint8_t mask;
+} OV7692_WREG;
+
+#ifdef CONFIG_WEBCAM_OV7692_QRD
+/* 96MHz PCLK @ 24MHz MCLK */
+struct reg_addr_val_pair_struct ov7692_init_settings_array[] = {
+ {0x12, 0x80},
+ {0x0e, 0x08},
+ {0x69, 0x52},
+ {0x1e, 0xb3},
+ {0x48, 0x42},
+ {0xff, 0x01},
+ {0xae, 0xa0},
+ {0xa8, 0x26},
+ {0xb4, 0xc0},
+ {0xb5, 0x40},
+ {0xff, 0x00},
+ {0x0c, 0x00},
+ {0x62, 0x10},
+ {0x12, 0x00},
+ {0x17, 0x65},
+ {0x18, 0xa4},
+ {0x19, 0x0a},
+ {0x1a, 0xf6},
+ {0x3e, 0x30},
+ {0x64, 0x0a},
+ {0xff, 0x01},
+ {0xb4, 0xc0},
+ {0xff, 0x00},
+ {0x67, 0x20},
+ {0x81, 0x3f},
+ {0xcc, 0x02},
+ {0xcd, 0x80},
+ {0xce, 0x01},
+ {0xcf, 0xe0},
+ {0xc8, 0x02},
+ {0xc9, 0x80},
+ {0xca, 0x01},
+ {0xcb, 0xe0},
+ {0xd0, 0x48},
+ {0x82, 0x03},
+ /*{0x0e, 0x00},*/
+ {0x70, 0x00},
+ {0x71, 0x34},
+ {0x74, 0x28},
+ {0x75, 0x98},
+ {0x76, 0x00},
+ {0x77, 0x64},
+ {0x78, 0x01},
+ {0x79, 0xc2},
+ {0x7a, 0x4e},
+ {0x7b, 0x1f},
+ {0x7c, 0x00},
+ {0x11, 0x00},
+ {0x20, 0x00},
+ {0x21, 0x23},
+ {0x50, 0x9a},
+ {0x51, 0x80},
+ {0x4c, 0x7d},
+ /*{0x0e, 0x00},*/
+ {0x85, 0x10},
+ {0x86, 0x00},
+ {0x87, 0x00},
+ {0x88, 0x00},
+ {0x89, 0x2a},
+ {0x8a, 0x26},
+ {0x8b, 0x22},
+ {0xbb, 0x7a},
+ {0xbc, 0x69},
+ {0xbd, 0x11},
+ {0xbe, 0x13},
+ {0xbf, 0x81},
+ {0xc0, 0x96},
+ {0xc1, 0x1e},
+ {0xb7, 0x05},
+ {0xb8, 0x09},
+ {0xb9, 0x00},
+ {0xba, 0x18},
+ {0x5a, 0x1f},
+ {0x5b, 0x9f},
+ {0x5c, 0x6a},
+ {0x5d, 0x42},
+ {0x24, 0x78},
+ {0x25, 0x68},
+ {0x26, 0xb3},
+ {0xa3, 0x0b},
+ {0xa4, 0x15},
+ {0xa5, 0x2a},
+ {0xa6, 0x51},
+ {0xa7, 0x63},
+ {0xa8, 0x74},
+ {0xa9, 0x83},
+ {0xaa, 0x91},
+ {0xab, 0x9e},
+ {0xac, 0xaa},
+ {0xad, 0xbe},
+ {0xae, 0xce},
+ {0xaf, 0xe5},
+ {0xb0, 0xf3},
+ {0xb1, 0xfb},
+ {0xb2, 0x06},
+ {0x8c, 0x5c},
+ {0x8d, 0x11},
+ {0x8e, 0x12},
+ {0x8f, 0x19},
+ {0x90, 0x50},
+ {0x91, 0x20},
+ {0x92, 0x96},
+ {0x93, 0x80},
+ {0x94, 0x13},
+ {0x95, 0x1b},
+ {0x96, 0xff},
+ {0x97, 0x00},
+ {0x98, 0x3d},
+ {0x99, 0x36},
+ {0x9a, 0x51},
+ {0x9b, 0x43},
+ {0x9c, 0xf0},
+ {0x9d, 0xf0},
+ {0x9e, 0xf0},
+ {0x9f, 0xff},
+ {0xa0, 0x68},
+ {0xa1, 0x62},
+ {0xa2, 0x0e},
+};
+#endif
+/* Exposure Compensation */
+struct OV7692_WREG ov7692_exposure_compensation_lv0_tbl[] = {
+ /*@@ +1.7EV*/
+ {0x24, 0xc0},
+ {0x25, 0xb8},
+ {0x26, 0xe6},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv1_tbl[] = {
+ /*@@ +1.0EV*/
+ {0x24, 0xa8},
+ {0x25, 0xa0},
+ {0x26, 0xc4},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv2_default_tbl[] = {
+ /*@@ default*/
+ {0x24, 0x86},
+ {0x25, 0x76},
+ {0x26, 0xb3},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv3_tbl[] = {
+ /*@@ -1.0EV*/
+ {0x24, 0x70},
+ {0x25, 0x60},
+ {0x26, 0xa2},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv4_tbl[] = {
+ /*@@ -1.7EV*/
+ {0x24, 0x50},
+ {0x25, 0x40},
+ {0x26, 0xa2},
+};
+
+struct OV7692_WREG ov7692_antibanding_off_tbl[] = {
+ {0x13, 0xE5, INVMASK(0x20)},
+};
+
+struct OV7692_WREG ov7692_antibanding_auto_tbl[] = {
+ {0x13, 0x20, INVMASK(0x20)},
+ {0x14, 0x14, INVMASK(0x17)},
+};
+
+struct OV7692_WREG ov7692_antibanding_50z_tbl[] = {
+ /*Band 50Hz*/
+ {0x13, 0x20, INVMASK(0x20)},
+ {0x14, 0x17, INVMASK(0x17)},
+};
+
+struct OV7692_WREG ov7692_antibanding_60z_tbl[] = {
+ /*Band 60Hz*/
+ {0x13, 0x20, INVMASK(0x20)},
+ {0x14, 0x16, INVMASK(0x17)},
+};
+
+/*Saturation*/
+struct OV7692_WREG ov7692_saturation_lv0_tbl[] = {
+ /*Saturation level 0*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x00, INVMASK(0xff)},
+ {0xd9, 0x00, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv1_tbl[] = {
+ /*Saturation level 1*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x10, INVMASK(0xff)},
+ {0xd9, 0x10, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv2_tbl[] = {
+ /*Saturation level 2*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x20, INVMASK(0xff)},
+ {0xd9, 0x20, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+
+};
+
+struct OV7692_WREG ov7692_saturation_lv3_tbl[] = {
+ /*Saturation level 3*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x30, INVMASK(0xff)},
+ {0xd9, 0x30, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+
+};
+
+struct OV7692_WREG ov7692_saturation_default_lv4_tbl[] = {
+ /*Saturation level 4 (default)*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x40, INVMASK(0xff)},
+ {0xd9, 0x40, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv5_tbl[] = {
+ /*Saturation level 5*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x50, INVMASK(0xff)},
+ {0xd9, 0x50, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv6_tbl[] = {
+ /*Saturation level 6*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x60, INVMASK(0xff)},
+ {0xd9, 0x60, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv7_tbl[] = {
+ /*Saturation level 7*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x70, INVMASK(0xff)},
+ {0xd9, 0x70, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv8_tbl[] = {
+ /*Saturation level 8*/
+ {0x81, 0x33, INVMASK(0x33)},
+ {0xd8, 0x80, INVMASK(0xff)},
+ {0xd9, 0x80, INVMASK(0xff)},
+ {0xd2, 0x02, INVMASK(0xff)},
+};
+
+/*EFFECT*/
+struct OV7692_WREG ov7692_effect_normal_tbl[] = {
+ {0x81, 0x00, INVMASK(0x20)},
+ {0x28, 0x00, },
+ {0xd2, 0x00, },
+ {0xda, 0x80, },
+ {0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_mono_tbl[] = {
+ {0x81, 0x20, INVMASK(0x20)},
+ {0x28, 0x00, },
+ {0xd2, 0x18, },
+ {0xda, 0x80, },
+ {0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_bw_tbl[] = {
+ {0x81, 0x20, INVMASK(0x20)},
+ {0x28, 0x00, },
+ {0xd2, 0x18, },
+ {0xda, 0x80, },
+ {0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_sepia_tbl[] = {
+ {0x81, 0x20, INVMASK(0x20)},
+ {0x28, 0x00, },
+ {0xd2, 0x18, },
+ {0xda, 0x40, },
+ {0xdb, 0xa0, },
+};
+
+struct OV7692_WREG ov7692_effect_bluish_tbl[] = {
+ {0x81, 0x20, INVMASK(0x20)},
+ {0x28, 0x00, },
+ {0xd2, 0x18, },
+ {0xda, 0xc0, },
+ {0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_reddish_tbl[] = {
+ {0x81, 0x20, INVMASK(0x20)},
+ {0x28, 0x00, },
+ {0xd2, 0x18, },
+ {0xda, 0x80, },
+ {0xdb, 0xc0, },
+};
+
+struct OV7692_WREG ov7692_effect_greenish_tbl[] = {
+ {0x81, 0x20, INVMASK(0x20)},
+ {0x28, 0x00, },
+ {0xd2, 0x18, },
+ {0xda, 0x60, },
+ {0xdb, 0x60, },
+};
+
+struct OV7692_WREG ov7692_effect_negative_tbl[] = {
+ {0x81, 0x20, INVMASK(0x20)},
+ {0x28, 0x80, },
+ {0xd2, 0x40, },
+ {0xda, 0x80, },
+ {0xdb, 0x80, },
+};
+
+/*Contrast*/
+struct OV7692_WREG ov7692_contrast_lv0_tbl[] = {
+ /*Contrast -4*/
+ {0xb2, 0x29},
+ {0xa3, 0x55},
+ {0xa4, 0x5b},
+ {0xa5, 0x67},
+ {0xa6, 0x7e},
+ {0xa7, 0x89},
+ {0xa8, 0x93},
+ {0xa9, 0x9c},
+ {0xaa, 0xa4},
+ {0xab, 0xac},
+ {0xac, 0xb3},
+ {0xad, 0xbe},
+ {0xae, 0xc7},
+ {0xaf, 0xd5},
+ {0xb0, 0xdd},
+ {0xb1, 0xe1},
+};
+
+struct OV7692_WREG ov7692_contrast_lv1_tbl[] = {
+ /*Contrast -3*/
+ {0xb2, 0x20},
+ {0xa3, 0x43},
+ {0xa4, 0x4a},
+ {0xa5, 0x58},
+ {0xa6, 0x73},
+ {0xa7, 0x80},
+ {0xa8, 0x8b},
+ {0xa9, 0x96},
+ {0xaa, 0x9f},
+ {0xab, 0xa8},
+ {0xac, 0xb1},
+ {0xad, 0xbe},
+ {0xae, 0xc9},
+ {0xaf, 0xd8},
+ {0xb0, 0xe2},
+ {0xb1, 0xe8},
+};
+
+struct OV7692_WREG ov7692_contrast_lv2_tbl[] = {
+ /*Contrast -2*/
+ {0xb2, 0x18},
+ {0xa3, 0x31},
+ {0xa4, 0x39},
+ {0xa5, 0x4a},
+ {0xa6, 0x68},
+ {0xa7, 0x77},
+ {0xa8, 0x84},
+ {0xa9, 0x90},
+ {0xaa, 0x9b},
+ {0xab, 0xa5},
+ {0xac, 0xaf},
+ {0xad, 0xbe},
+ {0xae, 0xca},
+ {0xaf, 0xdc},
+ {0xb0, 0xe7},
+ {0xb1, 0xee},
+};
+
+struct OV7692_WREG ov7692_contrast_lv3_tbl[] = {
+ /*Contrast -1*/
+ {0xb2, 0x10},
+ {0xa3, 0x1f},
+ {0xa4, 0x28},
+ {0xa5, 0x3b},
+ {0xa6, 0x5d},
+ {0xa7, 0x6e},
+ {0xa8, 0x7d},
+ {0xa9, 0x8a},
+ {0xaa, 0x96},
+ {0xab, 0xa2},
+ {0xac, 0xad},
+ {0xad, 0xbe},
+ {0xae, 0xcc},
+ {0xaf, 0xe0},
+ {0xb0, 0xed},
+ {0xb1, 0xf4},
+};
+
+struct OV7692_WREG ov7692_contrast_default_lv4_tbl[] = {
+ /*Contrast 0*/
+ {0xb2, 0x6},
+ {0xa3, 0xb},
+ {0xa4, 0x15},
+ {0xa5, 0x2a},
+ {0xa6, 0x51},
+ {0xa7, 0x63},
+ {0xa8, 0x74},
+ {0xa9, 0x83},
+ {0xaa, 0x91},
+ {0xab, 0x9e},
+ {0xac, 0xaa},
+ {0xad, 0xbe},
+ {0xae, 0xce},
+ {0xaf, 0xe5},
+ {0xb0, 0xf3},
+ {0xb1, 0xfb},
+};
+
+struct OV7692_WREG ov7692_contrast_lv5_tbl[] = {
+ /*Contrast 1*/
+ {0xb2, 0xc},
+ {0xa3, 0x4},
+ {0xa4, 0xc},
+ {0xa5, 0x1f},
+ {0xa6, 0x45},
+ {0xa7, 0x58},
+ {0xa8, 0x6b},
+ {0xa9, 0x7c},
+ {0xaa, 0x8d},
+ {0xab, 0x9d},
+ {0xac, 0xac},
+ {0xad, 0xc3},
+ {0xae, 0xd2},
+ {0xaf, 0xe8},
+ {0xb0, 0xf2},
+ {0xb1, 0xf7},
+};
+
+struct OV7692_WREG ov7692_contrast_lv6_tbl[] = {
+ /*Contrast 2*/
+ {0xb2, 0x1},
+ {0xa3, 0x2},
+ {0xa4, 0x9},
+ {0xa5, 0x1a},
+ {0xa6, 0x3e},
+ {0xa7, 0x4a},
+ {0xa8, 0x59},
+ {0xa9, 0x6a},
+ {0xaa, 0x79},
+ {0xab, 0x8e},
+ {0xac, 0xa4},
+ {0xad, 0xc1},
+ {0xae, 0xdb},
+ {0xaf, 0xf4},
+ {0xb0, 0xff},
+ {0xb1, 0xff},
+};
+
+struct OV7692_WREG ov7692_contrast_lv7_tbl[] = {
+ /*Contrast 3*/
+ {0xb2, 0xc},
+ {0xa3, 0x4},
+ {0xa4, 0x8},
+ {0xa5, 0x17},
+ {0xa6, 0x27},
+ {0xa7, 0x3d},
+ {0xa8, 0x54},
+ {0xa9, 0x60},
+ {0xaa, 0x77},
+ {0xab, 0x85},
+ {0xac, 0xa4},
+ {0xad, 0xc6},
+ {0xae, 0xd2},
+ {0xaf, 0xe9},
+ {0xb0, 0xf0},
+ {0xb1, 0xf7},
+};
+
+struct OV7692_WREG ov7692_contrast_lv8_tbl[] = {
+ /*Contrast 4*/
+ {0xb2, 0x1},
+ {0xa3, 0x4},
+ {0xa4, 0x4},
+ {0xa5, 0x7},
+ {0xa6, 0xb},
+ {0xa7, 0x17},
+ {0xa8, 0x2a},
+ {0xa9, 0x41},
+ {0xaa, 0x59},
+ {0xab, 0x6b},
+ {0xac, 0x8b},
+ {0xad, 0xb1},
+ {0xae, 0xd2},
+ {0xaf, 0xea},
+ {0xb0, 0xf4},
+ {0xb1, 0xff},
+};
+
+ /*Sharpness*/
+struct OV7692_WREG ov7692_sharpness_lv0_tbl[] = {
+ /*Sharpness 0*/
+ {0xb4, 0x20, INVMASK(0x20)},
+ {0xb6, 0x00, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv1_tbl[] = {
+ /*Sharpness 1*/
+ {0xb4, 0x20, INVMASK(0x20)},
+ {0xb6, 0x01, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_default_lv2_tbl[] = {
+ /*Sharpness Auto (Default)*/
+ {0xb4, 0x00, INVMASK(0x20)},
+ {0xb6, 0x00, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv3_tbl[] = {
+ /*Sharpness 3*/
+ {0xb4, 0x20, INVMASK(0x20)},
+ {0xb6, 0x66, INVMASK(0x04)},
+};
+struct OV7692_WREG ov7692_sharpness_lv4_tbl[] = {
+ /*Sharpness 4*/
+ {0xb4, 0x20, INVMASK(0x20)},
+ {0xb6, 0x99, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv5_tbl[] = {
+ /*Sharpness 5*/
+ {0xb4, 0x20, INVMASK(0x20)},
+ {0xb6, 0xcc, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv6_tbl[] = {
+ /*Sharpness 6*/
+ {0xb4, 0x20, INVMASK(0x20)},
+ {0xb6, 0xff, INVMASK(0x1f)},
+};
+
+ /* ISO TYPE*/
+struct OV7692_WREG ov7692_iso_type_auto[] = {
+ /*@@ISO Auto*/
+ {0x14, 0x20, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_100[] = {
+ /*@@ISO 100*/
+ {0x14, 0x00, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_200[] = {
+ /*@@ISO 200*/
+ {0x14, 0x10, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_400[] = {
+ /*@@ISO 400*/
+ {0x14, 0x20, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_800[] = {
+ /*@@ISO 800*/
+ {0x14, 0x30, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_1600[] = {
+ /*@@ISO 1600*/
+ {0x14, 0x40, INVMASK(0x70)},
+};
+
+ /*Light Mode*/
+struct OV7692_WREG ov7692_wb_def[] = {
+ {0x13, 0xf7},
+ {0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_custom[] = {
+ {0x13, 0xf5},
+ {0x01, 0x56},
+ {0x02, 0x50},
+ {0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_inc[] = {
+ {0x13, 0xf5},
+ {0x01, 0x66},
+ {0x02, 0x40},
+ {0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_daylight[] = {
+ {0x13, 0xf5},
+ {0x01, 0x43},
+ {0x02, 0x5d},
+ {0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_cloudy[] = {
+ {0x13, 0xf5},
+ {0x01, 0x48},
+ {0x02, 0x63},
+ {0x15, 0x00},
+};
+
#endif
diff --git a/drivers/media/video/msm/ov7692_qrd.c b/drivers/media/video/msm/ov7692_qrd.c
index e558e57..d83f28e 100644
--- a/drivers/media/video/msm/ov7692_qrd.c
+++ b/drivers/media/video/msm/ov7692_qrd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,8 +10,6 @@
* GNU General Public License for more details.
*/
-/* #define DEBUG */
-
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/i2c.h>
@@ -52,129 +50,9 @@
/*============================================================================
- DATA DECLARATIONS
- ============================================================================*/
-/* 96MHz PCLK @ 24MHz MCLK */
-struct reg_addr_val_pair_struct ov7692_init_settings_array[] = {
- {0x12, 0x80},
- {0x0e, 0x08},
- {0x69, 0x52},
- {0x1e, 0xb3},
- {0x48, 0x42},
- {0xff, 0x01},
- {0xae, 0xa0},
- {0xa8, 0x26},
- {0xb4, 0xc0},
- {0xb5, 0x40},
- {0xff, 0x00},
- {0x0c, 0x00},
- {0x62, 0x10},
- {0x12, 0x00},
- {0x17, 0x65},
- {0x18, 0xa4},
- {0x19, 0x0a},
- {0x1a, 0xf6},
- {0x3e, 0x30},
- {0x64, 0x0a},
- {0xff, 0x01},
- {0xb4, 0xc0},
- {0xff, 0x00},
- {0x67, 0x20},
- {0x81, 0x3f},
- {0xcc, 0x02},
- {0xcd, 0x80},
- {0xce, 0x01},
- {0xcf, 0xe0},
- {0xc8, 0x02},
- {0xc9, 0x80},
- {0xca, 0x01},
- {0xcb, 0xe0},
- {0xd0, 0x48},
- {0x82, 0x03},
- {0x0e, 0x00},
- {0x70, 0x00},
- {0x71, 0x34},
- {0x74, 0x28},
- {0x75, 0x98},
- {0x76, 0x00},
- {0x77, 0x64},
- {0x78, 0x01},
- {0x79, 0xc2},
- {0x7a, 0x4e},
- {0x7b, 0x1f},
- {0x7c, 0x00},
- {0x11, 0x00},
- {0x20, 0x00},
- {0x21, 0x23},
- {0x50, 0x9a},
- {0x51, 0x80},
- {0x4c, 0x7d},
- {0x0e, 0x00},
- {0x85, 0x10},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x00},
- {0x89, 0x2a},
- {0x8a, 0x26},
- {0x8b, 0x22},
- {0xbb, 0x7a},
- {0xbc, 0x69},
- {0xbd, 0x11},
- {0xbe, 0x13},
- {0xbf, 0x81},
- {0xc0, 0x96},
- {0xc1, 0x1e},
- {0xb7, 0x05},
- {0xb8, 0x09},
- {0xb9, 0x00},
- {0xba, 0x18},
- {0x5a, 0x1f},
- {0x5b, 0x9f},
- {0x5c, 0x6a},
- {0x5d, 0x42},
- {0x24, 0x78},
- {0x25, 0x68},
- {0x26, 0xb3},
- {0xa3, 0x0b},
- {0xa4, 0x15},
- {0xa5, 0x2a},
- {0xa6, 0x51},
- {0xa7, 0x63},
- {0xa8, 0x74},
- {0xa9, 0x83},
- {0xaa, 0x91},
- {0xab, 0x9e},
- {0xac, 0xaa},
- {0xad, 0xbe},
- {0xae, 0xce},
- {0xaf, 0xe5},
- {0xb0, 0xf3},
- {0xb1, 0xfb},
- {0xb2, 0x06},
- {0x8c, 0x5c},
- {0x8d, 0x11},
- {0x8e, 0x12},
- {0x8f, 0x19},
- {0x90, 0x50},
- {0x91, 0x20},
- {0x92, 0x96},
- {0x93, 0x80},
- {0x94, 0x13},
- {0x95, 0x1b},
- {0x96, 0xff},
- {0x97, 0x00},
- {0x98, 0x3d},
- {0x99, 0x36},
- {0x9a, 0x51},
- {0x9b, 0x43},
- {0x9c, 0xf0},
- {0x9d, 0xf0},
- {0x9e, 0xf0},
- {0x9f, 0xff},
- {0xa0, 0x68},
- {0xa1, 0x62},
- {0xa2, 0x0e},
-};
+ DATA DECLARATIONS
+============================================================================*/
+
static bool OV7692_CSI_CONFIG;
/* 816x612, 24MHz MCLK 96MHz PCLK */
@@ -214,6 +92,10 @@
static struct ov7692_ctrl_t *ov7692_ctrl;
static DECLARE_WAIT_QUEUE_HEAD(ov7692_wait_queue);
DEFINE_MUTEX(ov7692_mut);
+static int effect_value;
+static int16_t ov7692_effect = CAMERA_EFFECT_OFF;
+static unsigned int SAT_U = 0x80;
+static unsigned int SAT_V = 0x80;
/*=============================================================*/
@@ -284,14 +166,33 @@
memset(buf, 0, sizeof(buf));
buf[0] = waddr;
buf[1] = bdata;
-
+ CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
rc = ov7692_i2c_txdata(ov7692_client->addr >> 1, buf, 2);
if (rc < 0)
CDBG("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
- waddr, bdata);
+ waddr, bdata);
+
return rc;
}
+static int32_t OV7692_WritePRegs(struct OV7692_WREG *pTb, int32_t len)
+{
+ int32_t i, ret = 0;
+ uint8_t regv;
+
+ for (i = 0; i < len; i++) {
+ if (pTb[i].mask == 0) {
+ ov7692_i2c_write_b_sensor(pTb[i].addr, pTb[i].data);
+ } else {
+ ov7692_i2c_read(pTb[i].addr, ®v, 1);
+ regv &= pTb[i].mask;
+ regv |= (pTb[i].data & (~pTb[i].mask));
+ ov7692_i2c_write_b_sensor(pTb[i].addr, regv);
+ }
+ }
+ return ret;
+}
+
static int32_t ov7692_sensor_setting(int update_type, int rt)
{
int32_t i, array_length;
@@ -314,8 +215,6 @@
ov7692_csi_params.dpcm_scheme = 0;
ov7692_csi_params.settle_cnt = 0x14;
- rc = msm_camio_csi_config(&ov7692_csi_params);
- msleep(20);
array_length = sizeof(ov7692_init_settings_array) /
sizeof(ov7692_init_settings_array[0]);
for (i = 0; i < array_length; i++) {
@@ -325,6 +224,10 @@
if (rc < 0)
return rc;
}
+ usleep_range(10000, 11000);
+ rc = msm_camio_csi_config(&ov7692_csi_params);
+ usleep_range(10000, 11000);
+ ov7692_i2c_write_b_sensor(0x0e, 0x00);
OV7692_CSI_CONFIG = 1;
msleep(20);
return rc;
@@ -371,6 +274,442 @@
return rc;
}
+static int ov7692_set_exposure_compensation(int compensation)
+{
+ long rc = 0;
+
+ CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+ CDBG("--CAMERA-- %s ...exposure_compensation = %d\n",
+ __func__ , compensation);
+ switch (compensation) {
+ case CAMERA_EXPOSURE_COMPENSATION_LV0:
+ CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV0\n");
+ rc = OV7692Core_WritePREG(
+ ov7692_exposure_compensation_lv0_tbl);
+ break;
+ case CAMERA_EXPOSURE_COMPENSATION_LV1:
+ CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV1\n");
+ rc = OV7692Core_WritePREG(
+ ov7692_exposure_compensation_lv1_tbl);
+ break;
+ case CAMERA_EXPOSURE_COMPENSATION_LV2:
+ CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV2\n");
+ rc = OV7692Core_WritePREG(
+ ov7692_exposure_compensation_lv2_default_tbl);
+ break;
+ case CAMERA_EXPOSURE_COMPENSATION_LV3:
+ CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV3\n");
+ rc = OV7692Core_WritePREG(
+ ov7692_exposure_compensation_lv3_tbl);
+ break;
+ case CAMERA_EXPOSURE_COMPENSATION_LV4:
+ CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV3\n");
+ rc = OV7692Core_WritePREG(
+ ov7692_exposure_compensation_lv4_tbl);
+ break;
+ default:
+ CDBG("--CAMERA--ERROR CAMERA_EXPOSURE_COMPENSATION\n");
+ break;
+ }
+ CDBG("--CAMERA-- %s ...(End)\n", __func__);
+ return rc;
+}
+
+static long ov7692_set_antibanding(int antibanding)
+{
+ long rc = 0;
+
+ CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+ CDBG("--CAMERA-- %s ...antibanding = %d\n", __func__, antibanding);
+ switch (antibanding) {
+ case CAMERA_ANTIBANDING_OFF:
+ CDBG("--CAMERA--CAMERA_ANTIBANDING_OFF\n");
+ break;
+ case CAMERA_ANTIBANDING_60HZ:
+ CDBG("--CAMERA--CAMERA_ANTIBANDING_60HZ\n");
+ rc = OV7692Core_WritePREG(ov7692_antibanding_60z_tbl);
+ break;
+ case CAMERA_ANTIBANDING_50HZ:
+ CDBG("--CAMERA--CAMERA_ANTIBANDING_50HZ\n");
+ rc = OV7692Core_WritePREG(ov7692_antibanding_50z_tbl);
+ break;
+ case CAMERA_ANTIBANDING_AUTO:
+ CDBG("--CAMERA--CAMERA_ANTIBANDING_AUTO\n");
+ rc = OV7692Core_WritePREG(ov7692_antibanding_auto_tbl);
+ break;
+ default:
+ CDBG("--CAMERA--CAMERA_ANTIBANDING_ERROR COMMAND\n");
+ break;
+ }
+ CDBG("--CAMERA-- %s ...(End)\n", __func__);
+ return rc;
+}
+
+static int ov7692_set_saturation(int saturation)
+{
+ long rc = 0;
+
+ CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+ CDBG("--CAMERA-- %s ...saturation = %d\n", __func__ , saturation);
+
+ if (effect_value == CAMERA_EFFECT_OFF) {
+ switch (saturation) {
+ case CAMERA_SATURATION_LV0:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV0\n");
+ rc = OV7692Core_WritePREG(ov7692_saturation_lv0_tbl);
+ break;
+ case CAMERA_SATURATION_LV1:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV1\n");
+ rc = OV7692Core_WritePREG(ov7692_saturation_lv1_tbl);
+ break;
+ case CAMERA_SATURATION_LV2:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV2\n");
+ rc = OV7692Core_WritePREG(ov7692_saturation_lv2_tbl);
+ break;
+ case CAMERA_SATURATION_LV3:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV3\n");
+ rc = OV7692Core_WritePREG(ov7692_saturation_lv3_tbl);
+ break;
+ case CAMERA_SATURATION_LV4:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV4\n");
+ rc = OV7692Core_WritePREG(
+ ov7692_saturation_default_lv4_tbl);
+ break;
+ case CAMERA_SATURATION_LV5:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV5\n");
+ rc = OV7692Core_WritePREG(ov7692_saturation_lv5_tbl);
+ break;
+ case CAMERA_SATURATION_LV6:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV6\n");
+ rc = OV7692Core_WritePREG(ov7692_saturation_lv6_tbl);
+ break;
+ case CAMERA_SATURATION_LV7:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV7\n");
+ rc = OV7692Core_WritePREG(ov7692_saturation_lv7_tbl);
+ break;
+ case CAMERA_SATURATION_LV8:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV8\n");
+ rc = OV7692Core_WritePREG(ov7692_saturation_lv8_tbl);
+ break;
+ default:
+ CDBG("--CAMERA--CAMERA_SATURATION_ERROR COMMAND\n");
+ break;
+ }
+ }
+
+ /*for recover saturation level when change special effect*/
+ switch (saturation) {
+ case CAMERA_SATURATION_LV0:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV0\n");
+ SAT_U = 0x00;
+ SAT_V = 0x00;
+ break;
+ case CAMERA_SATURATION_LV1:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV1\n");
+ SAT_U = 0x10;
+ SAT_V = 0x10;
+ break;
+ case CAMERA_SATURATION_LV2:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV2\n");
+ SAT_U = 0x20;
+ SAT_V = 0x20;
+ break;
+ case CAMERA_SATURATION_LV3:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV3\n");
+ SAT_U = 0x30;
+ SAT_V = 0x30;
+ break;
+ case CAMERA_SATURATION_LV4:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV4\n");
+ SAT_U = 0x40;
+ SAT_V = 0x40;
+ break;
+ case CAMERA_SATURATION_LV5:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV5\n");
+ SAT_U = 0x50;
+ SAT_V = 0x50;
+ break;
+ case CAMERA_SATURATION_LV6:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV6\n");
+ SAT_U = 0x60;
+ SAT_V = 0x60;
+ break;
+ case CAMERA_SATURATION_LV7:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV7\n");
+ SAT_U = 0x70;
+ SAT_V = 0x70;
+ break;
+ case CAMERA_SATURATION_LV8:
+ CDBG("--CAMERA--CAMERA_SATURATION_LV8\n");
+ SAT_U = 0x80;
+ SAT_V = 0x80;
+ break;
+ default:
+ CDBG("--CAMERA--CAMERA_SATURATION_ERROR COMMAND\n");
+ break;
+ }
+ CDBG("--CAMERA-- %s ...(End)\n", __func__);
+ return rc;
+}
+
+static long ov7692_set_effect(int mode, int effect)
+{
+ int rc = 0;
+ CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+
+ switch (mode) {
+ case SENSOR_PREVIEW_MODE:
+ break;
+ case SENSOR_HFR_60FPS_MODE:
+ break;
+ case SENSOR_HFR_90FPS_MODE:
+ /* Context A Special Effects */
+ CDBG("-CAMERA- %s ...SENSOR_PREVIEW_MODE\n", __func__);
+ break;
+ case SENSOR_SNAPSHOT_MODE:
+ /* Context B Special Effects */
+ CDBG("-CAMERA- %s ...SENSOR_SNAPSHOT_MODE\n", __func__);
+ break;
+ default:
+ break;
+ }
+ effect_value = effect;
+ switch (effect) {
+ case CAMERA_EFFECT_OFF: {
+ CDBG("--CAMERA-- %s ...CAMERA_EFFECT_OFF\n", __func__);
+ rc = OV7692Core_WritePREG(ov7692_effect_normal_tbl);
+ /* for recover saturation level
+ when change special effect*/
+ ov7692_i2c_write_b_sensor(0xda, SAT_U);
+ /* for recover saturation level
+ when change special effect*/
+ ov7692_i2c_write_b_sensor(0xdb, SAT_V);
+ break;
+ }
+ case CAMERA_EFFECT_MONO: {
+ CDBG("--CAMERA-- %s ...CAMERA_EFFECT_MONO\n", __func__);
+ rc = OV7692Core_WritePREG(ov7692_effect_mono_tbl);
+ break;
+ }
+ case CAMERA_EFFECT_BW: {
+ CDBG("--CAMERA-- %s ...CAMERA_EFFECT_BW\n", __func__);
+ rc = OV7692Core_WritePREG(ov7692_effect_bw_tbl);
+ break;
+ }
+ case CAMERA_EFFECT_BLUISH: {
+ CDBG("--CAMERA-- %s ...CAMERA_EFFECT_BLUISH\n", __func__);
+ rc = OV7692Core_WritePREG(ov7692_effect_bluish_tbl);
+ break;
+ }
+ case CAMERA_EFFECT_SOLARIZE: {
+ CDBG("%s ...CAMERA_EFFECT_NEGATIVE(No Support)!\n", __func__);
+ break;
+ }
+ case CAMERA_EFFECT_SEPIA: {
+ CDBG("--CAMERA-- %s ...CAMERA_EFFECT_SEPIA\n", __func__);
+ rc = OV7692Core_WritePREG(ov7692_effect_sepia_tbl);
+ break;
+ }
+ case CAMERA_EFFECT_REDDISH: {
+ CDBG("--CAMERA-- %s ...CAMERA_EFFECT_REDDISH\n", __func__);
+ rc = OV7692Core_WritePREG(ov7692_effect_reddish_tbl);
+ break;
+ }
+ case CAMERA_EFFECT_GREENISH: {
+ CDBG("--CAMERA-- %s ...CAMERA_EFFECT_GREENISH\n", __func__);
+ rc = OV7692Core_WritePREG(ov7692_effect_greenish_tbl);
+ break;
+ }
+ case CAMERA_EFFECT_NEGATIVE: {
+ CDBG("--CAMERA-- %s ...CAMERA_EFFECT_NEGATIVE\n", __func__);
+ rc = OV7692Core_WritePREG(ov7692_effect_negative_tbl);
+ break;
+ }
+ default: {
+ CDBG("--CAMERA-- %s ...Default(Not Support)\n", __func__);
+ }
+ }
+ ov7692_effect = effect;
+ /*Refresh Sequencer */
+ CDBG("--CAMERA-- %s ...(End)\n", __func__);
+ return rc;
+}
+
+static int ov7692_set_contrast(int contrast)
+{
+ int rc = 0;
+ CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+ CDBG("--CAMERA-- %s ...contrast = %d\n", __func__ , contrast);
+
+ if (effect_value == CAMERA_EFFECT_OFF) {
+ switch (contrast) {
+ case CAMERA_CONTRAST_LV0:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV0\n");
+ rc = OV7692Core_WritePREG(ov7692_contrast_lv0_tbl);
+ break;
+ case CAMERA_CONTRAST_LV1:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV1\n");
+ rc = OV7692Core_WritePREG(ov7692_contrast_lv1_tbl);
+ break;
+ case CAMERA_CONTRAST_LV2:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV2\n");
+ rc = OV7692Core_WritePREG(ov7692_contrast_lv2_tbl);
+ break;
+ case CAMERA_CONTRAST_LV3:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV3\n");
+ rc = OV7692Core_WritePREG(ov7692_contrast_lv3_tbl);
+ break;
+ case CAMERA_CONTRAST_LV4:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV4\n");
+ rc = OV7692Core_WritePREG(
+ ov7692_contrast_default_lv4_tbl);
+ break;
+ case CAMERA_CONTRAST_LV5:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV5\n");
+ rc = OV7692Core_WritePREG(ov7692_contrast_lv5_tbl);
+ break;
+ case CAMERA_CONTRAST_LV6:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV6\n");
+ rc = OV7692Core_WritePREG(ov7692_contrast_lv6_tbl);
+ break;
+ case CAMERA_CONTRAST_LV7:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV7\n");
+ rc = OV7692Core_WritePREG(ov7692_contrast_lv7_tbl);
+ break;
+ case CAMERA_CONTRAST_LV8:
+ CDBG("--CAMERA--CAMERA_CONTRAST_LV8\n");
+ rc = OV7692Core_WritePREG(ov7692_contrast_lv8_tbl);
+ break;
+ default:
+ CDBG("--CAMERA--CAMERA_CONTRAST_ERROR COMMAND\n");
+ break;
+ }
+ }
+ CDBG("--CAMERA-- %s ...(End)\n", __func__);
+ return rc;
+}
+
+static int ov7692_set_sharpness(int sharpness)
+{
+ int rc = 0;
+ CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+ CDBG("--CAMERA-- %s ...sharpness = %d\n", __func__ , sharpness);
+
+ if (effect_value == CAMERA_EFFECT_OFF) {
+ switch (sharpness) {
+ case CAMERA_SHARPNESS_LV0:
+ CDBG("--CAMERA--CAMERA_SHARPNESS_LV0\n");
+ rc = OV7692Core_WritePREG(ov7692_sharpness_lv0_tbl);
+ break;
+ case CAMERA_SHARPNESS_LV1:
+ CDBG("--CAMERA--CAMERA_SHARPNESS_LV1\n");
+ rc = OV7692Core_WritePREG(ov7692_sharpness_lv1_tbl);
+ break;
+ case CAMERA_SHARPNESS_LV2:
+ CDBG("--CAMERA--CAMERA_SHARPNESS_LV2\n");
+ rc = OV7692Core_WritePREG(
+ ov7692_sharpness_default_lv2_tbl);
+ break;
+ case CAMERA_SHARPNESS_LV3:
+ CDBG("--CAMERA--CAMERA_SHARPNESS_LV3\n");
+ rc = OV7692Core_WritePREG(ov7692_sharpness_lv3_tbl);
+ break;
+ case CAMERA_SHARPNESS_LV4:
+ CDBG("--CAMERA--CAMERA_SHARPNESS_LV4\n");
+ rc = OV7692Core_WritePREG(ov7692_sharpness_lv4_tbl);
+ break;
+ case CAMERA_SHARPNESS_LV5:
+ CDBG("--CAMERA--CAMERA_SHARPNESS_LV5\n");
+ rc = OV7692Core_WritePREG(ov7692_sharpness_lv5_tbl);
+ break;
+ case CAMERA_SHARPNESS_LV6:
+ CDBG("--CAMERA--CAMERA_SHARPNESS_LV6\n");
+ rc = OV7692Core_WritePREG(ov7692_sharpness_lv6_tbl);
+ break;
+ default:
+ CDBG("--CAMERA--CAMERA_SHARPNESS_ERROR COMMAND\n");
+ break;
+ }
+ }
+ CDBG("--CAMERA-- %s ...(End)\n", __func__);
+ return rc;
+}
+
+static int ov7692_set_iso(int8_t iso_type)
+{
+ long rc = 0;
+
+ CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+ CDBG("--CAMERA-- %s ...iso_type = %d\n", __func__ , iso_type);
+ switch (iso_type) {
+ case CAMERA_ISO_TYPE_AUTO:
+ CDBG("--CAMERA--CAMERA_ISO_TYPE_AUTO\n");
+ rc = OV7692Core_WritePREG(ov7692_iso_type_auto);
+ break;
+ case CAMEAR_ISO_TYPE_HJR:
+ CDBG("--CAMERA--CAMEAR_ISO_TYPE_HJR\n");
+ rc = OV7692Core_WritePREG(ov7692_iso_type_auto);
+ break;
+ case CAMEAR_ISO_TYPE_100:
+ CDBG("--CAMERA--CAMEAR_ISO_TYPE_100\n");
+ rc = OV7692Core_WritePREG(ov7692_iso_type_100);
+ break;
+ case CAMERA_ISO_TYPE_200:
+ CDBG("--CAMERA--CAMERA_ISO_TYPE_200\n");
+ rc = OV7692Core_WritePREG(ov7692_iso_type_200);
+ break;
+ case CAMERA_ISO_TYPE_400:
+ CDBG("--CAMERA--CAMERA_ISO_TYPE_400\n");
+ rc = OV7692Core_WritePREG(ov7692_iso_type_400);
+ break;
+ case CAMEAR_ISO_TYPE_800:
+ CDBG("--CAMERA--CAMEAR_ISO_TYPE_800\n");
+ rc = OV7692Core_WritePREG(ov7692_iso_type_800);
+ break;
+ case CAMERA_ISO_TYPE_1600:
+ CDBG("--CAMERA--CAMERA_ISO_TYPE_1600\n");
+ rc = OV7692Core_WritePREG(ov7692_iso_type_1600);
+ break;
+ default:
+ CDBG("--CAMERA--ERROR ISO TYPE\n");
+ break;
+ }
+ CDBG("--CAMERA-- %s ...(End)\n", __func__);
+ return rc;
+}
+
+static int ov7692_set_wb_oem(uint8_t param)
+{
+ int rc = 0;
+ CDBG("--CAMERA--%s runs\r\n", __func__);
+
+ switch (param) {
+ case CAMERA_WB_AUTO:
+ CDBG("--CAMERA--CAMERA_WB_AUTO\n");
+ rc = OV7692Core_WritePREG(ov7692_wb_def);
+ break;
+ case CAMERA_WB_CUSTOM:
+ CDBG("--CAMERA--CAMERA_WB_CUSTOM\n");
+ rc = OV7692Core_WritePREG(ov7692_wb_custom);
+ break;
+ case CAMERA_WB_INCANDESCENT:
+ CDBG("--CAMERA--CAMERA_WB_INCANDESCENT\n");
+ rc = OV7692Core_WritePREG(ov7692_wb_inc);
+ break;
+ case CAMERA_WB_DAYLIGHT:
+ CDBG("--CAMERA--CAMERA_WB_DAYLIGHT\n");
+ rc = OV7692Core_WritePREG(ov7692_wb_daylight);
+ break;
+ case CAMERA_WB_CLOUDY_DAYLIGHT:
+ CDBG("--CAMERA--CAMERA_WB_CLOUDY_DAYLIGHT\n");
+ rc = OV7692Core_WritePREG(ov7692_wb_cloudy);
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
+
static void ov7692_power_on(void)
{
CDBG("%s\n", __func__);
@@ -392,13 +731,12 @@
static void ov7692_hw_reset(void)
{
CDBG("--CAMERA-- %s ... (Start...)\n", __func__);
- gpio_set_value(ov7692_reset_gpio, 1); /* reset camera reset pin */
- msleep(20);
+ gpio_set_value(ov7692_reset_gpio, 1); /*reset camera reset pin*/
+ usleep_range(5000, 5100);
gpio_set_value(ov7692_reset_gpio, 0);
- msleep(20);
+ usleep_range(5000, 5100);
gpio_set_value(ov7692_reset_gpio, 1);
- msleep(20);
-
+ usleep_range(1000, 1100);
CDBG("--CAMERA-- %s ... (End...)\n", __func__);
}
@@ -458,6 +796,9 @@
if (data)
ov7692_ctrl->sensordata = data;
+ /* turn on LDO for PVT */
+ if (data->pmic_gpio_enable)
+ lcd_camera_power_onoff(1);
/* enable mclk first */
@@ -465,7 +806,7 @@
msleep(20);
ov7692_power_on();
- msleep(20);
+ usleep_range(5000, 5100);
rc = ov7692_probe_init_sensor(data);
if (rc < 0) {
@@ -481,6 +822,8 @@
init_fail:
CDBG(" ov7692_sensor_open_init fail\n");
+ if (data->pmic_gpio_enable)
+ lcd_camera_power_onoff(0);
kfree(ov7692_ctrl);
init_done:
CDBG("ov7692_sensor_open_init done\n");
@@ -559,14 +902,160 @@
CDBG("ov7692_sensor_config: cfgtype = %d\n", cdata.cfgtype);
switch (cdata.cfgtype) {
case CFG_SET_MODE:
- rc = ov7692_set_sensor_mode(cdata.mode,
- cdata.rs);
+ rc = ov7692_set_sensor_mode(cdata.mode, cdata.rs);
+ break;
+ case CFG_SET_EFFECT:
+ CDBG("--CAMERA-- CFG_SET_EFFECT mode=%d, effect = %d !!\n",
+ cdata.mode, cdata.cfg.effect);
+ rc = ov7692_set_effect(cdata.mode, cdata.cfg.effect);
+ break;
+ case CFG_START:
+ CDBG("--CAMERA-- CFG_START (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_PWR_UP:
+ CDBG("--CAMERA-- CFG_PWR_UP (Not Support) !!\n");
+ /* Not Support */
break;
case CFG_PWR_DOWN:
+ CDBG("--CAMERA-- CFG_PWR_DOWN !!\n");
ov7692_power_down();
break;
+ case CFG_WRITE_EXPOSURE_GAIN:
+ CDBG("--CAMERA-- CFG_WRITE_EXPOSURE_GAIN (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_DEFAULT_FOCUS:
+ CDBG("--CAMERA-- CFG_SET_DEFAULT_FOCUS (Not Implement) !!\n");
+ break;
+ case CFG_MOVE_FOCUS:
+ CDBG("--CAMERA-- CFG_MOVE_FOCUS (Not Implement) !!\n");
+ break;
+ case CFG_REGISTER_TO_REAL_GAIN:
+ CDBG("--CAMERA-- CFG_REGISTER_TO_REAL_GAIN (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_REAL_TO_REGISTER_GAIN:
+ CDBG("--CAMERA-- CFG_REAL_TO_REGISTER_GAIN (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_FPS:
+ CDBG("--CAMERA-- CFG_SET_FPS (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_PICT_FPS:
+ CDBG("--CAMERA-- CFG_SET_PICT_FPS (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_BRIGHTNESS:
+ CDBG("--CAMERA-- CFG_SET_BRIGHTNESS !!\n");
+ /* rc = ov7692_set_brightness(cdata.cfg.brightness); */
+ break;
+ case CFG_SET_CONTRAST:
+ CDBG("--CAMERA-- CFG_SET_CONTRAST !!\n");
+ rc = ov7692_set_contrast(cdata.cfg.contrast);
+ break;
+ case CFG_SET_ZOOM:
+ CDBG("--CAMERA-- CFG_SET_ZOOM (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_EXPOSURE_MODE:
+ CDBG("--CAMERA-- CFG_SET_EXPOSURE_MODE !!\n");
+ /* rc = ov7692_set_exposure_mode(cdata.cfg.ae_mode); */
+ break;
+ case CFG_SET_WB:
+ CDBG("--CAMERA-- CFG_SET_WB!!\n");
+ ov7692_set_wb_oem(cdata.cfg.wb_val);
+ rc = 0 ;
+ break;
+ case CFG_SET_ANTIBANDING:
+ CDBG("--CAMERA-- CFG_SET_ANTIBANDING antibanding = %d !!\n",
+ cdata.cfg.antibanding);
+ rc = ov7692_set_antibanding(cdata.cfg.antibanding);
+ break;
+ case CFG_SET_EXP_GAIN:
+ CDBG("--CAMERA-- CFG_SET_EXP_GAIN (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_PICT_EXP_GAIN:
+ CDBG("--CAMERA-- CFG_SET_PICT_EXP_GAIN (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_LENS_SHADING:
+ CDBG("--CAMERA-- CFG_SET_LENS_SHADING !!\n");
+ /* rc = ov7692_lens_shading_enable(cdata.cfg.lens_shading); */
+ break;
+ case CFG_GET_PICT_FPS:
+ CDBG("--CAMERA-- CFG_GET_PICT_FPS (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_GET_PREV_L_PF:
+ CDBG("--CAMERA-- CFG_GET_PREV_L_PF (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_GET_PREV_P_PL:
+ CDBG("--CAMERA-- CFG_GET_PREV_P_PL (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_GET_PICT_L_PF:
+ CDBG("--CAMERA-- CFG_GET_PICT_L_PF (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_GET_PICT_P_PL:
+ CDBG("--CAMERA-- CFG_GET_PICT_P_PL (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_GET_AF_MAX_STEPS:
+ CDBG("--CAMERA-- CFG_GET_AF_MAX_STEPS (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_GET_PICT_MAX_EXP_LC:
+ CDBG("--CAMERA-- CFG_GET_PICT_MAX_EXP_LC (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SEND_WB_INFO:
+ CDBG("--CAMERA-- CFG_SEND_WB_INFO (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SENSOR_INIT:
+ CDBG("--CAMERA-- CFG_SENSOR_INIT (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_SATURATION:
+ CDBG("--CAMERA-- CFG_SET_SATURATION !!\n");
+ rc = ov7692_set_saturation(cdata.cfg.saturation);
+ break;
+ case CFG_SET_SHARPNESS:
+ CDBG("--CAMERA-- CFG_SET_SHARPNESS !!\n");
+ rc = ov7692_set_sharpness(cdata.cfg.sharpness);
+ break;
+ case CFG_SET_TOUCHAEC:
+ CDBG("--CAMERA-- CFG_SET_TOUCHAEC!!\n");
+ /* ov7692_set_touchaec(cdata.cfg.aec_cord.x,
+ cdata.cfg.aec_cord.y); */
+ rc = 0 ;
+ break;
+ case CFG_SET_AUTO_FOCUS:
+ CDBG("--CAMERA-- CFG_SET_AUTO_FOCUS (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_AUTOFLASH:
+ CDBG("--CAMERA-- CFG_SET_AUTOFLASH (Not Support) !!\n");
+ /* Not Support */
+ break;
+ case CFG_SET_EXPOSURE_COMPENSATION:
+ CDBG("--CAMERA-- CFG_SET_EXPOSURE_COMPENSATION !\n");
+ rc = ov7692_set_exposure_compensation(
+ cdata.cfg.exp_compensation);
+ break;
+ case CFG_SET_ISO:
+ CDBG("--CAMERA-- CFG_SET_ISO !\n");
+ rc = ov7692_set_iso(cdata.cfg.iso_type);
+ break;
default:
- rc = -EFAULT;
+ CDBG("--CAMERA-- %s: Command=%d (Not Implement) !!\n",
+ __func__, cdata.cfgtype);
+ rc = -EINVAL;
break;
}
@@ -577,6 +1066,7 @@
static int ov7692_sensor_release(void)
{
int rc = -EBADF;
+
mutex_lock(&ov7692_mut);
ov7692_sw_reset();
ov7692_power_down();
@@ -614,20 +1104,23 @@
rc = -ENOTSUPP;
goto probe_fail;
}
-
+ pr_debug("%s: %d Entered\n", __func__, __LINE__);
rc = ov7692_probe_init_gpio(info);
if (rc < 0) {
CDBG("%s: gpio init failed\n", __func__);
goto probe_fail;
}
+ /* turn on LDO for PVT */
+ if (info->pmic_gpio_enable)
+ lcd_camera_power_onoff(1);
ov7692_power_down();
msm_camio_clk_rate_set(24000000);
- msleep(20);
+ usleep_range(5000, 5100);
ov7692_power_on();
- msleep(20);
+ usleep_range(5000, 5100);
if (info->sensor_reset_enable)
ov7692_hw_reset();
@@ -645,12 +1138,18 @@
s->s_camera_type = FRONT_CAMERA_2D;
s->s_mount_angle = info->sensor_platform_info->mount_angle;
+ /* ov7692_sw_reset(); */
ov7692_power_down();
+ if (info->pmic_gpio_enable)
+ lcd_camera_power_onoff(0);
+
return rc;
probe_fail:
CDBG("ov7692_sensor_probe: SENSOR PROBE FAILS!\n");
+ if (info->pmic_gpio_enable)
+ lcd_camera_power_onoff(0);
i2c_del_driver(&ov7692_i2c_driver);
return rc;
}
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index f31aece..92700f6 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -38,7 +38,7 @@
static struct msm_camera_i2c_reg_conf imx074_prev_settings[] = {
{0x0307, 0x2D}, /*pll_multiplier*/
{0x0340, 0x06}, /*frame_length_lines_hi*/
- {0x0341, 0x2D}, /*frame_length_lines_lo*/
+ {0x0341, 0x34}, /*frame_length_lines_lo*/
{0x0342, 0x11}, /*line_length_pclk_hi*/
{0x0343, 0x78}, /*line_length_pclk_lo*/
{0x0347, 0x00}, /*y_addr_start*/
@@ -161,9 +161,9 @@
.x_output = 0x838,
.y_output = 0x618,
.line_length_pclk = 0x1178,
- .frame_length_lines = 0x62D,
+ .frame_length_lines = 0x634,
.vt_pixel_clk = 216000000,
- .op_pixel_clk = 216000000,
+ .op_pixel_clk = 108000000,
.binning_factor = 2,
},
};
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d0b4f1f..cade3d6 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -13,6 +13,7 @@
#include "msm_sensor.h"
#include "msm.h"
#include "msm_ispif.h"
+#include "msm_camera_i2c_mux.h"
/*=============================================================*/
@@ -449,6 +450,26 @@
{"cam_clk", MSM_SENSOR_MCLK_24HZ},
};
+int32_t msm_sensor_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+ struct v4l2_subdev *i2c_mux_sd =
+ dev_get_drvdata(&i2c_conf->mux_dev->dev);
+ v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+ VIDIOC_MSM_I2C_MUX_INIT, NULL);
+ v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+ VIDIOC_MSM_I2C_MUX_CFG, (void *)&i2c_conf->i2c_mux_mode);
+ return 0;
+}
+
+int32_t msm_sensor_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+ struct v4l2_subdev *i2c_mux_sd =
+ dev_get_drvdata(&i2c_conf->mux_dev->dev);
+ v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+ VIDIOC_MSM_I2C_MUX_RELEASE, NULL);
+ return 0;
+}
+
int32_t msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
{
int32_t rc = 0;
@@ -506,6 +527,10 @@
if (data->sensor_platform_info->ext_power_ctrl != NULL)
data->sensor_platform_info->ext_power_ctrl(1);
+ if (data->sensor_platform_info->i2c_conf &&
+ data->sensor_platform_info->i2c_conf->use_i2c_mux)
+ msm_sensor_enable_i2c_mux(data->sensor_platform_info->i2c_conf);
+
return rc;
enable_clk_failed:
msm_camera_config_gpio_table(data, 0);
@@ -531,6 +556,11 @@
{
struct msm_camera_sensor_info *data = s_ctrl->sensordata;
CDBG("%s\n", __func__);
+ if (data->sensor_platform_info->i2c_conf &&
+ data->sensor_platform_info->i2c_conf->use_i2c_mux)
+ msm_sensor_disable_i2c_mux(
+ data->sensor_platform_info->i2c_conf);
+
if (data->sensor_platform_info->ext_power_ctrl != NULL)
data->sensor_platform_info->ext_power_ctrl(0);
msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index 2177991..954dd2f 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -114,8 +114,8 @@
{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
{0x0306, 0x00}, /* pll_multiplier */
{0x0307, 0xA5}, /* pll_multiplier */
- {0x0202, 0x02}, /* coarse_integration_time */
- {0x0203, 0x1C}, /* coarse_integration_time */
+ {0x0202, 0x03}, /* coarse_integration_time */
+ {0x0203, 0xD8}, /* coarse_integration_time */
{0x0340, 0x03}, /* frame_length_lines */
{0x0341, 0xE0}, /* frame_length_lines */
{0x0342, 0x14}, /* line_length_pck */
@@ -152,7 +152,7 @@
{0x0306, 0x00}, /* pll_multiplier */
{0x0307, 0xA5}, /* pll_multiplier */
{0x0202, 0x02}, /* coarse_integration_time */
- {0x0203, 0x1C}, /* coarse_integration_time */
+ {0x0203, 0x90}, /* coarse_integration_time */
{0x0340, 0x02}, /* frame_length_lines */
{0x0341, 0x98}, /* frame_length_lines */
{0x0342, 0x14}, /* line_length_pck */
@@ -188,10 +188,10 @@
{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
{0x0306, 0x00}, /* pll_multiplier */
{0x0307, 0xA5}, /* pll_multiplier */
- {0x0202, 0x02}, /* coarse_integration_time */
- {0x0203, 0x1C}, /* coarse_integration_time */
+ {0x0202, 0x01}, /* coarse_integration_time */
+ {0x0203, 0xFA}, /* coarse_integration_time */
{0x0340, 0x02}, /* frame_length_lines */
- {0x0341, 0x0D}, /* frame_length_lines */
+ {0x0341, 0x02}, /* frame_length_lines */
{0x0342, 0x14}, /* line_length_pck */
{0x0343, 0xD8}, /* line_length_pck */
{0x0344, 0x01}, /* x_addr_start */
@@ -519,7 +519,7 @@
.x_output = 864,
.y_output = 480,
.line_length_pclk = 5336,
- .frame_length_lines = 525,
+ .frame_length_lines = 514,
.vt_pixel_clk = 330000000,
.op_pixel_clk = 320000000,
.binning_factor = 1,
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 315705c..ce81746 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -35,6 +35,7 @@
#include "vsg-subdev.h"
#define WFD_VERSION KERNEL_VERSION(0, 0, 1)
+#define WFD_DEVICE_NUMBER 38
#define DEFAULT_WFD_WIDTH 640
#define DEFAULT_WFD_HEIGHT 480
#define VSG_SCRATCH_BUFFERS 1
@@ -1155,7 +1156,8 @@
wfd_dev->pvdev->fops = &g_wfd_fops;
wfd_dev->pvdev->ioctl_ops = &g_wfd_ioctl_ops;
- rc = video_register_device(wfd_dev->pvdev, VFL_TYPE_GRABBER, -1);
+ rc = video_register_device(wfd_dev->pvdev, VFL_TYPE_GRABBER,
+ WFD_DEVICE_NUMBER);
if (rc) {
WFD_MSG_ERR("Failed to register the device\n");
goto err_video_register_device;
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index e4d8bd5..8049975 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -42,7 +42,7 @@
#define PM8921_VERSION_MASK 0xFFF0
#define PM8921_VERSION_VALUE 0x06F0
#define PM8922_VERSION_VALUE 0x0AF0
-#define PM8917_VERSION_VALUE 0x12F0
+#define PM8917_VERSION_VALUE 0x0CF0
#define PM8921_REVISION_MASK 0x000F
#define REG_PM8921_PON_CNTRL_3 0x01D
@@ -427,9 +427,26 @@
NCP("8921_ncp", 0x090),
};
+/*
+ * PM8917 adds 6 LDOs and a boost regulator beyond those available on PM8921.
+ * It also replaces SMPS 3 with FTSMPS 3. PM8917 does not have an NCP.
+ */
+static struct pm8xxx_vreg pm8917_regulator_data[] = {
+ /* name pc_name ctrl test hpm_min */
+ PLDO("8917_l30", "8917_l30_pc", 0x0A3, 0x0A4, LDO_150),
+ PLDO("8917_l31", "8917_l31_pc", 0x0A5, 0x0A6, LDO_150),
+ PLDO("8917_l32", "8917_l32_pc", 0x0A7, 0x0A8, LDO_150),
+ PLDO("8917_l33", "8917_l33_pc", 0x0C6, 0x0C7, LDO_150),
+ PLDO("8917_l34", "8917_l34_pc", 0x0D2, 0x0D3, LDO_150),
+ PLDO("8917_l35", "8917_l35_pc", 0x0D4, 0x0D5, LDO_300),
+
+ /* name ctrl */
+ BOOST("8917_boost", 0x04B),
+};
+
#define MAX_NAME_COMPARISON_LEN 32
-static int __devinit match_regulator(
+static int __devinit match_regulator(enum pm8xxx_version version,
struct pm8xxx_regulator_core_platform_data *core_data, char *name)
{
int found = 0;
@@ -452,6 +469,25 @@
break;
}
}
+ if (version == PM8XXX_VERSION_8917) {
+ for (i = 0; i < ARRAY_SIZE(pm8917_regulator_data); i++) {
+ if (pm8917_regulator_data[i].rdesc.name
+ && strncmp(pm8917_regulator_data[i].rdesc.name,
+ name, MAX_NAME_COMPARISON_LEN) == 0) {
+ core_data->is_pin_controlled = false;
+ core_data->vreg = &pm8917_regulator_data[i];
+ found = 1;
+ break;
+ } else if (pm8917_regulator_data[i].rdesc_pc.name
+ && strncmp(pm8917_regulator_data[i].rdesc_pc.name,
+ name, MAX_NAME_COMPARISON_LEN) == 0) {
+ core_data->is_pin_controlled = true;
+ core_data->vreg = &pm8917_regulator_data[i];
+ found = 1;
+ break;
+ }
+ }
+ }
if (!found)
pr_err("could not find a match for regulator: %s\n", name);
@@ -466,8 +502,11 @@
int ret = 0;
struct mfd_cell *mfd_regulators;
struct pm8xxx_regulator_core_platform_data *cdata;
+ enum pm8xxx_version version;
int i;
+ version = pm8xxx_get_version(pmic->dev);
+
/* Add one device for each regulator used by the board. */
mfd_regulators = kzalloc(sizeof(struct mfd_cell)
* (pdata->num_regulators), GFP_KERNEL);
@@ -488,6 +527,8 @@
}
for (i = 0; i < ARRAY_SIZE(regulator_data); i++)
mutex_init(®ulator_data[i].pc_lock);
+ for (i = 0; i < ARRAY_SIZE(pm8917_regulator_data); i++)
+ mutex_init(&pm8917_regulator_data[i].pc_lock);
for (i = 0; i < pdata->num_regulators; i++) {
if (!pdata->regulator_pdatas[i].init_data.constraints.name) {
@@ -495,7 +536,7 @@
ret = -EINVAL;
goto bail;
}
- if (!match_regulator(&cdata[i],
+ if (!match_regulator(version, &cdata[i],
pdata->regulator_pdatas[i].init_data.constraints.name)) {
ret = -ENODEV;
goto bail;
@@ -519,6 +560,8 @@
bail:
for (i = 0; i < ARRAY_SIZE(regulator_data); i++)
mutex_destroy(®ulator_data[i].pc_lock);
+ for (i = 0; i < ARRAY_SIZE(pm8917_regulator_data); i++)
+ mutex_destroy(&pm8917_regulator_data[i].pc_lock);
kfree(mfd_regulators);
kfree(cdata);
return ret;
@@ -908,6 +951,9 @@
if (pmic->mfd_regulators) {
for (i = 0; i < ARRAY_SIZE(regulator_data); i++)
mutex_destroy(®ulator_data[i].pc_lock);
+ for (i = 0; i < ARRAY_SIZE(pm8917_regulator_data); i++)
+ mutex_destroy(
+ &pm8917_regulator_data[i].pc_lock);
}
kfree(pmic->mfd_regulators);
kfree(pmic->regulator_cdata);
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
index 14c9ec4..17b518e 100644
--- a/drivers/mfd/pm8xxx-irq.c
+++ b/drivers/mfd/pm8xxx-irq.c
@@ -102,6 +102,7 @@
goto bail;
}
+ cp &= ~PM_IRQF_WRITE;
rc = pm8xxx_writeb(chip->dev,
SSBI_REG_ADDR_IRQ_CONFIG(chip->base_addr), cp);
if (rc)
@@ -127,7 +128,10 @@
pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
goto bail;
}
-
+ /*
+ * Set the write bit here as this could be a unrequested irq
+ * whose PM_IRQF_WRITE bit is not set
+ */
cp |= PM_IRQF_WRITE;
rc = pm8xxx_writeb(chip->dev,
SSBI_REG_ADDR_IRQ_CONFIG(chip->base_addr), cp);
@@ -222,7 +226,7 @@
irq_bit = pmirq % 8;
if (chip->config[pmirq] == 0) {
- pr_warn("masking rouge irq=%d pmirq=%d\n", d->irq, pmirq);
+ pr_warn("masking rogue irq=%d pmirq=%d\n", d->irq, pmirq);
chip->config[pmirq] = irq_bit << PM_IRQF_BITS_SHIFT;
}
@@ -242,7 +246,7 @@
irq_bit = pmirq % 8;
if (chip->config[pmirq] == 0) {
- pr_warn("mask acking rouge irq=%d pmirq=%d\n", d->irq, pmirq);
+ pr_warn("mask acking rogue irq=%d pmirq=%d\n", d->irq, pmirq);
chip->config[pmirq] = irq_bit << PM_IRQF_BITS_SHIFT;
}
@@ -295,6 +299,12 @@
chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
}
+ /*
+ * The PM_IRQF_WRITE flag serves as an indication that this interrupt
+ * been requested
+ */
+ chip->config[pmirq] |= PM_IRQF_WRITE;
+
config = chip->config[pmirq] | PM_IRQF_CLR;
return pm8xxx_write_config_irq(chip, block, config);
}
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index eb0048a..b655848 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -139,6 +139,12 @@
#define PM8901_DELAY_AFTER_REG_DISABLE_MS 4
#define PM8901_DELAY_BEFORE_SHUTDOWN_MS 8
+#define REG_PM8XXX_XO_CNTRL_2 0x114
+#define MP3_1_MASK 0xE0
+#define MP3_2_MASK 0x1C
+#define MP3_1_SHIFT 5
+#define MP3_2_SHIFT 2
+
struct pm8xxx_misc_chip {
struct list_head link;
struct pm8xxx_misc_platform_data pdata;
@@ -540,7 +546,7 @@
case PM8XXX_VERSION_8018:
rc = pm8xxx_misc_masked_write(chip,
REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
- (enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+ (enable ? SLEEP_CTRL_SMPL_EN_RESET
: SLEEP_CTRL_SMPL_EN_PWR_OFF));
break;
case PM8XXX_VERSION_8058:
@@ -552,7 +558,7 @@
case PM8XXX_VERSION_8921:
rc = pm8xxx_misc_masked_write(chip,
REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
- (enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+ (enable ? SLEEP_CTRL_SMPL_EN_RESET
: SLEEP_CTRL_SMPL_EN_PWR_OFF));
break;
default:
@@ -1046,6 +1052,48 @@
}
EXPORT_SYMBOL_GPL(pm8xxx_preload_dVdd);
+int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+ enum pm8xxx_aux_clk_div divider, bool enable)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ u8 clk_mask = 0, value = 0;
+
+ if (clk_id == CLK_MP3_1) {
+ clk_mask = MP3_1_MASK;
+ value = divider << MP3_1_SHIFT;
+ } else if (clk_id == CLK_MP3_2) {
+ clk_mask = MP3_2_MASK;
+ value = divider << MP3_2_SHIFT;
+ } else {
+ pr_err("Invalid clock id of %d\n", clk_id);
+ return -EINVAL;
+ }
+ if (!enable)
+ value = 0;
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8038:
+ case PM8XXX_VERSION_8921:
+ pm8xxx_misc_masked_write(chip,
+ REG_PM8XXX_XO_CNTRL_2, clk_mask, value);
+ break;
+ default:
+ /* Functionality not supported */
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_aux_clk_control);
+
static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
{
const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index 87abcda..d1d9132 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.c
@@ -241,6 +241,12 @@
},
};
+static struct mfd_cell tabla1x_devs[] = {
+ {
+ .name = "tabla1x_codec",
+ },
+};
+
static void tabla_bring_up(struct tabla *tabla)
{
tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x4);
@@ -261,15 +267,6 @@
static int tabla_reset(struct tabla *tabla)
{
int ret;
- struct pm_gpio param = {
- .direction = PM_GPIO_DIR_OUT,
- .output_buffer = PM_GPIO_OUT_BUF_CMOS,
- .output_value = 1,
- .pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_S4,
- .out_strength = PM_GPIO_STRENGTH_MED,
- .function = PM_GPIO_FUNC_NORMAL,
- };
if (tabla->reset_gpio) {
ret = gpio_request(tabla->reset_gpio, "CDC_RESET");
@@ -280,10 +277,6 @@
return ret;
}
- ret = pm8xxx_gpio_config(tabla->reset_gpio, ¶m);
- if (ret)
- pr_err("%s: Failed to configure gpio\n", __func__);
-
gpio_direction_output(tabla->reset_gpio, 1);
msleep(20);
gpio_direction_output(tabla->reset_gpio, 0);
@@ -367,6 +360,8 @@
static int tabla_device_init(struct tabla *tabla, int irq)
{
int ret;
+ struct mfd_cell *tabla_dev;
+ int tabla_dev_size;
mutex_init(&tabla->io_lock);
mutex_init(&tabla->xfer_lock);
@@ -386,9 +381,19 @@
pr_err("IRQ initialization failed\n");
goto err;
}
+ tabla->version = tabla_reg_read(tabla, TABLA_A_CHIP_VERSION) & 0x1F;
+ pr_info("%s : Tabla version %u initialized\n",
+ __func__, tabla->version);
+ if (TABLA_IS_1_X(tabla->version)) {
+ tabla_dev = tabla1x_devs;
+ tabla_dev_size = ARRAY_SIZE(tabla1x_devs);
+ } else {
+ tabla_dev = tabla_devs;
+ tabla_dev_size = ARRAY_SIZE(tabla_devs);
+ }
ret = mfd_add_devices(tabla->dev, -1,
- tabla_devs, ARRAY_SIZE(tabla_devs),
+ tabla_dev, tabla_dev_size,
NULL, 0);
if (ret != 0) {
dev_err(tabla->dev, "Failed to add children: %d\n", ret);
@@ -647,7 +652,7 @@
struct tabla_i2c *tabla;
tabla = get_i2c_tabla_device_info(reg);
- if (tabla->client == NULL) {
+ if (tabla == NULL || tabla->client == NULL) {
pr_err("failed to get device info\n");
return -ENODEV;
}
@@ -684,7 +689,7 @@
u8 i = 0;
tabla = get_i2c_tabla_device_info(reg);
- if (tabla->client == NULL) {
+ if (tabla == NULL || tabla->client == NULL) {
pr_err("failed to get device info\n");
return -ENODEV;
}
@@ -753,12 +758,12 @@
if (!pdata) {
dev_dbg(&client->dev, "no platform data?\n");
ret = -EINVAL;
- goto fail;
+ goto err_tabla;
}
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
dev_dbg(&client->dev, "can't talk I2C?\n");
ret = -EIO;
- goto fail;
+ goto err_tabla;
}
tabla->dev = &client->dev;
tabla->reset_gpio = pdata->reset_gpio;
@@ -964,11 +969,9 @@
tabla = slim_get_devicedata(pdev);
tabla_deinit_slimslave(tabla);
- tabla_device_exit(tabla);
tabla_disable_supplies(tabla);
slim_remove_device(tabla->slim_slave);
- kfree(tabla);
-
+ tabla_device_exit(tabla);
return 0;
}
diff --git a/drivers/mfd/wcd9310-slimslave.c b/drivers/mfd/wcd9310-slimslave.c
index dd586fa..12ac27f 100644
--- a/drivers/mfd/wcd9310-slimslave.c
+++ b/drivers/mfd/wcd9310-slimslave.c
@@ -236,7 +236,7 @@
*/
if ((slave_port_id >
SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) &&
- (slave_port_id <
+ (slave_port_id <=
SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID)) {
payload_rx = payload_rx |
(1 <<
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 43eb169..0066cd8 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -627,6 +627,13 @@
TrustZone Operating Environment (TZBSP) using Secure Channel
Manager (SCM) interface.
+config QSEECOM
+ tristate "Qualcomm Secure Execution Communicator driver"
+ help
+ Provides a communication interface between userspace and
+ Qualcomm Secure Execution Environment (QSEE) using Secure Channel
+ Manager (SCM) interface.
+
config QFP_FUSE
tristate "QFPROM Fuse Read/Write support"
help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 6b5fdcc..fb78f4e 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -64,4 +64,5 @@
+= msm_migrate_pages.o
obj-$(CONFIG_PMIC8058_XOADC) += pmic8058-xoadc.o
obj-$(CONFIG_TZCOM) += tzcom.o
+obj-$(CONFIG_QSEECOM) += qseecom.o
obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
diff --git a/drivers/misc/pmem.c b/drivers/misc/pmem.c
index f0d523e..2f48d71 100644
--- a/drivers/misc/pmem.c
+++ b/drivers/misc/pmem.c
@@ -2785,7 +2785,8 @@
pmem[id].dev.name = pdata->name;
pmem[id].dev.minor = id;
pmem[id].dev.fops = &pmem_fops;
- pr_info("pmem: Initializing %s (user-space) as %s\n",
+ pmem[id].reusable = pdata->reusable;
+ pr_info("pmem: Initializing %s as %s\n",
pdata->name, pdata->cached ? "cached" : "non-cached");
if (misc_register(&pmem[id].dev)) {
@@ -2793,24 +2794,23 @@
goto err_cant_register_device;
}
- pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
- pmem[id].memory_type, PAGE_SIZE);
- if (!pmem[id].base) {
- pr_err("pmem: Cannot allocate from reserved memory for %s\n",
- pdata->name);
- goto err_misc_deregister;
+ if (!pmem[id].reusable) {
+ pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
+ pmem[id].memory_type, PAGE_SIZE);
+ if (!pmem[id].base) {
+ pr_err("pmem: Cannot allocate from reserved memory for %s\n",
+ pdata->name);
+ goto err_misc_deregister;
+ }
}
- pr_info("allocating %lu bytes at %p (%lx physical) for %s\n",
- pmem[id].size, pmem[id].vbase, pmem[id].base, pmem[id].name);
-
- pmem[id].reusable = pdata->reusable;
/* reusable pmem requires map on demand */
pmem[id].map_on_demand = pdata->map_on_demand || pdata->reusable;
if (pmem[id].map_on_demand) {
if (pmem[id].reusable) {
const struct fmem_data *fmem_info = fmem_get_info();
pmem[id].area = fmem_info->area;
+ pmem[id].base = fmem_info->phys;
} else {
pmem_vma = get_vm_area(pmem[id].size, VM_IOREMAP);
if (!pmem_vma) {
@@ -2844,12 +2844,17 @@
if (pdata->release_region)
pmem[id].mem_release = pdata->release_region;
+ pr_info("allocating %lu bytes at %lx physical for %s\n",
+ pmem[id].size, pmem[id].base, pmem[id].name);
+
return 0;
cleanup_vm:
- remove_vm_area(pmem_vma);
+ if (!pmem[id].reusable)
+ remove_vm_area(pmem_vma);
err_free:
- free_contiguous_memory_by_paddr(pmem[id].base);
+ if (!pmem[id].reusable)
+ free_contiguous_memory_by_paddr(pmem[id].base);
err_misc_deregister:
misc_deregister(&pmem[id].dev);
err_cant_register_device:
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
new file mode 100644
index 0000000..e4c3152
--- /dev/null
+++ b/drivers/misc/qseecom.c
@@ -0,0 +1,1490 @@
+/* Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
+ *
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "QSEECOM: %s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/ion.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/qseecom.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/scm.h>
+#include <mach/peripheral-loader.h>
+#include "qseecom_legacy.h"
+
+#define QSEECOM_DEV "qseecom"
+#define QSEOS_VERSION_13 0x13
+#define QSEOS_VERSION_14 0x14
+#define QSEOS_CHECK_VERSION_CMD 0x00001803;
+
+enum qseecom_command_scm_resp_type {
+ QSEOS_APP_ID = 0xEE01,
+ QSEOS_LISTENER_ID
+};
+
+enum qseecom_qceos_cmd_id {
+ QSEOS_APP_START_COMMAND = 0x01,
+ QSEOS_APP_SHUTDOWN_COMMAND,
+ QSEOS_APP_LOOKUP_COMMAND,
+ QSEOS_REGISTER_LISTENER,
+ QSEOS_DEREGISTER_LISTENER,
+ QSEOS_CLIENT_SEND_DATA_COMMAND,
+ QSEOS_LISTENER_DATA_RSP_COMMAND,
+ QSEOS_CMD_MAX = 0xEFFFFFFF
+};
+
+enum qseecom_qceos_cmd_status {
+ QSEOS_RESULT_SUCCESS = 0,
+ QSEOS_RESULT_INCOMPLETE,
+ QSEOS_RESULT_FAILURE = 0xFFFFFFFF
+};
+
+__packed struct qseecom_check_app_ireq {
+ uint32_t qsee_cmd_id;
+ char app_name[MAX_APP_NAME_SIZE];
+};
+
+__packed struct qseecom_load_app_ireq {
+ uint32_t qsee_cmd_id;
+ uint32_t mdt_len; /* Length of the mdt file */
+ uint32_t img_len; /* Length of .bxx and .mdt files */
+ uint32_t phy_addr; /* phy addr of the start of image */
+ char app_name[MAX_APP_NAME_SIZE]; /* application name*/
+};
+
+__packed struct qseecom_unload_app_ireq {
+ uint32_t qsee_cmd_id;
+ uint32_t app_id;
+};
+
+__packed struct qseecom_register_listener_ireq {
+ uint32_t qsee_cmd_id;
+ uint32_t listener_id;
+ void *sb_ptr;
+ uint32_t sb_len;
+};
+
+__packed struct qseecom_unregister_listener_ireq {
+ uint32_t qsee_cmd_id;
+ uint32_t listener_id;
+};
+
+__packed struct qseecom_client_send_data_ireq {
+ uint32_t qsee_cmd_id;
+ uint32_t app_id;
+ void *req_ptr;
+ uint32_t req_len;
+ void *rsp_ptr; /* First 4 bytes should always be the return status */
+ uint32_t rsp_len;
+};
+
+/* send_data resp */
+__packed struct qseecom_client_listener_data_irsp {
+ uint32_t qsee_cmd_id;
+ uint32_t listener_id;
+};
+
+/*
+ * struct qseecom_command_scm_resp - qseecom response buffer
+ * @cmd_status: value from enum tz_sched_cmd_status
+ * @sb_in_rsp_addr: points to physical location of response
+ * buffer
+ * @sb_in_rsp_len: length of command response
+ */
+__packed struct qseecom_command_scm_resp {
+ uint32_t result;
+ enum qseecom_command_scm_resp_type resp_type;
+ unsigned int data;
+};
+
+static struct class *driver_class;
+static dev_t qseecom_device_no;
+static struct cdev qseecom_cdev;
+
+/* Data structures used in legacy support */
+static void *pil;
+static uint32_t pil_ref_cnt;
+static DEFINE_MUTEX(pil_access_lock);
+
+static DEFINE_MUTEX(send_msg_lock);
+static DEFINE_MUTEX(qsee_bw_mutex);
+static DEFINE_MUTEX(app_access_lock);
+
+static int qsee_bw_count;
+static struct clk *qseecom_bus_clk;
+static uint32_t qsee_perf_client;
+
+struct qseecom_registered_listener_list {
+ struct list_head list;
+ struct qseecom_register_listener_req svc;
+ u8 *sb_reg_req;
+ u8 *sb_virt;
+ s32 sb_phys;
+ size_t sb_length;
+ struct ion_handle *ihandle; /* Retrieve phy addr */
+
+ wait_queue_head_t rcv_req_wq;
+ int rcv_req_flag;
+};
+
+struct qseecom_registered_app_list {
+ struct list_head list;
+ u32 app_id;
+ u32 ref_cnt;
+};
+
+struct qseecom_control {
+ struct ion_client *ion_clnt; /* Ion client */
+ struct list_head registered_listener_list_head;
+ spinlock_t registered_listener_list_lock;
+
+ struct list_head registered_app_list_head;
+ spinlock_t registered_app_list_lock;
+
+ wait_queue_head_t send_resp_wq;
+ int send_resp_flag;
+
+ uint32_t qseos_version;
+};
+
+struct qseecom_client_handle {
+ u32 app_id;
+ u8 *sb_virt;
+ s32 sb_phys;
+ uint32_t user_virt_sb_base;
+ size_t sb_length;
+ struct ion_handle *ihandle; /* Retrieve phy addr */
+};
+
+struct qseecom_listener_handle {
+ u32 id;
+};
+
+static struct qseecom_control qseecom;
+
+struct qseecom_dev_handle {
+ bool service;
+ union {
+ struct qseecom_client_handle client;
+ struct qseecom_listener_handle listener;
+ };
+ bool released;
+ int abort;
+ wait_queue_head_t abort_wq;
+ atomic_t ioctl_count;
+};
+
+static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
+ struct qseecom_register_listener_req svc)
+{
+ struct qseecom_registered_listener_list *ptr;
+ int unique = 1;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+ list_for_each_entry(ptr, &qseecom.registered_listener_list_head, list) {
+ if (ptr->svc.listener_id == svc.listener_id) {
+ pr_err("Service id: %u is already registered\n",
+ ptr->svc.listener_id);
+ unique = 0;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+ return unique;
+}
+
+static struct qseecom_registered_listener_list *__qseecom_find_svc(
+ int32_t listener_id)
+{
+ struct qseecom_registered_listener_list *entry = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+ list_for_each_entry(entry, &qseecom.registered_listener_list_head, list)
+ {
+ if (entry->svc.listener_id == listener_id)
+ break;
+ }
+ spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+ return entry;
+}
+
+static int __qseecom_set_sb_memory(struct qseecom_registered_listener_list *svc,
+ struct qseecom_dev_handle *handle,
+ struct qseecom_register_listener_req *listener)
+{
+ int ret = 0;
+ unsigned int flags = 0;
+ struct qseecom_register_listener_ireq req;
+ struct qseecom_command_scm_resp resp;
+ ion_phys_addr_t pa;
+
+ /* Get the handle of the shared fd */
+ svc->ihandle = ion_import_fd(qseecom.ion_clnt, listener->ifd_data_fd);
+ if (svc->ihandle == NULL) {
+ pr_err("Ion client could not retrieve the handle\n");
+ return -ENOMEM;
+ }
+
+ /* Get the physical address of the ION BUF */
+ ret = ion_phys(qseecom.ion_clnt, svc->ihandle, &pa, &svc->sb_length);
+
+ /* Populate the structure for sending scm call to load image */
+ svc->sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt,
+ svc->ihandle, flags);
+ svc->sb_phys = pa;
+
+ if (qseecom.qseos_version == QSEOS_VERSION_14) {
+ req.qsee_cmd_id = QSEOS_REGISTER_LISTENER;
+ req.listener_id = svc->svc.listener_id;
+ req.sb_len = svc->sb_length;
+ req.sb_ptr = (void *)svc->sb_phys;
+
+ resp.result = QSEOS_RESULT_INCOMPLETE;
+
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+ sizeof(req), &resp, sizeof(resp));
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return -EINVAL;
+ }
+
+ if (resp.result != QSEOS_RESULT_SUCCESS) {
+ pr_err("Error SB registration req: resp.result = %d\n",
+ resp.result);
+ return -EPERM;
+ }
+ } else {
+ struct qseecom_command cmd;
+ struct qseecom_response resp;
+ struct qse_pr_init_sb_req_s sb_init_req;
+ struct qse_pr_init_sb_rsp_s sb_init_rsp;
+
+ svc->sb_reg_req = kzalloc((sizeof(sb_init_req) +
+ sizeof(sb_init_rsp)), GFP_KERNEL);
+
+ sb_init_req.pr_cmd = TZ_SCHED_CMD_ID_REGISTER_LISTENER;
+ sb_init_req.listener_id = svc->svc.listener_id;
+ sb_init_req.sb_len = svc->sb_length;
+ sb_init_req.sb_ptr = svc->sb_phys;
+
+ memcpy(svc->sb_reg_req, &sb_init_req, sizeof(sb_init_req));
+
+ /* It will always be a new cmd from this method */
+ cmd.cmd_type = TZ_SCHED_CMD_NEW;
+ cmd.sb_in_cmd_addr = (u8 *)(virt_to_phys(svc->sb_reg_req));
+ cmd.sb_in_cmd_len = sizeof(sb_init_req);
+
+ resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
+
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &cmd, sizeof(cmd)
+ , &resp, sizeof(resp));
+
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return -EINVAL;
+ }
+
+ if (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
+ pr_err("SB registration fail resp.cmd_status %d\n",
+ resp.cmd_status);
+ return -EINVAL;
+ }
+ memset(svc->sb_virt, 0, svc->sb_length);
+ }
+ return 0;
+}
+
+static int qseecom_register_listener(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct qseecom_register_listener_req rcvd_lstnr;
+ struct qseecom_registered_listener_list *new_entry;
+
+ ret = copy_from_user(&rcvd_lstnr, argp, sizeof(rcvd_lstnr));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
+
+ if (!__qseecom_is_svc_unique(data, rcvd_lstnr)) {
+ pr_err("Service is not unique and is already registered\n");
+ return ret;
+ }
+
+ ret = copy_to_user(argp, &rcvd_lstnr, sizeof(rcvd_lstnr));
+ if (ret) {
+ pr_err("copy_to_user failed\n");
+ return ret;
+ }
+
+ new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
+ if (!new_entry) {
+ pr_err("kmalloc failed\n");
+ return -ENOMEM;
+ }
+ memcpy(&new_entry->svc, &rcvd_lstnr, sizeof(rcvd_lstnr));
+ new_entry->rcv_req_flag = 0;
+
+ new_entry->svc.listener_id = rcvd_lstnr.listener_id;
+ new_entry->sb_length = rcvd_lstnr.sb_size;
+ if (__qseecom_set_sb_memory(new_entry, data, &rcvd_lstnr)) {
+ pr_err("qseecom_set_sb_memoryfailed\n");
+ kzfree(new_entry);
+ return -ENOMEM;
+ }
+ data->listener.id = rcvd_lstnr.listener_id;
+ data->service = true;
+ init_waitqueue_head(&new_entry->rcv_req_wq);
+
+ spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+ list_add_tail(&new_entry->list, &qseecom.registered_listener_list_head);
+ spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+ return ret;
+}
+
+static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
+{
+ int ret = 0;
+ unsigned long flags;
+ uint32_t unmap_mem = 0;
+ struct qseecom_register_listener_ireq req;
+ struct qseecom_registered_listener_list *ptr_svc = NULL;
+ struct qseecom_command_scm_resp resp;
+ struct ion_handle *ihandle = NULL; /* Retrieve phy addr */
+
+ if (qseecom.qseos_version == QSEOS_VERSION_14) {
+ req.qsee_cmd_id = QSEOS_DEREGISTER_LISTENER;
+ req.listener_id = data->listener.id;
+ resp.result = QSEOS_RESULT_INCOMPLETE;
+
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+ sizeof(req), &resp, sizeof(resp));
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return ret;
+ }
+
+ if (resp.result != QSEOS_RESULT_SUCCESS) {
+ pr_err("SB deregistartion: result=%d\n", resp.result);
+ return -EPERM;
+ }
+ } else {
+ struct qse_pr_init_sb_req_s sb_init_req;
+ struct qseecom_command cmd;
+ struct qseecom_response resp;
+ struct qseecom_registered_listener_list *svc;
+
+ svc = __qseecom_find_svc(data->listener.id);
+ sb_init_req.pr_cmd = TZ_SCHED_CMD_ID_REGISTER_LISTENER;
+ sb_init_req.listener_id = data->listener.id;
+ sb_init_req.sb_len = 0;
+ sb_init_req.sb_ptr = 0;
+
+ memcpy(svc->sb_reg_req, &sb_init_req, sizeof(sb_init_req));
+
+ /* It will always be a new cmd from this method */
+ cmd.cmd_type = TZ_SCHED_CMD_NEW;
+ cmd.sb_in_cmd_addr = (u8 *)(virt_to_phys(svc->sb_reg_req));
+ cmd.sb_in_cmd_len = sizeof(sb_init_req);
+ resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
+
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &cmd, sizeof(cmd),
+ &resp, sizeof(resp));
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return ret;
+ }
+ kzfree(svc->sb_reg_req);
+ if (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
+ pr_err("Error with SB initialization\n");
+ return -EPERM;
+ }
+ }
+ data->abort = 1;
+ spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+ list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head,
+ list) {
+ if (ptr_svc->svc.listener_id == data->listener.id) {
+ wake_up_all(&ptr_svc->rcv_req_wq);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+
+ while (atomic_read(&data->ioctl_count) > 1) {
+ if (wait_event_interruptible(data->abort_wq,
+ atomic_read(&data->ioctl_count) <= 1)) {
+ pr_err("Interrupted from abort\n");
+ ret = -ERESTARTSYS;
+ break;
+ }
+ }
+
+ spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+ list_for_each_entry(ptr_svc,
+ &qseecom.registered_listener_list_head,
+ list)
+ {
+ if (ptr_svc->svc.listener_id == data->listener.id) {
+ if (ptr_svc->sb_virt) {
+ unmap_mem = 1;
+ ihandle = ptr_svc->ihandle;
+ }
+ list_del(&ptr_svc->list);
+ kzfree(ptr_svc);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+
+ /* Unmap the memory */
+ if (unmap_mem) {
+ if (!IS_ERR_OR_NULL(ihandle)) {
+ ion_unmap_kernel(qseecom.ion_clnt, ihandle);
+ ion_free(qseecom.ion_clnt, ihandle);
+ }
+ }
+ data->released = true;
+ return ret;
+}
+
+static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ ion_phys_addr_t pa;
+ int32_t ret;
+ unsigned int flags = 0;
+ struct qseecom_set_sb_mem_param_req req;
+ uint32_t len;
+
+ /* Copy the relevant information needed for loading the image */
+ if (__copy_from_user(&req, (void __user *)argp, sizeof(req)))
+ return -EFAULT;
+
+ if (qseecom.qseos_version == QSEOS_VERSION_13) {
+ long pil_error;
+ mutex_lock(&pil_access_lock);
+ if (pil_ref_cnt == 0) {
+ pil = pil_get("tzapps");
+ if (IS_ERR(pil)) {
+ pr_err("Playready PIL image load failed\n");
+ pil_error = PTR_ERR(pil);
+ pil = NULL;
+ pr_debug("tzapps image load FAILED\n");
+ mutex_unlock(&pil_access_lock);
+ return pil_error;
+ }
+ }
+ pil_ref_cnt++;
+ mutex_unlock(&pil_access_lock);
+ }
+ /* Get the handle of the shared fd */
+ data->client.ihandle = ion_import_fd(qseecom.ion_clnt, req.ifd_data_fd);
+ if (IS_ERR_OR_NULL(data->client.ihandle)) {
+ pr_err("Ion client could not retrieve the handle\n");
+ return -ENOMEM;
+ }
+ /* Get the physical address of the ION BUF */
+ ret = ion_phys(qseecom.ion_clnt, data->client.ihandle, &pa, &len);
+ /* Populate the structure for sending scm call to load image */
+ data->client.sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt,
+ data->client.ihandle,
+ flags);
+ data->client.sb_phys = pa;
+ data->client.sb_length = req.sb_len;
+ data->client.user_virt_sb_base = req.virt_sb_base;
+ return 0;
+}
+
+
+static int __qseecom_listener_has_sent_rsp(struct qseecom_dev_handle *data)
+{
+ int ret;
+ ret = (qseecom.send_resp_flag != 0);
+ return ret || data->abort;
+}
+
+static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
+ struct qseecom_command_scm_resp *resp)
+{
+ int ret = 0;
+ uint32_t lstnr;
+ unsigned long flags;
+ struct qseecom_client_listener_data_irsp send_data_rsp;
+ struct qseecom_registered_listener_list *ptr_svc = NULL;
+
+
+ while (resp->result == QSEOS_RESULT_INCOMPLETE) {
+ lstnr = resp->data;
+ /*
+ * Wake up blocking lsitener service with the lstnr id
+ */
+ spin_lock_irqsave(&qseecom.registered_listener_list_lock,
+ flags);
+ list_for_each_entry(ptr_svc,
+ &qseecom.registered_listener_list_head, list) {
+ if (ptr_svc->svc.listener_id == lstnr) {
+ ptr_svc->rcv_req_flag = 1;
+ wake_up_interruptible(&ptr_svc->rcv_req_wq);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
+ flags);
+ if (ptr_svc->svc.listener_id != lstnr) {
+ pr_warning("Service requested for does on exist\n");
+ return -ERESTARTSYS;
+ }
+ pr_debug("waking up rcv_req_wq and "
+ "waiting for send_resp_wq\n");
+ if (wait_event_interruptible(qseecom.send_resp_wq,
+ __qseecom_listener_has_sent_rsp(data))) {
+ pr_warning("Interrupted: exiting send_cmd loop\n");
+ return -ERESTARTSYS;
+ }
+
+ if (data->abort) {
+ pr_err("Aborting driver\n");
+ return -ENODEV;
+ }
+ qseecom.send_resp_flag = 0;
+ send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
+ send_data_rsp.listener_id = lstnr ;
+
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
+ (const void *)&send_data_rsp,
+ sizeof(send_data_rsp), resp,
+ sizeof(*resp));
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
+{
+ struct qseecom_registered_app_list *entry = NULL;
+ unsigned long flags = 0;
+ u32 app_id = 0;
+ struct ion_handle *ihandle; /* Ion handle */
+ struct qseecom_load_img_req load_img_req;
+ int32_t ret;
+ ion_phys_addr_t pa = 0;
+ uint32_t len;
+ struct qseecom_command_scm_resp resp;
+ struct qseecom_check_app_ireq req;
+ /* Copy the relevant information needed for loading the image */
+ if (__copy_from_user(&load_img_req,
+ (void __user *)argp,
+ sizeof(struct qseecom_load_img_req))) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
+
+ req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+ memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
+
+ /* SCM_CALL to check if app_id for the mentioned app exists */
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+ sizeof(struct qseecom_check_app_ireq),
+ &resp, sizeof(resp));
+
+ if (resp.result == QSEOS_RESULT_FAILURE)
+ app_id = 0;
+ else
+ app_id = resp.data;
+
+ if (app_id) {
+ pr_warn("App id already exists\n");
+ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+ list_for_each_entry(entry,
+ &qseecom.registered_app_list_head, list){
+ if (entry->app_id == app_id) {
+ entry->ref_cnt++;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(
+ &qseecom.registered_app_list_lock, flags);
+ } else {
+ struct qseecom_load_app_ireq load_req;
+
+ pr_warn("App id does not exist\n");
+ /* Get the handle of the shared fd */
+ ihandle = ion_import_fd(qseecom.ion_clnt,
+ load_img_req.ifd_data_fd);
+ if (IS_ERR_OR_NULL(ihandle)) {
+ pr_err("Ion client could not retrieve the handle\n");
+ return -ENOMEM;
+ }
+
+ /* Get the physical address of the ION BUF */
+ ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &len);
+
+ /* Populate the structure for sending scm call to load image */
+ load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
+ load_req.mdt_len = load_img_req.mdt_len;
+ load_req.img_len = load_img_req.img_len;
+ load_req.phy_addr = pa;
+
+ /* SCM_CALL to load the app and get the app_id back */
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
+ sizeof(struct qseecom_load_app_ireq),
+ &resp, sizeof(resp));
+
+ if (resp.result == QSEOS_RESULT_INCOMPLETE) {
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret) {
+ pr_err("process_incomplete_cmd failed err: %d\n",
+ ret);
+ if (!IS_ERR_OR_NULL(ihandle))
+ ion_free(qseecom.ion_clnt, ihandle);
+ return ret;
+ }
+ }
+ if (resp.result != QSEOS_RESULT_SUCCESS) {
+ pr_err("scm_call failed resp.result != QSEOS_RESULT_SUCCESS\n");
+ if (!IS_ERR_OR_NULL(ihandle))
+ ion_free(qseecom.ion_clnt, ihandle);
+ return -EFAULT;
+ }
+
+ app_id = resp.data;
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ pr_err("kmalloc failed\n");
+ return -ENOMEM;
+ }
+ entry->app_id = app_id;
+ entry->ref_cnt = 1;
+
+ /* Deallocate the handle */
+ if (!IS_ERR_OR_NULL(ihandle))
+ ion_free(qseecom.ion_clnt, ihandle);
+
+ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+ list_add_tail(&entry->list, &qseecom.registered_app_list_head);
+ spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+ flags);
+ }
+ data->client.app_id = app_id;
+ load_img_req.app_id = app_id;
+ if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
+ pr_err("copy_to_user failed\n");
+ kzfree(entry);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int __qseecom_cleanup_app(struct qseecom_dev_handle *data)
+{
+ wake_up_all(&qseecom.send_resp_wq);
+ while (atomic_read(&data->ioctl_count) > 1) {
+ if (wait_event_interruptible(data->abort_wq,
+ atomic_read(&data->ioctl_count) <= 1)) {
+ pr_err("Interrupted from abort\n");
+ return -ERESTARTSYS;
+ break;
+ }
+ }
+ /* Set unload app */
+ return 1;
+}
+
+static int qseecom_unload_app(struct qseecom_dev_handle *data)
+{
+ unsigned long flags;
+ int ret = 0;
+ struct qseecom_command_scm_resp resp;
+ struct qseecom_registered_app_list *ptr_app;
+ uint32_t unload = 0;
+
+ if (qseecom.qseos_version == QSEOS_VERSION_14) {
+ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+ list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
+ list) {
+ if (ptr_app->app_id == data->client.app_id) {
+ if (ptr_app->ref_cnt == 1) {
+ unload = __qseecom_cleanup_app(data);
+ list_del(&ptr_app->list);
+ kzfree(ptr_app);
+ break;
+ } else {
+ ptr_app->ref_cnt--;
+ break;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+ flags);
+ }
+ if (!IS_ERR_OR_NULL(data->client.ihandle)) {
+ ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
+ ion_free(qseecom.ion_clnt, data->client.ihandle);
+ }
+
+ if ((unload) && (qseecom.qseos_version == QSEOS_VERSION_14)) {
+ struct qseecom_unload_app_ireq req;
+
+ /* Populate the structure for sending scm call to load image */
+ req.qsee_cmd_id = QSEOS_APP_SHUTDOWN_COMMAND;
+ req.app_id = data->client.app_id;
+
+ /* SCM_CALL to unload the app */
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+ sizeof(struct qseecom_unload_app_ireq),
+ &resp, sizeof(resp));
+ if (ret) {
+ pr_err("Fail to unload APP\n");
+ return -EFAULT;
+ }
+ if (resp.result == QSEOS_RESULT_INCOMPLETE) {
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret) {
+ pr_err("process_incomplete_cmd fail err: %d\n",
+ ret);
+ return ret;
+ }
+ }
+ }
+
+ if (qseecom.qseos_version == QSEOS_VERSION_13) {
+ data->abort = 1;
+ wake_up_all(&qseecom.send_resp_wq);
+ while (atomic_read(&data->ioctl_count) > 0) {
+ if (wait_event_interruptible(data->abort_wq,
+ atomic_read(&data->ioctl_count) <= 0)) {
+ pr_err("Interrupted from abort\n");
+ ret = -ERESTARTSYS;
+ break;
+ }
+ }
+ mutex_lock(&pil_access_lock);
+ if (pil_ref_cnt == 1)
+ pil_put(pil);
+ pil_ref_cnt--;
+ mutex_unlock(&pil_access_lock);
+ }
+ data->released = true;
+ return ret;
+}
+
+static uint32_t __qseecom_uvirt_to_kphys(struct qseecom_dev_handle *data,
+ uint32_t virt)
+{
+ return data->client.sb_phys + (virt - data->client.user_virt_sb_base);
+}
+
+static int __qseecom_send_cmd_legacy(struct qseecom_dev_handle *data,
+ struct qseecom_send_cmd_req *req)
+{
+ int ret = 0;
+ unsigned long flags;
+ u32 reqd_len_sb_in = 0;
+ struct qseecom_command cmd;
+ struct qseecom_response resp;
+
+
+ if (req->cmd_req_buf == NULL || req->resp_buf == NULL) {
+ pr_err("cmd buffer or response buffer is null\n");
+ return -EINVAL;
+ }
+
+ if (req->cmd_req_len <= 0 ||
+ req->resp_len <= 0 ||
+ req->cmd_req_len > data->client.sb_length ||
+ req->resp_len > data->client.sb_length) {
+ pr_err("cmd buffer length or "
+ "response buffer length not valid\n");
+ return -EINVAL;
+ }
+
+ reqd_len_sb_in = req->cmd_req_len + req->resp_len;
+ if (reqd_len_sb_in > data->client.sb_length) {
+ pr_debug("Not enough memory to fit cmd_buf and "
+ "resp_buf. Required: %u, Available: %u\n",
+ reqd_len_sb_in, data->client.sb_length);
+ return -ENOMEM;
+ }
+ cmd.cmd_type = TZ_SCHED_CMD_NEW;
+ cmd.sb_in_cmd_addr = (u8 *) data->client.sb_phys;
+ cmd.sb_in_cmd_len = req->cmd_req_len;
+
+ resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
+ resp.sb_in_rsp_addr = (u8 *)data->client.sb_phys + req->cmd_req_len;
+ resp.sb_in_rsp_len = req->resp_len;
+
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *)&cmd,
+ sizeof(cmd), &resp, sizeof(resp));
+
+ if (ret) {
+ pr_err("qseecom_scm_call_legacy failed with err: %d\n", ret);
+ return ret;
+ }
+
+ while (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
+ /*
+ * If cmd is incomplete, get the callback cmd out from SB out
+ * and put it on the list
+ */
+ struct qseecom_registered_listener_list *ptr_svc = NULL;
+ /*
+ * We don't know which service can handle the command. so we
+ * wake up all blocking services and let them figure out if
+ * they can handle the given command.
+ */
+ spin_lock_irqsave(&qseecom.registered_listener_list_lock,
+ flags);
+ list_for_each_entry(ptr_svc,
+ &qseecom.registered_listener_list_head, list) {
+ ptr_svc->rcv_req_flag = 1;
+ wake_up_interruptible(&ptr_svc->rcv_req_wq);
+ }
+ spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
+ flags);
+
+ pr_debug("waking up rcv_req_wq and "
+ "waiting for send_resp_wq\n");
+ if (wait_event_interruptible(qseecom.send_resp_wq,
+ __qseecom_listener_has_sent_rsp(data))) {
+ pr_warning("qseecom Interrupted: exiting send_cmd loop\n");
+ return -ERESTARTSYS;
+ }
+
+ if (data->abort) {
+ pr_err("Aborting driver\n");
+ return -ENODEV;
+ }
+ qseecom.send_resp_flag = 0;
+ cmd.cmd_type = TZ_SCHED_CMD_PENDING;
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *)&cmd,
+ sizeof(cmd), &resp, sizeof(resp));
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
+ struct qseecom_send_cmd_req *req)
+{
+ int ret = 0;
+ u32 reqd_len_sb_in = 0;
+ struct qseecom_client_send_data_ireq send_data_req;
+ struct qseecom_command_scm_resp resp;
+
+ if (req->cmd_req_buf == NULL || req->resp_buf == NULL) {
+ pr_err("cmd buffer or response buffer is null\n");
+ return -EINVAL;
+ }
+
+ if (req->cmd_req_len <= 0 ||
+ req->resp_len <= 0 ||
+ req->cmd_req_len > data->client.sb_length ||
+ req->resp_len > data->client.sb_length) {
+ pr_err("cmd buffer length or "
+ "response buffer length not valid\n");
+ return -EINVAL;
+ }
+
+ reqd_len_sb_in = req->cmd_req_len + req->resp_len;
+ if (reqd_len_sb_in > data->client.sb_length) {
+ pr_debug("Not enough memory to fit cmd_buf and "
+ "resp_buf. Required: %u, Available: %u\n",
+ reqd_len_sb_in, data->client.sb_length);
+ return -ENOMEM;
+ }
+
+ send_data_req.qsee_cmd_id = QSEOS_CLIENT_SEND_DATA_COMMAND;
+ send_data_req.app_id = data->client.app_id;
+ send_data_req.req_ptr = (void *)(__qseecom_uvirt_to_kphys(data,
+ (uint32_t)req->cmd_req_buf));
+ send_data_req.req_len = req->cmd_req_len;
+ send_data_req.rsp_ptr = (void *)(__qseecom_uvirt_to_kphys(data,
+ (uint32_t)req->resp_buf));
+ send_data_req.rsp_len = req->resp_len;
+
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *) &send_data_req,
+ sizeof(send_data_req),
+ &resp, sizeof(resp));
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return ret;
+ }
+
+ if (resp.result == QSEOS_RESULT_INCOMPLETE) {
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret) {
+ pr_err("process_incomplete_cmd failed err: %d\n", ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+
+static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp)
+{
+ int ret = 0;
+ struct qseecom_send_cmd_req req;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
+ if (qseecom.qseos_version == QSEOS_VERSION_14)
+ ret = __qseecom_send_cmd(data, &req);
+ else
+ ret = __qseecom_send_cmd_legacy(data, &req);
+ if (ret)
+ return ret;
+
+ pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
+ req.resp_len, req.resp_buf);
+ return ret;
+}
+
+static int __qseecom_send_cmd_req_clean_up(
+ struct qseecom_send_modfd_cmd_req *req)
+{
+ char *field;
+ uint32_t *update;
+ int ret = 0;
+ int i = 0;
+
+ for (i = 0; i < MAX_ION_FD; i++) {
+ if (req->ifd_data[i].fd != 0) {
+ field = (char *)req->cmd_req_buf +
+ req->ifd_data[i].cmd_buf_offset;
+ update = (uint32_t *) field;
+ *update = 0;
+ }
+ }
+ return ret;
+}
+
+static int __qseecom_update_with_phy_addr(
+ struct qseecom_send_modfd_cmd_req *req)
+{
+ struct ion_handle *ihandle;
+ char *field;
+ uint32_t *update;
+ ion_phys_addr_t pa;
+ int ret = 0;
+ int i = 0;
+ uint32_t length;
+
+ for (i = 0; i < MAX_ION_FD; i++) {
+ if (req->ifd_data[i].fd != 0) {
+ /* Get the handle of the shared fd */
+ ihandle = ion_import_fd(qseecom.ion_clnt,
+ req->ifd_data[i].fd);
+ if (IS_ERR_OR_NULL(ihandle)) {
+ pr_err("Ion client can't retrieve the handle\n");
+ return -ENOMEM;
+ }
+ field = (char *) req->cmd_req_buf +
+ req->ifd_data[i].cmd_buf_offset;
+ update = (uint32_t *) field;
+
+ /* Populate the cmd data structure with the phys_addr */
+ ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &length);
+ if (ret)
+ return -ENOMEM;
+
+ *update = (uint32_t)pa;
+ /* Deallocate the handle */
+ if (!IS_ERR_OR_NULL(ihandle))
+ ion_free(qseecom.ion_clnt, ihandle);
+ }
+ }
+ return ret;
+}
+
+static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ int ret = 0;
+ struct qseecom_send_modfd_cmd_req req;
+ struct qseecom_send_cmd_req send_cmd_req;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
+ send_cmd_req.cmd_req_buf = req.cmd_req_buf;
+ send_cmd_req.cmd_req_len = req.cmd_req_len;
+ send_cmd_req.resp_buf = req.resp_buf;
+ send_cmd_req.resp_len = req.resp_len;
+
+ ret = __qseecom_update_with_phy_addr(&req);
+ if (ret)
+ return ret;
+ if (qseecom.qseos_version == QSEOS_VERSION_14)
+ ret = __qseecom_send_cmd(data, &send_cmd_req);
+ else
+ ret = __qseecom_send_cmd_legacy(data, &send_cmd_req);
+ __qseecom_send_cmd_req_clean_up(&req);
+
+ if (ret)
+ return ret;
+
+ pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
+ req.resp_len, req.resp_buf);
+ return ret;
+}
+
+static int __qseecom_listener_has_rcvd_req(struct qseecom_dev_handle *data,
+ struct qseecom_registered_listener_list *svc)
+{
+ int ret;
+ ret = (svc->rcv_req_flag != 0);
+ return ret || data->abort;
+}
+
+static int qseecom_receive_req(struct qseecom_dev_handle *data)
+{
+ int ret = 0;
+ struct qseecom_registered_listener_list *this_lstnr;
+
+ this_lstnr = __qseecom_find_svc(data->listener.id);
+ while (1) {
+ if (wait_event_interruptible(this_lstnr->rcv_req_wq,
+ __qseecom_listener_has_rcvd_req(data,
+ this_lstnr))) {
+ pr_warning("Interrupted: exiting wait_rcv_req loop\n");
+ /* woken up for different reason */
+ return -ERESTARTSYS;
+ }
+
+ if (data->abort) {
+ pr_err("Aborting driver!\n");
+ return -ENODEV;
+ }
+ this_lstnr->rcv_req_flag = 0;
+ if (qseecom.qseos_version == QSEOS_VERSION_13) {
+ if (*((uint32_t *)this_lstnr->sb_virt) != 0)
+ break;
+ } else {
+ break;
+ }
+ }
+ return ret;
+}
+
+static int qseecom_send_resp(void)
+{
+ qseecom.send_resp_flag = 1;
+ wake_up_interruptible(&qseecom.send_resp_wq);
+ return 0;
+}
+
+static int qseecom_get_qseos_version(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ struct qseecom_qseos_version_req req;
+
+ if (copy_from_user(&req, argp, sizeof(req))) {
+ pr_err("copy_from_user failed");
+ return -EINVAL;
+ }
+ req.qseos_version = qseecom.qseos_version;
+ if (copy_to_user(argp, &req, sizeof(req))) {
+ pr_err("copy_to_user failed");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int qsee_vote_for_clock(void)
+{
+ int ret = 0;
+
+ if (!qsee_perf_client)
+ return -EINVAL;
+
+ mutex_lock(&qsee_bw_mutex);
+ if (!qsee_bw_count) {
+ ret = msm_bus_scale_client_update_request(
+ qsee_perf_client, 1);
+ if (ret) {
+ pr_err("Bandwidth request failed (%d)\n", ret);
+ } else {
+ ret = clk_enable(qseecom_bus_clk);
+ if (ret)
+ pr_err("Clock enable failed\n");
+ }
+ }
+ if (ret)
+ msm_bus_scale_client_update_request(qsee_perf_client, 0);
+ else
+ qsee_bw_count++;
+
+ mutex_unlock(&qsee_bw_mutex);
+ return ret;
+}
+
+static void qsee_disable_clock_vote(void)
+{
+ if (!qsee_perf_client)
+ return ;
+
+ mutex_lock(&qsee_bw_mutex);
+ if (qsee_bw_count > 0) {
+ if (qsee_bw_count-- == 1) {
+ msm_bus_scale_client_update_request(qsee_perf_client,
+ 0);
+ clk_disable(qseecom_bus_clk);
+ }
+ }
+ mutex_unlock(&qsee_bw_mutex);
+}
+
+
+static long qseecom_ioctl(struct file *file, unsigned cmd,
+ unsigned long arg)
+{
+ int ret = 0;
+ struct qseecom_dev_handle *data = file->private_data;
+ void __user *argp = (void __user *) arg;
+
+ if (data->abort) {
+ pr_err("Aborting qseecom driver\n");
+ return -ENODEV;
+ }
+
+ switch (cmd) {
+ case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: {
+ pr_debug("ioctl register_listener_req()\n");
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_register_listener(data, argp);
+ atomic_dec(&data->ioctl_count);
+ wake_up_all(&data->abort_wq);
+ if (ret)
+ pr_err("failed qseecom_register_listener: %d\n", ret);
+ break;
+ }
+ case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ: {
+ pr_debug("ioctl unregister_listener_req()\n");
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_unregister_listener(data);
+ atomic_dec(&data->ioctl_count);
+ wake_up_all(&data->abort_wq);
+ if (ret)
+ pr_err("failed qseecom_unregister_listener: %d\n", ret);
+ break;
+ }
+ case QSEECOM_IOCTL_SEND_CMD_REQ: {
+ /* Only one client allowed here at a time */
+ mutex_lock(&send_msg_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_send_cmd(data, argp);
+ atomic_dec(&data->ioctl_count);
+ wake_up_all(&data->abort_wq);
+ mutex_unlock(&send_msg_lock);
+ if (ret)
+ pr_err("failed qseecom_send_cmd: %d\n", ret);
+ break;
+ }
+ case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: {
+ /* Only one client allowed here at a time */
+ mutex_lock(&send_msg_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_send_modfd_cmd(data, argp);
+ atomic_dec(&data->ioctl_count);
+ wake_up_all(&data->abort_wq);
+ mutex_unlock(&send_msg_lock);
+ if (ret)
+ pr_err("failed qseecom_send_cmd: %d\n", ret);
+ break;
+ }
+ case QSEECOM_IOCTL_RECEIVE_REQ: {
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_receive_req(data);
+ atomic_dec(&data->ioctl_count);
+ wake_up_all(&data->abort_wq);
+ if (ret)
+ pr_err("failed qseecom_receive_req: %d\n", ret);
+ break;
+ }
+ case QSEECOM_IOCTL_SEND_RESP_REQ: {
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_send_resp();
+ atomic_dec(&data->ioctl_count);
+ wake_up_all(&data->abort_wq);
+ if (ret)
+ pr_err("failed qseecom_send_resp: %d\n", ret);
+ break;
+ }
+ case QSEECOM_IOCTL_SET_MEM_PARAM_REQ: {
+ ret = qseecom_set_client_mem_param(data, argp);
+ if (ret)
+ pr_err("failed Qqseecom_set_mem_param request: %d\n",
+ ret);
+ break;
+ }
+ case QSEECOM_IOCTL_LOAD_APP_REQ: {
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_load_app(data, argp);
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ if (ret)
+ pr_err("failed load_app request: %d\n", ret);
+ break;
+ }
+ case QSEECOM_IOCTL_UNLOAD_APP_REQ: {
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_unload_app(data);
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ if (ret)
+ pr_err("failed unload_app request: %d\n", ret);
+ break;
+ }
+ case QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ: {
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_get_qseos_version(data, argp);
+ if (ret)
+ pr_err("qseecom_get_qseos_version: %d\n", ret);
+ atomic_dec(&data->ioctl_count);
+ break;
+ }
+ case QSEECOM_IOCTL_PERF_ENABLE_REQ:{
+ atomic_inc(&data->ioctl_count);
+ ret = qsee_vote_for_clock();
+ if (ret)
+ pr_err("Failed to vote for clock%d\n", ret);
+ atomic_dec(&data->ioctl_count);
+ break;
+ }
+ case QSEECOM_IOCTL_PERF_DISABLE_REQ:{
+ atomic_inc(&data->ioctl_count);
+ qsee_disable_clock_vote();
+ atomic_dec(&data->ioctl_count);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static int qseecom_open(struct inode *inode, struct file *file)
+{
+ int ret = 0;
+ struct qseecom_dev_handle *data;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ pr_err("kmalloc failed\n");
+ return -ENOMEM;
+ }
+ file->private_data = data;
+ data->abort = 0;
+ data->service = false;
+ data->released = false;
+ init_waitqueue_head(&data->abort_wq);
+ atomic_set(&data->ioctl_count, 0);
+ return ret;
+}
+
+static int qseecom_release(struct inode *inode, struct file *file)
+{
+ struct qseecom_dev_handle *data = file->private_data;
+ int ret = 0;
+
+ if (data->released == false) {
+ pr_warn("data->released == false\n");
+ if (data->service)
+ ret = qseecom_unregister_listener(data);
+ else
+ ret = qseecom_unload_app(data);
+ if (ret) {
+ pr_err("Close failed\n");
+ return ret;
+ }
+ }
+ kfree(data);
+ return ret;
+}
+
+/* qseecom bus scaling */
+static struct msm_bus_paths qsee_bw_table[] = {
+ {
+ .vectors = (struct msm_bus_vectors[]){
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ },
+ },
+ .num_paths = 1,
+ },
+ {
+ .vectors = (struct msm_bus_vectors[]){
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ib = (492 * 8) * 1000000UL,
+ .ab = (492 * 8) * 100000UL,
+ },
+ },
+ .num_paths = 1,
+ },
+};
+
+static struct msm_bus_scale_pdata qsee_bus_pdata = {
+ .usecase = qsee_bw_table,
+ .num_usecases = ARRAY_SIZE(qsee_bw_table),
+ .name = "qsee",
+};
+
+static const struct file_operations qseecom_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = qseecom_ioctl,
+ .open = qseecom_open,
+ .release = qseecom_release
+};
+
+static int __init qseecom_init(void)
+{
+ int rc;
+ int ret = 0;
+ struct device *class_dev;
+ char qsee_not_legacy = 0;
+ uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
+
+ rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
+ if (rc < 0) {
+ pr_err("alloc_chrdev_region failed %d\n", rc);
+ return rc;
+ }
+
+ driver_class = class_create(THIS_MODULE, QSEECOM_DEV);
+ if (IS_ERR(driver_class)) {
+ rc = -ENOMEM;
+ pr_err("class_create failed %d\n", rc);
+ goto unregister_chrdev_region;
+ }
+
+ class_dev = device_create(driver_class, NULL, qseecom_device_no, NULL,
+ QSEECOM_DEV);
+ if (!class_dev) {
+ pr_err("class_device_create failed %d\n", rc);
+ rc = -ENOMEM;
+ goto class_destroy;
+ }
+
+ cdev_init(&qseecom_cdev, &qseecom_fops);
+ qseecom_cdev.owner = THIS_MODULE;
+
+ rc = cdev_add(&qseecom_cdev, MKDEV(MAJOR(qseecom_device_no), 0), 1);
+ if (rc < 0) {
+ pr_err("cdev_add failed %d\n", rc);
+ goto err;
+ }
+
+ INIT_LIST_HEAD(&qseecom.registered_listener_list_head);
+ spin_lock_init(&qseecom.registered_listener_list_lock);
+ INIT_LIST_HEAD(&qseecom.registered_app_list_head);
+ spin_lock_init(&qseecom.registered_app_list_lock);
+ init_waitqueue_head(&qseecom.send_resp_wq);
+ qseecom.send_resp_flag = 0;
+
+ rc = scm_call(6, 1, &system_call_id, sizeof(system_call_id),
+ &qsee_not_legacy, sizeof(qsee_not_legacy));
+ if (rc) {
+ pr_err("Failed to retrieve QSEE version information %d\n", rc);
+ goto err;
+ }
+ if (qsee_not_legacy)
+ qseecom.qseos_version = QSEOS_VERSION_14;
+ else {
+ qseecom.qseos_version = QSEOS_VERSION_13;
+ pil = NULL;
+ pil_ref_cnt = 0;
+ }
+ /* Create ION msm client */
+ qseecom.ion_clnt = msm_ion_client_create(0x03, "qseecom-kernel");
+ if (qseecom.ion_clnt == NULL) {
+ pr_err("Ion client cannot be created\n");
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ /* register client for bus scaling */
+ qsee_perf_client = msm_bus_scale_register_client(&qsee_bus_pdata);
+ if (!qsee_perf_client)
+ pr_err("Unable to register bus client\n");
+
+ qseecom_bus_clk = clk_get_sys("scm", "bus_clk");
+ if (!IS_ERR(qseecom_bus_clk)) {
+ ret = clk_set_rate(qseecom_bus_clk, 64000000);
+ if (ret) {
+ qseecom_bus_clk = NULL;
+ pr_err("Unable to set clock rate\n");
+ }
+ } else {
+ qseecom_bus_clk = NULL;
+ pr_warn("Unable to get bus clk\n");
+ }
+ return 0;
+err:
+ device_destroy(driver_class, qseecom_device_no);
+class_destroy:
+ class_destroy(driver_class);
+unregister_chrdev_region:
+ unregister_chrdev_region(qseecom_device_no, 1);
+ return rc;
+}
+
+static void __exit qseecom_exit(void)
+{
+ device_destroy(driver_class, qseecom_device_no);
+ class_destroy(driver_class);
+ unregister_chrdev_region(qseecom_device_no, 1);
+ ion_client_destroy(qseecom.ion_clnt);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm Secure Execution Environment Communicator");
+
+module_init(qseecom_init);
+module_exit(qseecom_exit);
diff --git a/drivers/misc/qseecom_legacy.h b/drivers/misc/qseecom_legacy.h
new file mode 100644
index 0000000..66f87e9
--- /dev/null
+++ b/drivers/misc/qseecom_legacy.h
@@ -0,0 +1,79 @@
+/* Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
+ *
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QSEECOM_LEGACY_H_
+#define __QSEECOM_LEGACY_H_
+
+#include <linux/types.h>
+
+#define TZ_SCHED_CMD_ID_REGISTER_LISTENER 0x04
+
+enum tz_sched_cmd_type {
+ TZ_SCHED_CMD_INVALID = 0,
+ TZ_SCHED_CMD_NEW, /* New TZ Scheduler Command */
+ TZ_SCHED_CMD_PENDING, /* Pending cmd...sched will restore stack */
+ TZ_SCHED_CMD_COMPLETE, /* TZ sched command is complete */
+ TZ_SCHED_CMD_MAX = 0x7FFFFFFF
+};
+
+enum tz_sched_cmd_status {
+ TZ_SCHED_STATUS_INCOMPLETE = 0,
+ TZ_SCHED_STATUS_COMPLETE,
+ TZ_SCHED_STATUS_MAX = 0x7FFFFFFF
+};
+/* Command structure for initializing shared buffers */
+__packed struct qse_pr_init_sb_req_s {
+ /* First 4 bytes should always be command id */
+ uint32_t pr_cmd;
+ /* Pointer to the physical location of sb buffer */
+ uint32_t sb_ptr;
+ /* length of shared buffer */
+ uint32_t sb_len;
+ uint32_t listener_id;
+};
+
+__packed struct qse_pr_init_sb_rsp_s {
+ /* First 4 bytes should always be command id */
+ uint32_t pr_cmd;
+ /* Return code, 0 for success, Approp error code otherwise */
+ int32_t ret;
+};
+
+/*
+ * struct QSEECom_command - QSECom command buffer
+ * @cmd_type: value from enum tz_sched_cmd_type
+ * @sb_in_cmd_addr: points to physical location of command
+ * buffer
+ * @sb_in_cmd_len: length of command buffer
+ */
+__packed struct qseecom_command {
+ uint32_t cmd_type;
+ uint8_t *sb_in_cmd_addr;
+ uint32_t sb_in_cmd_len;
+};
+
+/*
+ * struct QSEECom_response - QSECom response buffer
+ * @cmd_status: value from enum tz_sched_cmd_status
+ * @sb_in_rsp_addr: points to physical location of response
+ * buffer
+ * @sb_in_rsp_len: length of command response
+ */
+__packed struct qseecom_response {
+ uint32_t cmd_status;
+ uint8_t *sb_in_rsp_addr;
+ uint32_t sb_in_rsp_len;
+};
+
+#endif /* __QSEECOM_LEGACY_H_ */
diff --git a/drivers/misc/tzcom.c b/drivers/misc/tzcom.c
index e662f43..2b1484c 100644
--- a/drivers/misc/tzcom.c
+++ b/drivers/misc/tzcom.c
@@ -1002,7 +1002,10 @@
}
spin_unlock_irqrestore(&tzcom_data->registered_svc_list_lock, flags);
PDEBUG("After removing svc list");
-
+ if (pil != NULL) {
+ pil_put(pil);
+ pil = NULL;
+ }
PDEBUG("Freeing tzcom data");
kfree(tzcom_data);
return 0;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 3ae639e..e364eac 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1042,8 +1042,6 @@
host->curr.got_dataend = 0;
host->curr.got_auto_prog_done = 0;
- memset(&host->pio, 0, sizeof(host->pio));
-
datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
if (host->curr.wait_for_auto_prog_done)
@@ -1078,17 +1076,21 @@
/* Is data transfer in PIO mode required? */
if (!(datactrl & MCI_DPSM_DMAENABLE)) {
- host->pio.sg = data->sg;
- host->pio.sg_len = data->sg_len;
- host->pio.sg_off = 0;
+ unsigned int sg_miter_flags = SG_MITER_ATOMIC;
if (data->flags & MMC_DATA_READ) {
+ sg_miter_flags |= SG_MITER_TO_SG;
pio_irqmask = MCI_RXFIFOHALFFULLMASK;
if (host->curr.xfer_remain < MCI_FIFOSIZE)
pio_irqmask |= MCI_RXDATAAVLBLMASK;
- } else
+ } else {
+ sg_miter_flags |= SG_MITER_FROM_SG;
pio_irqmask = MCI_TXFIFOHALFEMPTYMASK |
MCI_TXFIFOEMPTYMASK;
+ }
+
+ sg_miter_start(&host->sg_miter, data->sg, data->sg_len,
+ sg_miter_flags);
}
if (data->flags & MMC_DATA_READ)
@@ -1254,6 +1256,7 @@
struct msmsdcc_host *host = dev_id;
void __iomem *base = host->base;
uint32_t status;
+ unsigned long flags;
spin_lock(&host->lock);
@@ -1268,9 +1271,10 @@
#if IRQ_DEBUG
msmsdcc_print_status(host, "irq1-r", status);
#endif
+ local_irq_save(flags);
- do {
- unsigned long flags;
+ while (sg_miter_next(&host->sg_miter)) {
+
unsigned int remain, len;
char *buffer;
@@ -1278,12 +1282,8 @@
| MCI_RXDATAAVLBL)))
break;
- /* Map the current scatter buffer */
- local_irq_save(flags);
- buffer = kmap_atomic(sg_page(host->pio.sg),
- KM_BIO_SRC_IRQ) + host->pio.sg->offset;
- buffer += host->pio.sg_off;
- remain = host->pio.sg->length - host->pio.sg_off;
+ buffer = host->sg_miter.addr;
+ remain = host->sg_miter.length;
len = 0;
if (status & MCI_RXACTIVE)
@@ -1294,11 +1294,7 @@
if (len > remain)
len = remain;
- /* Unmap the buffer */
- kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
- local_irq_restore(flags);
-
- host->pio.sg_off += len;
+ host->sg_miter.consumed = len;
host->curr.xfer_remain -= len;
host->curr.data_xfered += len;
remain -= len;
@@ -1306,20 +1302,11 @@
if (remain) /* Done with this page? */
break; /* Nope */
- if (status & MCI_RXACTIVE && host->curr.user_pages)
- flush_dcache_page(sg_page(host->pio.sg));
-
- if (!--host->pio.sg_len) {
- memset(&host->pio, 0, sizeof(host->pio));
- break;
- }
-
- /* Advance to next sg */
- host->pio.sg++;
- host->pio.sg_off = 0;
-
status = readl_relaxed(base + MMCISTATUS);
- } while (1);
+ }
+
+ sg_miter_stop(&host->sg_miter);
+ local_irq_restore(flags);
if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
@@ -2300,6 +2287,10 @@
/* Select free running MCLK as input clock of cm_dll_sdc4 */
clk |= (2 << 23);
+ /* Clear IO_PAD_PWR_SWITCH while powering off the card */
+ if (!ios->vdd)
+ host->io_pad_pwr_switch = 0;
+
if (host->io_pad_pwr_switch)
clk |= IO_PAD_PWR_SWITCH;
@@ -2575,6 +2566,10 @@
unsigned long flags;
int rc = 0;
+ spin_lock_irqsave(&host->lock, flags);
+ host->io_pad_pwr_switch = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
/* Change voltage level of VDDPX to high voltage */
rc = msmsdcc_set_vddp_high_vol(host);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index ee7a3e5..319d721 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -361,7 +361,7 @@
struct msmsdcc_sps_data sps;
bool is_dma_mode;
bool is_sps_mode;
- struct msmsdcc_pio_data pio;
+ struct sg_mapping_iter sg_miter;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 4be8373..167efd9 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -318,6 +318,17 @@
The driver provides wear leveling by storing erase counter into the
OOB.
+config MTD_LAZYECCSTATS
+ bool "MTD Lazy ECC Stats collection support"
+ default y
+ help
+ Normally bad block counts for ECC stats are collected at boot time.
+ This option delays the badblock stats collection until ECCGETSTATS
+ ioctl is invoked on the partition.
+
+ This can significantly decrease boot times depending on the size of
+ the partition. If unsure, say 'N'.
+
source "drivers/mtd/chips/Kconfig"
source "drivers/mtd/maps/Kconfig"
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f1af222..ed9468c 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -34,6 +34,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
#include <asm/uaccess.h>
@@ -904,6 +905,9 @@
case ECCGETSTATS:
{
+#ifdef CONFIG_MTD_LAZYECCSTATS
+ part_fill_badblockstats(mtd);
+#endif
if (copy_to_user(argp, &mtd->ecc_stats,
sizeof(struct mtd_ecc_stats)))
return -EFAULT;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 630be3e..4c75f32 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -353,6 +353,21 @@
kfree(p);
}
+void part_fill_badblockstats(struct mtd_info *mtd)
+{
+ struct mtd_part *part = PART(mtd);
+ if (part->master->block_isbad) {
+ uint64_t offs = 0;
+ mtd->ecc_stats.badblocks = 0;
+ while (offs < mtd->size) {
+ if (part->master->block_isbad(part->master,
+ offs + part->offset))
+ mtd->ecc_stats.badblocks++;
+ offs += mtd->erasesize;
+ }
+ }
+}
+
/*
* This function unregisters and destroy all slave MTD objects which are
* attached to the given master MTD object.
@@ -542,16 +557,10 @@
}
slave->mtd.ecclayout = master->ecclayout;
- if (master->block_isbad) {
- uint64_t offs = 0;
- while (offs < slave->mtd.size) {
- if (master->block_isbad(master,
- offs + slave->offset))
- slave->mtd.ecc_stats.badblocks++;
- offs += slave->mtd.erasesize;
- }
- }
+#ifndef CONFIG_MTD_LAZYECCSTATS
+ part_fill_badblockstats(&(slave->mtd));
+#endif
out_register:
return slave;
diff --git a/drivers/net/qfec.c b/drivers/net/qfec.c
index fc27837..e1f4be2 100644
--- a/drivers/net/qfec.c
+++ b/drivers/net/qfec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1899,6 +1899,11 @@
setup_timer(&priv->phy_tmr, qfec_phy_monitor, (unsigned long)dev);
mod_timer(&priv->phy_tmr, jiffies + HZ);
+ /* driver supports AN capable PHY only */
+ qfec_mdio_write(dev, priv->phy_id, MII_BMCR, BMCR_RESET);
+ res = (BMCR_ANENABLE|BMCR_ANRESTART);
+ qfec_mdio_write(dev, priv->phy_id, MII_BMCR, res);
+
/* initialize interrupts */
QFEC_LOG(QFEC_LOG_DBG, " %s: request irq %d\n", __func__, dev->irq);
res = request_irq(dev->irq, qfec_int, 0, dev->name, dev);
diff --git a/drivers/net/wireless/libra/qcomwlan_pwrif.c b/drivers/net/wireless/libra/qcomwlan_pwrif.c
index 8268f24..6a0c78f 100644
--- a/drivers/net/wireless/libra/qcomwlan_pwrif.c
+++ b/drivers/net/wireless/libra/qcomwlan_pwrif.c
@@ -72,7 +72,7 @@
static const int vregs_qwlan_peek_current[] = {
4000,
150000,
- 200000,
+ 60000,
0,
32000,
130000,
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 93de829..3104daf 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -29,6 +29,7 @@
#define BMS_CONTROL 0x224
#define BMS_OUTPUT0 0x230
#define BMS_OUTPUT1 0x231
+#define BMS_TOLERANCES 0x232
#define BMS_TEST1 0x237
#define ADC_ARB_SECP_CNTRL 0x190
@@ -1268,6 +1269,10 @@
}
EXPORT_SYMBOL_GPL(pm8921_bms_get_fcc);
+#define IBAT_TOL_MASK 0x0F
+#define OCV_TOL_MASK 0xF0
+#define IBAT_TOL_DEFAULT 0x03
+#define IBAT_TOL_NOCHG 0x0F
void pm8921_bms_charging_began(void)
{
int batt_temp, rc;
@@ -1291,7 +1296,8 @@
bms_start_percent = the_chip->start_percent;
bms_start_ocv_uv = raw.last_good_ocv_uv;
calculate_cc_uah(the_chip, raw.cc, &bms_start_cc_uah);
-
+ pm_bms_masked_write(the_chip, BMS_TOLERANCES,
+ IBAT_TOL_MASK, IBAT_TOL_DEFAULT);
pr_debug("start_percent = %u%%\n", the_chip->start_percent);
}
EXPORT_SYMBOL_GPL(pm8921_bms_charging_began);
@@ -1373,6 +1379,8 @@
last_chargecycles);
the_chip->start_percent = -EINVAL;
the_chip->end_percent = -EINVAL;
+ pm_bms_masked_write(the_chip, BMS_TOLERANCES,
+ IBAT_TOL_MASK, IBAT_TOL_NOCHG);
}
EXPORT_SYMBOL_GPL(pm8921_bms_charging_end);
@@ -1514,6 +1522,9 @@
BMS_CONTROL, rc);
}
+ /* The charger will call start charge later if usb is present */
+ pm_bms_masked_write(chip, BMS_TOLERANCES,
+ IBAT_TOL_MASK, IBAT_TOL_NOCHG);
return 0;
}
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index fa8f866..aca724a 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -415,14 +415,6 @@
disable ? CHG_CHARGE_DIS_BIT : 0);
}
-static bool pm_is_chg_charge_dis_bit_set(struct pm8921_chg_chip *chip)
-{
- u8 temp = 0;
-
- pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
- return !!(temp & CHG_CHARGE_DIS_BIT);
-}
-
#define PM8921_CHG_V_MIN_MV 3240
#define PM8921_CHG_V_STEP_MV 20
#define PM8921_CHG_V_STEP_10_MV_BIT BIT(7)
@@ -1024,24 +1016,34 @@
break;
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_ONLINE:
- if (pm_is_chg_charge_dis_bit_set(the_chip) ||
- !is_usb_chg_plugged_in(the_chip))
- val->intval = 0;
- else if (psy->type == POWER_SUPPLY_TYPE_USB ||
+ val->intval = 0;
+ if (charging_disabled)
+ return 0;
+
+ /* USB charging */
+ if (psy->type == POWER_SUPPLY_TYPE_USB ||
psy->type == POWER_SUPPLY_TYPE_USB_DCP ||
psy->type == POWER_SUPPLY_TYPE_USB_CDP ||
psy->type == POWER_SUPPLY_TYPE_USB_ACA) {
- val->intval = 1;
- } else if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
+ val->intval = is_usb_chg_plugged_in(the_chip);
+ return 0;
+ }
+
+ /* DC charging */
+ if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
+ /* external charger is connected */
+ if (the_chip->dc_present || is_ext_charging(the_chip)) {
+ val->intval = 1;
+ return 0;
+ }
+ /* USB with max current greater than 500 mA connected */
pm_chg_iusbmax_get(the_chip, ¤t_max);
if (current_max > USB_WALL_THRESHOLD_MA)
- val->intval = 1;
- else
- val->intval = 0;
- } else {
- val->intval = 0;
- pr_err("Unkown POWER_SUPPLY_TYPE %d\n", psy->type);
+ val->intval = is_usb_chg_plugged_in(the_chip);
+ return 0;
}
+
+ pr_err("Unkown POWER_SUPPLY_TYPE %d\n", psy->type);
break;
default:
return -EINVAL;
@@ -1592,6 +1594,7 @@
the_chip->usb_psy.type = type;
power_supply_changed(&the_chip->usb_psy);
+ power_supply_changed(&the_chip->dc_psy);
return 0;
}
EXPORT_SYMBOL_GPL(pm8921_set_usb_power_supply_type);
@@ -1639,6 +1642,7 @@
power_supply_set_charge_type(chip->ext_psy,
POWER_SUPPLY_CHARGE_TYPE_NONE);
pm8921_disable_source_current(false); /* release BATFET */
+ power_supply_changed(&chip->dc_psy);
chip->ext_charging = false;
chip->ext_charge_done = false;
bms_notify_check(chip);
@@ -1686,8 +1690,10 @@
return;
}
+ power_supply_set_online(chip->ext_psy, dc_present);
power_supply_set_charge_type(chip->ext_psy,
POWER_SUPPLY_CHARGE_TYPE_FAST);
+ power_supply_changed(&chip->dc_psy);
chip->ext_charging = true;
chip->ext_charge_done = false;
bms_notify_check(chip);
@@ -1768,6 +1774,7 @@
power_supply_changed(&chip->batt_psy);
power_supply_changed(&chip->usb_psy);
+ power_supply_changed(&chip->dc_psy);
return IRQ_HANDLED;
}
@@ -1819,6 +1826,7 @@
power_supply_changed(&chip->batt_psy);
power_supply_changed(&chip->usb_psy);
+ power_supply_changed(&chip->dc_psy);
bms_notify_check(chip);
@@ -1841,6 +1849,7 @@
power_supply_changed(&chip->batt_psy);
power_supply_changed(&chip->usb_psy);
+ power_supply_changed(&chip->dc_psy);
return IRQ_HANDLED;
}
@@ -1851,6 +1860,7 @@
pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
power_supply_changed(&chip->batt_psy);
power_supply_changed(&chip->usb_psy);
+ power_supply_changed(&chip->dc_psy);
bms_notify_check(chip);
diff --git a/drivers/regulator/pm8xxx-regulator.c b/drivers/regulator/pm8xxx-regulator.c
index 94b028d..fa17449 100644
--- a/drivers/regulator/pm8xxx-regulator.c
+++ b/drivers/regulator/pm8xxx-regulator.c
@@ -401,6 +401,19 @@
#define NCP_SET_POINTS ((NCP_UV_MAX - NCP_UV_MIN) \
/ NCP_UV_STEP + 1)
+/* Boost masks and values */
+#define BOOST_ENABLE_MASK 0x80
+#define BOOST_DISABLE 0x00
+#define BOOST_ENABLE 0x80
+#define BOOST_VPROG_MASK 0x1F
+
+#define BOOST_UV_MIN 4000000
+#define BOOST_UV_MAX 5550000
+#define BOOST_UV_STEP 50000
+
+#define BOOST_SET_POINTS ((BOOST_UV_MAX - BOOST_UV_MIN) \
+ / BOOST_UV_STEP + 1)
+
#define vreg_err(vreg, fmt, ...) \
pr_err("%s: " fmt, vreg->rdesc.name, ##__VA_ARGS__)
@@ -1424,6 +1437,64 @@
return rc;
}
+static int pm8xxx_boost_get_voltage(struct regulator_dev *rdev)
+{
+ struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
+ u8 vprog;
+
+ vprog = vreg->ctrl_reg & BOOST_VPROG_MASK;
+
+ return BOOST_UV_STEP * vprog + BOOST_UV_MIN;
+}
+
+static int pm8xxx_boost_list_voltage(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ if (selector >= BOOST_SET_POINTS)
+ return 0;
+
+ return selector * BOOST_UV_STEP + BOOST_UV_MIN;
+}
+
+static int pm8xxx_boost_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
+ int rc;
+ int uV = min_uV;
+ u8 val;
+
+ if (uV < BOOST_UV_MIN && max_uV >= BOOST_UV_MIN)
+ uV = BOOST_UV_MIN;
+
+ if (uV < BOOST_UV_MIN || uV > BOOST_UV_MAX) {
+ vreg_err(vreg,
+ "request v=[%d, %d] is outside possible v=[%d, %d]\n",
+ min_uV, max_uV, BOOST_UV_MIN, BOOST_UV_MAX);
+ return -EINVAL;
+ }
+
+ val = (uV - BOOST_UV_MIN + BOOST_UV_STEP - 1) / BOOST_UV_STEP;
+ uV = val * BOOST_UV_STEP + BOOST_UV_MIN;
+
+ if (uV > max_uV) {
+ vreg_err(vreg,
+ "request v=[%d, %d] cannot be met by any set point\n",
+ min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ /* voltage setting */
+ rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, val,
+ BOOST_VPROG_MASK, &vreg->ctrl_reg);
+ if (rc)
+ vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc);
+ else
+ pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_VOLTAGE);
+
+ return rc;
+}
+
static unsigned int pm8xxx_ldo_get_mode(struct regulator_dev *rdev)
{
struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
@@ -2066,6 +2137,38 @@
return rc;
}
+static int pm8xxx_boost_enable(struct regulator_dev *rdev)
+{
+ struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
+ int rc;
+
+ rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, BOOST_ENABLE,
+ BOOST_ENABLE_MASK, &vreg->ctrl_reg);
+
+ if (rc)
+ vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc);
+ else
+ pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_ENABLE);
+
+ return rc;
+}
+
+static int pm8xxx_boost_disable(struct regulator_dev *rdev)
+{
+ struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
+ int rc;
+
+ rc = pm8xxx_vreg_masked_write(vreg, vreg->ctrl_addr, BOOST_DISABLE,
+ BOOST_ENABLE_MASK, &vreg->ctrl_reg);
+
+ if (rc)
+ vreg_err(vreg, "pm8xxx_vreg_masked_write failed, rc=%d\n", rc);
+ else
+ pm8xxx_vreg_show_state(rdev, PM8XXX_REGULATOR_ACTION_DISABLE);
+
+ return rc;
+}
+
static int pm8xxx_ldo_pin_control_enable(struct regulator_dev *rdev)
{
struct pm8xxx_vreg *vreg = rdev_get_drvdata(rdev);
@@ -2506,6 +2609,11 @@
pr_info("%s %-9s: %s, v=%7d uV\n",
action_label, vreg->rdesc.name, enable_label, uV);
break;
+ case PM8XXX_REGULATOR_TYPE_BOOST:
+ uV = pm8xxx_boost_get_voltage(rdev);
+ pr_info("%s %-9s: %s, v=%7d uV\n",
+ action_label, vreg->rdesc.name, enable_label, uV);
+ break;
default:
break;
}
@@ -2601,6 +2709,16 @@
.enable_time = pm8xxx_enable_time,
};
+static struct regulator_ops pm8xxx_boost_ops = {
+ .enable = pm8xxx_boost_enable,
+ .disable = pm8xxx_boost_disable,
+ .is_enabled = pm8xxx_vreg_is_enabled,
+ .set_voltage = pm8xxx_boost_set_voltage,
+ .get_voltage = pm8xxx_boost_get_voltage,
+ .list_voltage = pm8xxx_boost_list_voltage,
+ .enable_time = pm8xxx_enable_time,
+};
+
/* Pin control regulator operations. */
static struct regulator_ops pm8xxx_ldo_pc_ops = {
.enable = pm8xxx_ldo_pin_control_enable,
@@ -2629,6 +2747,7 @@
[PM8XXX_REGULATOR_TYPE_VS] = &pm8xxx_vs_ops,
[PM8XXX_REGULATOR_TYPE_VS300] = &pm8xxx_vs300_ops,
[PM8XXX_REGULATOR_TYPE_NCP] = &pm8xxx_ncp_ops,
+ [PM8XXX_REGULATOR_TYPE_BOOST] = &pm8xxx_boost_ops,
};
static struct regulator_ops *pm8xxx_reg_pc_ops[PM8XXX_REGULATOR_TYPE_MAX] = {
@@ -2647,6 +2766,7 @@
[PM8XXX_REGULATOR_TYPE_VS] = 0,
[PM8XXX_REGULATOR_TYPE_VS300] = 0,
[PM8XXX_REGULATOR_TYPE_NCP] = NCP_SET_POINTS,
+ [PM8XXX_REGULATOR_TYPE_BOOST] = BOOST_SET_POINTS,
};
static int pm8xxx_init_ldo(struct pm8xxx_vreg *vreg, bool is_real)
@@ -2937,6 +3057,20 @@
return rc;
}
+static int pm8xxx_init_boost(struct pm8xxx_vreg *vreg)
+{
+ int rc;
+
+ /* Save the current control register state. */
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg);
+ if (rc) {
+ vreg_err(vreg, "pm8xxx_readb failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
static int __devinit pm8xxx_vreg_probe(struct platform_device *pdev)
{
struct pm8xxx_regulator_core_platform_data *core_data;
@@ -3058,6 +3192,9 @@
case PM8XXX_REGULATOR_TYPE_NCP:
rc = pm8xxx_init_ncp(vreg);
break;
+ case PM8XXX_REGULATOR_TYPE_BOOST:
+ rc = pm8xxx_init_boost(vreg);
+ break;
default:
break;
}
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 02d1c39..22297be 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1171,6 +1171,27 @@
}
slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
sat->satcl.laddr = laddr;
+ /*
+ * Since capability message is already sent, present
+ * message will indicate subsystem hosting this
+ * satellite has restarted.
+ * Remove all active channels of this satellite
+ * when this is detected
+ */
+ if (sat->sent_capability) {
+ for (i = 0; i < sat->nsatch; i++) {
+ enum slim_ch_state chs =
+ slim_get_ch_state(&sat->satcl,
+ sat->satch[i].chanh);
+ pr_err("Slim-SSR, sat:%d, rm chan:%d",
+ laddr,
+ sat->satch[i].chan);
+ if (chs == SLIM_CH_ACTIVE)
+ slim_control_ch(&sat->satcl,
+ sat->satch[i].chanh,
+ SLIM_CH_REMOVE, true);
+ }
+ }
} else if (mt != SLIM_MSG_MT_CORE &&
mc != SLIM_MSG_MC_REPORT_PRESENT) {
satv = msm_slim_get_ctrl(dev);
@@ -1886,7 +1907,7 @@
}
- dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
+ dev->rclk = clk_get(dev->dev, "core_clk");
if (!dev->rclk) {
dev_err(dev->dev, "slimbus clock not found");
goto err_clk_get_failed;
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 6733396..cc008ab 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2730,15 +2730,19 @@
* -EXFULL is returned if there is no space in TDM to reserve the bandwidth.
* -EISCONN/-ENOTCONN is returned if the channel is already connected or not
* yet defined.
+ * -EINVAL is returned if individual control of a grouped-channel is attempted.
*/
int slim_control_ch(struct slim_device *sb, u16 chanh,
enum slim_ch_control chctrl, bool commit)
{
struct slim_controller *ctrl = sb->ctrl;
- struct slim_ich *slc;
int ret = 0;
/* Get rid of the group flag in MSB if any */
u8 chan = SLIM_HDL_TO_CHIDX(chanh);
+ struct slim_ich *slc = &ctrl->chans[chan];
+ if (!(slc->nextgrp & SLIM_START_GRP))
+ return -EINVAL;
+
mutex_lock(&sb->sldev_reconf);
mutex_lock(&ctrl->m_ctrl);
do {
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
new file mode 100644
index 0000000..7768eed
--- /dev/null
+++ b/drivers/spmi/Kconfig
@@ -0,0 +1,29 @@
+#
+# SPMI driver configuration
+#
+menuconfig SPMI
+ bool "SPMI support"
+ help
+ SPMI (System Power Management Interface) is a two-wire
+ serial interface between baseband and application processors
+ and Power Management Integrated Circuits (PMIC).
+
+if SPMI
+config SPMI_MSM_PMIC_ARB
+ tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
+ help
+ If you say yes to this option, support will be included for the
+ built-in SPMI PMIC Arbiter interface on Qualcomm MSM family
+ processors.
+
+ This is required for communicating with Qualcomm PMICs and
+ other devices that have the SPMI interface.
+
+config MSM_QPNP
+ depends on ARCH_MSMCOPPER
+ depends on OF_SPMI
+ bool "MSM QPNP"
+ help
+ Say 'y' here to include support for the Qualcomm QPNP
+ support. QPNP is a SPMI based PMIC implementation.
+endif
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
new file mode 100644
index 0000000..659e886
--- /dev/null
+++ b/drivers/spmi/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for kernel SPMI framework.
+#
+obj-$(CONFIG_SPMI) += spmi.o
+obj-$(CONFIG_SPMI_MSM_PMIC_ARB) += spmi-pmic-arb.o
+obj-$(CONFIG_MSM_QPNP) += qpnp.o
diff --git a/drivers/spmi/qpnp.c b/drivers/spmi/qpnp.c
new file mode 100644
index 0000000..ddf9000
--- /dev/null
+++ b/drivers/spmi/qpnp.c
@@ -0,0 +1,55 @@
+/* Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Resource handling based on platform.c.
+ */
+
+#include <mach/qpnp.h>
+
+/**
+ * qpnp_get_resource - get a resource for a device
+ * @dev: qpnp device
+ * @type: resource type
+ * @num: resource index
+ */
+struct resource *qpnp_get_resource(struct spmi_device *dev,
+ unsigned int node_idx, unsigned int type,
+ unsigned int res_num)
+{
+ int i;
+
+ for (i = 0; i < dev->dev_node[node_idx].num_resources; i++) {
+ struct resource *r = &dev->dev_node[node_idx].resource[i];
+
+ if (type == resource_type(r) && res_num-- == 0)
+ return r;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(qpnp_get_resource);
+
+/**
+ * qpnp_get_irq - get an IRQ for a device
+ * @dev: qpnp device
+ * @num: IRQ number index
+ */
+int qpnp_get_irq(struct spmi_device *dev, unsigned int node_idx,
+ unsigned int res_num)
+{
+ struct resource *r = qpnp_get_resource(dev, node_idx,
+ IORESOURCE_IRQ, res_num);
+
+ return r ? r->start : -ENXIO;
+}
+EXPORT_SYMBOL_GPL(qpnp_get_irq);
+
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
new file mode 100644
index 0000000..e5a9d40
--- /dev/null
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -0,0 +1,733 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/of_spmi.h>
+#include <mach/qpnp-int.h>
+
+#define SPMI_PMIC_ARB_NAME "spmi_pmic_arb"
+
+/* PMIC Arbiter configuration registers */
+#define PMIC_ARB_VERSION 0x0000
+#define PMIC_ARB_INT_EN 0x0004
+
+/* PMIC Arbiter channel registers */
+#define PMIC_ARB_CMD(N) (0x0800 + (0x80 * (N)))
+#define PMIC_ARB_CONFIG(N) (0x0804 + (0x80 * (N)))
+#define PMIC_ARB_STATUS(N) (0x0808 + (0x80 * (N)))
+#define PMIC_ARB_WDATA0(N) (0x0810 + (0x80 * (N)))
+#define PMIC_ARB_WDATA1(N) (0x0814 + (0x80 * (N)))
+#define PMIC_ARB_RDATA0(N) (0x0818 + (0x80 * (N)))
+#define PMIC_ARB_RDATA1(N) (0x081C + (0x80 * (N)))
+
+/* Interrupt Controller */
+#define SPMI_PIC_OWNER_ACC_STATUS(M, N) (0x0000 + ((32 * (M)) + (4 * (N))))
+#define SPMI_PIC_ACC_ENABLE(N) (0x0200 + (4 * (N)))
+#define SPMI_PIC_IRQ_STATUS(N) (0x0600 + (4 * (N)))
+#define SPMI_PIC_IRQ_CLEAR(N) (0x0A00 + (4 * (N)))
+
+/* Channel Status fields */
+enum pmic_arb_chnl_status {
+ PMIC_ARB_STATUS_DONE = (1 << 0),
+ PMIC_ARB_STATUS_FAILURE = (1 << 1),
+ PMIC_ARB_STATUS_DENIED = (1 << 2),
+ PMIC_ARB_STATUS_DROPPED = (1 << 3),
+};
+
+/* Command register fields */
+#define PMIC_ARB_CMD_MAX_BYTE_COUNT 8
+
+/* Command Opcodes */
+enum pmic_arb_cmd_op_code {
+ PMIC_ARB_OP_EXT_WRITEL = 0,
+ PMIC_ARB_OP_EXT_READL = 1,
+ PMIC_ARB_OP_EXT_WRITE = 2,
+ PMIC_ARB_OP_RESET = 3,
+ PMIC_ARB_OP_SLEEP = 4,
+ PMIC_ARB_OP_SHUTDOWN = 5,
+ PMIC_ARB_OP_WAKEUP = 6,
+ PMIC_ARB_OP_AUTHENTICATE = 7,
+ PMIC_ARB_OP_MSTR_READ = 8,
+ PMIC_ARB_OP_MSTR_WRITE = 9,
+ PMIC_ARB_OP_EXT_READ = 13,
+ PMIC_ARB_OP_WRITE = 14,
+ PMIC_ARB_OP_READ = 15,
+ PMIC_ARB_OP_ZERO_WRITE = 16,
+};
+
+/* Maximum number of support PMIC peripherals */
+#define PMIC_ARB_MAX_PERIPHS 256
+#define PMIC_ARB_PERIPH_ID_VALID (1 << 15)
+#define PMIC_ARB_TIMEOUT_US 100
+#define PMIC_ARB_APID_MASK 0xFF
+#define PMIC_ARB_PPID_MASK 0xFFF
+
+/**
+ * base - base address of the PMIC Arbiter core registers.
+ * intr - base address of the SPMI interrupt control registers
+ */
+struct spmi_pmic_arb_dev {
+ struct spmi_controller controller;
+ struct device *dev;
+ struct device *slave;
+ void __iomem *base;
+ void __iomem *intr;
+ int pic_irq;
+ int pic_enable_cnt;
+ spinlock_t lock;
+ u8 owner;
+ u8 channel;
+ u8 min_apid;
+ u8 max_apid;
+ u16 periph_id_map[PMIC_ARB_MAX_PERIPHS];
+};
+
+static u32 pmic_arb_read(struct spmi_pmic_arb_dev *dev, u32 offset)
+{
+ u32 val = readl_relaxed(dev->base + offset);
+ pr_debug("address 0x%p, val 0x%x\n", dev->base + offset, val);
+ return val;
+}
+
+static void pmic_arb_write(struct spmi_pmic_arb_dev *dev, u32 offset, u32 val)
+{
+ pr_debug("address 0x%p, val 0x%x\n", dev->base + offset, val);
+ writel_relaxed(val, dev->base + offset);
+}
+
+static int pmic_arb_wait_for_done(struct spmi_pmic_arb_dev *dev)
+{
+ u32 status = 0;
+ u32 timeout = PMIC_ARB_TIMEOUT_US;
+ u32 offset = PMIC_ARB_STATUS(dev->channel);
+
+ while (timeout--) {
+ status = pmic_arb_read(dev, offset);
+
+ if (status & PMIC_ARB_STATUS_DONE) {
+ if (status & PMIC_ARB_STATUS_DENIED) {
+ dev_err(dev->dev,
+ "%s: transaction denied (0x%x)\n",
+ __func__, status);
+ return -EPERM;
+ }
+
+ if (status & PMIC_ARB_STATUS_FAILURE) {
+ dev_err(dev->dev,
+ "%s: transaction failed (0x%x)\n",
+ __func__, status);
+ return -EIO;
+ }
+
+ if (status & PMIC_ARB_STATUS_DROPPED) {
+ dev_err(dev->dev,
+ "%s: transaction dropped (0x%x)\n",
+ __func__, status);
+ return -EIO;
+ }
+
+ return 0;
+ }
+ udelay(1);
+ }
+
+ dev_err(dev->dev, "%s: timeout, status 0x%x\n", __func__, status);
+ return -ETIMEDOUT;
+}
+
+static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+{
+ u32 data = pmic_arb_read(dev, reg);
+
+ switch (bc & 0x3) {
+ case 3:
+ *buf++ = data & 0xff;
+ data >>= 8;
+ case 2:
+ *buf++ = data & 0xff;
+ data >>= 8;
+ case 1:
+ *buf++ = data & 0xff;
+ data >>= 8;
+ case 0:
+ *buf++ = data & 0xff;
+ default:
+ break;
+ }
+}
+
+static void
+pa_write_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+{
+ u32 data = 0;
+
+ switch (bc & 0x3) {
+ case 3:
+ data = (buf[0]|buf[1]<<8|buf[2]<<16|buf[3]<<24);
+ break;
+ case 2:
+ data = (buf[0]|buf[1]<<8|buf[2]<<16);
+ break;
+ case 1:
+ data = (buf[0]|buf[1]<<8);
+ break;
+ case 0:
+ data = (buf[0]);
+ break;
+ default:
+ break;
+ }
+
+ pmic_arb_write(dev, reg, data);
+}
+
+/* Non-data command */
+static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
+{
+ struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+ unsigned long flags;
+ u32 cmd;
+ int rc;
+
+ pr_debug("op:0x%x sid:%d\n", opc, sid);
+
+ /* Check for valid non-data command */
+ if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
+ return -EINVAL;
+
+ cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
+
+ spin_lock_irqsave(&pmic_arb->lock, flags);
+ pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+ rc = pmic_arb_wait_for_done(pmic_arb);
+ spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+ return rc;
+}
+
+static int pmic_arb_read_cmd(struct spmi_controller *ctrl,
+ u8 opc, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+ struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+ unsigned long flags;
+ u32 cmd;
+ int rc;
+
+ pr_debug("op:0x%x sid:%d bc:%d addr:0x%x\n", opc, sid, bc, addr);
+
+ /* Check the opcode */
+ if (opc >= 0x60 && opc <= 0x7F)
+ opc = PMIC_ARB_OP_READ;
+ else if (opc >= 0x20 && opc <= 0x2F)
+ opc = PMIC_ARB_OP_EXT_READ;
+ else if (opc >= 0x38 && opc <= 0x3F)
+ opc = PMIC_ARB_OP_EXT_READL;
+ else
+ return -EINVAL;
+
+ cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+ spin_lock_irqsave(&pmic_arb->lock, flags);
+ pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+ rc = pmic_arb_wait_for_done(pmic_arb);
+ if (rc)
+ goto done;
+
+ /* Read from FIFO, note 'bc' is actually number of bytes minus 1 */
+ pa_read_data(pmic_arb, buf, PMIC_ARB_RDATA0(pmic_arb->channel), bc);
+
+ if (bc > 3)
+ pa_read_data(pmic_arb, buf + 4,
+ PMIC_ARB_RDATA1(pmic_arb->channel), bc);
+
+done:
+ spin_unlock_irqrestore(&pmic_arb->lock, flags);
+ return rc;
+}
+
+static int pmic_arb_write_cmd(struct spmi_controller *ctrl,
+ u8 opc, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+ struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+ unsigned long flags;
+ u32 cmd;
+ int rc;
+
+ pr_debug("op:0x%x sid:%d bc:%d addr:0x%x\n", opc, sid, bc, addr);
+
+ /* Check the opcode */
+ if (opc >= 0x40 && opc <= 0x5F)
+ opc = PMIC_ARB_OP_WRITE;
+ else if (opc >= 0x00 && opc <= 0x0F)
+ opc = PMIC_ARB_OP_EXT_WRITE;
+ else if (opc >= 0x30 && opc <= 0x37)
+ opc = PMIC_ARB_OP_EXT_WRITEL;
+ else if (opc >= 0x80 && opc <= 0xFF)
+ opc = PMIC_ARB_OP_ZERO_WRITE;
+ else
+ return -EINVAL;
+
+ cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+ /* Write data to FIFOs */
+ spin_lock_irqsave(&pmic_arb->lock, flags);
+ pa_write_data(pmic_arb, buf, PMIC_ARB_WDATA0(pmic_arb->channel), bc);
+
+ if (bc > 3)
+ pa_write_data(pmic_arb, buf + 4,
+ PMIC_ARB_WDATA1(pmic_arb->channel), bc);
+
+ /* Start the transaction */
+ pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+ rc = pmic_arb_wait_for_done(pmic_arb);
+ spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+ return rc;
+}
+
+/* APID to PPID */
+static u16 get_peripheral_id(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+ return pmic_arb->periph_id_map[apid] & PMIC_ARB_PPID_MASK;
+}
+
+/* APID to PPID, returns valid flag */
+static int is_apid_valid(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+ return pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID;
+}
+
+/* PPID to APID */
+static uint32_t map_peripheral_id(struct spmi_pmic_arb_dev *pmic_arb, u16 ppid)
+{
+ int first = pmic_arb->min_apid;
+ int last = pmic_arb->max_apid;
+ int i;
+
+ /* Search table for a matching PPID */
+ for (i = first; i <= last; ++i) {
+ if ((pmic_arb->periph_id_map[i] & PMIC_ARB_PPID_MASK) == ppid)
+ return i;
+ }
+
+ dev_err(pmic_arb->dev, "Unknown ppid 0x%x\n", ppid);
+ return PMIC_ARB_MAX_PERIPHS;
+}
+
+/* Enable interrupt at the PMIC Arbiter PIC */
+static int pmic_arb_pic_enable(struct spmi_controller *ctrl,
+ struct qpnp_irq_spec *spec, uint32_t data)
+{
+ struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+ u8 apid = data & PMIC_ARB_APID_MASK;
+ unsigned long flags;
+ u32 status;
+
+ dev_dbg(pmic_arb->dev, "PIC enable, apid:0x%x, sid:0x%x, pid:0x%x\n",
+ apid, spec->slave, spec->per);
+
+ if (data < pmic_arb->min_apid || data > pmic_arb->max_apid) {
+ dev_err(pmic_arb->dev, "int enable: invalid APID %d\n", data);
+ return -EINVAL;
+ }
+
+ if (!is_apid_valid(pmic_arb, apid)) {
+ dev_err(pmic_arb->dev, "int enable: int not supported\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&pmic_arb->lock, flags);
+ status = readl_relaxed(pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+ if (!status) {
+ if (pmic_arb->pic_enable_cnt++ == 0)
+ enable_irq(pmic_arb->pic_irq);
+ writel_relaxed(0x1, pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+ /* Interrupt needs to be enabled before returning to caller */
+ wmb();
+ }
+ spin_unlock_irqrestore(&pmic_arb->lock, flags);
+ return 0;
+}
+
+/* Disable interrupt at the PMIC Arbiter PIC */
+static int pmic_arb_pic_disable(struct spmi_controller *ctrl,
+ struct qpnp_irq_spec *spec, uint32_t data)
+{
+ struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+ u8 apid = data & PMIC_ARB_APID_MASK;
+ unsigned long flags;
+ u32 status;
+
+ dev_dbg(pmic_arb->dev, "PIC disable, apid:0x%x, sid:0x%x, pid:0x%x\n",
+ apid, spec->slave, spec->per);
+
+ if (data < pmic_arb->min_apid || data > pmic_arb->max_apid) {
+ dev_err(pmic_arb->dev, "int disable: invalid APID %d\n", data);
+ return -EINVAL;
+ }
+
+ if (!is_apid_valid(pmic_arb, apid)) {
+ dev_err(pmic_arb->dev, "int disable: int not supported\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&pmic_arb->lock, flags);
+ status = readl_relaxed(pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+ if (status) {
+ if (pmic_arb->pic_enable_cnt-- == 1)
+ disable_irq(pmic_arb->pic_irq);
+ writel_relaxed(0x0, pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+ /* Interrupt needs to be disabled before returning to caller */
+ wmb();
+ }
+ spin_unlock_irqrestore(&pmic_arb->lock, flags);
+ return 0;
+}
+
+static irqreturn_t
+periph_interrupt(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+ u16 ppid = get_peripheral_id(pmic_arb, apid);
+ void __iomem *base = pmic_arb->intr;
+ u8 sid = (ppid >> 8) & 0x0F;
+ u8 pid = ppid & 0xFF;
+ u32 status;
+ int i;
+
+ if (!is_apid_valid(pmic_arb, apid)) {
+ dev_err(pmic_arb->dev, "unknown peripheral id 0x%x\n", ppid);
+ /* return IRQ_NONE; */
+ }
+
+ /* Read the peripheral specific interrupt bits */
+ status = readl_relaxed(base + SPMI_PIC_IRQ_STATUS(apid));
+
+ /* Clear the peripheral interrupts */
+ writel_relaxed(status, base + SPMI_PIC_IRQ_CLEAR(apid));
+ /* Interrupt needs to be cleared/acknowledged before exiting ISR */
+ mb();
+
+ dev_dbg(pmic_arb->dev,
+ "interrupt, apid:0x%x, sid:0x%x, pid:0x%x, intr:0x%x\n",
+ apid, sid, pid, status);
+
+ /* Send interrupt notification */
+ for (i = 0; status && i < 8; ++i, status >>= 1) {
+ if (status & 0x1) {
+ struct qpnp_irq_spec irq_spec = {
+ .slave = sid,
+ .per = pid,
+ .irq = i,
+ };
+ qpnpint_handle_irq(&pmic_arb->controller, &irq_spec);
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+/* Peripheral interrupt handler */
+static irqreturn_t pmic_arb_periph_irq(int irq, void *dev_id)
+{
+ struct spmi_pmic_arb_dev *pmic_arb = dev_id;
+ void __iomem *intr = pmic_arb->intr;
+ u8 ee = pmic_arb->owner;
+ u32 ret = IRQ_NONE;
+ u32 status;
+
+ int first = pmic_arb->min_apid >> 5;
+ int last = pmic_arb->max_apid >> 5;
+ int i, j;
+
+ dev_dbg(pmic_arb->dev, "Peripheral interrupt detected\n");
+
+ /* Check the accumulated interrupt status */
+ for (i = first; i <= last; ++i) {
+ status = readl_relaxed(intr + SPMI_PIC_OWNER_ACC_STATUS(ee, i));
+
+ for (j = 0; status && j < 32; ++j, status >>= 1) {
+ if (status & 0x1) {
+ u8 id = (i * 32) + j;
+ ret |= periph_interrupt(pmic_arb, id);
+ }
+ }
+ }
+
+ return ret;
+}
+
+/* Callback to register an APID for specific slave/peripheral */
+static int pmic_arb_intr_priv_data(struct spmi_controller *ctrl,
+ struct qpnp_irq_spec *spec, uint32_t *data)
+{
+ struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+ u16 ppid = ((spec->slave & 0x0F) << 8) | (spec->per & 0xFF);
+ *data = map_peripheral_id(pmic_arb, ppid);
+ return 0;
+}
+
+static int __devinit
+spmi_pmic_arb_get_property(struct platform_device *pdev, char *pname, u32 *prop)
+{
+ int ret = of_property_read_u32(pdev->dev.of_node, pname, prop);
+
+ if (ret)
+ dev_err(&pdev->dev, "missing property: %s\n", pname);
+ else
+ pr_debug("%s = 0x%x\n", pname, *prop);
+
+ return ret;
+}
+
+static int __devinit spmi_pmic_arb_get_map_data(struct platform_device *pdev,
+ struct spmi_pmic_arb_dev *pmic_arb)
+{
+ int i;
+ int ret;
+ int map_size;
+ u32 *map_data;
+ const int map_width = 2 * sizeof(*map_data);
+ const struct device_node *of_node = pdev->dev.of_node;
+
+ /* Get size of the mapping table (in bytes) */
+ if (!of_get_property(of_node, "qcom,pmic-arb-ppid-map", &map_size)) {
+ dev_err(&pdev->dev, "missing ppid mapping table\n");
+ return -ENODEV;
+ }
+
+ /* Map size can't exceed the maximum number of peripherals */
+ if (map_size == 0 || map_size % map_width ||
+ map_size > map_width * PMIC_ARB_MAX_PERIPHS) {
+ dev_err(&pdev->dev, "map size of %d is not valid\n", map_size);
+ return -ENODEV;
+ }
+
+ map_data = kzalloc(map_size, GFP_KERNEL);
+ if (!map_data) {
+ dev_err(&pdev->dev, "can not allocate map data\n");
+ return -ENOMEM;
+ }
+
+ ret = of_property_read_u32_array(of_node,
+ "qcom,pmic-arb-ppid-map", map_data, map_size/sizeof(u32));
+ if (ret) {
+ dev_err(&pdev->dev, "invalid or missing property: ppid-map\n");
+ goto err;
+ };
+
+ pmic_arb->max_apid = 0;
+ pmic_arb->min_apid = PMIC_ARB_MAX_PERIPHS - 1;
+
+ /* Build the mapping table from the data */
+ for (i = 0; i < map_size/sizeof(u32);) {
+ u32 ppid = map_data[i++];
+ u32 apid = map_data[i++];
+
+ if (apid > PMIC_ARB_APID_MASK) {
+ ret = -ENODEV;
+ dev_err(&pdev->dev, "invalid APID: 0x%x\n", apid);
+ goto err;
+ }
+
+ if (ppid > PMIC_ARB_PPID_MASK) {
+ ret = -ENODEV;
+ dev_err(&pdev->dev, "invalid PPID: 0x%x\n", ppid);
+ goto err;
+ }
+
+ if (pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID)
+ dev_warn(&pdev->dev, "duplicate APID 0x%x\n", apid);
+
+ pmic_arb->periph_id_map[apid] = ppid | PMIC_ARB_PERIPH_ID_VALID;
+
+ if (apid > pmic_arb->max_apid)
+ pmic_arb->max_apid = apid;
+
+ if (apid < pmic_arb->min_apid)
+ pmic_arb->min_apid = apid;
+ }
+
+ pr_debug("%d value(s) mapped, min:%d, max:%d\n",
+ map_size/map_width, pmic_arb->min_apid, pmic_arb->max_apid);
+
+err:
+ kfree(map_data);
+ return ret;
+}
+
+static struct qpnp_local_int spmi_pmic_arb_intr_cb = {
+ .mask = pmic_arb_pic_disable,
+ .unmask = pmic_arb_pic_enable,
+ .register_priv_data = pmic_arb_intr_priv_data,
+};
+
+static int __devinit spmi_pmic_arb_probe(struct platform_device *pdev)
+{
+ struct spmi_pmic_arb_dev *pmic_arb;
+ struct resource *mem_res;
+ u32 cell_index;
+ u32 prop;
+ int ret = 0;
+
+ pr_debug("SPMI PMIC Arbiter\n");
+
+ pmic_arb = devm_kzalloc(&pdev->dev,
+ sizeof(struct spmi_pmic_arb_dev), GFP_KERNEL);
+ if (!pmic_arb) {
+ dev_err(&pdev->dev, "can not allocate pmic_arb data\n");
+ return -ENOMEM;
+ }
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res) {
+ dev_err(&pdev->dev, "missing base memory resource\n");
+ return -ENODEV;
+ }
+
+ pmic_arb->base = devm_ioremap(&pdev->dev,
+ mem_res->start, resource_size(mem_res));
+ if (!pmic_arb->base) {
+ dev_err(&pdev->dev, "ioremap of 'base' failed\n");
+ return -ENOMEM;
+ }
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!mem_res) {
+ dev_err(&pdev->dev, "missing mem resource (interrupts)\n");
+ return -ENODEV;
+ }
+
+ pmic_arb->intr = devm_ioremap(&pdev->dev,
+ mem_res->start, resource_size(mem_res));
+ if (!pmic_arb->intr) {
+ dev_err(&pdev->dev, "ioremap of 'intr' failed\n");
+ return -ENOMEM;
+ }
+
+ pmic_arb->pic_irq = platform_get_irq(pdev, 0);
+ if (!pmic_arb->pic_irq) {
+ dev_err(&pdev->dev, "missing IRQ resource\n");
+ return -ENODEV;
+ }
+
+ ret = devm_request_irq(&pdev->dev, pmic_arb->pic_irq,
+ pmic_arb_periph_irq, IRQF_TRIGGER_HIGH, pdev->name, pmic_arb);
+ if (ret) {
+ dev_err(&pdev->dev, "request IRQ failed\n");
+ return ret;
+ }
+ disable_irq(pmic_arb->pic_irq);
+
+ /* Get properties from the device tree */
+ ret = spmi_pmic_arb_get_property(pdev, "cell-index", &cell_index);
+ if (ret)
+ return -ENODEV;
+
+ ret = spmi_pmic_arb_get_map_data(pdev, pmic_arb);
+ if (ret)
+ return ret;
+
+ ret = spmi_pmic_arb_get_property(pdev, "qcom,pmic-arb-ee", &prop);
+ if (ret)
+ return -ENODEV;
+ pmic_arb->owner = (u8)prop;
+
+ ret = spmi_pmic_arb_get_property(pdev, "qcom,pmic-arb-channel", &prop);
+ if (ret)
+ return -ENODEV;
+ pmic_arb->channel = (u8)prop;
+
+ pmic_arb->dev = &pdev->dev;
+ platform_set_drvdata(pdev, pmic_arb);
+ spmi_set_ctrldata(&pmic_arb->controller, pmic_arb);
+
+ spin_lock_init(&pmic_arb->lock);
+
+ pmic_arb->controller.nr = cell_index;
+ pmic_arb->controller.dev.parent = pdev->dev.parent;
+ pmic_arb->controller.dev.of_node = of_node_get(pdev->dev.of_node);
+
+ /* Callbacks */
+ pmic_arb->controller.cmd = pmic_arb_cmd;
+ pmic_arb->controller.read_cmd = pmic_arb_read_cmd;
+ pmic_arb->controller.write_cmd = pmic_arb_write_cmd;
+
+ ret = spmi_add_controller(&pmic_arb->controller);
+ if (ret)
+ goto err_add_controller;
+
+ /* Register the interrupt enable/disable functions */
+ qpnpint_register_controller(cell_index, &spmi_pmic_arb_intr_cb);
+
+ /* Register device(s) from the device tree */
+ of_spmi_register_devices(&pmic_arb->controller);
+
+ pr_debug("PMIC Arb Version 0x%x\n",
+ pmic_arb_read(pmic_arb, PMIC_ARB_VERSION));
+
+ return 0;
+
+err_add_controller:
+ platform_set_drvdata(pdev, NULL);
+ return ret;
+}
+
+static int __devexit spmi_pmic_arb_remove(struct platform_device *pdev)
+{
+ struct spmi_pmic_arb_dev *pmic_arb = platform_get_drvdata(pdev);
+
+ free_irq(pmic_arb->pic_irq, pmic_arb);
+ platform_set_drvdata(pdev, NULL);
+ spmi_del_controller(&pmic_arb->controller);
+ return 0;
+}
+
+static struct of_device_id spmi_pmic_arb_match_table[] = {
+ { .compatible = "qcom,spmi-pmic-arb",
+ },
+ {}
+};
+
+static struct platform_driver spmi_pmic_arb_driver = {
+ .probe = spmi_pmic_arb_probe,
+ .remove = __exit_p(spmi_pmic_arb_remove),
+ .driver = {
+ .name = SPMI_PMIC_ARB_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = spmi_pmic_arb_match_table,
+ },
+};
+
+static int __init spmi_pmic_arb_init(void)
+{
+ return platform_driver_register(&spmi_pmic_arb_driver);
+}
+postcore_initcall(spmi_pmic_arb_init);
+
+static void __exit spmi_pmic_arb_exit(void)
+{
+ platform_driver_unregister(&spmi_pmic_arb_driver);
+}
+module_exit(spmi_pmic_arb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:spmi_pmic_arb");
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
new file mode 100644
index 0000000..2842cd8
--- /dev/null
+++ b/drivers/spmi/spmi.c
@@ -0,0 +1,789 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spmi.h>
+
+struct spmii_boardinfo {
+ struct list_head list;
+ struct spmi_boardinfo board_info;
+};
+
+static DEFINE_MUTEX(board_lock);
+static LIST_HEAD(board_list);
+static LIST_HEAD(spmi_ctrl_list);
+static DEFINE_IDR(ctrl_idr);
+static struct device_type spmi_ctrl_type = { 0 };
+
+#define to_spmi(dev) platform_get_drvdata(to_platform_device(dev))
+
+/* Forward declarations */
+struct bus_type spmi_bus_type;
+static int spmi_register_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_busnum_to_ctrl: Map bus number to controller
+ * @busnum: bus number
+ * Returns controller representing this bus number
+ */
+struct spmi_controller *spmi_busnum_to_ctrl(u32 bus_num)
+{
+ struct spmi_controller *ctrl;
+
+ mutex_lock(&board_lock);
+ list_for_each_entry(ctrl, &spmi_ctrl_list, list) {
+ if (bus_num == ctrl->nr) {
+ mutex_unlock(&board_lock);
+ return ctrl;
+ }
+ }
+ mutex_unlock(&board_lock);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(spmi_busnum_to_ctrl);
+
+/**
+ * spmi_add_controller: Controller bring-up.
+ * @ctrl: controller to be registered.
+ * A controller is registered with the framework using this API. ctrl->nr is the
+ * desired number with which SPMI framework registers the controller.
+ * Function will return -EBUSY if the number is in use.
+ */
+int spmi_add_controller(struct spmi_controller *ctrl)
+{
+ int id;
+ int status;
+
+ pr_debug("adding controller for bus %d (0x%p)\n", ctrl->nr, ctrl);
+
+ if (ctrl->nr & ~MAX_ID_MASK) {
+ pr_err("invalid bus identifier %d\n", ctrl->nr);
+ return -EINVAL;
+ }
+
+retry:
+ if (idr_pre_get(&ctrl_idr, GFP_KERNEL) == 0) {
+ pr_err("no free memory for idr\n");
+ return -ENOMEM;
+ }
+
+ mutex_lock(&board_lock);
+ status = idr_get_new_above(&ctrl_idr, ctrl, ctrl->nr, &id);
+ if (status == 0 && id != ctrl->nr) {
+ status = -EAGAIN;
+ idr_remove(&ctrl_idr, id);
+ }
+ mutex_unlock(&board_lock);
+ if (status == -EAGAIN)
+ goto retry;
+
+ if (status == 0)
+ status = spmi_register_controller(ctrl);
+ return status;
+}
+EXPORT_SYMBOL_GPL(spmi_add_controller);
+
+/**
+ * spmi_del_controller: Controller tear-down.
+ * @ctrl: controller to which this device is to be added to.
+ *
+ * Controller added with the above API is torn down using this API.
+ */
+int spmi_del_controller(struct spmi_controller *ctrl)
+{
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(spmi_del_controller);
+
+#define spmi_device_attr_gr NULL
+#define spmi_device_uevent NULL
+static void spmi_dev_release(struct device *dev)
+{
+ struct spmi_device *spmidev = to_spmi_device(dev);
+ kfree(spmidev);
+}
+
+static struct device_type spmi_dev_type = {
+ .groups = spmi_device_attr_gr,
+ .uevent = spmi_device_uevent,
+ .release = spmi_dev_release,
+};
+
+/**
+ * spmi_alloc_device: Allocate a new SPMI devices.
+ * @ctrl: controller to which this device is to be added to.
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize a SPMI device without
+ * registering it immediately. This allows a driver to directly fill
+ * the spmi_device structure before calling spmi_add_device().
+ *
+ * Caller is responsible to call spmi_add_device() on the returned
+ * spmi_device. If the caller needs to discard the spmi_device without
+ * adding it, then spmi_dev_put() should be called.
+ */
+struct spmi_device *spmi_alloc_device(struct spmi_controller *ctrl)
+{
+ struct spmi_device *spmidev;
+
+ if (!ctrl) {
+ pr_err("Missing SPMI controller\n");
+ return NULL;
+ }
+
+ spmidev = kzalloc(sizeof(*spmidev), GFP_KERNEL);
+ if (!spmidev) {
+ dev_err(&ctrl->dev, "unable to allocate spmi_device\n");
+ return NULL;
+ }
+
+ spmidev->ctrl = ctrl;
+ spmidev->dev.parent = ctrl->dev.parent;
+ spmidev->dev.bus = &spmi_bus_type;
+ spmidev->dev.type = &spmi_dev_type;
+ device_initialize(&spmidev->dev);
+
+ return spmidev;
+}
+EXPORT_SYMBOL_GPL(spmi_alloc_device);
+
+/* Validate the SPMI device structure */
+static struct device *get_valid_device(struct spmi_device *spmidev)
+{
+ struct device *dev;
+
+ if (!spmidev)
+ return NULL;
+
+ dev = &spmidev->dev;
+ if (dev->bus != &spmi_bus_type || dev->type != &spmi_dev_type)
+ return NULL;
+
+ return dev;
+}
+
+/**
+ * spmi_add_device: Add a new device without register board info.
+ * @ctrl: controller to which this device is to be added to.
+ *
+ * Called when device doesn't have an explicit client-driver to be probed, or
+ * the client-driver is a module installed dynamically.
+ */
+int spmi_add_device(struct spmi_device *spmidev)
+{
+ int rc;
+ struct device *dev = get_valid_device(spmidev);
+
+ if (!dev) {
+ pr_err("%s: invalid SPMI device\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Set the device name */
+ dev_set_name(dev, "%s-%p", spmidev->name, spmidev);
+
+ /* Device may be bound to an active driver when this returns */
+ rc = device_add(dev);
+
+ if (rc < 0)
+ dev_err(dev, "Can't add %s, status %d\n", dev_name(dev), rc);
+ else
+ dev_dbg(dev, "device %s registered\n", dev_name(dev));
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(spmi_add_device);
+
+/**
+ * spmi_new_device: Instantiates a new SPMI device
+ * @ctrl: controller to which this device is to be added to.
+ * @info: board information for this device.
+ *
+ * Returns the new device or NULL.
+ */
+struct spmi_device *spmi_new_device(struct spmi_controller *ctrl,
+ struct spmi_boardinfo const *info)
+{
+ struct spmi_device *spmidev;
+ int rc;
+
+ if (!ctrl || !info)
+ return NULL;
+
+ spmidev = spmi_alloc_device(ctrl);
+ if (!spmidev)
+ return NULL;
+
+ spmidev->name = info->name;
+ spmidev->sid = info->slave_id;
+ spmidev->dev.of_node = info->of_node;
+ spmidev->resource = info->resource;
+ spmidev->num_resources = info->num_resources;
+ spmidev->dev.platform_data = (void *)info->platform_data;
+
+ rc = spmi_add_device(spmidev);
+ if (rc < 0) {
+ spmi_dev_put(spmidev);
+ return NULL;
+ }
+
+ return spmidev;
+}
+EXPORT_SYMBOL_GPL(spmi_new_device);
+
+/* spmi_remove_device: Remove the effect of spmi_add_device() */
+void spmi_remove_device(struct spmi_device *spmi_dev)
+{
+ device_unregister(&spmi_dev->dev);
+}
+EXPORT_SYMBOL_GPL(spmi_remove_device);
+
+/* If controller is not present, only add to boards list */
+static void spmi_match_ctrl_to_boardinfo(struct spmi_controller *ctrl,
+ struct spmi_boardinfo *bi)
+{
+ struct spmi_device *spmidev;
+
+ spmidev = spmi_new_device(ctrl, bi);
+ if (!spmidev)
+ dev_err(ctrl->dev.parent, "can't create new device for %s\n",
+ bi->name);
+}
+
+/**
+ * spmi_register_board_info: Board-initialization routine.
+ * @bus_num: controller number (bus) on which this device will sit.
+ * @info: list of all devices on all controllers present on the board.
+ * @n: number of entries.
+ * API enumerates respective devices on corresponding controller.
+ * Called from board-init function.
+ */
+int spmi_register_board_info(int busnum,
+ struct spmi_boardinfo const *info, unsigned n)
+{
+ int i;
+ struct spmii_boardinfo *bi;
+
+ bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
+ if (!bi)
+ return -ENOMEM;
+
+ for (i = 0; i < n; i++, bi++, info++) {
+ struct spmi_controller *ctrl;
+
+ memcpy(&bi->board_info, info, sizeof(*info));
+ mutex_lock(&board_lock);
+ list_add_tail(&bi->list, &board_list);
+ list_for_each_entry(ctrl, &spmi_ctrl_list, list)
+ if (ctrl->nr == busnum)
+ spmi_match_ctrl_to_boardinfo(ctrl,
+ &bi->board_info);
+ mutex_unlock(&board_lock);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spmi_register_board_info);
+
+/* ------------------------------------------------------------------------- */
+
+static inline int
+spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid)
+{
+ BUG_ON(!ctrl || !ctrl->cmd);
+ return ctrl->cmd(ctrl, opcode, sid);
+}
+
+static inline int spmi_read_cmd(struct spmi_controller *ctrl,
+ u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+ BUG_ON(!ctrl || !ctrl->read_cmd);
+ return ctrl->read_cmd(ctrl, opcode, sid, addr, bc, buf);
+}
+
+static inline int spmi_write_cmd(struct spmi_controller *ctrl,
+ u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+ BUG_ON(!ctrl || !ctrl->write_cmd);
+ return ctrl->write_cmd(ctrl, opcode, sid, addr, bc, buf);
+}
+
+/*
+ * register read/write: 5-bit address, 1 byte of data
+ * extended register read/write: 8-bit address, up to 16 bytes of data
+ * extended register read/write long: 16-bit address, up to 8 bytes of data
+ */
+
+/**
+ * spmi_register_read() - register read
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads 1 byte of data from a Slave device register.
+ */
+int spmi_register_read(struct spmi_controller *ctrl, u8 sid, u8 addr, u8 *buf)
+{
+ /* 4-bit Slave Identifier, 5-bit register address */
+ if (sid > SPMI_MAX_SLAVE_ID || addr > 0x1F)
+ return -EINVAL;
+
+ return spmi_read_cmd(ctrl, SPMI_CMD_READ, sid, addr, 0, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_register_read);
+
+/**
+ * spmi_ext_register_read() - extended register read
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @len: the request number of bytes to read (up to 16 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 16 bytes of data from the extended register space on a
+ * Slave device.
+ */
+int spmi_ext_register_read(struct spmi_controller *ctrl,
+ u8 sid, u8 addr, u8 *buf, int len)
+{
+ /* 4-bit Slave Identifier, 8-bit register address, up to 16 bytes */
+ if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 16)
+ return -EINVAL;
+
+ return spmi_read_cmd(ctrl, SPMI_CMD_EXT_READ, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_read);
+
+/**
+ * spmi_ext_register_readl() - extended register read long
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @len: the request number of bytes to read (up to 8 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 8 bytes of data from the extended register space on a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_readl(struct spmi_controller *ctrl,
+ u8 sid, u16 addr, u8 *buf, int len)
+{
+ /* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */
+ if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 8)
+ return -EINVAL;
+
+ return spmi_read_cmd(ctrl, SPMI_CMD_EXT_READL, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_readl);
+
+/**
+ * spmi_register_write() - register write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ *
+ * Writes 1 byte of data to a Slave device register.
+ */
+int spmi_register_write(struct spmi_controller *ctrl, u8 sid, u8 addr, u8 *buf)
+{
+ u8 op = SPMI_CMD_WRITE;
+
+ /* 4-bit Slave Identifier, 5-bit register address */
+ if (sid > SPMI_MAX_SLAVE_ID || addr > 0x1F)
+ return -EINVAL;
+
+ return spmi_write_cmd(ctrl, op, sid, addr, 0, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_register_write);
+
+/**
+ * spmi_register_zero_write() - register zero write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @data: the data to be written to register 0 (7-bits).
+ *
+ * Writes data to register 0 of the Slave device.
+ */
+int spmi_register_zero_write(struct spmi_controller *ctrl, u8 sid, u8 data)
+{
+ u8 op = SPMI_CMD_ZERO_WRITE;
+
+ /* 4-bit Slave Identifier, 5-bit register address */
+ if (sid > SPMI_MAX_SLAVE_ID)
+ return -EINVAL;
+
+ return spmi_write_cmd(ctrl, op, sid, 0, 0, &data);
+}
+EXPORT_SYMBOL_GPL(spmi_register_zero_write);
+
+/**
+ * spmi_ext_register_write() - extended register write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 16 bytes).
+ *
+ * Writes up to 16 bytes of data to the extended register space of a
+ * Slave device.
+ */
+int spmi_ext_register_write(struct spmi_controller *ctrl,
+ u8 sid, u8 addr, u8 *buf, int len)
+{
+ u8 op = SPMI_CMD_EXT_WRITE;
+
+ /* 4-bit Slave Identifier, 8-bit register address, up to 16 bytes */
+ if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 16)
+ return -EINVAL;
+
+ return spmi_write_cmd(ctrl, op, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_write);
+
+/**
+ * spmi_ext_register_writel() - extended register write long
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 8 bytes).
+ *
+ * Writes up to 8 bytes of data to the extended register space of a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_writel(struct spmi_controller *ctrl,
+ u8 sid, u16 addr, u8 *buf, int len)
+{
+ u8 op = SPMI_CMD_EXT_WRITEL;
+
+ /* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */
+ if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 8)
+ return -EINVAL;
+
+ return spmi_write_cmd(ctrl, op, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_writel);
+
+/**
+ * spmi_command_reset() - sends RESET command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Reset command initializes the Slave and forces all registers to
+ * their reset values. The Slave shall enter the STARTUP state after
+ * receiving a Reset command.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_reset(struct spmi_controller *ctrl, u8 sid)
+{
+ if (sid > SPMI_MAX_SLAVE_ID)
+ return -EINVAL;
+ return spmi_cmd(ctrl, SPMI_CMD_RESET, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_reset);
+
+/**
+ * spmi_command_sleep() - sends SLEEP command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Sleep command causes the Slave to enter the user defined SLEEP state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_sleep(struct spmi_controller *ctrl, u8 sid)
+{
+ if (sid > SPMI_MAX_SLAVE_ID)
+ return -EINVAL;
+ return spmi_cmd(ctrl, SPMI_CMD_SLEEP, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_sleep);
+
+/**
+ * spmi_command_wakeup() - sends WAKEUP command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Wakeup command causes the Slave to move from the SLEEP state to
+ * the ACTIVE state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_wakeup(struct spmi_controller *ctrl, u8 sid)
+{
+ if (sid > SPMI_MAX_SLAVE_ID)
+ return -EINVAL;
+ return spmi_cmd(ctrl, SPMI_CMD_WAKEUP, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_wakeup);
+
+/**
+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Shutdown command causes the Slave to enter the SHUTDOWN state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_shutdown(struct spmi_controller *ctrl, u8 sid)
+{
+ if (sid > SPMI_MAX_SLAVE_ID)
+ return -EINVAL;
+ return spmi_cmd(ctrl, SPMI_CMD_SHUTDOWN, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_shutdown);
+
+/* ------------------------------------------------------------------------- */
+
+static const struct spmi_device_id *spmi_match(const struct spmi_device_id *id,
+ const struct spmi_device *spmi_dev)
+{
+ while (id->name[0]) {
+ if (strncmp(spmi_dev->name, id->name, SPMI_NAME_SIZE) == 0)
+ return id;
+ id++;
+ }
+ return NULL;
+}
+
+static int spmi_device_match(struct device *dev, struct device_driver *drv)
+{
+ struct spmi_device *spmi_dev;
+ struct spmi_driver *sdrv = to_spmi_driver(drv);
+
+ if (dev->type == &spmi_dev_type)
+ spmi_dev = to_spmi_device(dev);
+ else
+ return 0;
+
+ /* Attempt an OF style match */
+ if (of_driver_match_device(dev, drv))
+ return 1;
+
+ if (sdrv->id_table)
+ return spmi_match(sdrv->id_table, spmi_dev) != NULL;
+
+ if (drv->name)
+ return strncmp(spmi_dev->name, drv->name, SPMI_NAME_SIZE) == 0;
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int spmi_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+ struct spmi_device *spmi_dev = NULL;
+ struct spmi_driver *driver;
+ if (dev->type == &spmi_dev_type)
+ spmi_dev = to_spmi_device(dev);
+
+ if (!spmi_dev || !dev->driver)
+ return 0;
+
+ driver = to_spmi_driver(dev->driver);
+ if (!driver->suspend)
+ return 0;
+
+ return driver->suspend(spmi_dev, mesg);
+}
+
+static int spmi_legacy_resume(struct device *dev)
+{
+ struct spmi_device *spmi_dev = NULL;
+ struct spmi_driver *driver;
+ if (dev->type == &spmi_dev_type)
+ spmi_dev = to_spmi_device(dev);
+
+ if (!spmi_dev || !dev->driver)
+ return 0;
+
+ driver = to_spmi_driver(dev->driver);
+ if (!driver->resume)
+ return 0;
+
+ return driver->resume(spmi_dev);
+}
+
+static int spmi_pm_suspend(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm)
+ return pm_generic_suspend(dev);
+ else
+ return spmi_legacy_suspend(dev, PMSG_SUSPEND);
+}
+
+static int spmi_pm_resume(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm)
+ return pm_generic_resume(dev);
+ else
+ return spmi_legacy_resume(dev);
+}
+
+#else
+#define spmi_pm_suspend NULL
+#define spmi_pm_resume NULL
+#endif
+
+static const struct dev_pm_ops spmi_pm_ops = {
+ .suspend = spmi_pm_suspend,
+ .resume = spmi_pm_resume,
+ SET_RUNTIME_PM_OPS(
+ pm_generic_suspend,
+ pm_generic_resume,
+ pm_generic_runtime_idle
+ )
+};
+struct bus_type spmi_bus_type = {
+ .name = "spmi",
+ .match = spmi_device_match,
+ .pm = &spmi_pm_ops,
+};
+EXPORT_SYMBOL_GPL(spmi_bus_type);
+
+struct device spmi_dev = {
+ .init_name = "spmi",
+};
+
+static int spmi_drv_probe(struct device *dev)
+{
+ const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+ return sdrv->probe(to_spmi_device(dev));
+}
+
+static int spmi_drv_remove(struct device *dev)
+{
+ const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+ return sdrv->remove(to_spmi_device(dev));
+}
+
+static void spmi_drv_shutdown(struct device *dev)
+{
+ const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+ sdrv->shutdown(to_spmi_device(dev));
+}
+
+/**
+ * spmi_driver_register: Client driver registration with SPMI framework.
+ * @drv: client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the SPMI framework.
+ * It is called from the driver's module-init function.
+ */
+int spmi_driver_register(struct spmi_driver *drv)
+{
+ drv->driver.bus = &spmi_bus_type;
+
+ if (drv->probe)
+ drv->driver.probe = spmi_drv_probe;
+
+ if (drv->remove)
+ drv->driver.remove = spmi_drv_remove;
+
+ if (drv->shutdown)
+ drv->driver.shutdown = spmi_drv_shutdown;
+
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(spmi_driver_register);
+
+static int spmi_register_controller(struct spmi_controller *ctrl)
+{
+ int ret = 0;
+
+ /* Can't register until after driver model init */
+ if (WARN_ON(!spmi_bus_type.p)) {
+ ret = -EAGAIN;
+ goto exit;
+ }
+
+ dev_set_name(&ctrl->dev, "spmi-%d", ctrl->nr);
+ ctrl->dev.bus = &spmi_bus_type;
+ ctrl->dev.type = &spmi_ctrl_type;
+ ret = device_register(&ctrl->dev);
+ if (ret)
+ goto exit;
+
+ dev_dbg(&ctrl->dev, "Bus spmi-%d registered: dev:%x\n",
+ ctrl->nr, (u32)&ctrl->dev);
+
+ mutex_lock(&board_lock);
+ list_add_tail(&ctrl->list, &spmi_ctrl_list);
+ mutex_unlock(&board_lock);
+
+ return 0;
+
+exit:
+ mutex_lock(&board_lock);
+ idr_remove(&ctrl_idr, ctrl->nr);
+ mutex_unlock(&board_lock);
+ return ret;
+}
+
+static void __exit spmi_exit(void)
+{
+ device_unregister(&spmi_dev);
+ bus_unregister(&spmi_bus_type);
+}
+
+static int __init spmi_init(void)
+{
+ int retval;
+
+ retval = bus_register(&spmi_bus_type);
+ if (!retval)
+ retval = device_register(&spmi_dev);
+
+ if (retval)
+ bus_unregister(&spmi_bus_type);
+
+ return retval;
+}
+postcore_initcall(spmi_init);
+module_exit(spmi_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("SPMI module");
+MODULE_ALIAS("platform:spmi");
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
index d12c8e8..c900647 100644
--- a/drivers/staging/qcache/fmem.c
+++ b/drivers/staging/qcache/fmem.c
@@ -51,9 +51,11 @@
{
struct fmem_platform_data *pdata = pdev->dev.platform_data;
- fmem_data.phys = pdata->phys + pdata->reserved_size;
- fmem_data.size = pdata->size - pdata->reserved_size;
- fmem_data.reserved_size = pdata->reserved_size;
+ fmem_data.phys = pdata->phys + pdata->reserved_size_low;
+ fmem_data.size = pdata->size - pdata->reserved_size_low -
+ pdata->reserved_size_high;
+ fmem_data.reserved_size_low = pdata->reserved_size_low;
+ fmem_data.reserved_size_high = pdata->reserved_size_high;
if (!fmem_data.size)
return -ENODEV;
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index 2a2166a..c38b279 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/msm_tsens.h>
#include <linux/io.h>
+#include <linux/err.h>
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
@@ -56,10 +57,12 @@
#define SENSOR4_EN BIT(7)
#define SENSORS_EN (SENSOR0_EN | SENSOR1_EN | \
SENSOR2_EN | SENSOR3_EN | SENSOR4_EN)
-#define TSENS_MIN_STATUS_MASK BIT(8)
-#define TSENS_LOWER_STATUS_CLR BIT(9)
-#define TSENS_UPPER_STATUS_CLR BIT(10)
-#define TSENS_MAX_STATUS_MASK BIT(11)
+#define TSENS_STATUS_CNTL_OFFSET 8
+#define TSENS_MIN_STATUS_MASK BIT((tsens_status_cntl_start))
+#define TSENS_LOWER_STATUS_CLR BIT((tsens_status_cntl_start + 1))
+#define TSENS_UPPER_STATUS_CLR BIT((tsens_status_cntl_start + 2))
+#define TSENS_MAX_STATUS_MASK BIT((tsens_status_cntl_start + 3))
+
#define TSENS_MEASURE_PERIOD 4 /* 1 sec. default */
#define TSENS_8960_SLP_CLK_ENA BIT(26)
@@ -86,6 +89,7 @@
#define TSENS_S0_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x00003628)
#define TSENS_STATUS_ADDR_OFFSET 2
+#define TSENS_SENSOR_STATUS_SIZE 4
#define TSENS_INT_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x0000363c)
#define TSENS_LOWER_INT_MASK BIT(1)
@@ -113,6 +117,26 @@
#define TSENS_8660_CONFIG_MASK (3 << TSENS_8660_CONFIG_SHIFT)
#define TSENS_8660_SLP_CLK_ENA BIT(24)
+#define TSENS_8064_SENSOR5_EN BIT(8)
+#define TSENS_8064_SENSOR6_EN BIT(9)
+#define TSENS_8064_SENSOR7_EN BIT(10)
+#define TSENS_8064_SENSOR8_EN BIT(11)
+#define TSENS_8064_SENSOR9_EN BIT(12)
+#define TSENS_8064_SENSOR10_EN BIT(13)
+#define TSENS_8064_SENSORS_EN (SENSORS_EN | \
+ TSENS_8064_SENSOR5_EN | \
+ TSENS_8064_SENSOR6_EN | \
+ TSENS_8064_SENSOR7_EN | \
+ TSENS_8064_SENSOR8_EN | \
+ TSENS_8064_SENSOR9_EN | \
+ TSENS_8064_SENSOR10_EN)
+#define TSENS_8064_STATUS_CNTL (MSM_CLK_CTL_BASE + 0x00003660)
+#define TSENS_8064_S5_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x00003664)
+#define TSENS_8064_SEQ_SENSORS 5
+#define TSENS_8064_S4_S5_OFFSET 40
+
+static int tsens_status_cntl_start;
+
struct tsens_tm_device_sensor {
struct thermal_zone_device *tz_dev;
enum thermal_device_mode mode;
@@ -121,11 +145,11 @@
int offset;
int calib_data;
int calib_data_backup;
+ uint32_t slope_mul_tsens_factor;
};
struct tsens_tm_device {
bool prev_reading_avail;
- int slope_mul_tsens_factor;
int tsens_factor;
uint32_t tsens_num_sensor;
enum platform_type hw_type;
@@ -137,26 +161,28 @@
/* Temperature on y axis and ADC-code on x-axis */
static int tsens_tz_code_to_degC(int adc_code, int sensor_num)
{
- int degC, degcbeforefactor;
- degcbeforefactor = adc_code * tmdev->slope_mul_tsens_factor
- + tmdev->sensor[sensor_num].offset;
+ int degcbeforefactor, degc;
+ degcbeforefactor = (adc_code *
+ tmdev->sensor[sensor_num].slope_mul_tsens_factor
+ + tmdev->sensor[sensor_num].offset);
+
if (degcbeforefactor == 0)
- degC = degcbeforefactor;
+ degc = degcbeforefactor;
else if (degcbeforefactor > 0)
- degC = (degcbeforefactor + tmdev->tsens_factor/2)
- / tmdev->tsens_factor;
- else /* rounding for negative degrees */
- degC = (degcbeforefactor - tmdev->tsens_factor/2)
- / tmdev->tsens_factor;
- return degC;
+ degc = (degcbeforefactor + tmdev->tsens_factor/2)
+ / tmdev->tsens_factor;
+ else
+ degc = (degcbeforefactor - tmdev->tsens_factor/2)
+ / tmdev->tsens_factor;
+ return degc;
}
static int tsens_tz_degC_to_code(int degC, int sensor_num)
{
int code = (degC * tmdev->tsens_factor -
- tmdev->sensor[sensor_num].offset
- + tmdev->slope_mul_tsens_factor/2)
- / tmdev->slope_mul_tsens_factor;
+ tmdev->sensor[sensor_num].offset
+ + tmdev->sensor[sensor_num].slope_mul_tsens_factor/2)
+ / tmdev->sensor[sensor_num].slope_mul_tsens_factor;
if (code > TSENS_THRESHOLD_MAX_CODE)
code = TSENS_THRESHOLD_MAX_CODE;
@@ -167,7 +193,7 @@
static void tsens8960_get_temp(int sensor_num, unsigned long *temp)
{
- unsigned int code;
+ unsigned int code, offset = 0, sensor_addr;
if (!tmdev->prev_reading_avail) {
while (!(readl_relaxed(TSENS_INT_STATUS_ADDR)
@@ -176,7 +202,12 @@
TSENS_TRDY_RDY_MAX_TIME);
tmdev->prev_reading_avail = true;
}
- code = readl_relaxed(TSENS_S0_STATUS_ADDR +
+
+ sensor_addr = (unsigned int)TSENS_S0_STATUS_ADDR;
+ if (tmdev->hw_type == APQ_8064 &&
+ sensor_num >= TSENS_8064_SEQ_SENSORS)
+ offset = TSENS_8064_S4_S5_OFFSET;
+ code = readl_relaxed(sensor_addr + offset +
(sensor_num << TSENS_STATUS_ADDR_OFFSET));
*temp = tsens_tz_code_to_degC(code, sensor_num);
}
@@ -247,7 +278,8 @@
}
writel_relaxed(reg | TSENS_SW_RST, TSENS_CNTL_ADDR);
if (tmdev->hw_type == MSM_8960 ||
- tmdev->hw_type == MSM_9615)
+ tmdev->hw_type == MSM_9615 ||
+ tmdev->hw_type == APQ_8064)
reg |= mask | TSENS_8960_SLP_CLK_ENA
| TSENS_EN;
else
@@ -257,7 +289,11 @@
} else {
reg &= ~mask;
if (!(reg & SENSOR0_EN)) {
- if (tmdev->hw_type == MSM_8960 ||
+ if (tmdev->hw_type == APQ_8064)
+ reg &= ~(TSENS_8064_SENSORS_EN |
+ TSENS_8960_SLP_CLK_ENA |
+ TSENS_EN);
+ else if (tmdev->hw_type == MSM_8960 ||
tmdev->hw_type == MSM_9615)
reg &= ~(SENSORS_EN |
TSENS_8960_SLP_CLK_ENA |
@@ -319,7 +355,11 @@
lo_code = TSENS_THRESHOLD_MIN_CODE;
hi_code = TSENS_THRESHOLD_MAX_CODE;
- reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+ if (tmdev->hw_type == APQ_8064)
+ reg_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+ else
+ reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+
reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR);
switch (trip) {
case TSENS_TRIP_STAGE3:
@@ -386,14 +426,21 @@
return -EINVAL;
}
- if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
- writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR);
- else {
+ if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) {
+ if (tmdev->hw_type == APQ_8064)
+ writel_relaxed(reg_cntl | mask, TSENS_8064_STATUS_CNTL);
+ else
+ writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR);
+ } else {
if (code < lo_code || code > hi_code) {
pr_info("%s with invalid code %x\n", __func__, code);
return -EINVAL;
}
- writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR);
+ if (tmdev->hw_type == APQ_8064)
+ writel_relaxed(reg_cntl & ~mask,
+ TSENS_8064_STATUS_CNTL);
+ else
+ writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR);
}
mb();
return 0;
@@ -465,7 +512,10 @@
lo_code = TSENS_THRESHOLD_MIN_CODE;
hi_code = TSENS_THRESHOLD_MAX_CODE;
- reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+ if (tmdev->hw_type == APQ_8064)
+ reg_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+ else
+ reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR);
switch (trip) {
case TSENS_TRIP_STAGE3:
@@ -561,25 +611,40 @@
{
struct tsens_tm_device *tm = data;
unsigned int threshold, threshold_low, i, code, reg, sensor, mask;
+ unsigned int sensor_addr;
bool upper_th_x, lower_th_x;
int adc_code;
- reg = readl_relaxed(TSENS_CNTL_ADDR);
- writel_relaxed(reg | TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR,
- TSENS_CNTL_ADDR);
+ if (tmdev->hw_type == APQ_8064) {
+ reg = readl_relaxed(TSENS_8064_STATUS_CNTL);
+ writel_relaxed(reg | TSENS_LOWER_STATUS_CLR |
+ TSENS_UPPER_STATUS_CLR, TSENS_8064_STATUS_CNTL);
+ } else {
+ reg = readl_relaxed(TSENS_CNTL_ADDR);
+ writel_relaxed(reg | TSENS_LOWER_STATUS_CLR |
+ TSENS_UPPER_STATUS_CLR, TSENS_CNTL_ADDR);
+ }
mask = ~(TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR);
threshold = readl_relaxed(TSENS_THRESHOLD_ADDR);
threshold_low = (threshold & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
>> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
threshold = (threshold & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
>> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
- reg = sensor = readl_relaxed(TSENS_CNTL_ADDR);
- sensor &= (uint32_t) SENSORS_EN;
+ sensor = readl_relaxed(TSENS_CNTL_ADDR);
+ if (tmdev->hw_type == APQ_8064) {
+ reg = readl_relaxed(TSENS_8064_STATUS_CNTL);
+ sensor &= (uint32_t) TSENS_8064_SENSORS_EN;
+ } else {
+ reg = sensor;
+ sensor &= (uint32_t) SENSORS_EN;
+ }
sensor >>= TSENS_SENSOR0_SHIFT;
+ sensor_addr = (unsigned int)TSENS_S0_STATUS_ADDR;
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ if (i == TSENS_8064_SEQ_SENSORS)
+ sensor_addr += TSENS_8064_S4_S5_OFFSET;
if (sensor & TSENS_MASK1) {
- code = readl_relaxed(TSENS_S0_STATUS_ADDR +
- (i << TSENS_STATUS_ADDR_OFFSET));
+ code = readl_relaxed(sensor_addr);
upper_th_x = code >= threshold;
lower_th_x = code <= threshold_low;
if (upper_th_x)
@@ -589,8 +654,7 @@
if (upper_th_x || lower_th_x) {
/* Notify user space */
schedule_work(&tm->sensor[i].work);
- adc_code = readl_relaxed(TSENS_S0_STATUS_ADDR
- + (i << TSENS_STATUS_ADDR_OFFSET));
+ adc_code = readl_relaxed(sensor_addr);
pr_info("\nTrip point triggered by "
"current temperature (%d degrees) "
"measured by Temperature-Sensor %d\n",
@@ -598,18 +662,37 @@
}
}
sensor >>= 1;
+ sensor_addr += TSENS_SENSOR_STATUS_SIZE;
}
+ if (tmdev->hw_type == APQ_8064)
+ writel_relaxed(reg & mask, TSENS_8064_STATUS_CNTL);
+ else
writel_relaxed(reg & mask, TSENS_CNTL_ADDR);
mb();
return IRQ_HANDLED;
}
+static void tsens8960_sensor_mode_init(void)
+{
+ unsigned int reg_cntl = 0;
+
+ reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+ if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+ tmdev->hw_type == APQ_8064) {
+ writel_relaxed(reg_cntl &
+ ~((((1 << tmdev->tsens_num_sensor) - 1) >> 1)
+ << (TSENS_SENSOR0_SHIFT + 1)), TSENS_CNTL_ADDR);
+ tmdev->sensor[TSENS_MAIN_SENSOR].mode = THERMAL_DEVICE_ENABLED;
+ }
+}
+
static void tsens_disable_mode(void)
{
unsigned int reg_cntl = 0;
reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
- if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615)
+ if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+ tmdev->hw_type == APQ_8064)
writel_relaxed(reg_cntl &
~((((1 << tmdev->tsens_num_sensor) - 1) <<
TSENS_SENSOR0_SHIFT) | TSENS_8960_SLP_CLK_ENA
@@ -624,6 +707,7 @@
static void tsens_hw_init(void)
{
unsigned int reg_cntl = 0, reg_cfg = 0, reg_thr = 0;
+ unsigned int reg_status_cntl = 0;
reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
writel_relaxed(reg_cntl | TSENS_SW_RST, TSENS_CNTL_ADDR);
@@ -657,6 +741,25 @@
(TSENS_8660_CONFIG << TSENS_8660_CONFIG_SHIFT);
writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+ } else if (tmdev->hw_type == APQ_8064) {
+ reg_cntl |= TSENS_8960_SLP_CLK_ENA |
+ (TSENS_MEASURE_PERIOD << 18) |
+ (((1 << tmdev->tsens_num_sensor) - 1) <<
+ TSENS_SENSOR0_SHIFT);
+ writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+ reg_status_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+ reg_status_cntl |= TSENS_LOWER_STATUS_CLR |
+ TSENS_UPPER_STATUS_CLR |
+ TSENS_MIN_STATUS_MASK |
+ TSENS_MAX_STATUS_MASK;
+ writel_relaxed(reg_status_cntl, TSENS_8064_STATUS_CNTL);
+ reg_cntl |= TSENS_EN;
+ writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+
+ reg_cfg = readl_relaxed(TSENS_8960_CONFIG_ADDR);
+ reg_cfg = (reg_cfg & ~TSENS_8960_CONFIG_MASK) |
+ (TSENS_8960_CONFIG << TSENS_8960_CONFIG_SHIFT);
+ writel_relaxed(reg_cfg, TSENS_8960_CONFIG_ADDR);
}
reg_thr |= (TSENS_LOWER_LIMIT_TH << TSENS_THRESHOLD_LOWER_LIMIT_SHIFT) |
@@ -692,8 +795,10 @@
}
tmdev->sensor[TSENS_MAIN_SENSOR].offset = tmdev->tsens_factor *
- TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor *
+ TSENS_CAL_DEGC -
+ tmdev->sensor[TSENS_MAIN_SENSOR].slope_mul_tsens_factor *
tmdev->sensor[TSENS_MAIN_SENSOR].calib_data;
+
tmdev->prev_reading_avail = false;
INIT_WORK(&tmdev->sensor[TSENS_MAIN_SENSOR].work,
notify_uspace_tsens_fn);
@@ -703,35 +808,27 @@
static int tsens_calib_sensors8960(void)
{
- uint32_t *main_sensor_addr, sensor_shift, *backup_sensor_addr;
- uint32_t sensor_mask, i;
+ uint32_t i;
+ uint8_t *main_sensor_addr, *backup_sensor_addr;
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
- main_sensor_addr = TSENS_8960_QFPROM_ADDR0 +
- (TSENS_8960_QFPROM_SHIFT *
- ((i & TSENS_8960_QFPROM_SHIFT) >> TSENS_SENSOR_QFPROM_SHIFT));
- sensor_shift = (i % TSENS_8960_QFPROM_SHIFT) * TSENS_RED_SHIFT;
- sensor_mask = TSENS_THRESHOLD_MAX_CODE << sensor_shift;
- backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 +
- (TSENS_8960_QFPROM_SHIFT *
- ((i & TSENS_8960_QFPROM_SHIFT) >> TSENS_SENSOR_QFPROM_SHIFT));
+ main_sensor_addr = TSENS_8960_QFPROM_ADDR0 + i;
+ backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 + i;
- tmdev->sensor[i].calib_data = (readl_relaxed(main_sensor_addr)
- & sensor_mask) >> sensor_shift;
+ tmdev->sensor[i].calib_data = readb_relaxed(main_sensor_addr);
tmdev->sensor[i].calib_data_backup =
- (readl_relaxed(backup_sensor_addr) &
- sensor_mask) >> sensor_shift;
+ readb_relaxed(backup_sensor_addr);
if (tmdev->sensor[i].calib_data_backup)
tmdev->sensor[i].calib_data =
tmdev->sensor[i].calib_data_backup;
-
if (!tmdev->sensor[i].calib_data) {
WARN(1, "%s: No temperature sensor:%d data for"
" calibration in QFPROM!\n", __func__, i);
return -ENODEV;
}
- tmdev->sensor[i].offset = tmdev->tsens_factor *
- TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor *
- tmdev->sensor[i].calib_data;
+ tmdev->sensor[i].offset = (TSENS_CAL_DEGC *
+ tmdev->tsens_factor)
+ - (tmdev->sensor[i].calib_data *
+ tmdev->sensor[i].slope_mul_tsens_factor);
tmdev->prev_reading_avail = false;
INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
}
@@ -756,7 +853,8 @@
if (tmdev->hw_type == MSM_8660)
rc = tsens_calib_sensors8660();
- else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615)
+ else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+ tmdev->hw_type == APQ_8064)
rc = tsens_calib_sensors8960();
return rc;
@@ -764,7 +862,7 @@
int msm_tsens_early_init(struct tsens_platform_data *pdata)
{
- int rc = 0;
+ int rc = 0, i;
if (!pdata) {
pr_err("No TSENS Platform data\n");
@@ -780,7 +878,8 @@
return -ENOMEM;
}
- tmdev->slope_mul_tsens_factor = pdata->slope;
+ for (i = 0; i < pdata->tsens_num_sensor; i++)
+ tmdev->sensor[i].slope_mul_tsens_factor = pdata->slope[i];
tmdev->tsens_factor = pdata->tsens_factor;
tmdev->tsens_num_sensor = pdata->tsens_num_sensor;
tmdev->hw_type = pdata->hw_type;
@@ -799,9 +898,14 @@
return rc;
}
+ if (tmdev->hw_type == APQ_8064)
+ tsens_status_cntl_start = 0;
+ else
+ tsens_status_cntl_start = TSENS_STATUS_CNTL_OFFSET;
+
tsens_hw_init();
- pr_info("msm_tsens_early_init: done\n");
+ pr_debug("msm_tsens_early_init: done\n");
return rc;
}
@@ -816,14 +920,14 @@
}
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
- char name[17];
+ char name[18];
snprintf(name, sizeof(name), "tsens_tz_sensor%d", i);
tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
tmdev->sensor[i].sensor_num = i;
tmdev->sensor[i].tz_dev = thermal_zone_device_register(name,
TSENS_TRIP_NUM, &tmdev->sensor[i],
&tsens_thermal_zone_ops, 0, 0, 0, 0);
- if (tmdev->sensor[i].tz_dev == NULL) {
+ if (IS_ERR(tmdev->sensor[i].tz_dev)) {
pr_err("%s: thermal_zone_device_register() failed.\n",
__func__);
rc = -ENODEV;
@@ -832,6 +936,8 @@
tmdev->sensor[i].mode = THERMAL_DEVICE_DISABLED;
}
+ tsens8960_sensor_mode_init();
+
rc = request_irq(TSENS_UPPER_LOWER_INT, tsens_isr,
IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
if (rc < 0) {
@@ -841,7 +947,7 @@
goto fail;
}
- pr_notice("%s: OK\n", __func__);
+ pr_debug("%s: OK\n", __func__);
mb();
return 0;
fail:
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index ed80b1b..ef28844 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -51,10 +51,7 @@
cpu_policy->user_policy.max = max_freq;
ret = cpufreq_update_policy(cpu);
- if (ret)
- pr_err("msm_thermal: cpufreq update to core%d %d err:%d\n",
- cpu, max_freq, ret);
- else
+ if (!ret)
pr_info("msm_thermal: Limiting core%d max frequency to %d\n",
cpu, max_freq);
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 9e85eb5..32e9dc0 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -2,7 +2,7 @@
* drivers/serial/msm_serial.c - driver for msm7k serial device and console
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
* Author: Robert Love <rlove@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -102,48 +102,32 @@
{
struct msm_port *msm_port = UART_TO_MSM(port);
- clk_enable(msm_port->clk);
-
msm_port->imr &= ~UART_IMR_TXLEV;
msm_write(port, msm_port->imr, UART_IMR);
-
- clk_disable(msm_port->clk);
}
static void msm_start_tx(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
- clk_enable(msm_port->clk);
-
msm_port->imr |= UART_IMR_TXLEV;
msm_write(port, msm_port->imr, UART_IMR);
-
- clk_disable(msm_port->clk);
}
static void msm_stop_rx(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
- clk_enable(msm_port->clk);
-
msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
msm_write(port, msm_port->imr, UART_IMR);
-
- clk_disable(msm_port->clk);
}
static void msm_enable_ms(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
- clk_enable(msm_port->clk);
-
msm_port->imr |= UART_IMR_DELTA_CTS;
msm_write(port, msm_port->imr, UART_IMR);
-
- clk_disable(msm_port->clk);
}
#ifdef CONFIG_SERIAL_MSM_CLOCK_CONTROL
@@ -365,7 +349,6 @@
unsigned int misr;
spin_lock_irqsave(&port->lock, flags);
- clk_enable(msm_port->clk);
misr = msm_read(port, UART_MISR);
msm_write(port, 0, UART_IMR); /* disable interrupt */
@@ -377,7 +360,6 @@
handle_delta_cts(port);
msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */
- clk_disable(msm_port->clk);
spin_unlock_irqrestore(&port->lock, flags);
return IRQ_HANDLED;
@@ -386,12 +368,8 @@
static unsigned int msm_tx_empty(struct uart_port *port)
{
unsigned int ret;
- struct msm_port *msm_port = UART_TO_MSM(port);
- clk_enable(msm_port->clk);
ret = (msm_read(port, UART_SR) & UART_SR_TX_EMPTY) ? TIOCSER_TEMT : 0;
- clk_disable(msm_port->clk);
-
return ret;
}
@@ -403,9 +381,6 @@
static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
unsigned int mr;
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- clk_enable(msm_port->clk);
mr = msm_read(port, UART_MR1);
@@ -417,22 +392,14 @@
mr |= UART_MR1_RX_RDY_CTL;
msm_write(port, mr, UART_MR1);
}
-
- clk_disable(msm_port->clk);
}
static void msm_break_ctl(struct uart_port *port, int break_ctl)
{
- struct msm_port *msm_port = UART_TO_MSM(port);
-
- clk_enable(msm_port->clk);
-
if (break_ctl)
msm_write(port, UART_CR_CMD_START_BREAK, UART_CR);
else
msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR);
-
- clk_disable(msm_port->clk);
}
static void msm_set_baud_rate(struct uart_port *port, unsigned int baud)
@@ -520,9 +487,14 @@
static void msm_init_clock(struct uart_port *port)
{
+ int ret;
struct msm_port *msm_port = UART_TO_MSM(port);
- clk_enable(msm_port->clk);
+ ret = clk_prepare_enable(msm_port->clk);
+ if (ret) {
+ pr_err("%s(): Can't enable uartclk. ret:%d\n", __func__, ret);
+ return;
+ }
#ifdef CONFIG_SERIAL_MSM_CLOCK_CONTROL
msm_port->clk_state = MSM_CLK_ON;
@@ -552,7 +524,7 @@
clk_disable(msm_port->clk);
msm_port->clk_state = MSM_CLK_PORT_OFF;
#else
- clk_disable(msm_port->clk);
+ clk_disable_unprepare(msm_port->clk);
#endif
}
@@ -631,13 +603,9 @@
{
struct msm_port *msm_port = UART_TO_MSM(port);
- clk_enable(msm_port->clk);
-
msm_port->imr = 0;
msm_write(port, 0, UART_IMR); /* disable interrupts */
- clk_disable(msm_port->clk);
-
free_irq(port->irq, port);
#ifdef CONFIG_SERIAL_MSM_RX_WAKEUP
@@ -657,10 +625,8 @@
{
unsigned long flags;
unsigned int baud, mr;
- struct msm_port *msm_port = UART_TO_MSM(port);
spin_lock_irqsave(&port->lock, flags);
- clk_enable(msm_port->clk);
/* calculate and set baud rate */
baud = uart_get_baud_rate(port, termios, old, 300, 115200);
@@ -723,8 +689,6 @@
port->read_status_mask |= UART_SR_RX_BREAK;
uart_update_timeout(port, termios->c_cflag, baud);
-
- clk_disable(msm_port->clk);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -792,20 +756,23 @@
static void msm_power(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
-#ifndef CONFIG_SERIAL_MSM_CLOCK_CONTROL
+ int ret;
struct msm_port *msm_port = UART_TO_MSM(port);
switch (state) {
case 0:
- clk_enable(msm_port->clk);
+ ret = clk_prepare_enable(msm_port->clk);
+ if (ret)
+ pr_err("msm_serial: %s(): Can't enable uartclk.\n",
+ __func__);
break;
case 3:
- clk_disable(msm_port->clk);
+ clk_disable_unprepare(msm_port->clk);
break;
default:
- printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state);
+ pr_err("msm_serial: %s(): Unknown PM state %d\n",
+ __func__, state);
}
-#endif
}
static struct uart_ops msm_uart_pops = {
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index c893889..8ea4632 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -47,7 +47,6 @@
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
- CI13XXX_DISABLE_STREAMING |
CI13XXX_ZERO_ITC,
.notify_event = ci13xxx_msm_notify_event,
diff --git a/drivers/usb/gadget/u_data_hsic.c b/drivers/usb/gadget/u_data_hsic.c
index 7b77a1d..818e2a6 100644
--- a/drivers/usb/gadget/u_data_hsic.c
+++ b/drivers/usb/gadget/u_data_hsic.c
@@ -85,8 +85,7 @@
unsigned port_num;
/* gadget */
- spinlock_t port_lock;
- void *port_usb;
+ atomic_t connected;
struct usb_ep *in;
struct usb_ep *out;
@@ -96,10 +95,12 @@
unsigned int tx_q_size;
struct list_head tx_idle;
struct sk_buff_head tx_skb_q;
+ spinlock_t tx_lock;
unsigned int rx_q_size;
struct list_head rx_idle;
struct sk_buff_head rx_skb_q;
+ spinlock_t rx_lock;
/* work */
struct workqueue_struct *wq;
@@ -175,17 +176,16 @@
struct gdata_port *port = ctx;
unsigned long flags;
- if (!port)
+ if (!port || !atomic_read(&port->connected))
return;
- spin_lock_irqsave(&port->port_lock, flags);
- if (port->port_usb) {
- port->tx_unthrottled_cnt++;
- queue_work(port->wq, &port->write_tomdm_w);
- pr_debug("%s: port num =%d unthrottled\n", __func__,
- port->port_num);
- }
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_lock_irqsave(&port->rx_lock, flags);
+ port->tx_unthrottled_cnt++;
+ spin_unlock_irqrestore(&port->rx_lock, flags);
+
+ queue_work(port->wq, &port->write_tomdm_w);
+ pr_debug("%s: port num =%d unthrottled\n", __func__,
+ port->port_num);
}
static void ghsic_data_write_tohost(struct work_struct *w)
@@ -200,14 +200,16 @@
port = container_of(w, struct gdata_port, write_tohost_w);
- spin_lock_irqsave(&port->port_lock, flags);
- if (!port->port_usb) {
- spin_unlock_irqrestore(&port->port_lock, flags);
+ if (!port)
+ return;
+
+ spin_lock_irqsave(&port->tx_lock, flags);
+ ep = port->in;
+ if (!ep) {
+ spin_unlock_irqrestore(&port->tx_lock, flags);
return;
}
- ep = port->in;
-
while (!list_empty(&port->tx_idle)) {
skb = __skb_dequeue(&port->tx_skb_q);
if (!skb)
@@ -231,9 +233,9 @@
info = (struct timestamp_info *)skb->cb;
info->tx_queued = get_timestamp();
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
ret = usb_ep_queue(ep, req, GFP_KERNEL);
- spin_lock_irqsave(&port->port_lock, flags);
+ spin_lock_irqsave(&port->tx_lock, flags);
if (ret) {
pr_err("%s: usb epIn failed\n", __func__);
list_add(&req->list, &port->tx_idle);
@@ -252,7 +254,7 @@
data_bridge_unthrottle_rx(port->brdg.ch_id);
}
}
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
}
static int ghsic_data_receive(void *p, void *data, size_t len)
@@ -261,21 +263,15 @@
unsigned long flags;
struct sk_buff *skb = data;
- if (!port) {
+ if (!port || !atomic_read(&port->connected)) {
dev_kfree_skb_any(skb);
- return -EINVAL;
+ return -ENOTCONN;
}
pr_debug("%s: p:%p#%d skb_len:%d\n", __func__,
port, port->port_num, skb->len);
- spin_lock_irqsave(&port->port_lock, flags);
- if (!port->port_usb) {
- spin_unlock_irqrestore(&port->port_lock, flags);
- dev_kfree_skb_any(skb);
- return -ENOTCONN;
- }
-
+ spin_lock_irqsave(&port->tx_lock, flags);
__skb_queue_tail(&port->tx_skb_q, skb);
if (ghsic_data_fctrl_support &&
@@ -284,12 +280,12 @@
port->rx_throttled_cnt++;
pr_debug_ratelimited("%s: flow ctrl enabled: tx skbq len: %u\n",
__func__, port->tx_skb_q.qlen);
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
queue_work(port->wq, &port->write_tohost_w);
return -EBUSY;
}
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
queue_work(port->wq, &port->write_tohost_w);
@@ -306,14 +302,12 @@
port = container_of(w, struct gdata_port, write_tomdm_w);
- spin_lock_irqsave(&port->port_lock, flags);
- if (!port->port_usb) {
- spin_unlock_irqrestore(&port->port_lock, flags);
+ if (!port || !atomic_read(&port->connected))
return;
- }
+ spin_lock_irqsave(&port->rx_lock, flags);
if (test_bit(TX_THROTTLED, &port->brdg.flags)) {
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
goto start_rx;
}
@@ -323,9 +317,9 @@
info = (struct timestamp_info *)skb->cb;
info->rx_done_sent = get_timestamp();
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
ret = data_bridge_write(port->brdg.ch_id, skb);
- spin_lock_irqsave(&port->port_lock, flags);
+ spin_lock_irqsave(&port->rx_lock, flags);
if (ret < 0) {
if (ret == -EBUSY) {
/*flow control*/
@@ -340,7 +334,7 @@
}
port->to_modem++;
}
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
start_rx:
ghsic_data_start_rx(port);
}
@@ -370,9 +364,9 @@
dev_kfree_skb_any(skb);
- spin_lock(&port->port_lock);
+ spin_lock(&port->tx_lock);
list_add_tail(&req->list, &port->tx_idle);
- spin_unlock(&port->port_lock);
+ spin_unlock(&port->tx_lock);
queue_work(port->wq, &port->write_tohost_w);
}
@@ -406,14 +400,14 @@
break;
}
- spin_lock(&port->port_lock);
+ spin_lock(&port->rx_lock);
if (queue) {
info->rx_done = get_timestamp();
__skb_queue_tail(&port->rx_skb_q, skb);
list_add_tail(&req->list, &port->rx_idle);
queue_work(port->wq, &port->write_tomdm_w);
}
- spin_unlock(&port->port_lock);
+ spin_unlock(&port->rx_lock);
}
static void ghsic_data_start_rx(struct gdata_port *port)
@@ -427,15 +421,17 @@
unsigned int created;
pr_debug("%s: port:%p\n", __func__, port);
- spin_lock_irqsave(&port->port_lock, flags);
- if (!port->port_usb) {
- spin_unlock_irqrestore(&port->port_lock, flags);
+ if (!port)
+ return;
+
+ spin_lock_irqsave(&port->rx_lock, flags);
+ ep = port->out;
+ if (!ep) {
+ spin_unlock_irqrestore(&port->rx_lock, flags);
return;
}
- ep = port->out;
-
- while (port->port_usb && !list_empty(&port->rx_idle)) {
+ while (atomic_read(&port->connected) && !list_empty(&port->rx_idle)) {
if (port->rx_skb_q.qlen > ghsic_data_pend_limit_with_bridge)
break;
@@ -454,22 +450,22 @@
req->context = skb;
info->rx_queued = get_timestamp();
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
ret = usb_ep_queue(ep, req, GFP_KERNEL);
- spin_lock_irqsave(&port->port_lock, flags);
+ spin_lock_irqsave(&port->rx_lock, flags);
if (ret) {
dev_kfree_skb_any(skb);
pr_err_ratelimited("%s: rx queue failed\n", __func__);
- if (port->port_usb)
+ if (atomic_read(&port->connected))
list_add(&req->list, &port->rx_idle);
else
usb_ep_free_request(ep, req);
break;
}
}
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
}
static void ghsic_data_start_io(struct gdata_port *port)
@@ -480,32 +476,41 @@
pr_debug("%s: port:%p\n", __func__, port);
- spin_lock_irqsave(&port->port_lock, flags);
- if (!port->port_usb) {
- spin_unlock_irqrestore(&port->port_lock, flags);
+ if (!port)
+ return;
+
+ spin_lock_irqsave(&port->rx_lock, flags);
+ ep = port->out;
+ if (!ep) {
+ spin_unlock_irqrestore(&port->rx_lock, flags);
return;
}
- ep = port->out;
ret = ghsic_data_alloc_requests(ep, &port->rx_idle,
port->rx_q_size, ghsic_data_epout_complete, GFP_ATOMIC);
if (ret) {
pr_err("%s: rx req allocation failed\n", __func__);
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&port->rx_lock, flags);
+
+ spin_lock_irqsave(&port->tx_lock, flags);
+ ep = port->in;
+ if (!ep) {
+ spin_unlock_irqrestore(&port->tx_lock, flags);
return;
}
- ep = port->in;
ret = ghsic_data_alloc_requests(ep, &port->tx_idle,
port->tx_q_size, ghsic_data_epin_complete, GFP_ATOMIC);
if (ret) {
pr_err("%s: tx req allocation failed\n", __func__);
ghsic_data_free_requests(ep, &port->rx_idle);
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
return;
}
-
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
/* queue out requests */
ghsic_data_start_rx(port);
@@ -517,7 +522,8 @@
container_of(w, struct gdata_port, connect_w);
int ret;
- if (!port || !test_bit(CH_READY, &port->bridge_sts))
+ if (!port || !atomic_read(&port->connected) ||
+ !test_bit(CH_READY, &port->bridge_sts))
return;
pr_debug("%s: port:%p\n", __func__, port);
@@ -551,28 +557,37 @@
struct sk_buff *skb;
unsigned long flags;
- spin_lock_irqsave(&port->port_lock, flags);
+ if (!port)
+ return;
- if (!port || !port->port_usb)
- goto free_buf_out;
+ spin_lock_irqsave(&port->tx_lock, flags);
+ if (!port->in) {
+ spin_unlock_irqrestore(&port->tx_lock, flags);
+ return;
+ }
ghsic_data_free_requests(port->in, &port->tx_idle);
- ghsic_data_free_requests(port->out, &port->rx_idle);
while ((skb = __skb_dequeue(&port->tx_skb_q)))
dev_kfree_skb_any(skb);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
+
+ spin_lock_irqsave(&port->rx_lock, flags);
+ if (!port->out) {
+ spin_unlock_irqrestore(&port->rx_lock, flags);
+ return;
+ }
+
+ ghsic_data_free_requests(port->out, &port->rx_idle);
while ((skb = __skb_dequeue(&port->rx_skb_q)))
dev_kfree_skb_any(skb);
-
-free_buf_out:
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
}
static int ghsic_data_probe(struct platform_device *pdev)
{
struct gdata_port *port;
- unsigned long flags;
pr_debug("%s: name:%s no_data_ports= %d\n",
__func__, pdev->name, no_data_ports);
@@ -585,11 +600,9 @@
port = gdata_ports[pdev->id].port;
set_bit(CH_READY, &port->bridge_sts);
- spin_lock_irqsave(&port->port_lock, flags);
/* if usb is online, try opening bridge */
- if (port->port_usb)
+ if (atomic_read(&port->connected))
queue_work(port->wq, &port->connect_w);
- spin_unlock_irqrestore(&port->port_lock, flags);
return 0;
}
@@ -598,9 +611,8 @@
static int ghsic_data_remove(struct platform_device *pdev)
{
struct gdata_port *port;
- struct usb_ep *ep_in = NULL;
- struct usb_ep *ep_out = NULL;
- unsigned long flags;
+ struct usb_ep *ep_in;
+ struct usb_ep *ep_out;
pr_debug("%s: name:%s\n", __func__, pdev->name);
@@ -611,15 +623,11 @@
port = gdata_ports[pdev->id].port;
- spin_lock_irqsave(&port->port_lock, flags);
- if (port->port_usb) {
- ep_in = port->in;
- ep_out = port->out;
- }
- spin_unlock_irqrestore(&port->port_lock, flags);
-
+ ep_in = port->in;
if (ep_in)
usb_ep_fifo_flush(ep_in);
+
+ ep_out = port->out;
if (ep_out)
usb_ep_fifo_flush(ep_out);
@@ -663,7 +671,8 @@
port->port_num = port_num;
/* port initialization */
- spin_lock_init(&port->port_lock);
+ spin_lock_init(&port->rx_lock);
+ spin_lock_init(&port->tx_lock);
INIT_WORK(&port->connect_w, ghsic_data_connect_w);
INIT_WORK(&port->disconnect_w, ghsic_data_disconnect_w);
@@ -724,14 +733,18 @@
if (port->out)
usb_ep_disable(port->in);
- spin_lock_irqsave(&port->port_lock, flags);
- port->port_usb = 0;
+ atomic_set(&port->connected, 0);
+
+ spin_lock_irqsave(&port->tx_lock, flags);
port->in = NULL;
- port->out = NULL;
port->n_tx_req_queued = 0;
- clear_bit(TX_THROTTLED, &port->brdg.flags);
clear_bit(RX_THROTTLED, &port->brdg.flags);
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
+
+ spin_lock_irqsave(&port->rx_lock, flags);
+ port->out = NULL;
+ clear_bit(TX_THROTTLED, &port->brdg.flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
queue_work(port->wq, &port->disconnect_w);
}
@@ -762,8 +775,15 @@
if (port->gtype == USB_GADGET_SERIAL) {
gser = gptr;
+
+ spin_lock_irqsave(&port->tx_lock, flags);
port->in = gser->in;
+ spin_unlock_irqrestore(&port->tx_lock, flags);
+
+ spin_lock_irqsave(&port->rx_lock, flags);
port->out = gser->out;
+ spin_unlock_irqrestore(&port->rx_lock, flags);
+
port->tx_q_size = ghsic_data_serial_tx_q_size;
port->rx_q_size = ghsic_data_serial_rx_q_size;
gser->in->driver_data = port;
@@ -772,8 +792,15 @@
out_desc = gser->out_desc;
} else {
gr = gptr;
+
+ spin_lock_irqsave(&port->tx_lock, flags);
port->in = gr->in;
+ spin_unlock_irqrestore(&port->tx_lock, flags);
+
+ spin_lock_irqsave(&port->rx_lock, flags);
port->out = gr->out;
+ spin_unlock_irqrestore(&port->rx_lock, flags);
+
port->tx_q_size = ghsic_data_rmnet_tx_q_size;
port->rx_q_size = ghsic_data_rmnet_rx_q_size;
gr->in->driver_data = port;
@@ -796,17 +823,22 @@
usb_ep_disable(port->in);
goto fail;
}
- spin_lock_irqsave(&port->port_lock, flags);
- port->port_usb = gptr;
+
+ atomic_set(&port->connected, 1);
+
+ spin_lock_irqsave(&port->tx_lock, flags);
port->to_host = 0;
- port->to_modem = 0;
- port->tomodem_drp_cnt = 0;
port->rx_throttled_cnt = 0;
port->rx_unthrottled_cnt = 0;
+ port->unthrottled_pnd_skbs = 0;
+ spin_unlock_irqrestore(&port->tx_lock, flags);
+
+ spin_lock_irqsave(&port->rx_lock, flags);
+ port->to_modem = 0;
+ port->tomodem_drp_cnt = 0;
port->tx_throttled_cnt = 0;
port->tx_unthrottled_cnt = 0;
- port->unthrottled_pnd_skbs = 0;
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->rx_lock, flags);
queue_work(port->wq, &port->connect_w);
fail:
@@ -932,42 +964,49 @@
if (!port)
continue;
pdrv = &gdata_ports[i].pdrv;
- spin_lock_irqsave(&port->port_lock, flags);
+ spin_lock_irqsave(&port->rx_lock, flags);
temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
"\nName: %s\n"
"#PORT:%d port#: %p\n"
- "dpkts_to_usbhost: %lu\n"
+ "data_ch_open: %d\n"
+ "data_ch_ready: %d\n"
+ "\n******UL INFO*****\n\n"
"dpkts_to_modem: %lu\n"
"tomodem_drp_cnt: %u\n"
- "tx_buf_len: %u\n"
"rx_buf_len: %u\n"
- "rx thld cnt %u\n"
- "rx unthld cnt %u\n"
"tx thld cnt %u\n"
"tx unthld cnt %u\n"
- "uthld pnd skbs %u\n"
- "RX_THROTTLED %d\n"
- "TX_THROTTLED %d\n"
- "data_ch_open: %d\n"
- "data_ch_ready: %d\n",
+ "TX_THROTTLED %d\n",
pdrv->driver.name,
i, port,
- port->to_host, port->to_modem,
+ test_bit(CH_OPENED, &port->bridge_sts),
+ test_bit(CH_READY, &port->bridge_sts),
+ port->to_modem,
port->tomodem_drp_cnt,
- port->tx_skb_q.qlen,
port->rx_skb_q.qlen,
- port->rx_throttled_cnt,
- port->rx_unthrottled_cnt,
port->tx_throttled_cnt,
port->tx_unthrottled_cnt,
- port->unthrottled_pnd_skbs,
- test_bit(RX_THROTTLED, &port->brdg.flags),
- test_bit(TX_THROTTLED, &port->brdg.flags),
- test_bit(CH_OPENED, &port->bridge_sts),
- test_bit(CH_READY, &port->bridge_sts));
+ test_bit(TX_THROTTLED, &port->brdg.flags));
+ spin_unlock_irqrestore(&port->rx_lock, flags);
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_lock_irqsave(&port->tx_lock, flags);
+ temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+ "\n******DL INFO******\n\n"
+ "dpkts_to_usbhost: %lu\n"
+ "tx_buf_len: %u\n"
+ "rx thld cnt %u\n"
+ "rx unthld cnt %u\n"
+ "uthld pnd skbs %u\n"
+ "RX_THROTTLED %d\n",
+ port->to_host,
+ port->tx_skb_q.qlen,
+ port->rx_throttled_cnt,
+ port->rx_unthrottled_cnt,
+ port->unthrottled_pnd_skbs,
+ test_bit(RX_THROTTLED, &port->brdg.flags));
+ spin_unlock_irqrestore(&port->tx_lock, flags);
+
}
ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
@@ -989,16 +1028,19 @@
if (!port)
continue;
- spin_lock_irqsave(&port->port_lock, flags);
- port->to_host = 0;
+ spin_lock_irqsave(&port->rx_lock, flags);
port->to_modem = 0;
port->tomodem_drp_cnt = 0;
- port->rx_throttled_cnt = 0;
- port->rx_unthrottled_cnt = 0;
port->tx_throttled_cnt = 0;
port->tx_unthrottled_cnt = 0;
+ spin_unlock_irqrestore(&port->rx_lock, flags);
+
+ spin_lock_irqsave(&port->tx_lock, flags);
+ port->to_host = 0;
+ port->rx_throttled_cnt = 0;
+ port->rx_unthrottled_cnt = 0;
port->unthrottled_pnd_skbs = 0;
- spin_unlock_irqrestore(&port->port_lock, flags);
+ spin_unlock_irqrestore(&port->tx_lock, flags);
}
return count;
}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index dc11eaf..97b0a2e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1274,6 +1274,7 @@
#ifdef CONFIG_USB_EHCI_MSM
#include "ehci-msm.c"
+#include "ehci-msm2.c"
#define PLATFORM_DRIVER_PRESENT
#endif
@@ -1391,7 +1392,11 @@
#endif
#ifdef CONFIG_USB_EHCI_MSM_HSIC
- &ehci_msm_hsic_driver
+ &ehci_msm_hsic_driver,
+#endif
+
+#ifdef CONFIG_USB_EHCI_MSM
+ &ehci_msm2_driver,
#endif
};
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index af7f2cf..dd3ec34 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -72,6 +72,8 @@
#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
+#define HSIC_DBG1_REG 0x38
+
static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
{
int ret = 0;
@@ -160,7 +162,7 @@
static struct regulator *hsic_hub_reg;
pdata = mehci->dev->platform_data;
- if (!pdata->hub_reset)
+ if (!pdata || !pdata->hub_reset)
return ret;
if (!init)
@@ -233,7 +235,7 @@
pdata = mehci->dev->platform_data;
- if (!pdata->strobe || !pdata->data)
+ if (!pdata || !pdata->strobe || !pdata->data)
return rc;
if (gpio_status == gpio_en)
@@ -270,16 +272,16 @@
{
int ret;
- clk_enable(mehci->alt_core_clk);
+ clk_prepare_enable(mehci->alt_core_clk);
ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
if (ret) {
- clk_disable(mehci->alt_core_clk);
+ clk_disable_unprepare(mehci->alt_core_clk);
dev_err(mehci->dev, "usb phy clk assert failed\n");
return ret;
}
usleep_range(10000, 12000);
- clk_disable(mehci->alt_core_clk);
+ clk_disable_unprepare(mehci->alt_core_clk);
ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
if (ret)
@@ -320,6 +322,7 @@
struct usb_hcd *hcd = hsic_to_hcd(mehci);
int cnt = 0;
int ret;
+ struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
ret = msm_hsic_phy_reset(mehci);
if (ret) {
@@ -337,36 +340,59 @@
if (cnt >= LINK_RESET_TIMEOUT_USEC)
return -ETIMEDOUT;
- /* select ULPI phy */
+ /* Reset PORTSC and select ULPI phy */
writel_relaxed(0x80000000, USB_PORTSC);
/* TODO: Need to confirm if HSIC PHY also requires delay after RESET */
msleep(100);
/* HSIC PHY Initialization */
- /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
- writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
- /*set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
- ulpi_write(mehci, 0xFF, 0x33);
+ /* HSIC init sequence when HSIC signals (Strobe/Data) are
+ routed via GPIOs */
+ if (pdata && pdata->strobe && pdata->data) {
- /* Enable periodic IO calibration in HSIC_CFG register */
- ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
+ /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
+ writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
- /* Configure GPIO 150/151 pins for HSIC functionality mode */
- ret = msm_hsic_config_gpios(mehci, 1);
- if (ret) {
- dev_err(mehci->dev, " gpio configuarion failed\n");
- return ret;
+ /*set periodic calibration interval to ~2.048sec in
+ HSIC_IO_CAL_REG */
+ ulpi_write(mehci, 0xFF, 0x33);
+
+ /* Enable periodic IO calibration in HSIC_CFG register */
+ ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
+
+ /* Configure GPIO 150/151 pins for HSIC functionality mode */
+ ret = msm_hsic_config_gpios(mehci, 1);
+ if (ret) {
+ dev_err(mehci->dev, " gpio configuarion failed\n");
+ return ret;
+ }
+ /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL
+ register */
+ writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
+ writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
+ /* Enable HSIC mode in HSIC_CFG register */
+ ulpi_write(mehci, 0x01, 0x31);
+ } else {
+ /* HSIC init sequence when HSIC signals (Strobe/Data) are routed
+ via dedicated I/O */
+
+ /* programmable length of connect signaling (33.2ns) */
+ ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
+ if (ret) {
+ pr_err("%s: Unable to program length of connect "
+ "signaling\n", __func__);
+ }
+
+ /*set periodic calibration interval to ~2.048sec in
+ HSIC_IO_CAL_REG */
+ ulpi_write(mehci, 0xFF, 0x33);
+
+ /* Enable HSIC mode in HSIC_CFG register */
+ ulpi_write(mehci, 0xA9, 0x30);
}
- /* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL register */
- writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
- writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
-
- /* Enable HSIC mode in HSIC_CFG register */
- ulpi_write(mehci, 0x01, 0x31);
-
return 0;
}
@@ -423,12 +449,12 @@
*/
mb();
- clk_disable(mehci->core_clk);
- clk_disable(mehci->phy_clk);
- clk_disable(mehci->cal_clk);
- clk_disable(mehci->ahb_clk);
+ clk_disable_unprepare(mehci->core_clk);
+ clk_disable_unprepare(mehci->phy_clk);
+ clk_disable_unprepare(mehci->cal_clk);
+ clk_disable_unprepare(mehci->ahb_clk);
pdata = mehci->dev->platform_data;
- if (pdata->hub_reset) {
+ if (pdata && pdata->hub_reset) {
ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_OFF);
if (ret)
pr_err("%s failed to devote for"
@@ -471,16 +497,16 @@
dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
pdata = mehci->dev->platform_data;
- if (pdata->hub_reset) {
+ if (pdata && pdata->hub_reset) {
ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
if (ret)
pr_err("%s failed to vote for"
"TCXO D1 buffer%d\n", __func__, ret);
}
- clk_enable(mehci->core_clk);
- clk_enable(mehci->phy_clk);
- clk_enable(mehci->cal_clk);
- clk_enable(mehci->ahb_clk);
+ clk_prepare_enable(mehci->core_clk);
+ clk_prepare_enable(mehci->phy_clk);
+ clk_prepare_enable(mehci->cal_clk);
+ clk_prepare_enable(mehci->ahb_clk);
temp = readl_relaxed(USB_USBCMD);
temp &= ~ASYNC_INTR_CTRL;
@@ -634,32 +660,32 @@
if (!init)
goto put_clocks;
- /*core_clk is required for LINK protocol engine,it should be at 60MHz */
+ /*core_clk is required for LINK protocol engine
+ *clock rate appropriately set by target specific clock driver */
mehci->core_clk = clk_get(mehci->dev, "core_clk");
if (IS_ERR(mehci->core_clk)) {
dev_err(mehci->dev, "failed to get core_clk\n");
ret = PTR_ERR(mehci->core_clk);
return ret;
}
- clk_set_rate(mehci->core_clk, 60000000);
- /* 60MHz alt_core_clk is for LINK to be used during PHY RESET */
+ /* alt_core_clk is for LINK to be used during PHY RESET
+ * clock rate appropriately set by target specific clock driver */
mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
if (IS_ERR(mehci->alt_core_clk)) {
dev_err(mehci->dev, "failed to core_clk\n");
ret = PTR_ERR(mehci->alt_core_clk);
goto put_core_clk;
}
- clk_set_rate(mehci->alt_core_clk, 60000000);
- /* 480MHz phy_clk is required for HSIC PHY operation */
+ /* phy_clk is required for HSIC PHY operation
+ * clock rate appropriately set by target specific clock driver */
mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
if (IS_ERR(mehci->phy_clk)) {
dev_err(mehci->dev, "failed to get phy_clk\n");
ret = PTR_ERR(mehci->phy_clk);
goto put_alt_core_clk;
}
- clk_set_rate(mehci->phy_clk, 480000000);
/* 10MHz cal_clk is required for calibration of I/O pads */
mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
@@ -678,18 +704,20 @@
goto put_cal_clk;
}
- clk_enable(mehci->core_clk);
- clk_enable(mehci->phy_clk);
- clk_enable(mehci->cal_clk);
- clk_enable(mehci->ahb_clk);
+ clk_prepare_enable(mehci->core_clk);
+ clk_prepare_enable(mehci->phy_clk);
+ clk_prepare_enable(mehci->cal_clk);
+ clk_prepare_enable(mehci->ahb_clk);
return 0;
put_clocks:
- clk_disable(mehci->core_clk);
- clk_disable(mehci->phy_clk);
- clk_disable(mehci->cal_clk);
- clk_disable(mehci->ahb_clk);
+ if (!atomic_read(&mehci->in_lpm)) {
+ clk_disable_unprepare(mehci->core_clk);
+ clk_disable_unprepare(mehci->phy_clk);
+ clk_disable_unprepare(mehci->cal_clk);
+ clk_disable_unprepare(mehci->ahb_clk);
+ }
clk_put(mehci->ahb_clk);
put_cal_clk:
clk_put(mehci->cal_clk);
@@ -778,7 +806,7 @@
}
pdata = mehci->dev->platform_data;
- if (pdata->hub_reset) {
+ if (pdata && pdata->hub_reset) {
mehci->xo_handle = msm_xo_get(MSM_XO_TCXO_D1, "hsic");
if (IS_ERR(mehci->xo_handle)) {
pr_err(" %s not able to get the handle"
@@ -843,7 +871,7 @@
deinit_hub:
msm_hsic_config_hub(mehci, 0);
free_xo_handle:
- if (pdata->hub_reset)
+ if (pdata && pdata->hub_reset)
msm_xo_put(mehci->xo_handle);
deinit_vddcx:
msm_hsic_init_vddcx(mehci, 0);
@@ -867,14 +895,13 @@
free_irq(mehci->peripheral_status_irq, mehci);
device_init_wakeup(&pdev->dev, 0);
- pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
usb_remove_hcd(hcd);
msm_hsic_config_gpios(mehci, 0);
msm_hsic_config_hub(mehci, 0);
pdata = mehci->dev->platform_data;
- if (pdata->hub_reset)
+ if (pdata && pdata->hub_reset)
msm_xo_put(mehci->xo_handle);
msm_hsic_init_vddcx(mehci, 0);
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
new file mode 100644
index 0000000..4f6fe3e
--- /dev/null
+++ b/drivers/usb/host/ehci-msm2.c
@@ -0,0 +1,1003 @@
+/* ehci-msm2.c - HSUSB Host Controller Driver Implementation
+ *
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ *
+ * Partly derived from ehci-fsl.c and ehci-hcd.c
+ * Copyright (c) 2000-2004 by David Brownell
+ * Copyright (c) 2005 MontaVista Software
+ *
+ * All source code in this file is licensed under the following license except
+ * where indicated.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can find it at http://www.fsf.org
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/wakelock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/usb/ulpi.h>
+#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb/msm_hsusb.h>
+#include <mach/clk.h>
+#include <mach/msm_iomap.h>
+
+#define MSM_USB_BASE (hcd->regs)
+
+struct msm_hcd {
+ struct ehci_hcd ehci;
+ struct device *dev;
+ struct clk *iface_clk;
+ struct clk *core_clk;
+ struct clk *alt_core_clk;
+ struct regulator *hsusb_vddcx;
+ struct regulator *hsusb_3p3;
+ struct regulator *hsusb_1p8;
+ struct regulator *vbus;
+ bool async_int;
+ atomic_t in_lpm;
+ struct wake_lock wlock;
+};
+
+static inline struct msm_hcd *hcd_to_mhcd(struct usb_hcd *hcd)
+{
+ return (struct msm_hcd *) (hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *mhcd_to_hcd(struct msm_hcd *mhcd)
+{
+ return container_of((void *) mhcd, struct usb_hcd, hcd_priv);
+}
+
+#define HSUSB_PHY_3P3_VOL_MIN 3050000 /* uV */
+#define HSUSB_PHY_3P3_VOL_MAX 3300000 /* uV */
+#define HSUSB_PHY_3P3_HPM_LOAD 50000 /* uA */
+
+#define HSUSB_PHY_1P8_VOL_MIN 1800000 /* uV */
+#define HSUSB_PHY_1P8_VOL_MAX 1800000 /* uV */
+#define HSUSB_PHY_1P8_HPM_LOAD 50000 /* uA */
+
+#define HSUSB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
+#define HSUSB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+#define HSUSB_PHY_VDD_DIG_LOAD 49360 /* uA */
+
+static int msm_ehci_init_vddcx(struct msm_hcd *mhcd, int init)
+{
+ int ret = 0;
+
+ if (!init)
+ goto disable_reg;
+
+ mhcd->hsusb_vddcx = regulator_get(mhcd->dev, "HSUSB_VDDCX");
+ if (IS_ERR(mhcd->hsusb_vddcx)) {
+ dev_err(mhcd->dev, "unable to get ehci vddcx\n");
+ return PTR_ERR(mhcd->hsusb_vddcx);
+ }
+
+ ret = regulator_set_voltage(mhcd->hsusb_vddcx,
+ HSUSB_PHY_VDD_DIG_VOL_MIN,
+ HSUSB_PHY_VDD_DIG_VOL_MAX);
+ if (ret) {
+ dev_err(mhcd->dev, "unable to set the voltage"
+ "for ehci vddcx\n");
+ goto reg_set_voltage_err;
+ }
+
+ ret = regulator_set_optimum_mode(mhcd->hsusb_vddcx,
+ HSUSB_PHY_VDD_DIG_LOAD);
+ if (ret < 0) {
+ dev_err(mhcd->dev, "%s: Unable to set optimum mode of the"
+ " regulator: VDDCX\n", __func__);
+ goto reg_optimum_mode_err;
+ }
+
+ ret = regulator_enable(mhcd->hsusb_vddcx);
+ if (ret) {
+ dev_err(mhcd->dev, "unable to enable ehci vddcx\n");
+ goto reg_enable_err;
+ }
+
+ return 0;
+
+disable_reg:
+ regulator_disable(mhcd->hsusb_vddcx);
+reg_enable_err:
+ regulator_set_optimum_mode(mhcd->hsusb_vddcx, 0);
+reg_optimum_mode_err:
+ regulator_set_voltage(mhcd->hsusb_vddcx, 0,
+ HSUSB_PHY_VDD_DIG_VOL_MIN);
+reg_set_voltage_err:
+ regulator_put(mhcd->hsusb_vddcx);
+
+ return ret;
+
+}
+
+static int msm_ehci_ldo_init(struct msm_hcd *mhcd, int init)
+{
+ int rc = 0;
+
+ if (!init)
+ goto put_1p8;
+
+ mhcd->hsusb_3p3 = regulator_get(mhcd->dev, "HSUSB_3p3");
+ if (IS_ERR(mhcd->hsusb_3p3)) {
+ dev_err(mhcd->dev, "unable to get hsusb 3p3\n");
+ return PTR_ERR(mhcd->hsusb_3p3);
+ }
+
+ rc = regulator_set_voltage(mhcd->hsusb_3p3,
+ HSUSB_PHY_3P3_VOL_MIN, HSUSB_PHY_3P3_VOL_MAX);
+ if (rc) {
+ dev_err(mhcd->dev, "unable to set voltage level for"
+ "hsusb 3p3\n");
+ goto put_3p3;
+ }
+ mhcd->hsusb_1p8 = regulator_get(mhcd->dev, "HSUSB_1p8");
+ if (IS_ERR(mhcd->hsusb_1p8)) {
+ dev_err(mhcd->dev, "unable to get hsusb 1p8\n");
+ rc = PTR_ERR(mhcd->hsusb_1p8);
+ goto put_3p3_lpm;
+ }
+ rc = regulator_set_voltage(mhcd->hsusb_1p8,
+ HSUSB_PHY_1P8_VOL_MIN, HSUSB_PHY_1P8_VOL_MAX);
+ if (rc) {
+ dev_err(mhcd->dev, "unable to set voltage level for"
+ "hsusb 1p8\n");
+ goto put_1p8;
+ }
+
+ return 0;
+
+put_1p8:
+ regulator_set_voltage(mhcd->hsusb_1p8, 0, HSUSB_PHY_1P8_VOL_MAX);
+ regulator_put(mhcd->hsusb_1p8);
+put_3p3_lpm:
+ regulator_set_voltage(mhcd->hsusb_3p3, 0, HSUSB_PHY_3P3_VOL_MAX);
+put_3p3:
+ regulator_put(mhcd->hsusb_3p3);
+
+ return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+#define HSUSB_PHY_SUSP_DIG_VOL 500000
+static int msm_ehci_config_vddcx(struct msm_hcd *mhcd, int high)
+{
+ int max_vol = HSUSB_PHY_VDD_DIG_VOL_MAX;
+ int min_vol;
+ int ret;
+
+ if (high)
+ min_vol = HSUSB_PHY_VDD_DIG_VOL_MIN;
+ else
+ min_vol = HSUSB_PHY_SUSP_DIG_VOL;
+
+ ret = regulator_set_voltage(mhcd->hsusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ dev_err(mhcd->dev, "%s: unable to set the voltage of regulator"
+ " HSUSB_VDDCX\n", __func__);
+ return ret;
+ }
+
+ dev_dbg(mhcd->dev, "%s: min_vol:%d max_vol:%d\n", __func__, min_vol,
+ max_vol);
+
+ return ret;
+}
+#else
+static int msm_ehci_config_vddcx(struct msm_hcd *mhcd, int high)
+{
+ return 0;
+}
+#endif
+
+static int msm_ehci_init_vbus(struct msm_hcd *mhcd, int init)
+{
+ struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ struct msm_usb_host_platform_data *pdata;
+
+ if (!init) {
+ regulator_put(mhcd->vbus);
+ return 0;
+ }
+
+ mhcd->vbus = regulator_get(mhcd->dev, "vbus");
+ if (IS_ERR(mhcd->vbus)) {
+ pr_err("Unable to get vbus\n");
+ return -ENODEV;
+ }
+
+ pdata = mhcd->dev->platform_data;
+ if (pdata)
+ hcd->power_budget = pdata->power_budget;
+
+ return 0;
+}
+
+static void msm_ehci_vbus_power(struct msm_hcd *mhcd, bool on)
+{
+ int ret;
+
+ if (!mhcd->vbus) {
+ pr_err("vbus is NULL.");
+ return;
+ }
+ if (on) {
+ ret = regulator_enable(mhcd->vbus);
+ if (ret) {
+ pr_err("unable to enable vbus\n");
+ return;
+ }
+ } else {
+ ret = regulator_disable(mhcd->vbus);
+ if (ret) {
+ pr_err("unable to disable vbus\n");
+ return;
+ }
+ }
+}
+
+static int msm_ehci_ldo_enable(struct msm_hcd *mhcd, int on)
+{
+ int ret = 0;
+
+ if (IS_ERR(mhcd->hsusb_1p8)) {
+ dev_err(mhcd->dev, "%s: HSUSB_1p8 is not initialized\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ if (IS_ERR(mhcd->hsusb_3p3)) {
+ dev_err(mhcd->dev, "%s: HSUSB_3p3 is not initialized\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ if (on) {
+ ret = regulator_set_optimum_mode(mhcd->hsusb_1p8,
+ HSUSB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ dev_err(mhcd->dev, "%s: Unable to set HPM of the"
+ " regulator: HSUSB_1p8\n", __func__);
+ return ret;
+ }
+
+ ret = regulator_enable(mhcd->hsusb_1p8);
+ if (ret) {
+ dev_err(mhcd->dev, "%s: unable to enable the hsusb"
+ " 1p8\n", __func__);
+ regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(mhcd->hsusb_3p3,
+ HSUSB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ dev_err(mhcd->dev, "%s: Unable to set HPM of the "
+ "regulator: HSUSB_3p3\n", __func__);
+ regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
+ regulator_disable(mhcd->hsusb_1p8);
+ return ret;
+ }
+
+ ret = regulator_enable(mhcd->hsusb_3p3);
+ if (ret) {
+ dev_err(mhcd->dev, "%s: unable to enable the "
+ "hsusb 3p3\n", __func__);
+ regulator_set_optimum_mode(mhcd->hsusb_3p3, 0);
+ regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
+ regulator_disable(mhcd->hsusb_1p8);
+ return ret;
+ }
+
+ } else {
+ ret = regulator_disable(mhcd->hsusb_1p8);
+ if (ret) {
+ dev_err(mhcd->dev, "%s: unable to disable the "
+ "hsusb 1p8\n", __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
+ if (ret < 0)
+ dev_err(mhcd->dev, "%s: Unable to set LPM of the "
+ "regulator: HSUSB_1p8\n", __func__);
+
+ ret = regulator_disable(mhcd->hsusb_3p3);
+ if (ret) {
+ dev_err(mhcd->dev, "%s: unable to disable the "
+ "hsusb 3p3\n", __func__);
+ return ret;
+ }
+ ret = regulator_set_optimum_mode(mhcd->hsusb_3p3, 0);
+ if (ret < 0)
+ dev_err(mhcd->dev, "%s: Unable to set LPM of the "
+ "regulator: HSUSB_3p3\n", __func__);
+ }
+
+ dev_dbg(mhcd->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+
+ return ret < 0 ? ret : 0;
+}
+
+
+#define ULPI_IO_TIMEOUT_USECS (10 * 1000)
+static int msm_ulpi_read(struct msm_hcd *mhcd, u32 reg)
+{
+ struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ unsigned long timeout;
+
+ /* initiate read operation */
+ writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
+ USB_ULPI_VIEWPORT);
+
+ /* wait for completion */
+ timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USECS);
+ while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
+ if (time_after(jiffies, timeout)) {
+ dev_err(mhcd->dev, "msm_ulpi_read: timeout %08x\n",
+ readl_relaxed(USB_ULPI_VIEWPORT));
+ return -ETIMEDOUT;
+ }
+ udelay(1);
+ }
+
+ return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
+}
+
+
+static int msm_ulpi_write(struct msm_hcd *mhcd, u32 val, u32 reg)
+{
+ struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ unsigned long timeout;
+
+ /* initiate write operation */
+ writel_relaxed(ULPI_RUN | ULPI_WRITE |
+ ULPI_ADDR(reg) | ULPI_DATA(val),
+ USB_ULPI_VIEWPORT);
+
+ /* wait for completion */
+ timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USECS);
+ while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
+ if (time_after(jiffies, timeout)) {
+ dev_err(mhcd->dev, "msm_ulpi_write: timeout\n");
+ return -ETIMEDOUT;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int msm_ehci_link_clk_reset(struct msm_hcd *mhcd, bool assert)
+{
+ int ret;
+
+ if (assert) {
+ ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_ASSERT);
+ if (ret)
+ dev_err(mhcd->dev, "usb alt_core_clk assert failed\n");
+ } else {
+ ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ dev_err(mhcd->dev, "usb alt_core_clk deassert failed\n");
+ }
+
+ return ret;
+}
+
+static int msm_ehci_phy_reset(struct msm_hcd *mhcd)
+{
+ struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ u32 val;
+ int ret;
+ int retries;
+
+ ret = msm_ehci_link_clk_reset(mhcd, 1);
+ if (ret)
+ return ret;
+
+ udelay(1);
+
+ ret = msm_ehci_link_clk_reset(mhcd, 0);
+ if (ret)
+ return ret;
+
+ val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
+ writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
+
+ for (retries = 3; retries > 0; retries--) {
+ ret = msm_ulpi_write(mhcd, ULPI_FUNC_CTRL_SUSPENDM,
+ ULPI_CLR(ULPI_FUNC_CTRL));
+ if (!ret)
+ break;
+ }
+ if (!retries)
+ return -ETIMEDOUT;
+
+ /* Wakeup the PHY with a reg-access for calibration */
+ for (retries = 3; retries > 0; retries--) {
+ ret = msm_ulpi_read(mhcd, ULPI_DEBUG);
+ if (ret != -ETIMEDOUT)
+ break;
+ }
+ if (!retries)
+ return -ETIMEDOUT;
+
+ dev_info(mhcd->dev, "phy_reset: success\n");
+
+ return 0;
+}
+
+#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
+static int msm_hsusb_reset(struct msm_hcd *mhcd)
+{
+ struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ unsigned long timeout;
+ int ret;
+
+ clk_prepare_enable(mhcd->alt_core_clk);
+ ret = msm_ehci_phy_reset(mhcd);
+ if (ret) {
+ dev_err(mhcd->dev, "phy_reset failed\n");
+ return ret;
+ }
+
+ writel_relaxed(USBCMD_RESET, USB_USBCMD);
+
+ timeout = jiffies + usecs_to_jiffies(LINK_RESET_TIMEOUT_USEC);
+ while (readl_relaxed(USB_USBCMD) & USBCMD_RESET) {
+ if (time_after(jiffies, timeout))
+ return -ETIMEDOUT;
+ udelay(1);
+ }
+
+ /* select ULPI phy */
+ writel_relaxed(0x80000000, USB_PORTSC);
+
+ msleep(100);
+
+ writel_relaxed(0x0, USB_AHBBURST);
+ writel_relaxed(0x00, USB_AHBMODE);
+
+ /* Ensure that RESET operation is completed before turning off clock */
+ mb();
+ clk_disable_unprepare(mhcd->alt_core_clk);
+
+ /*rising edge interrupts with Dp rise and fall enabled*/
+ msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_RISE);
+ msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_FALL);
+
+ /*Clear the PHY interrupts by reading the PHY interrupt latch register*/
+ msm_ulpi_read(mhcd, ULPI_USB_INT_LATCH);
+
+ return 0;
+}
+
+#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
+#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
+
+#ifdef CONFIG_PM_SLEEP
+static int msm_ehci_suspend(struct msm_hcd *mhcd)
+{
+ struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ unsigned long timeout;
+ u32 portsc;
+
+ if (atomic_read(&mhcd->in_lpm)) {
+ dev_dbg(mhcd->dev, "%s called in lpm\n", __func__);
+ return 0;
+ }
+
+ disable_irq(hcd->irq);
+
+ /* Set the PHCD bit, only if it is not set by the controller.
+ * PHY may take some time or even fail to enter into low power
+ * mode (LPM). Hence poll for 500 msec and reset the PHY and link
+ * in failure case.
+ */
+ portsc = readl_relaxed(USB_PORTSC);
+ if (!(portsc & PORTSC_PHCD)) {
+ writel_relaxed(portsc | PORTSC_PHCD,
+ USB_PORTSC);
+
+ timeout = jiffies + usecs_to_jiffies(PHY_SUSPEND_TIMEOUT_USEC);
+ while (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD)) {
+ if (time_after(jiffies, timeout)) {
+ dev_err(mhcd->dev, "Unable to suspend PHY\n");
+ msm_hsusb_reset(mhcd);
+ break;
+ }
+ udelay(1);
+ }
+ }
+
+ /*
+ * PHY has capability to generate interrupt asynchronously in low
+ * power mode (LPM). This interrupt is level triggered. So USB IRQ
+ * line must be disabled till async interrupt enable bit is cleared
+ * in USBCMD register. Assert STP (ULPI interface STOP signal) to
+ * block data communication from PHY.
+ */
+ writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
+ ULPI_STP_CTRL, USB_USBCMD);
+
+ /*
+ * Ensure that hardware is put in low power mode before
+ * clocks are turned OFF and VDD is allowed to minimize.
+ */
+ mb();
+
+ clk_disable_unprepare(mhcd->iface_clk);
+ clk_disable_unprepare(mhcd->core_clk);
+
+ msm_ehci_config_vddcx(mhcd, 0);
+
+ atomic_set(&mhcd->in_lpm, 1);
+ enable_irq(hcd->irq);
+ wake_unlock(&mhcd->wlock);
+
+ dev_info(mhcd->dev, "EHCI USB in low power mode\n");
+
+ return 0;
+}
+
+static int msm_ehci_resume(struct msm_hcd *mhcd)
+{
+ struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ unsigned long timeout;
+ unsigned temp;
+
+ if (!atomic_read(&mhcd->in_lpm)) {
+ dev_dbg(mhcd->dev, "%s called in !in_lpm\n", __func__);
+ return 0;
+ }
+
+ wake_lock(&mhcd->wlock);
+
+ clk_prepare_enable(mhcd->core_clk);
+ clk_prepare_enable(mhcd->iface_clk);
+
+ msm_ehci_config_vddcx(mhcd, 1);
+
+ temp = readl_relaxed(USB_USBCMD);
+ temp &= ~ASYNC_INTR_CTRL;
+ temp &= ~ULPI_STP_CTRL;
+ writel_relaxed(temp, USB_USBCMD);
+
+ if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
+ goto skip_phy_resume;
+
+ temp = readl_relaxed(USB_PORTSC) & ~PORTSC_PHCD;
+ writel_relaxed(temp, USB_PORTSC);
+
+ timeout = jiffies + usecs_to_jiffies(PHY_RESUME_TIMEOUT_USEC);
+ while ((readl_relaxed(USB_PORTSC) & PORTSC_PHCD) ||
+ !(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE)) {
+ if (time_after(jiffies, timeout)) {
+ /*This is a fatal error. Reset the link and PHY*/
+ dev_err(mhcd->dev, "Unable to resume USB. Resetting the h/w\n");
+ msm_hsusb_reset(mhcd);
+ break;
+ }
+ udelay(1);
+ }
+
+skip_phy_resume:
+
+ atomic_set(&mhcd->in_lpm, 0);
+
+ if (mhcd->async_int) {
+ mhcd->async_int = false;
+ pm_runtime_put_noidle(mhcd->dev);
+ enable_irq(hcd->irq);
+ }
+
+ dev_info(mhcd->dev, "EHCI USB exited from low power mode\n");
+
+ return 0;
+}
+#endif
+
+static irqreturn_t msm_ehci_irq(struct usb_hcd *hcd)
+{
+ struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+ if (atomic_read(&mhcd->in_lpm)) {
+ disable_irq_nosync(hcd->irq);
+ mhcd->async_int = true;
+ pm_runtime_get(mhcd->dev);
+ return IRQ_HANDLED;
+ }
+
+ return ehci_irq(hcd);
+}
+
+static int msm_ehci_reset(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ int retval;
+
+ ehci->caps = USB_CAPLENGTH;
+ ehci->regs = USB_CAPLENGTH +
+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
+ dbg_hcs_params(ehci, "reset");
+ dbg_hcc_params(ehci, "reset");
+
+ /* cache the data to minimize the chip reads*/
+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+ hcd->has_tt = 1;
+ ehci->sbrn = HCD_USB2;
+
+ retval = ehci_halt(ehci);
+ if (retval)
+ return retval;
+
+ /* data structure init */
+ retval = ehci_init(hcd);
+ if (retval)
+ return retval;
+
+ retval = ehci_reset(ehci);
+ if (retval)
+ return retval;
+
+ /* bursts of unspecified length. */
+ writel_relaxed(0, USB_AHBBURST);
+ /* Use the AHB transactor */
+ writel_relaxed(0, USB_AHBMODE);
+ /* Disable streaming mode and select host mode */
+ writel_relaxed(0x13, USB_USBMODE);
+
+ ehci_port_power(ehci, 1);
+ return 0;
+}
+
+static struct hc_driver msm_hc2_driver = {
+ .description = hcd_name,
+ .product_desc = "Qualcomm EHCI Host Controller",
+ .hcd_priv_size = sizeof(struct msm_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = msm_ehci_irq,
+ .flags = HCD_USB2 | HCD_MEMORY,
+
+ .reset = msm_ehci_reset,
+ .start = ehci_run,
+
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+
+ /*
+ * PM support
+ */
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+};
+
+static int msm_ehci_init_clocks(struct msm_hcd *mhcd, u32 init)
+{
+ int ret = 0;
+
+ if (!init)
+ goto put_clocks;
+
+ /* 60MHz alt_core_clk is for LINK to be used during PHY RESET */
+ mhcd->alt_core_clk = clk_get(mhcd->dev, "alt_core_clk");
+ if (IS_ERR(mhcd->alt_core_clk)) {
+ dev_err(mhcd->dev, "failed to get alt_core_clk\n");
+ ret = PTR_ERR(mhcd->alt_core_clk);
+ return ret;
+ }
+ clk_set_rate(mhcd->alt_core_clk, 60000000);
+
+ /* iface_clk is required for data transfers */
+ mhcd->iface_clk = clk_get(mhcd->dev, "iface_clk");
+ if (IS_ERR(mhcd->iface_clk)) {
+ dev_err(mhcd->dev, "failed to get iface_clk\n");
+ ret = PTR_ERR(mhcd->iface_clk);
+ goto put_alt_core_clk;
+ }
+
+ /* Link's protocol engine is based on pclk which must
+ * be running >55Mhz and frequency should also not change.
+ * Hence, vote for maximum clk frequency on its source
+ */
+ mhcd->core_clk = clk_get(mhcd->dev, "core_clk");
+ if (IS_ERR(mhcd->core_clk)) {
+ dev_err(mhcd->dev, "failed to get core_clk\n");
+ ret = PTR_ERR(mhcd->core_clk);
+ goto put_iface_clk;
+ }
+ clk_set_rate(mhcd->core_clk, INT_MAX);
+
+ clk_prepare_enable(mhcd->core_clk);
+ clk_prepare_enable(mhcd->iface_clk);
+
+ return 0;
+
+put_clocks:
+ clk_disable_unprepare(mhcd->iface_clk);
+ clk_disable_unprepare(mhcd->core_clk);
+ clk_put(mhcd->core_clk);
+put_iface_clk:
+ clk_put(mhcd->iface_clk);
+put_alt_core_clk:
+ clk_put(mhcd->alt_core_clk);
+
+ return ret;
+}
+
+static int __devinit ehci_msm2_probe(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd;
+ struct resource *res;
+ struct msm_hcd *mhcd;
+ int ret;
+
+ dev_dbg(&pdev->dev, "ehci_msm2 probe\n");
+
+ hcd = usb_create_hcd(&msm_hc2_driver, &pdev->dev,
+ dev_name(&pdev->dev));
+ if (!hcd) {
+ dev_err(&pdev->dev, "Unable to create HCD\n");
+ return -ENOMEM;
+ }
+
+ hcd->irq = platform_get_irq(pdev, 0);
+ if (hcd->irq < 0) {
+ dev_err(&pdev->dev, "Unable to get IRQ resource\n");
+ ret = hcd->irq;
+ goto put_hcd;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get memory resource\n");
+ ret = -ENODEV;
+ goto put_hcd;
+ }
+
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = resource_size(res);
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto put_hcd;
+ }
+
+ mhcd = hcd_to_mhcd(hcd);
+ mhcd->dev = &pdev->dev;
+
+ ret = msm_ehci_init_clocks(mhcd, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to initialize clocks\n");
+ ret = -ENODEV;
+ goto unmap;
+ }
+
+ ret = msm_ehci_init_vddcx(mhcd, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to initialize VDDCX\n");
+ ret = -ENODEV;
+ goto deinit_clocks;
+ }
+
+ ret = msm_ehci_config_vddcx(mhcd, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+ goto deinit_vddcx;
+ }
+
+ ret = msm_ehci_ldo_init(mhcd, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+ goto deinit_vddcx;
+ }
+
+ ret = msm_ehci_ldo_enable(mhcd, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+ goto deinit_ldo;
+ }
+
+ ret = msm_ehci_init_vbus(mhcd, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to get vbus\n");
+ goto disable_ldo;
+ }
+
+ ret = msm_hsusb_reset(mhcd);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb PHY initialization failed\n");
+ goto vbus_deinit;
+ }
+
+ ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to register HCD\n");
+ goto vbus_deinit;
+ }
+
+ /*TBD:for now enable vbus here*/
+ msm_ehci_vbus_power(mhcd, 1);
+
+ device_init_wakeup(&pdev->dev, 1);
+ wake_lock_init(&mhcd->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
+ wake_lock(&mhcd->wlock);
+ /*
+ * This pdev->dev is assigned parent of root-hub by USB core,
+ * hence, runtime framework automatically calls this driver's
+ * runtime APIs based on root-hub's state.
+ */
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+
+vbus_deinit:
+ msm_ehci_init_vbus(mhcd, 0);
+disable_ldo:
+ msm_ehci_ldo_enable(mhcd, 0);
+deinit_ldo:
+ msm_ehci_ldo_init(mhcd, 0);
+deinit_vddcx:
+ msm_ehci_init_vddcx(mhcd, 0);
+deinit_clocks:
+ msm_ehci_init_clocks(mhcd, 0);
+unmap:
+ iounmap(hcd->regs);
+put_hcd:
+ usb_put_hcd(hcd);
+
+ return ret;
+}
+
+static int __devexit ehci_msm2_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+ device_init_wakeup(&pdev->dev, 0);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+
+ usb_remove_hcd(hcd);
+ msm_ehci_vbus_power(mhcd, 0);
+ msm_ehci_init_vbus(mhcd, 0);
+ msm_ehci_ldo_enable(mhcd, 0);
+ msm_ehci_ldo_init(mhcd, 0);
+ msm_ehci_init_vddcx(mhcd, 0);
+
+ msm_ehci_init_clocks(mhcd, 0);
+ wake_lock_destroy(&mhcd->wlock);
+ iounmap(hcd->regs);
+ usb_put_hcd(hcd);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ehci_msm2_pm_suspend(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+ dev_dbg(dev, "ehci-msm2 PM suspend\n");
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(hcd->irq);
+
+ return msm_ehci_suspend(mhcd);
+
+}
+
+static int ehci_msm2_pm_resume(struct device *dev)
+{
+ int ret;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+ dev_dbg(dev, "ehci-msm2 PM resume\n");
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(hcd->irq);
+
+ ret = msm_ehci_resume(mhcd);
+ if (ret)
+ return ret;
+
+ /* Bring the device to full powered state upon system resume */
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int ehci_msm2_runtime_idle(struct device *dev)
+{
+ dev_dbg(dev, "EHCI runtime idle\n");
+
+ return 0;
+}
+
+static int ehci_msm2_runtime_suspend(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+ dev_dbg(dev, "EHCI runtime suspend\n");
+ return msm_ehci_suspend(mhcd);
+}
+
+static int ehci_msm2_runtime_resume(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+
+ dev_dbg(dev, "EHCI runtime resume\n");
+ return msm_ehci_resume(mhcd);
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops ehci_msm2_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ehci_msm2_pm_suspend, ehci_msm2_pm_resume)
+ SET_RUNTIME_PM_OPS(ehci_msm2_runtime_suspend, ehci_msm2_runtime_resume,
+ ehci_msm2_runtime_idle)
+};
+#endif
+
+static struct platform_driver ehci_msm2_driver = {
+ .probe = ehci_msm2_probe,
+ .remove = __devexit_p(ehci_msm2_remove),
+ .driver = {
+ .name = "msm_ehci_host",
+#ifdef CONFIG_PM
+ .pm = &ehci_msm2_dev_pm_ops,
+#endif
+ },
+};
diff --git a/drivers/usb/host/ehci-msm72k.c b/drivers/usb/host/ehci-msm72k.c
index 87c75e7..b3939ef 100644
--- a/drivers/usb/host/ehci-msm72k.c
+++ b/drivers/usb/host/ehci-msm72k.c
@@ -79,9 +79,9 @@
return;
if (vote)
- clk_enable(pdata->ebi1_clk);
+ clk_prepare_enable(pdata->ebi1_clk);
else
- clk_disable(pdata->ebi1_clk);
+ clk_disable_unprepare(pdata->ebi1_clk);
}
static void msm_xusb_enable_clks(struct msmusb_hcd *mhcd)
@@ -96,8 +96,8 @@
/* OTG driver takes care of clock management */
break;
case USB_PHY_SERIAL_PMIC:
- clk_enable(mhcd->alt_core_clk);
- clk_enable(mhcd->iface_clk);
+ clk_prepare_enable(mhcd->alt_core_clk);
+ clk_prepare_enable(mhcd->iface_clk);
break;
default:
pr_err("%s: undefined phy type ( %X )\n", __func__,
@@ -119,8 +119,8 @@
/* OTG driver takes care of clock management */
break;
case USB_PHY_SERIAL_PMIC:
- clk_disable(mhcd->alt_core_clk);
- clk_disable(mhcd->iface_clk);
+ clk_disable_unprepare(mhcd->alt_core_clk);
+ clk_disable_unprepare(mhcd->iface_clk);
break;
default:
pr_err("%s: undefined phy type ( %X )\n", __func__,
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
index 59d9769..0ee1827 100644
--- a/drivers/usb/otg/msm72k_otg.c
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -562,9 +562,9 @@
if (on)
/* enable clocks */
- clk_enable(dev->alt_core_clk);
+ clk_prepare_enable(dev->alt_core_clk);
else
- clk_disable(dev->alt_core_clk);
+ clk_disable_unprepare(dev->alt_core_clk);
return 0;
}
@@ -589,7 +589,7 @@
* low power mode routine
*/
if (dev->pdata->pclk_required_during_lpm)
- clk_enable(dev->iface_clk);
+ clk_prepare_enable(dev->iface_clk);
usb_gadget_vbus_connect(xceiv->gadget);
} else {
@@ -601,7 +601,7 @@
* low power mode routine
*/
if (dev->pdata->pclk_required_during_lpm)
- clk_disable(dev->iface_clk);
+ clk_disable_unprepare(dev->iface_clk);
otg_pm_qos_update_latency(dev, 0);
if (pdata->setup_gpio)
@@ -628,9 +628,9 @@
*/
if (dev->pdata->pclk_required_during_lpm) {
if (on)
- clk_enable(dev->iface_clk);
+ clk_prepare_enable(dev->iface_clk);
else
- clk_disable(dev->iface_clk);
+ clk_disable_unprepare(dev->iface_clk);
}
dev->start_host(xceiv->host, on);
@@ -759,9 +759,9 @@
mb();
if (dev->iface_clk)
- clk_disable(dev->iface_clk);
+ clk_disable_unprepare(dev->iface_clk);
- clk_disable(dev->core_clk);
+ clk_disable_unprepare(dev->core_clk);
/* usb phy no more require TCXO clock, hence vote for TCXO disable*/
ret = msm_xo_mode_vote(dev->xo_handle, MSM_XO_MODE_OFF);
if (ret)
@@ -835,10 +835,10 @@
pr_err("%s failed to vote for"
"TCXO D1 buffer%d\n", __func__, ret);
- clk_enable(dev->core_clk);
+ clk_prepare_enable(dev->core_clk);
if (dev->iface_clk)
- clk_enable(dev->iface_clk);
+ clk_prepare_enable(dev->iface_clk);
temp = readl(USB_USBCMD);
temp &= ~ASYNC_INTR_CTRL;
@@ -1550,7 +1550,7 @@
unsigned long timeout;
u32 mode, work = 0;
- clk_enable(dev->alt_core_clk);
+ clk_prepare_enable(dev->alt_core_clk);
if (!phy_reset)
goto reset_link;
@@ -1596,7 +1596,7 @@
/* Ensure that RESET operation is completed before turning off clock */
mb();
- clk_disable(dev->alt_core_clk);
+ clk_disable_unprepare(dev->alt_core_clk);
if ((xceiv->gadget && xceiv->gadget->is_a_peripheral) ||
test_bit(ID, &dev->inputs))
@@ -2646,7 +2646,7 @@
*/
clk_set_rate(dev->core_clk, INT_MAX);
- clk_enable(dev->core_clk);
+ clk_prepare_enable(dev->core_clk);
if (!dev->pdata->pclk_is_hw_gated) {
dev->iface_clk = clk_get(&pdev->dev, "iface_clk");
@@ -2655,7 +2655,7 @@
ret = PTR_ERR(dev->iface_clk);
goto put_core_clk;
}
- clk_enable(dev->iface_clk);
+ clk_prepare_enable(dev->iface_clk);
}
if (!dev->pdata->phy_reset) {
@@ -2888,11 +2888,11 @@
clk_put(dev->phy_reset_clk);
put_iface_clk:
if (dev->iface_clk) {
- clk_disable(dev->iface_clk);
+ clk_disable_unprepare(dev->iface_clk);
clk_put(dev->iface_clk);
}
put_core_clk:
- clk_disable(dev->core_clk);
+ clk_disable_unprepare(dev->core_clk);
clk_put(dev->core_clk);
put_alt_core_clk:
clk_put(dev->alt_core_clk);
@@ -2942,10 +2942,10 @@
dev->pdata->chg_init(0);
free_irq(dev->irq, pdev);
iounmap(dev->regs);
- clk_disable(dev->core_clk);
+ clk_disable_unprepare(dev->core_clk);
clk_put(dev->core_clk);
if (dev->iface_clk) {
- clk_disable(dev->iface_clk);
+ clk_disable_unprepare(dev->iface_clk);
clk_put(dev->iface_clk);
}
if (dev->alt_core_clk)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 4e1895f..6964835 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -538,7 +538,7 @@
motg->reset_counter++;
}
- clk_enable(motg->clk);
+ clk_prepare_enable(motg->clk);
ret = msm_otg_phy_reset(motg);
if (ret) {
dev_err(otg->dev, "phy_reset failed\n");
@@ -558,7 +558,7 @@
/* Ensure that RESET operation is completed before turning off clock */
mb();
- clk_disable(motg->clk);
+ clk_disable_unprepare(motg->clk);
if (pdata->otg_control == OTG_PHY_CONTROL) {
val = readl_relaxed(USB_OTGSC);
@@ -711,8 +711,8 @@
/* Ensure that above operation is completed before turning off clocks */
mb();
- clk_disable(motg->pclk);
- clk_disable(motg->core_clk);
+ clk_disable_unprepare(motg->pclk);
+ clk_disable_unprepare(motg->core_clk);
/* usb phy no more require TCXO clock, hence vote for TCXO disable */
clk_disable_unprepare(motg->xo_handle);
@@ -765,9 +765,9 @@
dev_err(otg->dev, "%s failed to vote for "
"TCXO D0 buffer%d\n", __func__, ret);
- clk_enable(motg->core_clk);
+ clk_prepare_enable(motg->core_clk);
- clk_enable(motg->pclk);
+ clk_prepare_enable(motg->pclk);
if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
msm_hsusb_ldo_enable(motg, 1);
@@ -2529,7 +2529,7 @@
goto free_xo_handle;
}
- clk_enable(motg->pclk);
+ clk_prepare_enable(motg->pclk);
ret = msm_hsusb_init_vddcx(motg, 1);
if (ret) {
@@ -2554,7 +2554,7 @@
dev_err(&pdev->dev, "hsusb vreg enable failed\n");
goto free_ldo_init;
}
- clk_enable(motg->core_clk);
+ clk_prepare_enable(motg->core_clk);
writel(0, USB_USBINTR);
writel(0, USB_OTGSC);
@@ -2652,14 +2652,14 @@
free_irq(motg->irq, motg);
destroy_wlock:
wake_lock_destroy(&motg->wlock);
- clk_disable(motg->core_clk);
+ clk_disable_unprepare(motg->core_clk);
msm_hsusb_ldo_enable(motg, 0);
free_ldo_init:
msm_hsusb_ldo_init(motg, 0);
free_init_vddcx:
msm_hsusb_init_vddcx(motg, 0);
devote_xo_handle:
- clk_disable(motg->pclk);
+ clk_disable_unprepare(motg->pclk);
clk_disable_unprepare(motg->xo_handle);
free_xo_handle:
clk_put(motg->xo_handle);
@@ -2726,8 +2726,8 @@
if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
dev_err(otg->dev, "Unable to suspend PHY\n");
- clk_disable(motg->pclk);
- clk_disable(motg->core_clk);
+ clk_disable_unprepare(motg->pclk);
+ clk_disable_unprepare(motg->core_clk);
clk_put(motg->xo_handle);
msm_hsusb_ldo_enable(motg, 0);
msm_hsusb_ldo_init(motg, 0);
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index d3f8b2b..0110df9 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -270,6 +270,11 @@
select FB_MSM_MIPI_DSI_TOSHIBA
default n
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+ bool
+ select FB_MSM_MIPI_DSI_TOSHIBA
+ default n
+
config FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
bool
select FB_MSM_MIPI_DSI_NOVATEK
@@ -446,6 +451,7 @@
bool "MIPI Panel Detect"
select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
@@ -497,9 +503,20 @@
config FB_MSM_LVDS_MIPI_PANEL_DETECT
bool "LVDS + MIPI Panel Auto Detect"
- select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
select FB_MSM_LVDS_CHIMEI_WXGA
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+ select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
+ select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
+ select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
+ select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+ select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+ select FB_MSM_MIPI_SIMULATOR_VIDEO
select FB_MSM_MIPI_CHIMEI_WXGA
+ select FB_MSM_MIPI_CHIMEI_WUXGA
---help---
Support for LVDS + MIPI panel auto detect
@@ -541,6 +558,10 @@
bool "MIPI Toshiba WSVGA PT Panel"
select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA_PANEL
+ bool "MIPI Toshiba WUXGA (1920x1200) Panel"
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+
config FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT_PANEL
bool "MIPI NOVATEK VIDEO QHD PT Panel"
select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index bd7628d..2bdab74 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -114,7 +114,7 @@
endif
ifeq ($(CONFIG_FB_MSM_MIPI_PANEL_DETECT),y)
-obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o
+obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o mipi_toshiba_video_wuxga.o
obj-y += mipi_novatek_video_qhd_pt.o mipi_novatek_cmd_qhd_pt.o
obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
obj-y += mipi_NT35510_video_wvga_pt.o mipi_NT35510_cmd_wvga_pt.o
@@ -124,6 +124,7 @@
else
obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT) += mipi_toshiba_video_wvga_pt.o
obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT) += mipi_toshiba_video_wsvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA) += mipi_toshiba_video_wuxga.o
obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT) += mipi_novatek_video_qhd_pt.o
obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT) += mipi_novatek_cmd_qhd_pt.o
obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
diff --git a/drivers/video/msm/adv7520.c b/drivers/video/msm/adv7520.c
index b3b34bb..7386983 100644
--- a/drivers/video/msm/adv7520.c
+++ b/drivers/video/msm/adv7520.c
@@ -874,7 +874,11 @@
} else
DEV_ERR("adv7520_probe: failed to add fb device\n");
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+ external_common_state->sdev.name = "hdmi_as_primary";
+#else
external_common_state->sdev.name = "hdmi";
+#endif
if (switch_dev_register(&external_common_state->sdev) < 0)
DEV_ERR("Hdmi switch registration failed\n");
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 07a075c..0a86a50 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -480,16 +480,19 @@
static ssize_t hdmi_msm_wta_cec_frame(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ int i;
int retry = ((struct hdmi_msm_cec_msg *) buf)->retransmit;
- if (retry > 15)
- retry = 15;
- while (1) {
+ for (i = 0; i < RETRANSMIT_MAX_NUM; i++) {
hdmi_msm_cec_msg_send((struct hdmi_msm_cec_msg *) buf);
if (hdmi_msm_state->cec_frame_wr_status
- & CEC_STATUS_WR_ERROR && retry--)
+ & CEC_STATUS_WR_ERROR && retry--) {
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->fsm_reset_done)
+ retry++;
+ mutex_unlock(&hdmi_msm_state_mutex);
msleep(360);
- else
+ } else
break;
}
@@ -911,8 +914,13 @@
uint32 offset = 4;
*len = 0;
- if ((in_buf[2] == 4) && (type != 2)) { /* no non-DTD data present */
- DEV_WARN("EDID: no non-DTD data present\n");
+
+ /*edid buffer 1, byte 2 being 4 means no non-DTD/Data block collection
+ present.
+ edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block collection
+ present and no DTD data present.*/
+ if ((in_buf[2] == 0) || (in_buf[2] == 4)) {
+ DEV_WARN("EDID: no DTD or non-DTD data present\n");
return NULL;
}
while (offset < 0x80) {
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 93e6d40..ef357db 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -79,6 +79,8 @@
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_line_latch_detect(void);
+
#ifdef TOGGLE_CEC_HARDWARE_FSM
static boolean msg_send_complete = TRUE;
static boolean msg_recv_complete = TRUE;
@@ -111,7 +113,7 @@
#define HDMI_MSM_CEC_INT_FRAME_WR_DONE_ACK BIT(0)
#define HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT BIT(0)
-#define HDMI_MSM_CEC_FRAME_WR_SUCCESS(___st) (((___st)&0xF) ==\
+#define HDMI_MSM_CEC_FRAME_WR_SUCCESS(___st) (((___st)&0xB) ==\
(HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT |\
HDMI_MSM_CEC_INT_FRAME_WR_DONE_MASK |\
HDMI_MSM_CEC_INT_FRAME_ERROR_MASK))
@@ -142,8 +144,8 @@
*/
HDMI_OUTP(0x02A0, HDMI_MSM_CEC_ADDR_LOGICAL_ADDR(4));
- /* 0x028C CEC_CTRL */
- HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+ hdmi_msm_state->first_monitor = 0;
+ hdmi_msm_state->fsm_reset_done = false;
/* 0x029C CEC_INT */
/* Enable CEC interrupts */
@@ -161,7 +163,11 @@
* BIT_1_ERR_RANGE_HI = 8 => 750us, the test used 775us,
* so increased this to 9 which => 800us.
*/
- HDMI_OUTP(0x02E0, 0x889788);
+ /*
+ * CEC latch up issue - To fire monitor interrupt
+ * for every start of message
+ */
+ HDMI_OUTP(0x02E0, 0x880000);
/*
* Slight adjustment to logic 0 low period on write
@@ -173,6 +179,8 @@
*/
HDMI_OUTP(0x02A4, 0x1 | (7 * 0x30) << 7);
+ /* 0x028C CEC_CTRL */
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
}
void hdmi_msm_cec_write_logical_addr(int addr)
@@ -207,6 +215,9 @@
boolean frameType = (msg->recvr_id == 15 ? BIT(0) : 0);
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->fsm_reset_done = false;
+ mutex_unlock(&hdmi_msm_state_mutex);
#ifdef TOGGLE_CEC_HARDWARE_FSM
msg_send_complete = FALSE;
#endif
@@ -278,9 +289,34 @@
msg_recv_complete = TRUE;
}
msg_send_complete = TRUE;
+#else
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
#endif
}
+void hdmi_msm_cec_line_latch_detect(void)
+{
+ /*
+ * CECT 9-5-1
+ * The timer period needs to be changed to appropriate value
+ */
+ /*
+ * Timedout without RD_DONE, WR_DONE or ERR_INT
+ * Toggle CEC hardware FSM
+ */
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->first_monitor == 1) {
+ DEV_WARN("CEC line is probably latched up - CECT 9-5-1");
+ if (!msg_recv_complete)
+ hdmi_msm_state->fsm_reset_done = true;
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+ hdmi_msm_state->first_monitor = 0;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+}
+
void hdmi_msm_cec_msg_recv(void)
{
uint32 data;
@@ -476,6 +512,14 @@
temp_msg.frame_size = i + 2;
hdmi_msm_cec_msg_send(&temp_msg);
break;
+ case 0x44:
+ /* User Control Pressed */
+ DEV_INFO("User Control Pressed\n");
+ break;
+ case 0x45:
+ /* User Control Released */
+ DEV_INFO("User Control Released\n");
+ break;
default:
DEV_INFO("Recvd an unknown cmd = [%u]\n",
hdmi_msm_state->cec_queue_wr->opcode);
@@ -837,6 +881,13 @@
HDMI_OUTP(0x0254, 4 | (hpd_state ? 0 : 2));
}
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_latch_work(struct work_struct *work)
+{
+ hdmi_msm_cec_line_latch_detect();
+}
+#endif
+
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdcp_deauthenticate(void);
static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
@@ -1099,6 +1150,8 @@
HDMI_MSM_CEC_INT_FRAME_WR_DONE_ACK);
mutex_lock(&hdmi_msm_state_mutex);
hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_DONE;
+ hdmi_msm_state->first_monitor = 0;
+ del_timer(&hdmi_msm_state->cec_read_timer);
mutex_unlock(&hdmi_msm_state_mutex);
complete(&hdmi_msm_state->cec_frame_wr_done);
return IRQ_HANDLED;
@@ -1112,17 +1165,50 @@
#endif
HDMI_OUTP(0x029C, cec_intr_status);
mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->first_monitor = 0;
+ del_timer(&hdmi_msm_state->cec_read_timer);
hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_ERROR;
mutex_unlock(&hdmi_msm_state_mutex);
complete(&hdmi_msm_state->cec_frame_wr_done);
return IRQ_HANDLED;
}
- if ((cec_intr_status & (1 << 4)) && (cec_intr_status & (1 << 5)))
+ if ((cec_intr_status & (1 << 4)) && (cec_intr_status & (1 << 5))) {
DEV_DBG("CEC_IRQ_MONITOR\n");
+ HDMI_OUTP(0x029C, cec_intr_status |
+ HDMI_MSM_CEC_INT_MONITOR_ACK);
+
+ /*
+ * CECT 9-5-1
+ * On the first occassion start a timer
+ * for few hundred ms, if it expires then
+ * reset the CEC block else go on with
+ * frame transactions as usual.
+ * Below adds hdmi_msm_cec_msg_recv() as an
+ * item into the work queue instead of running in
+ * interrupt context
+ */
+ mutex_lock(&hdmi_msm_state_mutex);
+ if (hdmi_msm_state->first_monitor == 0) {
+ /* This timer might have to be changed
+ * worst case theoritical =
+ * 16 bytes * 8 * 2.7msec = 346 msec
+ */
+ mod_timer(&hdmi_msm_state->cec_read_timer,
+ jiffies + HZ/2);
+ hdmi_msm_state->first_monitor = 1;
+ }
+ mutex_unlock(&hdmi_msm_state_mutex);
+ return IRQ_HANDLED;
+ }
if ((cec_intr_status & (1 << 6)) && (cec_intr_status & (1 << 7))) {
DEV_DBG("CEC_IRQ_FRAME_RD_DONE\n");
+
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->first_monitor = 0;
+ del_timer(&hdmi_msm_state->cec_read_timer);
+ mutex_unlock(&hdmi_msm_state_mutex);
HDMI_OUTP(0x029C, cec_intr_status |
HDMI_MSM_CEC_INT_FRAME_RD_DONE_ACK);
hdmi_msm_cec_msg_recv();
@@ -1135,6 +1221,9 @@
HDMI_OUTP(0x028C, 0x0);
HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
}
+#else
+ HDMI_OUTP(0x028C, 0x0);
+ HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
#endif
return IRQ_HANDLED;
@@ -2371,6 +2460,8 @@
[8] AN_0_READY
[9] AN_1_READY */
/* wait for an0 and an1 ready bits to be set in LINK0_STATUS */
+
+ mutex_lock(&hdcp_auth_state_mutex);
timeout_count = 100;
while (((HDMI_INP_ND(0x011C) & (0x3 << 8)) != (0x3 << 8))
&& timeout_count--)
@@ -2404,6 +2495,7 @@
[31:0] LINK0_AN_1 */
/* read an1 calculation */
link0_an_1 = HDMI_INP(0x0150);
+ mutex_unlock(&hdcp_auth_state_mutex);
/* three bits 28..30 */
hdcp_key_state((HDMI_INP(0x011C) >> 28) & 0x7);
@@ -3867,7 +3959,11 @@
"AUDIO CFG is %08x", i, audio_pkt_ctrl, audio_cfg);
msleep(20);
}
+
+ mutex_lock(&hdcp_auth_state_mutex);
hdmi_msm_reset_core();
+ mutex_unlock(&hdcp_auth_state_mutex);
+
hdmi_msm_init_phy(external_common_state->video_resolution);
/* HDMI_USEC_REFTIMER[0x0208] */
HDMI_OUTP(0x0208, 0x0001001B);
@@ -3924,6 +4020,13 @@
}
#endif
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_read_timer_func(unsigned long data)
+{
+ queue_work(hdmi_work_queue, &hdmi_msm_state->cec_latch_detect_work);
+}
+#endif
+
static void hdmi_msm_hpd_read_work(struct work_struct *work)
{
uint32 hpd_ctrl;
@@ -3959,12 +4062,18 @@
static void hdmi_msm_hpd_off(void)
{
+ if (!hdmi_msm_state->hpd_initialized) {
+ DEV_DBG("%s: HPD is already OFF, returning\n", __func__);
+ return;
+ }
+
DEV_DBG("%s: (timer, clk, 5V, core, IRQ off)\n", __func__);
del_timer(&hdmi_msm_state->hpd_state_timer);
disable_irq(hdmi_msm_state->irq);
hdmi_msm_set_mode(FALSE);
hdmi_msm_state->hpd_initialized = FALSE;
+ hdmi_msm_powerdown_phy();
hdmi_msm_state->pd->cec_power(0);
hdmi_msm_state->pd->enable_5v(0);
hdmi_msm_state->pd->core_power(0, 1);
@@ -3983,6 +4092,12 @@
static int hdmi_msm_hpd_on(bool trigger_handler)
{
static int phy_reset_done;
+ uint32 hpd_ctrl;
+
+ if (hdmi_msm_state->hpd_initialized) {
+ DEV_DBG("%s: HPD is already ON, returning\n", __func__);
+ return 0;
+ }
hdmi_msm_clk(1);
hdmi_msm_state->pd->core_power(1, 1);
@@ -4000,36 +4115,34 @@
HDMI_OUTP(0x0208, 0x0001001B);
/* Check HPD State */
- if (!hdmi_msm_state->hpd_initialized) {
- uint32 hpd_ctrl;
- enable_irq(hdmi_msm_state->irq);
+ enable_irq(hdmi_msm_state->irq);
- /* set timeout to 4.1ms (max) for hardware debounce */
- hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
+ /* set timeout to 4.1ms (max) for hardware debounce */
+ hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
- /* Toggle HPD circuit to trigger HPD sense */
- HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
- HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
+ /* Toggle HPD circuit to trigger HPD sense */
+ HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
+ HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
- DEV_DBG("%s: (clk, 5V, core, IRQ on) <trigger:%s>\n", __func__,
- trigger_handler ? "true" : "false");
+ DEV_DBG("%s: (clk, 5V, core, IRQ on) <trigger:%s>\n", __func__,
+ trigger_handler ? "true" : "false");
- if (trigger_handler) {
- /* Set HPD state machine: ensure at least 2 readouts */
- mutex_lock(&hdmi_msm_state_mutex);
- hdmi_msm_state->hpd_stable = 0;
- hdmi_msm_state->hpd_prev_state = TRUE;
- mutex_lock(&external_common_state_hpd_mutex);
- external_common_state->hpd_state = FALSE;
- mutex_unlock(&external_common_state_hpd_mutex);
- hdmi_msm_state->hpd_cable_chg_detected = TRUE;
- mutex_unlock(&hdmi_msm_state_mutex);
- mod_timer(&hdmi_msm_state->hpd_state_timer,
- jiffies + HZ/2);
- }
-
- hdmi_msm_state->hpd_initialized = TRUE;
+ if (trigger_handler) {
+ /* Set HPD state machine: ensure at least 2 readouts */
+ mutex_lock(&hdmi_msm_state_mutex);
+ hdmi_msm_state->hpd_stable = 0;
+ hdmi_msm_state->hpd_prev_state = TRUE;
+ mutex_lock(&external_common_state_hpd_mutex);
+ external_common_state->hpd_state = FALSE;
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_state->hpd_cable_chg_detected = TRUE;
+ mutex_unlock(&hdmi_msm_state_mutex);
+ mod_timer(&hdmi_msm_state->hpd_state_timer,
+ jiffies + HZ/2);
}
+
+ hdmi_msm_state->hpd_initialized = TRUE;
+
hdmi_msm_set_mode(TRUE);
return 0;
@@ -4248,6 +4361,15 @@
add_timer(&hdmi_msm_state->hdcp_timer);
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ init_timer(&hdmi_msm_state->cec_read_timer);
+ hdmi_msm_state->cec_read_timer.function =
+ hdmi_msm_cec_read_timer_func;
+ hdmi_msm_state->cec_read_timer.data = (uint32)NULL;
+
+ hdmi_msm_state->cec_read_timer.expires = 0xffffffffL;
+ #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+
fb_dev = msm_fb_add_device(pdev);
if (fb_dev) {
rc = external_common_state_create(fb_dev);
@@ -4285,7 +4407,11 @@
queue_work(hdmi_work_queue, &hdmi_msm_state->hpd_read_work);
/* Initialize hdmi node and register with switch driver */
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+ external_common_state->sdev.name = "hdmi_as_primary";
+#else
external_common_state->sdev.name = "hdmi";
+#endif
if (switch_dev_register(&external_common_state->sdev) < 0)
DEV_ERR("Hdmi switch registration failed\n");
@@ -4452,7 +4578,10 @@
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+ INIT_WORK(&hdmi_msm_state->cec_latch_detect_work,
+ hdmi_msm_cec_latch_work);
init_completion(&hdmi_msm_state->cec_frame_wr_done);
+ init_completion(&hdmi_msm_state->cec_line_latch_wait);
#endif
rc = platform_device_register(&this_device);
diff --git a/drivers/video/msm/hdmi_msm.h b/drivers/video/msm/hdmi_msm.h
index 6d19d157..9675fd5 100644
--- a/drivers/video/msm/hdmi_msm.h
+++ b/drivers/video/msm/hdmi_msm.h
@@ -75,8 +75,10 @@
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
boolean cec_enabled;
+ unsigned int first_monitor;
int cec_logical_addr;
struct completion cec_frame_wr_done;
+ struct timer_list cec_read_timer;
#define CEC_STATUS_WR_ERROR 0x0001
#define CEC_STATUS_WR_DONE 0x0002
#define CEC_STATUS_WR_TMOUT 0x0004
@@ -86,8 +88,17 @@
struct hdmi_msm_cec_msg *cec_queue_wr;
struct hdmi_msm_cec_msg *cec_queue_rd;
boolean cec_queue_full;
+ boolean fsm_reset_done;
+
+ /*
+ * CECT 9-5-1
+ */
+ struct completion cec_line_latch_wait;
+ struct work_struct cec_latch_detect_work;
+
#define CEC_QUEUE_SIZE 16
#define CEC_QUEUE_END (hdmi_msm_state->cec_queue_start + CEC_QUEUE_SIZE)
+#define RETRANSMIT_MAX_NUM 7
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
int irq;
diff --git a/drivers/video/msm/lcdc_gordon.c b/drivers/video/msm/lcdc_gordon.c
index f9532b4..8327c6c 100644
--- a/drivers/video/msm/lcdc_gordon.c
+++ b/drivers/video/msm/lcdc_gordon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2010, 2012 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -84,6 +84,7 @@
static int spi_sdo;
static int spi_sdi;
static int spi_dac;
+static int bl_level;
static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
(1 << 6),
(1 << 5),
@@ -313,6 +314,17 @@
spi_init(); /* LCD needs SPI */
gordon_disp_powerup();
gordon_disp_on();
+ if (bl_level <= 1) {
+ /* keep back light OFF */
+ serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+ udelay(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ } else {
+ /* keep back light ON */
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+ udelay(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ }
gordon_state.disp_initialized = TRUE;
}
return 0;
@@ -351,18 +363,20 @@
static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
{
- int bl_level = mfd->bl_level;
+ bl_level = mfd->bl_level;
- if (bl_level <= 1) {
- /* keep back light OFF */
- serigo(GORDON_REG_LCDIFCTL2, 0x0B);
- udelay(15);
- serigo(GORDON_REG_VALTRAN, 0x01);
- } else {
- /* keep back light ON */
- serigo(GORDON_REG_LCDIFCTL2, 0x7B);
- udelay(15);
- serigo(GORDON_REG_VALTRAN, 0x01);
+ if (gordon_state.disp_initialized) {
+ if (bl_level <= 1) {
+ /* keep back light OFF */
+ serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+ udelay(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ } else {
+ /* keep back light ON */
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+ udelay(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ }
}
}
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 43520e0..d8987e2 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -86,6 +86,9 @@
struct workqueue_struct *mdp_dma_wq; /*mdp dma wq */
struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */
+struct workqueue_struct *mdp_hist_wq; /*mdp histogram wq */
+struct work_struct mdp_histogram_worker;
+
static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
static struct delayed_work mdp_pipe_ctrl_worker;
@@ -211,8 +214,8 @@
}
/*mask off non LUT select bits*/
- out = inpdw(MDP_BASE + 0x90070) & ~(0x1 << 10);
- MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | out);
+ out = inpdw(MDP_BASE + 0x90070) & ~((0x1 << 10) | 0x7);
+ MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x7 | out);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
mdp_lut_i = (mdp_lut_i + 1)%2;
@@ -225,9 +228,9 @@
if (mdp_lut_push) {
mutex_lock(&mdp_lut_push_sem);
mdp_lut_push = 0;
- out = inpdw(MDP_BASE + 0x90070) & ~(0x1 << 10);
+ out = inpdw(MDP_BASE + 0x90070) & ~((0x1 << 10) | 0x7);
MDP_OUTP(MDP_BASE + 0x90070,
- (mdp_lut_push_i << 10) | out);
+ (mdp_lut_push_i << 10) | 0x7 | out);
mutex_unlock(&mdp_lut_push_sem);
}
}
@@ -237,20 +240,112 @@
#ifdef CONFIG_FB_MSM_MDP40
unsigned int mdp_hist_frame_cnt;
-struct completion mdp_hist_comp;
-boolean mdp_is_hist_start = FALSE;
#else
static unsigned int mdp_hist_frame_cnt;
-static struct completion mdp_hist_comp;
-static boolean mdp_is_hist_start = FALSE;
#endif
+struct completion mdp_hist_comp;
static DEFINE_MUTEX(mdp_hist_mutex);
static boolean mdp_is_hist_data = FALSE;
+static boolean mdp_is_hist_start = FALSE;
+boolean mdp_is_hist_valid = FALSE;
+static boolean mdp_is_hist_init = FALSE;
+static uint32 mdp_hist_r[128];
+static uint32 mdp_hist_g[128];
+static uint32 mdp_hist_b[128];
+
+void __mdp_histogram_kickoff()
+{
+ char *mdp_hist_base;
+
+ if (mdp_rev >= MDP_REV_40)
+ mdp_hist_base = MDP_BASE + 0x95000;
+ else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31)
+ mdp_hist_base = MDP_BASE + 0x94000;
+ else {
+ pr_err("%s(): Unsupported MDP rev. %u\n", __func__, mdp_rev);
+ return ;
+ }
+
+ if (mdp_is_hist_data == TRUE) {
+ MDP_OUTP(mdp_hist_base + 0x004, mdp_hist_frame_cnt);
+ MDP_OUTP(mdp_hist_base, 1);
+ }
+}
+
+void __mdp_histogram_reset()
+{
+ char *mdp_hist_base;
+
+ if (mdp_rev >= MDP_REV_40)
+ mdp_hist_base = MDP_BASE + 0x95000;
+ else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31)
+ mdp_hist_base = MDP_BASE + 0x94000;
+ else {
+ pr_err("%s(): Unsupported MDP rev %u\n", __func__, mdp_rev);
+ return ;
+ }
+
+ MDP_OUTP(mdp_hist_base + 0x00C, 1);
+}
+
+static void mdp_hist_read_work(struct work_struct *data)
+{
+ char *mdp_hist_base;
+ uint32 r_data_offset = 0x100, g_data_offset = 0x200;
+ uint32 b_data_offset = 0x300;
+ int num_bins, i = 0;
+
+ if (mdp_rev >= MDP_REV_42) {
+ mdp_hist_base = MDP_BASE + 0x95000;
+ r_data_offset = 0x400;
+ g_data_offset = 0x800;
+ b_data_offset = 0xc00;
+ num_bins = 128;
+ } else if (mdp_rev >= MDP_REV_40 && mdp_rev <= MDP_REV_41) {
+ mdp_hist_base = MDP_BASE + 0x95000;
+ num_bins = 32;
+ } else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31) {
+ mdp_hist_base = MDP_BASE + 0x94000;
+ num_bins = 32;
+ } else {
+ pr_err("%s(): Unsupported MDP rev %u\n", __func__, mdp_rev);
+ return ;
+ }
+
+ mutex_lock(&mdp_hist_mutex);
+ if (mdp_is_hist_data == FALSE) {
+ pr_debug("%s, Histogram disabled before read.\n", __func__);
+ goto error;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ for (i = 0; i < num_bins; i++) {
+ mdp_hist_r[i] = inpdw(mdp_hist_base + r_data_offset + (4*i));
+ mdp_hist_g[i] = inpdw(mdp_hist_base + g_data_offset + (4*i));
+ mdp_hist_b[i] = inpdw(mdp_hist_base + b_data_offset + (4*i));
+ }
+
+ __mdp_histogram_kickoff();
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ /* if read was triggered by an underrun, don't wake up readers*/
+ if (mdp_is_hist_valid && mdp_is_hist_init) {
+ complete(&mdp_hist_comp);
+ } else {
+ if (mdp_is_hist_valid == FALSE)
+ mdp_is_hist_valid = TRUE;
+
+ if (mdp_is_hist_init == FALSE)
+ mdp_is_hist_init = TRUE;
+ }
+error:
+ mutex_unlock(&mdp_hist_mutex);
+}
/*should hold mdp_hist_mutex before calling this function*/
int _mdp_histogram_ctrl(boolean en)
{
- unsigned long flag;
unsigned long hist_base;
uint32_t status;
@@ -266,34 +361,40 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
mdp_hist_frame_cnt = 1;
mdp_enable_irq(MDP_HISTOGRAM_TERM);
- spin_lock_irqsave(&mdp_spin_lock, flag);
- if (mdp_rev >= MDP_REV_40) {
- MDP_OUTP(MDP_BASE + hist_base + 0x10, 1);
- MDP_OUTP(MDP_BASE + hist_base + 0x1c, INTR_HIST_DONE);
- }
- spin_unlock_irqrestore(&mdp_spin_lock, flag);
- MDP_OUTP(MDP_BASE + hist_base + 0x4, mdp_hist_frame_cnt);
- MDP_OUTP(MDP_BASE + hist_base, 1);
- mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ INIT_COMPLETION(mdp_hist_comp);
+
+ /*Clear the interrupts before enabling them*/
+ MDP_OUTP(MDP_BASE + hist_base + 0x18, INTR_HIST_DONE |
+ INTR_HIST_RESET_SEQ_DONE);
+ MDP_OUTP(MDP_BASE + hist_base + 0x10, 1);
+ MDP_OUTP(MDP_BASE + hist_base + 0x1c, INTR_HIST_DONE |
+ INTR_HIST_RESET_SEQ_DONE);
+
mdp_is_hist_data = TRUE;
+ mdp_is_hist_valid = TRUE;
+ mdp_is_hist_init = FALSE;
+
+ __mdp_histogram_reset();
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
} else {
if (!mdp_is_hist_data)
return -EINVAL;
mdp_is_hist_data = FALSE;
+ mdp_is_hist_valid = FALSE;
+ mdp_is_hist_init = FALSE;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ status = inpdw(MDP_BASE + hist_base + 0x1C);
+ status &= ~(INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+ MDP_OUTP(MDP_BASE + hist_base + 0x1C, status);
+ MDP_OUTP(MDP_BASE + hist_base + 0x18, INTR_HIST_DONE |
+ INTR_HIST_RESET_SEQ_DONE);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
complete(&mdp_hist_comp);
- if (mdp_rev >= MDP_REV_40) {
- mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- status = inpdw(MDP_BASE + hist_base + 0x1C);
- status &= ~INTR_HIST_DONE;
- MDP_OUTP(MDP_BASE + hist_base + 0x1C, status);
-
- MDP_OUTP(MDP_BASE + hist_base + 0x18, INTR_HIST_DONE);
- mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
- FALSE);
- }
-
mdp_disable_irq(MDP_HISTOGRAM_TERM);
}
@@ -307,6 +408,10 @@
if (mdp_is_hist_start)
ret = _mdp_histogram_ctrl(en);
mutex_unlock(&mdp_hist_mutex);
+
+ if (en == false)
+ flush_workqueue(mdp_hist_wq);
+
return ret;
}
@@ -361,6 +466,10 @@
ret = _mdp_histogram_ctrl(FALSE);
+ mutex_unlock(&mdp_hist_mutex);
+ flush_workqueue(mdp_hist_wq);
+ return ret;
+
mdp_hist_stop_err:
mutex_unlock(&mdp_hist_mutex);
return ret;
@@ -369,55 +478,26 @@
/*call from within mdp_hist_mutex*/
static int _mdp_copy_hist_data(struct mdp_histogram *hist)
{
- char *mdp_hist_base;
- uint32 r_data_offset = 0x100, g_data_offset = 0x200;
- uint32 b_data_offset = 0x300;
int ret = 0;
- if (mdp_rev >= MDP_REV_42) {
- mdp_hist_base = MDP_BASE + 0x95000;
- r_data_offset = 0x400;
- g_data_offset = 0x800;
- b_data_offset = 0xc00;
- } else if (mdp_rev >= MDP_REV_40 && mdp_rev <= MDP_REV_41) {
- mdp_hist_base = MDP_BASE + 0x95000;
- } else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31) {
- mdp_hist_base = MDP_BASE + 0x94000;
- } else {
- pr_err("%s(): Unsupported MDP rev %u\n", __func__, mdp_rev);
- return -EPERM;
- }
-
- mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
if (hist->r) {
- ret = copy_to_user(hist->r, mdp_hist_base + r_data_offset,
- hist->bin_cnt * 4);
+ ret = copy_to_user(hist->r, mdp_hist_r, hist->bin_cnt * 4);
if (ret)
goto hist_err;
}
if (hist->g) {
- ret = copy_to_user(hist->g, mdp_hist_base + g_data_offset,
- hist->bin_cnt * 4);
+ ret = copy_to_user(hist->g, mdp_hist_g, hist->bin_cnt * 4);
if (ret)
goto hist_err;
}
if (hist->b) {
- ret = copy_to_user(hist->b, mdp_hist_base + b_data_offset,
- hist->bin_cnt * 4);
+ ret = copy_to_user(hist->b, mdp_hist_b, hist->bin_cnt * 4);
if (ret)
goto hist_err;
}
-
- if (mdp_is_hist_start == TRUE) {
- MDP_OUTP(mdp_hist_base + 0x004,
- mdp_hist_frame_cnt);
- MDP_OUTP(mdp_hist_base, 1);
- }
- mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
return 0;
-
hist_err:
- printk(KERN_ERR "%s: invalid hist buffer\n", __func__);
+ pr_err("%s: invalid hist buffer\n", __func__);
return ret;
}
@@ -435,17 +515,17 @@
mutex_lock(&mdp_hist_mutex);
if (!mdp_is_hist_data) {
- ret = -EINVAL;
- goto error;
- }
-
- if (!mdp_is_hist_start) {
- printk(KERN_ERR "%s histogram not started\n", __func__);
+ pr_err("%s - histogram not ready\n", __func__);
ret = -EPERM;
goto error;
}
- INIT_COMPLETION(mdp_hist_comp);
+ if (!mdp_is_hist_start) {
+ pr_err("%s histogram not started\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+
mdp_hist_frame_cnt = hist->frame_cnt;
mutex_unlock(&mdp_hist_mutex);
@@ -455,8 +535,9 @@
}
mutex_lock(&mdp_hist_mutex);
- if (mdp_is_hist_data)
+ if (mdp_is_hist_data && mdp_is_hist_init)
ret = _mdp_copy_hist_data(hist);
+
error:
mutex_unlock(&mdp_hist_mutex);
return ret;
@@ -818,7 +899,7 @@
#ifndef CONFIG_FB_MSM_MDP40
irqreturn_t mdp_isr(int irq, void *ptr)
{
- uint32 mdp_interrupt = 0;
+ uint32 hist_interrupt, mdp_interrupt = 0;
struct mdp_dma_data *dma;
unsigned long flag;
@@ -853,37 +934,48 @@
}
#ifndef CONFIG_FB_MSM_MDP22
if (mdp_interrupt & MDP_HIST_DONE) {
+ hist_interrupt = inp32(MDP_DMA_P_HIST_INTR_STATUS);
outp32(MDP_BASE + 0x94018, 0x3);
outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
- complete(&mdp_hist_comp);
+ if (hist_interrupt & INTR_HIST_RESET_SEQ_DONE)
+ __mdp_histogram_kickoff();
+
+ if (hist_interrupt & INTR_HIST_DONE) {
+ if (waitqueue_active(&mdp_hist_comp.wait)) {
+ if (!queue_work(mdp_hist_wq,
+ &mdp_histogram_worker)) {
+ pr_err("%s: can't queue hist_read\n",
+ __func__);
+ }
+ } else
+ __mdp_histogram_reset();
+ }
}
/* LCDC UnderFlow */
if (mdp_interrupt & LCDC_UNDERFLOW) {
mdp_lcdc_underflow_cnt++;
/*when underflow happens HW resets all the histogram
- registers that were set before so restore them back
- to normal.*/
+ registers that were set before so restore them back
+ to normal.*/
MDP_OUTP(MDP_BASE + 0x94010, 1);
- MDP_OUTP(MDP_BASE + 0x9401c, 2);
- if (mdp_is_hist_start == TRUE) {
- MDP_OUTP(MDP_BASE + 0x94004,
- mdp_hist_frame_cnt);
- MDP_OUTP(MDP_BASE + 0x94000, 1);
- }
+ MDP_OUTP(MDP_BASE + 0x9401c, INTR_HIST_DONE);
+ mdp_is_hist_valid = FALSE;
+ __mdp_histogram_reset();
}
/* LCDC Frame Start */
if (mdp_interrupt & LCDC_FRAME_START) {
+ dma = &dma2_data;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
/* let's disable LCDC interrupt */
mdp_intr_mask &= ~LCDC_FRAME_START;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-
- dma = &dma2_data;
if (dma->waiting) {
dma->waiting = FALSE;
complete(&dma->comp);
}
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
}
/* DMA2 LCD-Out Complete */
@@ -968,6 +1060,8 @@
spin_lock_init(&mdp_spin_lock);
mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
+ mdp_hist_wq = create_singlethread_workqueue("mdp_hist_wq");
+ INIT_WORK(&mdp_histogram_worker, mdp_hist_read_work);
mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
mdp_pipe_ctrl_workqueue_handler);
@@ -1008,8 +1102,6 @@
mutex_init(&dma_wb_data.ov_mutex);
#endif
-
-
#ifndef CONFIG_FB_MSM_MDP22
init_completion(&mdp_hist_comp);
#endif
@@ -1127,7 +1219,6 @@
}
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
#endif
- mdp_histogram_ctrl(TRUE);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
ret = panel_next_on(pdev);
@@ -1140,6 +1231,7 @@
mdp4_mddi_overlay_restore();
#endif
+ mdp_histogram_ctrl(TRUE);
return ret;
}
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 35a1453..3d3668e 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -44,6 +44,10 @@
extern int mdp_rev;
extern struct mdp_csc_cfg mdp_csc_convert[4];
+extern struct workqueue_struct *mdp_hist_wq;
+extern struct work_struct mdp_histogram_worker;
+extern boolean mdp_is_hist_valid;
+
#define MDP4_REVISION_V1 0
#define MDP4_REVISION_V2 1
#define MDP4_REVISION_V2_1 2
@@ -606,6 +610,10 @@
#define MDP_EBI2_LCD0 (msm_mdp_base + 0x003c)
#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0040)
#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x005c)
+
+#define MDP_DMA_P_HIST_INTR_STATUS (msm_mdp_base + 0x94014)
+#define MDP_DMA_P_HIST_INTR_CLEAR (msm_mdp_base + 0x94018)
+#define MDP_DMA_P_HIST_INTR_ENABLE (msm_mdp_base + 0x9401C)
#endif
#define MDP_FULL_BYPASS_WORD43 (msm_mdp_base + 0x101ac)
@@ -733,6 +741,8 @@
int mdp_start_histogram(struct fb_info *info);
int mdp_stop_histogram(struct fb_info *info);
int mdp_histogram_ctrl(boolean en);
+void __mdp_histogram_kickoff(void);
+void __mdp_histogram_reset(void);
void mdp_footswitch_ctrl(boolean on);
#ifdef CONFIG_FB_MSM_MDP303
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 155bc54..77e8cd1 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -20,7 +20,6 @@
extern struct mdp_dma_data dma_wb_data;
extern unsigned int mdp_hist_frame_cnt;
extern struct completion mdp_hist_comp;
-extern boolean mdp_is_hist_start;
extern boolean mdp_is_in_isr;
extern uint32 mdp_intr_mask;
extern spinlock_t mdp_spin_lock;
@@ -713,6 +712,8 @@
int mdp4_csc_config(struct mdp_csc_cfg_data *config);
void mdp4_csc_write(struct mdp_csc_cfg *data, uint32_t base);
int mdp4_csc_enable(struct mdp_csc_cfg_data *config);
+int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr);
+int mdp4_pgc_cfg(struct mdp_pgc_lut_data *pgc_ptr);
u32 mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index bf53c73..a9efc1c 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -370,17 +370,18 @@
static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
{
- uint32 val;
+ uint32 val, s;
int n;
n = mdp4_leading_0(src);
if (n > f_num)
n = f_num;
- val = src << n; /* maximum to reduce lose of resolution */
- val /= dst;
+ s = src << n; /* maximum to reduce lose of resolution */
+ val = s / dst;
if (n < f_num) {
n = f_num - n;
val <<= n;
+ val |= ((s % dst) << n) / dst;
}
return val;
@@ -1303,6 +1304,11 @@
u32 data = 0, stage, flush_bits = 0, pipe_cnt = 0, pull_mode = 0;
u32 cfg[MDP4_MIXER_MAX];
+ if (mixer == MDP4_MIXER0)
+ flush_bits |= 0x1;
+ else if (mixer == MDP4_MIXER1)
+ flush_bits |= 0x2;
+
for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++) {
cfg[i] = 0;
for (j = MDP4_MIXER_STAGE_BASE; j < MDP4_MIXER_STAGE_MAX; j++) {
@@ -2031,7 +2037,8 @@
}
}
-static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req)
+static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req,
+ struct msm_fb_data_type *mfd)
{
int is_fg;
@@ -2055,9 +2062,18 @@
return OVERLAY_PERF_LEVEL1;
if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE)
- return OVERLAY_PERF_LEVEL3;
- else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE)
- return OVERLAY_PERF_LEVEL2;
+ return OVERLAY_PERF_LEVEL4;
+ else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE) {
+ u32 max, min;
+ max = (req->dst_rect.h > req->dst_rect.w) ?
+ req->dst_rect.h : req->dst_rect.w;
+ min = (mfd->panel_info.yres > mfd->panel_info.xres) ?
+ mfd->panel_info.xres : mfd->panel_info.yres;
+ if (max > min) /* landscape mode */
+ return OVERLAY_PERF_LEVEL3;
+ else /* potrait mode */
+ return OVERLAY_PERF_LEVEL2;
+ }
else
return OVERLAY_PERF_LEVEL1;
}
@@ -2163,7 +2179,7 @@
return -EINTR;
}
- perf_level = mdp4_overlay_get_perf_level(req);
+ perf_level = mdp4_overlay_get_perf_level(req, mfd);
mixer = mfd->panel_info.pdest; /* DISPLAY_1 or DISPLAY_2 */
@@ -2342,6 +2358,9 @@
mdp4_stat.overlay_unset[pipe->mixer_num]++;
mdp4_overlay_pipe_free(pipe);
+
+ mdp4_set_perf_level();
+
mutex_unlock(&mfd->dma->ov_mutex);
return 0;
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index 5cdafe1..0b707d7 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -38,13 +38,16 @@
{
uint8 *buf;
int bpp, ptype;
+ int yres, remainder;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct msm_fb_data_type *mfd;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info;
int ret;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -55,10 +58,28 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
if (atv_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -150,16 +171,36 @@
uint8 *buf;
int bpp;
unsigned long flag;
+ int yres, remainder;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* no need to power on cmd block since it's lcdc mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
mutex_lock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 3f12827..a3be2af 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -96,13 +96,16 @@
int hsync_end_x;
uint8 *buf;
int bpp, ptype;
+ int yres, remainder;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct msm_fb_data_type *mfd;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info;
int ret;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -115,10 +118,28 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
if (dsi_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -295,7 +316,9 @@
{
struct fb_info *fbi;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
int bpp;
+ int yres, remainder;
uint8 *buf = NULL;
if (dsi_pipe == NULL)
@@ -314,10 +337,28 @@
fbi = mfd->fbi;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
if (pipe->is_3d) {
pipe->src_height = pipe->src_height_3d;
@@ -648,16 +689,36 @@
struct fb_info *fbi = mfd->fbi;
uint8 *buf;
int bpp;
+ int yres, remainder;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* no need to power on cmd block since it's dsi video mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
mutex_lock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 3a1a9aa..590ad65 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -231,8 +231,15 @@
return -EINVAL;
mdp4_overlay_panel_mode(MDP4_MIXER1, MDP4_PANEL_DTV);
- if (dtv_pipe != NULL)
- ret = mdp4_dtv_start(mfd);
+
+ /* Allocate dtv_pipe at dtv_on*/
+ if (dtv_pipe == NULL) {
+ if (mdp4_overlay_dtv_set(mfd, NULL)) {
+ pr_warn("%s: dtv_pipe is NULL, dtv_set failed\n",
+ __func__);
+ return -EINVAL;
+ }
+ }
ret = panel_next_on(pdev);
if (ret != 0)
@@ -527,7 +534,7 @@
*/
temp_src_format = inpdw(rgb_base + 0x0050);
MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
- mdp4_mixer_stage_up(pipe);
+ mdp4_mixer_stage_up(dtv_pipe);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
#endif
@@ -604,14 +611,6 @@
return;
mutex_lock(&mfd->dma->ov_mutex);
- if (dtv_pipe == NULL) {
- if (mdp4_overlay_dtv_set(mfd, NULL)) {
- pr_warn("%s: dtv_pipe == NULL\n", __func__);
- mutex_unlock(&mfd->dma->ov_mutex);
- return;
- }
- }
-
pipe = dtv_pipe;
if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 3dece1f..ae498fc 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -84,8 +84,11 @@
struct msm_fb_data_type *mfd;
struct mdp4_overlay_pipe *pipe;
int ret;
+ int yres, remainder;
+ struct msm_panel_info *panel_info;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -98,6 +101,17 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
if (is_mdp4_hw_reset()) {
@@ -107,8 +121,15 @@
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
if (lcdc_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -552,16 +573,36 @@
struct fb_info *fbi = mfd->fbi;
uint8 *buf;
int bpp;
+ int yres, remainder;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* no need to power on cmd block since it's lcdc mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
mutex_lock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index cd4afd0..7739837 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -394,20 +394,49 @@
temp = kzalloc(sizeof(struct msmfb_writeback_data_list),
GFP_KERNEL);
if (temp == NULL) {
- pr_err("Out of memory\n");
- goto err;
+ pr_err("%s: out of memory\n", __func__);
+ goto register_alloc_fail;
}
- temp->addr = (void *)(data->iova + data->offset);
+ if (data->iova)
+ temp->addr = (void *)(data->iova + data->offset);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ else {
+ struct ion_handle *srcp_ihdl;
+ ulong len;
+ srcp_ihdl = ion_import_fd(mfd->iclient,
+ data->memory_id);
+ if (IS_ERR_OR_NULL(srcp_ihdl)) {
+ pr_err("%s: ion import fd failed\n", __func__);
+ goto register_ion_fail;
+ }
+ if (ion_phys(mfd->iclient,
+ srcp_ihdl,
+ (ulong *)&temp->addr,
+ (size_t *)&len)) {
+ pr_err("%s: unable to get ion phys\n",
+ __func__);
+ goto register_ion_fail;
+ }
+ temp->addr += data->offset;
+ }
+#else
+ else {
+ pr_err("%s: only support ion memory\n", __func__);
+ goto register_ion_fail;
+ }
+#endif
memcpy(&temp->buf_info, data, sizeof(struct msmfb_data));
if (mdp4_overlay_writeback_register_buffer(mfd, temp)) {
- pr_err("Error registering node\n");
- kfree(temp);
- temp = NULL;
+ pr_err("%s: error registering node\n", __func__);
+ goto register_ion_fail;
}
}
-err:
return temp;
+ register_ion_fail:
+ kfree(temp);
+ register_alloc_fail:
+ return NULL;
}
int mdp4_writeback_start(
struct fb_info *info)
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index d82672e..d8a55ed 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -24,6 +24,7 @@
#include <linux/debugfs.h>
#include <linux/semaphore.h>
#include <linux/uaccess.h>
+#include <linux/msm_mdp.h>
#include <asm/system.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
@@ -295,12 +296,6 @@
bits = mdp_intr_mask;
outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
- /* histogram */
- MDP_OUTP(MDP_BASE + 0x95010, 1); /* auto clear HIST */
-
- /* enable histogram interrupts */
- outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
-
/* For the max read pending cmd config below, if the MDP clock */
/* is less than the AXI clock, then we must use 3 pending */
/* pending requests. Otherwise, we should use 8 pending requests. */
@@ -385,11 +380,8 @@
that histogram works.*/
MDP_OUTP(MDP_BASE + 0x95010, 1);
outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
- if (mdp_is_hist_start == TRUE) {
- MDP_OUTP(MDP_BASE + 0x95004,
- mdp_hist_frame_cnt);
- MDP_OUTP(MDP_BASE + 0x95000, 1);
- }
+ mdp_is_hist_valid = FALSE;
+ __mdp_histogram_reset();
}
if (isr & INTR_EXTERNAL_INTF_UDERRUN)
@@ -568,16 +560,18 @@
outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
mb();
isr &= mask;
+ if (isr & INTR_HIST_RESET_SEQ_DONE)
+ __mdp_histogram_kickoff();
+
if (isr & INTR_HIST_DONE) {
- if (waitqueue_active(&(mdp_hist_comp.wait))) {
- complete(&mdp_hist_comp);
- } else {
- if (mdp_is_hist_start == TRUE) {
- MDP_OUTP(MDP_BASE + 0x95004,
- mdp_hist_frame_cnt);
- MDP_OUTP(MDP_BASE + 0x95000, 1);
+ if (waitqueue_active(&mdp_hist_comp.wait)) {
+ if (!queue_work(mdp_hist_wq,
+ &mdp_histogram_worker)) {
+ pr_err("%s - can't queue hist_read\n",
+ __func__);
}
- }
+ } else
+ __mdp_histogram_reset();
}
}
@@ -2617,3 +2611,381 @@
}
buf->phys_addr = 0;
}
+
+static int mdp4_update_pcc_regs(uint32_t offset,
+ struct mdp_pcc_cfg_data *cfg_ptr)
+{
+ int ret = -1;
+
+ if (offset && cfg_ptr) {
+
+ outpdw(offset, cfg_ptr->r.c);
+ outpdw(offset + 0x30, cfg_ptr->g.c);
+ outpdw(offset + 0x60, cfg_ptr->b.c);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.r);
+ outpdw(offset + 0x30, cfg_ptr->g.r);
+ outpdw(offset + 0x60, cfg_ptr->b.r);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.g);
+ outpdw(offset + 0x30, cfg_ptr->g.g);
+ outpdw(offset + 0x60, cfg_ptr->b.g);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.b);
+ outpdw(offset + 0x30, cfg_ptr->g.b);
+ outpdw(offset + 0x60, cfg_ptr->b.b);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rr);
+ outpdw(offset + 0x30, cfg_ptr->g.rr);
+ outpdw(offset + 0x60, cfg_ptr->b.rr);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.gg);
+ outpdw(offset + 0x30, cfg_ptr->g.gg);
+ outpdw(offset + 0x60, cfg_ptr->b.gg);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.bb);
+ outpdw(offset + 0x30, cfg_ptr->g.bb);
+ outpdw(offset + 0x60, cfg_ptr->b.bb);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rg);
+ outpdw(offset + 0x30, cfg_ptr->g.rg);
+ outpdw(offset + 0x60, cfg_ptr->b.rg);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.gb);
+ outpdw(offset + 0x30, cfg_ptr->g.gb);
+ outpdw(offset + 0x60, cfg_ptr->b.gb);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rb);
+ outpdw(offset + 0x30, cfg_ptr->g.rb);
+ outpdw(offset + 0x60, cfg_ptr->b.rb);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rgb_0);
+ outpdw(offset + 0x30, cfg_ptr->g.rgb_0);
+ outpdw(offset + 0x60, cfg_ptr->b.rgb_0);
+ offset += 4;
+
+ outpdw(offset, cfg_ptr->r.rgb_1);
+ outpdw(offset + 0x30, cfg_ptr->g.rgb_1);
+ outpdw(offset + 0x60, cfg_ptr->b.rgb_1);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int mdp4_read_pcc_regs(uint32_t offset,
+ struct mdp_pcc_cfg_data *cfg_ptr)
+{
+ int ret = -1;
+
+ if (offset && cfg_ptr) {
+ cfg_ptr->r.c = inpdw(offset);
+ cfg_ptr->g.c = inpdw(offset + 0x30);
+ cfg_ptr->b.c = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.r = inpdw(offset);
+ cfg_ptr->g.r = inpdw(offset + 0x30);
+ cfg_ptr->b.r = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.g = inpdw(offset);
+ cfg_ptr->g.g = inpdw(offset + 0x30);
+ cfg_ptr->b.g = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.b = inpdw(offset);
+ cfg_ptr->g.b = inpdw(offset + 0x30);
+ cfg_ptr->b.b = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rr = inpdw(offset);
+ cfg_ptr->g.rr = inpdw(offset + 0x30);
+ cfg_ptr->b.rr = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.gg = inpdw(offset);
+ cfg_ptr->g.gg = inpdw(offset + 0x30);
+ cfg_ptr->b.gg = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.bb = inpdw(offset);
+ cfg_ptr->g.bb = inpdw(offset + 0x30);
+ cfg_ptr->b.bb = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rg = inpdw(offset);
+ cfg_ptr->g.rg = inpdw(offset + 0x30);
+ cfg_ptr->b.rg = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.gb = inpdw(offset);
+ cfg_ptr->g.gb = inpdw(offset + 0x30);
+ cfg_ptr->b.gb = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rb = inpdw(offset);
+ cfg_ptr->g.rb = inpdw(offset + 0x30);
+ cfg_ptr->b.rb = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rgb_0 = inpdw(offset);
+ cfg_ptr->g.rgb_0 = inpdw(offset + 0x30);
+ cfg_ptr->b.rgb_0 = inpdw(offset + 0x60);
+ offset += 4;
+
+ cfg_ptr->r.rgb_1 = inpdw(offset);
+ cfg_ptr->g.rgb_1 = inpdw(offset + 0x30);
+ cfg_ptr->b.rgb_1 = inpdw(offset + 0x60);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+#define MDP_DMA_P_BASE 0x90000
+#define MDP_DMA_S_BASE 0xA0000
+
+#define MDP_PCC_OFFSET 0xA000
+
+#define MDP_DMA_P_OP_MODE_OFFSET 0x70
+#define MDP_DMA_S_OP_MODE_OFFSET 0x28
+
+
+#define DMA_PCC_R2_OFFSET 0x100
+
+int mdp4_pcc_cfg(struct mdp_pcc_cfg_data *cfg_ptr)
+{
+ int ret = -1;
+ uint32_t pcc_offset = 0, mdp_cfg_offset = 0;
+ uint32_t mdp_dma_op_mode = 0;
+
+ switch (cfg_ptr->block) {
+ case MDP_BLOCK_DMA_P:
+ pcc_offset = (uint32_t) (MDP_BASE + MDP_DMA_P_BASE \
+ + MDP_PCC_OFFSET);
+ mdp_cfg_offset = (uint32_t)(MDP_BASE + MDP_DMA_P_BASE);
+ mdp_dma_op_mode = (uint32_t)(MDP_BASE + MDP_DMA_P_BASE \
+ + MDP_DMA_P_OP_MODE_OFFSET);
+ break;
+
+ case MDP_BLOCK_DMA_S:
+ pcc_offset = (uint32_t)(MDP_BASE + MDP_DMA_S_BASE \
+ + MDP_PCC_OFFSET);
+ mdp_cfg_offset = (uint32_t)(MDP_BASE + MDP_DMA_S_BASE);
+ mdp_dma_op_mode = (uint32_t)(MDP_BASE + MDP_DMA_S_BASE \
+ + MDP_DMA_S_OP_MODE_OFFSET);
+ break;
+
+ default:
+ break;
+ }
+
+ if (0x8 & cfg_ptr->ops)
+ pcc_offset += DMA_PCC_R2_OFFSET;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ switch ((0x6 & cfg_ptr->ops)>>1) {
+ case 0x1:
+ ret = mdp4_read_pcc_regs(pcc_offset, cfg_ptr);
+ break;
+
+ case 0x2:
+ ret = mdp4_update_pcc_regs(pcc_offset, cfg_ptr);
+ break;
+
+ default:
+ break;
+ }
+
+ if (0x8 & cfg_ptr->ops)
+ outpdw(mdp_dma_op_mode,
+ (inpdw(mdp_dma_op_mode)|((0x8&cfg_ptr->ops)<<10)));
+
+ outpdw(mdp_cfg_offset,
+ (inpdw(mdp_cfg_offset)|((cfg_ptr->ops&0x1)<<29)));
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+#define MDP_DMA_GC_OFFSET 0x8800
+
+#define MDP_LM_0_BASE 0x10004
+#define MDP_LM_1_BASE 0x18004
+#define MDP_LM_GC_OFFSET 0x47ec
+
+#define MDP_LM_OP_MODE_OFFSET 0x10
+
+#define MDP_DMA_P_CONFIG_OFFSET MDP_DMA_P_BASE
+#define MDP_DMA_S_CONFIG_OFFSET MDP_DMA_S_BASE
+#define MDP_LM_0_OP_MODE_OFFSET (MDP_LM_0_BASE + MDP_LM_OP_MODE_OFFSET)
+#define MDP_LM_1_OP_MODE_OFFSET (MDP_LM_1_BASE + MDP_LM_OP_MODE_OFFSET)
+
+#define MDP_GC_COLOR_OFFSET 0x100
+#define MDP_GC_PARMS_OFFSET 0x80
+
+#define MDP_AR_GC_MAX_STAGES 16
+
+static int update_ar_gc_lut(uint32_t *offset, struct mdp_pgc_lut_data *lut_data)
+{
+ int ret = -1, count = 0;
+
+ uint32_t *c0_offset = offset;
+ uint32_t *c0_params_offset = (uint32_t *)((uint32_t)c0_offset
+ + MDP_GC_PARMS_OFFSET);
+
+ uint32_t *c1_offset = (uint32_t *)((uint32_t)offset
+ + MDP_GC_COLOR_OFFSET);
+
+ uint32_t *c1_params_offset = (uint32_t *)((uint32_t)c1_offset
+ + MDP_GC_PARMS_OFFSET);
+
+ uint32_t *c2_offset = (uint32_t *)((uint32_t)offset
+ + 2*MDP_GC_COLOR_OFFSET);
+
+ uint32_t *c2_params_offset = (uint32_t *)((uint32_t)c2_offset
+ +MDP_GC_PARMS_OFFSET);
+
+
+ for (count = 0; count < MDP_AR_GC_MAX_STAGES; count++) {
+ if (count < lut_data->num_r_stages) {
+ outpdw(c0_offset+count,
+ ((0xfff & lut_data->r_data[count].x_start)
+ | 0x10000));
+
+ outpdw(c0_params_offset+count,
+ ((0x7fff & lut_data->r_data[count].slope)
+ | ((0xffff
+ & lut_data->r_data[count].offset)
+ << 16)));
+ } else
+ outpdw(c0_offset+count, 0);
+
+ if (count < lut_data->num_b_stages) {
+ outpdw(c1_offset+count,
+ ((0xfff & lut_data->b_data[count].x_start)
+ | 0x10000));
+
+ outpdw(c1_params_offset+count,
+ ((0x7fff & lut_data->b_data[count].slope)
+ | ((0xffff
+ & lut_data->b_data[count].offset)
+ << 16)));
+ } else
+ outpdw(c1_offset+count, 0);
+
+ if (count < lut_data->num_g_stages) {
+ outpdw(c2_offset+count,
+ ((0xfff & lut_data->g_data[count].x_start)
+ | 0x10000));
+
+ outpdw(c2_params_offset+count,
+ ((0x7fff & lut_data->g_data[count].slope)
+ | ((0xffff
+ & lut_data->g_data[count].offset)
+ << 16)));
+ } else
+ outpdw(c2_offset+count, 0);
+ }
+
+ ret = 0;
+
+ return ret;
+}
+
+int mdp4_pgc_cfg(struct mdp_pgc_lut_data *pgc_ptr)
+{
+ int ret = 0;
+ uint32_t *offset = 0, *pgc_enable_offset = 0, lshift_bits = 0;
+ struct mdp_ar_gc_lut_data r[MDP_AR_GC_MAX_STAGES];
+ struct mdp_ar_gc_lut_data g[MDP_AR_GC_MAX_STAGES];
+ struct mdp_ar_gc_lut_data b[MDP_AR_GC_MAX_STAGES];
+
+ ret = copy_from_user(&r[0], pgc_ptr->r_data,
+ pgc_ptr->num_r_stages*sizeof(struct mdp_ar_gc_lut_data));
+ if (!ret) {
+ ret = copy_from_user(&g[0],
+ pgc_ptr->g_data,
+ pgc_ptr->num_g_stages
+ * sizeof(struct mdp_ar_gc_lut_data));
+ if (!ret)
+ ret = copy_from_user(&b[0],
+ pgc_ptr->b_data,
+ pgc_ptr->num_b_stages
+ * sizeof(struct mdp_ar_gc_lut_data));
+ }
+
+ if (ret)
+ return ret;
+
+ pgc_ptr->r_data = &r[0];
+ pgc_ptr->g_data = &g[0];
+ pgc_ptr->b_data = &b[0];
+
+ switch (pgc_ptr->block) {
+ case MDP_BLOCK_DMA_P:
+ offset = (uint32_t *)(MDP_BASE + MDP_DMA_P_BASE
+ + MDP_DMA_GC_OFFSET);
+ pgc_enable_offset = (uint32_t *)(MDP_BASE
+ + MDP_DMA_P_CONFIG_OFFSET);
+ lshift_bits = 28;
+ break;
+
+ case MDP_BLOCK_DMA_S:
+ offset = (uint32_t *)(MDP_BASE + MDP_DMA_S_BASE
+ + MDP_DMA_GC_OFFSET);
+ pgc_enable_offset = (uint32_t *)(MDP_BASE
+ + MDP_DMA_S_CONFIG_OFFSET);
+ lshift_bits = 28;
+ break;
+
+ case MDP_BLOCK_OVERLAY_0:
+ offset = (uint32_t *)(MDP_BASE + MDP_LM_0_BASE
+ + MDP_LM_GC_OFFSET);
+ pgc_enable_offset = (uint32_t *)(MDP_BASE
+ + MDP_LM_0_OP_MODE_OFFSET);
+ lshift_bits = 2;
+ break;
+
+ case MDP_BLOCK_OVERLAY_1:
+ offset = (uint32_t *)(MDP_BASE + MDP_LM_1_BASE
+ + MDP_LM_GC_OFFSET);
+ pgc_enable_offset = (uint32_t *)(MDP_BASE
+ + MDP_LM_0_OP_MODE_OFFSET);
+ lshift_bits = 2;
+ break;
+
+ default:
+ ret = -1;
+ break;
+ }
+
+ if (!ret) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ ret = update_ar_gc_lut(offset, pgc_ptr);
+ if (!ret)
+ outpdw(pgc_enable_offset, (inpdw(pgc_enable_offset)
+ |(1<<lshift_bits)));
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+
+ return ret;
+}
+
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index 3997814..e8b288f 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -522,14 +522,37 @@
boolean sync)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct fb_info *fbi = mfd->fbi;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
MDPIBUF *iBuf;
int bpp = info->var.bits_per_pixel / 8;
+ int yres, remainder;
+
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
down(&mfd->sem);
+
iBuf = &mfd->ibuf;
iBuf->buf = (uint8 *) info->fix.smem_start;
- iBuf->buf += info->var.xoffset * bpp +
- info->var.yoffset * info->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ iBuf->buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ iBuf->buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ iBuf->buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
iBuf->ibuf_width = info->var.xres_virtual;
iBuf->bpp = bpp;
diff --git a/drivers/video/msm/mdp_dma_dsi_video.c b/drivers/video/msm/mdp_dma_dsi_video.c
index 505eb74..0e76a07 100644
--- a/drivers/video/msm/mdp_dma_dsi_video.c
+++ b/drivers/video/msm/mdp_dma_dsi_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -67,14 +67,17 @@
int hsync_end_x;
uint8 *buf;
uint32 dma2_cfg_reg;
+ int yres, remainder;
int bpp;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct msm_fb_data_type *mfd;
+ struct msm_panel_info *panel_info;
int ret;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -85,10 +88,29 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_DSI_VIDEO;
@@ -239,17 +261,38 @@
uint8 *buf;
int bpp;
unsigned long flag;
+ int yres, remainder;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
int irq_block = MDP_DMA2_TERM;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
down(&mfd->dma->mutex);
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
/* no need to power on cmd block since it's dsi mode */
/* starting address */
MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x8, (uint32) buf);
diff --git a/drivers/video/msm/mdp_dma_lcdc.c b/drivers/video/msm/mdp_dma_lcdc.c
index 9ce7e13..5dada35 100644
--- a/drivers/video/msm/mdp_dma_lcdc.c
+++ b/drivers/video/msm/mdp_dma_lcdc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 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
@@ -89,12 +89,15 @@
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct msm_fb_data_type *mfd;
+ struct msm_panel_info *panel_info;
uint32 dma_base;
uint32 timer_base = LCDC_BASE;
uint32 block = MDP_DMA2_BLOCK;
int ret;
+ int yres, remainder;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -105,12 +108,32 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_LCDC;
@@ -299,6 +322,7 @@
}
#endif
+ down(&mfd->dma->mutex);
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
MDP_OUTP(MDP_BASE + timer_base, 0);
@@ -307,6 +331,7 @@
mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
ret = panel_next_off(pdev);
+ up(&mfd->dma->mutex);
/* delay to make sure the last frame finishes */
msleep(16);
@@ -317,23 +342,45 @@
void mdp_lcdc_update(struct msm_fb_data_type *mfd)
{
struct fb_info *fbi = mfd->fbi;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
uint8 *buf;
int bpp;
unsigned long flag;
uint32 dma_base;
+ int yres, remainder;
int irq_block = MDP_DMA2_TERM;
#ifdef CONFIG_FB_MSM_MDP40
int intr = INTR_DMA_P_DONE;
#endif
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
if (!mfd->panel_power_on)
return;
+ down(&mfd->dma->mutex);
/* no need to power on cmd block since it's lcdc mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
dma_base = DMA_P_BASE;
@@ -365,4 +412,5 @@
spin_unlock_irqrestore(&mdp_spin_lock, flag);
wait_for_completion_killable(&mfd->dma->comp);
mdp_disable_irq(irq_block);
+ up(&mfd->dma->mutex);
}
diff --git a/drivers/video/msm/mdp_dma_tv.c b/drivers/video/msm/mdp_dma_tv.c
index 66d9422..1305e03 100644
--- a/drivers/video/msm/mdp_dma_tv.c
+++ b/drivers/video/msm/mdp_dma_tv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 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
@@ -39,12 +39,15 @@
int mdp_dma3_on(struct platform_device *pdev)
{
struct msm_fb_data_type *mfd;
+ struct msm_panel_info *panel_info;
struct fb_info *fbi;
uint8 *buf;
int bpp;
int ret = 0;
+ int yres, remainder;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -53,13 +56,33 @@
return -EINVAL;
fbi = mfd->fbi;
+
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
/* starting address[31..8] of Video frame buffer is CS0 */
MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
@@ -112,15 +135,37 @@
uint8 *buf;
int bpp;
unsigned long flag;
+ int yres, remainder;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* no need to power on cmd block since dma3 is running */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
+
MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
spin_lock_irqsave(&mdp_spin_lock, flag);
diff --git a/drivers/video/msm/mdp_hw_init.c b/drivers/video/msm/mdp_hw_init.c
index 8f8b4d3..ff3ad41 100644
--- a/drivers/video/msm/mdp_hw_init.c
+++ b/drivers/video/msm/mdp_hw_init.c
@@ -635,8 +635,6 @@
MDP_OUTP(MDP_BASE + 0xE0000, 0);
MDP_OUTP(MDP_BASE + 0x100, 0xffffffff);
MDP_OUTP(MDP_BASE + 0x90070, 0);
- MDP_OUTP(MDP_BASE + 0x94010, 1);
- MDP_OUTP(MDP_BASE + 0x9401c, 2);
#endif
/*
diff --git a/drivers/video/msm/mipi_chimei_wuxga.c b/drivers/video/msm/mipi_chimei_wuxga.c
index c63df46..7abb0d4 100644
--- a/drivers/video/msm/mipi_chimei_wuxga.c
+++ b/drivers/video/msm/mipi_chimei_wuxga.c
@@ -55,12 +55,12 @@
/* DSIPHY_TIMING_CTRL */
.timing = { 0xC9, 0x92, 0x29, /* panel specific */
0, /* DSIPHY_TIMING_CTRL_3 = 0 */
- 0x2E, 0x9B, 0x2C, 0x94, 0x2E, 0x03, 0x04}, /* panel specific */
+ 0x2D, 0x9B, 0x2B, 0x94, 0x2D, 0x03, 0x04}, /* panel specific */
/* DSIPHY_PLL_CTRL */
.pll = { 0x00, /* common 8960 */
/* VCO */
- 0x32, (0x01 | 0x30) , (0x19 | 0xC0), /* panel specific */
+ 0x30, (0x01 | 0x30) , (0x19 | 0xC0), /* panel specific */
0x00, 0x50, 0x48, 0x63,
0x77, 0x88, 0x99, /* Auto update by dsi-mipi driver */
0x00, 0x14, 0x03, 0x00, 0x02, /* common 8960 */
@@ -104,19 +104,19 @@
* LVDS-CLK = DSI-CLK/4 , 320 MHZ/4= 80 MHZ.
*/
- pinfo->clk_rate = 640 * MHZ ; /* bitclk Calculated */
+ pinfo->clk_rate = 635 * MHZ ; /* bitclk Calculated */
/*
* this panel is operated by DE,
* vsycn and hsync are ignored
*/
- pinfo->lcdc.h_front_porch = 16; /* thfp */
- pinfo->lcdc.h_back_porch = 160; /* thb */
+ pinfo->lcdc.h_front_porch = 160-48-32; /* thfp */
+ pinfo->lcdc.h_back_porch = 48; /* thb */
pinfo->lcdc.h_pulse_width = 32; /* thpw */
- pinfo->lcdc.v_front_porch = 0; /* tvfp */
- pinfo->lcdc.v_back_porch = 26; /* tvb */
+ pinfo->lcdc.v_front_porch = 26-3-6; /* tvfp */
+ pinfo->lcdc.v_back_porch = 3; /* tvb */
pinfo->lcdc.v_pulse_width = 6; /* tvpw */
pinfo->lcdc.border_clr = 0; /* black */
@@ -138,7 +138,7 @@
pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
/* Four lanes are recomended for 1920x1200 at 60 frames per second */
- pinfo->mipi.frame_rate = 45; /* 45 frames per second */
+ pinfo->mipi.frame_rate = 60;
pinfo->mipi.data_lane0 = true;
pinfo->mipi.data_lane1 = true;
pinfo->mipi.data_lane2 = true;
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 9907109..4fbb044 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -50,7 +50,8 @@
#define MIPI_DSI_PANEL_WSVGA_PT 4
#define MIPI_DSI_PANEL_QHD_PT 5
#define MIPI_DSI_PANEL_WXGA 6
-#define DSI_PANEL_MAX 6
+#define MIPI_DSI_PANEL_WUXGA 7
+#define DSI_PANEL_MAX 7
enum { /* mipi dsi panel */
DSI_VIDEO_MODE,
diff --git a/drivers/video/msm/mipi_toshiba.c b/drivers/video/msm/mipi_toshiba.c
index 5788f27..2db8bcf 100644
--- a/drivers/video/msm/mipi_toshiba.c
+++ b/drivers/video/msm/mipi_toshiba.c
@@ -196,7 +196,8 @@
mipi_dsi_cmds_tx(mfd, &toshiba_tx_buf,
toshiba_wvga_display_on_cmds,
ARRAY_SIZE(toshiba_wvga_display_on_cmds));
- else if (TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WSVGA_PT)
+ else if (TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WSVGA_PT ||
+ TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WUXGA)
mipi_dsi_cmds_tx(mfd, &toshiba_tx_buf,
toshiba_wsvga_display_on_cmds,
ARRAY_SIZE(toshiba_wsvga_display_on_cmds));
diff --git a/drivers/video/msm/mipi_toshiba_video_wuxga.c b/drivers/video/msm/mipi_toshiba_video_wuxga.c
new file mode 100644
index 0000000..297248f
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba_video_wuxga.c
@@ -0,0 +1,97 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_toshiba.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* 1920*1200, RGB888, 4 Lane 60 fps video mode */
+ /* regulator */
+ {0x03, 0x0a, 0x04, 0x00, 0x20},
+ /* timing */
+ {0x66, 0x26, 0x1F, 0x00, 0x55, 0x9C, 0x16, 0x90,
+ 0x23, 0x03, 0x04, 0xa0},
+ /* phy ctrl */
+ {0x5f, 0x00, 0x00, 0x10},
+ /* strength */
+ {0xff, 0x00, 0x06, 0x00},
+ /* pll control */
+ {0x0, 0xD7, 0x1, 0x19, 0x00, 0x50, 0x48, 0x63,
+ 0x41, 0x0f, 0x01,
+ 0x00, 0x14, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01 },
+};
+
+static int __init mipi_video_toshiba_wuxga_init(void)
+{
+ int ret;
+
+ if (msm_fb_detect_client("mipi_video_toshiba_wuxga"))
+ return 0;
+
+ pinfo.xres = 1920;
+ pinfo.yres = 1200;
+
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 50;
+ pinfo.lcdc.h_front_porch = 50;
+ pinfo.lcdc.h_pulse_width = 170;
+ pinfo.lcdc.v_back_porch = 7;
+ pinfo.lcdc.v_front_porch = 8;
+ pinfo.lcdc.v_pulse_width = 30;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = MIPI_TOSHIBA_PWM_LEVEL;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 981560000;
+
+ pinfo.mipi.mode = DSI_VIDEO_MODE;
+ pinfo.mipi.pulse_mode_hsa_he = TRUE;
+ pinfo.mipi.hfp_power_stop = FALSE;
+ pinfo.mipi.hbp_power_stop = FALSE;
+ pinfo.mipi.hsa_power_stop = FALSE;
+ pinfo.mipi.eof_bllp_power_stop = TRUE;
+ pinfo.mipi.bllp_power_stop = TRUE;
+ pinfo.mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+ pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_BGR;
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.data_lane1 = TRUE;
+ pinfo.mipi.data_lane2 = TRUE;
+ pinfo.mipi.data_lane3 = TRUE;
+ pinfo.mipi.tx_eot_append = TRUE;
+ pinfo.mipi.t_clk_post = 0x04;
+ pinfo.mipi.t_clk_pre = 0x1c;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.frame_rate = 60;
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+ ret = mipi_toshiba_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WUXGA);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_toshiba_wuxga_init);
diff --git a/drivers/video/msm/mipi_truly_video_wvga_pt.c b/drivers/video/msm/mipi_truly_video_wvga_pt.c
index 931c564..03ef32b 100644
--- a/drivers/video/msm/mipi_truly_video_wvga_pt.c
+++ b/drivers/video/msm/mipi_truly_video_wvga_pt.c
@@ -38,10 +38,8 @@
{
int ret;
-#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
if (msm_fb_detect_client("mipi_video_truly_wvga"))
return 0;
-#endif
pinfo.xres = 480;
pinfo.yres = 800;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 489e6d2..69e0423 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -606,6 +606,7 @@
return 0;
}
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
static int msm_fb_ext_suspend(struct device *dev)
{
struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
@@ -635,13 +636,16 @@
return ret;
}
+#endif
static struct dev_pm_ops msm_fb_dev_pm_ops = {
.runtime_suspend = msm_fb_runtime_suspend,
.runtime_resume = msm_fb_runtime_resume,
.runtime_idle = msm_fb_runtime_idle,
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
.suspend = msm_fb_ext_suspend,
.resume = msm_fb_ext_resume,
+#endif
};
static struct platform_driver msm_fb_driver = {
@@ -969,6 +973,7 @@
struct fb_var_screeninfo *var;
int *id;
int fbram_offset;
+ int remainder, remainder_mode2;
/*
* fb info initialization
@@ -1105,15 +1110,28 @@
fix->line_length = msm_fb_line_length(mfd->index, panel_info->xres,
bpp);
+
+ /* Make sure all buffers can be addressed on a page boundary by an x
+ * and y offset */
+
+ remainder = (fix->line_length * panel_info->yres) % PAGE_SIZE;
+ if (!remainder)
+ remainder = PAGE_SIZE;
+ remainder_mode2 = (fix->line_length *
+ panel_info->mode2_yres) % PAGE_SIZE;
+ if (!remainder_mode2)
+ remainder_mode2 = PAGE_SIZE;
+
/* calculate smem_len based on max size of two supplied modes */
- fix->smem_len = roundup(MAX(msm_fb_line_length(mfd->index,
- panel_info->xres,
- bpp) *
- panel_info->yres * mfd->fb_page,
- msm_fb_line_length(mfd->index,
+ fix->smem_len = MAX((msm_fb_line_length(mfd->index, panel_info->xres,
+ bpp) *
+ panel_info->yres + PAGE_SIZE -
+ remainder) * mfd->fb_page,
+ (msm_fb_line_length(mfd->index,
panel_info->mode2_xres,
bpp) *
- panel_info->mode2_yres * mfd->fb_page), PAGE_SIZE);
+ panel_info->mode2_yres + PAGE_SIZE -
+ remainder_mode2) * mfd->fb_page);
@@ -2914,6 +2932,50 @@
return 0;
}
+static int msmfb_handle_pp_ioctl(struct msmfb_mdp_pp *pp_ptr)
+{
+ int ret = -1;
+
+ if (!pp_ptr)
+ return ret;
+
+ switch (pp_ptr->op) {
+#ifdef CONFIG_FB_MSM_MDP40
+ case mdp_op_csc_cfg:
+ ret = mdp4_csc_config(&(pp_ptr->data.csc_cfg_data));
+ break;
+
+ case mdp_op_pcc_cfg:
+ ret = mdp4_pcc_cfg(&(pp_ptr->data.pcc_cfg_data));
+ break;
+
+ case mdp_op_lut_cfg:
+ switch (pp_ptr->data.lut_cfg_data.lut_type) {
+ case mdp_lut_igc:
+ break;
+
+ case mdp_lut_pgc:
+ ret = mdp4_pgc_cfg(
+ &pp_ptr->data.lut_cfg_data.data.pgc_lut_data);
+ break;
+
+ case mdp_lut_hist:
+ break;
+
+ default:
+ break;
+ }
+ break;
+#endif
+ default:
+ pr_warn("Unsupported request to MDP_PP IOCTL.\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
@@ -3207,28 +3269,15 @@
ret = -EINVAL;
#endif
break;
+
case MSMFB_MDP_PP:
ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
if (ret)
return ret;
- switch (mdp_pp.op) { /*Add PCC and LUT op handling here*/
-#ifdef CONFIG_FB_MSM_MDP40
- case mdp_op_csc_cfg:
- ret = mdp4_csc_config((struct mdp_csc_cfg_data *)
- &(mdp_pp.data));
- break;
- case mdp_op_pcc_cfg:
- case mdp_op_lut_cfg:
-#endif
- default:
- pr_warn("%s: Only CSC supported by MDP_PP IOCTL.\n",
- __func__);
- ret = -EINVAL;
- break;
- }
-
+ ret = msmfb_handle_pp_ioctl(&mdp_pp);
break;
+
default:
MSM_FB_INFO("MDP: unknown ioctl (cmd=%x) received!\n", cmd);
ret = -EINVAL;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
index 51a0d13..433dad4 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,8 +14,8 @@
#ifndef _VCD_DDL_API_H_
#define _VCD_DDL_API_H_
+#include <media/msm/vcd_api.h>
#include "vidc.h"
-#include "vcd_api.h"
#define VCD_EVT_RESP_DDL_BASE 0x3000
#define VCD_EVT_RESP_DEVICE_INIT (VCD_EVT_RESP_DDL_BASE + 0x1)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
index 42a991c..10b3404 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,7 +15,7 @@
#define _VCD_DDL_UTILS_H_
#include <linux/delay.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
extern u32 vidc_msg_pmem;
extern u32 vidc_msg_timing;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
index f63ebcd..a5a8e57 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
@@ -24,8 +24,8 @@
#define VIDC_REG_IN(x...)
#endif
-#define __inpdw(port) (*((u32 *) (port)))
-#define __outpdw(port, val) (*((u32 *) (port)) = ((u32) (val)))
+#define __inpdw(port) __raw_readl(port)
+#define __outpdw(port, val) __raw_writel(val, port)
#define in_dword(addr) (__inpdw(addr))
#define in_dword_masked(addr, mask) (__inpdw(addr) & (mask))
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index c32ac81..8851b52 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -21,9 +21,9 @@
#include <linux/interrupt.h>
#include <linux/memory_alloc.h>
#include <asm/sizes.h>
+#include <media/msm/vidc_init.h>
#include "vidc.h"
#include "vcd_res_tracker.h"
-#include "vidc_init.h"
static unsigned int vidc_clk_table[3] = {
48000000, 133330000, 200000000
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
index 7c68d63..02b2369 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
#include "vcd_res_tracker_api.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
index eb08b7e..ac5bce9 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
index 25aa6bc..965c3aa 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_firmware.h"
#include "vcd_ddl_utils.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
index 7952dfb..a136de8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
*/
#ifndef _VCD_DDL_FIRMWARE_H_
#define _VCD_DDL_FIRMWARE_H_
-#include "vcd_property.h"
+#include <media/msm/vcd_property.h>
#define VCD_FW_BIG_ENDIAN 0x0
#define VCD_FW_LITTLE_ENDIAN 0x1
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
index f09bd71..6a69955 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
index 2ec8419..15adf21 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
DDL_INLINE struct ddl_context *ddl_get_context(void)
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
index 00c00cd..9dc495b 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
*/
#ifndef _VCD_DDL_INTERNAL_PROPERTY_H_
#define _VCD_DDL_INTERNAL_PROPERTY_H_
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
#define VCD_EVT_RESP_DDL_BASE 0x3000
#define VCD_EVT_RESP_DEVICE_INIT (VCD_EVT_RESP_DDL_BASE + 0x1)
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
index ece4c30..fe71dc1 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vidc.h"
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
index 376ea6d..2a74da8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
index 6d3c666..3aebdaf 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl_metadata.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index c8ea83f..17dedb8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
#include <linux/memory_alloc.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_ddl_utils.h"
#if DEBUG
diff --git a/drivers/video/msm/vidc/720p/ddl/vidc.c b/drivers/video/msm/vidc/720p/ddl/vidc.c
index 0f5932a..de6cbbb 100644
--- a/drivers/video/msm/vidc/720p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/720p/ddl/vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,8 +12,8 @@
*/
#include <linux/unistd.h>
+#include <media/msm/vidc_type.h>
#include "vidc.h"
-#include "vidc_type.h"
#if DEBUG
#define DBG(x...) printk(KERN_DEBUG x)
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index 522ff16..86bf397 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -16,9 +16,9 @@
#include <linux/regulator/consumer.h>
#include <mach/clk.h>
#include <linux/interrupt.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_init.h>
+#include <media/msm/vidc_type.h>
#include "vcd_res_tracker.h"
-#include "vidc_init.h"
#define MSM_AXI_QOS_NAME "msm_vidc_reg"
#define AXI_CLK_SCALING
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index b300fbc..bfaac82 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -29,11 +29,11 @@
#include <linux/clk.h>
#include <linux/timer.h>
#include <mach/msm_subsystem_map.h>
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
#include "vcd_res_tracker_api.h"
-#include "vidc_type.h"
-#include "vcd_api.h"
#include "vdec_internal.h"
-#include "vidc_init.h"
@@ -2111,8 +2111,10 @@
struct video_client_ctx *client_ctx = file->private_data;
INFO("msm_vidc_dec: Inside %s()", __func__);
- res_trk_close_secure_session();
+ vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
+ vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
vid_dec_close_client(client_ctx);
+ res_trk_close_secure_session();
vidc_release_firmware();
#ifndef USE_RES_TRACKER
vidc_disable_clk();
@@ -2125,13 +2127,15 @@
{
struct video_client_ctx *client_ctx = file->private_data;
- DBG("msm_vidc_dec: Inside %s()", __func__);
+ INFO("msm_vidc_dec: Inside %s()", __func__);
+ vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
+ vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
vid_dec_close_client(client_ctx);
vidc_release_firmware();
#ifndef USE_RES_TRACKER
vidc_disable_clk();
#endif
- DBG("msm_vidc_dec: Return from %s()", __func__);
+ INFO("msm_vidc_dec: Return from %s()", __func__);
return 0;
}
diff --git a/drivers/video/msm/vidc/common/dec/vdec_internal.h b/drivers/video/msm/vidc/common/dec/vdec_internal.h
index f310e25..89da9a2 100644
--- a/drivers/video/msm/vidc/common/dec/vdec_internal.h
+++ b/drivers/video/msm/vidc/common/dec/vdec_internal.h
@@ -16,7 +16,7 @@
#include <linux/msm_vidc_dec.h>
#include <linux/cdev.h>
-#include "vidc_init.h"
+#include <media/msm/vidc_init.h>
#define NUM_OF_DRIVER_NODES 2
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index cc6606c..6d6dcdc 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -27,11 +27,11 @@
#include <linux/workqueue.h>
#include <linux/android_pmem.h>
#include <linux/clk.h>
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
-#include "vidc_type.h"
-#include "vcd_api.h"
#include "venc_internal.h"
-#include "vidc_init.h"
#include "vcd_res_tracker_api.h"
#define VID_ENC_NAME "msm_vidc_enc"
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index e3bb9db..f362f7b 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -28,10 +28,10 @@
#include <linux/android_pmem.h>
#include <linux/clk.h>
#include <mach/msm_subsystem_map.h>
-#include "vidc_type.h"
-#include "vcd_api.h"
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
#include "venc_internal.h"
-#include "vidc_init.h"
#if DEBUG
#define DBG(x...) printk(KERN_DEBUG x)
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h
index 2b5a532..a07f7ab 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.h
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,8 +16,7 @@
#include <linux/msm_vidc_enc.h>
#include <linux/cdev.h>
-
-#include "vidc_init.h"
+#include <media/msm/vidc_init.h>
#define VID_ENC_MAX_NUM_OF_BUFF 100
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index cd3f954..0ea64d4 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -31,9 +31,9 @@
#include <mach/clk.h>
#include <linux/pm_runtime.h>
#include <mach/msm_subsystem_map.h>
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
+#include <media/msm/vidc_init.h>
#include "vidc_init_internal.h"
-#include "vidc_init.h"
#include "vcd_res_tracker_api.h"
#if DEBUG
@@ -384,6 +384,59 @@
}
EXPORT_SYMBOL(vidc_get_fd_info);
+void vidc_cleanup_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer)
+{
+ u32 *num_of_buffers = NULL;
+ u32 i = 0;
+ struct buf_addr_table *buf_addr_table;
+ if (buffer == BUFFER_TYPE_INPUT) {
+ buf_addr_table = client_ctx->input_buf_addr_table;
+ num_of_buffers = &client_ctx->num_of_input_buffers;
+ DBG("%s(): buffer = INPUT\n", __func__);
+
+ } else {
+ buf_addr_table = client_ctx->output_buf_addr_table;
+ num_of_buffers = &client_ctx->num_of_output_buffers;
+ DBG("%s(): buffer = OUTPUT\n", __func__);
+ }
+
+ if (!*num_of_buffers)
+ goto bail_out_cleanup;
+ if (!client_ctx->user_ion_client)
+ goto bail_out_cleanup;
+ for (i = 0; i < *num_of_buffers; ++i) {
+ if (buf_addr_table[i].client_data) {
+ msm_subsystem_unmap_buffer(
+ (struct msm_mapped_buffer *)
+ buf_addr_table[i].client_data);
+ buf_addr_table[i].client_data = NULL;
+ }
+ if (buf_addr_table[i].buff_ion_handle) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ buf_addr_table[i].buff_ion_handle);
+ ion_free(client_ctx->user_ion_client,
+ buf_addr_table[i].buff_ion_handle);
+ buf_addr_table[i].buff_ion_handle = NULL;
+ }
+ }
+ if (client_ctx->vcd_h264_mv_buffer.client_data) {
+ msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+ client_ctx->vcd_h264_mv_buffer.client_data);
+ client_ctx->vcd_h264_mv_buffer.client_data = NULL;
+ }
+ if (client_ctx->h264_mv_ion_handle) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ client_ctx->h264_mv_ion_handle = NULL;
+ }
+bail_out_cleanup:
+ return;
+}
+EXPORT_SYMBOL(vidc_cleanup_addr_table);
+
u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
enum buffer_dir buffer,
u32 search_with_user_vaddr,
@@ -540,9 +593,10 @@
client_ctx->user_ion_client,
buff_ion_handle,
ionflag);
- if (!(*kernel_vaddr)) {
+ if (IS_ERR_OR_NULL((void *)*kernel_vaddr)) {
ERR("%s():ION virtual addr fail\n",
__func__);
+ *kernel_vaddr = (unsigned long)NULL;
goto ion_error;
}
if (ion_phys(client_ctx->user_ion_client,
@@ -587,7 +641,7 @@
mutex_unlock(&client_ctx->enrty_queue_lock);
return true;
ion_error:
- if (*kernel_vaddr)
+ if (*kernel_vaddr && buff_ion_handle)
ion_unmap_kernel(client_ctx->user_ion_client, buff_ion_handle);
if (!IS_ERR_OR_NULL(buff_ion_handle))
ion_free(client_ctx->user_ion_client, buff_ion_handle);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.h b/drivers/video/msm/vidc/common/init/vidc_init.h
deleted file mode 100644
index ced99ff..0000000
--- a/drivers/video/msm/vidc/common/init/vidc_init.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef VIDC_INIT_H
-#define VIDC_INIT_H
-#include <linux/ion.h>
-#include "vidc_type.h"
-
-#define VIDC_MAX_NUM_CLIENTS 4
-#define MAX_VIDEO_NUM_OF_BUFF 100
-
-enum buffer_dir {
- BUFFER_TYPE_INPUT,
- BUFFER_TYPE_OUTPUT
-};
-
-struct buf_addr_table {
- unsigned long user_vaddr;
- unsigned long kernel_vaddr;
- unsigned long phy_addr;
- unsigned long buff_ion_flag;
- struct ion_handle *buff_ion_handle;
- int pmem_fd;
- struct file *file;
- unsigned long dev_addr;
- void *client_data;
-};
-
-struct video_client_ctx {
- void *vcd_handle;
- u32 num_of_input_buffers;
- u32 num_of_output_buffers;
- struct buf_addr_table input_buf_addr_table[MAX_VIDEO_NUM_OF_BUFF];
- struct buf_addr_table output_buf_addr_table[MAX_VIDEO_NUM_OF_BUFF];
- struct list_head msg_queue;
- struct mutex msg_queue_lock;
- struct mutex enrty_queue_lock;
- wait_queue_head_t msg_wait;
- struct completion event;
- struct vcd_property_h264_mv_buffer vcd_h264_mv_buffer;
- struct vcd_property_enc_recon_buffer recon_buffer[4];
- u32 event_status;
- u32 seq_header_set;
- u32 stop_msg;
- u32 stop_called;
- u32 stop_sync_cb;
- struct ion_client *user_ion_client;
- struct ion_handle *seq_hdr_ion_handle;
- struct ion_handle *h264_mv_ion_handle;
- struct ion_handle *recon_buffer_ion_handle[4];
- u32 dmx_disable;
-};
-
-void __iomem *vidc_get_ioaddr(void);
-int vidc_load_firmware(void);
-void vidc_release_firmware(void);
-u32 vidc_get_fd_info(struct video_client_ctx *client_ctx,
- enum buffer_dir buffer, int pmem_fd,
- unsigned long kvaddr, int index);
-u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
- enum buffer_dir buffer, u32 search_with_user_vaddr,
- unsigned long *user_vaddr, unsigned long *kernel_vaddr,
- unsigned long *phy_addr, int *pmem_fd, struct file **file,
- s32 *buffer_index);
-u32 vidc_insert_addr_table(struct video_client_ctx *client_ctx,
- enum buffer_dir buffer, unsigned long user_vaddr,
- unsigned long *kernel_vaddr, int pmem_fd,
- unsigned long buffer_addr_offset,
- unsigned int max_num_buffers, unsigned long length);
-u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
- enum buffer_dir buffer, unsigned long user_vaddr,
- unsigned long *kernel_vaddr);
-
-u32 vidc_timer_create(void (*timer_handler)(void *),
- void *user_data, void **timer_handle);
-void vidc_timer_release(void *timer_handle);
-void vidc_timer_start(void *timer_handle, u32 time_out);
-void vidc_timer_stop(void *timer_handle);
-
-
-#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index b557752..9fc76d8 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,10 +13,10 @@
#ifndef _VCD_H_
#define _VCD_H_
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
+#include "vcd_util.h"
#include "vcd_ddl_api.h"
#include "vcd_res_tracker_api.h"
-#include "vcd_util.h"
#include "vcd_client_sm.h"
#include "vcd_core.h"
#include "vcd_device_sm.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
index 5e9fd55..e0ef3af 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle)
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.h b/drivers/video/msm/vidc/common/vcd/vcd_api.h
deleted file mode 100644
index 9580ece..0000000
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#ifndef _VCD_API_H_
-#define _VCD_API_H_
-#include "vcd_property.h"
-#include "vcd_status.h"
-
-#define VCD_FRAME_FLAG_EOS 0x00000001
-#define VCD_FRAME_FLAG_DECODEONLY 0x00000004
-#define VCD_FRAME_FLAG_DATACORRUPT 0x00000008
-#define VCD_FRAME_FLAG_ENDOFFRAME 0x00000010
-#define VCD_FRAME_FLAG_SYNCFRAME 0x00000020
-#define VCD_FRAME_FLAG_EXTRADATA 0x00000040
-#define VCD_FRAME_FLAG_CODECCONFIG 0x00000080
-#define VCD_FRAME_FLAG_BFRAME 0x00100000
-#define VCD_FRAME_FLAG_EOSEQ 0x00200000
-
-#define VCD_FLUSH_INPUT 0x0001
-#define VCD_FLUSH_OUTPUT 0x0002
-#define VCD_FLUSH_ALL 0x0003
-
-#define VCD_FRAMETAG_INVALID 0xffffffff
-
-struct vcd_handle_container {
- void *handle;
-};
-struct vcd_flush_cmd {
- u32 mode;
-};
-
-enum vcd_frame {
- VCD_FRAME_YUV = 1,
- VCD_FRAME_I,
- VCD_FRAME_P,
- VCD_FRAME_B,
- VCD_FRAME_NOTCODED,
- VCD_FRAME_IDR,
- VCD_FRAME_32BIT = 0x7fffffff
-};
-
-enum vcd_power_state {
- VCD_PWR_STATE_ON = 1,
- VCD_PWR_STATE_SLEEP,
-};
-
-struct vcd_frame_data {
- u8 *virtual;
- u8 *physical;
- u32 ion_flag;
- u32 alloc_len;
- u32 data_len;
- u32 offset;
- s64 time_stamp;
- u32 flags;
- u32 frm_clnt_data;
- struct vcd_property_dec_output_buffer dec_op_prop;
- u32 interlaced;
- enum vcd_frame frame;
- u32 ip_frm_tag;
- u32 intrlcd_ip_frm_tag;
- u8 *desc_buf;
- u32 desc_size;
-};
-
-struct vcd_sequence_hdr {
- u8 *sequence_header;
- u32 sequence_header_len;
-
-};
-
-enum vcd_buffer_type {
- VCD_BUFFER_INPUT = 0x1,
- VCD_BUFFER_OUTPUT = 0x2,
- VCD_BUFFER_INVALID = 0x3,
- VCD_BUFFER_32BIT = 0x7FFFFFFF
-};
-
-struct vcd_buffer_requirement {
- u32 min_count;
- u32 actual_count;
- u32 max_count;
- size_t sz;
- u32 align;
- u32 buf_pool_id;
-};
-
-struct vcd_init_config {
- void *device_name;
- void *(*map_dev_base_addr) (void *device_name);
- void (*un_map_dev_base_addr) (void);
- void (*interrupt_clr) (void);
- void (*register_isr) (void *device_name);
- void (*deregister_isr) (void);
- u32 (*timer_create) (void (*timer_handler)(void *),
- void *user_data, void **timer_handle);
- void (*timer_release) (void *timer_handle);
- void (*timer_start) (void *timer_handle, u32 time_out);
- void (*timer_stop) (void *timer_handle);
-};
-
-u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle);
-u32 vcd_term(s32 driver_handle);
-u32 vcd_open(s32 driver_handle, u32 decoding,
- void (*callback) (u32 event, u32 status, void *info, size_t sz,
- void *handle, void *const client_data), void *client_data);
-u32 vcd_close(void *handle);
-u32 vcd_encode_start(void *handle);
-u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame);
-u32 vcd_decode_start(void *handle, struct vcd_sequence_hdr *seq_hdr);
-u32 vcd_decode_frame(void *handle, struct vcd_frame_data *input_frame);
-u32 vcd_pause(void *handle);
-u32 vcd_resume(void *handle);
-u32 vcd_flush(void *handle, u32 mode);
-u32 vcd_stop(void *handle);
-u32 vcd_set_property(void *handle, struct vcd_property_hdr *prop_hdr,
- void *prop_val);
-u32 vcd_get_property(void *handle, struct vcd_property_hdr *prop_hdr,
- void *prop_val);
-u32 vcd_set_buffer_requirements(void *handle, enum vcd_buffer_type buffer,
- struct vcd_buffer_requirement *buffer_req);
-u32 vcd_get_buffer_requirements(void *handle, enum vcd_buffer_type buffer,
- struct vcd_buffer_requirement *buffer_req);
-u32 vcd_set_buffer(void *handle, enum vcd_buffer_type buffer_type,
- u8 *buffer, u32 buf_size);
-u32 vcd_allocate_buffer(void *handle, enum vcd_buffer_type buffer,
- u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr);
-
-u32 vcd_free_buffer(void *handle, enum vcd_buffer_type buffer_type, u8 *buffer);
-u32 vcd_fill_output_buffer(void *handle, struct vcd_frame_data *buffer);
-u32 vcd_set_device_power(s32 driver_handle,
- enum vcd_power_state pwr_state);
-void vcd_read_and_clear_interrupt(void);
-void vcd_response_handler(void);
-u8 vcd_get_num_of_clients(void);
-u32 vcd_get_ion_status(void);
-struct ion_client *vcd_get_ion_client(void);
-#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index e00e85f..9376900 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
static const struct vcd_clnt_state_table *vcd_clnt_state_table[];
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
index e9ab41c..9f2d63d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
*/
#ifndef _VCD_CLIENT_SM_H_
#define _VCD_CLIENT_SM_H_
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
struct vcd_clnt_state_table;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index 64dec2d..1f844e8 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,7 +14,7 @@
#define _VCD_CORE_H_
#include <linux/ion.h>
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
#include "vcd_util.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index 4c477cb..9576387 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
static const struct vcd_dev_state_table *vcd_dev_state_table[];
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
index 8245966..2443c33 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,7 @@
#ifndef _VCD_DEVICE_SM_H_
#define _VCD_DEVICE_SM_H_
-#include "vcd_api.h"
+#include <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
#include "vcd_core.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
index 6a1cc80..01bd931 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd_power_sm.h"
#include "vcd_core.h"
#include "vcd.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_property.h b/drivers/video/msm/vidc/common/vcd/vcd_property.h
deleted file mode 100644
index a3069e3..0000000
--- a/drivers/video/msm/vidc/common/vcd/vcd_property.h
+++ /dev/null
@@ -1,350 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#ifndef _VCD_DRIVER_PROPERTY_H_
-#define _VCD_DRIVER_PROPERTY_H_
-
-#define VCD_START_BASE 0x0
-#define VCD_I_LIVE (VCD_START_BASE + 0x1)
-#define VCD_I_CODEC (VCD_START_BASE + 0x2)
-#define VCD_I_FRAME_SIZE (VCD_START_BASE + 0x3)
-#define VCD_I_METADATA_ENABLE (VCD_START_BASE + 0x4)
-#define VCD_I_METADATA_HEADER (VCD_START_BASE + 0x5)
-#define VCD_I_PROFILE (VCD_START_BASE + 0x6)
-#define VCD_I_LEVEL (VCD_START_BASE + 0x7)
-#define VCD_I_BUFFER_FORMAT (VCD_START_BASE + 0x8)
-#define VCD_I_FRAME_RATE (VCD_START_BASE + 0x9)
-#define VCD_I_TARGET_BITRATE (VCD_START_BASE + 0xA)
-#define VCD_I_MULTI_SLICE (VCD_START_BASE + 0xB)
-#define VCD_I_ENTROPY_CTRL (VCD_START_BASE + 0xC)
-#define VCD_I_DEBLOCKING (VCD_START_BASE + 0xD)
-#define VCD_I_RATE_CONTROL (VCD_START_BASE + 0xE)
-#define VCD_I_QP_RANGE (VCD_START_BASE + 0xF)
-#define VCD_I_SESSION_QP (VCD_START_BASE + 0x10)
-#define VCD_I_INTRA_PERIOD (VCD_START_BASE + 0x11)
-#define VCD_I_VOP_TIMING (VCD_START_BASE + 0x12)
-#define VCD_I_SHORT_HEADER (VCD_START_BASE + 0x13)
-#define VCD_I_SEQ_HEADER (VCD_START_BASE + 0x14)
-#define VCD_I_HEADER_EXTENSION (VCD_START_BASE + 0x15)
-#define VCD_I_INTRA_REFRESH (VCD_START_BASE + 0x16)
-#define VCD_I_POST_FILTER (VCD_START_BASE + 0x17)
-#define VCD_I_PROGRESSIVE_ONLY (VCD_START_BASE + 0x18)
-#define VCD_I_OUTPUT_ORDER (VCD_START_BASE + 0x19)
-#define VCD_I_RECON_BUFFERS (VCD_START_BASE + 0x1A)
-#define VCD_I_FREE_RECON_BUFFERS (VCD_START_BASE + 0x1B)
-#define VCD_I_GET_RECON_BUFFER_SIZE (VCD_START_BASE + 0x1C)
-#define VCD_I_H264_MV_BUFFER (VCD_START_BASE + 0x1D)
-#define VCD_I_FREE_H264_MV_BUFFER (VCD_START_BASE + 0x1E)
-#define VCD_I_GET_H264_MV_SIZE (VCD_START_BASE + 0x1F)
-#define VCD_I_DEC_PICTYPE (VCD_START_BASE + 0x20)
-#define VCD_I_CONT_ON_RECONFIG (VCD_START_BASE + 0x21)
-#define VCD_I_META_BUFFER_MODE (VCD_START_BASE + 0x22)
-#define VCD_I_DISABLE_DMX (VCD_START_BASE + 0x23)
-#define VCD_I_DISABLE_DMX_SUPPORT (VCD_START_BASE + 0x24)
-
-#define VCD_START_REQ (VCD_START_BASE + 0x1000)
-#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
-
-#define VCD_I_RESERVED_BASE (VCD_START_BASE + 0x10000)
-
-struct vcd_property_hdr {
- u32 prop_id;
- size_t sz;
-};
-
-struct vcd_property_live {
- u32 live;
-};
-
-enum vcd_codec {
- VCD_CODEC_H264 = 0x1,
- VCD_CODEC_H263 = 0x2,
- VCD_CODEC_MPEG1 = 0x3,
- VCD_CODEC_MPEG2 = 0x4,
- VCD_CODEC_MPEG4 = 0x5,
- VCD_CODEC_DIVX_3 = 0x6,
- VCD_CODEC_DIVX_4 = 0x7,
- VCD_CODEC_DIVX_5 = 0x8,
- VCD_CODEC_DIVX_6 = 0x9,
- VCD_CODEC_XVID = 0xA,
- VCD_CODEC_VC1 = 0xB,
- VCD_CODEC_VC1_RCV = 0xC
-};
-
-struct vcd_property_codec {
- enum vcd_codec codec;
-};
-
-struct vcd_property_frame_size {
- u32 width;
- u32 height;
- u32 stride;
- u32 scan_lines;
-};
-
-
-#define VCD_METADATA_DATANONE 0x001
-#define VCD_METADATA_QCOMFILLER 0x002
-#define VCD_METADATA_QPARRAY 0x004
-#define VCD_METADATA_CONCEALMB 0x008
-#define VCD_METADATA_SEI 0x010
-#define VCD_METADATA_VUI 0x020
-#define VCD_METADATA_VC1 0x040
-#define VCD_METADATA_PASSTHROUGH 0x080
-#define VCD_METADATA_ENC_SLICE 0x100
-
-struct vcd_property_meta_data_enable {
- u32 meta_data_enable_flag;
-};
-
-struct vcd_property_metadata_hdr {
- u32 meta_data_id;
- u32 version;
- u32 port_index;
- u32 type;
-};
-
-struct vcd_property_frame_rate {
- u32 fps_denominator;
- u32 fps_numerator;
-};
-
-struct vcd_property_target_bitrate {
- u32 target_bitrate;
-};
-
-enum vcd_yuv_buffer_format {
- VCD_BUFFER_FORMAT_NV12 = 0x1,
- VCD_BUFFER_FORMAT_TILE_4x2 = 0x2,
- VCD_BUFFER_FORMAT_NV12_16M2KA = 0x3,
- VCD_BUFFER_FORMAT_TILE_1x1 = 0x4
-};
-
-struct vcd_property_buffer_format {
- enum vcd_yuv_buffer_format buffer_format;
-};
-
-struct vcd_property_post_filter {
- u32 post_filter;
-};
-
-enum vcd_codec_profile {
- VCD_PROFILE_UNKNOWN = 0x0,
- VCD_PROFILE_MPEG4_SP = 0x1,
- VCD_PROFILE_MPEG4_ASP = 0x2,
- VCD_PROFILE_H264_BASELINE = 0x3,
- VCD_PROFILE_H264_MAIN = 0x4,
- VCD_PROFILE_H264_HIGH = 0x5,
- VCD_PROFILE_H263_BASELINE = 0x6,
- VCD_PROFILE_VC1_SIMPLE = 0x7,
- VCD_PROFILE_VC1_MAIN = 0x8,
- VCD_PROFILE_VC1_ADVANCE = 0x9,
- VCD_PROFILE_MPEG2_MAIN = 0xA,
- VCD_PROFILE_MPEG2_SIMPLE = 0xB
-};
-
-struct vcd_property_profile {
- enum vcd_codec_profile profile;
-};
-
-enum vcd_codec_level {
- VCD_LEVEL_UNKNOWN = 0x0,
- VCD_LEVEL_MPEG4_0 = 0x1,
- VCD_LEVEL_MPEG4_0b = 0x2,
- VCD_LEVEL_MPEG4_1 = 0x3,
- VCD_LEVEL_MPEG4_2 = 0x4,
- VCD_LEVEL_MPEG4_3 = 0x5,
- VCD_LEVEL_MPEG4_3b = 0x6,
- VCD_LEVEL_MPEG4_4 = 0x7,
- VCD_LEVEL_MPEG4_4a = 0x8,
- VCD_LEVEL_MPEG4_5 = 0x9,
- VCD_LEVEL_MPEG4_6 = 0xA,
- VCD_LEVEL_MPEG4_7 = 0xB,
- VCD_LEVEL_MPEG4_X = 0xC,
- VCD_LEVEL_H264_1 = 0x10,
- VCD_LEVEL_H264_1b = 0x11,
- VCD_LEVEL_H264_1p1 = 0x12,
- VCD_LEVEL_H264_1p2 = 0x13,
- VCD_LEVEL_H264_1p3 = 0x14,
- VCD_LEVEL_H264_2 = 0x15,
- VCD_LEVEL_H264_2p1 = 0x16,
- VCD_LEVEL_H264_2p2 = 0x17,
- VCD_LEVEL_H264_3 = 0x18,
- VCD_LEVEL_H264_3p1 = 0x19,
- VCD_LEVEL_H264_3p2 = 0x1A,
- VCD_LEVEL_H264_4 = 0x1B,
- VCD_LEVEL_H264_4p1 = 0x1C,
- VCD_LEVEL_H264_4p2 = 0x1D,
- VCD_LEVEL_H264_5 = 0x1E,
- VCD_LEVEL_H264_5p1 = 0x1F,
- VCD_LEVEL_H263_10 = 0x20,
- VCD_LEVEL_H263_20 = 0x21,
- VCD_LEVEL_H263_30 = 0x22,
- VCD_LEVEL_H263_40 = 0x23,
- VCD_LEVEL_H263_45 = 0x24,
- VCD_LEVEL_H263_50 = 0x25,
- VCD_LEVEL_H263_60 = 0x26,
- VCD_LEVEL_H263_70 = 0x27,
- VCD_LEVEL_H263_X = 0x28,
- VCD_LEVEL_MPEG2_LOW = 0x30,
- VCD_LEVEL_MPEG2_MAIN = 0x31,
- VCD_LEVEL_MPEG2_HIGH_14 = 0x32,
- VCD_LEVEL_MPEG2_HIGH = 0x33,
- VCD_LEVEL_MPEG2_X = 0x34,
- VCD_LEVEL_VC1_S_LOW = 0x40,
- VCD_LEVEL_VC1_S_MEDIUM = 0x41,
- VCD_LEVEL_VC1_M_LOW = 0x42,
- VCD_LEVEL_VC1_M_MEDIUM = 0x43,
- VCD_LEVEL_VC1_M_HIGH = 0x44,
- VCD_LEVEL_VC1_A_0 = 0x45,
- VCD_LEVEL_VC1_A_1 = 0x46,
- VCD_LEVEL_VC1_A_2 = 0x47,
- VCD_LEVEL_VC1_A_3 = 0x48,
- VCD_LEVEL_VC1_A_4 = 0x49,
- VCD_LEVEL_VC1_X = 0x4A
-};
-
-struct vcd_property_level {
- enum vcd_codec_level level;
-};
-
-enum vcd_m_slice_sel {
- VCD_MSLICE_OFF = 0x1,
- VCD_MSLICE_BY_MB_COUNT = 0x2,
- VCD_MSLICE_BY_BYTE_COUNT = 0x3,
- VCD_MSLICE_BY_GOB = 0x4
-};
-
-struct vcd_property_multi_slice {
- enum vcd_m_slice_sel m_slice_sel;
- u32 m_slice_size;
-};
-
-enum vcd_entropy_sel {
- VCD_ENTROPY_SEL_CAVLC = 0x1,
- VCD_ENTROPY_SEL_CABAC = 0x2
-};
-
-enum vcd_cabac_model {
- VCD_CABAC_MODEL_NUMBER_0 = 0x1,
- VCD_CABAC_MODEL_NUMBER_1 = 0x2,
- VCD_CABAC_MODEL_NUMBER_2 = 0x3
-};
-
-struct vcd_property_entropy_control {
- enum vcd_entropy_sel entropy_sel;
- enum vcd_cabac_model cabac_model;
-};
-
-enum vcd_db_config {
- VCD_DB_ALL_BLOCKING_BOUNDARY = 0x1,
- VCD_DB_DISABLE = 0x2,
- VCD_DB_SKIP_SLICE_BOUNDARY = 0x3
-};
-struct vcd_property_db_config {
- enum vcd_db_config db_config;
- u32 slice_alpha_offset;
- u32 slice_beta_offset;
-};
-
-enum vcd_rate_control {
- VCD_RATE_CONTROL_OFF = 0x1,
- VCD_RATE_CONTROL_VBR_VFR = 0x2,
- VCD_RATE_CONTROL_VBR_CFR = 0x3,
- VCD_RATE_CONTROL_CBR_VFR = 0x4,
- VCD_RATE_CONTROL_CBR_CFR = 0x5
-};
-
-struct vcd_property_rate_control {
- enum vcd_rate_control rate_control;
-};
-
-struct vcd_property_qp_range {
- u32 max_qp;
- u32 min_qp;
-};
-
-struct vcd_property_session_qp {
- u32 i_frame_qp;
- u32 p_frame_qp;
- u32 b_frame_qp;
-};
-
-struct vcd_property_i_period {
- u32 p_frames;
- u32 b_frames;
-};
-
-struct vcd_property_vop_timing {
- u32 vop_time_resolution;
-};
-
-struct vcd_property_short_header {
- u32 short_header;
-};
-
-struct vcd_property_intra_refresh_mb_number {
- u32 cir_mb_number;
-};
-
-struct vcd_property_req_i_frame {
- u32 req_i_frame;
-};
-
-struct vcd_frame_rect{
- u32 left;
- u32 top;
- u32 right;
- u32 bottom;
-};
-
-struct vcd_property_dec_output_buffer {
- struct vcd_frame_rect disp_frm;
- struct vcd_property_frame_size frm_size;
-};
-
-enum vcd_output_order {
- VCD_DEC_ORDER_DISPLAY = 0x0,
- VCD_DEC_ORDER_DECODE = 0x1
-};
-
-struct vcd_property_enc_recon_buffer{
- u8 *user_virtual_addr;
- u8 *kernel_virtual_addr;
- u8 *physical_addr;
- u8 *dev_addr;
- u32 buffer_size;
- u32 ysize;
- int pmem_fd;
- u32 offset;
- void *client_data;
-};
-
-struct vcd_property_h264_mv_buffer{
- u8 *kernel_virtual_addr;
- u8 *physical_addr;
- u32 size;
- u32 count;
- int pmem_fd;
- u32 offset;
- u8 *dev_addr;
- void *client_data;
-};
-
-struct vcd_property_buffer_size{
- int width;
- int height;
- int size;
- int alignment;
-};
-
-#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
index 34a3445..dec9b4e 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
*
*/
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
#define NORMALIZATION_FACTOR 3600
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_status.h b/drivers/video/msm/vidc/common/vcd/vcd_status.h
deleted file mode 100644
index 1a36167..0000000
--- a/drivers/video/msm/vidc/common/vcd/vcd_status.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _VCD_ERR_STATUS_H_
-#define _VCD_ERR_STATUS_H_
-
-#define VCD_EVT_RESP_BASE 0x1000
-#define VCD_EVT_RESP_OPEN (VCD_EVT_RESP_BASE + 0x1)
-#define VCD_EVT_RESP_START (VCD_EVT_RESP_BASE + 0x2)
-#define VCD_EVT_RESP_STOP (VCD_EVT_RESP_BASE + 0x3)
-#define VCD_EVT_RESP_PAUSE (VCD_EVT_RESP_BASE + 0x4)
-#define VCD_EVT_RESP_FLUSH_INPUT_DONE (VCD_EVT_RESP_BASE + 0x5)
-#define VCD_EVT_RESP_FLUSH_OUTPUT_DONE (VCD_EVT_RESP_BASE + 0x6)
-#define VCD_EVT_RESP_INPUT_FLUSHED (VCD_EVT_RESP_BASE + 0x7)
-#define VCD_EVT_RESP_OUTPUT_FLUSHED (VCD_EVT_RESP_BASE + 0x8)
-#define VCD_EVT_RESP_INPUT_DONE (VCD_EVT_RESP_BASE + 0x9)
-#define VCD_EVT_RESP_OUTPUT_DONE (VCD_EVT_RESP_BASE + 0xa)
-
-#define VCD_EVT_IND_BASE 0x2000
-#define VCD_EVT_IND_INPUT_RECONFIG (VCD_EVT_IND_BASE + 0x1)
-#define VCD_EVT_IND_OUTPUT_RECONFIG (VCD_EVT_IND_BASE + 0x2)
-#define VCD_EVT_IND_HWERRFATAL (VCD_EVT_IND_BASE + 0x3)
-#define VCD_EVT_IND_RESOURCES_LOST (VCD_EVT_IND_BASE + 0x4)
-#define VCD_EVT_IND_INFO_OUTPUT_RECONFIG (VCD_EVT_IND_BASE + 0x5)
-#define VCD_EVT_IND_INFO_FIELD_DROPPED (VCD_EVT_IND_BASE + 0x6)
-
-#define VCD_S_SUCCESS 0x0
-
-#define VCD_S_ERR_BASE 0x80000000
-#define VCD_ERR_FAIL (VCD_S_ERR_BASE + 0x01)
-#define VCD_ERR_ALLOC_FAIL (VCD_S_ERR_BASE + 0x02)
-#define VCD_ERR_ILLEGAL_OP (VCD_S_ERR_BASE + 0x03)
-#define VCD_ERR_ILLEGAL_PARM (VCD_S_ERR_BASE + 0x04)
-#define VCD_ERR_BAD_POINTER (VCD_S_ERR_BASE + 0x05)
-#define VCD_ERR_BAD_HANDLE (VCD_S_ERR_BASE + 0x06)
-#define VCD_ERR_NOT_SUPPORTED (VCD_S_ERR_BASE + 0x07)
-#define VCD_ERR_BAD_STATE (VCD_S_ERR_BASE + 0x08)
-#define VCD_ERR_BUSY (VCD_S_ERR_BASE + 0x09)
-#define VCD_ERR_MAX_CLIENT (VCD_S_ERR_BASE + 0x0a)
-#define VCD_ERR_IFRAME_EXPECTED (VCD_S_ERR_BASE + 0x0b)
-#define VCD_ERR_INTRLCD_FIELD_DROP (VCD_S_ERR_BASE + 0x0c)
-#define VCD_ERR_HW_FATAL (VCD_S_ERR_BASE + 0x0d)
-#define VCD_ERR_BITSTREAM_ERR (VCD_S_ERR_BASE + 0x0e)
-#define VCD_ERR_QEMPTY (VCD_S_ERR_BASE + 0x0f)
-#define VCD_ERR_SEQHDR_PARSE_FAIL (VCD_S_ERR_BASE + 0x10)
-#define VCD_ERR_INPUT_NOT_PROCESSED (VCD_S_ERR_BASE + 0x11)
-#define VCD_ERR_INDEX_NOMORE (VCD_S_ERR_BASE + 0x12)
-
-#define VCD_FAILED(rc) ((rc > VCD_S_ERR_BASE) ? true : false)
-
-#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 509b897..ebc30fd 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -13,7 +13,7 @@
#include <linux/memory_alloc.h>
#include <mach/msm_subsystem_map.h>
#include <asm/div64.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
#include "vcd.h"
#include "vdec_internal.h"
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_util.h b/drivers/video/msm/vidc/common/vcd/vcd_util.h
index 07ad651..7164029 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_util.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,8 +12,8 @@
*/
#ifndef _VCD_UTIL_H_
#define _VCD_UTIL_H_
-#include "vidc_type.h"
-#include "vcd_api.h"
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_api.h>
#if DEBUG
diff --git a/drivers/video/msm/vidc/common/vcd/vidc_type.h b/drivers/video/msm/vidc/common/vcd/vidc_type.h
deleted file mode 100644
index bd87c0d..0000000
--- a/drivers/video/msm/vidc/common/vcd/vidc_type.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#ifndef VIDC_TYPE_H
-#define VIDC_TYPE_H
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/list.h>
-#include <linux/time.h>
-#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
-
-#define DEBUG 0
-#define VIDC_ENABLE_DBGFS
-
-#define USE_RES_TRACKER
-#endif
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 9c43f56..79f7874 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -428,6 +428,7 @@
header-y += msm_ipc.h
header-y += msm_charm.h
header-y += tzcom.h
+header-y += qseecom.h
header-y += qcedev.h
header-y += idle_stats_device.h
header-y += genlock.h
diff --git a/include/linux/fmem.h b/include/linux/fmem.h
index aebeec4..44b7005 100644
--- a/include/linux/fmem.h
+++ b/include/linux/fmem.h
@@ -20,7 +20,8 @@
struct fmem_platform_data {
unsigned long phys;
unsigned long size;
- unsigned long reserved_size;
+ unsigned long reserved_size_low;
+ unsigned long reserved_size_high;
};
struct fmem_data {
@@ -28,7 +29,8 @@
void *virt;
struct vm_struct *area;
unsigned long size;
- unsigned long reserved_size;
+ unsigned long reserved_size_low;
+ unsigned long reserved_size_high;
};
enum fmem_state {
diff --git a/include/linux/ion.h b/include/linux/ion.h
index ade87e6..caed2a2 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -64,12 +64,12 @@
enum ion_heap_ids {
INVALID_HEAP_ID = -1,
- ION_IOMMU_HEAP_ID = 4,
ION_CP_MM_HEAP_ID = 8,
ION_CP_MFC_HEAP_ID = 12,
ION_CP_WB_HEAP_ID = 16, /* 8660 only */
ION_CAMERA_HEAP_ID = 20, /* 8660 only */
ION_SF_HEAP_ID = 24,
+ ION_IOMMU_HEAP_ID = 25,
ION_QSECOM_HEAP_ID = 27,
ION_AUDIO_HEAP_ID = 28,
@@ -160,6 +160,8 @@
* of this heap in the case of a shared heap.
* @reusable Flag indicating whether this heap is reusable of not.
* (see FMEM)
+ * @mem_is_fmem Flag indicating whether this memory is coming from fmem
+ * or not.
* @virt_addr: Virtual address used when using fmem.
* @request_region: function to be called when the number of allocations
* goes from 0 -> 1
@@ -174,6 +176,7 @@
ion_phys_addr_t secure_base; /* Base addr used when heap is shared */
size_t secure_size; /* Size used for securing heap when heap is shared*/
int reusable;
+ int mem_is_fmem;
ion_virt_addr_t *virt_addr;
int (*request_region)(void *);
int (*release_region)(void *);
@@ -184,6 +187,8 @@
* struct ion_co_heap_pdata - defines a carveout heap in the given platform
* @adjacent_mem_id: Id of heap that this heap must be adjacent to.
* @align: Alignment requirement for the memory
+ * @mem_is_fmem Flag indicating whether this memory is coming from fmem
+ * or not.
* @request_region: function to be called when the number of allocations
* goes from 0 -> 1
* @release_region: function to be called when the number of allocations
@@ -194,6 +199,7 @@
struct ion_co_heap_pdata {
int adjacent_mem_id;
unsigned int align;
+ int mem_is_fmem;
int (*request_region)(void *);
int (*release_region)(void *);
void *(*setup_region)(void);
@@ -564,6 +570,7 @@
struct ion_handle *handle, int domain_num,
int partition_num, unsigned long align,
unsigned long iova_length, unsigned long *iova,
+ unsigned long *buffer_size,
unsigned long flags)
{
return -ENODEV;
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index c4f601b..c90d8d1 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -73,6 +73,22 @@
PM8XXX_RESTART_ON_HARD_RESET,
};
+enum pm8xxx_aux_clk_id {
+ CLK_MP3_1,
+ CLK_MP3_2,
+};
+
+enum pm8xxx_aux_clk_div {
+ X0_DIV_NONE,
+ XO_DIV_1,
+ XO_DIV_2,
+ XO_DIV_4,
+ XO_DIV_8,
+ XO_DIV_16,
+ XO_DIV_32,
+ XO_DIV_64,
+};
+
#if defined(CONFIG_MFD_PM8XXX_MISC) || defined(CONFIG_MFD_PM8XXX_MISC_MODULE)
/**
@@ -181,6 +197,19 @@
*/
int pm8xxx_usb_id_pullup(int enable);
+/**
+ * pm8xxx_aux_clk_control - Control an auxiliary clock
+ * @clk_id: ID of clock to be programmed, registers of XO_CNTRL2
+ * @divider: divisor to use when configuring desired clock
+ * @enable: enable (1) the designated clock with the supplied division,
+ * or disable (0) the designated clock
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+ enum pm8xxx_aux_clk_div divider,
+ bool enable);
+
#else
static inline int pm8xxx_reset_pwr_off(int reset)
@@ -225,6 +254,12 @@
{
return -ENODEV;
}
+static inline int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+ enum pm8xxx_aux_clk_div divider, bool enable)
+{
+ return -ENODEV;
+}
+
#endif
#endif
diff --git a/include/linux/mfd/pm8xxx/regulator.h b/include/linux/mfd/pm8xxx/regulator.h
index 9e0ce86..83492d2 100644
--- a/include/linux/mfd/pm8xxx/regulator.h
+++ b/include/linux/mfd/pm8xxx/regulator.h
@@ -30,6 +30,7 @@
* %PM8XXX_REGULATOR_TYPE_VS: voltage switch capable of sourcing 100mA
* %PM8XXX_REGULATOR_TYPE_VS300: voltage switch capable of sourcing 300mA
* %PM8XXX_REGULATOR_TYPE_NCP: negative charge pump
+ * %PM8XXX_REGULATOR_TYPE_BOOST: boost regulator
* %PM8XXX_REGULATOR_TYPE_MAX: used internally for error checking; not
* a valid regulator type.
*
@@ -44,6 +45,7 @@
PM8XXX_REGULATOR_TYPE_VS,
PM8XXX_REGULATOR_TYPE_VS300,
PM8XXX_REGULATOR_TYPE_NCP,
+ PM8XXX_REGULATOR_TYPE_BOOST,
PM8XXX_REGULATOR_TYPE_MAX,
};
@@ -257,4 +259,13 @@
.prev_write_count = -1, \
}
+#define BOOST(_name, _ctrl_addr) \
+ { \
+ .type = PM8XXX_REGULATOR_TYPE_BOOST, \
+ .ctrl_addr = _ctrl_addr, \
+ .rdesc.name = _name, \
+ .write_count = 0, \
+ .prev_write_count = -1, \
+ }
+
#endif
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 18997d7..cb394e8 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -436,6 +436,15 @@
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
+#define SPMI_NAME_SIZE 32
+#define SPMI_MODULE_PREFIX "spmi:"
+
+struct spmi_device_id {
+ char name[SPMI_NAME_SIZE];
+ kernel_ulong_t driver_data /* Data private to the driver */
+ __attribute__((aligned(sizeof(kernel_ulong_t))));
+};
+
/* dmi */
enum dmi_field {
DMI_NONE,
diff --git a/include/linux/msm_audio_mvs.h b/include/linux/msm_audio_mvs.h
index 2813c8f..8ec9796 100644
--- a/include/linux/msm_audio_mvs.h
+++ b/include/linux/msm_audio_mvs.h
@@ -24,7 +24,7 @@
#define MVS_MODE_G729A 0xE
#define MVS_MODE_G711A 0xF
#define MVS_MODE_G722 0x10
-#define MVS_MODE_PCM_WB 0x80000000
+#define MVS_MODE_PCM_WB 0x12
enum msm_audio_amr_mode {
MVS_AMR_MODE_0475, /* AMR 4.75 kbps */
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 9eb6dda..5e39f89 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -140,6 +140,13 @@
#define KGSL_2D1_REG_MEMORY "kgsl_2d1_reg_memory"
#define KGSL_2D1_IRQ "kgsl_2d1_irq"
+struct kgsl_device_iommu_data {
+ const char **iommu_ctx_names;
+ int iommu_ctx_count;
+ unsigned int physstart;
+ unsigned int physend;
+};
+
struct kgsl_device_platform_data {
struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
int init_level;
@@ -148,9 +155,10 @@
unsigned int idle_timeout;
unsigned int nap_allowed;
unsigned int clk_map;
+ unsigned int idle_needed;
struct msm_bus_scale_pdata *bus_scale_table;
- const char *iommu_user_ctx_name;
- const char *iommu_priv_ctx_name;
+ struct kgsl_device_iommu_data *iommu_data;
+ int iommu_count;
};
#endif
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 189548c..99b5acd 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -22,14 +22,15 @@
MSM_8660 = 0,
MSM_8960,
MSM_9615,
+ APQ_8064,
MSM_TYPE
};
struct tsens_platform_data {
- int slope;
int tsens_factor;
uint32_t tsens_num_sensor;
enum platform_type hw_type;
+ int slope[11];
};
struct tsens_device {
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 3a6f037..cf58d27 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -49,6 +49,8 @@
struct mtd_info;
+void part_fill_badblockstats(struct mtd_info *mtd);
+
/*
* Functions dealing with the various ways of partitioning the space
*/
diff --git a/include/linux/of.h b/include/linux/of.h
index 6a1272c..f904bf4 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -241,6 +241,16 @@
return false;
}
+#define for_each_child_of_node(parent, child) \
+ while (0)
+
+static inline struct property *of_find_property(const struct device_node *np,
+ const char *name,
+ int *lenp)
+{
+ return NULL;
+}
+
static inline int of_property_read_u32_array(const struct device_node *np,
char *propname, u32 *out_values, size_t sz)
{
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3118623..01b925a 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -4,6 +4,7 @@
#include <linux/errno.h>
#include <linux/of.h>
+#ifdef CONFIG_OF_ADDRESS
extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r);
@@ -25,12 +26,37 @@
#define pci_address_to_pio pci_address_to_pio
#endif
-#ifdef CONFIG_PCI
+#else /* CONFIG_OF_ADDRESS */
+static inline int of_address_to_resource(struct device_node *dev, int index,
+ struct resource *r)
+{
+ return -EINVAL;
+}
+static inline struct device_node *of_find_matching_node_by_address(
+ struct device_node *from,
+ const struct of_device_id *matches,
+ u64 base_address)
+{
+ return NULL;
+}
+static inline void __iomem *of_iomap(struct device_node *device, int index)
+{
+ return NULL;
+}
+static inline const u32 *of_get_address(struct device_node *dev, int index,
+ u64 *size, unsigned int *flags)
+{
+ return NULL;
+}
+#endif /* CONFIG_OF_ADDRESS */
+
+
+#if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_PCI)
extern const __be32 *of_get_pci_address(struct device_node *dev, int bar_no,
u64 *size, unsigned int *flags);
extern int of_pci_address_to_resource(struct device_node *dev, int bar,
struct resource *r);
-#else /* CONFIG_PCI */
+#else /* CONFIG_OF_ADDRESS && CONFIG_PCI */
static inline int of_pci_address_to_resource(struct device_node *dev, int bar,
struct resource *r)
{
@@ -42,8 +68,7 @@
{
return NULL;
}
-#endif /* CONFIG_PCI */
-
+#endif /* CONFIG_OF_ADDRESS && CONFIG_PCI */
#endif /* __OF_ADDRESS_H */
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
new file mode 100644
index 0000000..6d39026
--- /dev/null
+++ b/include/linux/qseecom.h
@@ -0,0 +1,149 @@
+#ifndef __QSEECOM_H_
+#define __QSEECOM_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define MAX_ION_FD 4
+#define MAX_APP_NAME_SIZE 32
+
+/*
+ * struct qseecom_register_listener_req -
+ * for register listener ioctl request
+ * @listener_id - service id (shared between userspace and QSE)
+ * @ifd_data_fd - ion handle
+ * @virt_sb_base - shared buffer base in user space
+ * @sb_size - shared buffer size
+ */
+struct qseecom_register_listener_req {
+ uint32_t listener_id; /* in */
+ int32_t ifd_data_fd; /* in */
+ uint32_t virt_sb_base; /* in */
+ uint32_t sb_size; /* in */
+};
+
+/*
+ * struct qseecom_send_cmd_req - for send command ioctl request
+ * @cmd_req_len - command buffer length
+ * @cmd_req_buf - command buffer
+ * @resp_len - response buffer length
+ * @resp_buf - response buffer
+ */
+struct qseecom_send_cmd_req {
+ void *cmd_req_buf; /* in */
+ unsigned int cmd_req_len; /* in */
+ void *resp_buf; /* in/out */
+ unsigned int resp_len; /* in/out */
+};
+
+
+/*
+ * struct qseecom_ion_fd_info - ion fd handle data information
+ * @fd - ion handle to some memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_ion_fd_info {
+ int32_t fd;
+ uint32_t cmd_buf_offset;
+};
+/*
+ * struct qseecom_send_modfd_cmd_req - for send command ioctl request
+ * @cmd_req_len - command buffer length
+ * @cmd_req_buf - command buffer
+ * @resp_len - response buffer length
+ * @resp_buf - response buffer
+ * @ifd_data_fd - ion handle to memory allocated in user space
+ * @cmd_buf_offset - command buffer offset
+ */
+struct qseecom_send_modfd_cmd_req {
+ void *cmd_req_buf; /* in */
+ unsigned int cmd_req_len; /* in */
+ void *resp_buf; /* in/out */
+ unsigned int resp_len; /* in/out */
+ struct qseecom_ion_fd_info ifd_data[MAX_ION_FD];
+};
+/*
+ * struct qseecom_listener_send_resp_req - signal to continue the send_cmd req.
+ * Used as a trigger from HLOS service to notify QSEECOM that it's done with its
+ * operation and provide the response for QSEECOM can continue the incomplete
+ * command execution
+ * @resp_len - Length of the response
+ * @resp_buf - Response buffer where the response of the cmd should go.
+ */
+struct qseecom_send_resp_req {
+ void *resp_buf; /* in */
+ unsigned int resp_len; /* in */
+};
+
+/*
+ * struct qseecom_load_img_data - for sending image length information and
+ * ion file descriptor to the qseecom driver. ion file descriptor is used
+ * for retrieving the ion file handle and in turn the physical address of
+ * the image location.
+ * @mdt_len - Length of the .mdt file in bytes.
+ * @img_len - Length of the .mdt + .b00 +..+.bxx images files in bytes
+ * @ion_fd - Ion file descriptor used when allocating memory.
+ * @img_name - Name of the image.
+*/
+struct qseecom_load_img_req {
+ uint32_t mdt_len; /* in */
+ uint32_t img_len; /* in */
+ int32_t ifd_data_fd; /* in */
+ char img_name[MAX_APP_NAME_SIZE]; /* in */
+ int app_id; /* out*/
+};
+
+struct qseecom_set_sb_mem_param_req {
+ int32_t ifd_data_fd; /* in */
+ uint32_t virt_sb_base; /* in */
+ uint32_t sb_len; /* in */
+};
+
+/*
+ * struct qseecom_qseos_version_req - get qseos version
+ * @qseos_version - version number
+ */
+struct qseecom_qseos_version_req {
+ unsigned int qseos_version; /* in */
+};
+
+#define QSEECOM_IOC_MAGIC 0x97
+
+
+#define QSEECOM_IOCTL_REGISTER_LISTENER_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 1, struct qseecom_register_listener_req)
+
+#define QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ \
+ _IO(QSEECOM_IOC_MAGIC, 2)
+
+#define QSEECOM_IOCTL_SEND_CMD_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 3, struct qseecom_send_cmd_req)
+
+#define QSEECOM_IOCTL_SEND_MODFD_CMD_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 4, struct qseecom_send_modfd_cmd_req)
+
+#define QSEECOM_IOCTL_RECEIVE_REQ \
+ _IO(QSEECOM_IOC_MAGIC, 5)
+
+#define QSEECOM_IOCTL_SEND_RESP_REQ \
+ _IO(QSEECOM_IOC_MAGIC, 6)
+
+#define QSEECOM_IOCTL_LOAD_APP_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 7, struct qseecom_load_img_req)
+
+#define QSEECOM_IOCTL_SET_MEM_PARAM_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 8, struct qseecom_set_sb_mem_param_req)
+
+#define QSEECOM_IOCTL_UNLOAD_APP_REQ \
+ _IO(QSEECOM_IOC_MAGIC, 9)
+
+#define QSEECOM_IOCTL_GET_QSEOS_VERSION_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 10, struct qseecom_qseos_version_req)
+
+#define QSEECOM_IOCTL_PERF_ENABLE_REQ \
+ _IO(QSEECOM_IOC_MAGIC, 11)
+
+#define QSEECOM_IOCTL_PERF_DISABLE_REQ \
+ _IO(QSEECOM_IOC_MAGIC, 12)
+
+#endif /* __QSEECOM_H_ */
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index 448d9ab..75b132b 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -877,6 +877,7 @@
* -EXFULL is returned if there is no space in TDM to reserve the bandwidth.
* -EISCONN/-ENOTCONN is returned if the channel is already connected or not
* yet defined.
+ * -EINVAL is returned if individual control of a grouped-channel is attempted.
*/
extern int slim_control_ch(struct slim_device *sb, u16 grpchanh,
enum slim_ch_control chctrl, bool commit);
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
new file mode 100644
index 0000000..ffcb24e
--- /dev/null
+++ b/include/linux/spmi.h
@@ -0,0 +1,408 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_SPMI_H
+#define _LINUX_SPMI_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+/* Maximum slave identifier */
+#define SPMI_MAX_SLAVE_ID 16
+
+/* SPMI Commands */
+enum spmi_commands {
+ SPMI_CMD_EXT_WRITE = 0x00,
+ SPMI_CMD_RESET = 0x10,
+ SPMI_CMD_SLEEP = 0x11,
+ SPMI_CMD_SHUTDOWN = 0x12,
+ SPMI_CMD_WAKEUP = 0x13,
+ SPMI_CMD_AUTHENTICATE = 0x14,
+ SPMI_CMD_MSTR_READ = 0x15,
+ SPMI_CMD_MSTR_WRITE = 0x16,
+ SPMI_CMD_TRANSFER_BUS_OWNERSHIP = 0x1A,
+ SPMI_CMD_DDB_MASTER_READ = 0x1B,
+ SPMI_CMD_DDB_SLAVE_READ = 0x1C,
+ SPMI_CMD_EXT_READ = 0x20,
+ SPMI_CMD_EXT_WRITEL = 0x30,
+ SPMI_CMD_EXT_READL = 0x38,
+ SPMI_CMD_WRITE = 0x40,
+ SPMI_CMD_READ = 0x60,
+ SPMI_CMD_ZERO_WRITE = 0x80,
+};
+
+struct spmi_device;
+
+/**
+ * struct spmi_controller: interface to the SPMI master controller
+ * @nr: board-specific number identifier for this controller/bus
+ * @name: name for this controller
+ * @cmd: sends a non-data command sequence on the SPMI bus.
+ * @read_cmd: sends a register read command sequence on the SPMI bus.
+ * @write_cmd: sends a register write command sequence on the SPMI bus.
+ */
+struct spmi_controller {
+ struct device dev;
+ unsigned int nr;
+ struct list_head list;
+ int (*cmd)(struct spmi_controller *, u8 opcode, u8 sid);
+ int (*read_cmd)(struct spmi_controller *,
+ u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);
+ int (*write_cmd)(struct spmi_controller *,
+ u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);
+};
+#define to_spmi_controller(d) container_of(d, struct spmi_controller, dev)
+
+/**
+ * struct spmi_driver: Manage SPMI generic/slave device driver
+ * @probe: binds this driver to a SPMI device.
+ * @remove: unbinds this driver from the SPMI device.
+ * @shutdown: standard shutdown callback used during powerdown/halt.
+ * @suspend: standard suspend callback used during system suspend
+ * @resume: standard resume callback used during system resume
+ * @driver: SPMI device drivers should initialize name and owner field of
+ * this structure
+ * @id_table: list of SPMI devices supported by this driver
+ */
+struct spmi_driver {
+ int (*probe)(struct spmi_device *dev);
+ int (*remove)(struct spmi_device *dev);
+ void (*shutdown)(struct spmi_device *dev);
+ int (*suspend)(struct spmi_device *dev,
+ pm_message_t pmesg);
+ int (*resume)(struct spmi_device *dev);
+
+ struct device_driver driver;
+ const struct spmi_device_id *id_table;
+};
+#define to_spmi_driver(d) container_of(d, struct spmi_driver, driver)
+
+/**
+ * Client/device handle (struct spmi_device):
+ * ------------------------------------------
+ * This is the client/device handle returned when a SPMI device
+ * is registered with a controller.
+ * Pointer to this structure is used by client-driver as a handle.
+ * @dev: driver model representation of the device.
+ * @name: name of driver to use with this device.
+ * @ctrl: SPMI controller managing the bus hosting this device.
+ * @resource: array of resources for this device_node
+ * @num_resources: number of resources for this device node
+ * @sid: slave identifier.
+ */
+struct spmi_device {
+ struct device dev;
+ const char *name;
+ struct spmi_controller *ctrl;
+ struct resource *resource;
+ u32 num_resources;
+ u8 sid;
+};
+#define to_spmi_device(d) container_of(d, struct spmi_device, dev)
+
+/**
+ * struct spmi_boardinfo: Declare board info for SPMI device bringup.
+ * @slave_id: slave identifier.
+ * @spmi_device: device to be registered with the SPMI framework.
+ * @of_node: pointer to the OpenFirmware device node.
+ * @num_resources: number of resources for this device node
+ * @resource: array of resources for this device_node
+ * @platform_data: goes to spmi_device.dev.platform_data
+ */
+struct spmi_boardinfo {
+ char name[SPMI_NAME_SIZE];
+ uint8_t slave_id;
+ struct device_node *of_node;
+ u32 num_resources;
+ struct resource *resource;
+ const void *platform_data;
+};
+
+/**
+ * spmi_driver_register: Client driver registration with SPMI framework.
+ * @drv: client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the SPMI framework.
+ * It is called from the driver's module-init function.
+ */
+extern int spmi_driver_register(struct spmi_driver *drv);
+
+/**
+ * spmi_driver_unregister - reverse effect of spmi_driver_register
+ * @sdrv: the driver to unregister
+ * Context: can sleep
+ */
+static inline void spmi_driver_unregister(struct spmi_driver *sdrv)
+{
+ if (sdrv)
+ driver_unregister(&sdrv->driver);
+}
+
+/**
+ * spmi_add_controller: Controller bring-up.
+ * @ctrl: controller to be registered.
+ *
+ * A controller is registered with the framework using this API. ctrl->nr is the
+ * desired number with which SPMI framework registers the controller.
+ * Function will return -EBUSY if the number is in use.
+ */
+extern int spmi_add_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_del_controller: Controller tear-down.
+ * Controller added with the above API is teared down using this API.
+ */
+extern int spmi_del_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_busnum_to_ctrl: Map bus number to controller
+ * @busnum: bus number
+ *
+ * Returns controller device representing this bus number
+ */
+extern struct spmi_controller *spmi_busnum_to_ctrl(u32 bus_num);
+
+/**
+ * spmi_alloc_device: Allocate a new SPMI devices.
+ * @ctrl: controller to which this device is to be added to.
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize a SPMI device without
+ * registering it immediately. This allows a driver to directly fill
+ * the spmi_device structure before calling spmi_add_device().
+ *
+ * Caller is responsible to call spmi_add_device() on the returned
+ * spmi_device. If the caller needs to discard the spmi_device without
+ * adding it, then spmi_dev_put() should be called.
+ */
+extern struct spmi_device *spmi_alloc_device(struct spmi_controller *ctrl);
+
+/**
+ * spmi_add_device: Add spmi_device allocated with spmi_alloc_device().
+ * @spmi_dev: spmi_device to be added (registered).
+ */
+extern int spmi_add_device(struct spmi_device *spmi_dev);
+
+/**
+ * spmi_new_device: Instantiates a new SPMI device
+ * @ctrl: controller to which this device is to be added to.
+ * @info: board information for this device.
+ *
+ * Returns the new device or NULL.
+ */
+extern struct spmi_device *spmi_new_device(struct spmi_controller *ctrl,
+ struct spmi_boardinfo const *info);
+
+/* spmi_remove_device: Remove the effect of spmi_add_device() */
+extern void spmi_remove_device(struct spmi_device *spmi_dev);
+
+#ifdef CONFIG_SPMI
+/**
+ * spmi_register_board_info: Board-initialization routine.
+ * @bus_num: controller number (bus) on which this device will sit.
+ * @info: list of all devices on all controllers present on the board.
+ * @n: number of entries.
+ *
+ * API enumerates respective devices on corresponding controller.
+ * Called from board-init function.
+ */
+extern int spmi_register_board_info(int busnum,
+ struct spmi_boardinfo const *info, unsigned n);
+#else
+static inline int spmi_register_board_info(int busnum,
+ struct spmi_boardinfo const *info, unsigned n)
+{
+ return 0;
+}
+#endif
+
+static inline void *spmi_get_ctrldata(const struct spmi_controller *ctrl)
+{
+ return dev_get_drvdata(&ctrl->dev);
+}
+
+static inline void spmi_set_ctrldata(struct spmi_controller *ctrl, void *data)
+{
+ dev_set_drvdata(&ctrl->dev, data);
+}
+
+static inline void *spmi_get_devicedata(const struct spmi_device *dev)
+{
+ return dev_get_drvdata(&dev->dev);
+}
+
+static inline void spmi_set_devicedata(struct spmi_device *dev, void *data)
+{
+ dev_set_drvdata(&dev->dev, data);
+}
+
+static inline void spmi_dev_put(struct spmi_device *spmidev)
+{
+ if (spmidev)
+ put_device(&spmidev->dev);
+}
+
+/**
+ * spmi_register_read() - register read
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads 1 byte of data from a Slave device register.
+ */
+extern int spmi_register_read(struct spmi_controller *ctrl,
+ u8 sid, u8 ad, u8 *buf);
+
+/**
+ * spmi_ext_register_read() - extended register read
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @len: the request number of bytes to read (up to 16 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 16 bytes of data from the extended register space on a
+ * Slave device.
+ */
+extern int spmi_ext_register_read(struct spmi_controller *ctrl,
+ u8 sid, u8 ad, u8 *buf, int len);
+
+/**
+ * spmi_ext_register_readl() - extended register read long
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @len: the request number of bytes to read (up to 8 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 8 bytes of data from the extended register space on a
+ * Slave device using 16-bit address.
+ */
+extern int spmi_ext_register_readl(struct spmi_controller *ctrl,
+ u8 sid, u16 ad, u8 *buf, int len);
+
+/**
+ * spmi_register_write() - register write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ *
+ * Writes 1 byte of data to a Slave device register.
+ */
+extern int spmi_register_write(struct spmi_controller *ctrl,
+ u8 sid, u8 ad, u8 *buf);
+
+/**
+ * spmi_register_zero_write() - register zero write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @data: the data to be written to register 0 (7-bits).
+ *
+ * Writes data to register 0 of the Slave device.
+ */
+extern int spmi_register_zero_write(struct spmi_controller *ctrl,
+ u8 sid, u8 data);
+
+/**
+ * spmi_ext_register_write() - extended register write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 16 bytes).
+ *
+ * Writes up to 16 bytes of data to the extended register space of a
+ * Slave device.
+ */
+extern int spmi_ext_register_write(struct spmi_controller *ctrl,
+ u8 sid, u8 ad, u8 *buf, int len);
+
+/**
+ * spmi_ext_register_writel() - extended register write long
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 8 bytes).
+ *
+ * Writes up to 8 bytes of data to the extended register space of a
+ * Slave device using 16-bit address.
+ */
+extern int spmi_ext_register_writel(struct spmi_controller *ctrl,
+ u8 sid, u16 ad, u8 *buf, int len);
+
+/**
+ * spmi_command_reset() - sends RESET command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Reset command initializes the Slave and forces all registers to
+ * their reset values. The Slave shall enter the STARTUP state after
+ * receiving a Reset command.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_reset(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_sleep() - sends SLEEP command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Sleep command causes the Slave to enter the user defined SLEEP state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_sleep(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_wakeup() - sends WAKEUP command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Wakeup command causes the Slave to move from the SLEEP state to
+ * the ACTIVE state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_wakeup(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Shutdown command causes the Slave to enter the SHUTDOWN state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_shutdown(struct spmi_controller *ctrl, u8 sid);
+#endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 037cfe7..79fb177 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -277,6 +277,10 @@
unsigned hub_reset;
};
+struct msm_usb_host_platform_data {
+ unsigned int power_budget;
+};
+
struct usb_bam_pipe_connect {
u32 src_phy_addr;
int src_pipe_index;
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h
index 9595796..540a74c 100644
--- a/include/linux/usb/ulpi.h
+++ b/include/linux/usb/ulpi.h
@@ -145,6 +145,7 @@
#define ULPI_INT_SESS_VALID (1 << 2)
#define ULPI_INT_SESS_END (1 << 3)
#define ULPI_INT_IDGRD (1 << 4)
+#define ULPI_INT_DP (1 << 7)
/* Debug */
#define ULPI_DEBUG_LINESTATE0 (1 << 0)
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 1cd8448..8bb2558 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -56,6 +56,7 @@
struct vcd_frame_data {
u8 *virtual;
u8 *physical;
+ u32 ion_flag;
u32 alloc_len;
u32 data_len;
u32 offset;
diff --git a/include/media/msm/vidc_init.h b/include/media/msm/vidc_init.h
index 60cc35f..4e28c74 100644
--- a/include/media/msm/vidc_init.h
+++ b/include/media/msm/vidc_init.h
@@ -14,7 +14,8 @@
#ifndef VIDC_INIT_H
#define VIDC_INIT_H
#include <linux/ion.h>
-#include "vidc_type.h"
+#include <media/msm/vidc_type.h>
+#include <media/msm/vcd_property.h>
#define VIDC_MAX_NUM_CLIENTS 4
#define MAX_VIDEO_NUM_OF_BUFF 100
@@ -28,6 +29,7 @@
unsigned long user_vaddr;
unsigned long kernel_vaddr;
unsigned long phy_addr;
+ unsigned long buff_ion_flag;
struct ion_handle *buff_ion_handle;
int pmem_fd;
struct file *file;
@@ -63,6 +65,9 @@
void __iomem *vidc_get_ioaddr(void);
int vidc_load_firmware(void);
void vidc_release_firmware(void);
+u32 vidc_get_fd_info(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer, int pmem_fd,
+ unsigned long kvaddr, int index);
u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
enum buffer_dir buffer, u32 search_with_user_vaddr,
unsigned long *user_vaddr, unsigned long *kernel_vaddr,
@@ -76,6 +81,8 @@
u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
enum buffer_dir buffer, unsigned long user_vaddr,
unsigned long *kernel_vaddr);
+void vidc_cleanup_addr_table(struct video_client_ctx *client_ctx,
+ enum buffer_dir buffer);
u32 vidc_timer_create(void (*timer_handler)(void *),
void *user_data, void **timer_handle);
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 87fbbd2..867bd8a 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -184,10 +184,10 @@
_IOW(MSM_CAM_IOCTL_MAGIC, 51, uint32_t *)
#define MSM_CAM_IOCTL_GET_MCTL_INFO \
- _IOR(MSM_CAM_IOCTL_MAGIC, 51, struct msm_mctl_node_info *)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_mctl_node_info *)
#define MSM_CAM_IOCTL_MCTL_DIVERT_DONE \
- _IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_cam_evt_divert_frame *)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 53, struct msm_cam_evt_divert_frame *)
struct msm_mctl_pp_cmd {
int32_t id;
@@ -693,6 +693,9 @@
#define MSM_V4L2_CAM_OP_ZSL (MSM_V4L2_CAM_OP_DEFAULT+4)
/* camera operation mode for raw snapshot - one frame output queue */
#define MSM_V4L2_CAM_OP_RAW (MSM_V4L2_CAM_OP_DEFAULT+5)
+/* camera operation mode for jpeg snapshot - one frame output queue */
+#define MSM_V4L2_CAM_OP_JPEG_CAPTURE (MSM_V4L2_CAM_OP_DEFAULT+6)
+
#define MSM_V4L2_VID_CAP_TYPE 0
#define MSM_V4L2_STREAM_ON 1
@@ -762,8 +765,16 @@
#define CFG_GET_OUTPUT_INFO 32
#define CFG_GET_EEPROM_DATA 33
#define CFG_SET_ACTUATOR_INFO 34
-#define CFG_GET_ACTUATOR_INFO 35
-#define CFG_MAX 36
+#define CFG_GET_ACTUATOR_INFO 35
+/* TBD: QRD */
+#define CFG_SET_SATURATION 36
+#define CFG_SET_SHARPNESS 37
+#define CFG_SET_TOUCHAEC 38
+#define CFG_SET_AUTO_FOCUS 39
+#define CFG_SET_AUTOFLASH 40
+#define CFG_SET_EXPOSURE_COMPENSATION 41
+#define CFG_SET_ISO 42
+#define CFG_MAX 43
#define MOVE_NEAR 0
@@ -854,14 +865,6 @@
#define CAMERA_SETAE_AVERAGE 0
#define CAMERA_SETAE_CENWEIGHT 1
-#define CFG_SET_SATURATION 30
-#define CFG_SET_SHARPNESS 31
-#define CFG_SET_TOUCHAEC 32
-#define CFG_SET_AUTO_FOCUS 33
-#define CFG_SET_AUTOFLASH 34
-/* QRD */
-#define CFG_SET_EXPOSURE_COMPENSATION 35
-
#define CAMERA_WB_AUTO 1 /* This list must match aeecamera.h */
#define CAMERA_WB_CUSTOM 2
#define CAMERA_WB_INCANDESCENT 3
@@ -945,6 +948,14 @@
MSM_V4L2_POWER_LINE_AUTO,
};
+#define CAMERA_ISO_TYPE_AUTO 0
+#define CAMEAR_ISO_TYPE_HJR 1
+#define CAMEAR_ISO_TYPE_100 2
+#define CAMERA_ISO_TYPE_200 3
+#define CAMERA_ISO_TYPE_400 4
+#define CAMEAR_ISO_TYPE_800 5
+#define CAMERA_ISO_TYPE_1600 6
+
struct sensor_pict_fps {
uint16_t prevfps;
uint16_t pictfps;
@@ -1080,6 +1091,7 @@
uint16_t pictp_pl;
uint32_t pict_max_exp_lc;
uint16_t p_fps;
+ uint8_t iso_type;
struct sensor_init_cfg init_info;
struct sensor_pict_fps gfps;
struct exp_gain_cfg exp_gain;
@@ -1125,6 +1137,10 @@
uint32_t f_pix_den;
uint32_t total_f_dist_num;
uint32_t total_f_dist_den;
+ uint32_t hor_view_angle_num;
+ uint32_t hor_view_angle_den;
+ uint32_t ver_view_angle_num;
+ uint32_t ver_view_angle_den;
};
struct msm_actuator_cfg_data {
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 5dd1445..07784e2 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -241,6 +241,9 @@
#define VPE_SCALER_CONFIG_LEN 260
#define VPE_DIS_OFFSET_CFG_LEN 12
+#define IMEM_Y_OFFSET 0x2E000000
+#define IMEM_CBCR_OFFSET 0x2E00FA00
+
struct msm_vpe_op_mode_cfg {
uint8_t op_mode_cfg[VPE_OPERATION_MODE_CFG_LEN];
};
@@ -311,6 +314,8 @@
#define VFE_OUTPUTS_PREVIEW BIT(6)
#define VFE_OUTPUTS_VIDEO BIT(7)
#define VFE_OUTPUTS_RAW BIT(8)
+#define VFE_OUTPUTS_JPEG_AND_THUMB BIT(9)
+#define VFE_OUTPUTS_THUMB_AND_JPEG BIT(10)
#endif /*__MSM_ISP_H__*/
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 36139ba..de2b356 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -590,7 +590,8 @@
IRIS_EVT_NEW_SRCH_LIST,
IRIS_EVT_NEW_AF_LIST,
IRIS_EVT_TXRDSDAT,
- IRIS_EVT_TXRDSDONE
+ IRIS_EVT_TXRDSDONE,
+ IRIS_EVT_RADIO_DISABLED
};
enum emphasis_type {
FM_RX_EMP75 = 0x0,
@@ -674,7 +675,7 @@
/* Band limits */
#define REGION_US_EU_BAND_LOW 87500
-#define REGION_US_EU_BAND_HIGH 107900
+#define REGION_US_EU_BAND_HIGH 108000
#define REGION_JAPAN_STANDARD_BAND_LOW 76000
#define REGION_JAPAN_STANDARD_BAND_HIGH 90000
#define REGION_JAPAN_WIDE_BAND_LOW 90000
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8e66a25..164d3b4 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -931,7 +931,7 @@
if (conn->sec_level == BT_SECURITY_SDP)
conn->sec_level = BT_SECURITY_LOW;
- if (conn->pending_sec_level > conn->sec_level)
+ if (!status && encrypt && conn->pending_sec_level > conn->sec_level)
conn->sec_level = conn->pending_sec_level;
hci_proto_encrypt_cfm(conn, status, encrypt);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 312de3f..d5c4189 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -489,6 +489,7 @@
__u8 fixed_channel;
__u8 num_conf_req;
__u8 num_conf_rsp;
+ __u8 incoming;
__u8 fcs;
__u8 sec_level;
@@ -648,6 +649,8 @@
#define L2CAP_AMP_STATE_RESEGMENT 12
#define L2CAP_ATT_ERROR 0x01
+#define L2CAP_ATT_MTU_REQ 0x02
+#define L2CAP_ATT_MTU_RSP 0x03
#define L2CAP_ATT_RESPONSE_BIT 0x01
#define L2CAP_ATT_INDICATE 0x1D
#define L2CAP_ATT_NOT_SUPPORTED 0x06
@@ -689,6 +692,8 @@
void l2cap_sock_init(struct sock *sk, struct sock *parent);
struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
int proto, gfp_t prio);
+struct sock *l2cap_find_sock_by_fixed_cid_and_dir(__le16 cid, bdaddr_t *src,
+ bdaddr_t *dst, int server);
void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err);
void l2cap_chan_del(struct sock *sk, int err);
int l2cap_do_connect(struct sock *sk);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 47bfde5..4c2bd37 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -561,6 +561,19 @@
goto done;
}
+ if (!skb_queue_empty(&hdev->cmd_q)) {
+ BT_ERR("command queue is not empty, purging");
+ skb_queue_purge(&hdev->cmd_q);
+ }
+ if (!skb_queue_empty(&hdev->rx_q)) {
+ BT_ERR("rx queue is not empty, purging");
+ skb_queue_purge(&hdev->rx_q);
+ }
+ if (!skb_queue_empty(&hdev->raw_q)) {
+ BT_ERR("raw queue is not empty, purging");
+ skb_queue_purge(&hdev->raw_q);
+ }
+
if (!test_bit(HCI_RAW, &hdev->flags)) {
atomic_set(&hdev->cmd_cnt, 1);
set_bit(HCI_INIT, &hdev->flags);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b4dde4c..9662795 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -930,18 +930,24 @@
}
/* Find socket with fixed cid with given source and destination bdaddrs.
- * Returns closest match, locked.
+ * Direction of the req/rsp must match.
*/
-static struct sock *l2cap_get_sock_by_fixed_scid(int state,
- __le16 cid, bdaddr_t *src, bdaddr_t *dst)
+struct sock *l2cap_find_sock_by_fixed_cid_and_dir(__le16 cid, bdaddr_t *src,
+ bdaddr_t *dst, int incoming)
{
struct sock *sk = NULL, *sk1 = NULL;
struct hlist_node *node;
+ BT_DBG(" %d", incoming);
+
read_lock(&l2cap_sk_list.lock);
sk_for_each(sk, node, &l2cap_sk_list.head) {
- if (state && sk->sk_state != state)
+
+ if (incoming && !l2cap_pi(sk)->incoming)
+ continue;
+
+ if (!incoming && l2cap_pi(sk)->incoming)
continue;
if (l2cap_pi(sk)->scid == cid && !bacmp(&bt_sk(sk)->dst, dst)) {
@@ -1022,13 +1028,12 @@
l2cap_sock_init(sk, parent);
bacpy(&bt_sk(sk)->src, conn->src);
bacpy(&bt_sk(sk)->dst, conn->dst);
+ l2cap_pi(sk)->incoming = 1;
bt_accept_enqueue(parent, sk);
__l2cap_chan_add(conn, sk);
- l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-
sk->sk_state = BT_CONNECTED;
parent->sk_data_ready(parent, 0);
@@ -1061,10 +1066,10 @@
if (pending_sec > sec_level)
sec_level = pending_sec;
- if (smp_conn_security(conn, sec_level)) {
+ if (smp_conn_security(conn, sec_level))
l2cap_chan_ready(sk);
- hci_conn_put(conn->hcon);
- }
+
+ hci_conn_put(conn->hcon);
} else if (sk->sk_type != SOCK_SEQPACKET &&
sk->sk_type != SOCK_STREAM) {
@@ -1081,6 +1086,9 @@
}
read_unlock(&l->lock);
+
+ if (conn->hcon->out && conn->hcon->type == LE_LINK)
+ l2cap_le_conn_ready(conn);
}
/* Notify sockets that we cannot guaranty reliability anymore */
@@ -3035,7 +3043,8 @@
{
lock_sock(sk);
- if (l2cap_pi(sk)->mode != L2CAP_MODE_ERTM) {
+ if (l2cap_pi(sk)->mode != L2CAP_MODE_ERTM ||
+ sk->sk_state != BT_CONNECTED) {
release_sock(sk);
return;
}
@@ -7209,15 +7218,24 @@
return 0;
}
-static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
+static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid,
+ struct sk_buff *skb)
{
struct sock *sk;
struct sk_buff *skb_rsp;
struct l2cap_hdr *lh;
+ int dir;
+ u8 mtu_rsp[] = {L2CAP_ATT_MTU_RSP, 23, 0};
u8 err_rsp[] = {L2CAP_ATT_ERROR, 0x00, 0x00, 0x00,
L2CAP_ATT_NOT_SUPPORTED};
- sk = l2cap_get_sock_by_fixed_scid(0, cid, conn->src, conn->dst);
+ dir = (skb->data[0] & L2CAP_ATT_RESPONSE_BIT) ? 0 : 1;
+
+ sk = l2cap_find_sock_by_fixed_cid_and_dir(cid, conn->src,
+ conn->dst, dir);
+
+ BT_DBG("sk %p, dir:%d", sk, dir);
+
if (!sk)
goto drop;
@@ -7231,6 +7249,22 @@
if (l2cap_pi(sk)->imtu < skb->len)
goto drop;
+ if (skb->data[0] == L2CAP_ATT_MTU_REQ) {
+ skb_rsp = bt_skb_alloc(sizeof(mtu_rsp) + L2CAP_HDR_SIZE,
+ GFP_ATOMIC);
+ if (!skb_rsp)
+ goto drop;
+
+ lh = (struct l2cap_hdr *) skb_put(skb_rsp, L2CAP_HDR_SIZE);
+ lh->len = cpu_to_le16(sizeof(mtu_rsp));
+ lh->cid = cpu_to_le16(L2CAP_CID_LE_DATA);
+ memcpy(skb_put(skb_rsp, sizeof(mtu_rsp)), mtu_rsp,
+ sizeof(mtu_rsp));
+ hci_send_acl(conn->hcon, NULL, skb_rsp, 0);
+
+ goto free_skb;
+ }
+
if (!sock_queue_rcv_skb(sk, skb))
goto done;
@@ -7333,7 +7367,7 @@
struct hlist_node *node;
if (type != ACL_LINK)
- return -EINVAL;
+ return 0;
BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
@@ -7424,6 +7458,7 @@
struct l2cap_chan_list *l;
struct l2cap_conn *conn = hcon->l2cap_data;
struct sock *sk;
+ int smp = 0;
if (!conn)
return 0;
@@ -7445,9 +7480,7 @@
l2cap_chan_ready(sk);
}
- del_timer(&hcon->smp_timer);
- smp_link_encrypt_cmplt(conn, status, encrypt);
-
+ smp = 1;
bh_unlock_sock(sk);
continue;
}
@@ -7511,6 +7544,11 @@
read_unlock(&l->lock);
+ if (smp) {
+ del_timer(&hcon->smp_timer);
+ smp_link_encrypt_cmplt(conn, status, encrypt);
+ }
+
return 0;
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 94cacde..6a4a2f0 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -611,8 +611,16 @@
case L2CAP_MODE_BASIC:
l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
break;
- case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
+ if (!disable_ertm) {
+ /* No fallback to ERTM or Basic mode */
+ l2cap_pi(sk)->conf_state |=
+ L2CAP_CONF_STATE2_DEVICE;
+ break;
+ }
+ err = -EINVAL;
+ break;
+ case L2CAP_MODE_ERTM:
if (!disable_ertm)
break;
/* fall through */
@@ -957,7 +965,8 @@
else
err = bt_sock_recvmsg(iocb, sock, msg, len, flags);
- l2cap_ertm_recv_done(sk);
+ if (err >= 0)
+ l2cap_ertm_recv_done(sk);
return err;
}
@@ -1096,6 +1105,7 @@
static int l2cap_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
+ struct sock *srv_sk = NULL;
int err;
BT_DBG("sock %p, sk %p", sock, sk);
@@ -1103,6 +1113,16 @@
if (!sk)
return 0;
+ /* If this is an ATT Client socket, find the matching Server */
+ if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA && !l2cap_pi(sk)->incoming)
+ srv_sk = l2cap_find_sock_by_fixed_cid_and_dir(L2CAP_CID_LE_DATA,
+ &bt_sk(sk)->src, &bt_sk(sk)->dst, 1);
+
+ /* If server socket found, request tear down */
+ BT_DBG("client:%p server:%p", sk, srv_sk);
+ if (srv_sk)
+ l2cap_sock_set_timer(srv_sk, 1);
+
err = l2cap_sock_shutdown(sock, 2);
sock_orphan(sk);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 2e4c47a..910ef77 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -762,7 +762,7 @@
struct list_head *p;
size_t name_len;
- name_len = strlen(hdev->dev_name);
+ name_len = strnlen(hdev->dev_name, HCI_MAX_EIR_LENGTH);
if (name_len > 0) {
/* EIR Data type */
@@ -890,13 +890,17 @@
list_add(&uuid->list, &hdev->uuids);
- err = update_class(hdev);
- if (err < 0)
- goto failed;
+ if (test_bit(HCI_UP, &hdev->flags)) {
- err = update_eir(hdev);
- if (err < 0)
- goto failed;
+ err = update_class(hdev);
+ if (err < 0)
+ goto failed;
+
+ err = update_eir(hdev);
+ if (err < 0)
+ goto failed;
+ } else
+ err = 0;
err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
@@ -950,13 +954,16 @@
goto unlock;
}
- err = update_class(hdev);
- if (err < 0)
- goto unlock;
+ if (test_bit(HCI_UP, &hdev->flags)) {
+ err = update_class(hdev);
+ if (err < 0)
+ goto unlock;
- err = update_eir(hdev);
- if (err < 0)
- goto unlock;
+ err = update_eir(hdev);
+ if (err < 0)
+ goto unlock;
+ } else
+ err = 0;
err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
@@ -991,7 +998,10 @@
hdev->major_class |= cp->major & MGMT_MAJOR_CLASS_MASK;
hdev->minor_class = cp->minor;
- err = update_class(hdev);
+ if (test_bit(HCI_UP, &hdev->flags))
+ err = update_class(hdev);
+ else
+ err = 0;
if (err == 0)
err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
@@ -1027,9 +1037,12 @@
err = 0;
} else {
clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
- err = update_class(hdev);
- if (err == 0)
- err = update_eir(hdev);
+ if (test_bit(HCI_UP, &hdev->flags)) {
+ err = update_class(hdev);
+ if (err == 0)
+ err = update_eir(hdev);
+ } else
+ err = 0;
}
if (err == 0)
@@ -1514,6 +1527,7 @@
}
pairing_complete(cmd, status);
+ hci_conn_put(conn);
}
static void pairing_security_complete_cb(struct hci_conn *conn, u8 status)
@@ -1936,12 +1950,14 @@
if (hdev->disco_state != SCAN_IDLE) {
struct hci_cp_le_set_scan_enable le_cp = {0, 0};
- if (hdev->disco_state == SCAN_LE)
- hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
+ if (test_bit(HCI_UP, &hdev->flags)) {
+ if (hdev->disco_state == SCAN_LE)
+ hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
sizeof(le_cp), &le_cp);
- else
- hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
-
+ else
+ hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0,
+ NULL);
+ }
hdev->disco_state = SCAN_IDLE;
}
@@ -1969,18 +1985,20 @@
hci_dev_lock_bh(hdev);
- if (hdev->disco_state == SCAN_LE)
- hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
- sizeof(le_cp), &le_cp);
+ if (test_bit(HCI_UP, &hdev->flags)) {
+ if (hdev->disco_state == SCAN_LE)
+ hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
+ sizeof(le_cp), &le_cp);
/* re-start BR scan */
- if (hdev->disco_state != SCAN_IDLE) {
- struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
- hdev->disco_int_phase *= 2;
- hdev->disco_int_count = 0;
- cp.num_rsp = (u8) hdev->disco_int_phase;
- hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
- hdev->disco_state = SCAN_BR;
+ if (hdev->disco_state != SCAN_IDLE) {
+ struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
+ hdev->disco_int_phase *= 2;
+ hdev->disco_int_count = 0;
+ cp.num_rsp = (u8) hdev->disco_int_phase;
+ hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
+ hdev->disco_state = SCAN_BR;
+ }
}
hci_dev_unlock_bh(hdev);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 3b1e54c..99c4559 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -917,7 +917,7 @@
int lm = 0;
if (type != SCO_LINK && type != ESCO_LINK)
- return -EINVAL;
+ return 0;
BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index e301edf..2484a9a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -652,6 +652,7 @@
static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
{
struct key_master_id *master;
+ u8 sec_level;
u8 zerobuf[8];
if (!hcon || !key || !key->data)
@@ -666,6 +667,17 @@
hcon->enc_key_size = key->pin_len;
hcon->sec_req = TRUE;
+ sec_level = authreq_to_seclevel(key->auth);
+
+ BT_DBG("cur %d, req: %d", hcon->sec_level, sec_level);
+
+ if (sec_level > hcon->sec_level)
+ hcon->pending_sec_level = sec_level;
+
+
+ if (!(hcon->link_mode & HCI_LM_ENCRYPT))
+ hci_conn_hold(hcon);
+
hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
return 0;
@@ -690,11 +702,6 @@
if (smp_encrypt_link(hcon, key) < 0)
goto invalid_key;
- hcon->sec_level = authreq_to_seclevel(key->auth);
-
- if (!(hcon->link_mode & HCI_LM_ENCRYPT))
- hci_conn_hold(hcon);
-
return 0;
}
@@ -729,33 +736,26 @@
struct hci_conn *hcon = conn->hcon;
__u8 authreq;
- BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
+ BT_DBG("conn %p hcon %p %d req: %d",
+ conn, hcon, hcon->sec_level, sec_level);
- if (IS_ERR(hcon->hdev->tfm)) {
- BT_DBG("IS_ERR");
+ if (IS_ERR(hcon->hdev->tfm))
return 1;
- }
- if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
- BT_DBG("HCI_CONN_ENCRYPT_PEND");
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
return -EINPROGRESS;
- }
- if (sec_level == BT_SECURITY_LOW) {
- BT_DBG("BT_SECURITY_LOW");
+ if (sec_level == BT_SECURITY_LOW)
return 1;
- }
- if (hcon->sec_level > sec_level) {
- BT_DBG("hcon->sec_level > sec_level");
+
+ if (hcon->sec_level >= sec_level)
return 1;
- }
authreq = seclevel_to_authreq(sec_level);
- BT_ERR("conn = %p, sec: %d", conn, sec_level);
hcon->smp_conn = conn;
- hcon->sec_level = sec_level;
+ hcon->pending_sec_level = sec_level;
if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
struct link_key *key;
@@ -785,6 +785,7 @@
msecs_to_jiffies(SMP_TIMEOUT));
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+ hci_conn_hold(hcon);
} else {
struct smp_cmd_security_req cp;
cp.auth_req = authreq;
@@ -792,7 +793,6 @@
}
done:
- hcon->pending_sec_level = sec_level;
set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
return 0;
@@ -1045,15 +1045,17 @@
clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+ if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
+ hcon->sec_level = hcon->pending_sec_level;
+
if (!status && encrypt && !hcon->sec_req)
- smp_distribute_keys(conn, 0);
+ return smp_distribute_keys(conn, 0);
/* Fall back to Pairing request if failed a Link Security request */
else if (hcon->sec_req && (status || !encrypt))
- smp_conn_security(conn, hcon->sec_level);
+ smp_conn_security(conn, hcon->pending_sec_level);
- else
- hci_conn_put(hcon);
+ hci_conn_put(hcon);
return 0;
}
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index ac7f050..46f6461 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -49,7 +49,8 @@
#define AIF1_PB 1
#define AIF1_CAP 2
-#define NUM_CODEC_DAIS 2
+#define AIF2_PB 3
+#define NUM_CODEC_DAIS 3
struct tabla_codec_dai_data {
u32 rate;
@@ -570,6 +571,8 @@
-84, 40, digital_gain),
SOC_SINGLE_S8_TLV("RX6 Digital Volume", TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
-84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX7 Digital Volume", TABLA_A_CDC_RX7_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
SOC_SINGLE_S8_TLV("DEC1 Volume", TABLA_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
digital_gain),
@@ -2086,71 +2089,99 @@
{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX1 MIX1 INP1", "IIR1", "IIR1"},
{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX1 MIX1 INP2", "IIR1", "IIR1"},
{"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP1", "IIR1", "IIR1"},
{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP2", "IIR1", "IIR1"},
{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX3 MIX1 INP1", "IIR1", "IIR1"},
{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX3 MIX1 INP2", "IIR1", "IIR1"},
{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX4 MIX1 INP1", "IIR1", "IIR1"},
{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX4 MIX1 INP2", "IIR1", "IIR1"},
{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX5 MIX1 INP1", "IIR1", "IIR1"},
{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX5 MIX1 INP2", "IIR1", "IIR1"},
{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX6 MIX1 INP1", "IIR1", "IIR1"},
{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX6 MIX1 INP2", "IIR1", "IIR1"},
{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX7 MIX1 INP1", "IIR1", "IIR1"},
{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX7 MIX1 INP2", "IIR1", "IIR1"},
/* Decimator Inputs */
@@ -2633,7 +2664,7 @@
}
pr_debug("%s: DAI-ID %x %d %d\n", __func__, dai->id, tx_num, rx_num);
- if (dai->id == AIF1_PB) {
+ if (dai->id == AIF1_PB || dai->id == AIF2_PB) {
for (i = 0; i < rx_num; i++) {
tabla->dai[dai->id - 1].ch_num[i] = rx_slot[i];
tabla->dai[dai->id - 1].ch_act = 0;
@@ -2681,6 +2712,12 @@
tx_slot[cnt] = tx_ch[6 + cnt];
cnt++;
}
+ } else if (dai->id == AIF2_PB) {
+ *rx_num = tabla_dai[dai->id - 1].playback.channels_max;
+ while (cnt < *rx_num) {
+ rx_slot[cnt] = rx_ch[5 + cnt];
+ cnt++;
+ }
}
return 0;
}
@@ -2778,7 +2815,7 @@
* If current dai is a rx dai, set sample rate to
* all the rx paths that are currently not active
*/
- if (dai->id == AIF1_PB) {
+ if (dai->id == AIF1_PB || dai->id == AIF2_PB) {
rx_state = snd_soc_read(codec,
TABLA_A_CDC_CLK_RX_B1_CTL);
@@ -2858,6 +2895,20 @@
},
.ops = &tabla_dai_ops,
},
+ {
+ .name = "tabla_rx2",
+ .id = AIF2_PB,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .rates = WCD9310_RATES,
+ .formats = TABLA_FORMATS,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &tabla_dai_ops,
+ },
};
static struct snd_soc_dai_driver tabla_i2s_dai[] = {
@@ -2963,7 +3014,8 @@
switch (event) {
case SND_SOC_DAPM_POST_PMU:
for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
- if (tabla_dai[j].id == AIF1_PB)
+ if (tabla_dai[j].id == AIF1_PB ||
+ tabla_dai[j].id == AIF2_PB)
continue;
if (!strncmp(w->sname,
tabla_dai[j].capture.stream_name, 13)) {
@@ -2979,7 +3031,8 @@
break;
case SND_SOC_DAPM_POST_PMD:
for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
- if (tabla_dai[j].id == AIF1_PB)
+ if (tabla_dai[j].id == AIF1_PB ||
+ tabla_dai[j].id == AIF2_PB)
continue;
if (!strncmp(w->sname,
tabla_dai[j].capture.stream_name, 13)) {
@@ -3022,6 +3075,13 @@
SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX6", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX7", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
/* Headphone */
SND_SOC_DAPM_OUTPUT("HEADPHONE"),
SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
@@ -3789,19 +3849,15 @@
struct tabla_mbhc_general_cfg *generic;
struct tabla_mbhc_btn_detect_cfg *btn_det;
int n;
- u8 tabla_ver;
u8 *n_cic, *gain;
+ struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
tabla = snd_soc_codec_get_drvdata(codec);
generic = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
- tabla_ver = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
- tabla_ver &= 0x1F;
-
for (n = 0; n < 8; n++) {
- if ((tabla_ver != TABLA_VERSION_1_0 &&
- tabla_ver != TABLA_VERSION_1_1) || n != 7) {
+ if ((!TABLA_IS_1_X(tabla_core->version)) || n != 7) {
snd_soc_update_bits(codec,
TABLA_A_CDC_MBHC_FEATURE_B1_CFG,
0x07, n);
@@ -5043,6 +5099,9 @@
case AIF1_CAP:
ch_cnt = tabla_dai[i].capture.channels_max;
break;
+ case AIF2_PB:
+ ch_cnt = tabla_dai[i].playback.channels_max;
+ break;
default:
continue;
}
@@ -5197,13 +5256,32 @@
},
};
+static struct platform_driver tabla1x_codec_driver = {
+ .probe = tabla_probe,
+ .remove = tabla_remove,
+ .driver = {
+ .name = "tabla1x_codec",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &tabla_pm_ops,
+#endif
+ },
+};
+
static int __init tabla_codec_init(void)
{
- return platform_driver_register(&tabla_codec_driver);
+ int rtn = platform_driver_register(&tabla_codec_driver);
+ if (rtn == 0) {
+ rtn = platform_driver_register(&tabla1x_codec_driver);
+ if (rtn != 0)
+ platform_driver_unregister(&tabla_codec_driver);
+ }
+ return rtn;
}
static void __exit tabla_codec_exit(void)
{
+ platform_driver_unregister(&tabla1x_codec_driver);
platform_driver_unregister(&tabla_codec_driver);
}
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 1b3014e..6f2d651 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -56,7 +56,7 @@
obj-$(CONFIG_SND_SOC_MSM_QDSP6_INTF) += qdsp6/
-snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o msm-dai-stub.o
obj-$(CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO) += msm-dai-q6-hdmi.o
obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o
snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index b515090..bcf6784 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -310,7 +310,6 @@
if (clk_users != 1)
return 0;
- codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
if (codec_clk) {
clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
clk_enable(codec_clk);
@@ -329,7 +328,6 @@
pr_debug("%s: disabling MCLK. clk_users = %d\n",
__func__, clk_users);
clk_disable(codec_clk);
- clk_put(codec_clk);
tabla_mclk_enable(codec, 0);
}
}
@@ -350,7 +348,6 @@
if (clk_users != 1)
return 0;
- codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
if (codec_clk) {
clk_set_rate(codec_clk, 12288000);
clk_enable(codec_clk);
@@ -376,7 +373,6 @@
__func__, clk_users);
clk_disable(codec_clk);
- clk_put(codec_clk);
tabla_mclk_enable(w->codec, 0);
}
break;
@@ -736,8 +732,9 @@
int err;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- pr_debug("%s()\n", __func__);
+ pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
/*if (machine_is_msm_liquid()) {
top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
@@ -779,6 +776,8 @@
return err;
}
+ codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+
tabla_hs_detect(codec, &hs_jack, &button_jack, tabla_mbhc_cal,
TABLA_MICBIAS2, msm_enable_codec_ext_clk, 0,
TABLA_EXT_CLK_RATE);
@@ -865,6 +864,23 @@
return 0;
}
+static int msm_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+ channels->min, channels->max);
+
+ rate->min = rate->max = 48000;
+
+ return 0;
+}
+
static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -1084,6 +1100,17 @@
.platform_name = "msm-pcm-afe",
.ignore_suspend = 1,
},
+ {
+ .name = "Voice Stub",
+ .stream_name = "Voice Stub",
+ .cpu_dai_name = "VOICE_STUB",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dsp_link = &fe_media,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* .be_id = do not care */
+ },
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
@@ -1160,14 +1187,14 @@
{
.name = LPASS_BE_HDMI,
.stream_name = "HDMI Playback",
- .cpu_dai_name = "msm-dai-q6.8",
+ .cpu_dai_name = "msm-dai-q6-hdmi.8",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.no_codec = 1,
.be_id = MSM_BACKEND_DAI_HDMI_RX,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_hdmi_be_hw_params_fixup,
},
/* Backend AFE DAI Links */
{
@@ -1216,6 +1243,30 @@
.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
},
+ {
+ .name = LPASS_BE_STUB_RX,
+ .stream_name = "Stub Playback",
+ .cpu_dai_name = "msm-dai-stub",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tabla_codec",
+ .codec_dai_name = "tabla_rx2",
+ .no_pcm = 1,
+ /* .be_id = do not care */
+ .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ },
+ {
+ .name = LPASS_BE_STUB_TX,
+ .stream_name = "Stub Capture",
+ .cpu_dai_name = "msm-dai-stub",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tabla_codec",
+ .codec_dai_name = "tabla_tx1",
+ .no_pcm = 1,
+ /* .be_id = do not care */
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ },
};
struct snd_soc_card snd_soc_card_msm = {
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 8f71e83..14d9adf 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -271,6 +271,28 @@
.ops = &msm_fe_dai_ops,
.name = "AUXPCM_HOSTLESS",
},
+ {
+ .playback = {
+ .stream_name = "Voice Stub Playback",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "Voice Stub Capture",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "VOICE_STUB",
+ },
};
static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index aff87ae..070dc7b 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -100,6 +100,7 @@
break;
}
}
+ dai_data->rate = params_rate(params);
/* Q6 only supports 16 as now */
dai_data->port_config.mi2s.bitwidth = 16;
@@ -618,7 +619,7 @@
* data to the cpu driver, since cpu drive is unaware of any
* boarc specific configuration.
*/
- pcm_clk = clk_get(NULL, auxpcm_pdata->clk);
+ pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
if (IS_ERR(pcm_clk)) {
pr_err("%s: could not get pcm_clk\n", __func__);
return PTR_ERR(pcm_clk);
diff --git a/sound/soc/msm/msm-dai-stub.c b/sound/soc/msm/msm-dai-stub.c
new file mode 100644
index 0000000..b2bfa2c
--- /dev/null
+++ b/sound/soc/msm/msm-dai-stub.c
@@ -0,0 +1,102 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+static int msm_dai_stub_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_slot,
+ unsigned int rx_num, unsigned int *rx_slot)
+{
+ pr_debug("%s:\n", __func__);
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops msm_dai_stub_ops = {
+ .set_channel_map = msm_dai_stub_set_channel_map,
+};
+
+static struct snd_soc_dai_driver msm_dai_stub_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_stub_ops,
+};
+
+static __devinit int msm_dai_stub_dev_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+
+ dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
+
+ rc = snd_soc_register_dai(&pdev->dev, &msm_dai_stub_dai);
+
+ return rc;
+}
+
+static __devexit int msm_dai_stub_dev_remove(struct platform_device *pdev)
+{
+ pr_debug("%s:\n", __func__);
+
+ snd_soc_unregister_dai(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver msm_dai_stub_driver = {
+ .probe = msm_dai_stub_dev_probe,
+ .remove = msm_dai_stub_dev_remove,
+ .driver = {
+ .name = "msm-dai-stub",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_dai_stub_init(void)
+{
+ pr_debug("%s:\n", __func__);
+
+ return platform_driver_register(&msm_dai_stub_driver);
+}
+module_init(msm_dai_stub_init);
+
+static void __exit msm_dai_stub_exit(void)
+{
+ pr_debug("%s:\n", __func__);
+
+ platform_driver_unregister(&msm_dai_stub_driver);
+}
+module_exit(msm_dai_stub_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MSM Stub DSP DAI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 0a29016..0b7cc78 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,9 @@
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/android_pmem.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
#include "msm-pcm-q6.h"
#include "msm-pcm-routing.h"
@@ -99,6 +102,8 @@
break;
} else
atomic_set(&prtd->pending_buffer, 0);
+ if (runtime->status->hw_ptr >= runtime->control->appl_ptr)
+ break;
pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
__func__, prtd->pcm_count);
@@ -134,6 +139,9 @@
case ASM_SESSION_CMD_RUN: {
if (!atomic_read(&prtd->pending_buffer))
break;
+ if (runtime->status->hw_ptr >=
+ runtime->control->appl_ptr)
+ break;
pr_debug("%s:writing %d bytes"
" of buffer to dsp\n",
__func__, prtd->pcm_count);
@@ -340,8 +348,26 @@
struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
struct msm_audio *prtd = runtime->private_data;
int dir = 0;
+ int rc = 0;
- pr_debug("%s\n", __func__);
+ /*
+ If routing is still enabled, we need to issue EOS to
+ the DSP
+ To issue EOS to dsp, we need to be run state otherwise
+ EOS is not honored.
+ */
+ if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id)) {
+ rc = q6asm_run(prtd->audio_client, 0, 0, 0);
+ atomic_set(&prtd->pending_buffer, 0);
+ prtd->cmd_ack = 0;
+ q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+ pr_debug("%s\n", __func__);
+ rc = wait_event_timeout(the_locks.eos_wait,
+ prtd->cmd_ack, 5 * HZ);
+ if (rc < 0)
+ pr_err("EOS cmd timeout\n");
+ prtd->pcm_irq_pos = 0;
+ }
dir = IN;
atomic_set(&prtd->pending_buffer, 0);
@@ -436,7 +462,8 @@
return -ENOMEM;
}
buf = prtd->audio_client->port[dir].buf;
- if (!buf && !buf[0].data)
+
+ if (buf == NULL || buf[0].data == NULL)
return -ENOMEM;
pr_debug("%s:buf = %p\n", __func__, buf);
@@ -459,9 +486,39 @@
int rc = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct msm_audio *prtd = runtime->private_data;
+ uint64_t timestamp;
+ uint64_t temp;
switch (cmd) {
+ case SNDRV_COMPRESS_TSTAMP: {
+ struct snd_compr_tstamp tstamp;
+ pr_debug("SNDRV_COMPRESS_TSTAMP\n");
+
+ memset(&tstamp, 0x0, sizeof(struct snd_compr_tstamp));
+ timestamp = q6asm_get_session_time(prtd->audio_client);
+ if (timestamp < 0) {
+ pr_err("%s: Get Session Time return value =%lld\n",
+ __func__, timestamp);
+ return -EAGAIN;
+ }
+ temp = (timestamp * 2 * runtime->channels);
+ temp = temp * (runtime->rate/1000);
+ temp = div_u64(temp, 1000);
+ tstamp.sampling_rate = runtime->rate;
+ tstamp.rendered = (size_t)(temp & 0xFFFFFFFF);
+ tstamp.decoded = (size_t)((temp >> 32) & 0xFFFFFFFF);
+ tstamp.timestamp = timestamp;
+ pr_debug("%s: bytes_consumed:lsb = %d, msb = %d,"
+ "timestamp = %lld,\n",
+ __func__, tstamp.rendered, tstamp.decoded,
+ tstamp.timestamp);
+ if (copy_to_user((void *) arg, &tstamp,
+ sizeof(struct snd_compr_tstamp)))
+ return -EFAULT;
+ return 0;
+ }
case SNDRV_PCM_IOCTL1_RESET:
+ prtd->cmd_ack = 0;
rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
if (rc < 0)
pr_err("%s: flush cmd failed rc=%d\n", __func__, rc);
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 8b6b5f1..b01c22c 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -46,6 +46,7 @@
static struct mutex routing_lock;
static int fm_switch_enable;
+
#define INT_FM_RX_VOL_MAX_STEPS 100
#define INT_FM_RX_VOL_GAIN 2000
@@ -1229,6 +1230,11 @@
0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VOICE_STUB_UL", "VOICE_STUB Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("STUB_RX", "Stub Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("STUB_TX", "Stub Capture", 0, 0, 0, 0),
+
/* Switch Definitions */
SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
&fm_switch_mixer_controls),
@@ -1432,6 +1438,8 @@
{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
+ {"STUB_RX", NULL, "VOICE_STUB_DL"},
+ {"VOICE_STUB_UL", NULL, "STUB_TX"},
};
static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
@@ -1636,6 +1644,23 @@
.remove = __devexit_p(msm_routing_pcm_remove),
};
+int msm_routing_check_backend_enabled(int fedai_id)
+{
+ int i;
+ if (fedai_id >= MSM_FRONTEND_DAI_MM_MAX_ID) {
+ /* bad ID assigned in machine driver */
+ pr_err("%s: bad MM ID\n", __func__);
+ return 0;
+ }
+ for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+ if ((test_bit(fedai_id,
+ &msm_bedais[i].fe_sessions))) {
+ return msm_bedais[i].active;
+ }
+ }
+ return 0;
+}
+
static int __init msm_soc_routing_platform_init(void)
{
mutex_init(&routing_lock);
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 25efb58..9515ab3 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -32,6 +32,8 @@
#define LPASS_BE_SEC_I2S_RX "(Backend) SECONDARY_I2S_RX"
#define LPASS_BE_MI2S_RX "(Backend) MI2S_RX"
+#define LPASS_BE_STUB_RX "(Backend) STUB_RX"
+#define LPASS_BE_STUB_TX "(Backend) STUB_TX"
/* For multimedia front-ends, asm session is allocated dynamically.
* Hence, asm session/multimedia front-end mapping has to be maintained.
@@ -85,4 +87,6 @@
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
int lpa_set_volume(unsigned volume);
+
+int msm_routing_check_backend_enabled(int fedai_id);
#endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index eafe0f9..471284b 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -129,7 +129,7 @@
struct snd_pcm_runtime *runtime = substream->runtime;
struct msm_voice *prtd = runtime->private_data;
- int ret;
+ int ret = 0;
mutex_lock(&prtd->lock);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index bedfd68..eb363e7 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -309,7 +309,6 @@
if (clk_users != 1)
return 0;
- codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
if (codec_clk) {
clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
clk_enable(codec_clk);
@@ -328,7 +327,6 @@
pr_debug("%s: disabling MCLK. clk_users = %d\n",
__func__, clk_users);
clk_disable(codec_clk);
- clk_put(codec_clk);
tabla_mclk_enable(codec, 0);
}
}
@@ -708,8 +706,9 @@
int err;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- pr_debug("%s()\n", __func__);
+ pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
if (machine_is_msm8960_liquid()) {
top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
@@ -752,6 +751,8 @@
return err;
}
+ codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+
tabla_hs_detect(codec, &hs_jack, &button_jack, tabla_mbhc_cal,
TABLA_MICBIAS2, msm8960_enable_codec_ext_clk, 0,
TABLA_EXT_CLK_RATE);
@@ -984,7 +985,7 @@
};
/* Digital audio interface glue - connects codec <---> CPU */
-static struct snd_soc_dai_link msm8960_dai[] = {
+static struct snd_soc_dai_link msm8960_dai_common[] = {
/* FrontEnd DAI Links */
{
.name = "MSM8960 Media1",
@@ -1105,32 +1106,6 @@
.no_codec = 1,
.ignore_suspend = 1,
},
- /* Backend DAI Links */
- {
- .name = LPASS_BE_SLIMBUS_0_RX,
- .stream_name = "Slimbus Playback",
- .cpu_dai_name = "msm-dai-q6.16384",
- .platform_name = "msm-pcm-routing",
- .codec_name = "tabla_codec",
- .codec_dai_name = "tabla_rx1",
- .no_pcm = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
- .init = &msm8960_audrx_init,
- .be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
- .ops = &msm8960_be_ops,
- },
- {
- .name = LPASS_BE_SLIMBUS_0_TX,
- .stream_name = "Slimbus Capture",
- .cpu_dai_name = "msm-dai-q6.16385",
- .platform_name = "msm-pcm-routing",
- .codec_name = "tabla_codec",
- .codec_dai_name = "tabla_tx1",
- .no_pcm = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
- .be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
- .ops = &msm8960_be_ops,
- },
/* Backend BT/FM DAI Links */
{
.name = LPASS_BE_INT_BT_SCO_RX,
@@ -1278,13 +1253,88 @@
},
};
-struct snd_soc_card snd_soc_card_msm8960 = {
- .name = "msm8960-snd-card",
- .dai_link = msm8960_dai,
- .num_links = ARRAY_SIZE(msm8960_dai),
+static struct snd_soc_dai_link msm8960_dai_delta_tabla1x[] = {
+ /* Backend DAI Links */
+ {
+ .name = LPASS_BE_SLIMBUS_0_RX,
+ .stream_name = "Slimbus Playback",
+ .cpu_dai_name = "msm-dai-q6.16384",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tabla1x_codec",
+ .codec_dai_name = "tabla_rx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .init = &msm8960_audrx_init,
+ .be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
+ .ops = &msm8960_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_0_TX,
+ .stream_name = "Slimbus Capture",
+ .cpu_dai_name = "msm-dai-q6.16385",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tabla1x_codec",
+ .codec_dai_name = "tabla_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8960_be_ops,
+ },
+};
+
+
+static struct snd_soc_dai_link msm8960_dai_delta_tabla2x[] = {
+ /* Backend DAI Links */
+ {
+ .name = LPASS_BE_SLIMBUS_0_RX,
+ .stream_name = "Slimbus Playback",
+ .cpu_dai_name = "msm-dai-q6.16384",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tabla_codec",
+ .codec_dai_name = "tabla_rx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .init = &msm8960_audrx_init,
+ .be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
+ .ops = &msm8960_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_0_TX,
+ .stream_name = "Slimbus Capture",
+ .cpu_dai_name = "msm-dai-q6.16385",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tabla_codec",
+ .codec_dai_name = "tabla_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8960_be_ops,
+ },
+};
+
+static struct snd_soc_dai_link msm8960_tabla1x_dai[
+ ARRAY_SIZE(msm8960_dai_common) +
+ ARRAY_SIZE(msm8960_dai_delta_tabla1x)];
+
+
+static struct snd_soc_dai_link msm8960_dai[
+ ARRAY_SIZE(msm8960_dai_common) +
+ ARRAY_SIZE(msm8960_dai_delta_tabla2x)];
+
+static struct snd_soc_card snd_soc_tabla1x_card_msm8960 = {
+ .name = "msm8960-tabla1x-snd-card",
+ .dai_link = msm8960_tabla1x_dai,
+ .num_links = ARRAY_SIZE(msm8960_tabla1x_dai),
+};
+
+static struct snd_soc_card snd_soc_card_msm8960 = {
+ .name = "msm8960-snd-card",
+ .dai_link = msm8960_dai,
+ .num_links = ARRAY_SIZE(msm8960_dai),
};
static struct platform_device *msm8960_snd_device;
+static struct platform_device *msm8960_snd_tabla1x_device;
static int msm8960_configure_headset_mic_gpios(void)
{
@@ -1359,6 +1409,10 @@
return -ENOMEM;
}
+ memcpy(msm8960_dai, msm8960_dai_common, sizeof(msm8960_dai_common));
+ memcpy(msm8960_dai + ARRAY_SIZE(msm8960_dai_common),
+ msm8960_dai_delta_tabla2x, sizeof(msm8960_dai_delta_tabla2x));
+
platform_set_drvdata(msm8960_snd_device, &snd_soc_card_msm8960);
ret = platform_device_add(msm8960_snd_device);
if (ret) {
@@ -1367,6 +1421,27 @@
return ret;
}
+ msm8960_snd_tabla1x_device = platform_device_alloc("soc-audio", 1);
+ if (!msm8960_snd_tabla1x_device) {
+ pr_err("Platform device allocation failed\n");
+ kfree(tabla_mbhc_cal);
+ return -ENOMEM;
+ }
+
+ memcpy(msm8960_tabla1x_dai, msm8960_dai_common,
+ sizeof(msm8960_dai_common));
+ memcpy(msm8960_tabla1x_dai + ARRAY_SIZE(msm8960_dai_common),
+ msm8960_dai_delta_tabla1x, sizeof(msm8960_dai_delta_tabla1x));
+
+ platform_set_drvdata(msm8960_snd_tabla1x_device,
+ &snd_soc_tabla1x_card_msm8960);
+ ret = platform_device_add(msm8960_snd_tabla1x_device);
+ if (ret) {
+ platform_device_put(msm8960_snd_tabla1x_device);
+ kfree(tabla_mbhc_cal);
+ return ret;
+ }
+
if (msm8960_configure_headset_mic_gpios()) {
pr_err("%s Fail to configure headset mic gpios\n", __func__);
msm8960_headset_gpios_configured = 0;
@@ -1386,6 +1461,7 @@
}
msm8960_free_headset_mic_gpios();
platform_device_unregister(msm8960_snd_device);
+ platform_device_unregister(msm8960_snd_tabla1x_device);
kfree(tabla_mbhc_cal);
}
module_exit(msm8960_audio_exit);
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index dc49f12..d822af5 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -3211,7 +3211,7 @@
{
pr_debug("%s\n", __func__);
- if (session_id < 0) {
+ if (session_id < 0 || session_id > SESSION_MAX) {
pr_err("%s: invalid session_id = %d\n", __func__, session_id);
return -EINVAL;
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c03f7ca7..3063f3e 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1318,7 +1318,7 @@
/* Do we need to apply any queued changes? */
if (sort[w->id] != cur_sort || w->reg != cur_reg ||
w->dapm != cur_dapm || w->subseq != cur_subseq) {
- if (!list_empty(&pending))
+ if (cur_dapm && !list_empty(&pending))
dapm_seq_run_coalesced(cur_dapm, &pending);
if (cur_dapm && cur_dapm->seq_notifier) {
@@ -1378,7 +1378,7 @@
"Failed to apply widget power: %d\n", ret);
}
- if (!list_empty(&pending))
+ if (cur_dapm && !list_empty(&pending))
dapm_seq_run_coalesced(cur_dapm, &pending);
if (cur_dapm && cur_dapm->seq_notifier) {
diff --git a/tools/perf/builtin-periodic.c b/tools/perf/builtin-periodic.c
index 70a0e2b..060e909 100644
--- a/tools/perf/builtin-periodic.c
+++ b/tools/perf/builtin-periodic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -194,6 +194,8 @@
if (p == NULL)
return PERF_PERIODIC_ERROR;
for (cpu = 0; cpu < cpus->nr; cpu++) {
+ if (((1 << cpu) & cpumask) == 0)
+ continue;
p->perf_fd[cpu] = sys_perf_event_open(p->attr, target_pid, cpu,
-1, 0);
if (p->perf_fd[cpu] < 0)