Merge "msm: vreg: Fix the vreg list for dangling node" into msm-3.0
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index 084050e..0c1762d 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -21,6 +21,7 @@
- qcom,sdcc-nonremovable - specifies whether the card in slot is
hot pluggable or hard wired.
- qcom,sdcc-disable_cmd23 - disable sending CMD23 to card when controller can't support it.
+ - qcom,sdcc-hs200 - enable eMMC4.5 HS200 bus speed mode
Example:
diff --git a/Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt b/Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt
new file mode 100644
index 0000000..f07d3c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/msm-qpnp-gpio.txt
@@ -0,0 +1,142 @@
+* msm-qpnp-gpio
+
+msm-qpnp-gpio is a GPIO chip driver for the MSM SPMI implementation.
+It creates a spmi_device for every spmi-dev-container block of device_nodes.
+These device_nodes contained within specify the PMIC GPIO number associated
+with each GPIO chip. The driver will map these to Linux GPIO numbers.
+
+[PMIC GPIO Device Declarations]
+
+-Root Node-
+
+Required properties :
+ - spmi-dev-container : Used to specify the following child nodes as part of the
+ same SPMI device.
+ - gpio-controller : Specify as gpio-contoller. All child nodes will belong to this
+ gpio_chip.
+ - #gpio-cells: We encode a PMIC GPIO number and a 32-bit flag field to
+ specify the gpio configuration. This must be set to '2'.
+ - #address-cells: Specify one address field. This must be set to '1'.
+ - #size-cells: Specify one size-cell. This must be set to '1'.
+ - compatible = "qcom,qpnp-gpio" : Specify driver matching for this driver.
+
+-Child Nodes-
+
+Required properties :
+ - reg : Specify the spmi offset and size for this gpio device.
+ - qcom,qpnp-gpio-num : Specify the PMIC GPIO number for this gpio device.
+
+Optional properties :
+ - qcom,qpnp-gpio-cfg : Specify the PMIC gpio configuration.
+ The format of this configuration is specified in a tuple of 9 entries.
+ These entries should be specified in the same order as the entries listed
+ in this following discription.
+
+ @direction: indicates whether the gpio should be input, output, or
+ both.
+ QPNP_GPIO_DIR_OUT = 1,
+ QPNP_GPIO_DIR_IN = 2,
+ QPNP_GPIO_DIR_BOTH = 3
+
+ @output_type: indicates gpio should be configured as CMOS or open
+ drain.
+ QPNP_GPIO_OUT_BUF_OPEN_DRAIN = 1,
+ QPNP_GPIO_OUT_BUF_CMOS = 0
+
+ @output_value: The gpio output value of the gpio line - 0 or 1
+ @pull: Indicates whether a pull up or pull down should be
+ applied. If a pullup is required the current strength
+ needs to be specified. Current values of 30uA, 1.5uA,
+ 31.5uA, 1.5uA with 30uA boost are supported.
+ QPNP_GPIO_PULL_UP_30 = 0,
+ QPNP_GPIO_PULL_UP_1P5 = 1,
+ QPNP_GPIO_PULL_UP_31P5 = 2,
+ QPNP_GPIO_PULL_UP_1P5_30 = 3,
+ QPNP_GPIO_PULL_DN = 4,
+ QPNP_GPIO_PULL_NO = 5
+
+ @vin_sel: specifies the voltage level when the output is set to 1.
+ For an input gpio specifies the voltage level at which
+ the input is interpreted as a logical 1.
+ QPNP_GPIO_VIN0 = 0,
+ QPNP_GPIO_VIN1 = 1,
+ QPNP_GPIO_VIN2 = 2,
+ QPNP_GPIO_VIN3 = 3,
+ QPNP_GPIO_VIN4 = 4,
+ QPNP_GPIO_VIN5 = 5,
+ QPNP_GPIO_VIN6 = 6,
+ QPNP_GPIO_VIN7 = 7
+
+ @out_strength: the amount of current supplied for an output gpio.
+ QPNP_GPIO_OUT_STRENGTH_HIGH = 1,
+ QPNP_GPIO_OUT_STRENGTH_MED = 2,
+ QPNP_GPIO_OUT_STRENGTH_LOW = 3
+
+ @source_sel: choose alternate function for the gpio. Certain gpios
+ can be paired (shorted) with each other. Some gpio pin
+ can act as alternate functions.
+ QPNP_GPIO_FUNC_NORMAL = 0,
+ QPNP_GPIO_FUNC_PAIRED = 1
+ QPNP_GPIO_FUNC_1 = 2,
+ QPNP_GPIO_FUNC_3 = 3,
+ QPNP_GPIO_DTEST1 = 4,
+ QPNP_GPIO_DTEST2 = 5,
+ QPNP_GPIO_DTEST3 = 6,
+ QPNP_GPIO_DTEST4 = 7
+
+ @inv_int_pol: Invert polarity before feeding the line to the interrupt
+ module in pmic. This feature will almost be never used
+ since the pm8xxx interrupt block can detect both edges
+ and both levels.
+ @master_en: 1 = Enable features within the GPIO block based on
+ configurations.
+ 0 = Completely disable the GPIO block and let the pin
+ float with high impedance regardless of other settings.
+
+[PMIC GPIO clients]
+
+Required properties :
+ - gpios : Contains 3 fields of the form <&gpio_controller pmic_gpio_num flags>
+
+[Example]
+
+qpnp: qcom,spmi@fc4c0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ qcom,pm8941@0 {
+ spmi-slave-container;
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm8941_gpios: gpios {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qcom,pm8941_gpio1@0xc000 {
+ reg = <0xc000 0x100>;
+ qcom,qpnp-gpio-num = <62>;
+ };
+
+ qcom,pm8941_gpio2@0xc100 {
+ reg = <0xc100 0x100>;
+ qcom,qpnp-gpio-num = <20>;
+ qcom,qpnp-gpio-cfg = <0x1 0x1 0x1 0x2 0x3 0x2 0x0 0x0 0x1>;
+ };
+ };
+
+ qcom,testgpio@1000 {
+ compatible = "qcom,qpnp-testgpio";
+ reg = <0x1000 0x1000>;
+ gpios = <&pm8941_gpios 62 0x0 &pm8941_gpios 20 0x1>;
+ };
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/spmi/msm-spmi.txt b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
index 8fe415b..d50037f 100644
--- a/Documentation/devicetree/bindings/spmi/msm-spmi.txt
+++ b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
@@ -1,13 +1,28 @@
* SPMI
-The spmi Device Tree support interprets up to two levels of Device Tree
+The SPMI Device Tree support interprets up to three levels of Device Tree
topology. The first level is required and specifies only a slave address.
The second level is optional and allows for the specification of different
-offsets within the same 16-bit address space underneath a particular SPMI
-slave ID. Within the second level, any number of address ranges can be
-associated with a particular device within that 16-bit range.
+device nodes within the same 16-bit address space underneath a particular
+SPMI slave ID. Within the second level, any number of address ranges can be
+associated with a particular device within that 16-bit range. An additional
+flag allows for the possiblity to specify that all device nodes should
+have their resources dedicated to only one spmi_device. This flag can
+be specified at the second level, or an optional third level. By default
+without this flag, one spmi_device is created for each device_node.
-First level
+[Root Node]
+
+Recommended properties :
+ - interrupt-controller : Used to specify the root node as the
+ interrupt controller for SPMI devices.
+ - #interrupt-cells : The number of cells used to express one interrupt.
+
+Notes :
+ - It is considered an error to include either spmi-container-dev or
+ spmi-slave-dev in the Root Node.
+
+[First Level Nodes]
Required properites :
@@ -22,51 +37,124 @@
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
-Second level
+[Second Level Nodes]
Required properties :
- spmi-slave-container: Used by the parser to understand that this is the
- second level of the tree.
+ second level of the tree that includes device nodes associated with the
+ same slave_id.
- reg: <a b> where a is < 65536 and b is a size. Each device supports an
arbitrary number of address ranges.
- compatible : "qcom," prefixed string to match against the driver.
Recommended properties :
- - interrupts : <a b c> where a is the slave ID, b is is the peripheral ID,
+ - interrupts : <a b c> where a is the slave ID, b is the peripheral ID,
c is the device interrupt number (0-7). Each device supports any arbitrary
number of interrupts.
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
-Example:
+Optional properties :
+
+ - spmi-dev-container: This specifies that all the device nodes specified for
+ this slave_id should have their resources coalesced into only one
+ spmi_device.
+
+[Third Level Nodes]
+
+Required properties :
+
+ - spmi-dev-container: This specifies that all the device nodes specified for
+ this slave_id should have their resources coalesced into only one
+ spmi_device.
+ - reg: <a b> where a is < 65536 and b is a size. Each device supports an
+ arbitrary number of address ranges.
+ - compatible : "qcom," prefixed string to match against the driver.
+
+Recommended properties :
+
+ - interrupts : <a b c> where a is the slave ID, b is the peripheral ID,
+ c is the device interrupt number (0-7). Each device supports any arbitrary
+ number of interrupts.
+ - interrupt-parent : the phandle for the interrupt controller that
+ services interrupts for this device.
+
+Notes :
+ - It is considered an error to include spmi-slave-dev at this level.
+
+[Example]
/ {
- qcom,spmi@fc4c0000 {
+ qpnp: qcom,spmi@fc4c0000 {
#address-cells = <1>;
#size-cells = <0>;
- interrupt-parent = <&qpnpint>;
- pmic8941@d {
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ testint@f {
+ interrupt-parent = <&qpnp>;
+ compatible = "qcom,qpnp-testint";
+ reg = <0xf>;
+ interrupts = <0x3 0x15 0x0 0x3 0x15 0x02 0x1 0x47 0x0>;
+
+ };
+
+ pm8941@0 {
+ spmi-slave-container;
+ reg = <0x0>;
#address-cells = <1>;
#size-cells = <1>;
- reg = <0xd>;
+
+ pm8941_gpios: gpios {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-gpio";
+ gpio-controller;
+ #gpio-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm8941_gpio1@0xc000 {
+ compatible = "qcom,qpnp-gpio";
+ reg = <0xc000 0x100>;
+ qcom,qpnp_gpio = <1>;
+ interrupt-parent = <&qpnp>;
+ interrupts = <0x3 0x15 0x02 0x1 0x47 0x0>;
+ };
+
+ pm8941_gpio2@0xc100 {
+ compatible = "qcom,qpnp-gpio";
+ reg = <0xc100 0x100>;
+ qcom,qpnp_gpio = <2>;
+ interrupt-parent = <&qpnp>;
+ interrupts = <0x3 0x15 0x0>;
+ };
+ };
+
+ testgpio@0x1000 {
+ compatible = "qcom,qpnp-testgpio";
+ reg = <0x1000 0x1000>;
+ qpnp-gpios = <&pm8941_gpios 0x0>;
+ };
+ };
+ pm8841@2 {
spmi-slave-container;
-
- coincell@2800 {
- compatible = "qcom,qpnp-coincell";
- reg = <0x2800 0x4000>;
- interrupts = <0xd 0x28 0x6 0xd 0x28 0x3>;
-
- };
- pon@800 {
- compatible = "qcom,qpnp-pon";
- reg = <0x800 0x4000>;
- };
- };
- customer_dev@2 {
- compatible = "qcom,qpnp-pon";
reg = <0x2>;
- interrupts = <0x2 0x08 0x1 0x2 0x8 0x3>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spmi-dev-container;
+ compatible = "qcom,qpnp-gpio";
+
+ pm8841_gpio1@0xc000 {
+ reg = <0xc000 0x100>;
+ qcom,qpnp_gpio = <1>;
+ };
+
+ pm8841_gpio2@0xc100 {
+ reg = <0xc100 0x100>;
+ qcom,qpnp_gpio = <2>;
+ };
};
+
};
};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f5046dc..e6f6998 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -645,6 +645,7 @@
select GENERIC_TIME
select GENERIC_ALLOCATOR
select HAVE_SCHED_CLOCK
+ select HAVE_CLK_PREPARE
help
Support for Qualcomm MSM/QSD based systems. This runs on the
apps processor of the MSM/QSD and depends on a shared memory
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index b9179a3..f7eb7b9 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -49,9 +49,10 @@
reg = <0xf980b000 0x1000>;
interrupts = <0 123 0>;
- qcom,sdcc-clk-rates = <400000 24000000 48000000>;
+ qcom,sdcc-clk-rates = <400000 24000000 48000000 96000000 192000000>;
qcom,sdcc-sup-voltages = <3300 3300>;
qcom,sdcc-bus-width = <8>;
+ qcom,sdcc-hs200;
qcom,sdcc-nonremovable;
qcom,sdcc-disable_cmd23;
};
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 0b89d45..e9479c6 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -104,6 +104,8 @@
# CONFIG_BATTERY_MSM is not set
# CONFIG_HWMON is not set
# CONFIG_MFD_SUPPORT is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_STUB=y
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_FB=y
diff --git a/arch/arm/configs/msm7627-perf_defconfig b/arch/arm/configs/msm7627-perf_defconfig
index ea5c7c9..3fbe374 100644
--- a/arch/arm/configs/msm7627-perf_defconfig
+++ b/arch/arm/configs/msm7627-perf_defconfig
@@ -263,6 +263,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_SWITCH=y
diff --git a/arch/arm/configs/msm7627_defconfig b/arch/arm/configs/msm7627_defconfig
index 0841f7e..f05b5f7 100644
--- a/arch/arm/configs/msm7627_defconfig
+++ b/arch/arm/configs/msm7627_defconfig
@@ -261,6 +261,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_SWITCH=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 31e04f1..44986a4 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -58,6 +58,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0xC800000
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
@@ -230,7 +231,9 @@
# CONFIG_HWMON is not set
CONFIG_MARIMBA_CORE=y
CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_RC_CORE is not set
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
# CONFIG_MT9T013 is not set
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index bb54f68..6ba9790 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -58,6 +58,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0xC800000
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
@@ -231,7 +232,9 @@
# CONFIG_HWMON is not set
CONFIG_MARIMBA_CORE=y
CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_RC_CORE is not set
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
# CONFIG_MT9T013 is not set
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 5466498..b6c56b6 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -45,6 +45,8 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0x1A000000
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M ip=dhcp"
@@ -327,6 +329,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index 1a70816..851f189 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -46,6 +46,8 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0x1A000000
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M ip=dhcp"
@@ -329,6 +331,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 1365641..494b3a3 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -234,7 +234,7 @@
CONFIG_PMIC8XXX_VIBRATOR=y
CONFIG_PMIC8XXX_UPL=y
CONFIG_PMIC8058_XOADC=y
-CONFIG_TZCOM=y
+CONFIG_QSEECOM=y
CONFIG_SCSI=y
CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
@@ -385,6 +385,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index fa4ba4e..9b850da 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -233,7 +233,7 @@
CONFIG_PMIC8XXX_VIBRATOR=y
CONFIG_PMIC8XXX_UPL=y
CONFIG_PMIC8058_XOADC=y
-CONFIG_TZCOM=y
+CONFIG_QSEECOM=y
CONFIG_SCSI=y
CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
@@ -386,6 +386,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index d14757b..288381b 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -308,7 +308,9 @@
CONFIG_REGULATOR_PM8XXX=y
CONFIG_REGULATOR_GPIO=y
CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
CONFIG_USB_VIDEO_CLASS=y
@@ -392,6 +394,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index dafaffc..d12df73 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -308,7 +308,9 @@
CONFIG_REGULATOR_PM8XXX=y
CONFIG_REGULATOR_GPIO=y
CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
CONFIG_USB_VIDEO_CLASS=y
@@ -392,6 +394,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index d4552f8..c709178 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -235,6 +235,7 @@
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 7216c12..20a5449 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2107,5 +2107,60 @@
separately. This will guarantee that the last acesses for each cpu
will be logged but there will be fewer entries per cpu
+config MSM_CACHE_ERP
+ bool "Cache / CPU error reporting"
+ depends on ARCH_MSM_KRAIT
+ help
+ Say 'Y' here to enable reporting of cache and TLB errors to the kernel
+ log. Enabling this feature can be used as a system debugging technique
+ if cache corruption is suspected. Cache error statistics will also be
+ reported in /proc/cpu/msm_cache_erp.
+
+ For production builds, you should probably say 'N' here.
+
+config MSM_L1_ERR_PANIC
+ bool "Panic on L1 cache / TLB errors"
+ depends on MSM_CACHE_ERP
+ help
+ To cause the kernel to panic whenever an L1 cache or TLB error is
+ detected, say 'Y' here. This may be useful as a debugging technique if
+ general system instability is suspected.
+
+ For production builds, you should probably say 'N' here.
+
+
+config MSM_L2_ERP_PORT_PANIC
+ bool "Panic on L2 master port errors"
+ depends on MSM_CACHE_ERP
+ help
+ Master port errors can occur when a memory request is not properly
+ handled by the destination slave. Enable this option to catch drivers
+ which attempt to access bad areas of the address space, or access
+ hardware registers in an improper state (such as certain clocks not
+ being on). This option may help with debugging, though production
+ builds should probably say 'N' here.
+
+config MSM_L2_ERP_1BIT_PANIC
+ bool "Panic on recoverable L2 soft errors"
+ depends on MSM_CACHE_ERP
+ help
+ Enable this option to cause a kernel panic whenever the L2 cache
+ encounters a single-bit (correctable) soft error. This option should
+ only be enabled when doing low-level debugging where cache corruption
+ is suspected.
+
+ For production builds, you should definitely say 'N' here.
+
+config MSM_L2_ERP_2BIT_PANIC
+ bool "Panic on unrecoverable L2 soft errors"
+ depends on MSM_CACHE_ERP
+ help
+ Enable this option to cause a kernel panic whenever the L2 cache
+ encounters a double-bit (non-correctable) soft error. Debug builds
+ will likely benefit from having this option enabled to catch cache
+ problems as soon as possible.
+
+ For production builds, it may be acceptable to say 'N' here, since
+ an uncorrectable error might not necessarily cause further problems.
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 6cde804..c4d2c54 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -260,7 +260,7 @@
obj-$(CONFIG_MACH_APQ8064_RUMI3) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o
-obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o
+obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -329,3 +329,4 @@
obj-$(CONFIG_ARCH_MSM8960) += mdm2.o mdm_common.o
obj-$(CONFIG_MSM_RTB) += msm_rtb.o
+obj-$(CONFIG_MSM_CACHE_ERP) += cache_erp.o
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index ae4b084..687033c 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -219,6 +219,34 @@
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
+/* 8625 PLL4 @ 1209MHz with GSM capable modem */
+static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_pll4_1209[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
+ { 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 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 0, 604800, ACPU_PLL_4, 6, 1, 75600, 3, 6, 200000 },
+ { 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, 7, 200000},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 8625 PLL4 @ 1209MHz with CDMA capable modem */
+static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_1209[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
+ { 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 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
+ { 0, 604800, ACPU_PLL_4, 6, 1, 75600, 3, 6, 200000 },
+ { 1, 1209600, ACPU_PLL_4, 6, 0, 151200, 3, 7, 200000},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
/* 7625a PLL2 @ 1200MHz with GSM capable modem */
static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_25a[] = {
{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
@@ -333,6 +361,8 @@
PLL_CONFIG(960, 589, 1200, 800),
PLL_CONFIG(960, 737, 1200, 1008),
PLL_CONFIG(960, 589, 1200, 1008),
+ PLL_CONFIG(960, 245, 1200, 1209),
+ PLL_CONFIG(960, 196, 1200, 1209),
{ 0, 0, 0, 0, 0 }
};
@@ -875,3 +905,9 @@
.max_speed_delta_khz = 504000,
.init = acpuclk_7627_init,
};
+
+struct acpuclk_soc_data acpuclk_8625_soc_data __initdata = {
+ /* TODO: Need to update speed delta from H/w Team */
+ .max_speed_delta_khz = 604800,
+ .init = acpuclk_7627_init,
+};
diff --git a/arch/arm/mach-msm/acpuclock.h b/arch/arm/mach-msm/acpuclock.h
index ef6c359..c5f0ee3 100644
--- a/arch/arm/mach-msm/acpuclock.h
+++ b/arch/arm/mach-msm/acpuclock.h
@@ -110,5 +110,6 @@
extern struct acpuclk_soc_data acpuclk_9615_soc_data;
extern struct acpuclk_soc_data acpuclk_8930_soc_data;
extern struct acpuclk_soc_data acpuclk_8064_soc_data;
+extern struct acpuclk_soc_data acpuclk_8625_soc_data;
#endif
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 97f8722..7b9bdac 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -236,7 +236,6 @@
static struct completion dfab_unvote_completion;
static DEFINE_SPINLOCK(wakelock_reference_lock);
static int wakelock_reference_count;
-static struct delayed_work msm9615_bam_init_work;
static int a2_pc_disabled_wakelock_skipped;
/* End A2 power collaspe */
@@ -1639,10 +1638,9 @@
if (polling_mode)
rx_switch_to_interrupt_mode();
- queue_rx();
-
toggle_apps_ack();
complete_all(&bam_connection_completion);
+ queue_rx();
}
static void disconnect_to_bam(void)
@@ -1959,10 +1957,10 @@
}
bam_mux_initialized = 1;
- queue_rx();
toggle_apps_ack();
bam_connection_is_active = 1;
complete_all(&bam_connection_completion);
+ queue_rx();
return 0;
rx_event_reg_failed:
@@ -2034,7 +2032,7 @@
return ret;
}
-static void msm9615_bam_init(struct work_struct *work)
+static void msm9615_bam_init(void)
{
int ret = 0;
@@ -2079,19 +2077,10 @@
} else if (new_state & SMSM_A2_POWER_CONTROL) {
bam_dmux_log("%s: init\n", __func__);
grab_wakelock();
- if (cpu_is_msm9615()) {
- /*
- * even though a2 has signaled it is ready via the
- * SMSM_A2_POWER_CONTROL bit, it has not yet
- * enabled the pipes as needed by sps_connect
- * in satallite mode. Add a short delay to give modem
- * time to enable the pipes.
- */
- schedule_delayed_work(&msm9615_bam_init_work,
- msecs_to_jiffies(100));
- } else {
+ if (cpu_is_msm9615())
+ msm9615_bam_init();
+ else
bam_init();
- }
} else {
bam_dmux_log("%s: bad state change\n", __func__);
pr_err("%s: unsupported state change\n", __func__);
@@ -2159,7 +2148,6 @@
init_completion(&bam_connection_completion);
init_completion(&dfab_unvote_completion);
INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
- INIT_DELAYED_WORK(&msm9615_bam_init_work, msm9615_bam_init);
wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
rc = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_A2_POWER_CONTROL,
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index f23bf2a..70d76fb 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -512,6 +512,9 @@
msm_gpiomux_install(apq8064_cam_common_configs,
ARRAY_SIZE(apq8064_cam_common_configs));
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+ sensor_board_info_imx074.mount_angle = 0;
+
platform_device_register(&msm8960_device_i2c_mux_gsbi4);
platform_device_register(&msm8960_device_csiphy0);
platform_device_register(&msm8960_device_csiphy1);
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 8c87925..bf82e40 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -82,22 +82,6 @@
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting audio_auxpcm[] = {
- /* Suspended state */
- {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- },
- /* Active state */
- {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- },
-};
-
-
static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -448,37 +432,6 @@
},
};
-static struct msm_gpiomux_config apq8064_audio_auxpcm_configs[] __initdata = {
- {
- .gpio = 43,
- .settings = {
- [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
- [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
- },
- },
- {
- .gpio = 44,
- .settings = {
- [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
- [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
- },
- },
- {
- .gpio = 45,
- .settings = {
- [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
- [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
- },
- },
- {
- .gpio = 46,
- .settings = {
- [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
- [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
- },
- },
-};
-
/* External 3.3 V regulator enable */
static struct msm_gpiomux_config apq8064_ext_regulator_configs[] __initdata = {
{
@@ -633,8 +586,9 @@
msm_gpiomux_install(apq8064_audio_codec_configs,
ARRAY_SIZE(apq8064_audio_codec_configs));
- msm_gpiomux_install(apq8064_audio_auxpcm_configs,
- ARRAY_SIZE(apq8064_audio_auxpcm_configs));
+ pr_debug("%s(): audio-auxpcm: Include GPIO configs"
+ " as audio is not the primary user"
+ " for these GPIO Pins\n", __func__);
msm_gpiomux_install(apq8064_ext_regulator_configs,
ARRAY_SIZE(apq8064_ext_regulator_configs));
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 2bb2702..57bf7ac 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1491,7 +1491,7 @@
[0] = {
.reg_base_addr = MSM_SAW_L2_BASE,
.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_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x00A00020,
.modes = msm_spm_l2_seq_list,
@@ -1508,7 +1508,7 @@
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
.vctl_timeout_us = 50,
@@ -1523,7 +1523,7 @@
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
.vctl_timeout_us = 50,
@@ -1538,7 +1538,7 @@
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
.vctl_timeout_us = 50,
@@ -1553,7 +1553,7 @@
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
.vctl_timeout_us = 50,
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index 84dbea8..9099266 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -31,18 +31,6 @@
.pull = GPIOMUX_PULL_DOWN,
};
-static struct gpiomux_setting spi_active_config2 = {
- .func = GPIOMUX_FUNC_2,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting spi_suspended_config2 = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
static struct gpiomux_setting gsbi3_suspended_cfg = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_2MA,
@@ -313,13 +301,6 @@
},
},
{
- .gpio = 14, /* GSBI1 SPI_CS_1 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &spi_suspended_config2,
- [GPIOMUX_ACTIVE] = &spi_active_config2,
- },
- },
- {
.gpio = 16, /* GSBI3 I2C QUP SDA */
.settings = {
[GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
@@ -346,18 +327,6 @@
},
},
{
- .gpio = 24, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 25, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
.gpio = 44, /* GSBI12 I2C QUP SDA */
.settings = {
[GPIOMUX_SUSPENDED] = &gsbi12,
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 3a6a30d..db1fb46 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -437,7 +437,7 @@
static struct rpm_regulator_init_data
msm8930_rpm_regulator_init_data[] __devinitdata = {
/* ID a_on pd ss min_uV max_uV supply sys_uA freq */
- RPM_SMPS(S1, 1, 1, 1, 500000, 1150000, NULL, 100000, 4p80),
+ RPM_SMPS(S1, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80),
RPM_SMPS(S2, 1, 1, 0, 1400000, 1400000, NULL, 100000, 1p60),
RPM_SMPS(S3, 0, 1, 0, 1150000, 1150000, NULL, 100000, 3p20),
RPM_SMPS(S4, 1, 1, 0, 2200000, 2200000, NULL, 100000, 1p60),
@@ -463,7 +463,7 @@
RPM_LDO(L21, 0, 1, 0, 1900000, 1900000, "8038_s4", 0, 0),
RPM_LDO(L22, 1, 1, 0, 1850000, 2950000, NULL, 10000, 10000),
RPM_LDO(L23, 1, 1, 1, 1800000, 1800000, "8038_s4", 0, 0),
- RPM_LDO(L24, 1, 1, 1, 500000, 1150000, "8038_s2", 10000, 10000),
+ RPM_LDO(L24, 0, 1, 1, 500000, 1150000, "8038_s2", 10000, 10000),
RPM_LDO(L26, 1, 1, 0, 1050000, 1050000, "8038_s2", 10000, 10000),
/* ID a_on pd ss supply */
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 2c81e66..dbd6329 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1134,7 +1134,7 @@
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
.vctl_timeout_us = 50,
@@ -1149,7 +1149,7 @@
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
.vctl_timeout_us = 50,
@@ -1198,7 +1198,7 @@
[0] = {
.reg_base_addr = MSM_SAW_L2_BASE,
.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_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x00A00020,
.modes = msm_spm_l2_seq_list,
@@ -1653,10 +1653,11 @@
};
static struct tsens_platform_data msm_tsens_pdata = {
- .slope = {872, 872, 872, 872, 872},
.tsens_factor = 1000,
- .hw_type = MSM_8960,
- .tsens_num_sensor = 5,
+ .hw_type = APQ_8064,
+ .tsens_num_sensor = 11,
+ .slope = {1176, 1176, 1154, 1176, 1111,
+ 1132, 1132, 1199, 1132, 1199, 1132},
};
#ifdef CONFIG_MSM_FAKE_BATTERY
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 3b0f8be..462cb5d 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1344,7 +1344,7 @@
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
.vctl_timeout_us = 50,
@@ -1359,7 +1359,7 @@
.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
#endif
.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
.vctl_timeout_us = 50,
@@ -1408,7 +1408,7 @@
[0] = {
.reg_base_addr = MSM_SAW_L2_BASE,
.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_DLY] = 0x02020204,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x00A00020,
.modes = msm_spm_l2_seq_list,
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 74471dd..a1a0dc7 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -514,7 +514,9 @@
#ifdef CONFIG_LTC4088_CHARGER
&msm_device_charger,
#endif
+#ifndef CONFIG_USB_GADGET_CI13XXX_MSM_HSIC
&msm_device_otg,
+#endif
&msm_device_hsic_peripheral,
&msm_device_gadget_peripheral,
&msm_device_hsusb_host,
diff --git a/arch/arm/mach-msm/board-copper-regulator.c b/arch/arm/mach-msm/board-copper-regulator.c
new file mode 100644
index 0000000..a7f0eac
--- /dev/null
+++ b/arch/arm/mach-msm/board-copper-regulator.c
@@ -0,0 +1,322 @@
+/*
+ * 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/platform_device.h>
+#include <linux/regulator/stub-regulator.h>
+
+#define VREG_CONSUMERS(_name) \
+ static struct regulator_consumer_supply vreg_consumers_##_name[]
+
+/*
+ * Consumer specific regulator names:
+ * regulator name consumer dev_name
+ */
+VREG_CONSUMERS(S1B) = {
+ REGULATOR_SUPPLY("8841_s1", NULL),
+};
+VREG_CONSUMERS(S2B) = {
+ REGULATOR_SUPPLY("8841_s2", NULL),
+};
+VREG_CONSUMERS(S3B) = {
+ REGULATOR_SUPPLY("8841_s3", NULL),
+};
+VREG_CONSUMERS(S4B) = {
+ REGULATOR_SUPPLY("8841_s4", NULL),
+};
+VREG_CONSUMERS(S5B) = {
+ REGULATOR_SUPPLY("8841_s5", NULL),
+};
+VREG_CONSUMERS(S6B) = {
+ REGULATOR_SUPPLY("8841_s6", NULL),
+};
+VREG_CONSUMERS(S7B) = {
+ REGULATOR_SUPPLY("8841_s7", NULL),
+};
+VREG_CONSUMERS(S8B) = {
+ REGULATOR_SUPPLY("8841_s8", NULL),
+};
+VREG_CONSUMERS(S1) = {
+ REGULATOR_SUPPLY("8941_s1", NULL),
+};
+VREG_CONSUMERS(S2) = {
+ REGULATOR_SUPPLY("8941_s2", NULL),
+};
+VREG_CONSUMERS(S3) = {
+ REGULATOR_SUPPLY("8941_s3", NULL),
+};
+VREG_CONSUMERS(L1) = {
+ REGULATOR_SUPPLY("8941_l1", NULL),
+};
+VREG_CONSUMERS(L2) = {
+ REGULATOR_SUPPLY("8941_l2", NULL),
+};
+VREG_CONSUMERS(L3) = {
+ REGULATOR_SUPPLY("8941_l3", NULL),
+};
+VREG_CONSUMERS(L4) = {
+ REGULATOR_SUPPLY("8941_l4", NULL),
+};
+VREG_CONSUMERS(L5) = {
+ REGULATOR_SUPPLY("8941_l5", NULL),
+};
+VREG_CONSUMERS(L6) = {
+ REGULATOR_SUPPLY("8941_l6", NULL),
+};
+VREG_CONSUMERS(L7) = {
+ REGULATOR_SUPPLY("8941_l7", NULL),
+};
+VREG_CONSUMERS(L8) = {
+ REGULATOR_SUPPLY("8941_l8", NULL),
+};
+VREG_CONSUMERS(L9) = {
+ REGULATOR_SUPPLY("8941_l9", NULL),
+};
+VREG_CONSUMERS(L10) = {
+ REGULATOR_SUPPLY("8941_l10", NULL),
+};
+VREG_CONSUMERS(L11) = {
+ REGULATOR_SUPPLY("8941_l11", NULL),
+};
+VREG_CONSUMERS(L12) = {
+ REGULATOR_SUPPLY("8941_l12", NULL),
+};
+VREG_CONSUMERS(L13) = {
+ REGULATOR_SUPPLY("8941_l13", NULL),
+};
+VREG_CONSUMERS(L14) = {
+ REGULATOR_SUPPLY("8941_l14", NULL),
+};
+VREG_CONSUMERS(L15) = {
+ REGULATOR_SUPPLY("8941_l15", NULL),
+};
+VREG_CONSUMERS(L16) = {
+ REGULATOR_SUPPLY("8941_l16", NULL),
+};
+VREG_CONSUMERS(L17) = {
+ REGULATOR_SUPPLY("8941_l17", NULL),
+};
+VREG_CONSUMERS(L18) = {
+ REGULATOR_SUPPLY("8941_l18", NULL),
+};
+VREG_CONSUMERS(L19) = {
+ REGULATOR_SUPPLY("8941_l19", NULL),
+};
+VREG_CONSUMERS(L20) = {
+ REGULATOR_SUPPLY("8941_l20", NULL),
+};
+VREG_CONSUMERS(L21) = {
+ REGULATOR_SUPPLY("8941_l21", NULL),
+};
+VREG_CONSUMERS(L22) = {
+ REGULATOR_SUPPLY("8941_l22", NULL),
+};
+VREG_CONSUMERS(L23) = {
+ REGULATOR_SUPPLY("8941_l23", NULL),
+};
+VREG_CONSUMERS(L24) = {
+ REGULATOR_SUPPLY("8941_l24", NULL),
+};
+VREG_CONSUMERS(LVS1) = {
+ REGULATOR_SUPPLY("8941_lvs1", NULL),
+};
+VREG_CONSUMERS(LVS2) = {
+ REGULATOR_SUPPLY("8941_lvs2", NULL),
+};
+VREG_CONSUMERS(LVS3) = {
+ REGULATOR_SUPPLY("8941_lvs3", NULL),
+};
+
+#define PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
+ _always_on, _supply_regulator, _hpm_min, _system_uA) \
+ struct stub_regulator_pdata vreg_dev_##_id##_pdata __devinitdata = { \
+ .init_data = { \
+ .constraints = { \
+ .valid_modes_mask = _modes, \
+ .valid_ops_mask = _ops, \
+ .min_uV = _min_uV, \
+ .max_uV = _max_uV, \
+ .input_uV = _max_uV, \
+ .apply_uV = 0, \
+ .always_on = _always_on, \
+ .name = _name, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id), \
+ .consumer_supplies = vreg_consumers_##_id, \
+ .supply_regulator = _supply_regulator, \
+ }, \
+ .hpm_min_load = _hpm_min, \
+ .system_uA = _system_uA, \
+ }
+
+#define PM8X41_LDO(_id, _name, _always_on, _min_uV, _max_uV, \
+ _supply_regulator, _hpm_min, _system_uA) \
+ PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+ | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
+ REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_DRMS, _always_on, \
+ _supply_regulator, _hpm_min, _system_uA)
+
+#define PM8X41_SMPS(_id, _name, _always_on, _min_uV, _max_uV, \
+ _supply_regulator, _hpm_min, _system_uA) \
+ PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+ | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
+ REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_DRMS, _always_on, \
+ _supply_regulator, _hpm_min, _system_uA)
+
+#define PM8X41_FTSMPS(_id, _name, _always_on, _min_uV, _max_uV, \
+ _supply_regulator, _hpm_min, _system_uA) \
+ PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL, \
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS \
+ | REGULATOR_CHANGE_MODE, _always_on, \
+ _supply_regulator, _hpm_min, _system_uA)
+
+#define PM8X41_VS(_id, _name, _always_on, _supply_regulator) \
+ PM8X41_VREG_INIT(_id, _name, 0, 0, 0, REGULATOR_CHANGE_STATUS, \
+ _always_on, _supply_regulator, 0, 0)
+
+/* PM8x41 regulator constraints */
+
+/* ID name a_on min_uV max_uV supply hpm_min sys_uA */
+PM8X41_SMPS(S1B, "8841_s1", 0, 900000, 1150000, NULL, 100000, 0);
+PM8X41_FTSMPS(S2B, "8841_s2", 0, 900000, 1150000, NULL, 100000, 0);
+PM8X41_SMPS(S3B, "8841_s3", 0, 1150000, 1150000, NULL, 100000, 0);
+PM8X41_FTSMPS(S4B, "8841_s4", 0, 900000, 900000, NULL, 100000, 0);
+PM8X41_FTSMPS(S5B, "8841_s5", 0, 850000, 1100000, NULL, 100000, 0);
+PM8X41_FTSMPS(S6B, "8841_s6", 0, 850000, 1100000, NULL, 100000, 0);
+PM8X41_FTSMPS(S7B, "8841_s7", 0, 850000, 1100000, NULL, 100000, 0);
+PM8X41_FTSMPS(S8B, "8841_s8", 0, 850000, 1100000, NULL, 100000, 0);
+PM8X41_SMPS(S1, "8941_s1", 0, 1300000, 1300000, NULL, 100000, 0);
+PM8X41_SMPS(S2, "8941_s2", 0, 2150000, 2150000, NULL, 100000, 0);
+PM8X41_SMPS(S3, "8941_s3", 0, 1800000, 1800000, NULL, 100000, 0);
+PM8X41_LDO(L1, "8941_l1", 0, 1225000, 1225000, "8941_s1", 100000, 0);
+PM8X41_LDO(L2, "8941_l2", 0, 1200000, 1200000, "8941_s3", 5000, 0);
+PM8X41_LDO(L3, "8941_l3", 0, 1200000, 1200000, "8941_s1", 10000, 0);
+PM8X41_LDO(L4, "8941_l4", 0, 1150000, 1150000, "8941_s1", 10000, 0);
+PM8X41_LDO(L5, "8941_l5", 0, 1800000, 1800000, "8941_s2", 1000, 0);
+PM8X41_LDO(L6, "8941_l6", 0, 1800000, 1800000, "8941_s2", 10000, 0);
+PM8X41_LDO(L7, "8941_l7", 0, 1800000, 1800000, "8941_s2", 1000, 0);
+PM8X41_LDO(L8, "8941_l8", 0, 1800000, 1800000, NULL, 1000, 0);
+PM8X41_LDO(L9, "8941_l9", 0, 1800000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L10, "8941_l10", 0, 1800000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L11, "8941_l11", 0, 1250000, 1250000, "8941_s1", 10000, 0);
+PM8X41_LDO(L12, "8941_l12", 0, 1800000, 1800000, "8941_s2", 10000, 0);
+PM8X41_LDO(L13, "8941_l13", 0, 2950000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L14, "8941_l14", 0, 1800000, 1800000, "8941_s2", 10000, 0);
+PM8X41_LDO(L15, "8941_l15", 0, 2050000, 2050000, "8941_s2", 10000, 0);
+PM8X41_LDO(L16, "8941_l16", 0, 2700000, 2700000, NULL, 10000, 0);
+PM8X41_LDO(L17, "8941_l17", 0, 2850000, 2850000, NULL, 10000, 0);
+PM8X41_LDO(L18, "8941_l18", 0, 2850000, 2850000, NULL, 10000, 0);
+PM8X41_LDO(L19, "8941_l19", 0, 2900000, 2900000, NULL, 10000, 0);
+PM8X41_LDO(L20, "8941_l20", 0, 2950000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L21, "8941_l21", 0, 2950000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L22, "8941_l22", 0, 3000000, 3000000, NULL, 10000, 0);
+PM8X41_LDO(L23, "8941_l23", 0, 3000000, 3000000, NULL, 10000, 0);
+PM8X41_LDO(L24, "8941_l24", 0, 3075000, 3075000, NULL, 5000, 0);
+
+/* ID name a_on supply */
+PM8X41_VS(LVS1, "8941_lvs1", 0, "8941_s3");
+PM8X41_VS(LVS2, "8941_lvs2", 0, "8941_s3");
+PM8X41_VS(LVS3, "8941_lvs3", 0, "8941_s3");
+
+#define VREG_DEVICE(_name, _devid) \
+ vreg_device_##_name __devinitdata = \
+ { \
+ .name = STUB_REGULATOR_DRIVER_NAME, \
+ .id = _devid, \
+ .dev = { .platform_data = &vreg_dev_##_name##_pdata }, \
+ }
+
+static struct platform_device VREG_DEVICE(S1B, 0);
+static struct platform_device VREG_DEVICE(S2B, 1);
+static struct platform_device VREG_DEVICE(S3B, 3);
+static struct platform_device VREG_DEVICE(S4B, 4);
+static struct platform_device VREG_DEVICE(S5B, 5);
+static struct platform_device VREG_DEVICE(S6B, 6);
+static struct platform_device VREG_DEVICE(S7B, 7);
+static struct platform_device VREG_DEVICE(S8B, 8);
+static struct platform_device VREG_DEVICE(S1, 9);
+static struct platform_device VREG_DEVICE(S2, 10);
+static struct platform_device VREG_DEVICE(S3, 11);
+static struct platform_device VREG_DEVICE(L1, 12);
+static struct platform_device VREG_DEVICE(L2, 13);
+static struct platform_device VREG_DEVICE(L3, 14);
+static struct platform_device VREG_DEVICE(L4, 15);
+static struct platform_device VREG_DEVICE(L5, 16);
+static struct platform_device VREG_DEVICE(L6, 17);
+static struct platform_device VREG_DEVICE(L7, 18);
+static struct platform_device VREG_DEVICE(L8, 19);
+static struct platform_device VREG_DEVICE(L9, 20);
+static struct platform_device VREG_DEVICE(L10, 21);
+static struct platform_device VREG_DEVICE(L11, 22);
+static struct platform_device VREG_DEVICE(L12, 23);
+static struct platform_device VREG_DEVICE(L13, 24);
+static struct platform_device VREG_DEVICE(L14, 25);
+static struct platform_device VREG_DEVICE(L15, 26);
+static struct platform_device VREG_DEVICE(L16, 27);
+static struct platform_device VREG_DEVICE(L17, 28);
+static struct platform_device VREG_DEVICE(L18, 29);
+static struct platform_device VREG_DEVICE(L19, 30);
+static struct platform_device VREG_DEVICE(L20, 31);
+static struct platform_device VREG_DEVICE(L21, 32);
+static struct platform_device VREG_DEVICE(L22, 33);
+static struct platform_device VREG_DEVICE(L23, 34);
+static struct platform_device VREG_DEVICE(L24, 35);
+static struct platform_device VREG_DEVICE(LVS1, 36);
+static struct platform_device VREG_DEVICE(LVS2, 37);
+static struct platform_device VREG_DEVICE(LVS3, 38);
+
+struct platform_device *msm_copper_stub_regulator_devices[] __devinitdata = {
+ &vreg_device_S1B,
+ &vreg_device_S2B,
+ &vreg_device_S3B,
+ &vreg_device_S4B,
+ &vreg_device_S5B,
+ &vreg_device_S6B,
+ &vreg_device_S7B,
+ &vreg_device_S8B,
+ &vreg_device_S1,
+ &vreg_device_S2,
+ &vreg_device_S3,
+ &vreg_device_L1,
+ &vreg_device_L2,
+ &vreg_device_L3,
+ &vreg_device_L4,
+ &vreg_device_L5,
+ &vreg_device_L6,
+ &vreg_device_L7,
+ &vreg_device_L8,
+ &vreg_device_L9,
+ &vreg_device_L10,
+ &vreg_device_L11,
+ &vreg_device_L12,
+ &vreg_device_L13,
+ &vreg_device_L14,
+ &vreg_device_L15,
+ &vreg_device_L16,
+ &vreg_device_L17,
+ &vreg_device_L18,
+ &vreg_device_L19,
+ &vreg_device_L20,
+ &vreg_device_L21,
+ &vreg_device_L22,
+ &vreg_device_L23,
+ &vreg_device_L24,
+ &vreg_device_LVS1,
+ &vreg_device_LVS2,
+ &vreg_device_LVS3,
+};
+
+int msm_copper_stub_regulator_devices_len __devinitdata =
+ ARRAY_SIZE(msm_copper_stub_regulator_devices);
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index c30be16..97ea645 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -26,6 +26,7 @@
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
+#include <linux/regulator/stub-regulator.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
#include <mach/board.h>
@@ -39,6 +40,7 @@
#include <mach/msm_smd.h>
#include <mach/qpnp-int.h>
#include "clock.h"
+#include "devices.h"
#define MSM_KERNEL_EBI1_MEM_SIZE 0x280000
#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
@@ -357,6 +359,8 @@
platform_device_register(&ion_dev);
#endif
platform_device_register(&msm_device_smd_copper);
+ platform_add_devices(msm_copper_stub_regulator_devices,
+ msm_copper_stub_regulator_devices_len);
}
static struct of_device_id irq_match[] __initdata = {
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 7b075cd..7fecf59 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -24,6 +24,12 @@
#include "board-msm7627a.h"
#include <mach/vreg.h>
+#define GPIO_SKU1_CAM_VGA_SHDN 18
+#define GPIO_SKU1_CAM_VGA_RESET_N 29
+#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
+
#ifdef CONFIG_MSM_CAMERA_V4L2
static uint32_t camera_off_gpio_table[] = {
GPIO_CFG(15, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
@@ -33,6 +39,55 @@
GPIO_CFG(15, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
};
+static struct gpio s5k4e1_cam_req_gpio[] = {
+ {GPIO_CAM_GP_CAMIF_RESET_N, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl s5k4e1_cam_gpio_set_tbl[] = {
+ {GPIO_CAM_GP_CAMIF_RESET_N, GPIOF_OUT_INIT_LOW, 1000},
+ {GPIO_CAM_GP_CAMIF_RESET_N, GPIOF_OUT_INIT_HIGH, 4000},
+};
+
+static struct msm_camera_gpio_conf gpio_conf_s5k4e1 = {
+ .camera_off_table = camera_off_gpio_table,
+ .camera_off_table_size = ARRAY_SIZE(camera_off_gpio_table),
+ .camera_on_table = camera_on_gpio_table,
+ .camera_on_table_size = ARRAY_SIZE(camera_on_gpio_table),
+ .cam_gpio_req_tbl = s5k4e1_cam_req_gpio,
+ .cam_gpio_req_tbl_size = ARRAY_SIZE(s5k4e1_cam_req_gpio),
+ .cam_gpio_set_tbl = s5k4e1_cam_gpio_set_tbl,
+ .cam_gpio_set_tbl_size = ARRAY_SIZE(s5k4e1_cam_gpio_set_tbl),
+ .gpio_no_mux = 1,
+};
+
+static struct msm_camera_gpio_conf gpio_conf_mt9e013 = {
+ .camera_off_table = camera_off_gpio_table,
+ .camera_on_table = camera_on_gpio_table,
+ .gpio_no_mux = 1,
+};
+
+static struct msm_camera_gpio_conf gpio_conf_ov9726 = {
+ .camera_off_table = camera_off_gpio_table,
+ .camera_on_table = camera_on_gpio_table,
+ .gpio_no_mux = 1,
+};
+
+#ifdef CONFIG_WEBCAM_OV7692_QRD
+static struct msm_camera_gpio_conf gpio_conf_ov7692 = {
+ .camera_off_table = camera_off_gpio_table,
+ .camera_on_table = camera_on_gpio_table,
+ .gpio_no_mux = 1,
+};
+#endif
+
+#ifdef CONFIG_OV5647
+static struct msm_camera_gpio_conf gpio_conf_ov5647 = {
+ .camera_off_table = camera_off_gpio_table,
+ .camera_on_table = camera_on_gpio_table,
+ .gpio_no_mux = 1,
+};
+#endif
+
#ifdef CONFIG_MSM_CAMERA_FLASH
static struct msm_camera_sensor_flash_src msm_flash_src = {
.flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
@@ -41,111 +96,22 @@
};
#endif
-static struct regulator_bulk_data regs_camera[] = {
- { .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
- { .supply = "gp2", .min_uV = 2850000, .max_uV = 2850000 },
- { .supply = "usb2", .min_uV = 1800000, .max_uV = 1800000 },
+static struct camera_vreg_t msm_cam_vreg[] = {
+ {"msme1", REG_LDO, 1800000, 1800000, 0},
+ {"gp2", REG_LDO, 2850000, 2850000, 0},
+ {"usb2", REG_LDO, 1800000, 1800000, 0},
};
-static void msm_camera_vreg_config(int vreg_en)
-{
- int rc = vreg_en ?
- regulator_bulk_enable(ARRAY_SIZE(regs_camera), regs_camera) :
- regulator_bulk_disable(ARRAY_SIZE(regs_camera), regs_camera);
-
- if (rc)
- pr_err("%s: could not %sable regulators: %d\n",
- __func__, vreg_en ? "en" : "dis", rc);
-}
-
-static int config_gpio_table(uint32_t *table, int len)
-{
- int rc = 0, i = 0;
-
- for (i = 0; i < len; i++) {
- rc = gpio_tlmm_config(table[i], GPIO_CFG_ENABLE);
- if (rc) {
- pr_err("%s not able to get gpio\n", __func__);
- for (i--; i >= 0; i--)
- gpio_tlmm_config(camera_off_gpio_table[i],
- GPIO_CFG_ENABLE);
- break;
- }
- }
- return rc;
-}
-
static struct msm_camera_sensor_info msm_camera_sensor_s5k4e1_data;
-/* TODO: static struct msm_camera_sensor_info msm_camera_sensor_ov9726_data; */
-static int config_camera_on_gpios_rear(void)
-{
- int rc = 0;
-
- if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
- msm_camera_vreg_config(1);
-
- rc = config_gpio_table(camera_on_gpio_table,
- ARRAY_SIZE(camera_on_gpio_table));
- if (rc < 0) {
- pr_err("%s: CAMSENSOR gpio table request"
- "failed\n", __func__);
- return rc;
- }
-
- return rc;
-}
-
-static void config_camera_off_gpios_rear(void)
-{
- if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
- msm_camera_vreg_config(0);
-
- config_gpio_table(camera_off_gpio_table,
- ARRAY_SIZE(camera_off_gpio_table));
-}
-
-static int config_camera_on_gpios_front(void)
-{
- int rc = 0;
-
- if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
- msm_camera_vreg_config(1);
-
- rc = config_gpio_table(camera_on_gpio_table,
- ARRAY_SIZE(camera_on_gpio_table));
- if (rc < 0) {
- pr_err("%s: CAMSENSOR gpio table request"
- "failed\n", __func__);
- return rc;
- }
-
- return rc;
-}
-
-static void config_camera_off_gpios_front(void)
-{
- if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
- msm_camera_vreg_config(0);
-
- config_gpio_table(camera_off_gpio_table,
- ARRAY_SIZE(camera_off_gpio_table));
-}
struct msm_camera_device_platform_data msm_camera_device_data_csi1 = {
- .camera_gpio_on = config_camera_on_gpios_rear,
- .camera_gpio_off = config_camera_off_gpios_rear,
- .ioclk.mclk_clk_rate = 24000000,
- .ioclk.vfe_clk_rate = 192000000,
.csid_core = 1,
.is_csic = 1,
};
struct msm_camera_device_platform_data msm_camera_device_data_csi0 = {
- .camera_gpio_on = config_camera_on_gpios_front,
- .camera_gpio_off = config_camera_off_gpios_front,
- .ioclk.mclk_clk_rate = 24000000,
- .ioclk.vfe_clk_rate = 192000000,
.csid_core = 0,
+ .is_csic = 1,
};
#ifdef CONFIG_DW9712_ACT
@@ -169,10 +135,9 @@
static struct msm_camera_sensor_platform_info sensor_board_info_s5k4e1 = {
.mount_angle = 90,
- .sensor_reset = GPIO_CAM_GP_CAMIF_RESET_N,
- .sensor_pwd = 85,
- .vcm_pwd = GPIO_CAM_GP_CAM_PWDN,
- .vcm_enable = 1,
+ .cam_vreg = msm_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_cam_vreg),
+ .gpio_conf = &gpio_conf_s5k4e1,
};
static struct msm_camera_sensor_info msm_camera_sensor_s5k4e1_data = {
@@ -190,6 +155,83 @@
};
#endif
+#ifdef CONFIG_WEBCAM_OV7692_QRD
+static struct msm_camera_sensor_platform_info sensor_board_info_ov7692 = {
+ .mount_angle = 90,
+ .cam_vreg = msm_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_cam_vreg),
+ .gpio_conf = &gpio_conf_ov7692,
+};
+
+static struct msm_camera_sensor_flash_data flash_ov7692 = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov7692_data = {
+ .sensor_name = "ov7692",
+ .sensor_reset_enable = 0,
+ .pmic_gpio_enable = 1,
+ .sensor_reset = GPIO_SKU1_CAM_VGA_RESET_N,
+ .sensor_pwd = GPIO_SKU1_CAM_VGA_SHDN,
+ .pdata = &msm_camera_device_data_csi0,
+ .flash_data = &flash_ov7692,
+ .sensor_platform_info = &sensor_board_info_ov7692,
+ .csi_if = 1,
+ .camera_type = FRONT_CAMERA_2D,
+};
+#endif
+
+#ifdef CONFIG_OV5647
+
+#ifdef CONFIG_AD5046_ACT
+static struct i2c_board_info ad5046_actuator_i2c_info = {
+ I2C_BOARD_INFO("ad5046_act", 0x18 >> 1),
+};
+
+static struct msm_actuator_info ad5046_actuator_info = {
+ .board_info = &ad5046_actuator_i2c_info,
+ .bus_id = MSM_GSBI0_QUP_I2C_BUS_ID,
+ .vcm_pwd = GPIO_SKU3_CAM_5MP_CAM_DRIVER_PWDN,
+ .vcm_enable = 1,
+};
+#endif
+
+static struct msm_camera_sensor_platform_info sensor_board_info_ov5647 = {
+ .mount_angle = 90,
+ .cam_vreg = msm_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_cam_vreg),
+ .gpio_conf = &gpio_conf_ov5647,
+};
+
+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,
+ .pmic_gpio_enable = 1,
+ .sensor_reset = GPIO_SKU3_CAM_5MP_CAMIF_RESET,
+ .sensor_pwd = GPIO_SKU3_CAM_5MP_SHDN_N,
+ .pdata = &msm_camera_device_data_csi1,
+ .flash_data = &flash_ov5647,
+ .sensor_platform_info = &sensor_board_info_ov5647,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+
+#ifdef CONFIG_AD5046_ACT
+ .actuator_info = &ad5046_actuator_info
+#endif
+};
+
+#endif
#ifdef CONFIG_MT9E013
static struct msm_camera_sensor_flash_data flash_mt9e013 = {
.flash_type = MSM_CAMERA_FLASH_LED,
@@ -198,10 +240,9 @@
static struct msm_camera_sensor_platform_info sensor_board_info_mt9e013 = {
.mount_angle = 90,
- .sensor_reset = 0,
- .sensor_pwd = 85,
- .vcm_pwd = 1,
- .vcm_enable = 0,
+ .cam_vreg = msm_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_cam_vreg),
+ .gpio_conf = &gpio_conf_mt9e013,
};
static struct msm_camera_sensor_info msm_camera_sensor_mt9e013_data = {
@@ -216,38 +257,6 @@
};
#endif
-#ifdef CONFIG_IMX072
-static struct msm_camera_sensor_platform_info imx072_sensor_7627a_info = {
- .mount_angle = 90
-};
-
-static struct msm_camera_sensor_flash_data flash_imx072 = {
- .flash_type = MSM_CAMERA_FLASH_LED,
- .flash_src = &msm_flash_src
-};
-
-static struct msm_camera_sensor_info msm_camera_sensor_imx072_data = {
- .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,
- .pdata = &msm_camera_device_data_csi1,
- .flash_data = &flash_imx072,
- .sensor_platform_info = &imx072_sensor_7627a_info,
- .csi_if = 1
-};
-
-static struct platform_device msm_camera_sensor_imx072 = {
- .name = "msm_camera_imx072",
- .dev = {
- .platform_data = &msm_camera_sensor_imx072_data,
- },
-};
-#endif
-
#ifdef CONFIG_WEBCAM_OV9726
static struct msm_camera_sensor_flash_data flash_ov9726 = {
.flash_type = MSM_CAMERA_FLASH_LED,
@@ -256,10 +265,9 @@
static struct msm_camera_sensor_platform_info sensor_board_info_ov9726 = {
.mount_angle = 90,
- .sensor_reset = GPIO_CAM_GP_CAM1MP_XCLR,
- .sensor_pwd = 85,
- .vcm_pwd = 1,
- .vcm_enable = 0,
+ .cam_vreg = msm_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_cam_vreg),
+ .gpio_conf = &gpio_conf_ov9726,
};
static struct msm_camera_sensor_info msm_camera_sensor_ov9726_data = {
@@ -276,36 +284,51 @@
static void __init msm7x27a_init_cam(void)
{
- platform_device_register(&msm7x27a_device_csic0);
- platform_device_register(&msm7x27a_device_csic1);
+ if (!(machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa()
+ || machine_is_msm7627a_qrd1())) {
+ sensor_board_info_s5k4e1.cam_vreg = NULL;
+ sensor_board_info_s5k4e1.num_vreg = 0;
+ sensor_board_info_mt9e013.cam_vreg = NULL;
+ sensor_board_info_mt9e013.num_vreg = 0;
+ sensor_board_info_ov9726.cam_vreg = NULL;
+ sensor_board_info_ov9726.num_vreg = 0;
+ sensor_board_info_ov7692.cam_vreg = NULL;
+ sensor_board_info_ov7692.num_vreg = 0;
+ sensor_board_info_ov5647.cam_vreg = NULL;
+ sensor_board_info_ov5647.num_vreg = 0;
+ }
+ if (machine_is_msm8625_surf() || machine_is_msm8625_evb()) {
+ platform_device_register(&msm8625_device_csic0);
+ platform_device_register(&msm8625_device_csic1);
+ } else {
+ platform_device_register(&msm7x27a_device_csic0);
+ platform_device_register(&msm7x27a_device_csic1);
+ }
platform_device_register(&msm7x27a_device_clkctl);
platform_device_register(&msm7x27a_device_vfe);
}
static struct i2c_board_info i2c_camera_devices[] = {
- #ifdef CONFIG_S5K4E1
{
I2C_BOARD_INFO("s5k4e1", 0x36),
.platform_data = &msm_camera_sensor_s5k4e1_data,
},
- #endif
- #ifdef CONFIG_WEBCAM_OV9726
{
I2C_BOARD_INFO("ov9726", 0x10),
.platform_data = &msm_camera_sensor_ov9726_data,
},
- #endif
- #ifdef CONFIG_IMX072
- {
- I2C_BOARD_INFO("imx072", 0x34),
- },
- #endif
- #ifdef CONFIG_MT9E013
{
I2C_BOARD_INFO("mt9e013", 0x6C >> 2),
.platform_data = &msm_camera_sensor_mt9e013_data,
},
- #endif
+ {
+ I2C_BOARD_INFO("ov7692", 0x78),
+ .platform_data = &msm_camera_sensor_ov7692_data,
+ },
+ {
+ I2C_BOARD_INFO("ov5647", 0x36 << 1),
+ .platform_data = &msm_camera_sensor_ov5647_data,
+ },
{
I2C_BOARD_INFO("sc628a", 0x6E),
},
@@ -389,13 +412,7 @@
gpio_direction_output(QRD_GPIO_CAM_5MP_RESET, 1);
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
+#endif
static void evb_camera_gpio_cfg(void)
{
@@ -469,6 +486,8 @@
}
+#ifndef CONFIG_MSM_CAMERA_V4L2
+
static void msm_camera_vreg_config(int vreg_en)
{
int rc = vreg_en ?
@@ -1034,23 +1053,27 @@
}
EXPORT_SYMBOL(lcd_camera_power_onoff);
-
void __init msm7627a_camera_init(void)
{
+
+#ifndef CONFIG_MSM_CAMERA_V4L2
int rc;
+#endif
pr_debug("msm7627a_camera_init Entered\n");
/* LCD and camera power (VREG & LDO) init */
- if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
+ if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
+ evb_camera_gpio_cfg();
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() || machine_is_msm8625_evb()) {
- evb_camera_gpio_cfg();
platform_add_devices(camera_devices_evb,
ARRAY_SIZE(camera_devices_evb));
} else if (machine_is_msm7627a_qrd3())
@@ -1062,6 +1085,7 @@
if (!machine_is_msm7627a_qrd1() || !machine_is_msm7627a_evb()
|| !machine_is_msm8625_evb())
register_i2c_devices();
+#ifndef CONFIG_MSM_CAMERA_V4L2
rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
if (rc) {
@@ -1075,6 +1099,7 @@
pr_err("%s: could not set voltages: %d\n", __func__, rc);
return;
}
+#endif
#if defined(CONFIG_MSM_CAMERA_V4L2)
msm7x27a_init_cam();
@@ -1091,6 +1116,7 @@
ARRAY_SIZE(i2c_camera_devices_evb));
} else
#endif
+ pr_debug("i2c_register_board_info\n");
i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
i2c_camera_devices,
ARRAY_SIZE(i2c_camera_devices));
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index d07703b..ec2be96 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -948,6 +948,7 @@
static void __init msm8625_reserve(void)
{
msm7x27a_reserve();
+ memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
msm_pm_8625_boot_pdata.p_addr = memblock_alloc(SZ_8, SZ_64K);
}
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index b3d7de4..41c02ab 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -439,6 +439,72 @@
.p_addr = 0,
};
+/* 8625 PM platform data */
+static struct msm_pm_platform_data msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+ /* CORE0 entries */
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 16000,
+ .residency = 20000,
+ },
+
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 12000,
+ .residency = 20000,
+ },
+
+ /* picked latency & redisdency values from 7x30 */
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 500,
+ .residency = 6000,
+ },
+
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ .latency = 2,
+ .residency = 10,
+ },
+
+ /* picked latency & redisdency values from 7x30 */
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 500,
+ .residency = 6000,
+ },
+
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ .latency = 2,
+ .residency = 10,
+ },
+
+};
+
+static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = {
+ .mode = MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR,
+ .v_addr = MSM_CFG_CTL_BASE,
+};
+
static struct android_pmem_platform_data android_pmem_adsp_pdata = {
.name = "pmem_adsp",
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
@@ -774,6 +840,13 @@
{
reserve_info = &msm7627a_reserve_info;
msm_reserve();
+ msm_pm_8625_boot_pdata.p_addr = memblock_alloc(SZ_8, SZ_64K);
+}
+
+static void __init msm8625_reserve(void)
+{
+ memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+ msm7627a_reserve();
}
static void msmqrd_adsp_add_pdev(void)
@@ -1145,6 +1218,11 @@
msm_pm_set_platform_data(msm7627a_pm_data,
ARRAY_SIZE(msm7627a_pm_data));
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+ } else {
+ msm_pm_set_platform_data(msm8625_pm_data,
+ ARRAY_SIZE(msm8625_pm_data));
+ BUG_ON(msm_pm_boot_init(&msm_pm_8625_boot_pdata));
+ msm8x25_spm_device_init();
}
msm_fb_add_devices();
@@ -1196,7 +1274,7 @@
MACHINE_START(MSM8625_EVB, "QRD MSM8625 EVB")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm8625_map_io,
- .reserve = msm7627a_reserve,
+ .reserve = msm8625_reserve,
.init_irq = msm8625_init_irq,
.init_machine = msm_qrd_init,
.timer = &msm_timer,
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
new file mode 100644
index 0000000..3c317e9
--- /dev/null
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -0,0 +1,475 @@
+/* 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/cpu.h>
+#include <mach/msm-krait-l2-accessors.h>
+
+#define CESR_DCTPE BIT(0)
+#define CESR_DCDPE BIT(1)
+#define CESR_ICTPE BIT(2)
+#define CESR_ICDPE BIT(3)
+#define CESR_DCTE (BIT(4) | BIT(5))
+#define CESR_ICTE (BIT(6) | BIT(7))
+#define CESR_TLBMH BIT(16)
+#define CESR_I_MASK 0x000000CC
+
+#define L2ESR_IND_ADDR 0x204
+#define L2ESYNR0_IND_ADDR 0x208
+#define L2ESYNR1_IND_ADDR 0x209
+#define L2EAR0_IND_ADDR 0x20C
+#define L2EAR1_IND_ADDR 0x20D
+
+#define L2ESR_MPDCD BIT(0)
+#define L2ESR_MPSLV BIT(1)
+#define L2ESR_TSESB BIT(2)
+#define L2ESR_TSEDB BIT(3)
+#define L2ESR_DSESB BIT(4)
+#define L2ESR_DSEDB BIT(5)
+#define L2ESR_MSE BIT(6)
+#define L2ESR_MPLDREXNOK BIT(8)
+
+#define L2ESR_CPU_MASK 0x0F
+#define L2ESR_CPU_SHIFT 16
+
+#ifdef CONFIG_MSM_L1_ERR_PANIC
+#define ERP_L1_ERR(a) panic(a)
+#else
+#define ERP_L1_ERR(a) do { } while (0)
+#endif
+
+#ifdef CONFIG_MSM_L2_ERP_PORT_PANIC
+#define ERP_PORT_ERR(a) panic(a)
+#else
+#define ERP_PORT_ERR(a) WARN(1, a)
+#endif
+
+#ifdef CONFIG_MSM_L2_ERP_1BIT_PANIC
+#define ERP_1BIT_ERR(a) panic(a)
+#else
+#define ERP_1BIT_ERR(a) do { } while (0)
+#endif
+
+#ifdef CONFIG_MSM_L2_ERP_2BIT_PANIC
+#define ERP_2BIT_ERR(a) panic(a)
+#else
+#define ERP_2BIT_ERR(a) do { } while (0)
+#endif
+
+#define MODULE_NAME "msm_cache_erp"
+
+struct msm_l1_err_stats {
+ unsigned int dctpe;
+ unsigned int dcdpe;
+ unsigned int ictpe;
+ unsigned int icdpe;
+ unsigned int dcte;
+ unsigned int icte;
+ unsigned int tlbmh;
+};
+
+struct msm_l2_err_stats {
+ unsigned int mpdcd;
+ unsigned int mpslv;
+ unsigned int tsesb;
+ unsigned int tsedb;
+ unsigned int dsesb;
+ unsigned int dsedb;
+ unsigned int mse;
+ unsigned int mplxrexnok;
+};
+
+static DEFINE_PER_CPU(struct msm_l1_err_stats, msm_l1_erp_stats);
+static struct msm_l2_err_stats msm_l2_erp_stats;
+
+static int l1_erp_irq, l2_erp_irq;
+static struct proc_dir_entry *procfs_entry;
+
+static inline unsigned int read_cesr(void)
+{
+ unsigned int cesr;
+ asm volatile ("mrc p15, 7, %0, c15, c0, 1" : "=r" (cesr));
+ return cesr;
+}
+
+static inline void write_cesr(unsigned int cesr)
+{
+ asm volatile ("mcr p15, 7, %[cesr], c15, c0, 1" : : [cesr]"r" (cesr));
+}
+
+static inline unsigned int read_cesynr(void)
+{
+ unsigned int cesynr;
+ asm volatile ("mrc p15, 7, %0, c15, c0, 3" : "=r" (cesynr));
+ return cesynr;
+}
+
+static int proc_read_status(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ struct msm_l1_err_stats *l1_stats;
+ char *p = page;
+ int len, cpu, ret, bytes_left = PAGE_SIZE;
+
+ for_each_present_cpu(cpu) {
+ l1_stats = &per_cpu(msm_l1_erp_stats, cpu);
+
+ ret = snprintf(p, bytes_left,
+ "CPU %d:\n" \
+ "\tD-cache tag parity errors:\t%u\n" \
+ "\tD-cache data parity errors:\t%u\n" \
+ "\tI-cache tag parity errors:\t%u\n" \
+ "\tI-cache data parity errors:\t%u\n" \
+ "\tD-cache timing errors:\t\t%u\n" \
+ "\tI-cache timing errors:\t\t%u\n" \
+ "\tTLB multi-hit errors:\t\t%u\n\n", \
+ cpu,
+ l1_stats->dctpe,
+ l1_stats->dcdpe,
+ l1_stats->ictpe,
+ l1_stats->icdpe,
+ l1_stats->dcte,
+ l1_stats->icte,
+ l1_stats->tlbmh);
+ p += ret;
+ bytes_left -= ret;
+ }
+
+ p += snprintf(p, bytes_left,
+ "L2 master port decode errors:\t\t%u\n" \
+ "L2 master port slave errors:\t\t%u\n" \
+ "L2 tag soft errors, single-bit:\t\t%u\n" \
+ "L2 tag soft errors, double-bit:\t\t%u\n" \
+ "L2 data soft errors, single-bit:\t%u\n" \
+ "L2 data soft errors, double-bit:\t%u\n" \
+ "L2 modified soft errors:\t\t%u\n" \
+ "L2 master port LDREX NOK errors:\t%u\n",
+ msm_l2_erp_stats.mpdcd,
+ msm_l2_erp_stats.mpslv,
+ msm_l2_erp_stats.tsesb,
+ msm_l2_erp_stats.tsedb,
+ msm_l2_erp_stats.dsesb,
+ msm_l2_erp_stats.dsedb,
+ msm_l2_erp_stats.mse,
+ msm_l2_erp_stats.mplxrexnok);
+
+ len = (p - page) - off;
+ if (len < 0)
+ len = 0;
+
+ *eof = (len <= count) ? 1 : 0;
+ *start = page + off;
+
+ return len;
+}
+
+static irqreturn_t msm_l1_erp_irq(int irq, void *dev_id)
+{
+ struct msm_l1_err_stats *l1_stats = dev_id;
+ unsigned int cesr = read_cesr();
+ unsigned int i_cesynr, d_cesynr;
+
+ pr_alert("L1 Error detected on CPU %d!\n", smp_processor_id());
+ pr_alert("\tCESR = 0x%08x\n", cesr);
+
+ if (cesr & CESR_DCTPE) {
+ pr_alert("D-cache tag parity error\n");
+ l1_stats->dctpe++;
+ }
+
+ if (cesr & CESR_DCDPE) {
+ pr_alert("D-cache data parity error\n");
+ l1_stats->dcdpe++;
+ }
+
+ if (cesr & CESR_ICTPE) {
+ pr_alert("I-cache tag parity error\n");
+ l1_stats->ictpe++;
+ }
+
+ if (cesr & CESR_ICDPE) {
+ pr_alert("I-cache data parity error\n");
+ l1_stats->icdpe++;
+ }
+
+ if (cesr & CESR_DCTE) {
+ pr_alert("D-cache timing error\n");
+ l1_stats->dcte++;
+ }
+
+ if (cesr & CESR_ICTE) {
+ pr_alert("I-cache timing error\n");
+ l1_stats->icte++;
+ }
+
+ if (cesr & CESR_TLBMH) {
+ pr_alert("TLB multi-hit error\n");
+ l1_stats->tlbmh++;
+ }
+
+ if (cesr & (CESR_ICTPE | CESR_ICDPE | CESR_ICTE)) {
+ i_cesynr = read_cesynr();
+ pr_alert("I-side CESYNR = 0x%08x\n", i_cesynr);
+ write_cesr(CESR_I_MASK);
+
+ /*
+ * Clear the I-side bits from the captured CESR value so that we
+ * don't accidentally clear any new I-side errors when we do
+ * the CESR write-clear operation.
+ */
+ cesr &= ~CESR_I_MASK;
+ }
+
+ if (cesr & (CESR_DCTPE | CESR_DCDPE | CESR_DCTE)) {
+ d_cesynr = read_cesynr();
+ pr_alert("D-side CESYNR = 0x%08x\n", d_cesynr);
+ }
+
+ /* Clear the interrupt bits we processed */
+ write_cesr(cesr);
+
+ ERP_L1_ERR("L1 cache / TLB error detected");
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t msm_l2_erp_irq(int irq, void *dev_id)
+{
+ unsigned int l2esr;
+ unsigned int l2esynr0;
+ unsigned int l2esynr1;
+ unsigned int l2ear0;
+ unsigned int l2ear1;
+ int soft_error = 0;
+ int port_error = 0;
+ int unrecoverable = 0;
+
+ l2esr = get_l2_indirect_reg(L2ESR_IND_ADDR);
+ l2esynr0 = get_l2_indirect_reg(L2ESYNR0_IND_ADDR);
+ l2esynr1 = get_l2_indirect_reg(L2ESYNR1_IND_ADDR);
+ l2ear0 = get_l2_indirect_reg(L2EAR0_IND_ADDR);
+ l2ear1 = get_l2_indirect_reg(L2EAR1_IND_ADDR);
+
+ pr_alert("L2 Error detected!\n");
+ pr_alert("\tL2ESR = 0x%08x\n", l2esr);
+ pr_alert("\tL2ESYNR0 = 0x%08x\n", l2esynr0);
+ pr_alert("\tL2ESYNR1 = 0x%08x\n", l2esynr1);
+ pr_alert("\tL2EAR0 = 0x%08x\n", l2ear0);
+ pr_alert("\tL2EAR1 = 0x%08x\n", l2ear1);
+ pr_alert("\tCPU bitmap = 0x%x\n", (l2esr >> L2ESR_CPU_SHIFT) &
+ L2ESR_CPU_MASK);
+
+ if (l2esr & L2ESR_MPDCD) {
+ pr_alert("L2 master port decode error\n");
+ port_error++;
+ msm_l2_erp_stats.mpdcd++;
+ }
+
+ if (l2esr & L2ESR_MPSLV) {
+ pr_alert("L2 master port slave error\n");
+ port_error++;
+ msm_l2_erp_stats.mpslv++;
+ }
+
+ if (l2esr & L2ESR_TSESB) {
+ pr_alert("L2 tag soft error, single-bit\n");
+ soft_error++;
+ msm_l2_erp_stats.tsesb++;
+ }
+
+ if (l2esr & L2ESR_TSEDB) {
+ pr_alert("L2 tag soft error, double-bit\n");
+ soft_error++;
+ unrecoverable++;
+ msm_l2_erp_stats.tsedb++;
+ }
+
+ if (l2esr & L2ESR_DSESB) {
+ pr_alert("L2 data soft error, single-bit\n");
+ soft_error++;
+ msm_l2_erp_stats.dsesb++;
+ }
+
+ if (l2esr & L2ESR_DSEDB) {
+ pr_alert("L2 data soft error, double-bit\n");
+ soft_error++;
+ unrecoverable++;
+ msm_l2_erp_stats.dsedb++;
+ }
+
+ if (l2esr & L2ESR_MSE) {
+ pr_alert("L2 modified soft error\n");
+ soft_error++;
+ msm_l2_erp_stats.mse++;
+ }
+
+ if (l2esr & L2ESR_MPLDREXNOK) {
+ pr_alert("L2 master port LDREX received Normal OK response\n");
+ port_error++;
+ msm_l2_erp_stats.mplxrexnok++;
+ }
+
+ if (port_error)
+ ERP_PORT_ERR("L2 master port error detected");
+
+ if (soft_error && !unrecoverable)
+ ERP_1BIT_ERR("L2 single-bit error detected");
+
+ if (unrecoverable)
+ ERP_2BIT_ERR("L2 double-bit error detected, trouble ahead");
+
+ set_l2_indirect_reg(L2ESR_IND_ADDR, l2esr);
+ return IRQ_HANDLED;
+}
+
+static void enable_erp_irq_callback(void *info)
+{
+ enable_percpu_irq(l1_erp_irq, IRQ_TYPE_LEVEL_HIGH);
+}
+
+static void disable_erp_irq_callback(void *info)
+{
+ disable_percpu_irq(l1_erp_irq);
+}
+
+static int cache_erp_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_STARTING:
+ enable_erp_irq_callback(NULL);
+ break;
+
+ case CPU_DYING:
+ disable_erp_irq_callback(NULL);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block cache_erp_cpu_notifier = {
+ .notifier_call = cache_erp_cpu_callback,
+};
+
+static int msm_cache_erp_probe(struct platform_device *pdev)
+{
+ struct resource *r;
+ int ret, cpu;
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "l1_irq");
+
+ if (!r) {
+ pr_err("Could not get L1 resource\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ l1_erp_irq = r->start;
+
+ ret = request_percpu_irq(l1_erp_irq, msm_l1_erp_irq, "MSM_L1",
+ &msm_l1_erp_stats);
+
+ if (ret) {
+ pr_err("Failed to request the L1 cache error interrupt\n");
+ goto fail;
+ }
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "l2_irq");
+
+ if (!r) {
+ pr_err("Could not get L2 resource\n");
+ ret = -ENODEV;
+ goto fail_l1;
+ }
+
+ l2_erp_irq = r->start;
+ ret = request_irq(l2_erp_irq, msm_l2_erp_irq, 0, "MSM_L2", NULL);
+
+ if (ret) {
+ pr_err("Failed to request the L2 cache error interrupt\n");
+ goto fail_l1;
+ }
+
+ procfs_entry = create_proc_entry("cpu/msm_cache_erp", S_IRUGO, NULL);
+
+ if (!procfs_entry) {
+ pr_err("Failed to create procfs node for cache error reporting\n");
+ ret = -ENODEV;
+ goto fail_l2;
+ }
+
+ get_online_cpus();
+ register_hotcpu_notifier(&cache_erp_cpu_notifier);
+ for_each_cpu(cpu, cpu_online_mask)
+ smp_call_function_single(cpu, enable_erp_irq_callback, NULL, 1);
+ put_online_cpus();
+
+ procfs_entry->read_proc = proc_read_status;
+ return 0;
+
+fail_l2:
+ free_irq(l2_erp_irq, NULL);
+fail_l1:
+ free_percpu_irq(l1_erp_irq, NULL);
+fail:
+ return ret;
+}
+
+static int msm_cache_erp_remove(struct platform_device *pdev)
+{
+ int cpu;
+ if (procfs_entry)
+ remove_proc_entry("cpu/msm_cache_erp", NULL);
+
+ get_online_cpus();
+ unregister_hotcpu_notifier(&cache_erp_cpu_notifier);
+ for_each_cpu(cpu, cpu_online_mask)
+ smp_call_function_single(cpu, disable_erp_irq_callback, NULL,
+ 1);
+ put_online_cpus();
+
+ free_percpu_irq(l1_erp_irq, NULL);
+
+ disable_irq(l2_erp_irq);
+ free_irq(l2_erp_irq, NULL);
+ return 0;
+}
+
+static struct platform_driver msm_cache_erp_driver = {
+ .probe = msm_cache_erp_probe,
+ .remove = msm_cache_erp_remove,
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_cache_erp_init(void)
+{
+ return platform_driver_register(&msm_cache_erp_driver);
+}
+
+static void __exit msm_cache_erp_exit(void)
+{
+ platform_driver_unregister(&msm_cache_erp_driver);
+}
+
+
+module_init(msm_cache_erp_init);
+module_exit(msm_cache_erp_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM cache error reporting driver");
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 8d040fe..24a676f 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -234,6 +234,7 @@
.rate = 19200000,
.ops = &clk_ops_tcxo,
CLK_INIT(tcxo_clk.c),
+ .warned = true,
},
};
@@ -259,6 +260,7 @@
.rate = 24576000,
.ops = &clk_ops_lpxo,
CLK_INIT(lpxo_clk.c),
+ .warned = true,
},
};
@@ -272,6 +274,7 @@
.rate = 768000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll1_clk.c),
+ .warned = true,
},
};
@@ -285,6 +288,7 @@
.rate = 806400000, /* TODO: Support scaling */
.ops = &clk_ops_pll_vote,
CLK_INIT(pll2_clk.c),
+ .warned = true,
},
};
@@ -311,6 +315,7 @@
.rate = 891000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll4_clk.c),
+ .warned = true,
},
};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 38ea570..98a32c6 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -26,7 +26,6 @@
#include <mach/msm_iomap.h>
#include <mach/clk.h>
#include <mach/rpm-regulator.h>
-#include <mach/msm_xo.h>
#include <mach/socinfo.h>
#include "clock-local.h"
@@ -468,57 +467,8 @@
* Clock Descriptions
*/
-static struct msm_xo_voter *xo_pxo, *xo_cxo;
-
-static int pxo_clk_enable(struct clk *clk)
-{
- return msm_xo_mode_vote(xo_pxo, MSM_XO_MODE_ON);
-}
-
-static void pxo_clk_disable(struct clk *clk)
-{
- msm_xo_mode_vote(xo_pxo, MSM_XO_MODE_OFF);
-}
-
-static struct clk_ops clk_ops_pxo = {
- .enable = pxo_clk_enable,
- .disable = pxo_clk_disable,
- .is_local = local_clk_is_local,
-};
-
-static struct fixed_clk pxo_clk = {
- .c = {
- .dbg_name = "pxo_clk",
- .rate = 27000000,
- .ops = &clk_ops_pxo,
- CLK_INIT(pxo_clk.c),
- },
-};
-
-static int cxo_clk_enable(struct clk *clk)
-{
- return msm_xo_mode_vote(xo_cxo, MSM_XO_MODE_ON);
-}
-
-static void cxo_clk_disable(struct clk *clk)
-{
- msm_xo_mode_vote(xo_cxo, MSM_XO_MODE_OFF);
-}
-
-static struct clk_ops clk_ops_cxo = {
- .enable = cxo_clk_enable,
- .disable = cxo_clk_disable,
- .is_local = local_clk_is_local,
-};
-
-static struct fixed_clk cxo_clk = {
- .c = {
- .dbg_name = "cxo_clk",
- .rate = 19200000,
- .ops = &clk_ops_cxo,
- CLK_INIT(cxo_clk.c),
- },
-};
+DEFINE_CLK_RPM_BRANCH(pxo_clk, pxo_a_clk, PXO, 27000000);
+DEFINE_CLK_RPM_BRANCH(cxo_clk, cxo_a_clk, CXO, 19200000);
static struct pll_clk pll2_clk = {
.mode_reg = MM_PLL1_MODE_REG,
@@ -528,6 +478,7 @@
.rate = 800000000,
.ops = &clk_ops_pll,
CLK_INIT(pll2_clk.c),
+ .warned = true,
},
};
@@ -541,6 +492,7 @@
.vdd_class = &vdd_sr2_pll,
.fmax[VDD_SR2_PLL_ON] = ULONG_MAX,
CLK_INIT(pll3_clk.c),
+ .warned = true,
},
};
@@ -554,6 +506,7 @@
.rate = 393216000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll4_clk.c),
+ .warned = true,
},
};
@@ -567,6 +520,7 @@
.rate = 384000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll8_clk.c),
+ .warned = true,
},
};
@@ -580,6 +534,7 @@
.rate = 480000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll14_clk.c),
+ .warned = true,
},
};
@@ -591,6 +546,7 @@
.rate = 975000000,
.ops = &clk_ops_pll,
CLK_INIT(pll15_clk.c),
+ .warned = true,
},
};
@@ -4896,6 +4852,8 @@
};
static struct clk_lookup msm_clocks_8064[] = {
+ CLK_LOOKUP("xo", cxo_a_clk.c, ""),
+ CLK_LOOKUP("xo", pxo_a_clk.c, ""),
CLK_LOOKUP("xo", cxo_clk.c, "msm_otg"),
CLK_LOOKUP("cxo", cxo_clk.c, "wcnss_wlan.0"),
CLK_LOOKUP("cxo", cxo_clk.c, "pil_riva"),
@@ -5175,6 +5133,8 @@
};
static struct clk_lookup msm_clocks_8960[] = {
+ CLK_LOOKUP("xo", cxo_a_clk.c, ""),
+ CLK_LOOKUP("xo", pxo_a_clk.c, ""),
CLK_LOOKUP("xo", cxo_clk.c, "msm_otg"),
CLK_LOOKUP("cxo", cxo_clk.c, "wcnss_wlan.0"),
CLK_LOOKUP("cxo", cxo_clk.c, "pil_riva"),
@@ -5693,6 +5653,8 @@
/* Local clock driver initialization. */
static void __init msm8960_clock_init(void)
{
+ /* Keep PXO on whenever APPS cpu is active */
+ clk_prepare_enable(&pxo_a_clk.c);
if (cpu_is_apq8064()) {
vdd_sr2_pll.set_vdd = set_vdd_sr2_pll_8064;
@@ -5701,17 +5663,6 @@
vdd_sr2_pll.set_vdd = set_vdd_sr2_pll_8930;
}
- xo_pxo = msm_xo_get(MSM_XO_PXO, "clock-8960");
- if (IS_ERR(xo_pxo)) {
- pr_err("%s: msm_xo_get(PXO) failed.\n", __func__);
- BUG();
- }
- xo_cxo = msm_xo_get(MSM_XO_CXO, "clock-8960");
- if (IS_ERR(xo_cxo)) {
- pr_err("%s: msm_xo_get(CXO) failed.\n", __func__);
- BUG();
- }
-
/*
* Change the freq tables for and voltage requirements for
* clocks which differ between 8960 and 8064.
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 4fa81b6..4da4454 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -24,7 +24,6 @@
#include <mach/msm_iomap.h>
#include <mach/clk.h>
-#include <mach/msm_xo.h>
#include <mach/scm-io.h>
#include <mach/rpm.h>
#include <mach/rpm-regulator.h>
@@ -298,62 +297,8 @@
.fmax[VDD_DIG_##l2] = (f2), \
.fmax[VDD_DIG_##l3] = (f3)
-static struct msm_xo_voter *xo_pxo, *xo_cxo;
-
-static bool xo_clk_is_local(struct clk *clk)
-{
- return false;
-}
-
-static int pxo_clk_enable(struct clk *clk)
-{
- return msm_xo_mode_vote(xo_pxo, MSM_XO_MODE_ON);
-}
-
-static void pxo_clk_disable(struct clk *clk)
-{
- msm_xo_mode_vote(xo_pxo, MSM_XO_MODE_OFF);
-}
-
-static struct clk_ops clk_ops_pxo = {
- .enable = pxo_clk_enable,
- .disable = pxo_clk_disable,
- .is_local = xo_clk_is_local,
-};
-
-static struct fixed_clk pxo_clk = {
- .c = {
- .dbg_name = "pxo_clk",
- .rate = 27000000,
- .ops = &clk_ops_pxo,
- CLK_INIT(pxo_clk.c),
- },
-};
-
-static int cxo_clk_enable(struct clk *clk)
-{
- return msm_xo_mode_vote(xo_cxo, MSM_XO_MODE_ON);
-}
-
-static void cxo_clk_disable(struct clk *clk)
-{
- msm_xo_mode_vote(xo_cxo, MSM_XO_MODE_OFF);
-}
-
-static struct clk_ops clk_ops_cxo = {
- .enable = cxo_clk_enable,
- .disable = cxo_clk_disable,
- .is_local = xo_clk_is_local,
-};
-
-static struct fixed_clk cxo_clk = {
- .c = {
- .dbg_name = "cxo_clk",
- .rate = 19200000,
- .ops = &clk_ops_cxo,
- CLK_INIT(cxo_clk.c),
- },
-};
+DEFINE_CLK_RPM_BRANCH(pxo_clk, pxo_a_clk, PXO, 27000000);
+DEFINE_CLK_RPM_BRANCH(cxo_clk, cxo_a_clk, CXO, 19200000);
static struct pll_vote_clk pll8_clk = {
.en_reg = BB_PLL_ENA_SC0_REG,
@@ -365,6 +310,7 @@
.rate = 384000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll8_clk.c),
+ .warned = true,
},
};
@@ -376,6 +322,7 @@
.rate = 800000000,
.ops = &clk_ops_pll,
CLK_INIT(pll2_clk.c),
+ .warned = true,
},
};
@@ -387,6 +334,7 @@
.rate = 0, /* TODO: Detect rate dynamically */
.ops = &clk_ops_pll,
CLK_INIT(pll3_clk.c),
+ .warned = true,
},
};
@@ -425,6 +373,7 @@
.rate = 540672000,
.ops = &clk_ops_pll4,
CLK_INIT(pll4_clk.c),
+ .warned = true,
},
};
@@ -3547,7 +3496,9 @@
};
static struct clk_lookup msm_clocks_8x60[] = {
- CLK_LOOKUP("cxo", cxo_clk.c, NULL),
+ CLK_LOOKUP("xo", cxo_clk.c, ""),
+ CLK_LOOKUP("xo", cxo_a_clk.c, ""),
+ CLK_LOOKUP("xo", pxo_a_clk.c, ""),
CLK_LOOKUP("xo", pxo_clk.c, "pil_modem"),
CLK_LOOKUP("pll4", pll4_clk.c, "pil_qdsp6v3"),
CLK_LOOKUP("measure", measure_clk.c, "debug"),
@@ -3888,18 +3839,9 @@
/* Local clock driver initialization. */
static void __init msm8660_clock_init(void)
{
- xo_pxo = msm_xo_get(MSM_XO_PXO, "clock-8x60");
- if (IS_ERR(xo_pxo)) {
- pr_err("%s: msm_xo_get(PXO) failed.\n", __func__);
- BUG();
- }
- xo_cxo = msm_xo_get(MSM_XO_CXO, "clock-8x60");
- if (IS_ERR(xo_cxo)) {
- pr_err("%s: msm_xo_get(CXO) failed.\n", __func__);
- BUG();
- }
-
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ /* Keep PXO on whenever APPS cpu is active */
+ clk_prepare_enable(&pxo_a_clk.c);
/* Initialize clock registers. */
reg_init();
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index ca14afa..3e059b6 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -25,7 +25,6 @@
#include <mach/msm_iomap.h>
#include <mach/clk.h>
-#include <mach/msm_xo.h>
#include <mach/rpm-9615.h>
#include <mach/rpm-regulator.h>
@@ -208,32 +207,7 @@
* Clock Descriptions
*/
-static struct msm_xo_voter *xo_cxo;
-
-static int cxo_clk_enable(struct clk *clk)
-{
- return msm_xo_mode_vote(xo_cxo, MSM_XO_MODE_ON);
-}
-
-static void cxo_clk_disable(struct clk *clk)
-{
- msm_xo_mode_vote(xo_cxo, MSM_XO_MODE_OFF);
-}
-
-static struct clk_ops clk_ops_cxo = {
- .enable = cxo_clk_enable,
- .disable = cxo_clk_disable,
- .is_local = local_clk_is_local,
-};
-
-static struct fixed_clk cxo_clk = {
- .c = {
- .dbg_name = "cxo_clk",
- .rate = 19200000,
- .ops = &clk_ops_cxo,
- CLK_INIT(cxo_clk.c),
- },
-};
+DEFINE_CLK_RPM_BRANCH(cxo_clk, cxo_a_clk, CXO, 19200000);
static DEFINE_SPINLOCK(soft_vote_lock);
@@ -294,6 +268,7 @@
.rate = 276000000,
.ops = &clk_ops_pll_acpu_vote,
CLK_INIT(pll0_clk.c),
+ .warned = true,
},
};
@@ -308,6 +283,7 @@
.rate = 276000000,
.ops = &clk_ops_pll_acpu_vote,
CLK_INIT(pll0_acpu_clk.c),
+ .warned = true,
},
};
@@ -321,6 +297,7 @@
.rate = 393216000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll4_clk.c),
+ .warned = true,
},
};
@@ -338,6 +315,7 @@
.rate = 384000000,
.ops = &clk_ops_pll_acpu_vote,
CLK_INIT(pll8_clk.c),
+ .warned = true,
},
};
@@ -352,6 +330,7 @@
.rate = 384000000,
.ops = &clk_ops_pll_acpu_vote,
CLK_INIT(pll8_acpu_clk.c),
+ .warned = true,
},
};
@@ -362,6 +341,7 @@
.rate = 440000000,
.ops = &clk_ops_pll,
CLK_INIT(pll9_acpu_clk.c),
+ .warned = true,
},
};
@@ -375,6 +355,7 @@
.rate = 480000000,
.ops = &clk_ops_pll_vote,
CLK_INIT(pll14_clk.c),
+ .warned = true,
},
};
@@ -1380,12 +1361,7 @@
static DEFINE_CLK_VOTER(dfab_sps_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
-
-/*
- * TODO: replace dummy_clk below with ebi1_clk.c once the
- * bus driver starts voting on ebi1 rates.
- */
-static DEFINE_CLK_VOTER(ebi1_adm_clk, &dummy_clk);
+static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c);
#ifdef CONFIG_DEBUG_FS
struct measure_sel {
@@ -1623,6 +1599,7 @@
};
static struct clk_lookup msm_clocks_9615[] = {
+ CLK_LOOKUP("xo", cxo_a_clk.c, ""),
CLK_LOOKUP("xo", cxo_clk.c, "msm_otg"),
CLK_LOOKUP("xo", cxo_clk.c, "BAM_RMNT"),
CLK_LOOKUP("pll0", pll0_clk.c, NULL),
@@ -1733,11 +1710,6 @@
CLK_LOOKUP("q6sw_clk", q6sw_clk, NULL),
CLK_LOOKUP("q6fw_clk", q6fw_clk, NULL),
CLK_LOOKUP("q6_func_clk", q6_func_clk, NULL),
-
- /* TODO: Make this real when RPM's ready. */
- CLK_DUMMY("ebi1_msmbus_clk", ebi1_msmbus_clk.c, NULL, OFF),
- CLK_DUMMY("mem_clk", ebi1_adm_clk.c, "msm_dmov", OFF),
-
};
static void set_fsm_mode(void __iomem *mode_reg)
@@ -1861,13 +1833,9 @@
/* Local clock driver initialization. */
static void __init msm9615_clock_init(void)
{
- xo_cxo = msm_xo_get(MSM_XO_CXO, "clock-9615");
- if (IS_ERR(xo_cxo)) {
- pr_err("%s: msm_xo_get(CXO) failed.\n", __func__);
- BUG();
- }
-
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ /* Keep CXO on whenever APPS cpu is active */
+ clk_prepare_enable(&cxo_a_clk.c);
clk_ops_pll.enable = sr_pll_clk_enable;
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 411a272..31be6af 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -1,6 +1,6 @@
/*
* 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
@@ -92,9 +92,9 @@
int rc = 0;
if (val)
- rc = clk_enable(clock);
+ rc = clk_prepare_enable(clock);
else
- clk_disable(clock);
+ clk_disable_unprepare(clock);
return rc;
}
diff --git a/arch/arm/mach-msm/clock-pcom-lookup.c b/arch/arm/mach-msm/clock-pcom-lookup.c
index c20b7e4..a0defe3 100644
--- a/arch/arm/mach-msm/clock-pcom-lookup.c
+++ b/arch/arm/mach-msm/clock-pcom-lookup.c
@@ -317,6 +317,11 @@
CLK_LOOKUP("ahb_m_clk", ahb_m_clk.c, NULL),
CLK_LOOKUP("ahb_s_clk", ahb_s_clk.c, NULL),
CLK_LOOKUP("cam_m_clk", cam_m_clk.c, NULL),
+ CLK_LOOKUP("cam_clk", cam_m_clk.c, "0-0036"),
+ CLK_LOOKUP("cam_clk", cam_m_clk.c, "0-001b"),
+ CLK_LOOKUP("cam_clk", cam_m_clk.c, "0-0010"),
+ CLK_LOOKUP("cam_clk", cam_m_clk.c, "0-0078"),
+ CLK_LOOKUP("cam_clk", cam_m_clk.c, "0-006c"),
CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_camera_ov9726.0"),
CLK_LOOKUP("csi_pclk", csi0_p_clk.c, "msm_camera_ov9726.0"),
CLK_LOOKUP("csi_vfe_clk", csi0_vfe_clk.c, "msm_camera_ov9726.0"),
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index f6b2b45..b5b6ca7 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -38,6 +38,7 @@
{50, 960000000},
{52, 1008000000},
{62, 1200000000},
+ {63, 1209600000},
{0, 0},
};
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index 2f4a17c..b0d5693 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -67,36 +67,38 @@
}, \
};
-#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, rate) \
+#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
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), \
+ .last_set_khz = ((r) / 1000), \
+ .last_set_sleep_khz = ((r) / 1000), \
.branch = true, \
.c = { \
.ops = &clk_ops_rpm_branch, \
.flags = CLKFLAG_SKIP_AUTO_OFF, \
.dbg_name = #name, \
- .rate = (rate), \
+ .rate = (r), \
CLK_INIT(name.c), \
+ .warned = true, \
}, \
}; \
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), \
+ .last_set_khz = ((r) / 1000), \
.active_only = true, \
.branch = true, \
.c = { \
.ops = &clk_ops_rpm_branch, \
.flags = CLKFLAG_SKIP_AUTO_OFF, \
.dbg_name = #active, \
- .rate = (rate), \
+ .rate = (r), \
CLK_INIT(active.c), \
+ .warned = true, \
}, \
};
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 5b89fa9..7f0cafd 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -127,6 +127,41 @@
unvote_vdd_level(clk->vdd_class, level);
}
+int clk_prepare(struct clk *clk)
+{
+ int ret = 0;
+ struct clk *parent;
+ if (!clk)
+ return 0;
+
+ mutex_lock(&clk->prepare_lock);
+ if (clk->prepare_count == 0) {
+ parent = clk_get_parent(clk);
+
+ ret = clk_prepare(parent);
+ if (ret)
+ goto out;
+ ret = clk_prepare(clk->depends);
+ if (ret)
+ goto err_prepare_depends;
+
+ if (clk->ops->prepare)
+ ret = clk->ops->prepare(clk);
+ if (ret)
+ goto err_prepare_clock;
+ }
+ clk->prepare_count++;
+out:
+ mutex_unlock(&clk->prepare_lock);
+ return ret;
+err_prepare_clock:
+ clk_unprepare(clk->depends);
+err_prepare_depends:
+ clk_unprepare(parent);
+ goto out;
+}
+EXPORT_SYMBOL(clk_prepare);
+
/*
* Standard clock functions defined in include/linux/clk.h
*/
@@ -140,6 +175,10 @@
return 0;
spin_lock_irqsave(&clk->lock, flags);
+ if (WARN(!clk->warned && !clk->prepare_count,
+ "%s: Don't call enable on unprepared clocks\n",
+ clk->dbg_name))
+ clk->warned = true;
if (clk->count == 0) {
parent = clk_get_parent(clk);
@@ -193,6 +232,11 @@
return;
spin_lock_irqsave(&clk->lock, flags);
+ if (WARN(!clk->warned && !clk->prepare_count,
+ "%s: Never called prepare or calling disable "
+ "after unprepare\n",
+ clk->dbg_name))
+ clk->warned = true;
if (WARN(clk->count == 0, "%s is unbalanced", clk->dbg_name))
goto out;
if (clk->count == 1) {
@@ -210,6 +254,37 @@
}
EXPORT_SYMBOL(clk_disable);
+void clk_unprepare(struct clk *clk)
+{
+ if (!clk)
+ return;
+
+ mutex_lock(&clk->prepare_lock);
+ if (!clk->prepare_count) {
+ if (WARN(!clk->warned, "%s is unbalanced (prepare)",
+ clk->dbg_name))
+ clk->warned = true;
+ goto out;
+ }
+ if (clk->prepare_count == 1) {
+ struct clk *parent = clk_get_parent(clk);
+
+ if (WARN(!clk->warned && clk->count,
+ "%s: Don't call unprepare when the clock is enabled\n",
+ clk->dbg_name))
+ clk->warned = true;
+
+ if (clk->ops->unprepare)
+ clk->ops->unprepare(clk);
+ clk_unprepare(clk->depends);
+ clk_unprepare(parent);
+ }
+ clk->prepare_count--;
+out:
+ mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL(clk_unprepare);
+
int clk_reset(struct clk *clk, enum clk_reset_action action)
{
if (!clk->ops->reset)
@@ -335,7 +410,7 @@
if (clk->ops->handoff && !(clk->flags & CLKFLAG_HANDOFF_RATE)) {
if (clk->ops->handoff(clk)) {
clk->flags |= CLKFLAG_HANDOFF_RATE;
- clk_enable(clk);
+ clk_prepare_enable(clk);
}
}
}
@@ -372,11 +447,11 @@
}
spin_unlock_irqrestore(&clk->lock, flags);
/*
- * Calling clk_disable() outside the lock is safe since
+ * Calling this outside the lock is safe since
* it doesn't need to be atomic with the flag change.
*/
if (handoff)
- clk_disable(clk);
+ clk_disable_unprepare(clk);
}
}
pr_info("clock_late_init() disabled %d unused clocks\n", count);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 4210bd9..bce2e0f 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/clkdev.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <mach/clk.h>
@@ -63,8 +64,10 @@
}
struct clk_ops {
+ int (*prepare)(struct clk *clk);
int (*enable)(struct clk *clk);
void (*disable)(struct clk *clk);
+ void (*unprepare)(struct clk *clk);
void (*auto_off)(struct clk *clk);
void (*enable_hwcg)(struct clk *clk);
void (*disable_hwcg)(struct clk *clk);
@@ -85,11 +88,14 @@
/**
* struct clk
+ * @prepare_count: prepare refcount
+ * @prepare_lock: protects clk_prepare()/clk_unprepare() path and @prepare_count
* @count: enable refcount
* @lock: protects clk_enable()/clk_disable() path and @count
* @depends: non-direct parent of clock to enable when this clock is enabled
* @vdd_class: voltage scaling requirement class
* @fmax: maximum frequency in Hz supported at each voltage level
+ * @warned: true if the clock has warned of incorrect usage, false otherwise
*/
struct clk {
uint32_t flags;
@@ -103,12 +109,16 @@
struct list_head children;
struct list_head siblings;
+ bool warned;
unsigned count;
spinlock_t lock;
+ unsigned prepare_count;
+ struct mutex prepare_lock;
};
#define CLK_INIT(name) \
.lock = __SPIN_LOCK_UNLOCKED((name).lock), \
+ .prepare_lock = __MUTEX_INITIALIZER((name).prepare_lock), \
.children = LIST_HEAD_INIT((name).children), \
.siblings = LIST_HEAD_INIT((name).siblings)
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 657751b..6a3a10c 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -636,6 +636,12 @@
.name = "peripheral_status_irq",
.flags = IORESOURCE_IRQ,
},
+ {
+ .start = MSM_GPIO_TO_INT(88),
+ .end = MSM_GPIO_TO_INT(88),
+ .name = "wakeup_irq",
+ .flags = IORESOURCE_IRQ,
+ },
};
static u64 dma_mask = DMA_BIT_MASK(32);
@@ -1386,9 +1392,14 @@
},
};
+static struct smd_subsystem_restart_config smd_ssr_config = {
+ .disable_smsm_reset_handshake = 1,
+};
+
static struct smd_platform smd_platform_data = {
.num_ss_configs = ARRAY_SIZE(smd_config_list),
.smd_ss_configs = smd_config_list,
+ .smd_ssr_config = &smd_ssr_config,
};
struct platform_device msm_device_smd_apq8064 = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 718cfb1..4c02215 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1090,9 +1090,14 @@
},
};
+static struct smd_subsystem_restart_config smd_ssr_config = {
+ .disable_smsm_reset_handshake = 1,
+};
+
static struct smd_platform smd_platform_data = {
.num_ss_configs = ARRAY_SIZE(smd_config_list),
.smd_ss_configs = smd_config_list,
+ .smd_ssr_config = &smd_ssr_config,
};
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 18acb36..0b204a0 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -921,6 +921,7 @@
[16] = MSM_GPIO_TO_INT(15),
[19] = MSM_GPIO_TO_INT(26),
[20] = MSM_GPIO_TO_INT(28),
+ [22] = USB_HSIC_IRQ,
[23] = MSM_GPIO_TO_INT(19),
[24] = MSM_GPIO_TO_INT(23),
[26] = MSM_GPIO_TO_INT(3),
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 3d2d2e7..057a006 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.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
@@ -391,6 +391,7 @@
.id = 0,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &jpegd_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
.resource = msm_iommu_jpegd_resources,
@@ -401,6 +402,7 @@
.id = 1,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &vpe_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
.resource = msm_iommu_vpe_resources,
@@ -411,6 +413,7 @@
.id = 2,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &mdp0_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
.resource = msm_iommu_mdp0_resources,
@@ -421,6 +424,7 @@
.id = 3,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &mdp1_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
.resource = msm_iommu_mdp1_resources,
@@ -431,6 +435,7 @@
.id = 4,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &rot_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
.resource = msm_iommu_rot_resources,
@@ -441,6 +446,7 @@
.id = 5,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &ijpeg_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
.resource = msm_iommu_ijpeg_resources,
@@ -451,6 +457,7 @@
.id = 6,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &vfe_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
.resource = msm_iommu_vfe_resources,
@@ -461,6 +468,7 @@
.id = 7,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &vcodec_a_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
.resource = msm_iommu_vcodec_a_resources,
@@ -471,6 +479,7 @@
.id = 8,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &vcodec_b_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
.resource = msm_iommu_vcodec_b_resources,
@@ -481,6 +490,7 @@
.id = 9,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &gfx3d_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
.resource = msm_iommu_gfx3d_resources,
@@ -491,6 +501,7 @@
.id = 10,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &gfx3d1_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_gfx3d1_resources),
.resource = msm_iommu_gfx3d1_resources,
@@ -501,6 +512,7 @@
.id = 10,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &gfx2d0_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
.resource = msm_iommu_gfx2d0_resources,
@@ -511,6 +523,7 @@
.id = 11,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &gfx2d1_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources),
.resource = msm_iommu_gfx2d1_resources,
@@ -521,6 +534,7 @@
.id = 11,
.dev = {
.parent = &msm_root_iommu_dev.dev,
+ .platform_data = &vcap_iommu,
},
.num_resources = ARRAY_SIZE(msm_iommu_vcap_resources),
.resource = msm_iommu_vcap_resources,
@@ -683,6 +697,7 @@
.id = 0,
.dev = {
.parent = &msm_device_iommu_jpegd.dev,
+ .platform_data = &jpegd_src_ctx,
},
};
@@ -691,6 +706,7 @@
.id = 1,
.dev = {
.parent = &msm_device_iommu_jpegd.dev,
+ .platform_data = &jpegd_dst_ctx,
},
};
@@ -699,6 +715,7 @@
.id = 2,
.dev = {
.parent = &msm_device_iommu_vpe.dev,
+ .platform_data = &vpe_src_ctx,
},
};
@@ -707,6 +724,7 @@
.id = 3,
.dev = {
.parent = &msm_device_iommu_vpe.dev,
+ .platform_data = &vpe_dst_ctx,
},
};
@@ -715,6 +733,7 @@
.id = 4,
.dev = {
.parent = &msm_device_iommu_mdp0.dev,
+ .platform_data = &mdp_vg1_ctx,
},
};
@@ -723,6 +742,7 @@
.id = 5,
.dev = {
.parent = &msm_device_iommu_mdp0.dev,
+ .platform_data = &mdp_rgb1_ctx,
},
};
@@ -731,6 +751,7 @@
.id = 6,
.dev = {
.parent = &msm_device_iommu_mdp1.dev,
+ .platform_data = &mdp_vg2_ctx,
},
};
@@ -739,6 +760,7 @@
.id = 7,
.dev = {
.parent = &msm_device_iommu_mdp1.dev,
+ .platform_data = &mdp_rgb2_ctx,
},
};
@@ -747,6 +769,7 @@
.id = 8,
.dev = {
.parent = &msm_device_iommu_rot.dev,
+ .platform_data = &rot_src_ctx,
},
};
@@ -755,6 +778,7 @@
.id = 9,
.dev = {
.parent = &msm_device_iommu_rot.dev,
+ .platform_data = &rot_dst_ctx,
},
};
@@ -763,6 +787,7 @@
.id = 10,
.dev = {
.parent = &msm_device_iommu_ijpeg.dev,
+ .platform_data = &ijpeg_src_ctx,
},
};
@@ -771,6 +796,7 @@
.id = 11,
.dev = {
.parent = &msm_device_iommu_ijpeg.dev,
+ .platform_data = &ijpeg_dst_ctx,
},
};
@@ -779,6 +805,7 @@
.id = 12,
.dev = {
.parent = &msm_device_iommu_vfe.dev,
+ .platform_data = &vfe_imgwr_ctx,
},
};
@@ -787,6 +814,7 @@
.id = 13,
.dev = {
.parent = &msm_device_iommu_vfe.dev,
+ .platform_data = &vfe_misc_ctx,
},
};
@@ -795,6 +823,7 @@
.id = 14,
.dev = {
.parent = &msm_device_iommu_vcodec_a.dev,
+ .platform_data = &vcodec_a_stream_ctx,
},
};
@@ -803,6 +832,7 @@
.id = 15,
.dev = {
.parent = &msm_device_iommu_vcodec_a.dev,
+ .platform_data = &vcodec_a_mm1_ctx,
},
};
@@ -811,6 +841,7 @@
.id = 16,
.dev = {
.parent = &msm_device_iommu_vcodec_b.dev,
+ .platform_data = &vcodec_b_mm2_ctx,
},
};
@@ -819,6 +850,7 @@
.id = 17,
.dev = {
.parent = &msm_device_iommu_gfx3d.dev,
+ .platform_data = &gfx3d_user_ctx,
},
};
@@ -827,6 +859,7 @@
.id = 18,
.dev = {
.parent = &msm_device_iommu_gfx3d.dev,
+ .platform_data = &gfx3d_priv_ctx,
},
};
@@ -835,6 +868,7 @@
.id = 19,
.dev = {
.parent = &msm_device_iommu_gfx3d1.dev,
+ .platform_data = &gfx3d1_user_ctx,
},
};
@@ -843,6 +877,7 @@
.id = 20,
.dev = {
.parent = &msm_device_iommu_gfx3d1.dev,
+ .platform_data = &gfx3d1_priv_ctx,
},
};
@@ -851,6 +886,7 @@
.id = 19,
.dev = {
.parent = &msm_device_iommu_gfx2d0.dev,
+ .platform_data = &gfx2d0_2d0_ctx,
},
};
@@ -859,6 +895,7 @@
.id = 20,
.dev = {
.parent = &msm_device_iommu_gfx2d1.dev,
+ .platform_data = &gfx2d1_2d1_ctx,
},
};
@@ -867,6 +904,7 @@
.id = 21,
.dev = {
.parent = &msm_device_iommu_vcap.dev,
+ .platform_data = &vcap_vc_ctx,
},
};
@@ -875,11 +913,11 @@
.id = 22,
.dev = {
.parent = &msm_device_iommu_vcap.dev,
+ .platform_data = &vcap_vp_ctx,
},
};
static struct platform_device *msm_iommu_common_devs[] = {
- &msm_device_iommu_jpegd,
&msm_device_iommu_vpe,
&msm_device_iommu_mdp0,
&msm_device_iommu_mdp1,
@@ -901,32 +939,11 @@
&msm_device_iommu_vcap,
};
-static struct msm_iommu_dev *msm_iommu_common_data[] = {
- &jpegd_iommu,
- &vpe_iommu,
- &mdp0_iommu,
- &mdp1_iommu,
- &rot_iommu,
- &ijpeg_iommu,
- &vfe_iommu,
- &vcodec_a_iommu,
- &vcodec_b_iommu,
- &gfx3d_iommu,
-};
-
-static struct msm_iommu_dev *msm_iommu_gfx2d_data[] = {
- &gfx2d0_iommu,
- &gfx2d1_iommu,
-};
-
-static struct msm_iommu_dev *msm_iommu_8064_data[] = {
- &gfx3d1_iommu,
- &vcap_iommu,
+static struct platform_device *msm_iommu_jpegd_devs[] = {
+ &msm_device_iommu_jpegd,
};
static struct platform_device *msm_iommu_common_ctx_devs[] = {
- &msm_device_jpegd_src_ctx,
- &msm_device_jpegd_dst_ctx,
&msm_device_vpe_src_ctx,
&msm_device_vpe_dst_ctx,
&msm_device_mdp_vg1_ctx,
@@ -958,102 +975,11 @@
&msm_device_vcap_vp_ctx,
};
-static struct msm_iommu_ctx_dev *msm_iommu_common_ctx_data[] = {
- &jpegd_src_ctx,
- &jpegd_dst_ctx,
- &vpe_src_ctx,
- &vpe_dst_ctx,
- &mdp_vg1_ctx,
- &mdp_rgb1_ctx,
- &mdp_vg2_ctx,
- &mdp_rgb2_ctx,
- &rot_src_ctx,
- &rot_dst_ctx,
- &ijpeg_src_ctx,
- &ijpeg_dst_ctx,
- &vfe_imgwr_ctx,
- &vfe_misc_ctx,
- &vcodec_a_stream_ctx,
- &vcodec_a_mm1_ctx,
- &vcodec_b_mm2_ctx,
- &gfx3d_user_ctx,
- &gfx3d_priv_ctx,
+static struct platform_device *msm_iommu_jpegd_ctx_devs[] = {
+ &msm_device_jpegd_src_ctx,
+ &msm_device_jpegd_dst_ctx,
};
-static struct msm_iommu_ctx_dev *msm_iommu_gfx2d_ctx_data[] = {
- &gfx2d0_2d0_ctx,
- &gfx2d1_2d1_ctx,
-};
-
-static struct msm_iommu_ctx_dev *msm_iommu_8064_ctx_data[] = {
- &gfx3d1_user_ctx,
- &gfx3d1_priv_ctx,
- &vcap_vc_ctx,
- &vcap_vp_ctx,
-};
-
-static int iommu_init_devs(struct platform_device *devs[],
- struct msm_iommu_dev *data[], int size)
-{
- int ret, i;
-
- for (i = 0; i < size; i++) {
- ret = platform_device_add_data(devs[i],
- data[i], sizeof(struct msm_iommu_dev));
- if (ret != 0) {
- pr_err("platform_device_add_data failed, "
- "i = %d\n", i);
- goto failure_unwind;
- }
-
- ret = platform_device_register(devs[i]);
-
- if (ret != 0) {
- pr_err("platform_device_register iommu failed, "
- "i = %d\n", i);
- goto failure_unwind;
- }
- }
- return 0;
-
-failure_unwind:
- while (--i >= 0)
- platform_device_unregister(devs[i]);
-
- return ret;
-}
-
-
-static int iommu_init_ctx_devs(struct platform_device *ctx_devs[],
- struct msm_iommu_ctx_dev *ctx_data[], int size)
-{
- int ret, i;
-
- for (i = 0; i < size; i++) {
- ret = platform_device_add_data(ctx_devs[i],
- ctx_data[i], sizeof(struct msm_iommu_ctx_dev));
- if (ret != 0) {
- pr_err("platform_device_add_data iommu failed, "
- "i = %d\n", i);
- goto failure_unwind;
- }
-
- ret = platform_device_register(ctx_devs[i]);
- if (ret != 0) {
- pr_err("platform_device_register ctx failed, "
- "i = %d\n", i);
- goto failure_unwind;
- }
- }
- return 0;
-
-failure_unwind:
- while (--i >= 0)
- platform_device_unregister(ctx_devs[i]);
-
- return ret;
-}
-
static int __init iommu_init(void)
{
int ret;
@@ -1069,45 +995,55 @@
}
/* Initialize common devs */
- ret = iommu_init_devs(msm_iommu_common_devs,
- msm_iommu_common_data,
+ ret = platform_add_devices(msm_iommu_common_devs,
ARRAY_SIZE(msm_iommu_common_devs));
if (ret != 0)
goto failure2;
/* Initialize soc-specific devs */
if (cpu_is_apq8064()) {
- ret = iommu_init_devs(msm_iommu_8064_devs,
- msm_iommu_8064_data,
+ ret = platform_add_devices(msm_iommu_8064_devs,
ARRAY_SIZE(msm_iommu_8064_devs));
} else {
- ret = iommu_init_devs(msm_iommu_gfx2d_devs,
- msm_iommu_gfx2d_data,
- ARRAY_SIZE(msm_iommu_gfx2d_devs));
+ ret = platform_add_devices(msm_iommu_gfx2d_devs,
+ ARRAY_SIZE(msm_iommu_gfx2d_devs));
}
if (ret != 0)
goto failure2;
+ if (!cpu_is_msm8930()) {
+ ret = platform_add_devices(msm_iommu_jpegd_devs,
+ ARRAY_SIZE(msm_iommu_jpegd_devs));
+
+ if (ret != 0)
+ goto failure2;
+ }
+
/* Initialize common ctx_devs */
- ret = iommu_init_ctx_devs(msm_iommu_common_ctx_devs,
- msm_iommu_common_ctx_data,
+ ret = platform_add_devices(msm_iommu_common_ctx_devs,
ARRAY_SIZE(msm_iommu_common_ctx_devs));
if (ret != 0)
goto failure2;
/* Initialize soc-specific ctx_devs */
if (cpu_is_apq8064()) {
- ret = iommu_init_ctx_devs(msm_iommu_8064_ctx_devs,
- msm_iommu_8064_ctx_data,
+ ret = platform_add_devices(msm_iommu_8064_ctx_devs,
ARRAY_SIZE(msm_iommu_8064_ctx_devs));
} else {
- ret = iommu_init_ctx_devs(msm_iommu_gfx2d_ctx_devs,
- msm_iommu_gfx2d_ctx_data,
+ ret = platform_add_devices(msm_iommu_gfx2d_ctx_devs,
ARRAY_SIZE(msm_iommu_gfx2d_ctx_devs));
}
if (ret != 0)
goto failure2;
+ if (!cpu_is_msm8930()) {
+ ret = platform_add_devices(msm_iommu_jpegd_ctx_devs,
+ ARRAY_SIZE(msm_iommu_jpegd_ctx_devs));
+
+ if (ret != 0)
+ goto failure2;
+ }
+
return 0;
failure2:
@@ -1133,6 +1069,11 @@
platform_device_unregister(msm_iommu_gfx2d_ctx_devs[i]);
}
+ if (!cpu_is_msm8930()) {
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_ctx_devs); i++)
+ platform_device_unregister(msm_iommu_jpegd_ctx_devs[i]);
+ }
+
/* Common devs. */
for (i = 0; i < ARRAY_SIZE(msm_iommu_common_devs); ++i)
platform_device_unregister(msm_iommu_common_devs[i]);
@@ -1146,6 +1087,11 @@
platform_device_unregister(msm_iommu_gfx2d_devs[i]);
}
+ if (!cpu_is_msm8930()) {
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_devs); i++)
+ platform_device_unregister(msm_iommu_jpegd_devs[i]);
+ }
+
platform_device_unregister(&msm_root_iommu_dev);
}
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index ff11c7a..beb0c55 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -17,7 +17,6 @@
#include <linux/regulator/machine.h>
#include <linux/init.h>
#include <linux/irq.h>
-#include <linux/memblock.h>
#include <mach/irqs.h>
#include <mach/msm_iomap.h>
#include <mach/board.h>
@@ -799,9 +798,7 @@
kgsl_3d0_pdata.pwrlevel[0].bus_freq = 160000000;
kgsl_3d0_pdata.pwrlevel[1].gpu_freq = 96000000;
kgsl_3d0_pdata.pwrlevel[1].bus_freq = 0;
- } else if (cpu_is_msm8625())
- /* msm8625 has an idle_timout of 50 hours */
- kgsl_3d0_pdata.idle_timeout = 18000000;
+ }
}
static void __init msm_register_device(struct platform_device *pdev, void *data)
@@ -1534,6 +1531,36 @@
.size = ARRAY_SIZE(msm_clock_8625_dummy),
};
+enum {
+ MSM8625,
+ MSM8625A,
+};
+
+static int __init msm8625_cpu_id(void)
+{
+ int raw_id, cpu;
+
+ raw_id = socinfo_get_raw_id();
+ switch (raw_id) {
+ /* Part number for 1GHz part */
+ case 0x770:
+ case 0x771:
+ case 0x780:
+ cpu = MSM8625;
+ break;
+ /* Part number for 1.2GHz part */
+ case 0x773:
+ case 0x774:
+ case 0x781:
+ cpu = MSM8625A;
+ break;
+ default:
+ pr_err("Invalid Raw ID\n");
+ return -ENODEV;
+ }
+ return cpu;
+}
+
int __init msm7x2x_misc_init(void)
{
if (machine_is_msm8625_rumi3()) {
@@ -1542,10 +1569,16 @@
}
msm_clock_init(&msm7x27a_clock_init_data);
- if (cpu_is_msm7x27aa() || cpu_is_msm8625())
+ if (cpu_is_msm7x27aa())
acpuclk_init(&acpuclk_7x27aa_soc_data);
- else
+ else if (cpu_is_msm8625()) {
+ if (msm8625_cpu_id() == MSM8625)
+ acpuclk_init(&acpuclk_7x27aa_soc_data);
+ else if (msm8625_cpu_id() == MSM8625A)
+ acpuclk_init(&acpuclk_8625_soc_data);
+ } else {
acpuclk_init(&acpuclk_7x27a_soc_data);
+ }
return 0;
@@ -1591,32 +1624,8 @@
(void *)MSM_QGIC_CPU_BASE);
}
-static phys_addr_t msm8625_phys_base;
-
-static void __init msm_reserve_sdram_memblock(void)
-{
- phys_addr_t paddr;
-
- paddr = memblock_alloc(SZ_8, SZ_64K);
- pr_debug("%s physical address = %x\n", __func__, paddr);
-
- if (!paddr) {
- pr_err("%s: failed to reserve SZ_8 bytes\n", __func__);
- return;
- }
-
- msm8625_phys_base = paddr;
-}
-
-phys_addr_t msm8625_get_phys_base(void)
-{
- return msm8625_phys_base;
-}
-EXPORT_SYMBOL(msm8625_get_phys_base);
-
void __init msm8625_map_io(void)
{
- msm_reserve_sdram_memblock();
msm_map_msm8625_io();
if (socinfo_init() < 0)
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index 73b58e0..3c81ccf 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -31,5 +31,4 @@
void __init msm8625_map_io(void);
int ar600x_wlan_power(bool on);
void __init msm8x25_spm_device_init(void);
-phys_addr_t msm8625_get_phys_base(void);
#endif
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 4371c23..2eb716a 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -324,5 +324,6 @@
extern struct platform_device msm_bus_8064_cpss_fpb;
extern struct platform_device mdm_8064_device;
-
extern struct platform_device msm_dsps_device_8064;
+extern struct platform_device *msm_copper_stub_regulator_devices[];
+extern int msm_copper_stub_regulator_devices_len;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index a87a759..7fa4a07 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -200,6 +200,11 @@
uint8_t cam_gpio_req_tbl_size;
struct msm_gpio_set_tbl *cam_gpio_set_tbl;
uint8_t cam_gpio_set_tbl_size;
+ uint32_t gpio_no_mux;
+ uint32_t *camera_off_table;
+ uint8_t camera_off_table_size;
+ uint32_t *camera_on_table;
+ uint8_t camera_on_table_size;
};
enum msm_camera_i2c_mux_mode {
diff --git a/arch/arm/mach-msm/include/mach/irqs-8930.h b/arch/arm/mach-msm/include/mach/irqs-8930.h
index ed927bd..bfc32f6 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8930.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8930.h
@@ -152,10 +152,10 @@
#define SPS_MTI_2 (GIC_SPI_START + 109)
#define SPS_MTI_3 (GIC_SPI_START + 110)
#define GPS_PPS_OUT (GIC_SPI_START + 111)
-#define SPS_MTI_5 (GIC_SPI_START + 112)
-#define SPS_MTI_6 (GIC_SPI_START + 113)
-#define SPS_MTI_7 (GIC_SPI_START + 114)
-#define SPS_MTI_8 (GIC_SPI_START + 115)
+/* SPI IRQ 112 is unused */
+/* SPI IRQ 113 is unused */
+/* SPI IRQ 114 is unused */
+/* SPI IRQ 115 is unused */
#define TLMM_MSM_DIR_CONN_IRQ_11 (GIC_SPI_START + 116)
#define TLMM_MSM_DIR_CONN_IRQ_10 (GIC_SPI_START + 117)
#define BAM_DMA1 (GIC_SPI_START + 118)
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 48e3837..27965d3 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -93,6 +93,8 @@
0xFB600000 */
#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
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 183afed..d896013 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -123,9 +123,19 @@
};
+/*
+ * Subsystem Restart Configuration
+ *
+ * @disable_smsm_reset_handshake
+ */
+struct smd_subsystem_restart_config {
+ int disable_smsm_reset_handshake;
+};
+
struct smd_platform {
uint32_t num_ss_configs;
struct smd_subsystem_config *smd_ss_configs;
+ struct smd_subsystem_restart_config *smd_ssr_config;
};
#ifdef CONFIG_MSM_SMD
diff --git a/arch/arm/mach-msm/include/mach/msm_xo.h b/arch/arm/mach-msm/include/mach/msm_xo.h
index 7760647..f9795b4 100644
--- a/arch/arm/mach-msm/include/mach/msm_xo.h
+++ b/arch/arm/mach-msm/include/mach/msm_xo.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
@@ -19,8 +19,6 @@
MSM_XO_TCXO_A1,
MSM_XO_TCXO_A2,
MSM_XO_CORE,
- MSM_XO_PXO,
- MSM_XO_CXO,
NUM_MSM_XO_IDS
};
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 215fdb3..407c55a 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -68,6 +68,7 @@
enum msm_cpu socinfo_get_msm_cpu(void);
uint32_t socinfo_get_id(void);
uint32_t socinfo_get_version(void);
+uint32_t socinfo_get_raw_id(void);
char *socinfo_get_build_id(void);
uint32_t socinfo_get_platform_type(void);
uint32_t socinfo_get_platform_subtype(void);
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index f7d2bcb..936fd6b 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -19,6 +19,8 @@
#include <linux/debugfs.h>
#include <linux/list.h>
#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
#include <mach/msm_xo.h>
#include <mach/rpm.h>
@@ -44,18 +46,93 @@
static struct msm_xo msm_xo_sources[NUM_MSM_XO_IDS];
#ifdef CONFIG_DEBUG_FS
-static const char *msm_xo_mode_to_str(unsigned mode)
+static const char *msm_xo_to_str[NUM_MSM_XO_IDS] = {
+ [MSM_XO_TCXO_D0] = "D0",
+ [MSM_XO_TCXO_D1] = "D1",
+ [MSM_XO_TCXO_A0] = "A0",
+ [MSM_XO_TCXO_A1] = "A1",
+ [MSM_XO_TCXO_A2] = "A2",
+ [MSM_XO_CORE] = "CORE",
+};
+
+static const char *msm_xo_mode_to_str[NUM_MSM_XO_MODES] = {
+ [MSM_XO_MODE_ON] = "ON",
+ [MSM_XO_MODE_PIN_CTRL] = "PIN",
+ [MSM_XO_MODE_OFF] = "OFF",
+};
+
+static int msm_xo_debugfs_open(struct inode *inode, struct file *filp)
{
- switch (mode) {
- case MSM_XO_MODE_ON:
- return "ON";
- case MSM_XO_MODE_PIN_CTRL:
- return "PIN";
- case MSM_XO_MODE_OFF:
- return "OFF";
- default:
- return "ERR";
+ filp->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t msm_xo_debugfs_read(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ int r;
+ char buf[10];
+ struct msm_xo_voter *xo = filp->private_data;
+
+ r = snprintf(buf, sizeof(buf), "%s\n", msm_xo_mode_to_str[xo->mode]);
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t msm_xo_debugfs_write(struct file *filp,
+ const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ struct msm_xo_voter *xo = filp->private_data;
+ char buf[10], *b;
+ int i, ret;
+
+ if (cnt > sizeof(buf) - 1)
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ return -EFAULT;
+ buf[cnt] = '\0';
+ b = strstrip(buf);
+
+ for (i = 0; i < ARRAY_SIZE(msm_xo_mode_to_str); i++)
+ if (!strncasecmp(b, msm_xo_mode_to_str[i], sizeof(buf))) {
+ ret = msm_xo_mode_vote(xo, i);
+ return ret ? : cnt;
+ }
+
+ return -EINVAL;
+}
+
+static const struct file_operations msm_xo_debugfs_fops = {
+ .open = msm_xo_debugfs_open,
+ .read = msm_xo_debugfs_read,
+ .write = msm_xo_debugfs_write,
+};
+
+static struct dentry *xo_debugfs_root;
+static struct msm_xo_voter *xo_debugfs_voters[NUM_MSM_XO_IDS];
+
+static int __init msm_xo_init_debugfs_voters(void)
+{
+ int i;
+
+ xo_debugfs_root = debugfs_create_dir("msm_xo", NULL);
+ if (!xo_debugfs_root)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(msm_xo_sources); i++) {
+ xo_debugfs_voters[i] = msm_xo_get(i, "debugfs");
+ if (IS_ERR(xo_debugfs_voters[i]))
+ goto err;
+ debugfs_create_file(msm_xo_to_str[i], S_IRUGO | S_IWUSR,
+ xo_debugfs_root, xo_debugfs_voters[i],
+ &msm_xo_debugfs_fops);
}
+ return 0;
+err:
+ while (--i >= 0)
+ msm_xo_put(xo_debugfs_voters[i]);
+ debugfs_remove_recursive(xo_debugfs_root);
+ return -ENOMEM;
}
static void msm_xo_dump_xo(struct seq_file *m, struct msm_xo *xo,
@@ -63,27 +140,22 @@
{
struct msm_xo_voter *voter;
- seq_printf(m, "%-20s%s\n", name, msm_xo_mode_to_str(xo->mode));
+ seq_printf(m, "CXO %-16s%s\n", name, msm_xo_mode_to_str[xo->mode]);
list_for_each_entry(voter, &xo->voters, list)
seq_printf(m, " %s %-16s %s\n",
xo->mode == voter->mode ? "*" : " ",
voter->name,
- msm_xo_mode_to_str(voter->mode));
+ msm_xo_mode_to_str[voter->mode]);
}
static int msm_xo_show_voters(struct seq_file *m, void *v)
{
unsigned long flags;
+ int i;
spin_lock_irqsave(&msm_xo_lock, flags);
- msm_xo_dump_xo(m, &msm_xo_sources[MSM_XO_TCXO_D0], "TCXO D0");
- msm_xo_dump_xo(m, &msm_xo_sources[MSM_XO_TCXO_D1], "TCXO D1");
- msm_xo_dump_xo(m, &msm_xo_sources[MSM_XO_TCXO_A0], "TCXO A0");
- msm_xo_dump_xo(m, &msm_xo_sources[MSM_XO_TCXO_A1], "TCXO A1");
- msm_xo_dump_xo(m, &msm_xo_sources[MSM_XO_TCXO_A2], "TCXO A2");
- msm_xo_dump_xo(m, &msm_xo_sources[MSM_XO_CORE], "TCXO Core");
- msm_xo_dump_xo(m, &msm_xo_sources[MSM_XO_PXO], "PXO during sleep");
- msm_xo_dump_xo(m, &msm_xo_sources[MSM_XO_CXO], "CXO");
+ for (i = 0; i < ARRAY_SIZE(msm_xo_sources); i++)
+ msm_xo_dump_xo(m, &msm_xo_sources[i], msm_xo_to_str[i]);
spin_unlock_irqrestore(&msm_xo_lock, flags);
return 0;
@@ -103,19 +175,20 @@
static int __init msm_xo_debugfs_init(void)
{
- struct dentry *entry;
-
- entry = debugfs_create_file("xo_voters", S_IRUGO, NULL, NULL,
- &msm_xo_voters_ops);
- return IS_ERR(entry) ? PTR_ERR(entry) : 0;
+ msm_xo_init_debugfs_voters();
+ if (!debugfs_create_file("xo_voters", S_IRUGO, NULL, NULL,
+ &msm_xo_voters_ops))
+ return -ENOMEM;
+ return 0;
}
-late_initcall(msm_xo_debugfs_init);
+#else
+static int __init msm_xo_debugfs_init(void) { return 0; }
#endif
static int msm_xo_update_vote(struct msm_xo *xo)
{
int ret;
- unsigned vote, prev_vote = xo->mode, ctx_set;
+ unsigned vote, prev_vote = xo->mode;
struct msm_rpm_iv_pair cmd;
if (xo->votes[MSM_XO_MODE_ON])
@@ -133,36 +206,21 @@
* command fails we'll rollback.
*/
xo->mode = vote;
-
- if (xo == &msm_xo_sources[MSM_XO_PXO]) {
- cmd.id = MSM_RPM_ID_PXO_CLK;
- cmd.value = msm_xo_sources[MSM_XO_PXO].mode ? 1 : 0;
- ret = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &cmd, 1);
- } else if (xo == &msm_xo_sources[MSM_XO_CXO]) {
- cmd.id = MSM_RPM_ID_CXO_CLK;
- cmd.value = msm_xo_sources[MSM_XO_CXO].mode ? 1 : 0;
- if (cpu_is_msm9615())
- ctx_set = MSM_RPM_CTX_SET_SLEEP;
- else
- ctx_set = MSM_RPM_CTX_SET_0;
- ret = msm_rpmrs_set_noirq(ctx_set, &cmd, 1);
- } else {
- cmd.id = MSM_RPM_ID_CXO_BUFFERS;
- cmd.value = (msm_xo_sources[MSM_XO_TCXO_D0].mode << 0) |
- (msm_xo_sources[MSM_XO_TCXO_D1].mode << 8) |
- (msm_xo_sources[MSM_XO_TCXO_A0].mode << 16) |
- (msm_xo_sources[MSM_XO_TCXO_A1].mode << 24) |
- (msm_xo_sources[MSM_XO_TCXO_A2].mode << 28) |
- /*
- * 8660 RPM has XO_CORE at bit 18 and 8960 RPM has
- * XO_CORE at bit 20. Since the opposite bit is
- * reserved in both cases, just set both and be
- * done with it.
- */
- ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 20) |
- ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 18);
- ret = msm_rpm_set_noirq(MSM_RPM_CTX_SET_0, &cmd, 1);
- }
+ cmd.id = MSM_RPM_ID_CXO_BUFFERS;
+ cmd.value = (msm_xo_sources[MSM_XO_TCXO_D0].mode << 0) |
+ (msm_xo_sources[MSM_XO_TCXO_D1].mode << 8) |
+ (msm_xo_sources[MSM_XO_TCXO_A0].mode << 16) |
+ (msm_xo_sources[MSM_XO_TCXO_A1].mode << 24) |
+ (msm_xo_sources[MSM_XO_TCXO_A2].mode << 28) |
+ /*
+ * 8660 RPM has XO_CORE at bit 18 and 8960 RPM has
+ * XO_CORE at bit 20. Since the opposite bit is
+ * reserved in both cases, just set both and be
+ * done with it.
+ */
+ ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 20) |
+ ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 18);
+ ret = msm_rpm_set_noirq(MSM_RPM_CTX_SET_0, &cmd, 1);
if (ret)
xo->mode = prev_vote;
@@ -299,39 +357,17 @@
int __init msm_xo_init(void)
{
- int i;
- int ret = 0;
- struct msm_rpm_iv_pair cmd[2];
+ int i, ret;
+ struct msm_rpm_iv_pair cmd[1];
for (i = 0; i < ARRAY_SIZE(msm_xo_sources); i++)
INIT_LIST_HEAD(&msm_xo_sources[i].voters);
- if (cpu_is_msm9615()) {
- cmd[0].id = MSM_RPM_ID_CXO_CLK;
- cmd[0].value = 1;
- ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, cmd, 1);
- if (ret)
- goto out;
-
- cmd[0].id = MSM_RPM_ID_CXO_CLK;
- cmd[0].value = 0;
- ret = msm_rpmrs_set(MSM_RPM_CTX_SET_SLEEP, cmd, 1);
- goto out;
- }
-
- cmd[0].id = MSM_RPM_ID_PXO_CLK;
- cmd[0].value = 1;
- cmd[1].id = MSM_RPM_ID_CXO_BUFFERS;
- cmd[1].value = 0;
- ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, cmd, 2);
- if (ret)
- goto out;
-
- cmd[0].id = MSM_RPM_ID_PXO_CLK;
+ cmd[0].id = MSM_RPM_ID_CXO_BUFFERS;
cmd[0].value = 0;
- ret = msm_rpmrs_set(MSM_RPM_CTX_SET_SLEEP, cmd, 1);
+ ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, cmd, ARRAY_SIZE(cmd));
if (ret)
- goto out;
-out:
- return ret;
+ return ret;
+ msm_xo_debugfs_init();
+ return 0;
}
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 92ed764..3c46d0f 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -17,7 +17,6 @@
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/io.h>
-#include <linux/highmem.h>
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
@@ -26,9 +25,7 @@
#include <asm/unified.h>
#include <mach/msm_iomap.h>
#include <mach/smp.h>
-
#include "pm.h"
-#include "devices-msm7x2xa.h"
#define MSM_CORE1_RESET 0xA8600590
#define MSM_CORE1_STATUS_MSK 0x02800000
@@ -209,8 +206,7 @@
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
int i, value;
- phys_addr_t base;
- void *vaddr;
+ void __iomem *second_ptr;
/*
* Initialise the present map, which describes the set of CPUs
@@ -225,14 +221,18 @@
* Write the address of secondary startup into the
* boot remapper register. The secondary CPU branches to this address.
*/
- base = msm8625_get_phys_base();
- __raw_writel(base, (MSM_CFG_CTL_BASE + 0x34));
+ __raw_writel(MSM8625_SECONDARY_PHYS, (MSM_CFG_CTL_BASE + 0x34));
mb();
- vaddr = kmap_atomic(phys_to_page(base));
+ 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(vaddr, virt_to_phys(msm_secondary_startup));
- kunmap_atomic(vaddr);
+ 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);
diff --git a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
index 030d08f..5df976d 100644
--- a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
@@ -193,8 +193,8 @@
audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
if (audio == NULL) {
- pr_err("%s:session id %d: Could not allocate memory for amrwb"
- "driver\n", __func__, audio->ac->session);
+ pr_err("%s: Could not allocate memory for amrwb driver\n",
+ __func__);
return -ENOMEM;
}
/* Allocate memory for encoder config param */
@@ -235,8 +235,8 @@
(void *)audio);
if (!audio->ac) {
- pr_err("%s:session id %d: Could not allocate memory for audio"
- "client\n", __func__, audio->ac->session);
+ pr_err("%s:audio[%p]: Could not allocate memory for audio"
+ "client\n", __func__, audio);
kfree(audio->enc_cfg);
kfree(audio);
return -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 541f62f..b5f071f 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -255,9 +255,9 @@
if (!dest || !svc_name || !svc_fn)
return NULL;
- if (!strcmp(dest, "ADSP"))
+ if (!strncmp(dest, "ADSP", 4))
dest_id = APR_DEST_QDSP6;
- else if (!strcmp(dest, "MODEM")) {
+ else if (!strncmp(dest, "MODEM", 5)) {
dest_id = APR_DEST_MODEM;
} else {
pr_err("APR: wrong destination\n");
@@ -286,23 +286,23 @@
pr_info("%s: modem Up\n", __func__);
}
- if (!strcmp(svc_name, "AFE")) {
+ if (!strncmp(svc_name, "AFE", 3)) {
client_id = APR_CLIENT_AUDIO;
svc_idx = 0;
svc_id = APR_SVC_AFE;
- } else if (!strcmp(svc_name, "ASM")) {
+ } else if (!strncmp(svc_name, "ASM", 3)) {
client_id = APR_CLIENT_AUDIO;
svc_idx = 1;
svc_id = APR_SVC_ASM;
- } else if (!strcmp(svc_name, "ADM")) {
+ } else if (!strncmp(svc_name, "ADM", 3)) {
client_id = APR_CLIENT_AUDIO;
svc_idx = 2;
svc_id = APR_SVC_ADM;
- } else if (!strcmp(svc_name, "CORE")) {
+ } else if (!strncmp(svc_name, "CORE", 4)) {
client_id = APR_CLIENT_AUDIO;
svc_idx = 3;
svc_id = APR_SVC_ADSP_CORE;
- } else if (!strcmp(svc_name, "TEST")) {
+ } else if (!strncmp(svc_name, "TEST", 4)) {
if (dest_id == APR_DEST_QDSP6) {
client_id = APR_CLIENT_AUDIO;
svc_idx = 4;
@@ -311,19 +311,19 @@
svc_idx = 7;
}
svc_id = APR_SVC_TEST_CLIENT;
- } else if (!strcmp(svc_name, "VSM")) {
+ } else if (!strncmp(svc_name, "VSM", 3)) {
client_id = APR_CLIENT_VOICE;
svc_idx = 0;
svc_id = APR_SVC_VSM;
- } else if (!strcmp(svc_name, "VPM")) {
+ } else if (!strncmp(svc_name, "VPM", 3)) {
client_id = APR_CLIENT_VOICE;
svc_idx = 1;
svc_id = APR_SVC_VPM;
- } else if (!strcmp(svc_name, "MVS")) {
+ } else if (!strncmp(svc_name, "MVS", 3)) {
client_id = APR_CLIENT_VOICE;
svc_idx = 2;
svc_id = APR_SVC_MVS;
- } else if (!strcmp(svc_name, "MVM")) {
+ } else if (!strncmp(svc_name, "MVM", 3)) {
if (dest_id == APR_DEST_MODEM) {
client_id = APR_CLIENT_VOICE;
svc_idx = 3;
@@ -333,7 +333,7 @@
svc_idx = 5;
svc_id = APR_SVC_ADSP_MVM;
}
- } else if (!strcmp(svc_name, "CVS")) {
+ } else if (!strncmp(svc_name, "CVS", 3)) {
if (dest_id == APR_DEST_MODEM) {
client_id = APR_CLIENT_VOICE;
svc_idx = 4;
@@ -343,7 +343,7 @@
svc_idx = 6;
svc_id = APR_SVC_ADSP_CVS;
}
- } else if (!strcmp(svc_name, "CVP")) {
+ } else if (!strncmp(svc_name, "CVP", 3)) {
if (dest_id == APR_DEST_MODEM) {
client_id = APR_CLIENT_VOICE;
svc_idx = 5;
@@ -353,7 +353,7 @@
svc_idx = 7;
svc_id = APR_SVC_ADSP_CVP;
}
- } else if (!strcmp(svc_name, "SRD")) {
+ } else if (!strncmp(svc_name, "SRD", 3)) {
client_id = APR_CLIENT_VOICE;
svc_idx = 6;
svc_id = APR_SVC_SRD;
@@ -679,16 +679,13 @@
static int __init apr_late_init(void)
{
- void *ret;
+ int ret = 0;
init_waitqueue_head(&dsp_wait);
init_waitqueue_head(&modem_wait);
atomic_set(&dsp_state, 1);
atomic_set(&modem_state, 1);
- ret = subsys_notif_register_notifier("modem", &mnb);
- pr_debug("subsys_register_notifier: ret1 = %p\n", ret);
- ret = subsys_notif_register_notifier("lpass", &lnb);
- pr_debug("subsys_register_notifier: ret2 = %p\n", ret);
-
- return 0;
+ subsys_notif_register_notifier("modem", &mnb);
+ subsys_notif_register_notifier("lpass", &lnb);
+ return ret;
}
late_initcall(apr_late_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 9823209..a3a14c4 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -442,8 +442,7 @@
}
- if ((payload_size < 0) ||
- (payload_size > MAX_PAYLOAD_SIZE)) {
+ if (payload_size > MAX_PAYLOAD_SIZE) {
pr_err("%s: Invalid payload size = %d\n",
__func__, payload_size);
@@ -614,8 +613,7 @@
goto done;
}
- if ((payload_size < 0) ||
- (payload_size > MAX_PAYLOAD_SIZE)) {
+ if (payload_size > MAX_PAYLOAD_SIZE) {
pr_err("%s: Invalid payload size = %d\n",
__func__, payload_size);
@@ -627,15 +625,17 @@
__func__);
goto done;
}
- if (session_id >= AFE_MAX_PORTS) {
+ if (session_id > (SESSION_MAX + 1)) {
pr_err("%s: Invalid Session = %d\n", __func__, session_id);
goto done;
}
mutex_lock(&rtac_asm_apr_mutex);
- if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
- pr_err("%s: APR not initialized\n", __func__);
- goto err;
+ if (session_id < SESSION_MAX+1) {
+ if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
+ pr_err("%s: APR not initialized\n", __func__);
+ goto err;
+ }
}
/* Set globals for copy of returned payload */
@@ -664,7 +664,8 @@
asm_params.opcode = opcode;
memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params));
- atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);
+ if (session_id < SESSION_MAX+1)
+ atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);
pr_debug("%s: Sending RTAC command size = %d, session_id=%d\n",
__func__, asm_params.pkt_size, session_id);
@@ -723,7 +724,7 @@
bool rtac_make_voice_callback(u32 mode, uint32_t *payload, u32 payload_size)
{
if ((atomic_read(&rtac_voice_apr_data[mode].cmd_state) != 1) ||
- (mode < 0) || (mode >= RTAC_VOICE_MODES))
+ (mode >= RTAC_VOICE_MODES))
return false;
pr_debug("%s\n", __func__);
@@ -782,10 +783,8 @@
goto done;
}
- if ((payload_size < 0) ||
- (payload_size > MAX_PAYLOAD_SIZE)) {
-
- pr_err("%s: Invalid payload size = %d\n",
+ if (payload_size > MAX_PAYLOAD_SIZE) {
+ pr_err("%s: Invalid payload size = %d\n",
__func__, payload_size);
goto done;
}
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 9321b40..d7f2623 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -654,6 +654,7 @@
struct notifier_block nb;
};
+static int disable_smsm_reset_handshake;
static struct platform_device loopback_tty_pdev = {.name = "LOOPBACK_TTY"};
static LIST_HEAD(smd_ch_closed_list);
@@ -2338,7 +2339,7 @@
/* If we get an interrupt and the apps SMSM_RESET
bit is already set, the modem is acking the
app's reset ack. */
- if (!cpu_is_msm8960() && !cpu_is_msm8930())
+ if (!disable_smsm_reset_handshake)
apps &= ~SMSM_RESET;
/* Issue a fake irq to handle any
* smd state changes during reset
@@ -2349,7 +2350,7 @@
modem_queue_start_reset_notify();
} else if (modm & SMSM_RESET) {
- if (!cpu_is_msm8960() && !cpu_is_msm8930())
+ if (!disable_smsm_reset_handshake)
apps |= SMSM_RESET;
pr_err("\nSMSM: Modem SMSM state changed to SMSM_RESET.");
@@ -2871,6 +2872,10 @@
num_ss = smd_platform_data->num_ss_configs;
smd_ss_config_list = smd_platform_data->smd_ss_configs;
+ if (smd_platform_data->smd_ssr_config)
+ disable_smsm_reset_handshake = smd_platform_data->
+ smd_ssr_config->disable_smsm_reset_handshake;
+
for (i = 0; i < num_ss; i++) {
cfg = &smd_ss_config_list[i];
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 9b10ffd..3faeb37 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -257,7 +257,6 @@
static struct socinfo_v1 dummy_socinfo = {
.format = 1,
.version = 1,
- .build_id = "Dummy socinfo placeholder"
};
uint32_t socinfo_get_id(void)
@@ -613,10 +612,14 @@
dummy_socinfo.id = 109;
else if (machine_is_msm9615_mtp() || machine_is_msm9615_cdp())
dummy_socinfo.id = 104;
- else if (early_machine_is_copper())
+ else if (early_machine_is_copper()) {
dummy_socinfo.id = 126;
- else if (machine_is_msm8625_rumi3())
+ strlcpy(dummy_socinfo.build_id, "copper - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (machine_is_msm8625_rumi3())
dummy_socinfo.id = 127;
+ strlcat(dummy_socinfo.build_id, "Dummy socinfo",
+ sizeof(dummy_socinfo.build_id));
return (void *) &dummy_socinfo;
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 8f3263e..8328ee2 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -477,4 +477,12 @@
This option enables support for on-chip GPIO found on Qualcomm PM8xxx
PMICs through RPC.
+config GPIO_QPNP
+ depends on ARCH_MSMCOPPER
+ depends on OF_SPMI
+ depends on MSM_QPNP_INT
+ tristate "Qualcomm QPNP GPIO support"
+ help
+ Say 'y' here to include support for the Qualcomm QPNP gpio
+ support. QPNP is a SPMI based PMIC implementation.
endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 83972f1..db19ac8 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -51,3 +51,4 @@
obj-$(CONFIG_GPIO_PM8XXX) += pm8xxx-gpio.o
obj-$(CONFIG_GPIO_PM8XXX_MPP) += pm8xxx-mpp.o
obj-$(CONFIG_GPIO_PM8XXX_RPC) += gpio-pm8xxx-rpc.o
+obj-$(CONFIG_GPIO_QPNP) += qpnp-gpio.o
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
new file mode 100644
index 0000000..b09b040
--- /dev/null
+++ b/drivers/gpio/qpnp-gpio.c
@@ -0,0 +1,706 @@
+/* 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/interrupt.h>
+#include <linux/types.h>
+#include <linux/spmi.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/qpnp/gpio.h>
+
+#include <mach/qpnp.h>
+
+#define Q_REG_ADDR(q_spec, reg_index) \
+ ((q_spec)->offset + reg_index)
+
+#define Q_REG_STATUS1 0x8
+#define Q_NUM_CTL_REGS 5
+
+/* control register base address offsets */
+#define Q_REG_IO_CTL1 0x42
+#define Q_REG_INPUT_CTL1 0x43
+#define Q_REG_OUTPUT_CTL1 0x44
+#define Q_REG_OUTPUT_CTL2 0x45
+#define Q_REG_EN_CTL1 0x46
+
+/* control register regs array indices */
+#define Q_REG_I_IO_CTL1 0
+#define Q_REG_I_INPUT_CTL1 1
+#define Q_REG_I_OUTPUT_CTL1 2
+#define Q_REG_I_OUTPUT_CTL2 3
+#define Q_REG_I_EN_CTL1 4
+
+/* control register configuration */
+#define Q_REG_VIN_SHIFT 0
+#define Q_REG_VIN_MASK 0x7
+#define Q_REG_PULL_SHIFT 4
+#define Q_REG_PULL_MASK 0x70
+#define Q_REG_INPUT_EN_SHIFT 7
+#define Q_REG_INPUT_EN_MASK 0x80
+#define Q_REG_OUT_STRENGTH_SHIFT 0
+#define Q_REG_OUT_STRENGTH_MASK 0x3
+#define Q_REG_OUT_TYPE_SHIFT 6
+#define Q_REG_OUT_TYPE_MASK 0x40
+#define Q_REG_OUT_INVERT_SHIFT 0
+#define Q_REG_OUT_INVERT_MASK 0x1
+#define Q_REG_SRC_SEL_SHIFT 1
+#define Q_REG_SRC_SEL_MASK 0xE
+#define Q_REG_OUTPUT_EN_SHIFT 7
+#define Q_REG_OUTPUT_EN_MASK 0x80
+#define Q_REG_MASTER_EN_SHIFT 7
+#define Q_REG_MASTER_EN_MASK 0x80
+
+
+struct qpnp_gpio_spec {
+ uint8_t slave; /* 0-15 */
+ uint16_t offset; /* 0-255 */
+ uint32_t gpio_chip_idx; /* offset from gpio_chip base */
+ int irq; /* logical IRQ number */
+ u8 regs[Q_NUM_CTL_REGS]; /* Control regs */
+};
+
+struct qpnp_gpio_chip {
+ struct gpio_chip gpio_chip;
+ struct spmi_device *spmi;
+ struct qpnp_gpio_spec **pmic_gpios;
+ struct qpnp_gpio_spec **chip_gpios;
+ uint32_t pmic_gpio_lowest;
+ uint32_t pmic_gpio_highest;
+ struct device_node *int_ctrl;
+ struct list_head chip_list;
+};
+
+static LIST_HEAD(qpnp_gpio_chips);
+static DEFINE_MUTEX(qpnp_gpio_chips_lock);
+
+static inline void qpnp_pmic_gpio_set_spec(struct qpnp_gpio_chip *q_chip,
+ uint32_t pmic_gpio,
+ struct qpnp_gpio_spec *spec)
+{
+ q_chip->pmic_gpios[pmic_gpio - q_chip->pmic_gpio_lowest] = spec;
+}
+
+static inline struct qpnp_gpio_spec *qpnp_pmic_gpio_get_spec(
+ struct qpnp_gpio_chip *q_chip,
+ uint32_t pmic_gpio)
+{
+ if (pmic_gpio < q_chip->pmic_gpio_lowest ||
+ pmic_gpio > q_chip->pmic_gpio_highest)
+ return NULL;
+
+ return q_chip->pmic_gpios[pmic_gpio - q_chip->pmic_gpio_lowest];
+}
+
+static inline struct qpnp_gpio_spec *qpnp_chip_gpio_get_spec(
+ struct qpnp_gpio_chip *q_chip,
+ uint32_t chip_gpio)
+{
+ if (chip_gpio > q_chip->gpio_chip.ngpio)
+ return NULL;
+
+ return q_chip->chip_gpios[chip_gpio];
+}
+
+static inline void qpnp_chip_gpio_set_spec(struct qpnp_gpio_chip *q_chip,
+ uint32_t chip_gpio,
+ struct qpnp_gpio_spec *spec)
+{
+ q_chip->chip_gpios[chip_gpio] = spec;
+}
+
+int qpnp_gpio_config(int gpio, struct qpnp_gpio_cfg *param)
+{
+ int rc, chip_offset;
+ struct qpnp_gpio_chip *q_chip;
+ struct qpnp_gpio_spec *q_spec = NULL;
+ struct gpio_chip *gpio_chip;
+
+ if (param == NULL)
+ return -EINVAL;
+
+ mutex_lock(&qpnp_gpio_chips_lock);
+ list_for_each_entry(q_chip, &qpnp_gpio_chips, chip_list) {
+ gpio_chip = &q_chip->gpio_chip;
+ if (gpio >= gpio_chip->base
+ && gpio < gpio_chip->base + gpio_chip->ngpio) {
+ chip_offset = gpio - gpio_chip->base;
+ q_spec = qpnp_chip_gpio_get_spec(q_chip, chip_offset);
+ if (WARN_ON(!q_spec)) {
+ mutex_unlock(&qpnp_gpio_chips_lock);
+ return -ENODEV;
+ }
+ break;
+ }
+ }
+ mutex_unlock(&qpnp_gpio_chips_lock);
+ if (!q_spec) {
+ pr_err("gpio %d not handled by any pmic\n", gpio);
+ return -EINVAL;
+ }
+
+ q_spec->regs[Q_REG_I_IO_CTL1] = (param->vin_sel <<
+ Q_REG_VIN_SHIFT) & Q_REG_VIN_MASK;
+ q_spec->regs[Q_REG_I_IO_CTL1] |= (param->pull <<
+ Q_REG_PULL_SHIFT) & Q_REG_PULL_MASK;
+ q_spec->regs[Q_REG_I_INPUT_CTL1] = ((param->direction &
+ QPNP_GPIO_DIR_IN) ? ((1 << Q_REG_INPUT_EN_SHIFT)) : 0);
+
+ if (param->direction & QPNP_GPIO_DIR_OUT) {
+ q_spec->regs[Q_REG_I_OUTPUT_CTL1] = (param->out_strength
+ << Q_REG_OUT_STRENGTH_SHIFT) & Q_REG_OUT_STRENGTH_MASK;
+ q_spec->regs[Q_REG_I_OUTPUT_CTL1] |= (param->output_type
+ << Q_REG_OUT_TYPE_SHIFT) & Q_REG_OUT_TYPE_MASK;
+ } else {
+ q_spec->regs[Q_REG_I_OUTPUT_CTL1] = 0;
+ }
+
+ if (param->direction & QPNP_GPIO_DIR_OUT) {
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] = (param->inv_int_pol
+ << Q_REG_OUT_INVERT_SHIFT) & Q_REG_OUT_INVERT_MASK;
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] |= (param->src_select
+ << Q_REG_SRC_SEL_SHIFT) & Q_REG_SRC_SEL_MASK;
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] |= (1 <<
+ Q_REG_OUTPUT_EN_SHIFT) & Q_REG_OUTPUT_EN_MASK;
+ } else {
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] = 0;
+ }
+
+ q_spec->regs[Q_REG_I_EN_CTL1] = (param->master_en <<
+ Q_REG_MASTER_EN_SHIFT) & Q_REG_MASTER_EN_MASK;
+
+ rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_IO_CTL1),
+ &q_spec->regs[Q_REG_I_IO_CTL1], Q_NUM_CTL_REGS);
+ if (rc)
+ dev_err(&q_chip->spmi->dev, "%s: unable to write master"
+ " enable\n", __func__);
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_gpio_config);
+
+int qpnp_gpio_map_gpio(uint16_t slave_id, uint32_t pmic_gpio)
+{
+ struct qpnp_gpio_chip *q_chip;
+ struct qpnp_gpio_spec *q_spec = NULL;
+
+ mutex_lock(&qpnp_gpio_chips_lock);
+ list_for_each_entry(q_chip, &qpnp_gpio_chips, chip_list) {
+ if (q_chip->spmi->sid != slave_id)
+ continue;
+ if (q_chip->pmic_gpio_lowest <= pmic_gpio &&
+ q_chip->pmic_gpio_highest >= pmic_gpio) {
+ q_spec = qpnp_pmic_gpio_get_spec(q_chip, pmic_gpio);
+ mutex_unlock(&qpnp_gpio_chips_lock);
+ if (WARN_ON(!q_spec))
+ return -ENODEV;
+ return q_chip->gpio_chip.base + q_spec->gpio_chip_idx;
+ }
+ }
+ mutex_unlock(&qpnp_gpio_chips_lock);
+ return -EINVAL;
+}
+EXPORT_SYMBOL(qpnp_gpio_map_gpio);
+
+static int qpnp_gpio_to_irq(struct gpio_chip *gpio_chip, unsigned offset)
+{
+ struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
+ struct qpnp_gpio_spec *q_spec;
+
+ q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
+ if (!q_spec)
+ return -EINVAL;
+
+ return q_spec->irq;
+}
+
+static int qpnp_gpio_get(struct gpio_chip *gpio_chip, unsigned offset)
+{
+ int rc, ret_val;
+ struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
+ struct qpnp_gpio_spec *q_spec = NULL;
+ u8 buf[1];
+
+ if (WARN_ON(!q_chip))
+ return -ENODEV;
+
+ q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
+ if (WARN_ON(!q_spec))
+ return -ENODEV;
+
+ /* gpio val is from RT status iff input is enabled */
+ if (q_spec->regs[Q_REG_I_INPUT_CTL1] & Q_REG_INPUT_EN_MASK) {
+ /* INT_RT_STS */
+ rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_STATUS1),
+ &buf[0], 1);
+ return buf[0];
+
+ } else {
+ ret_val = (q_spec->regs[Q_REG_I_OUTPUT_CTL2] &
+ Q_REG_OUT_INVERT_MASK) >> Q_REG_OUT_INVERT_SHIFT;
+ return ret_val;
+ }
+
+ return 0;
+}
+
+static int __qpnp_gpio_set(struct qpnp_gpio_chip *q_chip,
+ struct qpnp_gpio_spec *q_spec, int value)
+{
+ int rc;
+
+ if (!q_chip || !q_spec)
+ return -EINVAL;
+
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] &= ~(1 << Q_REG_OUT_INVERT_SHIFT);
+
+ if (value)
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] |=
+ (1 << Q_REG_OUT_INVERT_SHIFT);
+
+ rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_OUTPUT_CTL2),
+ &q_spec->regs[Q_REG_I_OUTPUT_CTL2], 1);
+ if (rc)
+ dev_err(&q_chip->spmi->dev, "%s: spmi write failed\n",
+ __func__);
+ return rc;
+}
+
+
+static void qpnp_gpio_set(struct gpio_chip *gpio_chip,
+ unsigned offset, int value)
+{
+ struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
+ struct qpnp_gpio_spec *q_spec;
+
+ if (WARN_ON(!q_chip))
+ return;
+
+ q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
+ if (WARN_ON(!q_spec))
+ return;
+
+ __qpnp_gpio_set(q_chip, q_spec, value);
+}
+
+static int qpnp_gpio_set_direction(struct qpnp_gpio_chip *q_chip,
+ struct qpnp_gpio_spec *q_spec, int direction)
+{
+ int rc;
+
+ if (!q_chip || !q_spec)
+ return -EINVAL;
+
+ if (direction & QPNP_GPIO_DIR_IN) {
+ q_spec->regs[Q_REG_I_INPUT_CTL1] |=
+ (1 << Q_REG_INPUT_EN_SHIFT);
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] &=
+ ~(1 << Q_REG_OUTPUT_EN_SHIFT);
+ } else {
+ q_spec->regs[Q_REG_I_INPUT_CTL1] &=
+ ~(1 << Q_REG_INPUT_EN_SHIFT);
+ q_spec->regs[Q_REG_I_OUTPUT_CTL2] |=
+ (1 << Q_REG_OUTPUT_EN_SHIFT);
+ }
+
+ rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_INPUT_CTL1),
+ &q_spec->regs[Q_REG_I_INPUT_CTL1], 3);
+ return rc;
+}
+
+static int qpnp_gpio_direction_input(struct gpio_chip *gpio_chip,
+ unsigned offset)
+{
+ struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
+ struct qpnp_gpio_spec *q_spec;
+
+ if (WARN_ON(!q_chip))
+ return -ENODEV;
+
+ q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
+ if (WARN_ON(!q_spec))
+ return -ENODEV;
+
+ return qpnp_gpio_set_direction(q_chip, q_spec, QPNP_GPIO_DIR_IN);
+}
+
+static int qpnp_gpio_direction_output(struct gpio_chip *gpio_chip,
+ unsigned offset,
+ int val)
+{
+ int rc;
+ struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
+ struct qpnp_gpio_spec *q_spec;
+
+ if (WARN_ON(!q_chip))
+ return -ENODEV;
+
+ q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
+ if (WARN_ON(!q_spec))
+ return -ENODEV;
+
+ rc = __qpnp_gpio_set(q_chip, q_spec, val);
+ if (rc)
+ return rc;
+
+ rc = qpnp_gpio_set_direction(q_chip, q_spec, QPNP_GPIO_DIR_OUT);
+
+ return rc;
+}
+
+static int qpnp_gpio_of_gpio_xlate(struct gpio_chip *gpio_chip,
+ struct device_node *np,
+ const void *gpio_spec, u32 *flags)
+{
+ struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
+ struct qpnp_gpio_spec *q_spec;
+ const __be32 *gpio = gpio_spec;
+ u32 n = be32_to_cpup(gpio);
+
+ if (WARN_ON(gpio_chip->of_gpio_n_cells < 2)) {
+ pr_err("%s: of_gpio_n_cells < 2\n", __func__);
+ return -EINVAL;
+ }
+
+ q_spec = qpnp_pmic_gpio_get_spec(q_chip, n);
+ if (!q_spec) {
+ pr_err("%s: no such PMIC gpio %u in device topology\n",
+ __func__, n);
+ return -EINVAL;
+ }
+
+ if (flags)
+ *flags = be32_to_cpu(gpio[1]);
+
+ return q_spec->gpio_chip_idx;
+}
+
+static int qpnp_gpio_config_default(struct spmi_device *spmi,
+ const __be32 *prop, int gpio)
+{
+ struct qpnp_gpio_cfg param;
+ int rc;
+
+ dev_dbg(&spmi->dev, "%s: p[0]: 0x%x p[1]: 0x%x p[2]: 0x%x p[3]:"
+ " 0x%x p[4]: 0x%x p[5]: 0x%x p[6]: 0x%x p[7]: 0x%x"
+ " p[8]: 0x%x\n", __func__,
+ be32_to_cpup(&prop[0]), be32_to_cpup(&prop[1]),
+ be32_to_cpup(&prop[2]), be32_to_cpup(&prop[3]),
+ be32_to_cpup(&prop[4]), be32_to_cpup(&prop[5]),
+ be32_to_cpup(&prop[6]), be32_to_cpup(&prop[7]),
+ be32_to_cpup(&prop[8]));
+
+ param.direction = be32_to_cpup(&prop[0]);
+ param.output_type = be32_to_cpup(&prop[1]);
+ param.output_value = be32_to_cpup(&prop[2]);
+ param.pull = be32_to_cpup(&prop[3]);
+ param.vin_sel = be32_to_cpup(&prop[4]);
+ param.out_strength = be32_to_cpup(&prop[5]);
+ param.src_select = be32_to_cpup(&prop[6]);
+ param.inv_int_pol = be32_to_cpup(&prop[7]);
+ param.master_en = be32_to_cpup(&prop[8]);
+
+ rc = qpnp_gpio_config(gpio, ¶m);
+ if (rc)
+ dev_err(&spmi->dev, "%s: unable to set default config for"
+ " gpio %d\n", __func__, gpio);
+ return rc;
+}
+
+static int qpnp_gpio_free_chip(struct qpnp_gpio_chip *q_chip)
+{
+ struct spmi_device *spmi = q_chip->spmi;
+ int rc, i;
+
+ if (q_chip->chip_gpios)
+ for (i = 0; i < spmi->num_dev_node; i++)
+ kfree(q_chip->chip_gpios[i]);
+
+ mutex_lock(&qpnp_gpio_chips_lock);
+ list_del(&q_chip->chip_list);
+ mutex_unlock(&qpnp_gpio_chips_lock);
+ rc = gpiochip_remove(&q_chip->gpio_chip);
+ if (rc)
+ dev_err(&q_chip->spmi->dev, "%s: unable to remove gpio\n",
+ __func__);
+ kfree(q_chip->chip_gpios);
+ kfree(q_chip->pmic_gpios);
+ kfree(q_chip);
+ return rc;
+}
+
+static int qpnp_gpio_probe(struct spmi_device *spmi)
+{
+ struct qpnp_gpio_chip *q_chip;
+ struct resource *res;
+ struct qpnp_gpio_spec *q_spec;
+ const __be32 *prop;
+ int i, rc, ret, gpio, len;
+ int lowest_gpio = INT_MAX, highest_gpio = INT_MIN;
+ u32 intspec[3];
+
+ q_chip = kzalloc(sizeof(*q_chip), GFP_KERNEL);
+ if (!q_chip) {
+ dev_err(&spmi->dev, "%s: Can't allocate gpio_chip\n",
+ __func__);
+ return -ENOMEM;
+ }
+ q_chip->spmi = spmi;
+ dev_set_drvdata(&spmi->dev, q_chip);
+
+ mutex_lock(&qpnp_gpio_chips_lock);
+ list_add(&q_chip->chip_list, &qpnp_gpio_chips);
+ mutex_unlock(&qpnp_gpio_chips_lock);
+
+ /* first scan through nodes to find the range required for allocation */
+ for (i = 0; i < spmi->num_dev_node; i++) {
+ prop = of_get_property(spmi->dev_node[i].of_node,
+ "qcom,qpnp-gpio-num", &len);
+ if (!prop) {
+ dev_err(&spmi->dev, "%s: unable to get"
+ " qcom,qpnp-gpio-num property\n", __func__);
+ ret = -EINVAL;
+ goto err_probe;
+ } else if (len != sizeof(__be32)) {
+ dev_err(&spmi->dev, "%s: Invalid qcom,qpnp-gpio-num"
+ " property\n", __func__);
+ ret = -EINVAL;
+ goto err_probe;
+ }
+
+ gpio = be32_to_cpup(prop);
+ if (gpio < lowest_gpio)
+ lowest_gpio = gpio;
+ if (gpio > highest_gpio)
+ highest_gpio = gpio;
+ }
+
+ if (highest_gpio < lowest_gpio) {
+ dev_err(&spmi->dev, "%s: no device nodes specified in"
+ " topology\n", __func__);
+ ret = -EINVAL;
+ goto err_probe;
+ } else if (lowest_gpio == 0) {
+ dev_err(&spmi->dev, "%s: 0 is not a valid PMIC GPIO\n",
+ __func__);
+ ret = -EINVAL;
+ goto err_probe;
+ }
+
+ q_chip->pmic_gpio_lowest = lowest_gpio;
+ q_chip->pmic_gpio_highest = highest_gpio;
+
+ /* allocate gpio lookup tables */
+ q_chip->pmic_gpios = kzalloc(sizeof(struct qpnp_gpio_spec *) *
+ highest_gpio - lowest_gpio + 1,
+ GFP_KERNEL);
+ q_chip->chip_gpios = kzalloc(sizeof(struct qpnp_gpio_spec *) *
+ spmi->num_dev_node, GFP_KERNEL);
+ if (!q_chip->pmic_gpios || !q_chip->chip_gpios) {
+ dev_err(&spmi->dev, "%s: unable to allocate memory\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_probe;
+ }
+
+ /* get interrupt controller device_node */
+ q_chip->int_ctrl = of_irq_find_parent(spmi->dev.of_node);
+ if (!q_chip->int_ctrl) {
+ dev_err(&spmi->dev, "%s: Can't find interrupt parent\n",
+ __func__);
+ ret = -EINVAL;
+ goto err_probe;
+ }
+
+ /* now scan through again and populate the lookup table */
+ for (i = 0; i < spmi->num_dev_node; i++) {
+ res = qpnp_get_resource(spmi, i, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&spmi->dev, "%s: node %s is missing has no"
+ " base address definition\n",
+ __func__, spmi->dev_node[i].of_node->full_name);
+ }
+
+ prop = of_get_property(spmi->dev_node[i].of_node,
+ "qcom,qpnp-gpio-num", &len);
+ if (!prop) {
+ dev_err(&spmi->dev, "%s: unable to get"
+ " qcom,qpnp-gpio-num property\n", __func__);
+ ret = -EINVAL;
+ goto err_probe;
+ } else if (len != sizeof(__be32)) {
+ dev_err(&spmi->dev, "%s: Invalid qcom,qpnp-gpio-num"
+ " property\n", __func__);
+ ret = -EINVAL;
+ goto err_probe;
+ }
+ gpio = be32_to_cpup(prop);
+
+ q_spec = kzalloc(sizeof(struct qpnp_gpio_spec),
+ GFP_KERNEL);
+ if (!q_spec) {
+ dev_err(&spmi->dev, "%s: unable to allocate"
+ " memory\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_probe;
+ }
+
+ q_spec->slave = spmi->sid;
+ q_spec->offset = res->start;
+ q_spec->gpio_chip_idx = i;
+
+ /* call into irq_domain to get irq mapping */
+ intspec[0] = q_chip->spmi->sid;
+ intspec[1] = (q_spec->offset >> 8) & 0xFF;
+ intspec[2] = 0;
+ q_spec->irq = irq_create_of_mapping(q_chip->int_ctrl,
+ intspec, 3);
+ if (!q_spec->irq) {
+ dev_err(&spmi->dev, "%s: invalid irq for gpio"
+ " %u\n", __func__, gpio);
+ ret = -EINVAL;
+ goto err_probe;
+ }
+ /* initialize lookup table entries */
+ qpnp_pmic_gpio_set_spec(q_chip, gpio, q_spec);
+ qpnp_chip_gpio_set_spec(q_chip, i, q_spec);
+ }
+
+ q_chip->gpio_chip.base = -1;
+ q_chip->gpio_chip.ngpio = spmi->num_dev_node;
+ q_chip->gpio_chip.label = "qpnp-gpio";
+ q_chip->gpio_chip.direction_input = qpnp_gpio_direction_input;
+ q_chip->gpio_chip.direction_output = qpnp_gpio_direction_output;
+ q_chip->gpio_chip.to_irq = qpnp_gpio_to_irq;
+ q_chip->gpio_chip.get = qpnp_gpio_get;
+ q_chip->gpio_chip.set = qpnp_gpio_set;
+ q_chip->gpio_chip.dev = &spmi->dev;
+ q_chip->gpio_chip.of_xlate = qpnp_gpio_of_gpio_xlate;
+ q_chip->gpio_chip.of_gpio_n_cells = 2;
+ q_chip->gpio_chip.can_sleep = 0;
+
+ rc = gpiochip_add(&q_chip->gpio_chip);
+ if (rc) {
+ dev_err(&spmi->dev, "%s: Can't add gpio chip, rc = %d\n",
+ __func__, rc);
+ ret = rc;
+ goto err_probe;
+ }
+
+ /* now configure gpio defaults if they exist */
+ for (i = 0; i < spmi->num_dev_node; i++) {
+ q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
+ if (WARN_ON(!q_spec))
+ return -ENODEV;
+
+ /* It's not an error to not config a default */
+ prop = of_get_property(spmi->dev_node[i].of_node,
+ "qcom,qpnp-gpio-cfg", &len);
+ /* 9 data values constitute one tuple */
+ if (prop && (len != (9 * sizeof(__be32)))) {
+ dev_err(&spmi->dev, "%s: invalid format for"
+ " qcom,qpnp-gpio-cfg property\n",
+ __func__);
+ ret = -EINVAL;
+ goto err_probe;
+ } else if (prop) {
+ rc = qpnp_gpio_config_default(spmi, prop,
+ q_chip->gpio_chip.base + i);
+ if (rc) {
+ ret = rc;
+ goto err_probe;
+ }
+ } else {
+ /* initialize with hardware defaults */
+ rc = spmi_ext_register_readl(
+ q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_IO_CTL1),
+ &q_spec->regs[Q_REG_I_IO_CTL1],
+ Q_NUM_CTL_REGS);
+ q_spec->regs[Q_REG_I_EN_CTL1] |=
+ (1 << Q_REG_MASTER_EN_SHIFT);
+ rc = spmi_ext_register_writel(
+ q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_EN_CTL1),
+ &q_spec->regs[Q_REG_EN_CTL1], 1);
+ if (rc) {
+ dev_err(&spmi->dev, "%s: spmi write"
+ " failed\n", __func__);
+ ret = rc;
+ goto err_probe;
+ }
+ }
+ }
+
+ dev_dbg(&spmi->dev, "%s: gpio_chip registered between %d-%u\n",
+ __func__, q_chip->gpio_chip.base,
+ (q_chip->gpio_chip.base + q_chip->gpio_chip.ngpio) - 1);
+ return 0;
+
+err_probe:
+ qpnp_gpio_free_chip(q_chip);
+ return ret;
+}
+
+static int qpnp_gpio_remove(struct spmi_device *spmi)
+{
+ struct qpnp_gpio_chip *q_chip = dev_get_drvdata(&spmi->dev);
+
+ return qpnp_gpio_free_chip(q_chip);
+}
+
+static struct of_device_id spmi_match_table[] = {
+ { .compatible = "qcom,qpnp-gpio",
+ },
+ {}
+};
+
+static const struct spmi_device_id qpnp_gpio_id[] = {
+ { "qcom,qpnp-gpio", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spmi, qpnp_gpio_id);
+
+static struct spmi_driver qpnp_gpio_driver = {
+ .driver = {
+ .name = "qcom,qpnp-gpio",
+ .of_match_table = spmi_match_table,
+ },
+ .probe = qpnp_gpio_probe,
+ .remove = qpnp_gpio_remove,
+ .id_table = qpnp_gpio_id,
+};
+
+static int __init qpnp_gpio_init(void)
+{
+ return spmi_driver_register(&qpnp_gpio_driver);
+}
+
+static void __exit qpnp_gpio_exit(void)
+{
+}
+
+MODULE_AUTHOR(
+ "Michael Bohan <mbohan@codeaurora.org>");
+MODULE_DESCRIPTION("QPNP PMIC gpio driver");
+MODULE_LICENSE("GPLv2");
+
+module_init(qpnp_gpio_init);
+module_exit(qpnp_gpio_exit);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 0cadc33..eb017de 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -420,7 +420,7 @@
static unsigned int
adreno_getchipid(struct kgsl_device *device)
{
- if (cpu_is_apq8064())
+ if (cpu_is_apq8064() || cpu_is_msm8930())
return a3xx_getchipid(device);
else
return a2xx_getchipid(device);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 805e0c1..50a6fab 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -903,10 +903,6 @@
struct kgsl_ibdesc *ibdesc;
struct kgsl_context *context;
-#ifdef CONFIG_MSM_KGSL_DRM
- kgsl_gpu_mem_flush(DRM_KGSL_GEM_CACHE_OP_TO_DEV);
-#endif
-
context = kgsl_find_context(dev_priv, param->drawctxt_id);
if (context == NULL) {
result = -EINVAL;
@@ -994,10 +990,6 @@
kfree(ibdesc);
done:
-#ifdef CONFIG_MSM_KGSL_DRM
- kgsl_gpu_mem_flush(DRM_KGSL_GEM_CACHE_OP_FROM_DEV);
-#endif
-
return result;
}
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 3e8aac3..b2fe095 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -160,7 +160,6 @@
#ifdef CONFIG_MSM_KGSL_DRM
extern int kgsl_drm_init(struct platform_device *dev);
extern void kgsl_drm_exit(void);
-extern void kgsl_gpu_mem_flush(int op);
#else
static inline int kgsl_drm_init(struct platform_device *dev)
{
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index e3f6f3b..03f8c42 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -156,22 +156,6 @@
kgsl_cache_range_op(memdesc, cacheop);
}
-/* Flush all the memory mapped in the MMU */
-
-void kgsl_gpu_mem_flush(int op)
-{
- struct drm_kgsl_gem_object *entry;
-
- list_for_each_entry(entry, &kgsl_mem_list, list) {
- kgsl_gem_mem_flush(&entry->memdesc, entry->type, op);
- }
-
- /* Takes care of WT/WC case.
- * More useful when we go barrierless
- */
- dmb();
-}
-
/* TODO:
* Add vsync wait */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index ea67835..406d0c9 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -284,7 +284,7 @@
DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store);
DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
kgsl_pwrctrl_max_gpuclk_store);
-DEVICE_ATTR(pwrnap, 0666, kgsl_pwrctrl_pwrnap_show, kgsl_pwrctrl_pwrnap_store);
+DEVICE_ATTR(pwrnap, 0664, kgsl_pwrctrl_pwrnap_show, kgsl_pwrctrl_pwrnap_store);
DEVICE_ATTR(idle_timer, 0644, kgsl_pwrctrl_idle_timer_show,
kgsl_pwrctrl_idle_timer_store);
DEVICE_ATTR(gpubusy, 0644, kgsl_pwrctrl_gpubusy_show,
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 4c9a239..d0b2a41 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -90,7 +90,7 @@
return ret;
}
-PWRSCALE_ATTR(policy, 0666, pwrscale_policy_show, pwrscale_policy_store);
+PWRSCALE_ATTR(policy, 0664, pwrscale_policy_show, pwrscale_policy_store);
static ssize_t pwrscale_avail_policies_show(struct kgsl_device *device,
char *buf)
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 7264c25..f61a196 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -13,6 +13,8 @@
#include <linux/vmalloc.h>
#include <linux/memory_alloc.h>
#include <asm/cacheflush.h>
+#include <linux/slab.h>
+#include <linux/kmemleak.h>
#include "kgsl.h"
#include "kgsl_sharedmem.h"
@@ -427,6 +429,8 @@
goto done;
}
+ kmemleak_not_leak(memdesc->sg);
+
memdesc->sglen = sglen;
sg_init_table(memdesc->sg, sglen);
@@ -499,6 +503,8 @@
return -ENOMEM;
}
+ kmemleak_not_leak(ptr);
+
protflags = GSL_PT_PAGE_RV;
if (!(flags & KGSL_MEMFLAGS_GPUREADONLY))
protflags |= GSL_PT_PAGE_WV;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 67a1c2d..e54110d 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -17,6 +17,8 @@
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
#include "kgsl_mmu.h"
+#include <linux/slab.h>
+#include <linux/kmemleak.h>
struct kgsl_device;
struct kgsl_process_private;
@@ -86,6 +88,8 @@
if (memdesc->sg == NULL)
return -ENOMEM;
+ kmemleak_not_leak(memdesc->sg);
+
memdesc->sglen = 1;
sg_init_table(memdesc->sg, 1);
sg_set_page(&memdesc->sg[0], page, size, 0);
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index e70a0a5..a4b4b0d 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -48,9 +48,16 @@
depends on MSM_CAMERA
---help---
OV 5M Bayer Sensor with AutoFocus
+
+config AD5046_ACT
+ bool "Lens actuator ad5046"
+ depends on MSM_CAMERA && OV5647
+ ---help---
+ ad5046 lens actuator driver for ov5647.
+ Say Y here if this is msm7627A variant platform.
config WEBCAM_OV7692_QRD
bool "Sensor OV7692 QRD(VGA YUV)"
- depends on MSM_CAMERA && ARCH_MSM7X27A && !MSM_CAMERA_V4L2
+ depends on MSM_CAMERA && ARCH_MSM7X27A
default n
---help---
Omni Vision VGA YUV Sensor for QRD Devices
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 8703669..2843d30 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -39,15 +39,14 @@
obj-$(CONFIG_IMX074) += imx074.o imx074_reg.o
obj-$(CONFIG_MT9E013) += mt9e013.o mt9e013_reg.o
obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
+ obj-$(CONFIG_OV5647) += ov5647.o ov5647_reg.o
obj-$(CONFIG_S5K4E1) += s5k4e1.o s5k4e1_reg.o
+ obj-$(CONFIG_WEBCAM_OV7692) += ov7692.o
+ obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd.o
endif
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
obj-$(CONFIG_MT9D112) += mt9d112.o mt9d112_reg.o
diff --git a/drivers/media/video/msm/actuators/Makefile b/drivers/media/video/msm/actuators/Makefile
index f0a0c69..d492155 100644
--- a/drivers/media/video/msm/actuators/Makefile
+++ b/drivers/media/video/msm/actuators/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_MSM_ACTUATOR) += msm_actuator.o
obj-$(CONFIG_IMX074_ACT) += imx074_act.o
obj-$(CONFIG_DW9712_ACT) += dw9712_act.o
+obj-$(CONFIG_AD5046_ACT) += ad5046_act.o
diff --git a/drivers/media/video/msm/actuators/ad5046_act.c b/drivers/media/video/msm/actuators/ad5046_act.c
new file mode 100644
index 0000000..d99774b
--- /dev/null
+++ b/drivers/media/video/msm/actuators/ad5046_act.c
@@ -0,0 +1,315 @@
+/* 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_actuator.h"
+#include "msm_camera_i2c.h"
+
+#define AD5046_TOTAL_STEPS_NEAR_TO_FAR 32
+static uint8_t mode_mask = 0x09;
+DEFINE_MUTEX(ad5046_act_mutex);
+static struct msm_actuator_ctrl_t ad5046_act_t;
+
+static struct region_params_t g_regions[] = {
+ /* step_bound[0] - macro side boundary
+ * step_bound[1] - infinity side boundary
+ */
+ /* Region 1 */
+ {
+ .step_bound = {AD5046_TOTAL_STEPS_NEAR_TO_FAR, 0},
+ .code_per_step = 2,
+ },
+};
+
+static uint16_t g_scenario[] = {
+ /* MOVE_NEAR and MOVE_FAR dir*/
+ AD5046_TOTAL_STEPS_NEAR_TO_FAR,
+};
+
+static int32_t ad5046_af_i2c_txdata(unsigned short saddr,
+ unsigned char *txdata, int length,
+ struct msm_actuator_ctrl_t *a_ctrl)
+{
+ struct i2c_msg msg[] = {
+ {
+ .addr = saddr,
+ .flags = 0,
+ .len = length,
+ .buf = txdata,
+ },
+ };
+ if (i2c_transfer(a_ctrl->i2c_client.client->adapter, msg, 1) < 0) {
+ pr_err("ad5046_af_i2c_txdata faild 0x%x\n", saddr);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int32_t ad5046_af_i2c_write_b_sensor(struct msm_actuator_ctrl_t *a_ctrl,
+ 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;
+ rc = ad5046_af_i2c_txdata(a_ctrl->i2c_addr, buf, 2, a_ctrl);
+ if (rc < 0)
+ pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+ waddr, bdata);
+
+ return rc;
+}
+
+static int32_t ad5046_wrapper_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
+ int16_t next_lens_position, void *params)
+{
+ uint8_t msb, lsb;
+
+ msb = (next_lens_position & 0xFF00) >> 8;
+ lsb = next_lens_position & 0xFF;
+ ad5046_af_i2c_write_b_sensor(a_ctrl, msb, lsb);
+
+ return 0;
+}
+
+int32_t msm_ad5046_act_move_focus(
+ struct msm_actuator_ctrl_t *a_ctrl,
+ int dir,
+ int32_t num_steps)
+{
+ int32_t rc = 0;
+ int8_t sign_dir = 0;
+ int16_t dest_step_pos = 0;
+ uint8_t code_val_msb, code_val_lsb;
+
+ CDBG("%s called, dir %d, num_steps %d\n",
+ __func__,
+ dir,
+ num_steps);
+
+ /* Determine sign direction */
+ if (dir == MOVE_NEAR)
+ sign_dir = 20;
+ else if (dir == MOVE_FAR)
+ sign_dir = -20;
+ else {
+ pr_err("Illegal focus direction\n");
+ rc = -EINVAL;
+ return rc;
+ }
+
+ /* Determine destination step position */
+ dest_step_pos = a_ctrl->curr_step_pos +
+ (sign_dir * num_steps);
+
+ if (dest_step_pos < 0)
+ dest_step_pos = 0;
+ else if (dest_step_pos > 1023)
+ dest_step_pos = 1023;
+
+ if (dest_step_pos == a_ctrl->curr_step_pos)
+ return rc;
+
+ a_ctrl->curr_step_pos = dest_step_pos;
+
+ code_val_msb = (uint8_t)((dest_step_pos & 0x03FF) >> 4);
+ code_val_lsb = (uint8_t)((dest_step_pos & 0x000F) << 4);
+ code_val_lsb |= mode_mask;
+
+ rc = ad5046_af_i2c_write_b_sensor(a_ctrl, 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 ad5046_set_default_focus(
+ struct msm_actuator_ctrl_t *a_ctrl)
+{
+ uint8_t code_val_msb = 0;
+ uint8_t code_val_lsb = 0;
+ int rc = 0;
+
+ CDBG("ad5046_set_default_focus called\n");
+
+ if (!a_ctrl->step_position_table)
+ a_ctrl->func_tbl.actuator_init_table(a_ctrl);
+
+ a_ctrl->curr_step_pos = 200;
+
+ code_val_msb = (a_ctrl->curr_step_pos & 0x03FF) >> 4;
+ code_val_lsb = (a_ctrl->curr_step_pos & 0x000F) << 4;
+ code_val_lsb |= mode_mask;
+
+ CDBG(KERN_ERR "ad5046_set_default_focus:lens pos = %d",
+ a_ctrl->curr_step_pos);
+ rc = ad5046_af_i2c_write_b_sensor(a_ctrl, 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 const struct i2c_device_id ad5046_act_i2c_id[] = {
+ {"ad5046_act", (kernel_ulong_t)&ad5046_act_t},
+ { }
+};
+
+static int ad5046_act_config(void __user *argp)
+{
+ LINFO("%s called\n", __func__);
+ return (int) msm_actuator_config(&ad5046_act_t, argp);
+}
+
+static int ad5046_i2c_add_driver_table(void)
+{
+ LINFO("%s called\n", __func__);
+ return (int) msm_actuator_init_table(&ad5046_act_t);
+}
+
+int32_t ad5046_act_i2c_probe(
+ struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int32_t rc = 0;
+
+ rc = msm_actuator_i2c_probe(client, id);
+
+ msleep(50);
+
+ return rc;
+}
+static struct i2c_driver ad5046_act_i2c_driver = {
+ .id_table = ad5046_act_i2c_id,
+ .probe = ad5046_act_i2c_probe,
+ .remove = __exit_p(ad5046_act_i2c_remove),
+ .driver = {
+ .name = "ad5046_act",
+ },
+};
+
+static int __init ad5046_i2c_add_driver(void)
+{
+ int rc = 0;
+
+ LINFO("%s called :%x\n", __func__, ad5046_act_t.i2c_addr);
+ rc = i2c_add_driver(ad5046_act_t.i2c_driver);
+ LINFO("%s called:%d %x\n", __func__, rc, ad5046_act_t.i2c_addr);
+ return rc;
+}
+
+static struct v4l2_subdev_core_ops ad5046_act_subdev_core_ops;
+
+static struct v4l2_subdev_ops ad5046_act_subdev_ops = {
+ .core = &ad5046_act_subdev_core_ops,
+};
+
+static int32_t ad5046_act_create_subdevice(
+ void *board_info,
+ void *sdev)
+{
+ int rc = 0;
+
+ struct msm_actuator_info *ptr;
+ LINFO("%s called\n", __func__);
+
+ ptr = board_info;
+ ad5046_act_t.vcm_pwd = ptr->vcm_pwd;
+ ad5046_act_t.vcm_enable = ptr->vcm_enable;
+ LINFO("vcm info: %x %x\n", ad5046_act_t.vcm_pwd,
+ ad5046_act_t.vcm_enable);
+ if (ad5046_act_t.vcm_enable) {
+ rc = gpio_request(ad5046_act_t.vcm_pwd, "ov5647_af");
+ if (!rc) {
+ LINFO("Enable VCM PWD\n");
+ gpio_direction_output(ad5046_act_t.vcm_pwd, 1);
+ }
+ msleep(20);
+
+ }
+ return (int) msm_actuator_create_subdevice(&ad5046_act_t,
+ ptr->board_info,
+ (struct v4l2_subdev *)sdev);
+}
+
+static struct msm_actuator_ctrl_t ad5046_act_t = {
+ .i2c_driver = &ad5046_act_i2c_driver,
+ .i2c_addr = 0x18>>1,
+ .act_v4l2_subdev_ops = &ad5046_act_subdev_ops,
+ .actuator_ext_ctrl = {
+ .a_init_table = ad5046_i2c_add_driver_table,
+ .a_create_subdevice = ad5046_act_create_subdevice,
+ .a_config = ad5046_act_config,
+ },
+
+ .i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+ },
+
+ .set_info = {
+ .total_steps = AD5046_TOTAL_STEPS_NEAR_TO_FAR,
+ },
+
+ .curr_step_pos = 0,
+ .curr_region_index = 0,
+ .initial_code = 0x0,
+ .actuator_mutex = &ad5046_act_mutex,
+
+ .func_tbl = {
+ .actuator_init_table = msm_actuator_init_table,
+ .actuator_move_focus = msm_ad5046_act_move_focus,
+ .actuator_set_default_focus = ad5046_set_default_focus,
+ .actuator_i2c_write = ad5046_wrapper_i2c_write,
+ },
+
+ .get_info = {
+ .focal_length_num = 46,
+ .focal_length_den = 10,
+ .f_number_num = 265,
+ .f_number_den = 100,
+ .f_pix_num = 14,
+ .f_pix_den = 10,
+ .total_f_dist_num = 197681,
+ .total_f_dist_den = 1000,
+ },
+
+ /* Initialize scenario */
+ .ringing_scenario[MOVE_NEAR] = g_scenario,
+ .scenario_size[MOVE_NEAR] = ARRAY_SIZE(g_scenario),
+ .ringing_scenario[MOVE_FAR] = g_scenario,
+ .scenario_size[MOVE_FAR] = ARRAY_SIZE(g_scenario),
+
+ /* Initialize region params */
+ .region_params = g_regions,
+ .region_size = ARRAY_SIZE(g_regions),
+};
+
+subsys_initcall(ad5046_i2c_add_driver);
+MODULE_DESCRIPTION("AD5046 actuator");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/dw9712_act.c b/drivers/media/video/msm/actuators/dw9712_act.c
index 562290f..546cffa 100644
--- a/drivers/media/video/msm/actuators/dw9712_act.c
+++ b/drivers/media/video/msm/actuators/dw9712_act.c
@@ -101,9 +101,9 @@
/* Determine sign direction */
if (dir == MOVE_NEAR)
- sign_dir = 1;
+ sign_dir = 16;
else if (dir == MOVE_FAR)
- sign_dir = -1;
+ sign_dir = -16;
else {
pr_err("Illegal focus direction\n");
rc = -EINVAL;
diff --git a/drivers/media/video/msm/io/msm_io_util.c b/drivers/media/video/msm/io/msm_io_util.c
index 207f8be..a04d6fd 100644
--- a/drivers/media/video/msm/io/msm_io_util.c
+++ b/drivers/media/video/msm/io/msm_io_util.c
@@ -95,32 +95,33 @@
curr_vreg->reg_name);
if (IS_ERR(reg_ptr[i])) {
pr_err("%s: %s get failed\n",
- __func__,
- curr_vreg->reg_name);
+ __func__,
+ curr_vreg->reg_name);
reg_ptr[i] = NULL;
goto vreg_get_fail;
}
if (curr_vreg->type == REG_LDO) {
rc = regulator_set_voltage(
- reg_ptr[i],
- curr_vreg->min_voltage,
- curr_vreg->max_voltage);
+ reg_ptr[i],
+ curr_vreg->min_voltage,
+ curr_vreg->max_voltage);
if (rc < 0) {
- pr_err(
- "%s: %s set voltage failed\n",
- __func__,
- curr_vreg->reg_name);
+ pr_err("%s: %s set voltage failed\n",
+ __func__,
+ curr_vreg->reg_name);
goto vreg_set_voltage_fail;
}
- rc = regulator_set_optimum_mode(
- reg_ptr[i],
- curr_vreg->op_mode);
- if (rc < 0) {
- pr_err(
- "%s: %s set optimum mode failed\n",
- __func__,
- curr_vreg->reg_name);
- goto vreg_set_opt_mode_fail;
+ if (curr_vreg->op_mode) {
+ rc = regulator_set_optimum_mode(
+ reg_ptr[i],
+ curr_vreg->op_mode);
+ if (rc < 0) {
+ pr_err("%s: %s set optimum"
+ "mode failed\n",
+ __func__,
+ curr_vreg->reg_name);
+ goto vreg_set_opt_mode_fail;
+ }
}
}
}
@@ -129,11 +130,12 @@
curr_vreg = &cam_vreg[i];
if (reg_ptr[i]) {
if (curr_vreg->type == REG_LDO) {
- regulator_set_optimum_mode(
- reg_ptr[i], 0);
+ if (curr_vreg->op_mode)
+ regulator_set_optimum_mode(
+ reg_ptr[i], 0);
regulator_set_voltage(
- reg_ptr[i],
- 0, curr_vreg->max_voltage);
+ reg_ptr[i], 0, curr_vreg->
+ max_voltage);
}
regulator_put(reg_ptr[i]);
reg_ptr[i] = NULL;
@@ -171,13 +173,13 @@
for (i = 0; i < num_vreg; i++) {
if (IS_ERR(reg_ptr[i])) {
pr_err("%s: %s null regulator\n",
- __func__, cam_vreg[i].reg_name);
+ __func__, cam_vreg[i].reg_name);
goto disable_vreg;
}
rc = regulator_enable(reg_ptr[i]);
if (rc < 0) {
pr_err("%s: %s enable failed\n",
- __func__, cam_vreg[i].reg_name);
+ __func__, cam_vreg[i].reg_name);
goto disable_vreg;
}
}
@@ -194,6 +196,30 @@
return rc;
}
+static int config_gpio_table(struct msm_camera_gpio_conf *gpio)
+{
+ int rc = 0, i = 0;
+ uint32_t *table_on;
+ uint32_t *table_off;
+ uint32_t len;
+
+ table_on = gpio->camera_on_table;
+ table_off = gpio->camera_off_table;
+ len = gpio->camera_on_table_size;
+
+ for (i = 0; i < len; i++) {
+ rc = gpio_tlmm_config(table_on[i], GPIO_CFG_ENABLE);
+ if (rc) {
+ pr_err("%s not able to get gpio\n", __func__);
+ for (i--; i >= 0; i--)
+ gpio_tlmm_config(table_off[i],
+ GPIO_CFG_ENABLE);
+ break;
+ }
+ }
+ return rc;
+}
+
int msm_camera_request_gpio_table(struct msm_camera_sensor_info *sinfo,
int gpio_en)
{
@@ -201,38 +227,49 @@
struct msm_camera_gpio_conf *gpio_conf =
sinfo->sensor_platform_info->gpio_conf;
- if (gpio_conf->cam_gpio_req_tbl == NULL ||
- gpio_conf->cam_gpio_common_tbl == NULL) {
- pr_err("%s: NULL camera gpio table\n", __func__);
- return -EFAULT;
+ if (!gpio_conf->gpio_no_mux) {
+ if (gpio_conf->cam_gpio_req_tbl == NULL ||
+ gpio_conf->cam_gpio_common_tbl == NULL) {
+ pr_err("%s: NULL camera gpio table\n", __func__);
+ return -EFAULT;
+ }
}
+ if (gpio_conf->gpio_no_mux)
+ config_gpio_table(gpio_conf);
if (gpio_en) {
- if (gpio_conf->cam_gpiomux_conf_tbl != NULL) {
- msm_gpiomux_install(
- (struct msm_gpiomux_config *)gpio_conf->
- cam_gpiomux_conf_tbl,
- gpio_conf->cam_gpiomux_conf_tbl_size);
- }
- rc = gpio_request_array(gpio_conf->cam_gpio_common_tbl,
+ if (!gpio_conf->gpio_no_mux) {
+ if (gpio_conf->cam_gpiomux_conf_tbl != NULL) {
+ msm_gpiomux_install(
+ (struct msm_gpiomux_config *)
+ gpio_conf->cam_gpiomux_conf_tbl,
+ gpio_conf->cam_gpiomux_conf_tbl_size);
+ }
+ rc = gpio_request_array(gpio_conf->cam_gpio_common_tbl,
gpio_conf->cam_gpio_common_tbl_size);
- if (rc < 0) {
- pr_err("%s common gpio request failed\n", __func__);
- return rc;
+ if (rc < 0) {
+ pr_err("%s common gpio request failed\n"
+ , __func__);
+ return rc;
+ }
}
- rc = gpio_request_array(gpio_conf->cam_gpio_req_tbl,
+ if (gpio_conf->cam_gpio_req_tbl_size) {
+ rc = gpio_request_array(gpio_conf->cam_gpio_req_tbl,
gpio_conf->cam_gpio_req_tbl_size);
- if (rc < 0) {
- pr_err("%s camera gpio request failed\n", __func__);
- gpio_free_array(gpio_conf->cam_gpio_common_tbl,
- gpio_conf->cam_gpio_common_tbl_size);
- return rc;
+ if (rc < 0) {
+ pr_err("%s camera gpio"
+ "request failed\n", __func__);
+ gpio_free_array(gpio_conf->cam_gpio_common_tbl,
+ gpio_conf->cam_gpio_common_tbl_size);
+ return rc;
+ }
}
} else {
gpio_free_array(gpio_conf->cam_gpio_req_tbl,
gpio_conf->cam_gpio_req_tbl_size);
- gpio_free_array(gpio_conf->cam_gpio_common_tbl,
- gpio_conf->cam_gpio_common_tbl_size);
+ if (!gpio_conf->gpio_no_mux)
+ gpio_free_array(gpio_conf->cam_gpio_common_tbl,
+ gpio_conf->cam_gpio_common_tbl_size);
}
return rc;
}
@@ -252,7 +289,7 @@
usleep_range(gpio_conf->cam_gpio_set_tbl[i].delay,
gpio_conf->cam_gpio_set_tbl[i].delay + 1000);
}
- } else {
+ } else if (!gpio_conf->gpio_no_mux) {
for (i = gpio_conf->cam_gpio_set_tbl_size - 1; i >= 0; i--) {
if (gpio_conf->cam_gpio_set_tbl[i].flags)
gpio_set_value_cansleep(
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 78c474e..a7f6a8c 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -2392,6 +2392,13 @@
return rc;
}
+ strlcpy(pcam->mctl.media_dev.model, QCAMERA_NAME,
+ sizeof(pcam->mctl.media_dev.model));
+ pcam->mctl.media_dev.dev = &client->dev;
+ rc = media_device_register(&pcam->mctl.media_dev);
+ pvdev->v4l2_dev = &pcam->v4l2_dev;
+ pcam->v4l2_dev.mdev = &pcam->mctl.media_dev;
+
/* init video device's driver interface */
D("sensor name = %s, sizeof(pvdev->name)=%d\n",
pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
@@ -2406,6 +2413,10 @@
pvdev->minor = -1;
pvdev->vfl_type = 1;
+ media_entity_init(&pvdev->entity, 0, NULL, 0);
+ pvdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+ pvdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
+
/* register v4l2 video device to kernel as /dev/videoXX */
D("video_register_device\n");
rc = video_register_device(pvdev,
@@ -2415,6 +2426,7 @@
pr_err("%s: video_register_device failed\n", __func__);
goto reg_fail;
}
+ pvdev->entity.name = video_device_node_name(pvdev);
D("%s: video device registered as /dev/video%d\n",
__func__, pvdev->num);
@@ -2600,6 +2612,15 @@
g_server_dev.mctl_node_info.mctl_node_name
[g_server_dev.mctl_node_info.num_mctl_nodes]);
+ /*Temporary solution to store info in media device structure
+ until we can expand media device structure to support more
+ device info*/
+ snprintf(pcam->mctl.media_dev.serial,
+ sizeof(pcam->mctl.media_dev.serial),
+ "%s-%d-%d", QCAMERA_NAME,
+ sdata->sensor_platform_info->mount_angle,
+ sdata->camera_type);
+
g_server_dev.camera_info.num_cameras++;
g_server_dev.mctl_node_info.num_mctl_nodes++;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index c90ab44..dd65c01 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -218,6 +218,8 @@
/* most-frequently accessed manager object*/
struct msm_sync sync;
+ /*Media device node*/
+ struct media_device media_dev;
/* the following reflect the HW topology information*/
/*mandatory*/
diff --git a/drivers/media/video/msm/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
index bee9f49..63547c8 100644
--- a/drivers/media/video/msm/msm_io_7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
@@ -97,33 +97,6 @@
clk_set_rate(clk, rate);
}
-int msm_sensor_probe_on(struct device *dev)
-{
- int rc = 0;
- struct msm_camera_sensor_info *sinfo = dev->platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
- camio_clk = camdev->ioclk;
-
- rc = camdev->camera_gpio_on();
- if (rc < 0)
- return rc;
-
- rc = msm_camio_clk_enable(CAMIO_CAM_MCLK_CLK);
- if (rc < 0)
- camdev->camera_gpio_off();
-
- return rc;
-}
-
-int msm_sensor_probe_off(struct device *dev)
-{
- struct msm_camera_sensor_info *sinfo = dev->platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-
- camdev->camera_gpio_off();
- return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
-}
-
void msm_camio_vfe_blk_reset(void)
{
uint32_t val;
@@ -152,28 +125,6 @@
usleep_range(10000, 11000);
}
-int msm_camio_probe_on(struct platform_device *pdev)
-{
- int rc = 0;
- const struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
- camio_clk = camdev->ioclk;
-
- rc = camdev->camera_gpio_on();
- if (rc < 0)
- return rc;
- return msm_camio_clk_enable(CAMIO_CAM_MCLK_CLK);
-}
-
-int msm_camio_probe_off(struct platform_device *pdev)
-{
- const struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-
- camdev->camera_gpio_off();
- return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
-}
-
void msm_camio_set_perf_lvl(enum msm_bus_perf_setting perf_setting)
{
switch (perf_setting) {
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index a0ac70d..3e2ddee 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -127,6 +127,10 @@
case VFE_OUTPUTS_JPEG_AND_THUMB:
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
break;
+ case VFE_OUTPUTS_PREVIEW:
+ case VFE_OUTPUTS_VIDEO:
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
+ break;
default:
image_mode = -1;
break;
@@ -402,6 +406,8 @@
stats.cs.buff = stats.buffer;
stats.cs.fd = stats.fd;
break;
+ case MSG_ID_STATS_AWB_AEC:
+ break;
default:
pr_err("%s: Invalid msg type", __func__);
break;
@@ -722,6 +728,7 @@
case CMD_AXI_CFG_ZSL_ALL_CHNLS:
case CMD_RAW_PICT_AXI_CFG:
case CMD_AXI_CFG_PRIM:
+ case CMD_AXI_CFG_SEC:
case CMD_AXI_CFG_PRIM_ALL_CHNLS:
case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC:
case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS:
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 492bcce..628fa62 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -177,7 +177,7 @@
int rc = 0;
struct msm_camsensor_info info;
struct msm_camera_sensor_info *sdata;
-
+ struct msm_cam_v4l2_device *pcam = sync->pcam_sync;
if (copy_from_user(&info,
arg,
sizeof(struct msm_camsensor_info))) {
@@ -191,7 +191,11 @@
memcpy(&info.name[0], sdata->sensor_name, MAX_SENSOR_NAME);
info.flash_enabled = sdata->flash_data->flash_type !=
MSM_CAMERA_FLASH_NONE;
-
+ info.pxlcode = pcam->usr_fmts[0].pxlcode;
+ info.flashtype = sdata->flash_type; /* two flash_types here? */
+ info.camera_type = sdata->camera_type;
+ info.sensor_type = 0; /* need to add YUV/SOC in probing */
+ info.mount_angle = sdata->sensor_platform_info->mount_angle;
/* copy back to user space */
if (copy_to_user((void *)arg,
&info,
@@ -199,7 +203,6 @@
ERR_COPY_TO_USER();
rc = -EFAULT;
}
-
return rc;
}
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 638c51d..e1f4532 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -327,6 +327,9 @@
{VFE_CMD_SCALE_OUTPUT2_CONFIG, VFE_SCALE_OUTPUT2_CONFIG,
QDSP_SCALEQUEUE, "VFE_CMD_SCALE_OUTPUT2_CONFIG",
"VFE_SCALE_OUTPUT2_CONFIG"},
+ {VFE_CMD_CAPTURE_RAW, VFE_START, QDSP_CMDQUEUE,
+ "VFE_CMD_CAPTURE_RAW", "VFE_START"},
+ {VFE_CMD_RECONFIG_VFE, VFE_MAX, VFE_MAX},
};
@@ -400,9 +403,9 @@
unsigned char buf[256];
struct msm_free_buf *free_buf = NULL;
struct vfe_outputack fack;
+ int i;
CDBG("%s:id=%d\n", __func__, id);
-
if (id != VFE_ADSP_EVENT) {
data = kzalloc(len, GFP_KERNEL);
if (!data) {
@@ -434,8 +437,9 @@
cbcr_phy = outch->ping.ch_paddr[1];
CDBG("MSG_OUTPUT_S: %x %x\n",
(unsigned int)y_phy, (unsigned int)cbcr_phy);
- vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_S,
- y_phy, cbcr_phy);
+ vfe_send_outmsg(&vfe2x_ctrl->subdev,
+ MSG_ID_OUTPUT_PRIMARY,
+ y_phy, cbcr_phy);
break;
case MSG_OUTPUT_T:
outch = &vfe2x_ctrl->thumb;
@@ -443,7 +447,8 @@
cbcr_phy = outch->ping.ch_paddr[1];
CDBG("MSG_OUTPUT_T: %x %x\n",
(unsigned int)y_phy, (unsigned int)cbcr_phy);
- vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_T,
+ vfe_send_outmsg(&vfe2x_ctrl->subdev,
+ MSG_ID_OUTPUT_SECONDARY,
y_phy, cbcr_phy);
break;
case MSG_OUTPUT1:
@@ -454,7 +459,7 @@
} else {
free_buf = vfe2x_check_free_buffer(
VFE_MSG_OUTPUT_IRQ,
- VFE_MSG_OUTPUT_P);
+ VFE_MSG_OUTPUT_PRIMARY);
CDBG("free_buf = %x\n", (unsigned int) free_buf);
if (free_buf) {
fack.header = VFE_OUTPUT2_ACK;
@@ -489,7 +494,22 @@
CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n",
y_phy, cbcr_phy);
-
+ if (free_buf) {
+ for (i = 0; i < 3; i++) {
+ if (vfe2x_ctrl->free_buf.buf[i].
+ ch_paddr[0] == y_phy) {
+ vfe2x_ctrl->free_buf.
+ buf[i].ch_paddr[0] =
+ free_buf->ch_paddr[0];
+ vfe2x_ctrl->free_buf.
+ buf[i].ch_paddr[1] =
+ free_buf->ch_paddr[1];
+ break;
+ }
+ }
+ if (i == 3)
+ CDBG("Address doesnt match\n");
+ }
memcpy(((struct vfe_frame_extra *)extdata),
&((struct vfe_endframe *)data)->extra,
sizeof(struct vfe_frame_extra));
@@ -497,8 +517,8 @@
vfe2x_ctrl->vfeFrameId =
((struct vfe_frame_extra *)extdata)->frame_id;
vfe_send_outmsg(&vfe2x_ctrl->subdev,
- MSG_ID_OUTPUT_P,
- y_phy, cbcr_phy);
+ MSG_ID_OUTPUT_PRIMARY,
+ y_phy, cbcr_phy);
break;
case MSG_RESET_ACK:
case MSG_START_ACK:
@@ -509,11 +529,55 @@
vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id);
if (id == MSG_START_ACK)
vfe2x_ctrl->vfe_started = 1;
+ if (id == MSG_VFE_ERROR) {
+ uint16_t *ptr;
+ struct vfe_error_msg *VFE_ErrorMessageBuffer
+ = data;
+ ptr = data;
+ CDBG("Error: %x %x\n", ptr[0], ptr[1]);
+ CDBG("CAMIF_Error = %d\n",
+ VFE_ErrorMessageBuffer->camif_error);
+ CDBG("output1YBusOverflow = %d\n",
+ VFE_ErrorMessageBuffer->
+ output1ybusoverflow);
+ CDBG("output1CbCrBusOverflow = %d\n",
+ VFE_ErrorMessageBuffer->
+ output1cbcrbusoverflow);
+ CDBG("output2YBusOverflow = %d\n",
+ VFE_ErrorMessageBuffer->
+ output2ybusoverflow);
+ CDBG("output2CbCrBusOverflow = %d\n",
+ VFE_ErrorMessageBuffer->
+ output2cbcrbusoverflow);
+ CDBG("autofocusStatBusOverflow = %d\n",
+ VFE_ErrorMessageBuffer->
+ autofocusstatbusoverflow);
+ CDBG("WB_EXPStatBusOverflow = %d\n",
+ VFE_ErrorMessageBuffer->
+ wb_expstatbusoverflow);
+ CDBG("AXIError = %d\n",
+ VFE_ErrorMessageBuffer->
+ axierror);
+ CDBG("CAMIF_Staus = %d\n",
+ VFE_ErrorMessageBuffer->
+ camif_staus);
+ CDBG("pixel_count = %d\n",
+ VFE_ErrorMessageBuffer->
+ pixel_count);
+ CDBG("line_count = %d\n",
+ VFE_ErrorMessageBuffer->
+ line_count);
+ }
break;
case MSG_SOF:
vfe2x_ctrl->vfeFrameId++;
if (vfe2x_ctrl->vfeFrameId == 0)
vfe2x_ctrl->vfeFrameId = 1; /* wrapped back */
+ if ((op_mode & SNAPSHOT_MASK_MODE) && !raw_mode) {
+ pr_err("Ignore SOF for snapshot\n");
+ kfree(data);
+ return;
+ }
vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SOF_ACK);
if (raw_mode)
vfe2x_send_isp_msg(vfe2x_ctrl,
@@ -584,9 +648,13 @@
unsigned long *bptr;
int cnt;
int rc = 0;
+ int o_mode = 0;
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ o_mode = SNAPSHOT_MASK_MODE;
- if (mode == OUTPUT_1) {
+ if (mode == OUTPUT_SEC) {
+ /* Thumbnail */
ao->output1buffer1_y_phy = ad->ping.ch_paddr[0];
ao->output1buffer1_cbcr_phy = ad->ping.ch_paddr[1];
ao->output1buffer2_y_phy = ad->pong.ch_paddr[0];
@@ -598,9 +666,8 @@
*bptr = ad->pong.ch_paddr[1];
bptr++;
}
- }
-
- if (mode == OUTPUT_2) {
+ } else if (mode == OUTPUT_PRIM && o_mode != SNAPSHOT_MASK_MODE) {
+ /* Preview */
ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
@@ -614,9 +681,30 @@
*bptr = ad->pong.ch_paddr[1];
bptr++;
}
- }
-
- if (mode == OUTPUT_1_AND_2) {
+ CDBG("%x %x\n", (unsigned int)ao->output2buffer1_y_phy,
+ (unsigned int)ao->output2buffer1_cbcr_phy);
+ CDBG("%x %x\n", (unsigned int)ao->output2buffer2_y_phy,
+ (unsigned int)ao->output2buffer2_cbcr_phy);
+ CDBG("%x %x\n", (unsigned int)ao->output2buffer3_y_phy,
+ (unsigned int)ao->output2buffer3_cbcr_phy);
+ CDBG("%x %x\n", (unsigned int)ao->output2buffer4_y_phy,
+ (unsigned int)ao->output2buffer4_cbcr_phy);
+ CDBG("%x %x\n", (unsigned int)ao->output2buffer5_y_phy,
+ (unsigned int)ao->output2buffer5_cbcr_phy);
+ CDBG("%x %x\n", (unsigned int)ao->output2buffer6_y_phy,
+ (unsigned int)ao->output2buffer6_cbcr_phy);
+ CDBG("%x %x\n", (unsigned int)ao->output2buffer7_y_phy,
+ (unsigned int)ao->output2buffer7_cbcr_phy);
+ vfe2x_ctrl->free_buf.buf[0].ch_paddr[0] = ad->ping.ch_paddr[0];
+ vfe2x_ctrl->free_buf.buf[0].ch_paddr[1] = ad->ping.ch_paddr[1];
+ vfe2x_ctrl->free_buf.buf[1].ch_paddr[0] = ad->pong.ch_paddr[0];
+ vfe2x_ctrl->free_buf.buf[1].ch_paddr[1] = ad->pong.ch_paddr[1];
+ vfe2x_ctrl->free_buf.buf[2].ch_paddr[0] =
+ ad->free_buf.ch_paddr[0];
+ vfe2x_ctrl->free_buf.buf[2].ch_paddr[1] =
+ ad->free_buf.ch_paddr[1];
+ } else if (mode == OUTPUT_PRIM && o_mode == SNAPSHOT_MASK_MODE) {
+ vfe2x_ctrl->reconfig_vfe = 0;
if (raw_mode) {
ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[0];
@@ -632,7 +720,7 @@
for (cnt = 0; cnt < 6; cnt++) {
*bptr = ad->pong.ch_paddr[0];
bptr++;
- *bptr = ad->pong.ch_paddr[0];
+ *bptr = ad->pong.ch_paddr[1];
bptr++;
}
}
@@ -664,12 +752,12 @@
vfe2x_subdev_notify(id, path);
if (op_mode & SNAPSHOT_MASK_MODE) {
- if (path == VFE_MSG_OUTPUT_S)
+ if (path == VFE_MSG_OUTPUT_PRIMARY)
outch = &vfe2x_ctrl->snap;
- else if (path == VFE_MSG_OUTPUT_T)
+ else if (path == VFE_MSG_OUTPUT_SECONDARY)
outch = &vfe2x_ctrl->thumb;
} else {
- if (path == VFE_MSG_OUTPUT_P)
+ if (path == VFE_MSG_OUTPUT_PRIMARY)
outch = &vfe2x_ctrl->prev;
}
if (outch->free_buf.ch_paddr[0])
@@ -684,15 +772,14 @@
int rc = 0;
vfe2x_subdev_notify(id, path);
-
CDBG("Opmode = %d\n", op_mode);
if (op_mode & SNAPSHOT_MASK_MODE) {
- if (path == VFE_MSG_OUTPUT_S)
+ if (path == VFE_MSG_OUTPUT_PRIMARY)
outch = &vfe2x_ctrl->snap;
- else if (path == VFE_MSG_OUTPUT_T)
+ else if (path == VFE_MSG_OUTPUT_SECONDARY)
outch = &vfe2x_ctrl->thumb;
} else {
- if (path == VFE_MSG_OUTPUT_P)
+ if (path == VFE_MSG_OUTPUT_PRIMARY)
outch = &vfe2x_ctrl->prev;
}
if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
@@ -711,13 +798,14 @@
struct buf_info *ch = NULL;
CDBG("path = %d op_mode = %d\n", path, op_mode);
+ /* TODO: Remove Mode specific stuff */
if (op_mode & SNAPSHOT_MASK_MODE) {
- if (path == VFE_MSG_OUTPUT_T)
+ if (path == VFE_MSG_OUTPUT_SECONDARY)
ch = &vfe2x_ctrl->thumb;
- else if (path == VFE_MSG_OUTPUT_S)
+ else if (path == VFE_MSG_OUTPUT_PRIMARY)
ch = &vfe2x_ctrl->snap;
} else {
- if (path == VFE_MSG_OUTPUT_P)
+ if (path == VFE_MSG_OUTPUT_PRIMARY)
ch = &vfe2x_ctrl->prev;
}
@@ -777,11 +865,11 @@
if (op_mode & SNAPSHOT_MASK_MODE) {
free_buf = vfe2x_check_free_buffer(
VFE_MSG_OUTPUT_IRQ,
- VFE_MSG_OUTPUT_T);
+ VFE_MSG_OUTPUT_SECONDARY);
} else {
free_buf = vfe2x_check_free_buffer(
VFE_MSG_OUTPUT_IRQ,
- VFE_MSG_OUTPUT_P);
+ VFE_MSG_OUTPUT_PRIMARY);
if (free_buf) {
fack.header = VFE_OUTPUT2_ACK;
@@ -875,6 +963,7 @@
break;
case CMD_STATS_AF_ENABLE:
case CMD_STATS_AF_AXI_CFG: {
+ CDBG("CMD_STATS_AF_ENABLE CMD_STATS_AF_AXI_CFG\n");
axid = data;
if (!axid) {
rc = -EFAULT;
@@ -908,6 +997,7 @@
goto config_failure;
}
*(uint32_t *)sfcfg = header;
+ CDBG("Number of buffers = %d\n", axid->bufnum1);
if (axid->bufnum1 > 0) {
regptr = &axid->region[0];
@@ -973,6 +1063,11 @@
op_mode = vfe2x_ctrl->start_cmd.mode_of_operation;
return rc;
}
+ if (vfecmd.id == VFE_CMD_RECONFIG_VFE) {
+ CDBG("VFE is RECONFIGURED\n");
+ vfe2x_ctrl->reconfig_vfe = 1;
+ return 0;
+ }
if (vfecmd.length > 256 - 4) {
cmd_data_alloc =
cmd_data = kmalloc(vfecmd.length + 4, GFP_ATOMIC);
@@ -1002,13 +1097,12 @@
if (queue == QDSP_CMDQUEUE) {
switch (vfecmd.id) {
case VFE_CMD_RESET:
- msm_adsp_enable(qcam_mod);
- msm_adsp_enable(vfe_mod);
msm_camio_vfe_blk_reset();
vfestopped = 0;
break;
case VFE_CMD_START:
case VFE_CMD_CAPTURE:
+ case VFE_CMD_CAPTURE_RAW:
spin_lock_irqsave(&vfe2x_ctrl->table_lock,
flags);
if (!list_empty(&vfe2x_ctrl->table_q)) {
@@ -1041,8 +1135,60 @@
} /* QDSP_CMDQUEUE */
}
break;
- case CMD_AXI_CFG_PREVIEW: {
- CDBG("CMD_AXI_CFG_PREVIEW\n");
+ case CMD_AXI_CFG_SEC: {
+ CDBG("CMD_AXI_CFG_SEC\n");
+ raw_mode = 0;
+ axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+ if (!axio) {
+ pr_err("NULL axio\n");
+ rc = -ENOMEM;
+ goto config_failure;
+ }
+
+ if (copy_from_user((char *)axio + 4,
+ (void __user *)(vfecmd.value),
+ sizeof(struct axiout))) {
+ CDBG("copy_from_user failed\n");
+ rc = -EFAULT;
+ goto config_done;
+ }
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ rc = vfe2x_configure_pingpong_buffers(
+ VFE_MSG_V2X_CAPTURE,
+ VFE_MSG_OUTPUT_SECONDARY);
+ else
+ rc = vfe2x_configure_pingpong_buffers(
+ VFE_MSG_V2X_PREVIEW,
+ VFE_MSG_OUTPUT_SECONDARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+
+ if (!(op_mode & SNAPSHOT_MASK_MODE))
+ free_buf = vfe2x_check_free_buffer(
+ VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_SECONDARY);
+ header = cmds_map[vfecmd.id].vfe_id;
+ queue = cmds_map[vfecmd.id].queue;
+ if (header == -1 && queue == -1) {
+ rc = -EFAULT;
+ goto config_done;
+ }
+ *(uint32_t *)axio = header;
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ vfe_7x_config_axi(OUTPUT_SEC,
+ &vfe2x_ctrl->thumb, axio);
+ else
+ vfe_7x_config_axi(OUTPUT_SEC,
+ &vfe2x_ctrl->video, axio);
+ cmd_data = axio;
+ }
+ break;
+ case CMD_AXI_CFG_PRIM: {
+ CDBG("CMD_AXI_CFG_PRIM : %d\n", op_mode);
raw_mode = 0;
axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
if (!axio) {
@@ -1058,18 +1204,40 @@
rc = -EFAULT;
goto config_done;
}
- rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_PREVIEW,
- VFE_MSG_OUTPUT_P);
- if (rc < 0) {
- pr_err("%s error configuring pingpong buffers"
- " for preview", __func__);
- rc = -EINVAL;
- goto config_done;
- }
-
- free_buf = vfe2x_check_free_buffer(
+ if (!vfe2x_ctrl->reconfig_vfe) {
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ rc = vfe2x_configure_pingpong_buffers(
+ VFE_MSG_V2X_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY);
+ else
+ rc = vfe2x_configure_pingpong_buffers(
+ VFE_MSG_V2X_PREVIEW,
+ VFE_MSG_OUTPUT_PRIMARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ if (!(op_mode & SNAPSHOT_MASK_MODE))
+ free_buf = vfe2x_check_free_buffer(
VFE_MSG_OUTPUT_IRQ,
- VFE_MSG_OUTPUT_P);
+ VFE_MSG_OUTPUT_PRIMARY);
+ } else {
+ vfe2x_ctrl->prev.ping.ch_paddr[0] =
+ vfe2x_ctrl->free_buf.buf[0].ch_paddr[0];
+ vfe2x_ctrl->prev.ping.ch_paddr[1] =
+ vfe2x_ctrl->free_buf.buf[0].ch_paddr[1];
+ vfe2x_ctrl->prev.pong.ch_paddr[0] =
+ vfe2x_ctrl->free_buf.buf[1].ch_paddr[0];
+ vfe2x_ctrl->prev.pong.ch_paddr[1] =
+ vfe2x_ctrl->free_buf.buf[1].ch_paddr[1];
+ vfe2x_ctrl->prev.free_buf.ch_paddr[0] =
+ vfe2x_ctrl->free_buf.buf[2].ch_paddr[0];
+ vfe2x_ctrl->prev.free_buf.ch_paddr[1] =
+ vfe2x_ctrl->free_buf.buf[2].ch_paddr[1];
+ vfe2x_ctrl->reconfig_vfe = 0;
+ }
header = cmds_map[vfecmd.id].vfe_id;
queue = cmds_map[vfecmd.id].queue;
if (header == -1 && queue == -1) {
@@ -1077,7 +1245,86 @@
goto config_done;
}
*(uint32_t *)axio = header;
- vfe_7x_config_axi(OUTPUT_2, &vfe2x_ctrl->prev, axio);
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ vfe_7x_config_axi(OUTPUT_PRIM, &vfe2x_ctrl->snap, axio);
+ else
+ vfe_7x_config_axi(OUTPUT_PRIM, &vfe2x_ctrl->prev, axio);
+ cmd_data = axio;
+ }
+ break;
+ case CMD_AXI_CFG_SEC|CMD_AXI_CFG_PRIM: {
+ CDBG("CMD_AXI_CFG_SEC|PRIM\n");
+ raw_mode = 0;
+ axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
+ if (!axio) {
+ pr_err("NULL axio\n");
+ rc = -ENOMEM;
+ goto config_failure;
+ }
+
+ if (copy_from_user((char *)axio + 4,
+ (void __user *)(vfecmd.value),
+ sizeof(struct axiout))) {
+ pr_err("copy_from_user failed\n");
+ rc = -EFAULT;
+ goto config_done;
+ }
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ rc = vfe2x_configure_pingpong_buffers(
+ VFE_MSG_V2X_CAPTURE,
+ VFE_MSG_OUTPUT_SECONDARY);
+ else
+ rc = vfe2x_configure_pingpong_buffers(
+ VFE_MSG_V2X_PREVIEW,
+ VFE_MSG_OUTPUT_SECONDARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+
+ if (!(op_mode & SNAPSHOT_MASK_MODE))
+ free_buf = vfe2x_check_free_buffer(
+ VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_SECONDARY);
+ header = cmds_map[vfecmd.id].vfe_id;
+ queue = cmds_map[vfecmd.id].queue;
+ if (header == -1 && queue == -1) {
+ rc = -EFAULT;
+ goto config_done;
+ }
+ *(uint32_t *)axio = header;
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ vfe_7x_config_axi(OUTPUT_SEC, &vfe2x_ctrl->thumb, axio);
+ else
+ vfe_7x_config_axi(OUTPUT_SEC, &vfe2x_ctrl->prev, axio);
+
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ rc = vfe2x_configure_pingpong_buffers(
+ VFE_MSG_V2X_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY);
+ else
+ rc = vfe2x_configure_pingpong_buffers(
+ VFE_MSG_V2X_PREVIEW,
+ VFE_MSG_OUTPUT_PRIMARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+
+ if (!(op_mode & SNAPSHOT_MASK_MODE))
+ free_buf = vfe2x_check_free_buffer(
+ VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_PRIMARY);
+ if (op_mode & SNAPSHOT_MASK_MODE)
+ vfe_7x_config_axi(OUTPUT_PRIM,
+ &vfe2x_ctrl->snap, axio);
+ else
+ vfe_7x_config_axi(OUTPUT_PRIM,
+ &vfe2x_ctrl->prev, axio);
cmd_data = axio;
}
break;
@@ -1099,7 +1346,7 @@
header = cmds_map[vfecmd.id].vfe_id;
queue = cmds_map[vfecmd.id].queue;
rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
- VFE_MSG_OUTPUT_S);
+ VFE_MSG_OUTPUT_PRIMARY);
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for preview", __func__);
@@ -1111,50 +1358,7 @@
goto config_done;
}
*(uint32_t *)axio = header;
- vfe_7x_config_axi(OUTPUT_1_AND_2, &vfe2x_ctrl->snap, axio);
- cmd_data = axio;
- }
- break;
- case CMD_AXI_CFG_SNAP: {
- raw_mode = 0;
- CDBG("CMD_AXI_CFG_SNAP :%d\n", op_mode);
- axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
- if (!axio) {
- rc = -ENOMEM;
- goto config_failure;
- }
-
- if (copy_from_user((char *)axio + 4,
- (void __user *)(vfecmd.value),
- sizeof(struct axiout))) {
- rc = -EFAULT;
- goto config_done;
- }
- header = cmds_map[vfecmd.id].vfe_id;
- queue = cmds_map[vfecmd.id].queue;
- rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
- VFE_MSG_OUTPUT_S);
- if (rc < 0) {
- pr_err("%s error configuring pingpong buffers"
- " for preview", __func__);
- rc = -EINVAL;
- goto config_done;
- }
- if (header == -1 && queue == -1) {
- rc = -EFAULT;
- goto config_done;
- }
- *(uint32_t *)axio = header;
- vfe_7x_config_axi(OUTPUT_1_AND_2, &vfe2x_ctrl->snap, axio);
- rc = vfe2x_configure_pingpong_buffers(VFE_MSG_V2X_CAPTURE,
- VFE_MSG_OUTPUT_T);
- if (rc < 0) {
- pr_err("%s error configuring pingpong buffers"
- " for preview", __func__);
- rc = -EINVAL;
- goto config_done;
- }
- vfe_7x_config_axi(OUTPUT_1, &vfe2x_ctrl->thumb, axio);
+ vfe_7x_config_axi(OUTPUT_PRIM, &vfe2x_ctrl->snap, axio);
cmd_data = axio;
}
break;
@@ -1169,6 +1373,7 @@
CDBG("send adsp command = %d\n", *(uint32_t *)cmd_data);
if (queue == QDSP_TABLEQUEUE &&
vfe2x_ctrl->tableack_pending) {
+ CDBG("store table cmd\n");
table_pending = kzalloc(sizeof(struct table_cmd), GFP_ATOMIC);
if (!table_pending) {
rc = -ENOMEM;
@@ -1188,12 +1393,14 @@
spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
} else {
if (queue == QDSP_TABLEQUEUE) {
+ CDBG("sending table cmd\n");
spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags);
rc = msm_adsp_write(vfe_mod, queue,
cmd_data, vfecmd.length + 4);
vfe2x_ctrl->tableack_pending = 1;
spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags);
} else {
+ CDBG("send n-table cmd\n");
if (*(uint32_t *)cmd_data == VFE_OUTPUT2_ACK) {
uint32_t *ptr = cmd_data;
CDBG("%x %x %x\n", ptr[0], ptr[1], ptr[2]);
@@ -1263,6 +1470,8 @@
rc = -EBUSY;
goto get_vfe_fail;
}
+ msm_adsp_enable(qcam_mod);
+ msm_adsp_enable(vfe_mod);
return 0;
get_vfe_fail:
@@ -1287,6 +1496,7 @@
void msm_vfe_subdev_release(struct platform_device *pdev)
{
+ CDBG("msm_cam_clk_enable: disable vfe_clk\n");
msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 0);
vfe_syncdata = NULL;
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.h b/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
index 0f7fb60..90237bd 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.h
@@ -51,6 +51,10 @@
struct msm_free_buf free_buf;
} __packed;
+struct prev_free_buf_info {
+ struct msm_free_buf buf[3];
+};
+
struct vfe_cmd_start {
uint32_t input_source:1;
uint32_t mode_of_operation:1;
@@ -76,9 +80,11 @@
struct vfe2x_ctrl_type {
struct buf_info prev;
+ struct buf_info video;
struct buf_info snap;
struct buf_info raw;
struct buf_info thumb;
+ struct prev_free_buf_info free_buf;
spinlock_t table_lock;
struct list_head table_q;
@@ -97,6 +103,7 @@
struct platform_device *pdev;
struct clk *vfe_clk[3];
spinlock_t sd_notify_lock;
+ uint32_t reconfig_vfe;
} __packed;
struct vfe_frame_extra {
@@ -379,6 +386,21 @@
int state;
int timeout;
};
+struct vfe_error_msg {
+ unsigned int camif_error:1;
+ unsigned int output1ybusoverflow:1;
+ unsigned int output1cbcrbusoverflow:1;
+ unsigned int output2ybusoverflow:1;
+ unsigned int output2cbcrbusoverflow:1;
+ unsigned int autofocusstatbusoverflow:1;
+ unsigned int wb_expstatbusoverflow:1;
+ unsigned int axierror:1;
+ unsigned int /* reserved */ : 24;
+ unsigned int camif_staus:1;
+ unsigned int pixel_count:14;
+ unsigned int line_count:14;
+ unsigned int /*reserved */ : 3;
+} __packed;
static struct msm_free_buf *vfe2x_check_free_buffer(int id, int path);
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index cfc0fe0..ef8993c 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -10,3 +10,5 @@
obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
obj-$(CONFIG_WEBCAM_OV9726) += ov9726_v4l2.o
+obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd_v4l2.o
+obj-$(CONFIG_OV5647) += ov5647_v4l2.o
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index cade3d6..e40a528 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -173,6 +173,100 @@
return 0;
}
+int32_t msm_sensor_setting3(struct msm_sensor_ctrl_t *s_ctrl,
+ int update_type, int res)
+{
+ int32_t rc = 0;
+ static int csi_config;
+ if (update_type == MSM_SENSOR_REG_INIT) {
+ CDBG("Register INIT\n");
+ s_ctrl->curr_csi_params = NULL;
+ csi_config = 0;
+ msm_camera_i2c_write(
+ s_ctrl->sensor_i2c_client,
+ 0x0e, 0x08,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ } else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
+ CDBG("PERIODIC : %d\n", res);
+ if (res == 0)
+ return 0;
+ if (!csi_config) {
+ msm_sensor_write_conf_array(
+ s_ctrl->sensor_i2c_client,
+ s_ctrl->msm_sensor_reg->mode_settings, res);
+ msleep(30);
+ s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
+ CDBG("CSI config in progress\n");
+ v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_CSIC_CFG,
+ s_ctrl->curr_csic_params);
+ CDBG("CSI config is done\n");
+ mb();
+ msleep(30);
+ msm_camera_i2c_write(
+ s_ctrl->sensor_i2c_client,
+ 0x0e, 0x00,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ csi_config = 1;
+ }
+ msleep(50);
+ }
+ return rc;
+}
+
+int32_t msm_sensor_setting2(struct msm_sensor_ctrl_t *s_ctrl,
+ int update_type, int res)
+{
+ int32_t rc = 0;
+ static int csi_config;
+
+ s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
+ if (csi_config == 0 || res == 0)
+ msleep(66);
+ else
+ msleep(266);
+ if (update_type == MSM_SENSOR_REG_INIT) {
+ CDBG("Register INIT\n");
+ s_ctrl->curr_csi_params = NULL;
+ msm_camera_i2c_write(
+ s_ctrl->sensor_i2c_client,
+ 0x103, 0x1,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msm_sensor_enable_debugfs(s_ctrl);
+ msm_sensor_write_init_settings(s_ctrl);
+ csi_config = 0;
+ } else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
+ CDBG("PERIODIC : %d\n", res);
+ msm_sensor_write_conf_array(
+ s_ctrl->sensor_i2c_client,
+ s_ctrl->msm_sensor_reg->mode_settings, res);
+ msleep(30);
+ if (!csi_config) {
+ s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
+ CDBG("CSI config in progress\n");
+ v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_CSIC_CFG,
+ s_ctrl->curr_csic_params);
+ CDBG("CSI config is done\n");
+ mb();
+ msleep(30);
+ csi_config = 1;
+ msm_camera_i2c_write(
+ s_ctrl->sensor_i2c_client,
+ 0x100, 0x1,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ }
+ msm_camera_i2c_write(
+ s_ctrl->sensor_i2c_client,
+ 0x4800, 0x4,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ msleep(266);
+ s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
+ msleep(50);
+ }
+ return rc;
+}
+
int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
int update_type, int res)
{
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 2b1be1e..d1a6cee 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -226,6 +226,12 @@
int32_t msm_sensor_setting1(struct msm_sensor_ctrl_t *s_ctrl,
int update_type, int res);
+int32_t msm_sensor_setting2(struct msm_sensor_ctrl_t *s_ctrl,
+ int update_type, int res);
+
+int32_t msm_sensor_setting3(struct msm_sensor_ctrl_t *s_ctrl,
+ int update_type, int res);
+
int msm_sensor_enable_debugfs(struct msm_sensor_ctrl_t *s_ctrl);
long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
@@ -233,6 +239,10 @@
struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
+#if (defined CONFIG_WEBCAM_OV7692_QRD || defined CONFIG_OV5647)
+ extern int lcd_camera_power_onoff(int on);
+#endif
+
#define VIDIOC_MSM_SENSOR_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 10, void __user *)
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
index 924cbc9..a6bc653 100644
--- a/drivers/media/video/msm/sensors/mt9e013_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -28,12 +28,6 @@
};
static struct msm_camera_i2c_reg_conf mt9e013_prev_settings[] = {
- {0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
- {0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
- {0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
- {0x0306, 0x003A},/*PLL_MULTIPLIER*/
- {0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
- {0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
/*Output Size (1632x1224)*/
{0x0344, 0x0008},/*X_ADDR_START*/
{0x0348, 0x0CC9},/*X_ADDR_END*/
@@ -56,12 +50,6 @@
};
static struct msm_camera_i2c_reg_conf mt9e013_snap_settings[] = {
- {0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
- {0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
- {0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
- {0x0306, 0x003A},/*PLL_MULTIPLIER*/
- {0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
- {0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
/*Output Size (3264x2448)*/
{0x0344, 0x0000},/*X_ADDR_START */
{0x0348, 0x0CCF},/*X_ADDR_END*/
@@ -172,14 +160,14 @@
{0x31B8, 0x0E3F},/*MIPI_TIMING_2*/
/*set data to RAW10 format*/
{0x0112, 0x0A0A},/*CCP_DATA_FORMAT*/
- {0x30F0, 0x8000},/*VCM CONTROL*/
+ {0x30F0, 0x800D},/*VCM CONTROL*/
{0x3044, 0x0590},
{0x306E, 0xFC80},
{0x30B2, 0xC000},
{0x30D6, 0x0800},
{0x316C, 0xB42F},
- {0x316E, 0x869C},
+ {0x316E, 0x869A},
{0x3170, 0x210E},
{0x317A, 0x010E},
{0x31E0, 0x1FB9},
@@ -188,17 +176,19 @@
{0x37C2, 0x0000},
{0x37C4, 0x0000},
{0x37C6, 0x0000},
+ {0x3E00, 0x0011},
{0x3E02, 0x8801},
- {0x3E04, 0x2301},
+ {0x3E04, 0x2801},
{0x3E06, 0x8449},
{0x3E08, 0x6841},
{0x3E0A, 0x400C},
{0x3E0C, 0x1001},
- {0x3E0E, 0x2103},
+ {0x3E0E, 0x2603},
{0x3E10, 0x4B41},
- {0x3E12, 0x4B26},
+ {0x3E12, 0x4B24},
+ {0x3E14, 0xA3CF},
{0x3E16, 0x8802},
- {0x3E18, 0x84FF},
+ {0x3E18, 0x8401},
{0x3E1A, 0x8601},
{0x3E1C, 0x8401},
{0x3E1E, 0x840A},
@@ -207,41 +197,56 @@
{0x3E24, 0x00FF},
{0x3E26, 0x0088},
{0x3E28, 0x2E8A},
+ {0x3E30, 0x0000},
{0x3E32, 0x8801},
- {0x3E34, 0x4024},
+ {0x3E34, 0x4029},
+ {0x3E36, 0x00FF},
{0x3E38, 0x8469},
- {0x3E3C, 0x2301},
- {0x3E3E, 0x3E25},
+ {0x3E3A, 0x00FF},
+ {0x3E3C, 0x2801},
+ {0x3E3E, 0x3E2A},
{0x3E40, 0x1C01},
- {0x3E42, 0x8486},
+ {0x3E42, 0xFF84},
{0x3E44, 0x8401},
- {0x3E46, 0x00FF},
+ {0x3E46, 0x0C01},
{0x3E48, 0x8401},
- {0x3E4A, 0x8601},
+ {0x3E4A, 0x00FF},
{0x3E4C, 0x8402},
- {0x3E4E, 0x00FF},
- {0x3E50, 0x6623},
+ {0x3E4E, 0x8984},
+ {0x3E50, 0x6628},
{0x3E52, 0x8340},
{0x3E54, 0x00FF},
{0x3E56, 0x4A42},
- {0x3E58, 0x2203},
- {0x3E5A, 0x674D},
- {0x3E5C, 0x3F25},
+ {0x3E58, 0x2703},
+ {0x3E5A, 0x6752},
+ {0x3E5C, 0x3F2A},
{0x3E5E, 0x846A},
{0x3E60, 0x4C01},
{0x3E62, 0x8401},
{0x3E66, 0x3901},
+ {0x3E90, 0x2C01},
+ {0x3E98, 0x2B02},
+ {0x3E92, 0x2A04},
+ {0x3E94, 0x2509},
+ {0x3E96, 0x0000},
+ {0x3E9A, 0x2905},
+ {0x3E9C, 0x00FF},
{0x3ECC, 0x00EB},
{0x3ED0, 0x1E24},
{0x3ED4, 0xAFC4},
{0x3ED6, 0x909B},
- {0x3ED8, 0x0006},
- {0x3EDA, 0xCFC6},
- {0x3EDC, 0x4FE4},
{0x3EE0, 0x2424},
{0x3EE2, 0x9797},
{0x3EE4, 0xC100},
- {0x3EE6, 0x0540}
+ {0x3EE6, 0x0540},
+ {0x3174, 0x8000},
+ /* PLL settings */
+ {0x0300, 0x0004},/*VT_PIX_CLK_DIV*/
+ {0x0302, 0x0001},/*VT_SYS_CLK_DIV*/
+ {0x0304, 0x0002},/*PRE_PLL_CLK_DIV*/
+ {0x0306, 0x003A},/*PLL_MULTIPLIER*/
+ {0x0308, 0x000A},/*OP_PIX_CLK_DIV*/
+ {0x030A, 0x0001},/*OP_SYS_CLK_DIV*/
};
static struct v4l2_subdev_info mt9e013_subdev_info[] = {
@@ -498,6 +503,7 @@
.sensor_v4l2_subdev_info_size = ARRAY_SIZE(mt9e013_subdev_info),
.sensor_v4l2_subdev_ops = &mt9e013_subdev_ops,
.func_tbl = &mt9e013_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
};
module_init(msm_sensor_init_module);
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
new file mode 100644
index 0000000..052305c
--- /dev/null
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -0,0 +1,634 @@
+/* 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_sensor.h"
+#define SENSOR_NAME "ov5647"
+#define PLATFORM_DRIVER_NAME "msm_camera_ov5647"
+#define ov5647_obj ov5647_##obj
+
+static struct msm_sensor_ctrl_t ov5647_s_ctrl;
+
+DEFINE_MUTEX(ov5647_mut);
+
+
+
+static struct msm_camera_i2c_reg_conf ov5647_start_settings[] = {
+ {0x4202, 0x00}, /* streaming on */
+};
+
+static struct msm_camera_i2c_reg_conf ov5647_stop_settings[] = {
+ {0x4202, 0x0f}, /* streaming off*/
+};
+
+static struct msm_camera_i2c_reg_conf ov5647_groupon_settings[] = {
+ {0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf ov5647_groupoff_settings[] = {
+ {0x0104, 0x0},
+};
+
+static struct msm_camera_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},
+};
+
+static struct msm_camera_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},
+};
+
+static struct msm_camera_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*/
+};
+
+
+static struct msm_camera_i2c_conf_array ov5647_init_conf[] = {
+ {&ov5647_recommend_settings[0],
+ ARRAY_SIZE(ov5647_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array ov5647_confs[] = {
+ {&ov5647_snap_settings[0],
+ ARRAY_SIZE(ov5647_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&ov5647_prev_settings[0],
+ ARRAY_SIZE(ov5647_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_camera_csi_params ov5647_csi_params = {
+ .data_format = CSI_8BIT,
+ .lane_cnt = 2,
+ .lane_assign = 0xe4,
+ .dpcm_scheme = 0,
+ .settle_cnt = 10,
+};
+
+static struct v4l2_subdev_info ov5647_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+static struct msm_sensor_output_info_t ov5647_dimensions[] = {
+ { /* For SNAPSHOT */
+ .x_output = 0xA30, /*2608*/ /*for 5Mp*/
+ .y_output = 0x7A0, /*1952*/
+ .line_length_pclk = 0xA8C,
+ .frame_length_lines = 0x7B0,
+ .vt_pixel_clk = 159408000,
+ .op_pixel_clk = 159408000,
+ .binning_factor = 0x0,
+ },
+ { /* For PREVIEW */
+ .x_output = 0x500, /*2608*/ /*for 5Mp*/
+ .y_output = 0x3C0, /*1952*/
+ .line_length_pclk = 0x768 * 2,
+ .frame_length_lines = 0x3D8,
+ .vt_pixel_clk = 159408000,
+ .op_pixel_clk = 159408000,
+ .binning_factor = 0x0,
+ },
+};
+
+static struct msm_sensor_output_reg_addr_t ov5647_reg_addr = {
+ .x_output = 0x3808,
+ .y_output = 0x380A,
+ .line_length_pclk = 0x380C,
+ .frame_length_lines = 0x380E,
+};
+
+static struct msm_camera_csi_params *ov5647_csi_params_array[] = {
+ &ov5647_csi_params,
+ &ov5647_csi_params,
+};
+
+static struct msm_sensor_id_info_t ov5647_id_info = {
+ .sensor_id_reg_addr = 0x300a,
+ .sensor_id = 0x5647,
+};
+
+static struct msm_sensor_exp_gain_info_t ov5647_exp_gain_info = {
+ .coarse_int_time_addr = 0x3500,
+ .global_gain_addr = 0x350A,
+ .vert_offset = 4,
+};
+
+void ov5647_sensor_reset_stream(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ msm_camera_i2c_write(
+ s_ctrl->sensor_i2c_client,
+ 0x103, 0x1,
+ MSM_CAMERA_I2C_BYTE_DATA);
+}
+
+static int32_t ov5647_write_pict_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t gain, uint32_t line)
+{
+
+ uint16_t max_line;
+ uint8_t gain_lsb, gain_hsb;
+ u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
+
+ gain_lsb = (uint8_t) (gain);
+ gain_hsb = (uint8_t)((gain & 0x300)>>8);
+
+ CDBG(KERN_ERR "snapshot exposure seting 0x%x, 0x%x, %d"
+ , gain, line, line);
+
+ if (line > 1964) {
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->vert_offset,
+ (uint8_t)((line+4) >> 8),
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->vert_offset + 1,
+ (uint8_t)((line+4) & 0x00FF),
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ max_line = line + 4;
+ } else if (line > 1968) {
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->vert_offset,
+ (uint8_t)((line+4) >> 8),
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->vert_offset + 1,
+ (uint8_t)((line+4) & 0x00FF),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ 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 */
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+
+ /* Coarse Integration Time */
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+ intg_time_hsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+ intg_time_msb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 2,
+ intg_time_lsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ /* gain */
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr,
+ gain_hsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+ gain_lsb-1,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ /* Coarse Integration Time */
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+ intg_time_hsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+ intg_time_msb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 2,
+ intg_time_lsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ /* gain */
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr,
+ gain_hsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+ gain_lsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+ return 0;
+
+}
+
+
+static int32_t ov5647_write_prev_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t gain, uint32_t line)
+{
+
+ uint16_t max_line;
+ u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
+ uint8_t gain_lsb, gain_hsb;
+
+ pr_info(KERN_ERR "preview exposure setting 0x%x, 0x%x, %d",
+ gain, line, line);
+
+ gain_lsb = (uint8_t) (gain);
+ gain_hsb = (uint8_t)((gain & 0x300)>>8);
+ /* adjust frame rate */
+ if (line > 980) {
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->vert_offset,
+ (uint8_t)((line+4) >> 8),
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->vert_offset + 1,
+ (uint8_t)((line+4) & 0x00FF),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ max_line = line + 4;
+ } else if (line > 984) {
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->vert_offset,
+ (uint8_t)(984 >> 8),
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->vert_offset + 1 ,
+ (uint8_t)(984 & 0x00FF),
+ MSM_CAMERA_I2C_BYTE_DATA);
+ 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);
+
+ s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
+
+ /* Coarse Integration Time */
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+ intg_time_hsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 1,
+ intg_time_msb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr + 2,
+ intg_time_lsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ /* gain */
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr,
+ gain_hsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->global_gain_addr + 1,
+ gain_lsb,
+ MSM_CAMERA_I2C_BYTE_DATA);
+
+ s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
+
+ return 0;
+}
+
+static const struct i2c_device_id ov5647_i2c_id[] = {
+ {SENSOR_NAME, (kernel_ulong_t)&ov5647_s_ctrl},
+ { }
+};
+
+static struct i2c_driver ov5647_i2c_driver = {
+ .id_table = ov5647_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+
+
+static struct msm_camera_i2c_client ov5647_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ return i2c_add_driver(&ov5647_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops ov5647_subdev_core_ops = {
+ .ioctl = msm_sensor_subdev_ioctl,
+ .s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops ov5647_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops ov5647_subdev_ops = {
+ .core = &ov5647_subdev_core_ops,
+ .video = &ov5647_subdev_video_ops,
+};
+
+int32_t ov5647_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ int32_t rc = 0;
+ struct msm_camera_sensor_info *info = NULL;
+
+ rc = msm_sensor_power_up(s_ctrl);
+ if (rc < 0) {
+ CDBG("%s: msm_sensor_power_up failed\n", __func__);
+ return rc;
+ }
+ info = s_ctrl->sensordata;
+
+ 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);
+
+ gpio_direction_output(info->sensor_pwd, 0);
+ usleep_range(4000, 4100);
+ gpio_direction_output(info->sensor_reset, 1);
+ usleep_range(2000, 2100);
+
+ return rc;
+
+}
+static struct msm_sensor_fn_t ov5647_func_tbl = {
+ .sensor_start_stream = msm_sensor_start_stream,
+ .sensor_stop_stream = msm_sensor_stop_stream,
+ .sensor_group_hold_on = msm_sensor_group_hold_on,
+ .sensor_group_hold_off = msm_sensor_group_hold_off,
+ .sensor_set_fps = msm_sensor_set_fps,
+ .sensor_write_exp_gain = ov5647_write_prev_exp_gain,
+ .sensor_write_snapshot_exp_gain = ov5647_write_pict_exp_gain,
+ .sensor_setting = msm_sensor_setting2,
+ .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+ .sensor_mode_init = msm_sensor_mode_init,
+ .sensor_get_output_info = msm_sensor_get_output_info,
+ .sensor_config = msm_sensor_config,
+ .sensor_power_up = ov5647_sensor_power_up,
+ .sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t ov5647_regs = {
+ .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+ .start_stream_conf = ov5647_start_settings,
+ .start_stream_conf_size = ARRAY_SIZE(ov5647_start_settings),
+ .stop_stream_conf = ov5647_stop_settings,
+ .stop_stream_conf_size = ARRAY_SIZE(ov5647_stop_settings),
+ .group_hold_on_conf = ov5647_groupon_settings,
+ .group_hold_on_conf_size = ARRAY_SIZE(ov5647_groupon_settings),
+ .group_hold_off_conf = ov5647_groupoff_settings,
+ .group_hold_off_conf_size =
+ ARRAY_SIZE(ov5647_groupoff_settings),
+ .init_settings = &ov5647_init_conf[0],
+ .init_size = ARRAY_SIZE(ov5647_init_conf),
+ .mode_settings = &ov5647_confs[0],
+ .output_settings = &ov5647_dimensions[0],
+ .num_conf = ARRAY_SIZE(ov5647_confs),
+};
+
+static struct msm_sensor_ctrl_t ov5647_s_ctrl = {
+ .msm_sensor_reg = &ov5647_regs,
+ .sensor_i2c_client = &ov5647_sensor_i2c_client,
+ .sensor_i2c_addr = 0x36 << 1 ,
+ .sensor_output_reg_addr = &ov5647_reg_addr,
+ .sensor_id_info = &ov5647_id_info,
+ .sensor_exp_gain_info = &ov5647_exp_gain_info,
+ .cam_mode = MSM_SENSOR_MODE_INVALID,
+ .csic_params = &ov5647_csi_params_array[0],
+ .msm_sensor_mutex = &ov5647_mut,
+ .sensor_i2c_driver = &ov5647_i2c_driver,
+ .sensor_v4l2_subdev_info = ov5647_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov5647_subdev_info),
+ .sensor_v4l2_subdev_ops = &ov5647_subdev_ops,
+ .func_tbl = &ov5647_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Omnivision WXGA Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c b/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c
new file mode 100644
index 0000000..f33d303
--- /dev/null
+++ b/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c
@@ -0,0 +1,695 @@
+/* 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_sensor.h"
+#define SENSOR_NAME "ov7692"
+#define PLATFORM_DRIVER_NAME "msm_camera_ov7692"
+#define ov7692_obj ov7692_##obj
+#define MSB 1
+#define LSB 0
+
+DEFINE_MUTEX(ov7692_mut);
+static struct msm_sensor_ctrl_t ov7692_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf ov7692_prev_settings[] = {
+ {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},
+ {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},
+ {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},
+
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_snap_settings[] = {
+ {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},
+ {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},
+ {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},
+
+};
+
+static struct msm_camera_i2c_reg_conf ov7692_recommend_settings[] = {
+ {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},
+ {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},
+ {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},
+
+};
+
+static struct v4l2_subdev_info ov7692_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+
+static struct msm_camera_i2c_conf_array ov7692_init_conf[] = {
+ {&ov7692_recommend_settings[0],
+ ARRAY_SIZE(ov7692_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array ov7692_confs[] = {
+ {&ov7692_snap_settings[0],
+ ARRAY_SIZE(ov7692_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&ov7692_prev_settings[0],
+ ARRAY_SIZE(ov7692_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t ov7692_dimensions[] = {
+ {
+ .x_output = 0x280,
+ .y_output = 0x1E0,
+ .line_length_pclk = 0x290,
+ .frame_length_lines = 0x1EC,
+ .vt_pixel_clk = 9216000,
+ .op_pixel_clk = 9216000,
+ .binning_factor = 1,
+ },
+ {
+ .x_output = 0x280,
+ .y_output = 0x1E0,
+ .line_length_pclk = 0x290,
+ .frame_length_lines = 0x1EC,
+ .vt_pixel_clk = 9216000,
+ .op_pixel_clk = 9216000,
+ .binning_factor = 1,
+ },
+};
+
+
+static struct msm_camera_csi_params ov7692_csi_params = {
+ .data_format = CSI_8BIT,
+ .lane_cnt = 1,
+ .lane_assign = 0xe4,
+ .dpcm_scheme = 0,
+ .settle_cnt = 0x14,
+};
+
+static struct msm_camera_csi_params *ov7692_csi_params_array[] = {
+ &ov7692_csi_params,
+ &ov7692_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t ov7692_reg_addr = {
+ .x_output = 0xCC,
+ .y_output = 0xCE,
+ .line_length_pclk = 0xC8,
+ .frame_length_lines = 0xCA,
+};
+
+static struct msm_sensor_id_info_t ov7692_id_info = {
+ .sensor_id_reg_addr = 0x0A,
+ .sensor_id = 0x7692,
+};
+
+static struct msm_sensor_exp_gain_info_t ov7692_exp_gain_info = {
+ .coarse_int_time_addr = 0x0202,
+ .global_gain_addr = 0x0204,
+ .vert_offset = 4,
+};
+
+static inline uint8_t ov7692_byte(uint16_t word, uint8_t offset)
+{
+ return word >> (offset * BITS_PER_BYTE);
+}
+
+
+static const struct i2c_device_id ov7692_i2c_id[] = {
+ {SENSOR_NAME, (kernel_ulong_t)&ov7692_s_ctrl},
+ { }
+};
+
+static struct i2c_driver ov7692_i2c_driver = {
+ .id_table = ov7692_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client ov7692_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ int rc = 0;
+ CDBG("OV7692\n");
+
+ rc = i2c_add_driver(&ov7692_i2c_driver);
+
+ return rc;
+}
+
+static struct v4l2_subdev_core_ops ov7692_subdev_core_ops = {
+ .ioctl = msm_sensor_subdev_ioctl,
+ .s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops ov7692_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops ov7692_subdev_ops = {
+ .core = &ov7692_subdev_core_ops,
+ .video = &ov7692_subdev_video_ops,
+};
+
+static int ov7692_pwdn_gpio;
+static int ov7692_reset_gpio;
+
+static int ov7692_probe_init_gpio(const struct msm_camera_sensor_info *data)
+{
+ int rc = 0;
+ CDBG("%s: entered\n", __func__);
+
+ ov7692_pwdn_gpio = data->sensor_pwd;
+ ov7692_reset_gpio = data->sensor_reset ;
+
+ CDBG("%s: pwdn_gpio:%d, reset_gpio:%d\n", __func__,
+ ov7692_pwdn_gpio, ov7692_reset_gpio);
+
+ if (data->sensor_reset_enable)
+ gpio_direction_output(data->sensor_reset, 1);
+
+ gpio_direction_output(data->sensor_pwd, 1);
+
+ return rc;
+
+}
+static void ov7692_power_on(void)
+{
+ CDBG("%s\n", __func__);
+ gpio_set_value(ov7692_pwdn_gpio, 0);
+}
+
+static void ov7692_power_down(void)
+{
+ CDBG("%s\n", __func__);
+ gpio_set_value(ov7692_pwdn_gpio, 1);
+}
+static int32_t ov7692_i2c_txdata(struct i2c_client *ov7692_client,
+ unsigned short saddr,
+ unsigned char *txdata, int length)
+{
+ struct i2c_msg msg[] = {
+ {
+ .addr = saddr,
+ .flags = 0,
+ .len = 2,
+ .buf = txdata,
+ },
+ };
+ if (i2c_transfer(ov7692_client->adapter, msg, 1) < 0) {
+ CDBG("ov7692_i2c_txdata faild 0x%x\n", ov7692_client->addr);
+ return -EIO;
+ }
+
+ return 0;
+}
+static int32_t ov7692_i2c_write_b_sensor(struct i2c_client *ov7692_client,
+ 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 = ov7692_i2c_txdata(ov7692_client, ov7692_client->addr >> 1, buf, 2);
+ if (rc < 0)
+ CDBG("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+ waddr, bdata);
+
+ return rc;
+}
+
+static void ov7692_sw_reset(struct msm_sensor_ctrl_t *s_ctrl)
+{
+
+ CDBG("%s\n", __func__);
+ ov7692_i2c_write_b_sensor(s_ctrl->sensor_i2c_client->client,
+ 0x12, 0x80);
+}
+
+static void ov7692_hw_reset(void)
+{
+ CDBG("--CAMERA-- %s ... (Start...)\n", __func__);
+ gpio_set_value(ov7692_reset_gpio, 1); /*reset camera reset pin*/
+ usleep_range(5000, 5100);
+ gpio_set_value(ov7692_reset_gpio, 0);
+ usleep_range(5000, 5100);
+ gpio_set_value(ov7692_reset_gpio, 1);
+ usleep_range(1000, 1100);
+ CDBG("--CAMERA-- %s ... (End...)\n", __func__);
+}
+
+
+
+int32_t ov7692_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ int32_t rc = 0;
+ struct msm_camera_sensor_info *info = NULL;
+
+ CDBG("%s: %d\n", __func__, __LINE__);
+
+ rc = msm_sensor_power_up(s_ctrl);
+ if (rc < 0) {
+ CDBG("%s: msm_sensor_power_up failed\n", __func__);
+ return rc;
+ }
+ info = s_ctrl->sensordata;
+
+ rc = ov7692_probe_init_gpio(info);
+ if (rc < 0) {
+ CDBG("%s: gpio init failed\n", __func__);
+ goto power_up_fail;
+ }
+ /* turn on LDO for PVT */
+ if (info->pmic_gpio_enable)
+ lcd_camera_power_onoff(1);
+
+ ov7692_power_down();
+
+ usleep_range(5000, 5100);
+
+ ov7692_power_on();
+ usleep_range(5000, 5100);
+
+ if (info->sensor_reset_enable)
+ ov7692_hw_reset();
+ else
+ ov7692_sw_reset(s_ctrl);
+
+ return rc;
+
+power_up_fail:
+ CDBG("ov7692_sensor_power_up: OV7692 SENSOR POWER UP FAILS!\n");
+ if (info->pmic_gpio_enable)
+ lcd_camera_power_onoff(0);
+ return rc;
+
+
+}
+
+
+static struct msm_sensor_fn_t ov7692_func_tbl = {
+ .sensor_start_stream = msm_sensor_start_stream,
+ .sensor_stop_stream = msm_sensor_stop_stream,
+ .sensor_group_hold_on = msm_sensor_group_hold_on,
+ .sensor_group_hold_off = msm_sensor_group_hold_off,
+ .sensor_set_fps = msm_sensor_set_fps,
+ .sensor_setting = msm_sensor_setting3,
+ .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+ .sensor_mode_init = msm_sensor_mode_init,
+ .sensor_get_output_info = msm_sensor_get_output_info,
+ .sensor_config = msm_sensor_config,
+ .sensor_power_up = ov7692_sensor_power_up,
+ .sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t ov7692_regs = {
+ .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+ .start_stream_conf_size = 0,
+ .stop_stream_conf_size = 0,
+ .group_hold_on_conf_size = 0,
+ .group_hold_off_conf_size = 0,
+ .init_settings = &ov7692_init_conf[0],
+ .init_size = ARRAY_SIZE(ov7692_init_conf),
+ .mode_settings = &ov7692_confs[0],
+ .output_settings = &ov7692_dimensions[0],
+ .num_conf = ARRAY_SIZE(ov7692_confs),
+};
+
+static struct msm_sensor_ctrl_t ov7692_s_ctrl = {
+ .msm_sensor_reg = &ov7692_regs,
+ .sensor_i2c_client = &ov7692_sensor_i2c_client,
+ .sensor_i2c_addr = 0x78,
+ .sensor_output_reg_addr = &ov7692_reg_addr,
+ .sensor_id_info = &ov7692_id_info,
+ .sensor_exp_gain_info = &ov7692_exp_gain_info,
+ .cam_mode = MSM_SENSOR_MODE_INVALID,
+ .csic_params = &ov7692_csi_params_array[0],
+ .msm_sensor_mutex = &ov7692_mut,
+ .sensor_i2c_driver = &ov7692_i2c_driver,
+ .sensor_v4l2_subdev_info = ov7692_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov7692_subdev_info),
+ .sensor_v4l2_subdev_ops = &ov7692_subdev_ops,
+ .func_tbl = &ov7692_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Omni VGA YUV sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/video/msm/sensors/ov9726_v4l2.c
index e345717..17291ff 100644
--- a/drivers/media/video/msm/sensors/ov9726_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov9726_v4l2.c
@@ -271,6 +271,7 @@
.sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov9726_subdev_info),
.sensor_v4l2_subdev_ops = &ov9726_subdev_ops,
.func_tbl = &ov9726_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
};
module_init(msm_sensor_init_module);
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
index 1f99119..699f0dd 100644
--- a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
+++ b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
@@ -196,8 +196,8 @@
.y_output = 0x7A8,
.line_length_pclk = 0xAB2,
.frame_length_lines = 0x7B4,
- .vt_pixel_clk = 816000000,
- .op_pixel_clk = 816000000,
+ .vt_pixel_clk = 81600000,
+ .op_pixel_clk = 81600000,
.binning_factor = 0,
},
{
@@ -205,8 +205,8 @@
.y_output = 0x3D4,
.line_length_pclk = 0xAB2,
.frame_length_lines = 0x3E0,
- .vt_pixel_clk = 816000000,
- .op_pixel_clk = 816000000,
+ .vt_pixel_clk = 81600000,
+ .op_pixel_clk = 81600000,
.binning_factor = 1,
},
};
@@ -349,8 +349,6 @@
gain = max_legal_gain;
}
- gain = 32;
- line = 1465;
pr_info("s5k4e1_write_exp_gain : gain = %d line = %d\n", gain, line);
line = (uint32_t) (line * s_ctrl->fps_divider);
fl_lines = s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider / Q10;
@@ -494,6 +492,7 @@
.sensor_v4l2_subdev_info_size = ARRAY_SIZE(s5k4e1_subdev_info),
.sensor_v4l2_subdev_ops = &s5k4e1_subdev_ops,
.func_tbl = &s5k4e1_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
};
module_init(msm_sensor_init_module);
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 31b8239..1b19c99 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -1208,6 +1208,75 @@
return rc;
}
+static long venc_set_header_mode(struct video_client_ctx *client_ctx,
+ __s32 mode)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_sps_pps_for_idr_enable sps_pps_for_idr_enable;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto err;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
+ vcd_property_hdr.sz = sizeof(sps_pps_for_idr_enable);
+ switch (mode) {
+ case V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE:
+ sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag = 0;
+ break;
+ case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME:
+ sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag = 1;
+ break;
+ case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME:
+ default:
+ WFD_MSG_ERR("Video header mode %d not supported\n",
+ mode);
+ rc = -ENOTSUPP;
+ goto err;
+ }
+
+ rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &sps_pps_for_idr_enable);
+ if (rc) {
+ WFD_MSG_ERR("Failed to set enable_sps_pps_for_idr\n");
+ goto err;
+ }
+err:
+ return rc;
+}
+
+static long venc_get_header_mode(struct video_client_ctx *client_ctx,
+ __s32 *mode)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_sps_pps_for_idr_enable sps_pps_for_idr_enable;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto err;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
+ vcd_property_hdr.sz = sizeof(sps_pps_for_idr_enable);
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &sps_pps_for_idr_enable);
+ if (rc) {
+ WFD_MSG_ERR("Failed to get sps/pps for idr enable\n");
+ goto err;
+ }
+
+ *mode = sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag ?
+ V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME :
+ V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
+err:
+ return rc;
+}
+
static long venc_alloc_input_buffer(struct v4l2_subdev *sd, void *arg)
{
struct mem_region *mregion = arg;
@@ -1497,6 +1566,9 @@
case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
rc = venc_set_qp_range(client_ctx, ctrl->id, ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+ rc = venc_set_header_mode(client_ctx, ctrl->value);
+ break;
default:
WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
@@ -1547,6 +1619,9 @@
case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
rc = venc_get_qp_range(client_ctx, ctrl->id, &ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+ rc = venc_get_header_mode(client_ctx, &ctrl->value);
+ break;
default:
WFD_MSG_ERR("Get property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 122ffb5..e854149 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -263,6 +263,7 @@
{
int ret;
const char *type;
+ const char *uhs_bus_speed_mode = "";
dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
@@ -292,6 +293,28 @@
break;
}
+ if (mmc_sd_card_uhs(card)) {
+ switch (card->sd_bus_speed) {
+ case UHS_SDR104_BUS_SPEED:
+ uhs_bus_speed_mode = "SDR104 ";
+ break;
+ case UHS_SDR50_BUS_SPEED:
+ uhs_bus_speed_mode = "SDR50 ";
+ break;
+ case UHS_DDR50_BUS_SPEED:
+ uhs_bus_speed_mode = "DDR50 ";
+ break;
+ case UHS_SDR25_BUS_SPEED:
+ uhs_bus_speed_mode = "SDR25 ";
+ break;
+ case UHS_SDR12_BUS_SPEED:
+ uhs_bus_speed_mode = "SDR12 ";
+ break;
+ default:
+ uhs_bus_speed_mode = "";
+ break;
+ }
+ }
if (mmc_host_is_spi(card->host)) {
printk(KERN_INFO "%s: new %s%s%s card on SPI\n",
mmc_hostname(card->host),
@@ -299,12 +322,13 @@
mmc_card_ddr_mode(card) ? "DDR " : "",
type);
} else {
- pr_info("%s: new %s%s%s%s card at address %04x\n",
+ pr_info("%s: new %s%s%s%s%s card at address %04x\n",
mmc_hostname(card->host),
mmc_sd_card_uhs(card) ? "ultra high speed " :
(mmc_card_highspeed(card) ? "high speed " : ""),
(mmc_card_hs200(card) ? "HS200 " : ""),
mmc_card_ddr_mode(card) ? "DDR " : "",
+ uhs_bus_speed_mode,
type, card->rca);
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 1eb9d5f..20c59fc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1246,7 +1246,7 @@
* If a host does all the power sequencing itself, ignore the
* initial MMC_POWER_UP stage.
*/
-static void mmc_power_up(struct mmc_host *host)
+void mmc_power_up(struct mmc_host *host)
{
int bit;
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 49684f6..d832d75 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -32,6 +32,8 @@
void mmc_init_erase(struct mmc_card *card);
+void mmc_power_up(struct mmc_host *host);
+void mmc_power_off(struct mmc_host *host);
void mmc_set_chip_select(struct mmc_host *host, int mode);
void mmc_set_clock(struct mmc_host *host, unsigned int hz);
void mmc_gate_clock(struct mmc_host *host);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index cd0eb4e..fb98b01 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1140,8 +1140,11 @@
if (err) {
printk(KERN_ERR "%s: Re-init card rc = %d (retries = %d)\n",
mmc_hostname(host), err, retries);
- mdelay(5);
retries--;
+ mmc_power_off(host);
+ usleep_range(5000, 5500);
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
continue;
}
break;
@@ -1278,6 +1281,10 @@
err = mmc_sd_init_card(host, host->ocr, NULL);
if (err) {
retries--;
+ mmc_power_off(host);
+ usleep_range(5000, 5500);
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
continue;
}
break;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index a1ad63e..ff12eb1 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -96,13 +96,24 @@
* An array holding the Tuning pattern to compare with when
* executing a tuning cycle.
*/
-static const u32 cmd19_tuning_block[16] = {
+static const u32 tuning_block_64[] = {
0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
0xF0FFF0FF, 0x3CCCFC0F, 0xCFCC33CC, 0xEEFFEFFF,
0xFDFFFDFF, 0xFFBFFFDF, 0xFFF7FFBB, 0xDE7B7FF7
};
+static const u32 tuning_block_128[] = {
+ 0xFF00FFFF, 0x0000FFFF, 0xCCCCFFFF, 0xCCCC33CC,
+ 0xCC3333CC, 0xFFFFCCCC, 0xFFFFEEFF, 0xFFEEEEFF,
+ 0xFFDDFFFF, 0xDDDDFFFF, 0xBBFFFFFF, 0xBBFFFFFF,
+ 0xFFFFFFBB, 0xFFFFFF77, 0x77FF7777, 0xFFEEDDBB,
+ 0x00FFFFFF, 0x00FFFFFF, 0xCCFFFF00, 0xCC33CCCC,
+ 0x3333CCCC, 0xFFCCCCCC, 0xFFEEFFFF, 0xEEEEFFFF,
+ 0xDDFFFFFF, 0xDDFFFFFF, 0xFFFFFFDD, 0xFFFFFFBB,
+ 0xFFFFBBBB, 0xFFFF77FF, 0xFF7777FF, 0xEEDDBB77
+};
+
#if IRQ_DEBUG == 1
static char *irq_status_bits[] = { "cmdcrcfail", "datcrcfail", "cmdtimeout",
"dattimeout", "txunderrun", "rxoverrun",
@@ -135,6 +146,7 @@
static inline void msmsdcc_delay(struct msmsdcc_host *host);
static void msmsdcc_dump_sdcc_state(struct msmsdcc_host *host);
static void msmsdcc_sg_start(struct msmsdcc_host *host);
+static int msmsdcc_vreg_reset(struct msmsdcc_host *host);
static inline unsigned short msmsdcc_get_nr_sg(struct msmsdcc_host *host)
{
@@ -330,9 +342,6 @@
BUG_ON(host->curr.data);
- host->curr.mrq = NULL;
- host->curr.cmd = NULL;
-
del_timer(&host->req_tout_timer);
if (mrq->data)
@@ -340,6 +349,9 @@
if (mrq->cmd->error == -ETIMEDOUT)
mdelay(5);
+ /* Clear current request information as current request has ended */
+ memset(&host->curr, 0, sizeof(struct msmsdcc_curr_req));
+
/*
* Need to drop the host lock here; mmc_request_done may call
* back into the driver...
@@ -499,10 +511,13 @@
msmsdcc_stop_data(host);
if (!mrq->data->stop || mrq->cmd->error ||
(mrq->sbc && !mrq->data->error)) {
- host->curr.mrq = NULL;
- host->curr.cmd = NULL;
mrq->data->bytes_xfered = host->curr.data_xfered;
del_timer(&host->req_tout_timer);
+ /*
+ * Clear current request information as current
+ * request has ended
+ */
+ memset(&host->curr, 0, sizeof(struct msmsdcc_curr_req));
spin_unlock_irqrestore(&host->lock, flags);
mmc_request_done(host->mmc, mrq);
@@ -656,10 +671,13 @@
msmsdcc_stop_data(host);
if (!mrq->data->stop || mrq->cmd->error ||
(mrq->sbc && !mrq->data->error)) {
- host->curr.mrq = NULL;
- host->curr.cmd = NULL;
mrq->data->bytes_xfered = host->curr.data_xfered;
del_timer(&host->req_tout_timer);
+ /*
+ * Clear current request information as current
+ * request has ended
+ */
+ memset(&host->curr, 0, sizeof(struct msmsdcc_curr_req));
spin_unlock_irqrestore(&host->lock, flags);
mmc_request_done(host->mmc, mrq);
@@ -985,7 +1003,9 @@
*c |= MCI_CSPM_DATCMD;
/* Check if AUTO CMD19 is required or not? */
- if (host->tuning_needed) {
+ if (host->tuning_needed &&
+ !(host->mmc->ios.timing == MMC_TIMING_MMC_HS200)) {
+
/*
* For open ended block read operation (without CMD23),
* AUTO_CMD19 bit should be set while sending the READ command.
@@ -1517,7 +1537,7 @@
mmc_hostname(host->mmc), cmd->opcode);
cmd->error = -ETIMEDOUT;
} else if ((status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) &&
- !host->cmd19_tuning_in_progress) {
+ !host->tuning_in_progress) {
pr_err("%s: CMD%d: Command CRC error\n",
mmc_hostname(host->mmc), cmd->opcode);
msmsdcc_dump_sdcc_state(host);
@@ -1547,6 +1567,7 @@
host->curr.cmd = cmd;
} else {
host->prog_enable = 0;
+ host->curr.wait_for_auto_prog_done = 0;
if (host->dummy_52_needed)
host->dummy_52_needed = 0;
if (cmd->data && cmd->error)
@@ -1968,6 +1989,10 @@
if (rc)
goto vccq_reg_deinit;
}
+ rc = msmsdcc_vreg_reset(host);
+ if (rc)
+ pr_err("msmsdcc.%d vreg reset failed (%d)\n",
+ host->pdev_id, rc);
goto out;
} else {
/* Deregister all regulators from regulator framework */
@@ -2076,6 +2101,21 @@
return rc;
}
+/*
+ * Reset vreg by ensuring it is off during probe. A call
+ * to enable vreg is needed to balance disable vreg
+ */
+static int msmsdcc_vreg_reset(struct msmsdcc_host *host)
+{
+ int rc;
+
+ rc = msmsdcc_setup_vreg(host, 1);
+ if (rc)
+ return rc;
+ rc = msmsdcc_setup_vreg(host, 0);
+ return rc;
+}
+
static int msmsdcc_set_vddp_level(struct msmsdcc_host *host, int level)
{
int rc = 0;
@@ -2127,6 +2167,22 @@
return rc;
}
+static inline int msmsdcc_set_vccq_vol(struct msmsdcc_host *host, int level)
+{
+ struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
+ int rc = 0;
+
+ if (curr_slot && curr_slot->vccq_data) {
+ rc = msmsdcc_vreg_set_voltage(curr_slot->vccq_data,
+ level, level);
+ if (rc)
+ pr_err("%s: %s: failed to change vccq level to %d",
+ mmc_hostname(host->mmc), __func__, level);
+ }
+
+ return rc;
+}
+
static inline int msmsdcc_is_pwrsave(struct msmsdcc_host *host)
{
if (host->clk_rate > 400000 && msmsdcc_pwrsave)
@@ -2408,7 +2464,8 @@
* Select the controller timing mode according
* to current bus speed mode
*/
- if (ios->timing == MMC_TIMING_UHS_SDR104) {
+ if ((ios->timing == MMC_TIMING_UHS_SDR104) ||
+ (ios->timing == MMC_TIMING_MMC_HS200)) {
clk |= (4 << 14);
host->tuning_needed = 1;
} else if (ios->timing == MMC_TIMING_UHS_DDR50) {
@@ -2515,9 +2572,9 @@
host->clks_on = 0;
}
- if (host->cmd19_tuning_in_progress)
+ if (host->tuning_in_progress)
WARN(!host->clks_on,
- "cmd19_tuning_in_progress but SDCC clocks are OFF\n");
+ "tuning_in_progress but SDCC clocks are OFF\n");
spin_unlock_irqrestore(&host->lock, flags);
}
@@ -2703,6 +2760,16 @@
host->io_pad_pwr_switch = 0;
spin_unlock_irqrestore(&host->lock, flags);
+ /*
+ * For eMMC cards, VccQ voltage range must be changed
+ * only if it operates in HS200 SDR 1.2V mode or in
+ * DDR 1.2V mode.
+ */
+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120) {
+ rc = msmsdcc_set_vccq_vol(host, 1200000);
+ goto out;
+ }
+
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
/* Change voltage level of VDDPX to high voltage */
rc = msmsdcc_set_vddp_high_vol(host);
@@ -3094,6 +3161,8 @@
struct msmsdcc_host *host = mmc_priv(mmc);
unsigned long flags;
u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0;
+ const u32 *tuning_block_pattern = tuning_block_64;
+ int size = sizeof(tuning_block_64); /* Tuning pattern size in bytes */
pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
@@ -3108,8 +3177,14 @@
WARN(!host->clks_on, "SDCC clocks are turned off\n");
WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
- host->cmd19_tuning_in_progress = 1;
+ host->tuning_in_progress = 1;
msmsdcc_delay(host);
+ if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
+ (mmc->ios.bus_width == MMC_BUS_WIDTH_8)) {
+ tuning_block_pattern = tuning_block_128;
+ size = sizeof(tuning_block_128);
+ }
+
spin_unlock_irqrestore(&host->lock, flags);
/* first of all reset the tuning block */
@@ -3117,7 +3192,7 @@
if (rc)
goto out;
- data_buf = kmalloc(64, GFP_KERNEL);
+ data_buf = kmalloc(size, GFP_KERNEL);
if (!data_buf) {
rc = -ENOMEM;
goto out;
@@ -3138,23 +3213,23 @@
if (rc)
goto kfree;
- cmd.opcode = MMC_SEND_TUNING_BLOCK;
+ cmd.opcode = opcode;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
- data.blksz = 64;
+ data.blksz = size;
data.blocks = 1;
data.flags = MMC_DATA_READ;
data.timeout_ns = 1000 * 1000 * 1000; /* 1 sec */
data.sg = &sg;
data.sg_len = 1;
- sg_init_one(&sg, data_buf, 64);
- memset(data_buf, 0, 64);
+ sg_init_one(&sg, data_buf, size);
+ memset(data_buf, 0, size);
mmc_wait_for_req(mmc, &mrq);
if (!cmd.error && !data.error &&
- !memcmp(data_buf, cmd19_tuning_block, 64)) {
- /* tuning is successful with this tuning point */
+ !memcmp(data_buf, tuning_block_pattern, size)) {
+ /* tuning is successful at this tuning point */
tuned_phases[tuned_phase_cnt++] = phase;
pr_debug("%s: %s: found good phase = %d\n",
mmc_hostname(mmc), __func__, phase);
@@ -3191,7 +3266,7 @@
out:
spin_lock_irqsave(&host->lock, flags);
msmsdcc_delay(host);
- host->cmd19_tuning_in_progress = 0;
+ host->tuning_in_progress = 0;
spin_unlock_irqrestore(&host->lock, flags);
exit:
pr_debug("%s: Exit %s\n", mmc_hostname(mmc), __func__);
@@ -3913,6 +3988,7 @@
}
} else {
host->prog_enable = 0;
+ host->curr.wait_for_auto_prog_done = 0;
msmsdcc_reset_and_restore(host);
msmsdcc_request_end(host, mrq);
}
@@ -4323,6 +4399,12 @@
mmc->caps |= (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
MMC_CAP_SET_XPC_180);
+ if (pdev->dev.of_node) {
+ if (of_get_property((&pdev->dev)->of_node,
+ "qcom,sdcc-hs200", NULL))
+ mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
+ }
+
if (plat->nonremovable)
mmc->caps |= MMC_CAP_NONREMOVABLE;
#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 8a728f2..0166173 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -2,7 +2,7 @@
* linux/drivers/mmc/host/msmsdcc.h - QCT MSM7K SDC Controller
*
* Copyright (C) 2008 Google, All Rights Reserved.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 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 as
@@ -394,7 +394,7 @@
struct timer_list req_tout_timer;
unsigned long reg_write_delay;
bool io_pad_pwr_switch;
- bool cmd19_tuning_in_progress;
+ bool tuning_in_progress;
bool tuning_needed;
bool sdio_gpio_lpm;
bool irq_wake_enabled;
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 5a016bb..ebd58ab 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.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
@@ -66,7 +66,7 @@
return snprintf(buf, PAGE_SIZE, "%u\n", dev->mdm_wait_timeout);
}
-static DEVICE_ATTR(modem_wait, 0666, modem_wait_show, modem_wait_store);
+static DEVICE_ATTR(modem_wait, 0664, modem_wait_show, modem_wait_store);
static int ctl_msg_dbg_mask;
module_param_named(dump_ctrl_msg, ctl_msg_dbg_mask, int,
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 1eb6845..ae3f934 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -466,6 +466,11 @@
status = rmnet_usb_ctrl_probe(iface, unet->status,
(struct rmnet_ctrl_dev *)unet->data[1]);
+ if (status)
+ goto out;
+
+ /* allow modem to wake up suspended system */
+ device_set_wakeup_enable(&udev->dev, 1);
out:
return status;
}
@@ -477,6 +482,7 @@
struct rmnet_ctrl_dev *dev;
udev = interface_to_usbdev(intf);
+ device_set_wakeup_enable(&udev->dev, 0);
unet = usb_get_intfdata(intf);
if (!unet) {
diff --git a/drivers/of/of_spmi.c b/drivers/of/of_spmi.c
index 2032b46..112497c 100644
--- a/drivers/of/of_spmi.c
+++ b/drivers/of/of_spmi.c
@@ -18,6 +18,7 @@
#include <linux/of_spmi.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/types.h>
struct of_spmi_dev_info {
struct spmi_controller *ctrl;
@@ -30,14 +31,49 @@
uint32_t num_irq;
};
-static void of_spmi_sum_resources(struct of_spmi_res_info *r_info, bool has_reg)
+/*
+ * Initialize r_info structure for safe usage
+ */
+static inline void of_spmi_init_resource(struct of_spmi_res_info *r_info,
+ struct device_node *node)
+{
+ r_info->node = node;
+ r_info->num_reg = 0;
+ r_info->num_irq = 0;
+}
+
+/*
+ * Allocate dev_node array for spmi_device
+ */
+static inline int of_spmi_alloc_device_store(struct of_spmi_dev_info *d_info,
+ uint32_t num_dev_node)
+{
+ d_info->b_info.num_dev_node = num_dev_node;
+ d_info->b_info.dev_node = kzalloc(sizeof(struct spmi_resource) *
+ num_dev_node, GFP_KERNEL);
+ if (!d_info->b_info.dev_node)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/*
+ * Calculate the number of resources to allocate
+ *
+ * The caller is responsible for initializing the of_spmi_res_info structure.
+ */
+static void of_spmi_sum_node_resources(struct of_spmi_res_info *r_info,
+ bool has_reg)
{
struct of_irq oirq;
uint64_t size;
uint32_t flags;
+ int i = 0;
- while (of_irq_map_one(r_info->node, r_info->num_irq, &oirq) == 0)
- r_info->num_irq++;
+ while (of_irq_map_one(r_info->node, i, &oirq) == 0)
+ i++;
+
+ r_info->num_irq += i;
if (!has_reg)
return;
@@ -48,16 +84,32 @@
* parent buses have a size-cell of 0. But SPMI does have a
* size-cell of 0.
*/
- while (of_get_address(r_info->node, r_info->num_reg,
- &size, &flags) != NULL)
- r_info->num_reg++;
+ i = 0;
+ while (of_get_address(r_info->node, i, &size, &flags) != NULL)
+ i++;
+
+ r_info->num_reg += i;
}
-/**
- * Allocate resources for a child of a spmi-slave node.
+/*
+ * free spmi_resource for the spmi_device
*/
-static int of_spmi_allocate_resources(struct of_spmi_dev_info *d_info,
- struct of_spmi_res_info *r_info)
+static void of_spmi_free_device_resources(struct of_spmi_dev_info *d_info)
+{
+ int i;
+
+ for (i = 0; i < d_info->b_info.num_dev_node; i++)
+ kfree(d_info->b_info.dev_node[i].resource);
+
+ kfree(d_info->b_info.dev_node);
+}
+
+/*
+ * Gather node resources and populate
+ */
+static void of_spmi_populate_node_resources(struct of_spmi_dev_info *d_info,
+ struct of_spmi_res_info *r_info,
+ int idx)
{
uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg;
@@ -67,13 +119,10 @@
uint64_t size;
uint32_t flags;
- if (num_irq || num_reg) {
- res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
- if (!res)
- return -ENOMEM;
+ res = d_info->b_info.dev_node[idx].resource;
+ d_info->b_info.dev_node[idx].of_node = r_info->node;
- d_info->b_info.num_resources = num_reg + num_irq;
- d_info->b_info.resource = res;
+ if ((num_irq || num_reg) && (res != NULL)) {
for (i = 0; i < num_reg; i++, res++) {
/* Addresses are always 16 bits */
addrp = of_get_address(r_info->node, i, &size, &flags);
@@ -85,10 +134,34 @@
WARN_ON(of_irq_to_resource_table(r_info->node, res, num_irq) !=
num_irq);
}
+}
+
+/*
+ * Allocate enough memory to handle the resources associated with the
+ * device_node. The number of device nodes included in this allocation
+ * depends on whether the spmi-dev-container flag is specified or not.
+ */
+static int of_spmi_allocate_node_resources(struct of_spmi_dev_info *d_info,
+ struct of_spmi_res_info *r_info,
+ uint32_t idx)
+{
+ uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg;
+ struct resource *res = NULL;
+
+ if (num_irq || num_reg) {
+ res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
+ if (!res)
+ return -ENOMEM;
+ }
+ d_info->b_info.dev_node[idx].num_resources = num_reg + num_irq;
+ d_info->b_info.dev_node[idx].resource = res;
return 0;
}
+/*
+ * create a single spmi_device
+ */
static int of_spmi_create_device(struct of_spmi_dev_info *d_info,
struct device_node *node)
{
@@ -117,6 +190,71 @@
return 0;
}
+/*
+ * Walks all children of a node containing the spmi-dev-container
+ * binding. This special type of spmi_device can include resources
+ * from more than one device node.
+ */
+static void of_spmi_walk_dev_container(struct of_spmi_dev_info *d_info,
+ struct device_node *container)
+{
+ struct of_spmi_res_info r_info = {};
+ struct spmi_controller *ctrl = d_info->ctrl;
+ struct device_node *node;
+ int rc, i, num_dev_node = 0;
+
+ /* first count the total number of device_nodes */
+ for_each_child_of_node(container, node)
+ num_dev_node++;
+
+ rc = of_spmi_alloc_device_store(d_info, num_dev_node);
+ if (rc) {
+ dev_err(&ctrl->dev, "%s: unable to allocate"
+ " device resources\n", __func__);
+ return;
+ }
+
+ /* allocate resources per device_node */
+ i = 0;
+ for_each_child_of_node(container, node) {
+ of_spmi_init_resource(&r_info, node);
+ of_spmi_sum_node_resources(&r_info, 1);
+ rc = of_spmi_allocate_node_resources(d_info, &r_info, i);
+ if (rc) {
+ dev_err(&ctrl->dev, "%s: unable to allocate"
+ " resources\n", __func__);
+ of_spmi_free_device_resources(d_info);
+ return;
+ }
+ i++;
+ }
+
+ /**
+ * Now we need to cycle through again and actually populate
+ * the resources for each node.
+ */
+ i = 0;
+ for_each_child_of_node(container, node) {
+ of_spmi_init_resource(&r_info, node);
+ of_spmi_sum_node_resources(&r_info, 1);
+ of_spmi_populate_node_resources(d_info, &r_info, i);
+ i++;
+ }
+
+ rc = of_spmi_create_device(d_info, container);
+ if (rc) {
+ dev_err(&ctrl->dev, "%s: unable to create device for"
+ " node %s\n", __func__, container->full_name);
+ of_spmi_free_device_resources(d_info);
+ return;
+ }
+}
+
+/*
+ * Walks all children of a node containing the spmi-slave-container
+ * binding. This indicates that all spmi_devices created from this
+ * point all share the same slave_id.
+ */
static void of_spmi_walk_slave_container(struct of_spmi_dev_info *d_info,
struct device_node *container)
{
@@ -127,59 +265,133 @@
for_each_child_of_node(container, node) {
struct of_spmi_res_info r_info;
- r_info.node = node;
- of_spmi_sum_resources(&r_info, 1);
+ /**
+ * Check to see if this node contains children which
+ * should be all created as the same spmi_device.
+ */
+ if (of_get_property(node, "spmi-dev-container", NULL)) {
+ of_spmi_walk_dev_container(d_info, node);
+ continue;
+ }
- rc = of_spmi_allocate_resources(d_info, &r_info);
+ rc = of_spmi_alloc_device_store(d_info, 1);
+ if (rc) {
+ dev_err(&ctrl->dev, "%s: unable to allocate"
+ " device resources\n", __func__);
+ goto slave_err;
+ }
+
+ of_spmi_init_resource(&r_info, node);
+ of_spmi_sum_node_resources(&r_info, 1);
+
+ rc = of_spmi_allocate_node_resources(d_info, &r_info, 0);
if (rc) {
dev_err(&ctrl->dev, "%s: unable to allocate"
" resources\n", __func__);
- return;
+ goto slave_err;
}
+
+ of_spmi_populate_node_resources(d_info, &r_info, 0);
+
rc = of_spmi_create_device(d_info, node);
if (rc) {
dev_err(&ctrl->dev, "%s: unable to create device for"
" node %s\n", __func__, node->full_name);
- return;
+ goto slave_err;
}
}
+ return;
+
+slave_err:
+ of_spmi_free_device_resources(d_info);
}
int of_spmi_register_devices(struct spmi_controller *ctrl)
{
- struct device_node *node;
+ struct device_node *node = ctrl->dev.of_node;
/* Only register child devices if the ctrl has a node pointer set */
- if (!ctrl->dev.of_node)
+ if (!node)
return -ENODEV;
+ if (of_get_property(node, "spmi-slave-container", NULL)) {
+ dev_err(&ctrl->dev, "%s: structural error: spmi-slave-container"
+ " is prohibited at the root level\n", __func__);
+ return -EINVAL;
+ } else if (of_get_property(node, "spmi-dev-container", NULL)) {
+ dev_err(&ctrl->dev, "%s: structural error: spmi-dev-container"
+ " is prohibited at the root level\n", __func__);
+ return -EINVAL;
+ }
+
+ /**
+ * Make best effort to launch as many nodes as possible. If there are
+ * syntax errors, we will simply ignore that subtree and keep going.
+ */
for_each_child_of_node(ctrl->dev.of_node, node) {
struct of_spmi_dev_info d_info = {};
const __be32 *slave_id;
- int len, rc;
+ int len, rc, have_dev_container = 0;
slave_id = of_get_property(node, "reg", &len);
if (!slave_id) {
- dev_err(&ctrl->dev, "of_spmi: invalid sid "
- "on %s\n", node->full_name);
+ dev_err(&ctrl->dev, "%s: invalid sid "
+ "on %s\n", __func__, node->full_name);
continue;
}
d_info.b_info.slave_id = be32_to_cpup(slave_id);
d_info.ctrl = ctrl;
+ if (of_get_property(node, "spmi-dev-container", NULL))
+ have_dev_container = 1;
if (of_get_property(node, "spmi-slave-container", NULL)) {
- of_spmi_walk_slave_container(&d_info, node);
- continue;
+ if (have_dev_container)
+ of_spmi_walk_dev_container(&d_info, node);
+ else
+ of_spmi_walk_slave_container(&d_info, node);
} else {
struct of_spmi_res_info r_info;
- r_info.node = node;
- of_spmi_sum_resources(&r_info, 0);
- rc = of_spmi_allocate_resources(&d_info, &r_info);
- if (rc)
+ /**
+ * A dev container at the second level without a slave
+ * container is considered an error.
+ */
+ if (have_dev_container) {
+ dev_err(&ctrl->dev, "%s: structural error,"
+ " node %s has spmi-dev-container without"
+ " specifying spmi-slave-container\n",
+ __func__, node->full_name);
continue;
- of_spmi_create_device(&d_info, node);
+ }
+
+ rc = of_spmi_alloc_device_store(&d_info, 1);
+ if (rc) {
+ dev_err(&ctrl->dev, "%s: unable to allocate"
+ " device resources\n", __func__);
+ continue;
+ }
+
+ of_spmi_init_resource(&r_info, node);
+ of_spmi_sum_node_resources(&r_info, 0);
+ rc = of_spmi_allocate_node_resources(&d_info,
+ &r_info, 0);
+ if (rc) {
+ dev_err(&ctrl->dev, "%s: unable to allocate"
+ " resources\n", __func__);
+ of_spmi_free_device_resources(&d_info);
+ continue;
+ }
+
+ of_spmi_populate_node_resources(&d_info, &r_info, 0);
+
+ rc = of_spmi_create_device(&d_info, node);
+ if (rc) {
+ dev_err(&ctrl->dev, "%s: unable to create"
+ " device\n", __func__);
+ of_spmi_free_device_resources(&d_info);
+ continue;
+ }
}
}
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index f157ff3..819aa2e 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -16,6 +16,7 @@
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
+#include <linux/power_supply.h>
#include <linux/mfd/pm8xxx/pm8921-bms.h>
#include <linux/mfd/pm8xxx/core.h>
#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
@@ -90,6 +91,8 @@
struct delayed_work calib_ccadc_work;
unsigned int calib_delay_ms;
unsigned int revision;
+ unsigned int xoadc_v0625_usb_present;
+ unsigned int xoadc_v0625_usb_absent;
unsigned int xoadc_v0625;
unsigned int xoadc_v125;
unsigned int batt_temp_channel;
@@ -117,6 +120,9 @@
#define DEFAULT_OCV_MICROVOLTS 3900000
#define DEFAULT_CHARGE_CYCLES 0
+static int last_usb_cal_delta_uv = 1800;
+module_param(last_usb_cal_delta_uv, int, 0644);
+
static int last_chargecycles = DEFAULT_CHARGE_CYCLES;
static int last_charge_increase;
module_param(last_chargecycles, int, 0644);
@@ -302,6 +308,23 @@
return 0;
}
+static int usb_chg_plugged_in(void)
+{
+ union power_supply_propval ret = {0,};
+ static struct power_supply *psy;
+
+ if (psy == NULL) {
+ psy = power_supply_get_by_name("usb");
+ if (psy == NULL)
+ return 0;
+ }
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
+ return 0;
+
+ return ret.intval;
+}
+
#define HOLD_OREG_DATA BIT(1)
static int pm_bms_lock_output_data(struct pm8921_bms_chip *chip)
{
@@ -396,18 +419,32 @@
#define XOADC_CALIB_UV 625000
#define VBATT_MUL_FACTOR 3
static int adjust_xo_vbatt_reading(struct pm8921_bms_chip *chip,
- unsigned int uv)
+ int usb_chg, unsigned int uv)
{
- u64 numerator, denominator;
+ s64 numerator, denominator;
+ int local_delta;
if (uv == 0)
return 0;
- numerator = ((u64)uv - chip->xoadc_v0625) * XOADC_CALIB_UV;
- denominator = chip->xoadc_v125 - chip->xoadc_v0625;
+ /* dont adjust if not calibrated */
+ if (chip->xoadc_v0625 == 0 || chip->xoadc_v125 == 0) {
+ pr_debug("No cal yet return %d\n", VBATT_MUL_FACTOR * uv);
+ return VBATT_MUL_FACTOR * uv;
+ }
+
+ if (usb_chg)
+ local_delta = last_usb_cal_delta_uv;
+ else
+ local_delta = 0;
+
+ pr_debug("using delta = %d\n", local_delta);
+ numerator = ((s64)uv - chip->xoadc_v0625 - local_delta)
+ * XOADC_CALIB_UV;
+ denominator = (s64)chip->xoadc_v125 - chip->xoadc_v0625 - local_delta;
if (denominator == 0)
return uv * VBATT_MUL_FACTOR;
- return (XOADC_CALIB_UV + div_u64(numerator, denominator))
+ return (XOADC_CALIB_UV + local_delta + div_s64(numerator, denominator))
* VBATT_MUL_FACTOR;
}
@@ -474,11 +511,12 @@
}
static int convert_vbatt_raw_to_uv(struct pm8921_bms_chip *chip,
+ int usb_chg,
uint16_t reading, int *result)
{
*result = xoadc_reading_to_microvolt(reading);
pr_debug("raw = %04x vbatt = %u\n", reading, *result);
- *result = adjust_xo_vbatt_reading(chip, *result);
+ *result = adjust_xo_vbatt_reading(chip, usb_chg, *result);
pr_debug("after adj vbatt = %u\n", *result);
return 0;
}
@@ -778,6 +816,7 @@
int16_t vsense_raw;
int16_t vbat_raw;
int vsense_uv;
+ int usb_chg;
if (the_chip == NULL) {
pr_err("Called to early\n");
@@ -803,7 +842,9 @@
mutex_unlock(&the_chip->bms_output_lock);
- convert_vbatt_raw_to_uv(the_chip, vbat_raw, vbat_uv);
+ usb_chg = usb_chg_plugged_in();
+
+ convert_vbatt_raw_to_uv(the_chip, usb_chg, vbat_raw, vbat_uv);
convert_vsense_to_uv(the_chip, vsense_raw, &vsense_uv);
*ibat_ua = vsense_uv * 1000 / (int)the_chip->r_sense;
@@ -818,6 +859,8 @@
static int read_soc_params_raw(struct pm8921_bms_chip *chip,
struct pm8921_soc_params *raw)
{
+ int usb_chg;
+
mutex_lock(&chip->bms_output_lock);
pm_bms_lock_output_data(chip);
@@ -834,13 +877,14 @@
pm_bms_unlock_output_data(chip);
mutex_unlock(&chip->bms_output_lock);
- convert_vbatt_raw_to_uv(chip,
+ usb_chg = usb_chg_plugged_in();
+ convert_vbatt_raw_to_uv(chip, usb_chg,
raw->vbatt_for_rbatt_raw, &raw->vbatt_for_rbatt_uv);
- convert_vbatt_raw_to_uv(chip,
+ convert_vbatt_raw_to_uv(chip, usb_chg,
raw->ocv_for_rbatt_raw, &raw->ocv_for_rbatt_uv);
- convert_vbatt_raw_to_uv(chip,
+ convert_vbatt_raw_to_uv(chip, usb_chg,
raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
- convert_vsense_to_uv(chip,
+ convert_vbatt_raw_to_uv(chip, usb_chg,
raw->vsense_for_rbatt_raw, &raw->vsense_for_rbatt_uv);
if (raw->last_good_ocv_uv)
@@ -866,9 +910,9 @@
{
unsigned int r_batt;
- if (raw->ocv_for_rbatt_uv == 0
- || raw->ocv_for_rbatt_uv == raw->vbatt_for_rbatt_uv
- || raw->vsense_for_rbatt_raw == 0) {
+ if (raw->ocv_for_rbatt_uv <= 0
+ || raw->ocv_for_rbatt_uv <= raw->vbatt_for_rbatt_uv
+ || raw->vsense_for_rbatt_raw <= 0) {
pr_debug("rbatt readings unavailable ocv = %d, vbatt = %d,"
"vsen = %d\n",
raw->ocv_for_rbatt_uv,
@@ -1180,11 +1224,13 @@
return soc;
}
-
+#define MIN_DELTA_625_UV 1000
static void calib_hkadc(struct pm8921_bms_chip *chip)
{
int voltage, rc;
struct pm8xxx_adc_chan_result result;
+ int usb_chg;
+ int this_delta;
rc = pm8xxx_adc_read(the_chip->ref1p25v_channel, &result);
if (rc) {
@@ -1204,10 +1250,30 @@
return;
}
voltage = xoadc_reading_to_microvolt(result.adc_code);
- pr_debug("result 0.625V = 0x%x, voltage = %duV adc_meas = %lld\n",
- result.adc_code, voltage, result.measurement);
+
+ usb_chg = usb_chg_plugged_in();
+ pr_debug("result 0.625V = 0x%x, voltage = %duV adc_meas = %lld "
+ "usb_chg = %d\n",
+ result.adc_code, voltage, result.measurement,
+ usb_chg);
+
+ if (usb_chg)
+ chip->xoadc_v0625_usb_present = voltage;
+ else
+ chip->xoadc_v0625_usb_absent = voltage;
chip->xoadc_v0625 = voltage;
+ if (chip->xoadc_v0625_usb_present && chip->xoadc_v0625_usb_absent) {
+ this_delta = chip->xoadc_v0625_usb_present
+ - chip->xoadc_v0625_usb_absent;
+ pr_debug("this_delta= %duV\n", this_delta);
+ if (this_delta > MIN_DELTA_625_UV)
+ last_usb_cal_delta_uv = this_delta;
+ pr_debug("625V_present= %d, 625V_absent= %d, delta = %duV\n",
+ chip->xoadc_v0625_usb_present,
+ chip->xoadc_v0625_usb_absent,
+ last_usb_cal_delta_uv);
+ }
}
static void calibrate_hkadc_work(struct work_struct *work)
@@ -1592,6 +1658,7 @@
{
int ocv_uv, rc;
int16_t ocv_raw;
+ int usb_chg;
/*
* Check if a ocv is available in bms hw,
@@ -1600,7 +1667,8 @@
*/
ocv_uv = 0;
pm_bms_read_output_data(chip, LAST_GOOD_OCV_VALUE, &ocv_raw);
- rc = convert_vbatt_raw_to_uv(chip, ocv_raw, &ocv_uv);
+ usb_chg = usb_chg_plugged_in();
+ rc = convert_vbatt_raw_to_uv(chip, usb_chg, ocv_raw, &ocv_uv);
if (rc || ocv_uv == 0) {
rc = adc_based_ocv(chip, &ocv_uv);
if (rc) {
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 60d4e64..78757f9 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -415,6 +415,13 @@
disable ? CHG_CHARGE_DIS_BIT : 0);
}
+static int pm_is_chg_charge_dis(struct pm8921_chg_chip *chip)
+{
+ u8 temp;
+
+ 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_10MV_OFFSET_BIT BIT(7)
@@ -1044,7 +1051,13 @@
}
}
-static enum power_supply_property pm_power_props[] = {
+static enum power_supply_property pm_power_props_usb[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+};
+
+static enum power_supply_property pm_power_props_mains[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
};
@@ -1054,7 +1067,53 @@
};
#define USB_WALL_THRESHOLD_MA 500
-static int pm_power_get_property(struct power_supply *psy,
+static int pm_power_get_property_mains(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int current_max;
+
+ /* Check if called before init */
+ if (!the_chip)
+ return -EINVAL;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = 0;
+ if (charging_disabled)
+ return 0;
+
+ /* check external charger first before the dc path */
+ if (is_ext_charging(the_chip)) {
+ val->intval = 1;
+ return 0;
+ }
+
+ if (pm_is_chg_charge_dis(the_chip)) {
+ val->intval = 0;
+ return 0;
+ }
+
+ if (the_chip->dc_present) {
+ 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 = is_usb_chg_plugged_in(the_chip);
+ return 0;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int pm_power_get_property_usb(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
@@ -1066,8 +1125,12 @@
switch (psp) {
case POWER_SUPPLY_PROP_CURRENT_MAX:
- pm_chg_iusbmax_get(the_chip, ¤t_max);
- val->intval = current_max;
+ if (pm_is_chg_charge_dis(the_chip)) {
+ val->intval = 0;
+ } else {
+ pm_chg_iusbmax_get(the_chip, ¤t_max);
+ val->intval = current_max;
+ }
break;
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_ONLINE:
@@ -1075,6 +1138,13 @@
if (charging_disabled)
return 0;
+ /*
+ * if drawing any current from usb is disabled behave
+ * as if no usb cable is connected
+ */
+ if (pm_is_chg_charge_dis(the_chip))
+ return 0;
+
/* USB charging */
if (psy->type == POWER_SUPPLY_TYPE_USB ||
psy->type == POWER_SUPPLY_TYPE_USB_DCP ||
@@ -1083,22 +1153,6 @@
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 = is_usb_chg_plugged_in(the_chip);
- return 0;
- }
-
- pr_err("Unkown POWER_SUPPLY_TYPE %d\n", psy->type);
break;
default:
return -EINVAL;
@@ -1667,6 +1721,7 @@
{
int usb_present;
+ pm_chg_failed_clear(chip, 1);
usb_present = is_usb_chg_plugged_in(chip);
if (chip->usb_present ^ usb_present) {
notify_usb_of_the_plugin_event(usb_present);
@@ -2328,6 +2383,7 @@
struct pm8921_chg_chip *chip = container_of(dwork,
struct pm8921_chg_chip, update_heartbeat_work);
+ pm_chg_failed_clear(chip, 1);
power_supply_changed(&chip->batt_psy);
schedule_delayed_work(&chip->update_heartbeat_work,
round_jiffies_relative(msecs_to_jiffies
@@ -2456,7 +2512,10 @@
struct pm8921_chg_chip *chip = container_of(dwork,
struct pm8921_chg_chip, eoc_work);
static int count;
- int end = is_charging_finished(chip);
+ int end;
+
+ pm_chg_failed_clear(chip, 1);
+ end = is_charging_finished(chip);
if (end == CHG_NOT_IN_PROGRESS) {
/* enable fastchg irq */
@@ -3457,17 +3516,17 @@
chip->usb_psy.type = POWER_SUPPLY_TYPE_USB,
chip->usb_psy.supplied_to = pm_power_supplied_to,
chip->usb_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
- chip->usb_psy.properties = pm_power_props,
- chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props),
- chip->usb_psy.get_property = pm_power_get_property,
+ chip->usb_psy.properties = pm_power_props_usb,
+ chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props_usb),
+ chip->usb_psy.get_property = pm_power_get_property_usb,
chip->dc_psy.name = "pm8921-dc",
chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS,
chip->dc_psy.supplied_to = pm_power_supplied_to,
chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
- chip->dc_psy.properties = pm_power_props,
- chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props),
- chip->dc_psy.get_property = pm_power_get_property,
+ chip->dc_psy.properties = pm_power_props_mains,
+ chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains),
+ chip->dc_psy.get_property = pm_power_get_property_mains,
chip->batt_psy.name = "battery",
chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY,
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 49e0d0e..fb1a99f 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -344,5 +344,14 @@
chip. It is only supposed to be used when Linux on application
processor is the master in control of XO buffers.
+config REGULATOR_STUB
+ tristate "Stub Regulator"
+ help
+ This driver adds stub regulator support. The driver is absent of any
+ real hardware based implementation. It allows for clients to register
+ their regulator device constraints and use all of the standard
+ regulator interfaces. This is useful for bringing up new platforms
+ when the real hardware based implementation may not be yet available.
+ Clients can use the real regulator device names with proper
+ constraint checking while the real driver is being developed.
endif
-
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 5318cff..74b1f71 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -48,5 +48,6 @@
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_PM8058_XO) += pm8058-xo.o
obj-$(CONFIG_REGULATOR_PM8XXX) += pm8xxx-regulator.o
+obj-$(CONFIG_REGULATOR_STUB) += stub-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/stub-regulator.c b/drivers/regulator/stub-regulator.c
new file mode 100644
index 0000000..afac80a
--- /dev/null
+++ b/drivers/regulator/stub-regulator.c
@@ -0,0 +1,232 @@
+/*
+ * 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/module.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/stub-regulator.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define STUB_REGULATOR_MAX_NAME 40
+
+struct regulator_stub {
+ struct regulator_desc rdesc;
+ struct regulator_dev *rdev;
+ int voltage;
+ bool enabled;
+ int mode;
+ int hpm_min_load;
+ int system_uA;
+ char name[STUB_REGULATOR_MAX_NAME];
+};
+
+static int regulator_stub_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ vreg_priv->voltage = min_uV;
+ return 0;
+}
+
+static int regulator_stub_get_voltage(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ return vreg_priv->voltage;
+}
+
+static int regulator_stub_list_voltage(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ struct regulation_constraints *constraints = rdev->constraints;
+
+ if (selector >= 2)
+ return -EINVAL;
+ else if (selector == 0)
+ return constraints->min_uV;
+ else
+ return constraints->max_uV;
+}
+
+static unsigned int regulator_stub_get_mode(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ return vreg_priv->mode;
+}
+
+static int regulator_stub_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+
+ if (mode != REGULATOR_MODE_NORMAL && mode != REGULATOR_MODE_IDLE) {
+ dev_err(&rdev->dev, "%s: invalid mode requested %u\n",
+ __func__, mode);
+ return -EINVAL;
+ }
+ vreg_priv->mode = mode;
+ return 0;
+}
+
+static unsigned int regulator_stub_get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV, int load_uA)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ unsigned int mode;
+
+ if (load_uA + vreg_priv->system_uA >= vreg_priv->hpm_min_load)
+ mode = REGULATOR_MODE_NORMAL;
+ else
+ mode = REGULATOR_MODE_IDLE;
+
+ return mode;
+}
+
+static int regulator_stub_enable(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ vreg_priv->enabled = true;
+ return 0;
+}
+
+static int regulator_stub_disable(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ vreg_priv->enabled = false;
+ return 0;
+}
+
+static int regulator_stub_is_enabled(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ return vreg_priv->enabled;
+}
+
+/* Real regulator operations. */
+static struct regulator_ops regulator_stub_ops = {
+ .enable = regulator_stub_enable,
+ .disable = regulator_stub_disable,
+ .is_enabled = regulator_stub_is_enabled,
+ .set_voltage = regulator_stub_set_voltage,
+ .get_voltage = regulator_stub_get_voltage,
+ .list_voltage = regulator_stub_list_voltage,
+ .set_mode = regulator_stub_set_mode,
+ .get_mode = regulator_stub_get_mode,
+ .get_optimum_mode = regulator_stub_get_optimum_mode,
+};
+
+static void regulator_stub_cleanup(struct regulator_stub *vreg_priv)
+{
+ if (vreg_priv && vreg_priv->rdev)
+ regulator_unregister(vreg_priv->rdev);
+ kfree(vreg_priv);
+}
+
+static int __devinit regulator_stub_probe(struct platform_device *pdev)
+{
+ struct stub_regulator_pdata *vreg_pdata;
+ struct regulator_desc *rdesc;
+ struct regulator_stub *vreg_priv;
+ int rc;
+
+ vreg_pdata = pdev->dev.platform_data;
+ if (!vreg_pdata) {
+ dev_err(&pdev->dev, "%s: no platform data\n", __func__);
+ return -EINVAL;
+ }
+
+ vreg_priv = kzalloc(sizeof(*vreg_priv), GFP_KERNEL);
+ if (!vreg_priv) {
+ dev_err(&pdev->dev, "%s: Unable to allocate memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+ dev_set_drvdata(&pdev->dev, vreg_priv);
+
+ rdesc = &vreg_priv->rdesc;
+ strncpy(vreg_priv->name, vreg_pdata->init_data.constraints.name,
+ STUB_REGULATOR_MAX_NAME);
+ rdesc->name = vreg_priv->name;
+ rdesc->ops = ®ulator_stub_ops;
+
+ /*
+ * Ensure that voltage set points are handled correctly for regulators
+ * which have a specified voltage constraint range, as well as those
+ * that do not.
+ */
+ if (vreg_pdata->init_data.constraints.min_uV == 0 &&
+ vreg_pdata->init_data.constraints.max_uV == 0)
+ rdesc->n_voltages = 0;
+ else
+ rdesc->n_voltages = 2;
+
+ rdesc->id = pdev->id;
+ rdesc->owner = THIS_MODULE;
+ rdesc->type = REGULATOR_VOLTAGE;
+ vreg_priv->system_uA = vreg_pdata->system_uA;
+ vreg_priv->hpm_min_load = vreg_pdata->hpm_min_load;
+
+ vreg_priv->rdev = regulator_register(rdesc, &pdev->dev,
+ &(vreg_pdata->init_data), vreg_priv);
+ if (IS_ERR(vreg_priv->rdev)) {
+ rc = PTR_ERR(vreg_priv->rdev);
+ vreg_priv->rdev = NULL;
+ dev_err(&pdev->dev, "%s: regulator_register failed\n",
+ __func__);
+ goto err_probe;
+ }
+
+ return 0;
+
+err_probe:
+ regulator_stub_cleanup(vreg_priv);
+ return rc;
+}
+
+static int __devexit regulator_stub_remove(struct platform_device *pdev)
+{
+ struct regulator_stub *vreg_priv = dev_get_drvdata(&pdev->dev);
+
+ regulator_stub_cleanup(vreg_priv);
+ return 0;
+}
+
+static struct platform_driver regulator_stub_driver = {
+ .probe = regulator_stub_probe,
+ .remove = __devexit_p(regulator_stub_remove),
+ .driver = {
+ .name = STUB_REGULATOR_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init regulator_stub_init(void)
+{
+ return platform_driver_register(®ulator_stub_driver);
+}
+postcore_initcall(regulator_stub_init);
+
+static void __exit regulator_stub_exit(void)
+{
+ platform_driver_unregister(®ulator_stub_driver);
+}
+module_exit(regulator_stub_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("stub regulator driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform: " STUB_REGULATOR_DRIVER_NAME);
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 2842cd8..20a290a 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -233,9 +233,9 @@
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;
+ spmidev->num_dev_node = info->num_dev_node;
+ spmidev->dev_node = info->dev_node;
rc = spmi_add_device(spmidev);
if (rc < 0) {
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
index c900647..acca6f1 100644
--- a/drivers/staging/qcache/fmem.c
+++ b/drivers/staging/qcache/fmem.c
@@ -16,6 +16,10 @@
#include <linux/fmem.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#ifdef CONFIG_MEMORY_HOTPLUG
+#include <linux/memory.h>
+#include <linux/memory_hotplug.h>
+#endif
#include "tmem.h"
#include <asm/mach/map.h>
@@ -23,6 +27,11 @@
enum fmem_state fmem_state;
static spinlock_t fmem_state_lock;
+#ifdef CONFIG_MEMORY_HOTPLUG
+static unsigned int section_powered_off[NR_MEM_SECTIONS];
+static unsigned int fmem_section_start, fmem_section_end;
+#endif
+
void *fmem_map_virtual_area(int cacheability)
{
unsigned long addr;
@@ -51,6 +60,10 @@
{
struct fmem_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_MEMORY_HOTPLUG
+ fmem_section_start = pdata->phys >> PA_SECTION_SHIFT;
+ fmem_section_end = (pdata->phys - 1 + pdata->size) >> PA_SECTION_SHIFT;
+#endif
fmem_data.phys = pdata->phys + pdata->reserved_size_low;
fmem_data.size = pdata->size - pdata->reserved_size_low -
pdata->reserved_size_high;
@@ -96,6 +109,10 @@
return snprintf(buf, 3, "t\n");
else if (fmem_state == FMEM_C_STATE)
return snprintf(buf, 3, "c\n");
+#ifdef CONFIG_MEMORY_HOTPLUG
+ else if (fmem_state == FMEM_O_STATE)
+ return snprintf(buf, 3, "o\n");
+#endif
else if (fmem_state == FMEM_UNINITIALIZED)
return snprintf(buf, 15, "uninitialized\n");
return snprintf(buf, 3, "?\n");
@@ -111,6 +128,10 @@
ret = fmem_set_state(FMEM_T_STATE);
else if (!strncmp(buf, "c", 1))
ret = fmem_set_state(FMEM_C_STATE);
+#ifdef CONFIG_MEMORY_HOTPLUG
+ else if (!strncmp(buf, "o", 1))
+ ret = fmem_set_state(FMEM_O_STATE);
+#endif
if (ret)
return ret;
return 1;
@@ -144,8 +165,92 @@
#endif
+#ifdef CONFIG_MEMORY_HOTPLUG
+bool fmem_is_disjoint(unsigned long start_pfn, unsigned long nr_pages)
+{
+ unsigned long fmem_start_pfn, fmem_end_pfn;
+ unsigned long unstable_end_pfn;
+ unsigned long highest_start_pfn, lowest_end_pfn;
+
+ fmem_start_pfn = (fmem_data.phys - fmem_data.reserved_size_low)
+ >> PAGE_SHIFT;
+ fmem_end_pfn = (fmem_data.phys + fmem_data.size +
+ fmem_data.reserved_size_high - 1) >> PAGE_SHIFT;
+ unstable_end_pfn = start_pfn + nr_pages - 1;
+
+ highest_start_pfn = max(fmem_start_pfn, start_pfn);
+ lowest_end_pfn = min(fmem_end_pfn, unstable_end_pfn);
+
+ return lowest_end_pfn < highest_start_pfn;
+}
+
+static int fmem_mem_going_offline_callback(void *arg)
+{
+ struct memory_notify *marg = arg;
+
+ if (fmem_is_disjoint(marg->start_pfn, marg->nr_pages))
+ return 0;
+ return fmem_set_state(FMEM_O_STATE);
+}
+
+static void fmem_mem_online_callback(void *arg)
+{
+ struct memory_notify *marg = arg;
+ int i;
+
+ section_powered_off[marg->start_pfn >> PFN_SECTION_SHIFT] = 0;
+
+ if (fmem_state != FMEM_O_STATE)
+ return;
+
+ for (i = fmem_section_start; i <= fmem_section_end; i++) {
+ if (section_powered_off[i])
+ return;
+ }
+
+ fmem_set_state(FMEM_T_STATE);
+}
+
+static void fmem_mem_offline_callback(void *arg)
+{
+ struct memory_notify *marg = arg;
+
+ section_powered_off[marg->start_pfn >> PFN_SECTION_SHIFT] = 1;
+}
+
+static int fmem_memory_callback(struct notifier_block *self,
+ unsigned long action, void *arg)
+{
+ int ret = 0;
+
+ switch (action) {
+ case MEM_ONLINE:
+ fmem_mem_online_callback(arg);
+ break;
+ case MEM_GOING_OFFLINE:
+ ret = fmem_mem_going_offline_callback(arg);
+ break;
+ case MEM_OFFLINE:
+ fmem_mem_offline_callback(arg);
+ break;
+ case MEM_GOING_ONLINE:
+ case MEM_CANCEL_ONLINE:
+ case MEM_CANCEL_OFFLINE:
+ break;
+ }
+ if (ret)
+ ret = notifier_from_errno(ret);
+ else
+ ret = NOTIFY_OK;
+ return ret;
+}
+#endif
+
static int __init fmem_init(void)
{
+#ifdef CONFIG_MEMORY_HOTPLUG
+ hotplug_memory_notifier(fmem_memory_callback, 0);
+#endif
return platform_driver_register(&fmem_driver);
}
@@ -184,13 +289,25 @@
tmem_enable();
create_sysfs = 1;
goto out_set;
- }
- if (new_state == FMEM_C_STATE) {
+ } else {
ret = -EINVAL;
goto out;
}
}
+#ifdef CONFIG_MEMORY_HOTPLUG
+ if (fmem_state == FMEM_C_STATE && new_state == FMEM_O_STATE) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ if (fmem_state == FMEM_O_STATE && new_state == FMEM_C_STATE) {
+ pr_warn("attempting to use powered off memory as fmem\n");
+ ret = -EAGAIN;
+ goto out;
+ }
+#endif
+
if (new_state == FMEM_T_STATE) {
void *v;
v = fmem_map_virtual_area(MT_DEVICE_CACHED);
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index ef28844..c6ba24e 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -18,6 +18,7 @@
#include <linux/mutex.h>
#include <linux/msm_tsens.h>
#include <linux/workqueue.h>
+#include <linux/cpu.h>
#define DEF_TEMP_SENSOR 0
#define DEF_THERMAL_CHECK_MS 1000
@@ -34,13 +35,11 @@
module_param(allowed_max_freq, int, 0);
module_param(check_interval_ms, int, 0);
-static DEFINE_PER_CPU(struct cpufreq_policy*, policy);
-static struct mutex policy_mutex;
static struct delayed_work check_temp_work;
-static int update_cpu_max_freq(int cpu, int max_freq)
+static int update_cpu_max_freq(struct cpufreq_policy *cpu_policy,
+ int cpu, int max_freq)
{
- struct cpufreq_policy *cpu_policy = per_cpu(policy, cpu);
int ret = 0;
if (!cpu_policy)
@@ -68,7 +67,6 @@
int cpu = 0;
int ret = 0;
- mutex_lock(&policy_mutex);
tsens_dev.sensor_num = DEF_TEMP_SENSOR;
ret = tsens_get_temp(&tsens_dev, &temp);
if (ret) {
@@ -78,70 +76,57 @@
}
for_each_possible_cpu(cpu) {
- cpu_policy = per_cpu(policy, cpu);
+ update_policy = 0;
+ cpu_policy = cpufreq_cpu_get(cpu);
if (!cpu_policy) {
- pr_debug("msm_thermal: No CPUFreq policy found for "
- "cpu %d\n", cpu);
+ pr_debug("msm_thermal: NULL policy on cpu %d\n", cpu);
continue;
}
if (temp >= allowed_max_high) {
if (cpu_policy->max > allowed_max_freq) {
update_policy = 1;
max_freq = allowed_max_freq;
+ } else {
+ pr_debug("msm_thermal: policy max for cpu %d "
+ "already < allowed_max_freq\n", cpu);
}
} else if (temp < allowed_max_low) {
if (cpu_policy->max < cpu_policy->cpuinfo.max_freq) {
max_freq = cpu_policy->cpuinfo.max_freq;
update_policy = 1;
+ } else {
+ pr_debug("msm_thermal: policy max for cpu %d "
+ "already at max allowed\n", cpu);
}
}
if (update_policy)
- update_cpu_max_freq(cpu, max_freq);
+ update_cpu_max_freq(cpu_policy, cpu, max_freq);
+
+ cpufreq_cpu_put(cpu_policy);
}
reschedule:
if (enabled)
schedule_delayed_work(&check_temp_work,
msecs_to_jiffies(check_interval_ms));
-
- mutex_unlock(&policy_mutex);
}
-static int msm_thermal_notifier(struct notifier_block *nb,
- unsigned long event, void *data)
-{
- if (event == CPUFREQ_START) {
- struct cpufreq_policy *cpu_policy = data;
- mutex_lock(&policy_mutex);
- per_cpu(policy, cpu_policy->cpu) = cpu_policy;
- mutex_unlock(&policy_mutex);
- }
-
- return 0;
-}
-
-static struct notifier_block msm_thermal_notifier_block = {
- .notifier_call = msm_thermal_notifier,
-};
-
static void disable_msm_thermal(void)
{
int cpu = 0;
struct cpufreq_policy *cpu_policy = NULL;
- cpufreq_unregister_notifier(&msm_thermal_notifier_block,
- CPUFREQ_POLICY_NOTIFIER);
- cancel_delayed_work(&check_temp_work);
-
- mutex_lock(&policy_mutex);
for_each_possible_cpu(cpu) {
- cpu_policy = per_cpu(policy, cpu);
- if (cpu_policy &&
- cpu_policy->max < cpu_policy->cpuinfo.max_freq)
- update_cpu_max_freq(cpu, cpu_policy->cpuinfo.max_freq);
+ cpu_policy = cpufreq_cpu_get(cpu);
+ if (cpu_policy) {
+ if (cpu_policy->max < cpu_policy->cpuinfo.max_freq)
+ update_cpu_max_freq(cpu_policy, cpu,
+ cpu_policy->
+ cpuinfo.max_freq);
+ cpufreq_cpu_put(cpu_policy);
+ }
}
- mutex_unlock(&policy_mutex);
}
static int set_enabled(const char *val, const struct kernel_param *kp)
@@ -172,12 +157,8 @@
int ret = 0;
enabled = 1;
- mutex_init(&policy_mutex);
INIT_DELAYED_WORK(&check_temp_work, check_temp);
- ret = cpufreq_register_notifier(&msm_thermal_notifier_block,
- CPUFREQ_POLICY_NOTIFIER);
-
schedule_delayed_work(&check_temp_work, 0);
return ret;
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index fa7d518..780a3c2 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -51,7 +51,9 @@
UARTDM_NCF_TX,
UARTDM_DMEN,
UARTDM_BCR,
- UARTDM_LAST
+ UARTDM_TXFS,
+ UARTDM_RXFS,
+ UARTDM_LAST,
};
#define UARTDM_MR1_ADDR 0x0
@@ -118,6 +120,7 @@
#define UARTDM_ISR_ADDR 0x14
#define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
+#define UARTDM_TXFS_ADDR 0x4C
#define UARTDM_RXFS_ADDR 0x50
/* Register field Mask Mapping */
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 8a125f6..9a8d552 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -61,6 +61,7 @@
int is_uartdm;
unsigned int old_snap_state;
unsigned int ver_id;
+ int tx_timeout;
};
#define UARTDM_VERSION_11_13 0
@@ -89,6 +90,8 @@
[UARTDM_DMRX] = UARTDM_DMRX_ADDR,
[UARTDM_NCF_TX] = UARTDM_NCF_TX_ADDR,
[UARTDM_DMEN] = UARTDM_DMEN_ADDR,
+ [UARTDM_TXFS] = UARTDM_TXFS_ADDR,
+ [UARTDM_RXFS] = UARTDM_RXFS_ADDR,
},
[UARTDM_VERSION_14] = {
[UARTDM_MR1] = 0x0,
@@ -108,6 +111,8 @@
[UARTDM_DMRX] = 0x34,
[UARTDM_NCF_TX] = 0x40,
[UARTDM_DMEN] = 0x3c,
+ [UARTDM_TXFS] = 0x4c,
+ [UARTDM_RXFS] = 0x50,
},
};
@@ -119,6 +124,7 @@
};
static struct dentry *debug_base;
static inline void wait_for_xmitr(struct uart_port *port, int bits);
+static int get_console_state(struct uart_port *port);
static inline void msm_hsl_write(struct uart_port *port,
unsigned int val, unsigned int off)
{
@@ -611,6 +617,9 @@
break;
}
+ /* Set timeout to be ~100x the character transmit time */
+ msm_hsl_port->tx_timeout = 1000000000 / baud;
+
vid = msm_hsl_port->ver_id;
msm_hsl_write(port, baud_code, regmap[vid][UARTDM_CSR]);
@@ -1041,12 +1050,51 @@
return &msm_hsl_uart_ports[line].uart;
}
+static unsigned int msm_hsl_console_state[8];
+
+static void dump_hsl_regs(struct uart_port *port)
+{
+ struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
+ unsigned int vid = msm_hsl_port->ver_id;
+ unsigned int sr, isr, mr1, mr2, ncf, txfs, rxfs, con_state;
+
+ sr = msm_hsl_read(port, regmap[vid][UARTDM_SR]);
+ isr = msm_hsl_read(port, regmap[vid][UARTDM_ISR]);
+ mr1 = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
+ mr2 = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
+ ncf = msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
+ txfs = msm_hsl_read(port, regmap[vid][UARTDM_TXFS]);
+ rxfs = msm_hsl_read(port, regmap[vid][UARTDM_RXFS]);
+ con_state = get_console_state(port);
+
+ msm_hsl_console_state[0] = sr;
+ msm_hsl_console_state[1] = isr;
+ msm_hsl_console_state[2] = mr1;
+ msm_hsl_console_state[3] = mr2;
+ msm_hsl_console_state[4] = ncf;
+ msm_hsl_console_state[5] = txfs;
+ msm_hsl_console_state[6] = rxfs;
+ msm_hsl_console_state[7] = con_state;
+
+ pr_info("%s(): Timeout: %d uS\n", __func__, msm_hsl_port->tx_timeout);
+ pr_info("%s(): SR: %08x\n", __func__, sr);
+ pr_info("%s(): ISR: %08x\n", __func__, isr);
+ pr_info("%s(): MR1: %08x\n", __func__, mr1);
+ pr_info("%s(): MR2: %08x\n", __func__, mr2);
+ pr_info("%s(): NCF: %08x\n", __func__, ncf);
+ pr_info("%s(): TXFS: %08x\n", __func__, txfs);
+ pr_info("%s(): RXFS: %08x\n", __func__, rxfs);
+ pr_info("%s(): Console state: %d\n", __func__, con_state);
+}
+
/*
* Wait for transmitter & holding register to empty
* Derived from wait_for_xmitr in 8250 serial driver by Russell King */
void wait_for_xmitr(struct uart_port *port, int bits)
{
- unsigned int vid = UART_TO_MSM(port)->ver_id;
+ struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
+ unsigned int vid = msm_hsl_port->ver_id;
+ int count = 0;
if (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
UARTDM_SR_TXEMT_BMSK)) {
@@ -1055,6 +1103,10 @@
udelay(1);
touch_nmi_watchdog();
cpu_relax();
+ if (++count == msm_hsl_port->tx_timeout) {
+ dump_hsl_regs(port);
+ panic("MSM HSL wait_for_xmitr is stuck!");
+ }
}
msm_hsl_write(port, CLEAR_TX_READY, regmap[vid][UARTDM_CR]);
}
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 7e731de..91c3123 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -164,6 +164,18 @@
.bNumConfigurations = 1,
};
+static struct usb_otg_descriptor otg_descriptor = {
+ .bLength = sizeof otg_descriptor,
+ .bDescriptorType = USB_DT_OTG,
+ .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
+ .bcdOTG = __constant_cpu_to_le16(0x0200),
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+ (struct usb_descriptor_header *) &otg_descriptor,
+ NULL,
+};
+
static struct usb_configuration android_config_driver = {
.label = "android",
.unbind = android_unbind_config,
@@ -1352,6 +1364,9 @@
strings_dev[STRING_SERIAL_IDX].id = id;
device_desc.iSerialNumber = id;
+ if (gadget_is_otg(cdev->gadget))
+ android_config_driver.descriptors = otg_desc;
+
gcnum = usb_gadget_controller_number(gadget);
if (gcnum >= 0)
device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 8ea4632..fac777c 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -47,7 +47,8 @@
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
- CI13XXX_ZERO_ITC,
+ CI13XXX_ZERO_ITC |
+ CI13XXX_IS_OTG,
.notify_event = ci13xxx_msm_notify_event,
};
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
index 135c84d..12b6774 100644
--- a/drivers/usb/gadget/ci13xxx_msm_hsic.c
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -35,14 +35,17 @@
#define MSM_USB_BASE (mhsic->regs)
-#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
-#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
-#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
-#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
-#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
-#define HSIC_CFG_REG 0x30
-#define HSIC_IO_CAL_PER_REG 0x33
-#define HSIC_DBG1_REG 0x38
+#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+#define USB_PHY_VDD_DIG_VOL_SUSP_MIN 500000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
+#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
+#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
+#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
+#define HSIC_CFG_REG 0x30
+#define HSIC_IO_CAL_PER_REG 0x33
+#define HSIC_DBG1_REG 0x38
struct msm_hsic_per *the_mhsic;
@@ -57,6 +60,11 @@
bool async_int;
void __iomem *regs;
int irq;
+ atomic_t in_lpm;
+ struct wake_lock wlock;
+ struct msm_xo_voter *xo_handle;
+ struct workqueue_struct *wq;
+ struct work_struct suspend_w;
};
static int msm_hsic_init_vddcx(struct msm_hsic_per *mhsic, int init)
@@ -302,6 +310,227 @@
}
}
+
+#ifdef CONFIG_PM_SLEEP
+static int msm_hsic_suspend(struct msm_hsic_per *mhsic)
+{
+ int cnt = 0, ret;
+ u32 val;
+
+ if (atomic_read(&mhsic->in_lpm)) {
+ dev_dbg(mhsic->dev, "%s called while in lpm\n", __func__);
+ return 0;
+ }
+ disable_irq(mhsic->irq);
+
+ /*
+ * 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.
+ */
+ val = readl_relaxed(USB_PORTSC) | PORTSC_PHCD;
+ writel_relaxed(val, USB_PORTSC);
+
+ while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
+ if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
+ break;
+ udelay(1);
+ cnt++;
+ }
+
+ if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
+ dev_err(mhsic->dev, "Unable to suspend PHY\n");
+ msm_hsic_reset(mhsic);
+ }
+
+ /*
+ * 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(mhsic->iface_clk);
+ clk_disable(mhsic->core_clk);
+ clk_disable(mhsic->phy_clk);
+ clk_disable(mhsic->cal_clk);
+
+ ret = msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_OFF);
+ if (ret)
+ dev_err(mhsic->dev, "%s failed to devote for TCXO %d\n"
+ , __func__, ret);
+
+ ret = regulator_set_voltage(mhsic->hsic_vddcx,
+ USB_PHY_VDD_DIG_VOL_SUSP_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret < 0)
+ dev_err(mhsic->dev, "unable to set vddcx voltage: min:0.5v max:1.32v\n");
+
+ if (device_may_wakeup(mhsic->dev))
+ enable_irq_wake(mhsic->irq);
+
+ atomic_set(&mhsic->in_lpm, 1);
+ enable_irq(mhsic->irq);
+ wake_unlock(&mhsic->wlock);
+
+ dev_info(mhsic->dev, "HSIC-USB in low power mode\n");
+
+ return 0;
+}
+
+static int msm_hsic_resume(struct msm_hsic_per *mhsic)
+{
+ int cnt = 0, ret;
+ unsigned temp;
+
+ if (!atomic_read(&mhsic->in_lpm)) {
+ dev_dbg(mhsic->dev, "%s called while not in lpm\n", __func__);
+ return 0;
+ }
+
+ wake_lock(&mhsic->wlock);
+ ret = regulator_set_voltage(mhsic->hsic_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret < 0)
+ dev_err(mhsic->dev,
+ "unable to set vddcx voltage: min:1.045v max:1.32v\n");
+
+ ret = msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_ON);
+ if (ret)
+ dev_err(mhsic->dev, "%s failed to vote for TCXO %d\n",
+ __func__, ret);
+
+ clk_enable(mhsic->iface_clk);
+ clk_enable(mhsic->core_clk);
+ clk_enable(mhsic->phy_clk);
+ clk_enable(mhsic->cal_clk);
+
+ 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);
+ while (cnt < PHY_RESUME_TIMEOUT_USEC) {
+ if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
+ (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
+ break;
+ udelay(1);
+ cnt++;
+ }
+
+ if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
+ /*
+ * This is a fatal error. Reset the link and
+ * PHY to make hsic working.
+ */
+ dev_err(mhsic->dev, "Unable to resume USB. Reset the hsic\n");
+ msm_hsic_reset(mhsic);
+ }
+skip_phy_resume:
+ if (device_may_wakeup(mhsic->dev))
+ disable_irq_wake(mhsic->irq);
+
+ atomic_set(&mhsic->in_lpm, 0);
+
+ if (mhsic->async_int) {
+ mhsic->async_int = false;
+ enable_irq(mhsic->irq);
+ }
+
+ dev_info(mhsic->dev, "HSIC-USB exited from low power mode\n");
+
+ return 0;
+}
+
+static int msm_hsic_pm_suspend(struct device *dev)
+{
+ struct msm_hsic_per *mhsic = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "MSM HSIC Peripheral PM suspend\n");
+
+ return msm_hsic_suspend(mhsic);
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_hsic_pm_resume(struct device *dev)
+{
+ dev_dbg(dev, "MSM HSIC Peripheral PM resume\n");
+
+ /*
+ * Do not resume hardware as part of system resume,
+ * rather, wait for the ASYNC INT from the h/w
+ */
+ return 0;
+}
+#else
+static int msm_hsic_pm_resume(struct device *dev)
+{
+ struct msm_hsic_per *mhsic = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "MSM HSIC Peripheral PM resume\n");
+
+ return msm_hsic_resume(mhsic);
+}
+#endif
+
+static void msm_hsic_pm_suspend_work(struct work_struct *w)
+{
+ pm_runtime_put_noidle(the_mhsic->dev);
+ pm_runtime_suspend(the_mhsic->dev);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_hsic_runtime_idle(struct device *dev)
+{
+ dev_dbg(dev, "MSM HSIC Peripheral runtime idle\n");
+
+ return 0;
+}
+
+static int msm_hsic_runtime_suspend(struct device *dev)
+{
+ struct msm_hsic_per *mhsic = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "MSM HSIC Peripheral runtime suspend\n");
+
+ return msm_hsic_suspend(mhsic);
+}
+
+static int msm_hsic_runtime_resume(struct device *dev)
+{
+ struct msm_hsic_per *mhsic = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "MSM HSIC Peripheral runtime resume\n");
+ pm_runtime_get_noresume(mhsic->dev);
+
+ return msm_hsic_resume(mhsic);
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
+ SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
+ msm_hsic_runtime_idle)
+};
+#endif
+
/**
* Dummy match function - will be called only for HSIC msm
* device (msm_device_gadget_hsic_peripheral).
@@ -320,6 +549,15 @@
static irqreturn_t msm_udc_hsic_irq(int irq, void *data)
{
+ struct msm_hsic_per *mhsic = data;
+
+ if (atomic_read(&mhsic->in_lpm)) {
+ disable_irq_nosync(mhsic->irq);
+ mhsic->async_int = true;
+ pm_request_resume(mhsic->dev);
+ return IRQ_HANDLED;
+ }
+
return udc_irq();
}
@@ -338,6 +576,10 @@
dev_dbg(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
msm_hsic_start();
break;
+ case CI13XXX_CONTROLLER_SUSPEND_EVENT:
+ dev_dbg(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
+ queue_work(mhsic->wq, &mhsic->suspend_w);
+ break;
default:
dev_dbg(dev, "unknown ci13xxx_udc event\n");
break;
@@ -378,6 +620,15 @@
goto error;
}
+ mhsic->wq = alloc_workqueue("mhsic_wq", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ if (!mhsic->wq) {
+ pr_err("%s: Unable to create workqueue mhsic wq\n",
+ __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+ INIT_WORK(&mhsic->suspend_w, msm_hsic_pm_suspend_work);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Unable to get memory resource\n");
@@ -392,6 +643,21 @@
}
dev_info(&pdev->dev, "HSIC Peripheral regs = %p\n", mhsic->regs);
+ mhsic->xo_handle = msm_xo_get(MSM_XO_CXO, "hsic_peripheral");
+ if (IS_ERR(mhsic->xo_handle)) {
+ dev_err(&pdev->dev, "%s not able to get the handle "
+ "to vote for TCXO\n", __func__);
+ ret = PTR_ERR(mhsic->xo_handle);
+ goto unmap;
+ }
+
+ ret = msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_ON);
+ if (ret) {
+ dev_err(&pdev->dev, "%s failed to vote for TCXO %d\n",
+ __func__, ret);
+ goto free_xo_handle;
+ }
+
ret = msm_hsic_enable_clocks(pdev, mhsic, true);
if (ret) {
@@ -422,16 +688,21 @@
msm_hsic_connect_peripheral(&pdev->dev);
+ device_init_wakeup(&pdev->dev, 1);
+ wake_lock_init(&mhsic->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
+ wake_lock(&mhsic->wlock);
+
ret = request_irq(mhsic->irq, msm_udc_hsic_irq,
- IRQF_SHARED, pdev->name, pdev);
+ IRQF_SHARED, pdev->name, mhsic);
if (ret < 0) {
dev_err(&pdev->dev, "request_irq failed\n");
ret = -ENODEV;
goto udc_remove;
}
- pm_runtime_no_callbacks(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
return 0;
udc_remove:
@@ -440,9 +711,13 @@
msm_hsic_init_vddcx(mhsic, 0);
deinit_clocks:
msm_hsic_enable_clocks(pdev, mhsic, 0);
+ msm_xo_mode_vote(mhsic->xo_handle, MSM_XO_MODE_OFF);
+free_xo_handle:
+ msm_xo_put(mhsic->xo_handle);
unmap:
iounmap(mhsic->regs);
error:
+ destroy_workqueue(mhsic->wq);
kfree(mhsic);
return ret;
}
@@ -452,19 +727,29 @@
struct msm_hsic_per *mhsic = platform_get_drvdata(pdev);
device_init_wakeup(&pdev->dev, 0);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+
msm_hsic_init_vddcx(mhsic, 0);
msm_hsic_enable_clocks(pdev, mhsic, 0);
+ msm_xo_put(mhsic->xo_handle);
+ wake_lock_destroy(&mhsic->wlock);
+ destroy_workqueue(mhsic->wq);
udc_remove();
iounmap(mhsic->regs);
kfree(mhsic);
return 0;
}
+
static struct platform_driver msm_hsic_peripheral_driver = {
.probe = msm_hsic_probe,
.remove = __devexit_p(hsic_msm_remove),
.driver = {
.name = "msm_hsic_peripheral",
+#ifdef CONFIG_PM
+ .pm = &msm_hsic_dev_pm_ops,
+#endif
},
};
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 0fc9a03..562b36a 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1918,6 +1918,11 @@
udc->configured = 0;
spin_unlock_irqrestore(udc->lock, flags);
+ gadget->b_hnp_enable = 0;
+ gadget->a_hnp_support = 0;
+ gadget->host_request = 0;
+ gadget->otg_srp_reqd = 0;
+
/* flush all endpoints */
gadget_for_each_ep(ep, gadget) {
usb_ep_fifo_flush(ep);
@@ -2046,8 +2051,15 @@
}
if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
- /* Assume that device is bus powered for now. */
- *((u16 *)req->buf) = _udc->remote_wakeup << 1;
+ if (setup->wIndex == OTG_STATUS_SELECTOR) {
+ *((u8 *)req->buf) = _udc->gadget.host_request <<
+ HOST_REQUEST_FLAG;
+ req->length = 1;
+ } else {
+ /* Assume that device is bus powered for now. */
+ *((u16 *)req->buf) = _udc->remote_wakeup << 1;
+ }
+ /* TODO: D1 - Remote Wakeup; D0 - Self Powered */
retval = 0;
} else if ((setup->bRequestType & USB_RECIP_MASK) \
== USB_RECIP_ENDPOINT) {
@@ -2297,8 +2309,7 @@
type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
type != (USB_DIR_IN|USB_RECIP_INTERFACE))
goto delegate;
- if (le16_to_cpu(req.wLength) != 2 ||
- le16_to_cpu(req.wValue) != 0)
+ if (le16_to_cpu(req.wValue) != 0)
break;
err = isr_get_status_response(udc, &req);
break;
@@ -2342,6 +2353,16 @@
udc->remote_wakeup = 1;
err = isr_setup_status_phase(udc);
break;
+ case USB_DEVICE_B_HNP_ENABLE:
+ udc->gadget.b_hnp_enable = 1;
+ err = isr_setup_status_phase(udc);
+ break;
+ case USB_DEVICE_A_HNP_SUPPORT:
+ udc->gadget.a_hnp_support = 1;
+ err = isr_setup_status_phase(udc);
+ break;
+ case USB_DEVICE_A_ALT_HNP_SUPPORT:
+ break;
case USB_DEVICE_TEST_MODE:
tmode = le16_to_cpu(req.wIndex) >> 8;
switch (tmode) {
@@ -2354,11 +2375,21 @@
err = isr_setup_status_phase(
udc);
break;
+ case TEST_OTG_SRP_REQD:
+ udc->gadget.otg_srp_reqd = 1;
+ err = isr_setup_status_phase(
+ udc);
+ break;
+ case TEST_OTG_HNP_REQD:
+ udc->gadget.host_request = 1;
+ err = isr_setup_status_phase(
+ udc);
+ break;
default:
break;
}
default:
- goto delegate;
+ break;
}
} else {
goto delegate;
@@ -3145,6 +3176,9 @@
udc->suspended = 1;
spin_unlock(udc->lock);
udc->driver->suspend(&udc->gadget);
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_SUSPEND_EVENT);
spin_lock(udc->lock);
}
isr_statistics.sli++;
@@ -3206,7 +3240,10 @@
udc->gadget.ops = &usb_gadget_ops;
udc->gadget.speed = USB_SPEED_UNKNOWN;
udc->gadget.is_dualspeed = 1;
- udc->gadget.is_otg = 0;
+ if (udc->udc_driver->flags & CI13XXX_IS_OTG)
+ udc->gadget.is_otg = 1;
+ else
+ udc->gadget.is_otg = 0;
udc->gadget.name = driver->name;
INIT_LIST_HEAD(&udc->gadget.ep_list);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index fce611a..684517b 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -125,9 +125,11 @@
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
#define CI13XXX_DISABLE_STREAMING BIT(3)
#define CI13XXX_ZERO_ITC BIT(4)
+#define CI13XXX_IS_OTG BIT(5)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_CONNECT_EVENT 1
+#define CI13XXX_CONTROLLER_SUSPEND_EVENT 2
void (*notify_event) (struct ci13xxx *udc, unsigned event);
};
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 39c53da..19ad77f 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -67,7 +67,7 @@
spinlock_t req_lock; /* guard {rx,tx}_reqs */
struct list_head tx_reqs, rx_reqs;
- atomic_t tx_qlen;
+ unsigned tx_qlen;
struct sk_buff_head rx_frames;
@@ -484,7 +484,6 @@
spin_unlock(&dev->req_lock);
dev_kfree_skb_any(skb);
- atomic_dec(&dev->tx_qlen);
if (netif_carrier_ok(dev->net))
netif_wake_queue(dev->net);
}
@@ -599,10 +598,18 @@
req->length = length;
/* throttle highspeed IRQ rate back slightly */
- if (gadget_is_dualspeed(dev->gadget))
- req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
- ? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
- : 0;
+ if (gadget_is_dualspeed(dev->gadget) &&
+ (dev->gadget->speed == USB_SPEED_HIGH)) {
+ dev->tx_qlen++;
+ if (dev->tx_qlen == qmult) {
+ req->no_interrupt = 0;
+ dev->tx_qlen = 0;
+ } else {
+ req->no_interrupt = 1;
+ }
+ } else {
+ req->no_interrupt = 0;
+ }
retval = usb_ep_queue(in, req, GFP_ATOMIC);
switch (retval) {
@@ -611,7 +618,6 @@
break;
case 0:
net->trans_start = jiffies;
- atomic_inc(&dev->tx_qlen);
}
if (retval) {
@@ -637,7 +643,7 @@
rx_fill(dev, gfp_flags);
/* and open the tx floodgates */
- atomic_set(&dev->tx_qlen, 0);
+ dev->tx_qlen = 0;
netif_wake_queue(dev->net);
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index d438555..657bc42 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -1203,10 +1203,9 @@
ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
#ifdef CONFIG_USB_OTG
if (hcd->self.otg_port == (wIndex + 1) &&
- hcd->self.b_hnp_enable &&
- ehci->start_hnp) {
+ hcd->self.b_hnp_enable) {
set_bit(wIndex, &ehci->suspended_ports);
- ehci->start_hnp(ehci);
+ otg_start_hnp(ehci->transceiver);
break;
}
#endif
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index dd3ec34..795e7a8 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/irq.h>
#include <linux/err.h>
#include <linux/wakelock.h>
#include <linux/pm_runtime.h>
@@ -53,6 +54,7 @@
struct msm_xo_voter *xo_handle;
struct wake_lock wlock;
int peripheral_status_irq;
+ int wakeup_irq;
};
static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
@@ -734,7 +736,7 @@
{
struct msm_hsic_hcd *mehci = dev_id;
- pr_debug("%s: mechi:%p dev_id:%p\n", __func__, mehci, dev_id);
+ pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
if (mehci)
msm_hsic_config_gpios(mehci, 0);
@@ -742,6 +744,16 @@
return IRQ_HANDLED;
}
+static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
+{
+ struct msm_hsic_hcd *mehci = data;
+
+ dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt\n", __func__);
+
+ return IRQ_HANDLED;
+}
+
+
static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -856,6 +868,24 @@
__func__, mehci->peripheral_status_irq, ret);
}
+ /* configure wakeup irq */
+ ret = platform_get_irq(pdev, 2);
+ if (ret > 0) {
+ mehci->wakeup_irq = ret;
+ dev_dbg(&pdev->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
+ ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
+ IRQF_TRIGGER_LOW,
+ "msm_hsic_wakeup", mehci);
+ if (!ret) {
+ disable_irq_nosync(mehci->wakeup_irq);
+ enable_irq_wake(mehci->wakeup_irq);
+ } else {
+ dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
+ mehci->wakeup_irq, ret);
+ mehci->wakeup_irq = 0;
+ }
+ }
+
/*
* This pdev->dev is assigned parent of root-hub by USB core,
* hence, runtime framework automatically calls this driver's
@@ -893,6 +923,10 @@
if (mehci->peripheral_status_irq)
free_irq(mehci->peripheral_status_irq, mehci);
+ if (mehci->wakeup_irq) {
+ disable_irq_wake(mehci->wakeup_irq);
+ free_irq(mehci->wakeup_irq, mehci);
+ }
device_init_wakeup(&pdev->dev, 0);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index f45f257..5649fd0 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -176,6 +176,7 @@
goto put_transceiver;
}
+ hcd_to_ehci(hcd)->transceiver = otg;
device_init_wakeup(&pdev->dev, 1);
pm_runtime_enable(&pdev->dev);
@@ -199,6 +200,7 @@
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
+ hcd_to_ehci(hcd)->transceiver = NULL;
otg_set_host(otg, NULL);
otg_put_transceiver(otg);
diff --git a/drivers/usb/host/ehci-msm72k.c b/drivers/usb/host/ehci-msm72k.c
index b3939ef..bf2cbd1 100644
--- a/drivers/usb/host/ehci-msm72k.c
+++ b/drivers/usb/host/ehci-msm72k.c
@@ -605,19 +605,6 @@
return retval;
}
-#ifdef CONFIG_USB_OTG
-static void ehci_msm_start_hnp(struct ehci_hcd *ehci)
-{
- struct usb_hcd *hcd = ehci_to_hcd(ehci);
- struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
-
- /* OTG driver handles HNP */
- otg_start_hnp(mhcd->xceiv);
-}
-#else
-#define ehci_msm_start_hnp NULL
-#endif
-
static int msm_xusb_init_host(struct platform_device *pdev,
struct msmusb_hcd *mhcd)
{
@@ -645,9 +632,9 @@
otg = container_of(mhcd->xceiv, struct msm_otg, otg);
hcd->regs = otg->regs;
otg->start_host = msm_hsusb_start_host;
- ehci->start_hnp = ehci_msm_start_hnp;
ret = otg_set_host(mhcd->xceiv, &hcd->self);
+ ehci->transceiver = mhcd->xceiv;
break;
case USB_PHY_SERIAL_PMIC:
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
@@ -753,6 +740,7 @@
case USB_PHY_INTEGRATED:
if (pdata->vbus_init)
pdata->vbus_init(0);
+ hcd_to_ehci(hcd)->transceiver = NULL;
otg_set_host(mhcd->xceiv, NULL);
otg_put_transceiver(mhcd->xceiv);
cancel_work_sync(&mhcd->otg_work);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 05c7faf..2c4f291 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -124,8 +124,6 @@
ktime_t last_periodic_enable;
u32 command;
- void (*start_hnp)(struct ehci_hcd *ehci);
-
/* SILICON QUIRKS */
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index dd07d4e..7ee02df 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -33,6 +33,7 @@
#include <linux/usb/ulpi.h>
#include <linux/usb/gadget.h>
#include <linux/usb/hcd.h>
+#include <linux/usb/quirks.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/regulator/consumer.h>
@@ -49,8 +50,8 @@
#define DRIVER_NAME "msm_otg"
#define ID_TIMER_FREQ (jiffies + msecs_to_jiffies(2000))
+#define ID_TIMER_INITIAL_FREQ (jiffies + msecs_to_jiffies(1000))
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
-
#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
@@ -581,25 +582,190 @@
return 0;
}
+static const char *timer_string(int bit)
+{
+ switch (bit) {
+ case A_WAIT_VRISE: return "a_wait_vrise";
+ case A_WAIT_VFALL: return "a_wait_vfall";
+ case B_SRP_FAIL: return "b_srp_fail";
+ case A_WAIT_BCON: return "a_wait_bcon";
+ case A_AIDL_BDIS: return "a_aidl_bdis";
+ case A_BIDL_ADIS: return "a_bidl_adis";
+ case B_ASE0_BRST: return "b_ase0_brst";
+ case A_TST_MAINT: return "a_tst_maint";
+ case B_TST_SRP: return "b_tst_srp";
+ case B_TST_CONFIG: return "b_tst_config";
+ default: return "UNDEFINED";
+ }
+}
+
+static enum hrtimer_restart msm_otg_timer_func(struct hrtimer *hrtimer)
+{
+ struct msm_otg *motg = container_of(hrtimer, struct msm_otg, timer);
+
+ switch (motg->active_tmout) {
+ case A_WAIT_VRISE:
+ /* TODO: use vbus_vld interrupt */
+ set_bit(A_VBUS_VLD, &motg->inputs);
+ break;
+ case A_TST_MAINT:
+ /* OTG PET: End session after TA_TST_MAINT */
+ set_bit(A_BUS_DROP, &motg->inputs);
+ break;
+ case B_TST_SRP:
+ /*
+ * OTG PET: Initiate SRP after TB_TST_SRP of
+ * previous session end.
+ */
+ set_bit(B_BUS_REQ, &motg->inputs);
+ break;
+ case B_TST_CONFIG:
+ clear_bit(A_CONN, &motg->inputs);
+ break;
+ default:
+ set_bit(motg->active_tmout, &motg->tmouts);
+ }
+
+ pr_debug("expired %s timer\n", timer_string(motg->active_tmout));
+ queue_work(system_nrt_wq, &motg->sm_work);
+ return HRTIMER_NORESTART;
+}
+
+static void msm_otg_del_timer(struct msm_otg *motg)
+{
+ int bit = motg->active_tmout;
+
+ pr_debug("deleting %s timer. remaining %lld msec\n", timer_string(bit),
+ div_s64(ktime_to_us(hrtimer_get_remaining(
+ &motg->timer)), 1000));
+ hrtimer_cancel(&motg->timer);
+ clear_bit(bit, &motg->tmouts);
+}
+
+static void msm_otg_start_timer(struct msm_otg *motg, int time, int bit)
+{
+ clear_bit(bit, &motg->tmouts);
+ motg->active_tmout = bit;
+ pr_debug("starting %s timer\n", timer_string(bit));
+ hrtimer_start(&motg->timer,
+ ktime_set(time / 1000, (time % 1000) * 1000000),
+ HRTIMER_MODE_REL);
+}
+
+static void msm_otg_init_timer(struct msm_otg *motg)
+{
+ hrtimer_init(&motg->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ motg->timer.function = msm_otg_timer_func;
+}
+
+static int msm_otg_start_hnp(struct otg_transceiver *otg)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+ if (otg->state != OTG_STATE_A_HOST) {
+ pr_err("HNP can not be initiated in %s state\n",
+ otg_state_string(otg->state));
+ return -EINVAL;
+ }
+
+ pr_debug("A-Host: HNP initiated\n");
+ clear_bit(A_BUS_REQ, &motg->inputs);
+ queue_work(system_nrt_wq, &motg->sm_work);
+ return 0;
+}
+
+static int msm_otg_start_srp(struct otg_transceiver *otg)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+ u32 val;
+ int ret = 0;
+
+ if (otg->state != OTG_STATE_B_IDLE) {
+ pr_err("SRP can not be initiated in %s state\n",
+ otg_state_string(otg->state));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if ((jiffies - motg->b_last_se0_sess) < msecs_to_jiffies(TB_SRP_INIT)) {
+ pr_debug("initial conditions of SRP are not met. Try again"
+ "after some time\n");
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ pr_debug("B-Device SRP started\n");
+
+ /*
+ * PHY won't pull D+ high unless it detects Vbus valid.
+ * Since by definition, SRP is only done when Vbus is not valid,
+ * software work-around needs to be used to spoof the PHY into
+ * thinking it is valid. This can be done using the VBUSVLDEXTSEL and
+ * VBUSVLDEXT register bits.
+ */
+ ulpi_write(otg, 0x03, 0x97);
+ /*
+ * Harware auto assist data pulsing: Data pulse is given
+ * for 7msec; wait for vbus
+ */
+ val = readl_relaxed(USB_OTGSC);
+ writel_relaxed((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, USB_OTGSC);
+
+ /* VBUS plusing is obsoleted in OTG 2.0 supplement */
+out:
+ return ret;
+}
+
+static void msm_otg_host_hnp_enable(struct otg_transceiver *otg, bool enable)
+{
+ struct usb_hcd *hcd = bus_to_hcd(otg->host);
+ struct usb_device *rhub = otg->host->root_hub;
+
+ if (enable) {
+ pm_runtime_disable(&rhub->dev);
+ rhub->state = USB_STATE_NOTATTACHED;
+ hcd->driver->bus_suspend(hcd);
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ } else {
+ usb_remove_hcd(hcd);
+ msm_otg_reset(otg);
+ usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+ }
+}
+
static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
- /*
- * Allow bus suspend only for host mode. Device mode bus suspend
- * is not implemented yet.
- */
- if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs)) {
- /*
- * ID_GND --> ID_A transition can not be detected in LPM.
- * Disallow host bus suspend when ACA is enabled.
- */
- if (suspend && !aca_enabled())
- pm_runtime_put(otg->dev);
- else
- pm_runtime_resume(otg->dev);
- }
+ if (aca_enabled() || (test_bit(ID, &motg->inputs) &&
+ !test_bit(ID_A, &motg->inputs)))
+ return 0;
+ if (suspend) {
+ switch (otg->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ if (TA_WAIT_BCON > 0)
+ break;
+ /* fall through */
+ case OTG_STATE_A_HOST:
+ pr_debug("host bus suspend\n");
+ clear_bit(A_BUS_REQ, &motg->inputs);
+ queue_work(system_nrt_wq, &motg->sm_work);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (otg->state) {
+ case OTG_STATE_A_SUSPEND:
+ /* Remote wakeup or resume */
+ set_bit(A_BUS_REQ, &motg->inputs);
+ otg->state = OTG_STATE_A_HOST;
+ break;
+ default:
+ break;
+ }
+ }
return 0;
}
@@ -905,6 +1071,11 @@
static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
{
+ struct usb_gadget *g = motg->otg.gadget;
+
+ if (g && g->is_a_peripheral)
+ return;
+
if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
motg->chg_type == USB_ACA_A_CHARGER ||
motg->chg_type == USB_ACA_B_CHARGER ||
@@ -987,11 +1158,9 @@
unsigned long action, void *priv)
{
struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
+ struct otg_transceiver *otg = &motg->otg;
struct usb_device *udev = priv;
- if (!aca_enabled())
- goto out;
-
if (action == USB_BUS_ADD || action == USB_BUS_REMOVE)
goto out;
@@ -1008,17 +1177,47 @@
switch (action) {
case USB_DEVICE_ADD:
- usb_disable_autosuspend(udev);
+ if (aca_enabled())
+ usb_disable_autosuspend(udev);
+ if (otg->state == OTG_STATE_A_WAIT_BCON) {
+ pr_debug("B_CONN set\n");
+ set_bit(B_CONN, &motg->inputs);
+ msm_otg_del_timer(motg);
+ otg->state = OTG_STATE_A_HOST;
+ /*
+ * OTG PET: A-device must end session within
+ * 10 sec after PET enumeration.
+ */
+ if (udev->quirks & USB_QUIRK_OTG_PET)
+ msm_otg_start_timer(motg, TA_TST_MAINT,
+ A_TST_MAINT);
+ }
/* fall through */
case USB_DEVICE_CONFIG:
if (udev->actconfig)
motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
else
motg->mA_port = IUNIT;
+ if (otg->state == OTG_STATE_B_HOST)
+ msm_otg_del_timer(motg);
break;
case USB_DEVICE_REMOVE:
- motg->mA_port = IUNIT;
- break;
+ if ((otg->state == OTG_STATE_A_HOST) ||
+ (otg->state == OTG_STATE_A_SUSPEND)) {
+ pr_debug("B_CONN clear\n");
+ clear_bit(B_CONN, &motg->inputs);
+ /*
+ * OTG PET: A-device must end session after
+ * PET disconnection if it is enumerated
+ * with bcdDevice[0] = 1. USB core sets
+ * bus->otg_vbus_off for us. clear it here.
+ */
+ if (udev->bus->otg_vbus_off) {
+ udev->bus->otg_vbus_off = 0;
+ set_bit(A_BUS_DROP, &motg->inputs);
+ }
+ queue_work(system_nrt_wq, &motg->sm_work);
+ }
default:
break;
}
@@ -1101,7 +1300,7 @@
msm_hsusb_vbus_power(motg, 0);
otg->host = NULL;
otg->state = OTG_STATE_UNDEFINED;
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
} else {
otg->host = NULL;
}
@@ -1115,6 +1314,9 @@
hcd = bus_to_hcd(host);
hcd->power_budget = motg->pdata->power_budget;
+#ifdef CONFIG_USB_OTG
+ host->otg_port = 1;
+#endif
motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
usb_register_notify(&motg->usbdev_nb);
otg->host = host;
@@ -1126,7 +1328,7 @@
*/
if (motg->pdata->mode == USB_HOST || otg->gadget) {
pm_runtime_get_sync(otg->dev);
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
}
return 0;
@@ -1202,7 +1404,7 @@
msm_otg_start_peripheral(otg, 0);
otg->gadget = NULL;
otg->state = OTG_STATE_UNDEFINED;
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
} else {
otg->gadget = NULL;
}
@@ -1218,7 +1420,7 @@
*/
if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
pm_runtime_get_sync(otg->dev);
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
}
return 0;
@@ -1380,6 +1582,7 @@
static void msm_otg_id_timer_func(unsigned long data)
{
struct msm_otg *motg = (struct msm_otg *) data;
+ struct otg_transceiver *otg = &motg->otg;
if (!aca_enabled())
return;
@@ -1389,11 +1592,15 @@
return;
}
+ if (otg->state == OTG_STATE_A_SUSPEND)
+ goto out;
+
if (msm_chg_check_aca_intr(motg)) {
dev_dbg(motg->otg.dev, "timer: aca work\n");
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
}
+out:
if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs))
mod_timer(&motg->id_timer, ID_TIMER_FREQ);
}
@@ -1734,16 +1941,22 @@
case USB_CHG_STATE_DETECTED:
msm_chg_block_off(motg);
msm_chg_enable_aca_det(motg);
+ /*
+ * Spurious interrupt is seen after enabling ACA detection
+ * due to which charger detection fails in case of PET.
+ * Add delay of 100 microsec to avoid that.
+ */
+ udelay(100);
msm_chg_enable_aca_intr(motg);
dev_dbg(otg->dev, "chg_type = %s\n",
chg_to_string(motg->chg_type));
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
return;
default:
return;
}
- schedule_delayed_work(&motg->chg_work, delay);
+ queue_delayed_work(system_nrt_wq, &motg->chg_work, delay);
}
/*
@@ -1771,10 +1984,12 @@
clear_bit(B_SESS_VLD, &motg->inputs);
}
} else if (pdata->otg_control == OTG_PHY_CONTROL) {
- if (otgsc & OTGSC_ID)
+ if (otgsc & OTGSC_ID) {
set_bit(ID, &motg->inputs);
- else
+ } else {
clear_bit(ID, &motg->inputs);
+ set_bit(A_BUS_REQ, &motg->inputs);
+ }
if (otgsc & OTGSC_BSV)
set_bit(B_SESS_VLD, &motg->inputs);
else
@@ -1820,11 +2035,12 @@
{
struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
struct otg_transceiver *otg = &motg->otg;
+ bool work = 0, srp_reqd;
pm_runtime_resume(otg->dev);
+ pr_debug("%s work\n", otg_state_string(otg->state));
switch (otg->state) {
case OTG_STATE_UNDEFINED:
- dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
msm_otg_reset(otg);
msm_otg_init_sm(motg);
otg->state = OTG_STATE_B_IDLE;
@@ -1836,31 +2052,15 @@
}
/* FALL THROUGH */
case OTG_STATE_B_IDLE:
- dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
if ((!test_bit(ID, &motg->inputs) ||
test_bit(ID_A, &motg->inputs)) && otg->host) {
- if (motg->chg_type == USB_ACA_DOCK_CHARGER)
- msm_otg_notify_charger(motg,
- IDEV_ACA_CHG_MAX);
- else if (test_bit(ID_A, &motg->inputs))
- msm_otg_notify_charger(motg,
- IDEV_ACA_CHG_MAX - IUNIT);
- else
- msm_hsusb_vbus_power(motg, 1);
- msm_otg_start_host(otg, 1);
- /*
- * Link can not generate PHY_ALT interrupt
- * in host mode when no device is attached
- * to the port. It is also observed PHY_ALT
- * interrupt missing upon Micro-A cable disconnect.
- * Hence disable PHY_ALT interrupt and perform
- * polling to detect RID change.
- */
- msm_chg_enable_aca_det(motg);
- msm_chg_disable_aca_intr(motg);
- mod_timer(&motg->id_timer, ID_TIMER_FREQ);
- otg->state = OTG_STATE_A_HOST;
+ pr_debug("!id || id_A\n");
+ clear_bit(B_BUS_REQ, &motg->inputs);
+ set_bit(A_BUS_REQ, &motg->inputs);
+ otg->state = OTG_STATE_A_IDLE;
+ work = 1;
} else if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ pr_debug("b_sess_vld\n");
switch (motg->chg_state) {
case USB_CHG_STATE_UNDEFINED:
msm_chg_detect_work(&motg->chg_work.work);
@@ -1906,7 +2106,18 @@
default:
break;
}
+ } else if (test_bit(B_BUS_REQ, &motg->inputs)) {
+ pr_debug("b_sess_end && b_bus_req\n");
+ if (msm_otg_start_srp(otg) < 0) {
+ clear_bit(B_BUS_REQ, &motg->inputs);
+ work = 1;
+ break;
+ }
+ otg->state = OTG_STATE_B_SRP_INIT;
+ msm_otg_start_timer(motg, TB_SRP_FAIL, B_SRP_FAIL);
+ break;
} else {
+ pr_debug("chg_work cancel");
cancel_delayed_work_sync(&motg->chg_work);
msm_otg_notify_charger(motg, 0);
motg->chg_state = USB_CHG_STATE_UNDEFINED;
@@ -1916,64 +2127,451 @@
pm_runtime_suspend(otg->dev);
}
break;
- case OTG_STATE_B_PERIPHERAL:
- dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
- if (!test_bit(B_SESS_VLD, &motg->inputs) ||
- !test_bit(ID, &motg->inputs) ||
- !test_bit(ID_C, &motg->inputs)) {
- msm_otg_start_peripheral(otg, 0);
+ case OTG_STATE_B_SRP_INIT:
+ if (!test_bit(ID, &motg->inputs) ||
+ test_bit(ID_A, &motg->inputs) ||
+ test_bit(ID_C, &motg->inputs) ||
+ (test_bit(B_SESS_VLD, &motg->inputs) &&
+ !test_bit(ID_B, &motg->inputs))) {
+ pr_debug("!id || id_a/c || b_sess_vld+!id_b\n");
+ msm_otg_del_timer(motg);
otg->state = OTG_STATE_B_IDLE;
- schedule_work(w);
+ /*
+ * clear VBUSVLDEXTSEL and VBUSVLDEXT register
+ * bits after SRP initiation.
+ */
+ ulpi_write(otg, 0x0, 0x98);
+ work = 1;
+ } else if (test_bit(B_SRP_FAIL, &motg->tmouts)) {
+ pr_debug("b_srp_fail\n");
+ pr_info("A-device did not respond to SRP\n");
+ clear_bit(B_BUS_REQ, &motg->inputs);
+ clear_bit(B_SRP_FAIL, &motg->tmouts);
+ otg_send_event(OTG_EVENT_NO_RESP_FOR_SRP);
+ ulpi_write(otg, 0x0, 0x98);
+ otg->state = OTG_STATE_B_IDLE;
+ motg->b_last_se0_sess = jiffies;
+ work = 1;
+ }
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ if (!test_bit(ID, &motg->inputs) ||
+ test_bit(ID_A, &motg->inputs) ||
+ test_bit(ID_B, &motg->inputs) ||
+ !test_bit(B_SESS_VLD, &motg->inputs)) {
+ pr_debug("!id || id_a/b || !b_sess_vld\n");
+ msm_otg_notify_charger(motg, 0);
+ srp_reqd = otg->gadget->otg_srp_reqd;
+ msm_otg_start_peripheral(otg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
+ if (test_bit(ID_B, &motg->inputs))
+ clear_bit(ID_B, &motg->inputs);
+ clear_bit(B_BUS_REQ, &motg->inputs);
+ otg->state = OTG_STATE_B_IDLE;
+ motg->b_last_se0_sess = jiffies;
+ if (srp_reqd)
+ msm_otg_start_timer(motg,
+ TB_TST_SRP, B_TST_SRP);
+ else
+ work = 1;
+ } else if (test_bit(B_BUS_REQ, &motg->inputs) &&
+ otg->gadget->b_hnp_enable &&
+ test_bit(A_BUS_SUSPEND, &motg->inputs)) {
+ pr_debug("b_bus_req && b_hnp_en && a_bus_suspend\n");
+ msm_otg_start_timer(motg, TB_ASE0_BRST, B_ASE0_BRST);
+ /* D+ pullup should not be disconnected within 4msec
+ * after A device suspends the bus. Otherwise PET will
+ * fail the compliance test.
+ */
+ udelay(1000);
+ msm_otg_start_peripheral(otg, 0);
+ otg->state = OTG_STATE_B_WAIT_ACON;
+ /*
+ * start HCD even before A-device enable
+ * pull-up to meet HNP timings.
+ */
+ otg->host->is_b_host = 1;
+ msm_otg_start_host(otg, 1);
} else if (test_bit(ID_C, &motg->inputs)) {
msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
}
break;
- case OTG_STATE_A_HOST:
- dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
- if (test_bit(ID, &motg->inputs) &&
- !test_bit(ID_A, &motg->inputs)) {
- msm_otg_start_host(otg, 0);
- msm_hsusb_vbus_power(motg, 0);
- msleep(100); /* TA_WAIT_VFALL */
+ case OTG_STATE_B_WAIT_ACON:
+ if (!test_bit(ID, &motg->inputs) ||
+ test_bit(ID_A, &motg->inputs) ||
+ test_bit(ID_B, &motg->inputs) ||
+ !test_bit(B_SESS_VLD, &motg->inputs)) {
+ pr_debug("!id || id_a/b || !b_sess_vld\n");
+ msm_otg_del_timer(motg);
/*
- * Exit point of host mode.
- *
- * 1. Micro-A cable disconnect: Just schedule
- * the work. PHY is reset in B_IDLE and LPM
- * is allowed.
- * 2. ID_GND --> ID_B: No need to reset the PHY.
- * HCD core clears all PORTSC bits and initializes
- * the controller to host mode in remove_hcd.
- * Restore PORTSC transceiver select bits (ULPI)
- * and reset the controller to change MODE bits.
- * PHY_ALT interrupt can not occur in host mode.
+ * A-device is physically disconnected during
+ * HNP. Remove HCD.
*/
- del_timer_sync(&motg->id_timer);
- if (motg->chg_state != USB_CHG_STATE_UNDEFINED) {
- msm_otg_link_reset(motg);
- msm_chg_enable_aca_intr(motg);
- }
+ msm_otg_start_host(otg, 0);
+ otg->host->is_b_host = 0;
+
+ clear_bit(B_BUS_REQ, &motg->inputs);
+ clear_bit(A_BUS_SUSPEND, &motg->inputs);
+ motg->b_last_se0_sess = jiffies;
otg->state = OTG_STATE_B_IDLE;
- schedule_work(w);
+ msm_otg_reset(otg);
+ work = 1;
+ } else if (test_bit(A_CONN, &motg->inputs)) {
+ pr_debug("a_conn\n");
+ clear_bit(A_BUS_SUSPEND, &motg->inputs);
+ otg->state = OTG_STATE_B_HOST;
+ /*
+ * PET disconnects D+ pullup after reset is generated
+ * by B device in B_HOST role which is not detected by
+ * B device. As workaorund , start timer of 300msec
+ * and stop timer if A device is enumerated else clear
+ * A_CONN.
+ */
+ msm_otg_start_timer(motg, TB_TST_CONFIG,
+ B_TST_CONFIG);
+ } else if (test_bit(B_ASE0_BRST, &motg->tmouts)) {
+ pr_debug("b_ase0_brst_tmout\n");
+ pr_info("B HNP fail:No response from A device\n");
+ msm_otg_start_host(otg, 0);
+ msm_otg_reset(otg);
+ otg->host->is_b_host = 0;
+ clear_bit(B_ASE0_BRST, &motg->tmouts);
+ clear_bit(A_BUS_SUSPEND, &motg->inputs);
+ clear_bit(B_BUS_REQ, &motg->inputs);
+ otg_send_event(OTG_EVENT_HNP_FAILED);
+ otg->state = OTG_STATE_B_IDLE;
+ work = 1;
+ } else if (test_bit(ID_C, &motg->inputs)) {
+ msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
+ }
+ break;
+ case OTG_STATE_B_HOST:
+ if (!test_bit(B_BUS_REQ, &motg->inputs) ||
+ !test_bit(A_CONN, &motg->inputs) ||
+ !test_bit(B_SESS_VLD, &motg->inputs)) {
+ pr_debug("!b_bus_req || !a_conn || !b_sess_vld\n");
+ clear_bit(A_CONN, &motg->inputs);
+ clear_bit(B_BUS_REQ, &motg->inputs);
+ msm_otg_start_host(otg, 0);
+ otg->host->is_b_host = 0;
+ otg->state = OTG_STATE_B_IDLE;
+ msm_otg_reset(otg);
+ work = 1;
+ } else if (test_bit(ID_C, &motg->inputs)) {
+ msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
+ }
+ break;
+ case OTG_STATE_A_IDLE:
+ otg->default_a = 1;
+ if (test_bit(ID, &motg->inputs) &&
+ !test_bit(ID_A, &motg->inputs)) {
+ pr_debug("id && !id_a\n");
+ otg->default_a = 0;
+ clear_bit(A_BUS_DROP, &motg->inputs);
+ otg->state = OTG_STATE_B_IDLE;
+ del_timer_sync(&motg->id_timer);
+ msm_otg_link_reset(motg);
+ msm_chg_enable_aca_intr(motg);
+ msm_otg_notify_charger(motg, 0);
+ work = 1;
+ } else if (!test_bit(A_BUS_DROP, &motg->inputs) &&
+ (test_bit(A_SRP_DET, &motg->inputs) ||
+ test_bit(A_BUS_REQ, &motg->inputs))) {
+ pr_debug("!a_bus_drop && (a_srp_det || a_bus_req)\n");
+
+ clear_bit(A_SRP_DET, &motg->inputs);
+ /* Disable SRP detection */
+ writel_relaxed((readl_relaxed(USB_OTGSC) &
+ ~OTGSC_INTSTS_MASK) &
+ ~OTGSC_DPIE, USB_OTGSC);
+
+ otg->state = OTG_STATE_A_WAIT_VRISE;
+ /* VBUS should not be supplied before end of SRP pulse
+ * generated by PET, if not complaince test fail.
+ */
+ usleep_range(10000, 12000);
+ /* ACA: ID_A: Stop charging untill enumeration */
+ if (test_bit(ID_A, &motg->inputs))
+ msm_otg_notify_charger(motg, 0);
+ else
+ msm_hsusb_vbus_power(motg, 1);
+ msm_otg_start_timer(motg, TA_WAIT_VRISE, A_WAIT_VRISE);
+ } else {
+ pr_debug("No session requested\n");
+ clear_bit(A_BUS_DROP, &motg->inputs);
+ if (test_bit(ID_A, &motg->inputs)) {
+ msm_otg_notify_charger(motg,
+ IDEV_ACA_CHG_MAX);
+ } else if (!test_bit(ID, &motg->inputs)) {
+ msm_otg_notify_charger(motg, 0);
+ /*
+ * A-device is not providing power on VBUS.
+ * Enable SRP detection.
+ */
+ writel_relaxed(0x13, USB_USBMODE);
+ writel_relaxed((readl_relaxed(USB_OTGSC) &
+ ~OTGSC_INTSTS_MASK) |
+ OTGSC_DPIE, USB_OTGSC);
+ mb();
+ }
+ }
+ break;
+ case OTG_STATE_A_WAIT_VRISE:
+ if ((test_bit(ID, &motg->inputs) &&
+ !test_bit(ID_A, &motg->inputs)) ||
+ test_bit(A_BUS_DROP, &motg->inputs) ||
+ test_bit(A_WAIT_VRISE, &motg->tmouts)) {
+ pr_debug("id || a_bus_drop || a_wait_vrise_tmout\n");
+ clear_bit(A_BUS_REQ, &motg->inputs);
+ msm_otg_del_timer(motg);
+ msm_hsusb_vbus_power(motg, 0);
+ otg->state = OTG_STATE_A_WAIT_VFALL;
+ msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
+ } else if (test_bit(A_VBUS_VLD, &motg->inputs)) {
+ pr_debug("a_vbus_vld\n");
+ otg->state = OTG_STATE_A_WAIT_BCON;
+ if (TA_WAIT_BCON > 0)
+ msm_otg_start_timer(motg, TA_WAIT_BCON,
+ A_WAIT_BCON);
+ msm_otg_start_host(otg, 1);
+ msm_chg_enable_aca_det(motg);
+ msm_chg_disable_aca_intr(motg);
+ mod_timer(&motg->id_timer, ID_TIMER_INITIAL_FREQ);
+ if (msm_chg_check_aca_intr(motg))
+ work = 1;
+ }
+ break;
+ case OTG_STATE_A_WAIT_BCON:
+ if ((test_bit(ID, &motg->inputs) &&
+ !test_bit(ID_A, &motg->inputs)) ||
+ test_bit(A_BUS_DROP, &motg->inputs) ||
+ test_bit(A_WAIT_BCON, &motg->tmouts)) {
+ pr_debug("(id && id_a/b/c) || a_bus_drop ||"
+ "a_wait_bcon_tmout\n");
+ if (test_bit(A_WAIT_BCON, &motg->tmouts)) {
+ pr_info("Device No Response\n");
+ otg_send_event(OTG_EVENT_DEV_CONN_TMOUT);
+ }
+ msm_otg_del_timer(motg);
+ clear_bit(A_BUS_REQ, &motg->inputs);
+ clear_bit(B_CONN, &motg->inputs);
+ msm_otg_start_host(otg, 0);
+ /*
+ * ACA: ID_A with NO accessory, just the A plug is
+ * attached to ACA: Use IDCHG_MAX for charging
+ */
+ if (test_bit(ID_A, &motg->inputs))
+ msm_otg_notify_charger(motg, IDEV_CHG_MIN);
+ else
+ msm_hsusb_vbus_power(motg, 0);
+ otg->state = OTG_STATE_A_WAIT_VFALL;
+ msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
+ } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
+ pr_debug("!a_vbus_vld\n");
+ clear_bit(B_CONN, &motg->inputs);
+ msm_otg_del_timer(motg);
+ msm_otg_start_host(otg, 0);
+ otg->state = OTG_STATE_A_VBUS_ERR;
+ msm_otg_reset(otg);
+ } else if (test_bit(ID_A, &motg->inputs)) {
+ msm_hsusb_vbus_power(motg, 0);
+ } else if (!test_bit(A_BUS_REQ, &motg->inputs)) {
+ /*
+ * If TA_WAIT_BCON is infinite, we don;t
+ * turn off VBUS. Enter low power mode.
+ */
+ if (TA_WAIT_BCON < 0)
+ pm_runtime_put_sync(otg->dev);
+ } else if (!test_bit(ID, &motg->inputs)) {
+ msm_hsusb_vbus_power(motg, 1);
+ }
+ break;
+ case OTG_STATE_A_HOST:
+ if ((test_bit(ID, &motg->inputs) &&
+ !test_bit(ID_A, &motg->inputs)) ||
+ test_bit(A_BUS_DROP, &motg->inputs)) {
+ pr_debug("id_a/b/c || a_bus_drop\n");
+ clear_bit(B_CONN, &motg->inputs);
+ clear_bit(A_BUS_REQ, &motg->inputs);
+ msm_otg_del_timer(motg);
+ otg->state = OTG_STATE_A_WAIT_VFALL;
+ msm_otg_start_host(otg, 0);
+ if (!test_bit(ID_A, &motg->inputs))
+ msm_hsusb_vbus_power(motg, 0);
+ msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
+ } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
+ pr_debug("!a_vbus_vld\n");
+ clear_bit(B_CONN, &motg->inputs);
+ msm_otg_del_timer(motg);
+ otg->state = OTG_STATE_A_VBUS_ERR;
+ msm_otg_start_host(otg, 0);
+ msm_otg_reset(otg);
+ } else if (!test_bit(A_BUS_REQ, &motg->inputs)) {
+ /*
+ * a_bus_req is de-asserted when root hub is
+ * suspended or HNP is in progress.
+ */
+ pr_debug("!a_bus_req\n");
+ msm_otg_del_timer(motg);
+ otg->state = OTG_STATE_A_SUSPEND;
+ if (otg->host->b_hnp_enable)
+ msm_otg_start_timer(motg, TA_AIDL_BDIS,
+ A_AIDL_BDIS);
+ else
+ pm_runtime_put_sync(otg->dev);
+ } else if (!test_bit(B_CONN, &motg->inputs)) {
+ pr_debug("!b_conn\n");
+ msm_otg_del_timer(motg);
+ otg->state = OTG_STATE_A_WAIT_BCON;
+ if (TA_WAIT_BCON > 0)
+ msm_otg_start_timer(motg, TA_WAIT_BCON,
+ A_WAIT_BCON);
+ if (msm_chg_check_aca_intr(motg))
+ work = 1;
+ } else if (test_bit(ID_A, &motg->inputs)) {
+ msm_otg_del_timer(motg);
+ msm_hsusb_vbus_power(motg, 0);
+ if (motg->chg_type == USB_ACA_DOCK_CHARGER)
+ msm_otg_notify_charger(motg,
+ IDEV_ACA_CHG_MAX);
+ else
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MIN - motg->mA_port);
+ } else if (!test_bit(ID, &motg->inputs)) {
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
+ msm_otg_notify_charger(motg, 0);
+ msm_hsusb_vbus_power(motg, 1);
+ }
+ break;
+ case OTG_STATE_A_SUSPEND:
+ if ((test_bit(ID, &motg->inputs) &&
+ !test_bit(ID_A, &motg->inputs)) ||
+ test_bit(A_BUS_DROP, &motg->inputs) ||
+ test_bit(A_AIDL_BDIS, &motg->tmouts)) {
+ pr_debug("id_a/b/c || a_bus_drop ||"
+ "a_aidl_bdis_tmout\n");
+ msm_otg_del_timer(motg);
+ clear_bit(B_CONN, &motg->inputs);
+ otg->state = OTG_STATE_A_WAIT_VFALL;
+ msm_otg_start_host(otg, 0);
+ msm_otg_reset(otg);
+ if (!test_bit(ID_A, &motg->inputs))
+ msm_hsusb_vbus_power(motg, 0);
+ msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
+ } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
+ pr_debug("!a_vbus_vld\n");
+ msm_otg_del_timer(motg);
+ clear_bit(B_CONN, &motg->inputs);
+ otg->state = OTG_STATE_A_VBUS_ERR;
+ msm_otg_start_host(otg, 0);
+ msm_otg_reset(otg);
+ } else if (!test_bit(B_CONN, &motg->inputs) &&
+ otg->host->b_hnp_enable) {
+ pr_debug("!b_conn && b_hnp_enable");
+ otg->state = OTG_STATE_A_PERIPHERAL;
+ msm_otg_host_hnp_enable(otg, 1);
+ otg->gadget->is_a_peripheral = 1;
+ msm_otg_start_peripheral(otg, 1);
+ } else if (!test_bit(B_CONN, &motg->inputs) &&
+ !otg->host->b_hnp_enable) {
+ pr_debug("!b_conn && !b_hnp_enable");
+ /*
+ * bus request is dropped during suspend.
+ * acquire again for next device.
+ */
+ set_bit(A_BUS_REQ, &motg->inputs);
+ otg->state = OTG_STATE_A_WAIT_BCON;
+ if (TA_WAIT_BCON > 0)
+ msm_otg_start_timer(motg, TA_WAIT_BCON,
+ A_WAIT_BCON);
} else if (test_bit(ID_A, &motg->inputs)) {
msm_hsusb_vbus_power(motg, 0);
msm_otg_notify_charger(motg,
- IDEV_ACA_CHG_MAX - motg->mA_port);
+ IDEV_CHG_MIN - motg->mA_port);
} else if (!test_bit(ID, &motg->inputs)) {
msm_otg_notify_charger(motg, 0);
msm_hsusb_vbus_power(motg, 1);
}
break;
+ case OTG_STATE_A_PERIPHERAL:
+ if ((test_bit(ID, &motg->inputs) &&
+ !test_bit(ID_A, &motg->inputs)) ||
+ test_bit(A_BUS_DROP, &motg->inputs)) {
+ pr_debug("id _f/b/c || a_bus_drop\n");
+ /* Clear BIDL_ADIS timer */
+ msm_otg_del_timer(motg);
+ otg->state = OTG_STATE_A_WAIT_VFALL;
+ msm_otg_start_peripheral(otg, 0);
+ otg->gadget->is_a_peripheral = 0;
+ msm_otg_start_host(otg, 0);
+ msm_otg_reset(otg);
+ if (!test_bit(ID_A, &motg->inputs))
+ msm_hsusb_vbus_power(motg, 0);
+ msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
+ } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
+ pr_debug("!a_vbus_vld\n");
+ /* Clear BIDL_ADIS timer */
+ msm_otg_del_timer(motg);
+ otg->state = OTG_STATE_A_VBUS_ERR;
+ msm_otg_start_peripheral(otg, 0);
+ otg->gadget->is_a_peripheral = 0;
+ msm_otg_start_host(otg, 0);
+ } else if (test_bit(A_BIDL_ADIS, &motg->tmouts)) {
+ pr_debug("a_bidl_adis_tmout\n");
+ msm_otg_start_peripheral(otg, 0);
+ otg->gadget->is_a_peripheral = 0;
+ otg->state = OTG_STATE_A_WAIT_BCON;
+ set_bit(A_BUS_REQ, &motg->inputs);
+ msm_otg_host_hnp_enable(otg, 0);
+ if (TA_WAIT_BCON > 0)
+ msm_otg_start_timer(motg, TA_WAIT_BCON,
+ A_WAIT_BCON);
+ } else if (test_bit(ID_A, &motg->inputs)) {
+ msm_hsusb_vbus_power(motg, 0);
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MIN - motg->mA_port);
+ } else if (!test_bit(ID, &motg->inputs)) {
+ msm_otg_notify_charger(motg, 0);
+ msm_hsusb_vbus_power(motg, 1);
+ }
+ break;
+ case OTG_STATE_A_WAIT_VFALL:
+ if (test_bit(A_WAIT_VFALL, &motg->tmouts)) {
+ clear_bit(A_VBUS_VLD, &motg->inputs);
+ otg->state = OTG_STATE_A_IDLE;
+ work = 1;
+ }
+ break;
+ case OTG_STATE_A_VBUS_ERR:
+ if ((test_bit(ID, &motg->inputs) &&
+ !test_bit(ID_A, &motg->inputs)) ||
+ test_bit(A_BUS_DROP, &motg->inputs) ||
+ test_bit(A_CLR_ERR, &motg->inputs)) {
+ otg->state = OTG_STATE_A_WAIT_VFALL;
+ if (!test_bit(ID_A, &motg->inputs))
+ msm_hsusb_vbus_power(motg, 0);
+ msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
+ msm_otg_notify_charger(motg, 0);
+ }
+ break;
default:
break;
}
+ if (work)
+ queue_work(system_nrt_wq, &motg->sm_work);
}
static irqreturn_t msm_otg_irq(int irq, void *data)
{
struct msm_otg *motg = data;
struct otg_transceiver *otg = &motg->otg;
- u32 otgsc = 0, usbsts;
+ u32 otgsc = 0, usbsts, pc;
+ bool work = 0;
+ irqreturn_t ret = IRQ_HANDLED;
if (atomic_read(&motg->in_lpm)) {
pr_debug("OTG IRQ: in LPM\n");
@@ -1984,44 +2582,144 @@
}
usbsts = readl(USB_USBSTS);
- if ((usbsts & PHY_ALT_INT)) {
- dev_dbg(otg->dev, "PHY_ALT interrupt\n");
- writel(PHY_ALT_INT, USB_USBSTS);
- if (msm_chg_check_aca_intr(motg)) {
- dev_dbg(otg->dev, "ACA work from IRQ\n");
- schedule_work(&motg->sm_work);
- }
- return IRQ_HANDLED;
- }
-
otgsc = readl(USB_OTGSC);
- if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
+
+ if (!(otgsc & OTG_OTGSTS_MASK) && !(usbsts & OTG_USBSTS_MASK))
return IRQ_NONE;
if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
if (otgsc & OTGSC_ID) {
- dev_dbg(otg->dev, "ID set\n");
+ pr_debug("Id set\n");
set_bit(ID, &motg->inputs);
} else {
- dev_dbg(otg->dev, "ID clear\n");
+ pr_debug("Id clear\n");
+ /*
+ * Assert a_bus_req to supply power on
+ * VBUS when Micro/Mini-A cable is connected
+ * with out user intervention.
+ */
+ set_bit(A_BUS_REQ, &motg->inputs);
clear_bit(ID, &motg->inputs);
msm_chg_enable_aca_det(motg);
}
- schedule_work(&motg->sm_work);
- } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
+ writel_relaxed(otgsc, USB_OTGSC);
+ work = 1;
+ } else if (otgsc & OTGSC_DPIS) {
+ pr_debug("DPIS detected\n");
+ writel_relaxed(otgsc, USB_OTGSC);
+ set_bit(A_SRP_DET, &motg->inputs);
+ set_bit(A_BUS_REQ, &motg->inputs);
+ work = 1;
+ } else if (otgsc & OTGSC_BSVIS) {
+ writel_relaxed(otgsc, USB_OTGSC);
+ /*
+ * BSV interrupt comes when operating as an A-device
+ * (VBUS on/off).
+ * But, handle BSV when charger is removed from ACA in ID_A
+ */
+ if ((otg->state >= OTG_STATE_A_IDLE) &&
+ !test_bit(ID_A, &motg->inputs))
+ return IRQ_HANDLED;
if (otgsc & OTGSC_BSV) {
- dev_dbg(otg->dev, "BSV set\n");
+ pr_debug("BSV set\n");
set_bit(B_SESS_VLD, &motg->inputs);
} else {
- dev_dbg(otg->dev, "BSV clear\n");
+ pr_debug("BSV clear\n");
clear_bit(B_SESS_VLD, &motg->inputs);
msm_chg_check_aca_intr(motg);
}
- schedule_work(&motg->sm_work);
+ work = 1;
+ } else if (usbsts & STS_PCI) {
+ pc = readl_relaxed(USB_PORTSC);
+ pr_debug("portsc = %x\n", pc);
+ ret = IRQ_NONE;
+ /*
+ * HCD Acks PCI interrupt. We use this to switch
+ * between different OTG states.
+ */
+ work = 1;
+ switch (otg->state) {
+ case OTG_STATE_A_SUSPEND:
+ if (otg->host->b_hnp_enable && (pc & PORTSC_CSC) &&
+ !(pc & PORTSC_CCS)) {
+ pr_debug("B_CONN clear\n");
+ clear_bit(B_CONN, &motg->inputs);
+ msm_otg_del_timer(motg);
+ }
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ /*
+ * A-peripheral observed activity on bus.
+ * clear A_BIDL_ADIS timer.
+ */
+ msm_otg_del_timer(motg);
+ work = 0;
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ if ((pc & PORTSC_CSC) && (pc & PORTSC_CCS)) {
+ pr_debug("A_CONN set\n");
+ set_bit(A_CONN, &motg->inputs);
+ /* Clear ASE0_BRST timer */
+ msm_otg_del_timer(motg);
+ }
+ break;
+ case OTG_STATE_B_HOST:
+ if ((pc & PORTSC_CSC) && !(pc & PORTSC_CCS)) {
+ pr_debug("A_CONN clear\n");
+ clear_bit(A_CONN, &motg->inputs);
+ msm_otg_del_timer(motg);
+ }
+ break;
+ case OTG_STATE_A_WAIT_BCON:
+ if (TA_WAIT_BCON < 0)
+ set_bit(A_BUS_REQ, &motg->inputs);
+ default:
+ work = 0;
+ break;
+ }
+ } else if (usbsts & STS_URI) {
+ ret = IRQ_NONE;
+ switch (otg->state) {
+ case OTG_STATE_A_PERIPHERAL:
+ /*
+ * A-peripheral observed activity on bus.
+ * clear A_BIDL_ADIS timer.
+ */
+ msm_otg_del_timer(motg);
+ work = 0;
+ break;
+ default:
+ work = 0;
+ break;
+ }
+ } else if (usbsts & STS_SLI) {
+ ret = IRQ_NONE;
+ work = 0;
+ switch (otg->state) {
+ case OTG_STATE_B_PERIPHERAL:
+ if (otg->gadget->b_hnp_enable) {
+ set_bit(A_BUS_SUSPEND, &motg->inputs);
+ set_bit(B_BUS_REQ, &motg->inputs);
+ work = 1;
+ }
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ msm_otg_start_timer(motg, TA_BIDL_ADIS,
+ A_BIDL_ADIS);
+ break;
+ default:
+ break;
+ }
+ } else if ((usbsts & PHY_ALT_INT)) {
+ writel_relaxed(PHY_ALT_INT, USB_USBSTS);
+ if (msm_chg_check_aca_intr(motg))
+ work = 1;
+ ret = IRQ_HANDLED;
}
+ if (work)
+ queue_work(system_nrt_wq, &motg->sm_work);
- writel(otgsc, USB_OTGSC);
- return IRQ_HANDLED;
+ return ret;
}
static void msm_otg_set_vbus_state(int online)
@@ -2044,7 +2742,7 @@
return;
}
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
}
static irqreturn_t msm_pmic_id_irq(int irq, void *data)
@@ -2060,10 +2758,11 @@
} else {
pr_debug("PMIC: ID clear\n");
clear_bit(ID, &motg->inputs);
+ set_bit(A_BUS_REQ, &motg->inputs);
}
if (motg->otg.state != OTG_STATE_UNDEFINED)
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
return IRQ_HANDLED;
}
@@ -2159,7 +2858,7 @@
}
pm_runtime_resume(otg->dev);
- schedule_work(&motg->sm_work);
+ queue_work(system_nrt_wq, &motg->sm_work);
out:
return status;
}
@@ -2622,6 +3321,7 @@
mb();
wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
+ msm_otg_init_timer(motg);
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
setup_timer(&motg->id_timer, msm_otg_id_timer_func,
@@ -2637,6 +3337,8 @@
otg->set_host = msm_otg_set_host;
otg->set_peripheral = msm_otg_set_peripheral;
otg->set_power = msm_otg_set_power;
+ otg->start_hnp = msm_otg_start_hnp;
+ otg->start_srp = msm_otg_start_srp;
otg->set_suspend = msm_otg_set_suspend;
otg->io_ops = &msm_otg_io_ops;
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 033a73c..579899c 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2056,7 +2056,7 @@
static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req,
struct msm_fb_data_type *mfd)
{
- int is_fg, i, cnt;
+ int is_fg = 0, i, cnt;
if (req->is_fg && ((req->alpha & 0x0ff) == 0xff))
is_fg = 1;
@@ -2078,9 +2078,13 @@
else if (mdp4_overlay_is_rgb_type(req->src.format))
return OVERLAY_PERF_LEVEL1;
- if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE)
- return OVERLAY_PERF_LEVEL4;
- else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE) {
+ if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE) {
+ if (mfd->mdp_rev >= MDP_REV_42)
+ return OVERLAY_PERF_LEVEL4;
+ else
+ return OVERLAY_PERF_LEVEL3;
+
+ } 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;
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index f319072..dfdc3f7 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -91,6 +91,9 @@
} else {
mdp3_dsi_cmd_dma_busy_wait(mfd);
}
+ } else {
+ /* video mode, wait until fifo cleaned */
+ mipi_dsi_controller_cfg(0);
}
/*
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index e613f29..c3874fa 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.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
@@ -239,6 +239,7 @@
struct vcd_property_intra_refresh_mb_number intra_refresh;
struct vcd_property_buffer_format buf_format;
struct vcd_property_buffer_format recon_buf_format;
+ struct vcd_property_sps_pps_for_idr_enable sps_pps;
struct ddl_buf_addr seq_header;
struct vcd_buffer_requirement input_buf_req;
struct vcd_buffer_requirement output_buf_req;
@@ -260,7 +261,7 @@
u32 mb_info_enable;
u32 ext_enc_control_val;
u32 num_references_for_p_frame;
- u32 closed_gop;
+ u32 closed_gop;
};
struct ddl_decoder_data {
struct ddl_codec_data_hdr hdr;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
index d658647..a2327d5 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.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
@@ -236,7 +236,6 @@
case VIDC_1080P_ERROR_PICTURE_STRUCTURE_ERR:
case VIDC_1080P_ERROR_SLICE_ADDR_INVALID:
case VIDC_1080P_ERROR_NON_FRAME_DATA_RECEIVED:
- case VIDC_1080P_ERROR_INCOMPLETE_FRAME:
case VIDC_1080P_ERROR_NALU_HEADER_ERROR:
case VIDC_1080P_ERROR_SPS_PARSE_ERROR:
case VIDC_1080P_ERROR_PPS_PARSE_ERROR:
@@ -309,6 +308,8 @@
case VIDC_1080P_WARN_BIT_RATE_NOT_SUPPORTED:
case VIDC_1080P_WARN_COLOR_DIFF_FORMAT_NOT_SUPPORTED:
case VIDC_1080P_WARN_NULL_EXTRA_METADATA_POINTER:
+ case VIDC_1080P_WARN_DEBLOCKING_NOT_DONE:
+ case VIDC_1080P_WARN_INCOMPLETE_FRAME:
case VIDC_1080P_ERROR_NULL_FW_DEBUG_INFO_POINTER:
case VIDC_1080P_ERROR_ALLOC_DEBUG_INFO_SIZE_INSUFFICIENT:
case VIDC_1080P_WARN_METADATA_NO_SPACE_NUM_CONCEAL_MB:
@@ -322,6 +323,9 @@
case VIDC_1080P_WARN_METADATA_NO_SPACE_MB_INFO:
case VIDC_1080P_WARN_METADATA_NO_SPACE_SLICE_SIZE:
case VIDC_1080P_WARN_RESOLUTION_WARNING:
+ case VIDC_1080P_WARN_NO_LONG_TERM_REFERENCE:
+ case VIDC_1080P_WARN_NO_SPACE_MPEG2_DATA_DUMP:
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_MISSING_MB:
status = true;
DDL_MSG_ERROR("VIDC_WARNING_IGNORED");
break;
@@ -626,6 +630,12 @@
case VIDC_1080P_WARN_NULL_EXTRA_METADATA_POINTER:
string = "VIDC_1080P_WARN_NULL_EXTRA_METADATA_POINTER";
break;
+ case VIDC_1080P_WARN_DEBLOCKING_NOT_DONE:
+ string = "VIDC_1080P_WARN_DEBLOCKING_NOT_DONE";
+ break;
+ case VIDC_1080P_WARN_INCOMPLETE_FRAME:
+ string = "VIDC_1080P_WARN_INCOMPLETE_FRAME";
+ break;
case VIDC_1080P_ERROR_NULL_FW_DEBUG_INFO_POINTER:
string = "VIDC_1080P_ERROR_NULL_FW_DEBUG_INFO_POINTER";
break;
@@ -666,6 +676,15 @@
case VIDC_1080P_WARN_RESOLUTION_WARNING:
string = "VIDC_1080P_WARN_RESOLUTION_WARNING";
break;
+ case VIDC_1080P_WARN_NO_LONG_TERM_REFERENCE:
+ string = "VIDC_1080P_WARN_NO_LONG_TERM_REFERENCE";
+ break;
+ case VIDC_1080P_WARN_NO_SPACE_MPEG2_DATA_DUMP:
+ string = "VIDC_1080P_WARN_NO_SPACE_MPEG2_DATA_DUMP";
+ break;
+ case VIDC_1080P_WARN_METADATA_NO_SPACE_MISSING_MB:
+ string = "VIDC_1080P_WARN_METADATA_NO_SPACE_MISSING_MB";
+ break;
}
if (string)
DDL_MSG_ERROR("Error code = 0x%x : %s", error_code, string);
@@ -733,9 +752,6 @@
case VIDC_1080P_ERROR_NON_FRAME_DATA_RECEIVED:
string = "VIDC_1080P_ERROR_NON_FRAME_DATA_RECEIVED";
break;
- case VIDC_1080P_ERROR_INCOMPLETE_FRAME:
- string = "VIDC_1080P_ERROR_INCOMPLETE_FRAME";
- break;
case VIDC_1080P_ERROR_NALU_HEADER_ERROR:
string = "VIDC_1080P_ERROR_NALU_HEADER_ERROR";
break;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 444db9f..40c5408 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -928,6 +928,21 @@
case VCD_I_META_BUFFER_MODE:
vcd_status = VCD_S_SUCCESS;
break;
+ case VCD_I_ENABLE_SPS_PPS_FOR_IDR:
+ {
+ struct vcd_property_sps_pps_for_idr_enable *sps_pps =
+ (struct vcd_property_sps_pps_for_idr_enable *) property_value;
+
+ if ((sizeof(struct vcd_property_sps_pps_for_idr_enable)) ==
+ property_hdr->sz) {
+ DDL_MSG_LOW("SPS PPS generation for IDR Encode "
+ "is Requested");
+ encoder->sps_pps.sps_pps_for_idr_enable_flag =
+ sps_pps->sps_pps_for_idr_enable_flag;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ }
default:
DDL_MSG_ERROR("INVALID ID %d\n", (int)property_hdr->prop_id);
vcd_status = VCD_ERR_ILLEGAL_OP;
@@ -1392,6 +1407,14 @@
property_value);
vcd_status = VCD_S_SUCCESS;
break;
+ case VCD_I_ENABLE_SPS_PPS_FOR_IDR:
+ if (sizeof(struct vcd_property_sps_pps_for_idr_enable) ==
+ property_hdr->sz) {
+ *(struct vcd_property_sps_pps_for_idr_enable *)
+ property_value = encoder->sps_pps;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
default:
vcd_status = VCD_ERR_ILLEGAL_OP;
break;
@@ -1959,5 +1982,6 @@
encoder->frame_rate.fps_numerator = DDL_INITIAL_FRAME_RATE;
encoder->frame_rate.fps_denominator = 1;
ddl_set_default_enc_property(ddl);
+ encoder->sps_pps.sps_pps_for_idr_enable_flag = false;
}
}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index 561cb7c..c46a349 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -85,6 +85,8 @@
#define VIDC_SM_ENC_EXT_CTRL_VBV_BUFFER_SIZE_SHFT 16
#define VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_BMSK 0x80
#define VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_SHFT 7
+#define VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_BMSK 0X100
+#define VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_SHFT 8
#define VIDC_SM_ENC_EXT_CTRL_SEQ_HDR_CTRL_BMSK 0x8
#define VIDC_SM_ENC_EXT_CTRL_SEQ_HDR_CTRL_SHFT 3
#define VIDC_SM_ENC_EXT_CTRL_FRAME_SKIP_ENABLE_BMSK 0x6
@@ -213,6 +215,8 @@
#define VIDC_SM_SEI_ENABLE_RECOVERY_POINT_SEI_BMSK 0x00000001
#define VIDC_SM_SEI_ENABLE_RECOVERY_POINT_SEI_SHFT 0
+#define VIDC_SM_NUM_STUFF_BYTES_CONSUME_ADDR 0X01ac
+
#define VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_BMSK 0x40
#define VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_SHFT 6
@@ -361,7 +365,7 @@
*shared_mem, u32 hec_enable,
enum VIDC_SM_frame_skip frame_skip_mode,
u32 seq_hdr_in_band, u32 vbv_buffer_size, u32 cpcfc_enable,
- u32 closed_gop_enable)
+ u32 sps_pps_control, u32 closed_gop_enable)
{
u32 enc_ctrl;
@@ -380,6 +384,9 @@
VIDC_SETFIELD((cpcfc_enable) ? 1 : 0,
VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_SHFT,
VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_BMSK) |
+ VIDC_SETFIELD((sps_pps_control) ? 1 : 0,
+ VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_BMSK) |
VIDC_SETFIELD(closed_gop_enable,
VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_SHFT,
VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_BMSK);
@@ -755,3 +762,11 @@
DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ERROR_CONCEALMENT_CONFIG_ADDR,
error_conceal_config);
}
+
+void vidc_sm_set_decoder_stuff_bytes_consumption(
+ struct ddl_buf_addr *shared_mem,
+ enum vidc_sm_num_stuff_bytes_consume_info consume_info)
+{
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_NUM_STUFF_BYTES_CONSUME_ADDR,
+ consume_info);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
index bc8b303..798a537 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -73,6 +73,11 @@
VIDC_SM_PROFILE_INFO_MAX = 0x7fffffff
};
+enum vidc_sm_num_stuff_bytes_consume_info {
+ VIDC_SM_NUM_STUFF_BYTES_CONSUME_ALL = 0x0,
+ VIDC_SM_NUM_STUFF_BYTES_CONSUME_NONE = 0xffffffff
+};
+
void vidc_sm_get_extended_decode_status(struct ddl_buf_addr *shared_mem,
u32 *more_field_needed,
u32 *resl_change);
@@ -100,7 +105,8 @@
void vidc_sm_set_extended_encoder_control(
struct ddl_buf_addr *shared_mem, u32 hec_enable,
enum VIDC_SM_frame_skip frame_skip_mode, u32 seq_hdr_in_band,
- u32 vbv_buffer_size, u32 cpcfc_enable, u32 closed_gop_enable);
+ u32 vbv_buffer_size, u32 cpcfc_enable, u32 sps_pps_control,
+ u32 closed_gop_enable);
void vidc_sm_set_encoder_param_change(struct ddl_buf_addr *shared_mem,
u32 bit_rate_chg, u32 frame_rate_chg, u32 i_period_chg);
void vidc_sm_set_encoder_vop_time(struct ddl_buf_addr *shared_mem,
@@ -170,4 +176,7 @@
u32 *sei_enable);
void vidc_sm_set_error_concealment_config(struct ddl_buf_addr *shared_mem,
u32 inter_slice, u32 intra_slice, u32 conceal_config_enable);
+void vidc_sm_set_decoder_stuff_bytes_consumption(
+ struct ddl_buf_addr *shared_mem,
+ enum vidc_sm_num_stuff_bytes_consume_info consume_info);
#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index c406371..66e129c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -263,6 +263,10 @@
VIDC_SM_RECOVERY_POINT_SEI);
ddl_context->vidc_decode_seq_start[ddl->command_channel](
&seq_start_param);
+
+ vidc_sm_set_decoder_stuff_bytes_consumption(
+ &ddl->shared_mem[ddl->command_channel],
+ VIDC_SM_NUM_STUFF_BYTES_CONSUME_NONE);
}
void ddl_vidc_decode_dynamic_property(struct ddl_client_context *ddl,
@@ -548,7 +552,8 @@
vidc_sm_set_extended_encoder_control(&ddl->shared_mem
[ddl->command_channel], hdr_ext_control,
r_cframe_skip, false, 0,
- h263_cpfc_enable, encoder->closed_gop);
+ h263_cpfc_enable, encoder->sps_pps.sps_pps_for_idr_enable_flag,
+ encoder->closed_gop);
vidc_sm_set_encoder_init_rc_value(&ddl->shared_mem
[ddl->command_channel],
encoder->target_bit_rate.target_bitrate);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
index 55db33c..7573ee8 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.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
@@ -94,7 +94,6 @@
#define VIDC_1080P_ERROR_SLICE_ADDR_INVALID 121
#define VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED 122
#define VIDC_1080P_ERROR_NON_FRAME_DATA_RECEIVED 123
-#define VIDC_1080P_ERROR_INCOMPLETE_FRAME 124
#define VIDC_1080P_ERROR_NO_BUFFER_RELEASED_FROM_HOST 125
#define VIDC_1080P_ERROR_NULL_FW_DEBUG_INFO_POINTER 126
#define VIDC_1080P_ERROR_ALLOC_DEBUG_INFO_SIZE_INSUFFICIENT 127
@@ -126,10 +125,16 @@
#define VIDC_1080P_WARN_BIT_RATE_NOT_SUPPORTED 168
#define VIDC_1080P_WARN_COLOR_DIFF_FORMAT_NOT_SUPPORTED 169
#define VIDC_1080P_WARN_NULL_EXTRA_METADATA_POINTER 170
+#define VIDC_1080P_WARN_DEBLOCKING_NOT_DONE 178
+#define VIDC_1080P_WARN_INCOMPLETE_FRAME 179
#define VIDC_1080P_WARN_METADATA_NO_SPACE_MB_INFO 180
#define VIDC_1080P_WARN_METADATA_NO_SPACE_SLICE_SIZE 181
#define VIDC_1080P_WARN_RESOLUTION_WARNING 182
+#define VIDC_1080P_WARN_NO_LONG_TERM_REFERENCE 183
+#define VIDC_1080P_WARN_NO_SPACE_MPEG2_DATA_DUMP 190
+#define VIDC_1080P_WARN_METADATA_NO_SPACE_MISSING_MB 191
+
#define VIDC_1080P_H264_ENC_TYPE_P 0
#define VIDC_1080P_H264_ENC_TYPE_B 1
#define VIDC_1080P_H264_ENC_TYPE_IDR 2
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 70fe6ca..e7cc68e 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1242,6 +1242,18 @@
NL80211_ATTR_IE_PROBE_RESP,
NL80211_ATTR_IE_ASSOC_RESP,
+ NL80211_ATTR_STA_WME,
+ NL80211_ATTR_SUPPORT_AP_UAPSD,
+
+ NL80211_ATTR_ROAM_SUPPORT,
+
+ NL80211_ATTR_SCHED_SCAN_MATCH,
+ NL80211_ATTR_MAX_MATCH_SETS,
+
+ NL80211_ATTR_PMKSA_CANDIDATE,
+
+ NL80211_ATTR_TX_NO_CCK_RATE,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/include/linux/of_spmi.h b/include/linux/of_spmi.h
index d07ce63..fe09dec 100644
--- a/include/linux/of_spmi.h
+++ b/include/linux/of_spmi.h
@@ -14,6 +14,17 @@
#include <linux/of_irq.h>
#ifdef CONFIG_OF_SPMI
+/**
+ * of_spmi_register_devices() - Register devices in the SPMI Device Tree
+ * @ctrl: spmi_controller which devices should be registered to.
+ *
+ * This routine scans the SPMI Device Tree, allocating resources and
+ * creating spmi_devices according to the SPMI bus Device Tree
+ * hierarchy. Details of this hierarchy can be found in
+ * Documentation/devicetree/bindings/spmi. This routine is normally
+ * called from the probe routine of the driver registering as a
+ * spmi_controller.
+ */
int of_spmi_register_devices(struct spmi_controller *ctrl);
#else
static int of_spmi_register_devices(struct spmi_controller *ctrl)
diff --git a/include/linux/qpnp/gpio.h b/include/linux/qpnp/gpio.h
new file mode 100644
index 0000000..0447a08
--- /dev/null
+++ b/include/linux/qpnp/gpio.h
@@ -0,0 +1,114 @@
+/* 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 <mach/qpnp.h>
+
+#define QPNP_GPIO_DIR_OUT 1
+#define QPNP_GPIO_DIR_IN 2
+#define QPNP_GPIO_DIR_BOTH (QPNP_GPIO_DIR_OUT | QPNP_GPIO_DIR_IN)
+
+#define QPNP_GPIO_OUT_BUF_OPEN_DRAIN 1
+#define QPNP_GPIO_OUT_BUF_CMOS 0
+
+#define QPNP_GPIO_VIN0 0
+#define QPNP_GPIO_VIN1 1
+#define QPNP_GPIO_VIN2 2
+#define QPNP_GPIO_VIN3 3
+#define QPNP_GPIO_VIN4 4
+#define QPNP_GPIO_VIN5 5
+#define QPNP_GPIO_VIN6 6
+#define QPNP_GPIO_VIN7 7
+
+#define QPNP_GPIO_PULL_UP_30 0
+#define QPNP_GPIO_PULL_UP_1P5 1
+#define QPNP_GPIO_PULL_UP_31P5 2
+#define QPNP_GPIO_PULL_UP_1P5_30 3
+#define QPNP_GPIO_PULL_DN 4
+#define QPNP_GPIO_PULL_NO 5
+
+#define QPNP_GPIO_OUT_STRENGTH_LOW 1
+#define QPNP_GPIO_OUT_STRENGTH_MED 2
+#define QPNP_GPIO_OUT_STRENGTH_HIGH 3
+
+#define QPNP_GPIO_FUNC_NORMAL 0
+#define QPNP_GPIO_FUNC_PAIRED 1
+#define QPNP_GPIO_FUNC_1 2
+#define QPNP_GPIO_FUNC_2 3
+#define QPNP_GPIO_DTEST1 4
+#define QPNP_GPIO_DTEST2 5
+#define QPNP_GPIO_DTEST3 6
+#define QPNP_GPIO_DTEST4 7
+
+/**
+ * struct qpnp_gpio_cfg - structure to specify gpio configurtion values
+ * @direction: indicates whether the gpio should be input, output, or
+ * both. Should be of the type QPNP_GPIO_DIR_*
+ * @output_type: indicates gpio should be configured as CMOS or open
+ * drain. Should be of the type QPNP_GPIO_OUT_BUF_*
+ * @output_value: The gpio output value of the gpio line - 0 or 1
+ * @pull: Indicates whether a pull up or pull down should be
+ * applied. If a pullup is required the current strength
+ * needs to be specified. Current values of 30uA, 1.5uA,
+ * 31.5uA, 1.5uA with 30uA boost are supported. This value
+ * should be one of the QPNP_GPIO_PULL_*
+ * @vin_sel: specifies the voltage level when the output is set to 1.
+ * For an input gpio specifies the voltage level at which
+ * the input is interpreted as a logical 1.
+ * @out_strength: the amount of current supplied for an output gpio,
+ * should be of the type QPNP_GPIO_STRENGTH_*
+ * @source_sel: choose alternate function for the gpio. Certain gpios
+ * can be paired (shorted) with each other. Some gpio pin
+ * can act as alternate functions. This parameter should
+ * be of type QPNP_GPIO_FUNC_*
+ * @inv_int_pol: Invert polarity before feeding the line to the interrupt
+ * module in pmic. This feature will almost be never used
+ * since the pm8xxx interrupt block can detect both edges
+ * and both levels.
+ * @master_en: 1 = Enable features within the GPIO block based on
+ * configurations.
+ * 0 = Completely disable the GPIO block and let the pin
+ * float with high impedance regardless of other settings.
+ */
+struct qpnp_gpio_cfg {
+ int direction;
+ int output_type;
+ int output_value;
+ int pull;
+ int vin_sel;
+ int out_strength;
+ int src_select;
+ int inv_int_pol;
+ int master_en;
+};
+
+/**
+ * qpnp_gpio_config - Apply gpio configuration for Linux gpio
+ * @gpio: Linux gpio number to configure.
+ * @param: parameters to configure.
+ *
+ * This routine takes a Linux gpio number that corresponds with a
+ * PMIC gpio and applies the configuration specified in 'param'.
+ * This gpio number can be ascertained by of_get_gpio_flags() or
+ * the qpnp_gpio_map_gpio() API.
+ */
+int qpnp_gpio_config(int gpio, struct qpnp_gpio_cfg *param);
+
+/**
+ * qpnp_gpio_map_gpio - Obtain Linux GPIO number from device spec
+ * @slave_id: slave_id of the spmi_device for the gpio in question.
+ * @pmic_gpio: PMIC gpio number to lookup.
+ *
+ * This routine is used in legacy configurations that do not support
+ * Device Tree. If you are using Device Tree, you should not use this.
+ * For such cases, use of_get_gpio() instead.
+ */
+int qpnp_gpio_map_gpio(uint16_t slave_id, uint32_t pmic_gpio);
diff --git a/include/linux/regulator/stub-regulator.h b/include/linux/regulator/stub-regulator.h
new file mode 100644
index 0000000..1119c51
--- /dev/null
+++ b/include/linux/regulator/stub-regulator.h
@@ -0,0 +1,33 @@
+/* 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 __STUB_REGULATOR_H__
+#define __STUB_REGULATOR_H__
+
+#include <linux/regulator/machine.h>
+
+#define STUB_REGULATOR_DRIVER_NAME "stub-regulator"
+
+/**
+ * struct stub_regulator_pdata - stub regulator device data
+ * @init_data: regulator constraints
+ * @hpm_min_load: minimum load in uA that will result in the regulator
+ * being set to high power mode
+ * @system_uA: current drawn from regulator not accounted for by any
+ * regulator framework consumer
+ */
+struct stub_regulator_pdata {
+ struct regulator_init_data init_data;
+ int hpm_min_load;
+ int system_uA;
+};
+#endif
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
index ffcb24e..927978a 100644
--- a/include/linux/spmi.h
+++ b/include/linux/spmi.h
@@ -88,24 +88,36 @@
#define to_spmi_driver(d) container_of(d, struct spmi_driver, driver)
/**
+ * struct spmi_resource: spmi_resource for one device_node
+ * @num_resources: number of resources for this device node
+ * @resources: array of resources for this device_node
+ * @of_node: device_node of the resource in question
+ */
+struct spmi_resource {
+ struct resource *resource;
+ u32 num_resources;
+ struct device_node *of_node;
+};
+
+/**
* 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.
+ * 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.
+ * @dev_node: array of SPMI resources - one entry per device_node.
+ * @num_dev_node: number of device_node structures.
+ * @sid: Slave Identifier.
*/
struct spmi_device {
struct device dev;
const char *name;
struct spmi_controller *ctrl;
- struct resource *resource;
- u32 num_resources;
+ struct spmi_resource *dev_node;
+ u32 num_dev_node;
u8 sid;
};
#define to_spmi_device(d) container_of(d, struct spmi_device, dev)
@@ -115,16 +127,16 @@
* @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
+ * @dev_node: one spmi_resource for each device_node.
+ * @num_dev_node: number of device_node structures.
* @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;
+ struct spmi_resource *dev_node;
+ u32 num_dev_node;
const void *platform_data;
};
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index f2ad7e1..5845cb6 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -183,6 +183,46 @@
struct msm_bus_scale_pdata *bus_scale_table;
};
+/* Timeout (in msec) values (min - max) associated with OTG timers */
+
+#define TA_WAIT_VRISE 100 /* ( - 100) */
+#define TA_WAIT_VFALL 500 /* ( - 1000) */
+
+/*
+ * This option is set for embedded hosts or OTG devices in which leakage
+ * currents are very minimal.
+ */
+#ifdef CONFIG_USB_OTG
+#define TA_WAIT_BCON 30000 /* (1100 - 30000) */
+#else
+#define TA_WAIT_BCON -1
+#endif
+
+#define TA_AIDL_BDIS 500 /* (200 - ) */
+#define TA_BIDL_ADIS 155 /* (155 - 200) */
+#define TB_SRP_FAIL 6000 /* (5000 - 6000) */
+#define TB_ASE0_BRST 200 /* (155 - ) */
+
+/* TB_SSEND_SRP and TB_SE0_SRP are combined */
+#define TB_SRP_INIT 2000 /* (1500 - ) */
+
+#define TA_TST_MAINT 10100 /* (9900 - 10100) */
+#define TB_TST_SRP 3000 /* ( - 5000) */
+#define TB_TST_CONFIG 300
+
+/* Timeout variables */
+
+#define A_WAIT_VRISE 0
+#define A_WAIT_VFALL 1
+#define A_WAIT_BCON 2
+#define A_AIDL_BDIS 3
+#define A_BIDL_ADIS 4
+#define B_SRP_FAIL 5
+#define B_ASE0_BRST 6
+#define A_TST_MAINT 7
+#define B_TST_SRP 8
+#define B_TST_CONFIG 9
+
/**
* struct msm_otg: OTG driver data. Shared by HCD and DCD.
* @otg: USB OTG Transceiver structure.
@@ -229,6 +269,18 @@
#define ID_A 2
#define ID_B 3
#define ID_C 4
+#define A_BUS_DROP 5
+#define A_BUS_REQ 6
+#define A_SRP_DET 7
+#define A_VBUS_VLD 8
+#define B_CONN 9
+#define ADP_CHANGE 10
+#define POWER_UP 11
+#define A_CLR_ERR 12
+#define A_BUS_RESUME 13
+#define A_BUS_SUSPEND 14
+#define A_CONN 15
+#define B_BUS_REQ 16
unsigned long inputs;
struct work_struct sm_work;
atomic_t in_lpm;
@@ -269,6 +321,10 @@
#define PHY_OTG_COMP_DISABLED BIT(2)
struct pm_qos_request_list pm_qos_req_dma;
int reset_counter;
+ unsigned long b_last_se0_sess;
+ unsigned long tmouts;
+ u8 active_tmout;
+ struct hrtimer timer;
};
struct msm_hsic_host_platform_data {
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index fcd91da..8a05136 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -33,6 +33,8 @@
#define PORTSC_PHCD (1 << 23) /* phy suspend mode */
#define PORTSC_PTS_MASK (3 << 30)
#define PORTSC_PTS_ULPI (3 << 30)
+#define PORTSC_CSC (1 << 1)
+#define PORTSC_CCS (1 << 0)
#define USB_ULPI_VIEWPORT (MSM_USB_BASE + 0x0170)
#define ULPI_RUN (1 << 30)
@@ -54,14 +56,26 @@
#define PHY_IDHV_INTEN (1 << 8) /* PHY ID HV interrupt */
#define PHY_OTGSESSVLDHV_INTEN (1 << 9) /* PHY Session Valid HV int. */
+#define STS_PCI (1 << 2) /* R/WC - Port Change Detect */
+#define STS_URI (1 << 6) /* R/WC - RESET recv'd */
+#define STS_SLI (1 << 8) /* R/WC - suspend state entered */
+
/* OTG definitions */
#define OTGSC_INTSTS_MASK (0x7f << 16)
#define OTGSC_IDPU (1 << 5)
+#define OTGSC_INTR_MASK (0x7f << 24)
+#define OTGSC_HADP (1 << 6)
#define OTGSC_ID (1 << 8)
#define OTGSC_BSV (1 << 11)
#define OTGSC_IDIS (1 << 16)
#define OTGSC_BSVIS (1 << 19)
#define OTGSC_IDIE (1 << 24)
#define OTGSC_BSVIE (1 << 27)
+#define OTGSC_DPIE (1 << 30)
+#define OTGSC_DPIS (1 << 22)
+
+/* OTG interrupt status mask */
+#define OTG_USBSTS_MASK (STS_PCI | STS_URI | STS_SLI | PHY_ALT_INT)
+#define OTG_OTGSTS_MASK (OTGSC_IDIS | OTGSC_BSVIS | OTGSC_DPIS)
#endif /* __LINUX_USB_GADGET_MSM72K_UDC_H__ */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index ebd2b75..fa3ddf8 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1344,6 +1344,7 @@
enum v4l2_mpeg_video_header_mode {
V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE = 0,
V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME = 1,
+ V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME = 2,
};
#define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC (V4L2_CID_MPEG_BASE+217)
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 0279216..0b501ea 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -50,6 +50,7 @@
#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_I_ENABLE_SPS_PPS_FOR_IDR (VCD_START_BASE + 0x25)
#define VCD_START_REQ (VCD_START_BASE + 0x1000)
#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
@@ -347,4 +348,8 @@
int alignment;
};
+struct vcd_property_sps_pps_for_idr_enable {
+ u32 sps_pps_for_idr_enable_flag;
+};
+
#endif
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 6a7f99b..cf7157c 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1190,7 +1190,6 @@
uint32_t s_mount_angle[MSM_MAX_CAMERA_SENSORS];
const char *video_dev_name[MSM_MAX_CAMERA_SENSORS];
enum sensor_type_t sensor_type[MSM_MAX_CAMERA_SENSORS];
-
};
struct msm_cam_config_dev_info {
@@ -1225,6 +1224,13 @@
uint8_t flash_enabled;
int8_t total_steps;
uint8_t support_3d;
+ enum flash_type flashtype;
+ enum sensor_type_t sensor_type;
+ uint32_t pxlcode; /* enum v4l2_mbus_pixelcode */
+ uint32_t camera_type; /* msm_camera_type */
+ int mount_angle;
+ uint32_t max_width;
+ uint32_t max_height;
};
#define V4L2_SINGLE_PLANE 0
@@ -1252,4 +1258,8 @@
uint8_t vpe_can_use;
};
+#define QCAMERA_NAME "qcamera"
+#define QCAMERA_DEVICE_GROUP_ID 1
+#define QCAMERA_VNODE_GROUP_ID 2
+
#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index e02597a..cb728a0 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -199,6 +199,7 @@
#define VFE_CMD_SCALE_OUTPUT2_CONFIG 135
#define VFE_CMD_CAPTURE_RAW 136
#define VFE_CMD_STOP_LIVESHOT 137
+#define VFE_CMD_RECONFIG_VFE 138
struct msm_isp_cmd {
int32_t id;
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 3e8de2c..9c089e0 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -161,7 +161,6 @@
struct mgmt_cp_pair_device {
bdaddr_t bdaddr;
__u8 io_cap;
- __u8 ssp_cap;
} __packed;
struct mgmt_rp_pair_device {
bdaddr_t bdaddr;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8be88bb..4898ea2 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -847,9 +847,11 @@
* @n_channels: total number of channels to scan
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
+ * @rates: bitmap of rates to advertise for each band
* @wiphy: the wiphy this was for
* @dev: the interface
* @aborted: (internal) scan request was notified as aborted
+ * @no_cck: used to send probe requests at non CCK rate in 2GHz band
*/
struct cfg80211_scan_request {
struct cfg80211_ssid *ssids;
@@ -858,10 +860,13 @@
const u8 *ie;
size_t ie_len;
+ u32 rates[IEEE80211_NUM_BANDS];
+
/* internal */
struct wiphy *wiphy;
struct net_device *dev;
bool aborted;
+ bool no_cck;
/* keep last */
struct ieee80211_channel *channels[0];
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index ca33664..a8e5af9 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -787,6 +787,10 @@
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
struct hci_cp_auth_requested cp;
+
+ /* encrypt must be pending if auth is also pending */
+ set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
+
cp.handle = cpu_to_le16(conn->handle);
hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp);
@@ -817,7 +821,7 @@
return 0;
} else if (conn->link_mode & HCI_LM_ENCRYPT) {
return hci_conn_auth(conn, sec_level, auth_type);
- } else if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+ } else if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
return 0;
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index deba87c..aac934a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2748,7 +2748,7 @@
conn->ssp_mode = (ev->features[0] & 0x01);
/*In case if remote device ssp supported/2.0 device
reduce the security level to MEDIUM if it is HIGH*/
- if (!conn->ssp_mode &&
+ if (!conn->ssp_mode && conn->auth_initiator &&
(conn->pending_sec_level == BT_SECURITY_HIGH))
conn->pending_sec_level = BT_SECURITY_MEDIUM;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 64d478b..bc68c9f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1613,9 +1613,8 @@
hci_dev_lock_bh(hdev);
- BT_DBG("SSP Cap is %d", cp->ssp_cap);
io_cap = cp->io_cap;
- if ((cp->ssp_cap == 0) || (io_cap == 0x03)) {
+ if (io_cap == 0x03) {
sec_level = BT_SECURITY_MEDIUM;
auth_type = HCI_AT_DEDICATED_BONDING;
} else {
@@ -1633,6 +1632,7 @@
io_cap = 0x01;
conn = hci_connect(hdev, ACL_LINK, 0, &cp->bdaddr, sec_level,
auth_type);
+ conn->auth_initiator = 1;
}
if (IS_ERR(conn)) {
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 17a80bf..78f12b3 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -447,6 +447,9 @@
enum nl80211_channel_type channel_type);
u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
+ const u8 *rates, unsigned int n_rates,
+ u32 *mask);
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
u32 beacon_int);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1a84262..ef59862 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -183,10 +183,12 @@
[NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
[NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
[NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 },
+ [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
[NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_DATA_LEN },
[NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_DATA_LEN },
+ [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -3378,7 +3380,6 @@
struct nlattr *attr;
struct wiphy *wiphy;
int err, tmp, n_ssids = 0, n_channels, i;
- enum ieee80211_band band;
size_t ie_len;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
@@ -3398,6 +3399,7 @@
if (!n_channels)
return -EINVAL;
} else {
+ enum ieee80211_band band;
n_channels = 0;
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
@@ -3458,6 +3460,8 @@
i++;
}
} else {
+ enum ieee80211_band band;
+
/* all channels */
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
int j;
@@ -3503,9 +3507,32 @@
nla_data(info->attrs[NL80211_ATTR_IE]),
request->ie_len);
}
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+ if (wiphy->bands[i])
+ request->rates[i] =
+ (1 << wiphy->bands[i]->n_bitrates) - 1;
+ if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
+ nla_for_each_nested(attr,
+ info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
+ tmp) {
+ enum ieee80211_band band = nla_type(attr);
+ if (band < 0 || band >= IEEE80211_NUM_BANDS) {
+ err = -EINVAL;
+ goto out_free;
+ }
+ err = ieee80211_get_ratemask(wiphy->bands[band],
+ nla_data(attr),
+ nla_len(attr),
+ &request->rates[band]);
+ if (err)
+ goto out_free;
+ }
+ }
request->dev = dev;
request->wiphy = &rdev->wiphy;
+ request->no_cck =
+ nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
rdev->scan_req = request;
err = rdev->ops->scan(&rdev->wiphy, dev, request);
@@ -4360,25 +4387,11 @@
nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
struct ieee80211_supported_band *sband =
wiphy->bands[ibss.channel->band];
- int i, j;
-
- if (n_rates == 0)
- return -EINVAL;
-
- for (i = 0; i < n_rates; i++) {
- int rate = (rates[i] & 0x7f) * 5;
- bool found = false;
-
- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate) {
- found = true;
- ibss.basic_rates |= BIT(j);
- break;
- }
- }
- if (!found)
- return -EINVAL;
- }
+ int err;
+ err = ieee80211_get_ratemask(sband, rates, n_rates,
+ &ibss.basic_rates);
+ if (err)
+ return err;
}
if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index cbbc927..0aa09bd 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -862,6 +862,8 @@
if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE)
creq->n_ssids = 0;
}
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+ creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
rdev->scan_req = creq;
err = rdev->ops->scan(wiphy, dev, creq);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index c69e653..c87358b 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1014,3 +1014,32 @@
return -EBUSY;
}
+
+int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
+ const u8 *rates, unsigned int n_rates,
+ u32 *mask)
+{
+ int i, j;
+ if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES)
+ return -EINVAL;
+ *mask = 0;
+ for (i = 0; i < n_rates; i++) {
+ int rate = (rates[i] & 0x7f) * 5;
+ bool found = false;
+ for (j = 0; j < sband->n_bitrates; j++) {
+ if (sband->bitrates[j].bitrate == rate) {
+ found = true;
+ *mask |= BIT(j);
+ break;
+ }
+ }
+ if (!found)
+ return -EINVAL;
+ }
+ /*
+ * mask must have at least one bit set here since we
+ * didn't accept a 0-length rates array nor allowed
+ * entries in the array that didn't exist
+ */
+ return 0;
+}
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 4396b07..46a49e7 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2848,8 +2848,11 @@
# unbounded string functions are overflow risks
my %str_fns = (
"sprintf" => "snprintf",
- "strcpy" => "strncpy",
- "strcat" => "strncat",
+ "strcpy" => "strlcpy",
+ "strncpy" => "strlcpy",
+ "strcat" => "strlcat",
+ "strncat" => "strlcat",
+ "vsprintf" => "vsnprintf",
"strcmp" => "strncmp",
"strcasecmp" => "strncasecmp",
"strchr" => "strnchr",
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 2c52866..d2690c3 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -47,7 +47,20 @@
# If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
# it, because this version is defined in the top level Makefile.
- if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+ if atag="`git describe --exact-match --abbrev=0 2>/dev/null`"; then
+ # Make sure we're at the tag that matches the Makefile.
+ # If not place the hash of the tag as well for
+ # v2.6.30-rc5-g314aef
+ if [ "x$atag" -ne "x$VERSION" ]; then
+ # If only the short version is requested,
+ # don't bother running further git commands
+ if $short; then
+ echo "+"
+ return
+ fi
+ printf '%s%s' -g "`git show-ref -s --abbrev $atag 2>/dev/null`"
+ fi
+ else
# If only the short version is requested, don't bother
# running further git commands
@@ -55,17 +68,18 @@
echo "+"
return
fi
+ # If we are past a tagged commit (like
+ # "v2.6.30-rc5-302-g72357d5"), we pretty print it and
+ # include the hash of any new tag on top.
+ if atag="`git describe 2>/dev/null`"; then
+ tag="`git describe --abbrev=0 2>/dev/null`"
+ commit="`echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'`"
+ printf '%s%s%s' -g "`git show-ref -s --abbrev $tag 2>/dev/null`" $commit
+ # If we don't have a tag at all we print -g{commitish}.
+ else
+ printf '%s%s' -g $head
+ fi
fi
- # If we are past a tagged commit (like
- # "v2.6.30-rc5-302-g72357d5"), we pretty print it but strip
- # off the v2.6.30-rc5 part because that's in the Makefile.
- if atag="`git describe 2>/dev/null`"; then
- atag="-${atag/v$KERNELVERSION-/}"
- # If we don't have a tag at all we print -g{commitish}.
- else
- atag="-g$head"
- fi
- printf '%s' "$atag"
# Is this git on svn?
if git config --get svn-remote.svn.url >/dev/null; then
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index d79af8c..828aaca 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -72,6 +72,7 @@
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
static struct snd_soc_dai_driver tabla_dai[];
+static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
enum tabla_bandgap_type {
TABLA_BANDGAP_OFF = 0,
@@ -236,6 +237,11 @@
/*compander*/
int comp_enabled[COMPANDER_MAX];
u32 comp_fs[COMPANDER_MAX];
+
+ /* Maintain the status of AUX PGA */
+ int aux_pga_cnt;
+ u8 aux_l_gain;
+ u8 aux_r_gain;
};
#ifdef CONFIG_DEBUG_FS
@@ -863,6 +869,11 @@
SOC_SINGLE_TLV("ADC5 Volume", TABLA_A_TX_5_6_EN, 5, 3, 0, analog_gain),
SOC_SINGLE_TLV("ADC6 Volume", TABLA_A_TX_5_6_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("AUX_PGA_LEFT Volume", TABLA_A_AUX_L_GAIN, 0, 39, 0,
+ aux_pga_gain),
+ SOC_SINGLE_TLV("AUX_PGA_RIGHT Volume", TABLA_A_AUX_R_GAIN, 0, 39, 0,
+ aux_pga_gain),
+
SOC_SINGLE("MICBIAS1 CAPLESS Switch", TABLA_A_MICB_1_CTL, 4, 1, 1),
SOC_SINGLE("MICBIAS2 CAPLESS Switch", TABLA_A_MICB_2_CTL, 4, 1, 1),
SOC_SINGLE("MICBIAS3 CAPLESS Switch", TABLA_A_MICB_3_CTL, 4, 1, 1),
@@ -1278,6 +1289,94 @@
SOC_DAPM_SINGLE("Switch", TABLA_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
};
+static const struct snd_kcontrol_new hphl_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TABLA_A_AUX_L_PA_CONN,
+ 7, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TABLA_A_AUX_R_PA_CONN,
+ 7, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_L_INV Switch",
+ TABLA_A_AUX_L_PA_CONN_INV, 7, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R_INV Switch",
+ TABLA_A_AUX_R_PA_CONN_INV, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new hphr_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TABLA_A_AUX_L_PA_CONN,
+ 6, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TABLA_A_AUX_R_PA_CONN,
+ 6, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_L_INV Switch",
+ TABLA_A_AUX_L_PA_CONN_INV, 6, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R_INV Switch",
+ TABLA_A_AUX_R_PA_CONN_INV, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout1_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TABLA_A_AUX_L_PA_CONN,
+ 5, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TABLA_A_AUX_R_PA_CONN,
+ 5, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_L_INV Switch",
+ TABLA_A_AUX_L_PA_CONN_INV, 5, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R_INV Switch",
+ TABLA_A_AUX_R_PA_CONN_INV, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout2_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TABLA_A_AUX_L_PA_CONN,
+ 4, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TABLA_A_AUX_R_PA_CONN,
+ 4, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_L_INV Switch",
+ TABLA_A_AUX_L_PA_CONN_INV, 4, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R_INV Switch",
+ TABLA_A_AUX_R_PA_CONN_INV, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout3_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TABLA_A_AUX_L_PA_CONN,
+ 3, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TABLA_A_AUX_R_PA_CONN,
+ 3, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_L_INV Switch",
+ TABLA_A_AUX_L_PA_CONN_INV, 3, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R_INV Switch",
+ TABLA_A_AUX_R_PA_CONN_INV, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout4_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TABLA_A_AUX_L_PA_CONN,
+ 2, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TABLA_A_AUX_R_PA_CONN,
+ 2, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_L_INV Switch",
+ TABLA_A_AUX_L_PA_CONN_INV, 2, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R_INV Switch",
+ TABLA_A_AUX_R_PA_CONN_INV, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout5_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TABLA_A_AUX_L_PA_CONN,
+ 1, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TABLA_A_AUX_R_PA_CONN,
+ 1, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_L_INV Switch",
+ TABLA_A_AUX_L_PA_CONN_INV, 1, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R_INV Switch",
+ TABLA_A_AUX_R_PA_CONN_INV, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new ear_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TABLA_A_AUX_L_PA_CONN,
+ 0, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TABLA_A_AUX_R_PA_CONN,
+ 0, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_L_INV Switch",
+ TABLA_A_AUX_L_PA_CONN_INV, 0, 1, 0),
+ SOC_DAPM_SINGLE("AUX_PGA_R_INV Switch",
+ TABLA_A_AUX_R_PA_CONN_INV, 0, 1, 0),
+};
+
static const struct snd_kcontrol_new lineout3_ground_switch =
SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
@@ -1357,6 +1456,260 @@
return 0;
}
+static void tabla_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
+{
+ snd_soc_write(codec, TABLA_A_BIAS_REF_CTL, 0x1C);
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x80);
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x04,
+ 0x04);
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
+ 0x01);
+ usleep_range(1000, 1000);
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x00);
+}
+
+static void tabla_codec_enable_bandgap(struct snd_soc_codec *codec,
+ enum tabla_bandgap_type choice)
+{
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+ /* TODO lock resources accessed by audio streams and threaded
+ * interrupt handlers
+ */
+
+ pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
+ tabla->bandgap_type);
+
+ if (tabla->bandgap_type == choice)
+ return;
+
+ if ((tabla->bandgap_type == TABLA_BANDGAP_OFF) &&
+ (choice == TABLA_BANDGAP_AUDIO_MODE)) {
+ tabla_codec_enable_audio_mode_bandgap(codec);
+ } else if (choice == TABLA_BANDGAP_MBHC_MODE) {
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x2,
+ 0x2);
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x80);
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x4,
+ 0x4);
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
+ 0x01);
+ usleep_range(1000, 1000);
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x00);
+ } else if ((tabla->bandgap_type == TABLA_BANDGAP_MBHC_MODE) &&
+ (choice == TABLA_BANDGAP_AUDIO_MODE)) {
+ snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
+ usleep_range(100, 100);
+ tabla_codec_enable_audio_mode_bandgap(codec);
+ } else if (choice == TABLA_BANDGAP_OFF) {
+ snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
+ } else {
+ pr_err("%s: Error, Invalid bandgap settings\n", __func__);
+ }
+ tabla->bandgap_type = choice;
+}
+
+static void tabla_codec_disable_clock_block(struct snd_soc_codec *codec)
+{
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ pr_debug("%s\n", __func__);
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x00);
+ ndelay(160);
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x02);
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x00);
+ tabla->clock_active = false;
+}
+
+static int tabla_codec_mclk_index(const struct tabla_priv *tabla)
+{
+ if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ)
+ return 0;
+ else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ)
+ return 1;
+ else {
+ BUG_ON(1);
+ return -EINVAL;
+ }
+}
+
+static void tabla_enable_rx_bias(struct snd_soc_codec *codec, u32 enable)
+{
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+ if (enable) {
+ tabla->rx_bias_count++;
+ if (tabla->rx_bias_count == 1)
+ snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
+ 0x80, 0x80);
+ } else {
+ tabla->rx_bias_count--;
+ if (!tabla->rx_bias_count)
+ snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
+ 0x80, 0x00);
+ }
+}
+
+static int tabla_codec_enable_config_mode(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: enable = %d\n", __func__, enable);
+ if (enable) {
+ snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
+ snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
+ usleep_range(5, 5);
+ snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80,
+ 0x80);
+ snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80,
+ 0x80);
+ usleep_range(10, 10);
+ snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80, 0);
+ usleep_range(20, 20);
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x08);
+ } else {
+ snd_soc_update_bits(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x1,
+ 0);
+ snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80, 0);
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
+ }
+ tabla->config_mode_active = enable ? true : false;
+
+ return 0;
+}
+
+static int tabla_codec_enable_clock_block(struct snd_soc_codec *codec,
+ int config_mode)
+{
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: config_mode = %d\n", __func__, config_mode);
+
+ if (config_mode) {
+ tabla_codec_enable_config_mode(codec, 1);
+ snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x00);
+ snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
+ snd_soc_write(codec, TABLA_A_CLK_BUFF_EN1, 0x0D);
+ usleep_range(1000, 1000);
+ } else
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
+
+ if (!config_mode && tabla->mbhc_polling_active) {
+ snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
+ tabla_codec_enable_config_mode(codec, 0);
+
+ }
+
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x05);
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x00);
+ snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x04);
+ snd_soc_update_bits(codec, TABLA_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
+ usleep_range(50, 50);
+ tabla->clock_active = true;
+ return 0;
+}
+
+static int tabla_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ tabla_codec_enable_bandgap(codec,
+ TABLA_BANDGAP_AUDIO_MODE);
+ tabla_enable_rx_bias(codec, 1);
+
+ snd_soc_update_bits(codec, TABLA_A_AUX_COM_CTL,
+ 0x08, 0x08);
+ /* Enable Zero Cross detect for AUX PGA channel
+ * and set the initial AUX PGA gain to NEG_0P0_DB
+ * to avoid glitches.
+ */
+ if (w->reg == TABLA_A_AUX_L_EN) {
+ snd_soc_update_bits(codec, TABLA_A_AUX_L_EN,
+ 0x20, 0x20);
+ tabla->aux_l_gain = snd_soc_read(codec,
+ TABLA_A_AUX_L_GAIN);
+ snd_soc_write(codec, TABLA_A_AUX_L_GAIN, 0x1F);
+ } else {
+ snd_soc_update_bits(codec, TABLA_A_AUX_R_EN,
+ 0x20, 0x20);
+ tabla->aux_r_gain = snd_soc_read(codec,
+ TABLA_A_AUX_R_GAIN);
+ snd_soc_write(codec, TABLA_A_AUX_R_GAIN, 0x1F);
+ }
+ if (tabla->aux_pga_cnt++ == 1
+ && !tabla->mclk_enabled) {
+ tabla_codec_enable_clock_block(codec, 1);
+ pr_debug("AUX PGA enabled RC osc\n");
+ }
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ if (w->reg == TABLA_A_AUX_L_EN)
+ snd_soc_write(codec, TABLA_A_AUX_L_GAIN,
+ tabla->aux_l_gain);
+ else
+ snd_soc_write(codec, TABLA_A_AUX_R_GAIN,
+ tabla->aux_r_gain);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Mute AUX PGA channel in use before disabling AUX PGA */
+ if (w->reg == TABLA_A_AUX_L_EN) {
+ tabla->aux_l_gain = snd_soc_read(codec,
+ TABLA_A_AUX_L_GAIN);
+ snd_soc_write(codec, TABLA_A_AUX_L_GAIN, 0x1F);
+ } else {
+ tabla->aux_r_gain = snd_soc_read(codec,
+ TABLA_A_AUX_R_GAIN);
+ snd_soc_write(codec, TABLA_A_AUX_R_GAIN, 0x1F);
+ }
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ tabla_enable_rx_bias(codec, 0);
+
+ snd_soc_update_bits(codec, TABLA_A_AUX_COM_CTL,
+ 0x08, 0x00);
+ if (w->reg == TABLA_A_AUX_L_EN) {
+ snd_soc_write(codec, TABLA_A_AUX_L_GAIN,
+ tabla->aux_l_gain);
+ snd_soc_update_bits(codec, TABLA_A_AUX_L_EN,
+ 0x20, 0x00);
+ } else {
+ snd_soc_write(codec, TABLA_A_AUX_R_GAIN,
+ tabla->aux_r_gain);
+ snd_soc_update_bits(codec, TABLA_A_AUX_R_EN,
+ 0x20, 0x00);
+ }
+
+ if (tabla->aux_pga_cnt-- == 0) {
+ if (tabla->mbhc_polling_active)
+ tabla_codec_enable_bandgap(codec,
+ TABLA_BANDGAP_MBHC_MODE);
+ else
+ tabla_codec_enable_bandgap(codec,
+ TABLA_BANDGAP_OFF);
+
+ if (!tabla->mclk_enabled &&
+ !tabla->mbhc_polling_active) {
+ tabla_codec_enable_clock_block(codec, 0);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
static int tabla_codec_enable_lineout(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -1945,24 +2298,6 @@
return 0;
}
-
-static void tabla_enable_rx_bias(struct snd_soc_codec *codec, u32 enable)
-{
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-
- if (enable) {
- tabla->rx_bias_count++;
- if (tabla->rx_bias_count == 1)
- snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
- 0x80, 0x80);
- } else {
- tabla->rx_bias_count--;
- if (!tabla->rx_bias_count)
- snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
- 0x80, 0x00);
- }
-}
-
static int tabla_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2270,7 +2605,8 @@
/* Earpiece (RX MIX1) */
{"EAR", NULL, "EAR PA"},
- {"EAR PA", NULL, "DAC1"},
+ {"EAR PA", NULL, "EAR_PA_MIXER"},
+ {"EAR_PA_MIXER", NULL, "DAC1"},
{"DAC1", NULL, "CP"},
{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX1"},
@@ -2281,8 +2617,11 @@
{"HEADPHONE", NULL, "HPHL"},
{"HEADPHONE", NULL, "HPHR"},
- {"HPHL", NULL, "HPHL DAC"},
- {"HPHR", NULL, "HPHR DAC"},
+ {"HPHL", NULL, "HPHL_PA_MIXER"},
+ {"HPHL_PA_MIXER", NULL, "HPHL DAC"},
+
+ {"HPHR", NULL, "HPHR_PA_MIXER"},
+ {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
{"HPHL DAC", NULL, "CP"},
{"HPHR DAC", NULL, "CP"},
@@ -2310,11 +2649,16 @@
{"LINEOUT4", NULL, "LINEOUT4 PA"},
{"LINEOUT5", NULL, "LINEOUT5 PA"},
- {"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
- {"LINEOUT2 PA", NULL, "LINEOUT2 DAC"},
- {"LINEOUT3 PA", NULL, "LINEOUT3 DAC"},
- {"LINEOUT4 PA", NULL, "LINEOUT4 DAC"},
- {"LINEOUT5 PA", NULL, "LINEOUT5 DAC"},
+ {"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
+ {"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
+ {"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
+ {"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
+ {"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
+ {"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
+ {"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
+ {"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
+ {"LINEOUT5 PA", NULL, "LINEOUT5_PA_MIXER"},
+ {"LINEOUT5_PA_MIXER", NULL, "LINEOUT5 DAC"},
{"LINEOUT1 DAC", NULL, "RX3 MIX1"},
{"LINEOUT5 DAC", NULL, "RX7 MIX1"},
@@ -2488,6 +2832,42 @@
{"ADC5", NULL, "AMIC5"},
{"ADC6", NULL, "AMIC6"},
+ /* AUX PGA Connections */
+ {"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"HPHL_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"HPHL_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"HPHL_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"HPHR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"HPHR_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"HPHR_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT1_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT1_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT1_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT2_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT2_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT2_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT3_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT3_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT3_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT4_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT4_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT4_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT5_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT5_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT5_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT5_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"EAR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"EAR_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"EAR_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"AUX_PGA_Left", NULL, "AMIC5"},
+ {"AUX_PGA_Right", NULL, "AMIC6"},
+
{"IIR1", NULL, "IIR1 INP1 MUX"},
{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
@@ -2590,7 +2970,6 @@
unsigned int value)
{
int ret;
-
BUG_ON(reg > TABLA_MAX_REGISTER);
if (!tabla_volatile(codec, reg)) {
@@ -2624,150 +3003,11 @@
return val;
}
-static void tabla_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
-{
- snd_soc_write(codec, TABLA_A_BIAS_REF_CTL, 0x1C);
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
- 0x80);
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x04,
- 0x04);
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
- 0x01);
- usleep_range(1000, 1000);
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
- 0x00);
-}
-
-static void tabla_codec_enable_bandgap(struct snd_soc_codec *codec,
- enum tabla_bandgap_type choice)
-{
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-
- /* TODO lock resources accessed by audio streams and threaded
- * interrupt handlers
- */
-
- pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
- tabla->bandgap_type);
-
- if (tabla->bandgap_type == choice)
- return;
-
- if ((tabla->bandgap_type == TABLA_BANDGAP_OFF) &&
- (choice == TABLA_BANDGAP_AUDIO_MODE)) {
- tabla_codec_enable_audio_mode_bandgap(codec);
- } else if (choice == TABLA_BANDGAP_MBHC_MODE) {
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x2,
- 0x2);
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
- 0x80);
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x4,
- 0x4);
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
- 0x01);
- usleep_range(1000, 1000);
- snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
- 0x00);
- } else if ((tabla->bandgap_type == TABLA_BANDGAP_MBHC_MODE) &&
- (choice == TABLA_BANDGAP_AUDIO_MODE)) {
- snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
- usleep_range(100, 100);
- tabla_codec_enable_audio_mode_bandgap(codec);
- } else if (choice == TABLA_BANDGAP_OFF) {
- snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
- } else {
- pr_err("%s: Error, Invalid bandgap settings\n", __func__);
- }
- tabla->bandgap_type = choice;
-}
-
-static int tabla_codec_enable_config_mode(struct snd_soc_codec *codec,
- int enable)
-{
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-
- if (enable) {
- snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
- snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
- usleep_range(5, 5);
- snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80,
- 0x80);
- snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80,
- 0x80);
- usleep_range(10, 10);
- snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80, 0);
- usleep_range(20, 20);
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x08);
- } else {
- snd_soc_update_bits(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x1,
- 0);
- snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80, 0);
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
- }
- tabla->config_mode_active = enable ? true : false;
-
- return 0;
-}
-
-static int tabla_codec_enable_clock_block(struct snd_soc_codec *codec,
- int config_mode)
-{
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-
- pr_debug("%s: config_mode = %d\n", __func__, config_mode);
-
- if (config_mode) {
- tabla_codec_enable_config_mode(codec, 1);
- snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x00);
- snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
- snd_soc_write(codec, TABLA_A_CLK_BUFF_EN1, 0x0D);
- usleep_range(1000, 1000);
- } else
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
-
- if (!config_mode && tabla->mbhc_polling_active) {
- snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
- tabla_codec_enable_config_mode(codec, 0);
-
- }
-
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x05);
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x00);
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x04);
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
- usleep_range(50, 50);
- tabla->clock_active = true;
- return 0;
-}
-static void tabla_codec_disable_clock_block(struct snd_soc_codec *codec)
-{
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
- pr_debug("%s\n", __func__);
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x00);
- ndelay(160);
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x02);
- snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x00);
- tabla->clock_active = false;
-}
-
-static int tabla_codec_mclk_index(const struct tabla_priv *tabla)
-{
- if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ)
- return 0;
- else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ)
- return 1;
- else {
- BUG_ON(1);
- return -EINVAL;
- }
-}
-
static void tabla_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
{
u8 *n_ready, *n_cic;
struct tabla_mbhc_btn_detect_cfg *btn_det;
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-
btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
@@ -3662,6 +3902,42 @@
/* Sidetone */
SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+
+ /* AUX PGA */
+ SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TABLA_A_AUX_L_EN, 7, 0,
+ tabla_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("AUX_PGA_Right", NULL, TABLA_A_AUX_R_EN, 7, 0,
+ tabla_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Lineout, ear and HPH PA Mixers */
+ SND_SOC_DAPM_MIXER("HPHL_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ hphl_pa_mix, ARRAY_SIZE(hphl_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("HPHR_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ hphr_pa_mix, ARRAY_SIZE(hphr_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT1_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout1_pa_mix, ARRAY_SIZE(lineout1_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT3_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout3_pa_mix, ARRAY_SIZE(lineout3_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT5_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout5_pa_mix, ARRAY_SIZE(lineout5_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("EAR_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ ear_pa_mix, ARRAY_SIZE(ear_pa_mix)),
};
static short tabla_codec_read_sta_result(struct snd_soc_codec *codec)
@@ -5272,7 +5548,9 @@
}
tabla->pdata = dev_get_platdata(codec->dev->parent);
tabla->intf_type = wcd9xxx_get_intf_type();
-
+ tabla->aux_pga_cnt = 0;
+ tabla->aux_l_gain = 0x1F;
+ tabla->aux_r_gain = 0x1F;
tabla_update_reg_address(tabla);
tabla_update_reg_defaults(codec);
tabla_codec_init_reg(codec);
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index ae4e403..a97bf87 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -55,7 +55,7 @@
#define TABLA_EXT_CLK_RATE 12288000
-#define TABLA_MBHC_DEF_BUTTONS 3
+#define TABLA_MBHC_DEF_BUTTONS 8
#define TABLA_MBHC_DEF_RLOADS 5
static u32 top_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(18);
@@ -604,7 +604,7 @@
void *tabla_cal;
struct tabla_mbhc_btn_detect_cfg *btn_cfg;
u16 *btn_low, *btn_high;
- u8 *n_cic, *gain;
+ u8 *n_ready, *n_cic, *gain;
tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
TABLA_MBHC_DEF_RLOADS),
@@ -625,25 +625,21 @@
S(mic_current, TABLA_PID_MIC_5_UA);
S(hph_current, TABLA_PID_MIC_5_UA);
S(t_mic_pid, 100);
- S(t_ins_complete, 1000);
+ S(t_ins_complete, 250);
S(t_ins_retry, 200);
#undef S
#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
S(v_no_mic, 30);
- S(v_hs_max, 1450);
+ S(v_hs_max, 1550);
#undef S
#define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
- S(c[0], 6);
- S(c[1], 10);
- S(c[2], 10);
- S(c[3], 14);
- S(c[4], 14);
- S(c[5], 16);
- S(c[6], 0);
- S(c[7], 0);
- S(nc, 5);
- S(n_meas, 11);
+ S(c[0], 62);
+ S(c[1], 124);
+ S(nc, 1);
+ S(n_meas, 3);
S(mbhc_nsc, 11);
+ S(n_btn_meas, 1);
+ S(n_btn_con, 2);
S(num_btn, TABLA_MBHC_DEF_BUTTONS);
S(v_btn_press_delta_sta, 100);
S(v_btn_press_delta_cic, 50);
@@ -651,15 +647,28 @@
btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
- btn_low[0] = 0;
- btn_high[0] = 40;
- btn_low[1] = 60;
- btn_high[1] = 140;
- btn_low[2] = 160;
- btn_high[2] = 240;
+ btn_low[0] = -50;
+ btn_high[0] = 10;
+ btn_low[1] = 11;
+ btn_high[1] = 38;
+ btn_low[2] = 39;
+ btn_high[2] = 64;
+ btn_low[3] = 65;
+ btn_high[3] = 91;
+ btn_low[4] = 92;
+ btn_high[4] = 115;
+ btn_low[5] = 116;
+ btn_high[5] = 141;
+ btn_low[6] = 142;
+ btn_high[6] = 163;
+ btn_low[7] = 164;
+ btn_high[7] = 250;
+ n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
+ n_ready[0] = 48;
+ n_ready[1] = 38;
n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
- n_cic[0] = 120;
- n_cic[1] = 94;
+ n_cic[0] = 60;
+ n_cic[1] = 47;
gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
gain[0] = 11;
gain[1] = 9;
@@ -777,7 +786,7 @@
}
err = snd_soc_jack_new(codec, "Button Jack",
- SND_JACK_BTN_0, &button_jack);
+ TABLA_JACK_BUTTON_MASK, &button_jack);
if (err) {
pr_err("failed to create new jack\n");
return err;
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 0430f7b..3d1cea0 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -761,14 +761,14 @@
dev_dbg(dai->dev, "enter %s, id = %d\n", __func__,
dai->id);
- if (!tx_slot && !rx_slot)
- return -EINVAL;
switch (dai->id) {
case SLIMBUS_0_RX:
/* channel number to be between 128 and 255. For RX port
* use channel numbers from 138 to 144, for TX port
* use channel numbers from 128 to 137
*/
+ if (!rx_slot)
+ return -EINVAL;
for (i = 0; i < rx_num; i++) {
dai_data->port_config.slim_sch.slave_ch_mapping[i] =
rx_slot[i];
@@ -787,6 +787,8 @@
* use channel numbers from 138 to 144, for TX port
* use channel numbers from 128 to 137
*/
+ if (!tx_slot)
+ return -EINVAL;
for (i = 0; i < tx_num; i++) {
dai_data->port_config.slim_sch.slave_ch_mapping[i] =
tx_slot[i];
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 14da1ba..4f19160 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -259,7 +259,7 @@
{
bool rc = false;
- if (be_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
+ if (fe_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
/* recheck FE ID in the mixer control defined in this file */
pr_err("%s: bad MM ID\n", __func__);
return rc;
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 7a16a10..a3e1c13 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -76,7 +76,11 @@
index = afe_get_port_index(data->token);
pr_debug("%s: Port ID %d, index %d\n", __func__,
data->token, index);
-
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d token %d\n",
+ __func__, index, data->token);
+ return 0;
+ }
if (data->opcode == APR_BASIC_RSP_RESULT) {
pr_debug("APR_BASIC_RSP_RESULT\n");
switch (payload[0]) {
@@ -139,6 +143,11 @@
s32 result = 0;
struct adm_set_params_command adm_params;
int index = afe_get_port_index(port_id);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d portid %d\n",
+ __func__, index, port_id);
+ return 0;
+ }
pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
@@ -331,8 +340,8 @@
open.channel_config = channel_mode & 0x00FF;
open.rate = rate;
- pr_debug("%s: channel_config=%d port_id=%d rate=%d\
- topology_id=0x%X\n", __func__, open.channel_config,\
+ pr_debug("%s: channel_config=%d port_id=%d rate=%d"
+ "topology_id=0x%X\n", __func__, open.channel_config,\
open.endpoint_id1, open.rate,\
open.topology_id);
@@ -498,6 +507,11 @@
int ret = 0, i = 0;
/* Assumes port_ids have already been validated during adm_open */
int index = afe_get_port_index(copp_id);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d token %d\n",
+ __func__, index, copp_id);
+ return 0;
+ }
pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
__func__, session_id, path, num_copps, port_id[0]);
@@ -526,7 +540,8 @@
pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
port_id[i], tmp);
- route.session[0].copp_id[i] =
+ if (tmp >= 0 && tmp < AFE_MAX_PORTS)
+ route.session[0].copp_id[i] =
atomic_read(&this_adm.copp_id[tmp]);
}
if (num_copps % 2)