Merge "msm: scm-pas: stub out bus scaling on 8226"
diff --git a/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt b/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt
new file mode 100644
index 0000000..01301be
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt
@@ -0,0 +1,18 @@
+* MSM PC Debug Counters
+
+MSM PC debug counter reserves 16 registers in the IMEM memory space which
+maintains a count on the state of power collapse on each core. This count
+will be useful to debug the power collapse state on each core.
+
+The required nodes for MSM PC Debug Counters are:
+
+- compatible: "qcom,pc-cntr"
+- reg: physical IMEM address reserved for PC counters
+
+Example:
+
+qcom,pc-cntr@fe800000 {
+ compatible = "qcom,pc-cntr";
+ reg = <0xfe800664 0x40>;
+ };
+
diff --git a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
index 2ba7341..d7d3ec2 100644
--- a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
+++ b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
@@ -40,9 +40,10 @@
Select from the following unsigned int.
0 : Default scaling to convert raw adc code to voltage.
1 : Conversion to temperature based on btm parameters.
- 2 : Returns result in milli degree's Centigrade.
+ 2 : Returns result in degC for 100k pull-up.
3 : Returns current across 0.1 ohm resistor.
4 : Returns XO thermistor voltage in degree's Centigrade.
+ 5 : Returns result in degC for 150k pull-up.
- qcom,hw-settle-time : Settling period for the channel before ADC read.
Select from the following unsigned int.
0 : 0us
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 43e87a8..9c2ce6c 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -35,6 +35,13 @@
0 will be treated as 500mA
- qcom,hsusb-otg-pclk-src-name: The source of pclk
- qcom,hsusb-otg-pmic-id-irq: ID, routed to PMIC IRQ number
+- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
+ below optional properties:
+ - qcom,msm_bus,name
+ - qcom,msm_bus,num_cases
+ - qcom,msm_bus,active_only
+ - qcom,msm_bus,num_paths
+ - qcom,msm_bus,vectors
Example HSUSB OTG controller device node :
usb@f9690000 {
@@ -51,8 +58,32 @@
qcom,hsusb-otg-power-budget = <500>;
qcom,hsusb-otg-pclk-src-name = "dfab_usb_clk";
qcom,hsusb-otg-pmic-id-irq = <47>
+
+ qcom,msm_bus,name = "usb2";
+ qcom,msm_bus,num_cases = <2>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm_bus,vectors =
+ <87 512 0 0>,
+ <87 512 60000000 960000000>;
};
+ANDROID USB:
+
+Required properties:
+- compatible: should be "qcom,android-usb"
+
+Optional properties :
+- reg : offset and length of memory region that is used by driver to
+ update USB PID and serial numbers used by bootloader in DLOAD mode.
+
+Example Android USB device node :
+ android_usb@fc42b0c8 {
+ compatible = "qcom,android-usb";
+ reg = <0xfc42b0c8 0xc8>;
+ };
+
+
BAM:
Required properties:
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index bff3732..9cc9e6e 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -17,6 +17,15 @@
the MSM USB3.0 core (which also includes the Synopsys DesignWare
USB3.0 controller)
+Optional properties :
+- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
+ below optional properties:
+ - qcom,msm_bus,name
+ - qcom,msm_bus,num_cases
+ - qcom,msm_bus,active_only
+ - qcom,msm_bus,num_paths
+ - qcom,msm_bus,vectors
+
Example MSM USB3.0 controller device node :
usb@f9200000 {
compatible = "qcom,dwc-usb3-msm";
@@ -30,4 +39,12 @@
HSUSB_1p8-supply = <&pm8941_l6>;
HSUSB_3p3-supply = <&pm8941_l24>;
qcom,dwc-usb3-msm-dbm-eps = <4>
+
+ qcom,msm_bus,name = "usb3";
+ qcom,msm_bus,num_cases = <2>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm_bus,vectors =
+ <61 512 0 0>,
+ <61 512 240000000 960000000>;
};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
old mode 100755
new mode 100644
index 751a823..0f5fd1c
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -517,9 +517,9 @@
qcom,fast-avg-setup = <0>;
};
- chan@50 {
- label = "xo_therm1";
- qcom,channel-num = <49>;
+ chan@178 {
+ label = "xo_therm_pu2";
+ qcom,channel-num = <178>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
qcom,calibration-type = "ratiometric";
@@ -527,6 +527,61 @@
qcom,hw-settle-time = <0>;
qcom,fast-avg-setup = <0>;
};
+
+ chan@179 {
+ label = "msm_therm";
+ qcom,channel-num = <179>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@180 {
+ label = "emmc_therm";
+ qcom,channel-num = <180>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@181 {
+ label = "pa_therm1";
+ qcom,channel-num = <181>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@183 {
+ label = "pa_therm2";
+ qcom,channel-num = <183>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@184 {
+ label = "quiet_therm";
+ qcom,channel-num = <184>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
};
iadc@3600 {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 0382021..344aa7f 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -41,7 +41,7 @@
core-vdda-supply = <&pm8941_l12>;
core-vcc-supply = <&pm8941_s3>;
qcom,hdmi-tx-supply-names = "hpd-5v", "core-vdda", "core-vcc";
- qcom,hdmi-tx-supply-type = <0 1 1>;
+ qcom,hdmi-tx-supply-type = <1 0 0>;
qcom,hdmi-tx-min-voltage-level = <0 1800000 1800000>;
qcom,hdmi-tx-max-voltage-level = <0 1800000 1800000>;
qcom,hdmi-tx-op-mode = <0 1800000 0>;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index 1af468a..d3e0bc3 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -140,6 +140,19 @@
debounce-interval = <15>;
};
};
+
+ spi@f9923000 {
+ ethernet-switch@2 {
+ compatible = "micrel,ks8851";
+ reg = <2>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <94 0>;
+ spi-max-frequency = <4800000>;
+ rst-gpio = <&pm8941_mpps 6 0>;
+ vdd-io-supply = <&spi_eth_vreg>;
+ vdd-phy-supply = <&spi_eth_vreg>;
+ };
+ };
};
&sdcc2 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index a83a1bd..fe60c83 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -91,9 +91,23 @@
HSUSB_3p3-supply = <&pm8941_l24>;
qcom,hsusb-otg-phy-type = <2>;
+ qcom,hsusb-otg-phy-init-seq = <0x63 0x81 0xffffffff>;
qcom,hsusb-otg-mode = <1>;
qcom,hsusb-otg-otg-control = <1>;
qcom,hsusb-otg-disable-reset;
+
+ qcom,msm_bus,name = "usb2";
+ qcom,msm_bus,num_cases = <2>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm_bus,vectors =
+ <87 512 0 0>,
+ <87 512 60000000 960000000>;
+ };
+
+ android_usb@fc42b0c8 {
+ compatible = "qcom,android-usb";
+ reg = <0xfc42b0c8 0xc8>;
};
sdcc1: qcom,sdcc@f9824000 {
@@ -108,6 +122,8 @@
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
+ qcom,sdcc-vdd-always_on;
+ qcom,sdcc-vdd-lpm_sup;
qcom,sdcc-vdd-voltage_level = <2950000 2950000>;
qcom,sdcc-vdd-current_level = <800 500000>;
@@ -595,6 +611,14 @@
HSUSB_1p8-supply = <&pm8941_l6>;
HSUSB_3p3-supply = <&pm8941_l24>;
qcom,dwc-usb3-msm-dbm-eps = <4>;
+
+ qcom,msm_bus,name = "usb3";
+ qcom,msm_bus,num_cases = <2>;
+ qcom,msm_bus,active_only = <0>;
+ qcom,msm_bus,num_paths = <1>;
+ qcom,msm_bus,vectors =
+ <61 512 0 0>,
+ <61 512 240000000 960000000>;
};
gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index 9c932d0..f3efbb8 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -116,7 +116,7 @@
qcom,vctl-timeout-us = <50>;
qcom,vctl-port = <0x0>;
qcom,phase-port = <0x1>;
- qcom,saw2-spm-cmd-ret = [0b 00 20 03 22 00 0f];
+ qcom,saw2-spm-cmd-ret = [00 20 03 22 00 0f];
qcom,saw2-spm-cmd-gdhs = [00 20 32 0b 42 07 44 22 50 02 32 50
0f];
qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 0b 42 07 01 b0 12 44 a0
@@ -383,4 +383,9 @@
<39 93>,
<40 95>;
};
+
+ qcom,pc-cntr@fe800000 {
+ compatible = "qcom,pc-cntr";
+ reg = <0xfe800664 0x40>;
+ };
};
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index ad02480..2c8f71e 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -229,6 +229,7 @@
CONFIG_NET_EMATCH_META=y
CONFIG_NET_EMATCH_TEXT=y
CONFIG_NET_CLS_ACT=y
+CONFIG_MARIMBA_CORE=y
CONFIG_BT=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
@@ -238,6 +239,8 @@
CONFIG_BT_HIDP=y
CONFIG_BT_HCISMD=y
CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
CONFIG_BT_HCIUART_ATH3K=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=m
@@ -322,6 +325,7 @@
CONFIG_SMB349_CHARGER=y
CONFIG_PM8921_CHARGER=y
CONFIG_PM8921_BMS=y
+CONFIG_BATTERY_BCL=y
CONFIG_SENSORS_PM8XXX_ADC=y
CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index ae72589..a2deab2 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -233,6 +233,7 @@
CONFIG_NET_EMATCH_META=y
CONFIG_NET_EMATCH_TEXT=y
CONFIG_NET_CLS_ACT=y
+CONFIG_MARIMBA_CORE=y
CONFIG_BT=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
@@ -243,6 +244,8 @@
CONFIG_BT_HCISMD=y
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=m
# CONFIG_CFG80211_WEXT is not set
@@ -326,6 +329,7 @@
CONFIG_SMB349_CHARGER=y
CONFIG_PM8921_CHARGER=y
CONFIG_PM8921_BMS=y
+CONFIG_BATTERY_BCL=y
CONFIG_SENSORS_PM8XXX_ADC=y
CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 38bab50..471ecd9 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -51,6 +51,7 @@
CONFIG_MSM_PIL_PRONTO=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_MODEM_SSR_8974=y
+CONFIG_MSM_ADSP_SSR_8974=y
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_QDSS=y
@@ -86,6 +87,7 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -149,10 +151,8 @@
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
-CONFIG_HVC_DCC=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM=y
-CONFIG_DCC_TTY=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index a9582f9..af21496 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -300,6 +300,7 @@
void machine_shutdown(void)
{
+ preempt_disable();
#ifdef CONFIG_SMP
smp_send_stop();
#endif
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index d2a5c23..badee85 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2043,6 +2043,15 @@
restarts the modem or the 8974 when the modem encounters a fatal error,
depending on the restart level selected in the subsystem restart driver.
+config MSM_ADSP_SSR_8974
+ bool "MSM 8974 adsp restart driver"
+ depends on (ARCH_MSM8974)
+ help
+ This option enables the adsp restart driver for the MSM8974.
+ It monitors the adsp SMSM status bits and the adsp watchdog line and
+ restarts the adsp or the 8974 when the adsp encounters a fatal error,
+ depending on the restart level selected in the subsystem restart driver.
+
config SCORPION_Uni_45nm_BUG
bool "Scorpion Uni 45nm(SC45U): Workaround for ICIMVAU and BPIMVA"
depends on ARCH_MSM7X30 || (ARCH_QSD8X50 && MSM_SOC_REV_A)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 83c8bfc..1be6e51 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -214,6 +214,7 @@
obj-$(CONFIG_MSM_MODEM_8960) += modem-8960.o
obj-$(CONFIG_MSM_MODEM_SSR_8974) += modem-ssr-8974.o
obj-$(CONFIG_MSM_LPASS_8960) += lpass-8960.o
+obj-$(CONFIG_MSM_ADSP_SSR_8974) += adsp-8974.o
obj-$(CONFIG_MSM_WCNSS_SSR_8960) += wcnss-ssr-8960.o
obj-$(CONFIG_MSM_GSS_SSR_8064) += gss-8064.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index a9521f0..3c80875 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -122,6 +122,7 @@
[13] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 5 },
[14] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 5 },
[15] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 5 },
+ { }
};
static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index 1642dae..07a7f8f 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -104,6 +104,7 @@
[9] = { { 864000, HFPLL, 1, 0, 0x20 }, LVL_HIGH, 1150000, 4 },
[10] = { { 918000, HFPLL, 1, 0, 0x22 }, LVL_HIGH, 1150000, 4 },
[11] = { { 972000, HFPLL, 1, 0, 0x24 }, LVL_HIGH, 1150000, 4 },
+ { }
};
/* TODO: Update core voltages when data is available. */
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index 782ee60..77876ee 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -144,6 +144,7 @@
[13] = { { 1080000, HFPLL, 1, 0, 0x28 }, LVL_HIGH, 1150000, 7 },
[14] = { { 1134000, HFPLL, 1, 0, 0x2A }, LVL_HIGH, 1150000, 7 },
[15] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 },
+ { }
};
static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index 34ba1da..dbc3e32 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -111,6 +111,7 @@
[13] = { { 1080000, HFPLL, 1, 0, 0x28 }, LVL_HIGH, 1150000, 7 },
[14] = { { 1134000, HFPLL, 1, 0, 0x2A }, LVL_HIGH, 1150000, 7 },
[15] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 },
+ { }
};
static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 8cc4b13..631bd7e 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -109,6 +109,7 @@
[16] = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 6 },
[17] = { { 1296000, HFPLL, 1, 0, 0x30 }, 1150000, 1150000, 6 },
[18] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 6 },
+ { }
};
static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 3c42090..63bff55 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -99,6 +99,7 @@
[7] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 5 },
[8] = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 5 },
[9] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 5 },
+ { }
};
static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index f0b1231..16f77ba 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -134,6 +134,7 @@
[23] = { { 2035200, HFPLL, 1, 0, 106 }, LVL_HIGH, 1050000, 3 },
[24] = { { 2112000, HFPLL, 1, 0, 110 }, LVL_HIGH, 1050000, 3 },
[25] = { { 2188800, HFPLL, 1, 0, 114 }, LVL_HIGH, 1050000, 3 },
+ { }
};
static struct acpu_level acpu_freq_tbl[] __initdata = {
diff --git a/arch/arm/mach-msm/adsp-8974.c b/arch/arm/mach-msm/adsp-8974.c
index 0ded432..050a24b 100644
--- a/arch/arm/mach-msm/adsp-8974.c
+++ b/arch/arm/mach-msm/adsp-8974.c
@@ -33,15 +33,18 @@
#define MODULE_NAME "adsp_8974"
#define MAX_BUF_SIZE 0x51
+/* Interrupt line for WDOG bite*/
+#define ADSP_Q6SS_WDOG_EXPIRED 194
+
/* Subsystem restart: QDSP6 data, functions */
-static void lpass_fatal_fn(struct work_struct *);
-static DECLARE_WORK(lpass_fatal_work, lpass_fatal_fn);
+static void adsp_fatal_fn(struct work_struct *);
+static DECLARE_WORK(adsp_fatal_work, adsp_fatal_fn);
-struct lpass_ssr {
- void *lpass_ramdump_dev;
-} lpass_ssr;
+struct adsp_ssr {
+ void *adsp_ramdump_dev;
+} adsp_ssr;
-static struct lpass_ssr lpass_ssr_8974;
+static struct adsp_ssr adsp_ssr_8974;
static int q6_crash_shutdown;
static int riva_notifier_cb(struct notifier_block *this, unsigned long code,
@@ -88,7 +91,7 @@
.notifier_call = modem_notifier_cb,
};
-static void lpass_log_failure_reason(void)
+static void adsp_log_failure_reason(void)
{
char *reason;
char buffer[MAX_BUF_SIZE];
@@ -116,15 +119,15 @@
wmb();
}
-static void lpass_fatal_fn(struct work_struct *work)
+static void adsp_fatal_fn(struct work_struct *work)
{
pr_err("%s %s: Watchdog bite received from Q6!\n", MODULE_NAME,
__func__);
- lpass_log_failure_reason();
+ adsp_log_failure_reason();
panic(MODULE_NAME ": Resetting the SoC");
}
-static void lpass_smsm_state_cb(void *data, uint32_t old_state,
+static void adsp_smsm_state_cb(void *data, uint32_t old_state,
uint32_t new_state)
{
/* Ignore if we're the one that set SMSM_RESET */
@@ -132,9 +135,9 @@
return;
if (new_state & SMSM_RESET) {
- pr_debug("%s: LPASS SMSM state changed to SMSM_RESET, new_state= 0x%x, old_state = 0x%x\n",
+ pr_debug("%s: ADSP SMSM state changed to SMSM_RESET, new_state= 0x%x, old_state = 0x%x\n",
__func__, new_state, old_state);
- lpass_log_failure_reason();
+ adsp_log_failure_reason();
panic(MODULE_NAME ": Resetting the SoC");
}
}
@@ -146,7 +149,7 @@
pr_debug("%s: Q6 NMI was sent.\n", __func__);
}
-static int lpass_shutdown(const struct subsys_desc *subsys)
+static int adsp_shutdown(const struct subsys_desc *subsys)
{
send_q6_nmi();
@@ -154,12 +157,12 @@
mb();
pil_force_shutdown("q6");
- disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
+ disable_irq_nosync(ADSP_Q6SS_WDOG_EXPIRED);
return 0;
}
-static int lpass_powerup(const struct subsys_desc *subsys)
+static int adsp_powerup(const struct subsys_desc *subsys)
{
int ret;
@@ -169,87 +172,86 @@
}
ret = pil_force_boot("q6");
- enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
+ enable_irq(ADSP_Q6SS_WDOG_EXPIRED);
return ret;
}
/* RAM segments - address and size for 8974 */
-static struct ramdump_segment q6_segments[] = { {0x8da00000, 0x8f200000 -
- 0x8da00000}, {0x28400000, 0x20000} };
-static int lpass_ramdump(int enable, const struct subsys_desc *subsys)
+static struct ramdump_segment q6_segment = {0xdc00000, 0x1800000};
+
+static int adsp_ramdump(int enable, const struct subsys_desc *subsys)
{
pr_debug("%s: enable[%d]\n", __func__, enable);
if (enable)
- return do_ramdump(lpass_ssr_8974.lpass_ramdump_dev,
- q6_segments,
- ARRAY_SIZE(q6_segments));
+ return do_ramdump(adsp_ssr_8974.adsp_ramdump_dev,
+ &q6_segment, 1);
else
return 0;
}
-static void lpass_crash_shutdown(const struct subsys_desc *subsys)
+static void adsp_crash_shutdown(const struct subsys_desc *subsys)
{
q6_crash_shutdown = 1;
send_q6_nmi();
}
-static irqreturn_t lpass_wdog_bite_irq(int irq, void *dev_id)
+static irqreturn_t adsp_wdog_bite_irq(int irq, void *dev_id)
{
int ret;
pr_debug("%s: rxed irq[0x%x]", __func__, irq);
- disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
- ret = schedule_work(&lpass_fatal_work);
+ disable_irq_nosync(ADSP_Q6SS_WDOG_EXPIRED);
+ ret = schedule_work(&adsp_fatal_work);
return IRQ_HANDLED;
}
-static struct subsys_device *lpass_8974_dev;
+static struct subsys_device *adsp_8974_dev;
-static struct subsys_desc lpass_8974 = {
- .name = "lpass",
- .shutdown = lpass_shutdown,
- .powerup = lpass_powerup,
- .ramdump = lpass_ramdump,
- .crash_shutdown = lpass_crash_shutdown
+static struct subsys_desc adsp_8974 = {
+ .name = "adsp",
+ .shutdown = adsp_shutdown,
+ .powerup = adsp_powerup,
+ .ramdump = adsp_ramdump,
+ .crash_shutdown = adsp_crash_shutdown
};
-static int __init lpass_restart_init(void)
+static int __init adsp_restart_init(void)
{
- lpass_8974_dev = subsys_register(&lpass_8974);
- if (IS_ERR(lpass_8974_dev))
- return PTR_ERR(lpass_8974_dev);
+ adsp_8974_dev = subsys_register(&adsp_8974);
+ if (IS_ERR(adsp_8974_dev))
+ return PTR_ERR(adsp_8974_dev);
return 0;
}
-static int __init lpass_fatal_init(void)
+static int __init adsp_fatal_init(void)
{
int ret;
ret = smsm_state_cb_register(SMSM_Q6_STATE, SMSM_RESET,
- lpass_smsm_state_cb, 0);
+ adsp_smsm_state_cb, 0);
if (ret < 0)
pr_err("%s: Unable to register SMSM callback! (%d)\n",
__func__, ret);
- ret = request_irq(LPASS_Q6SS_WDOG_EXPIRED, lpass_wdog_bite_irq,
+ ret = request_irq(ADSP_Q6SS_WDOG_EXPIRED, adsp_wdog_bite_irq,
IRQF_TRIGGER_RISING, "q6_wdog", NULL);
if (ret < 0) {
- pr_err("%s: Unable to request LPASS_Q6SS_WDOG_EXPIRED irq.",
+ pr_err("%s: Unable to request ADSP_Q6SS_WDOG_EXPIRED irq.",
__func__);
goto out;
}
- ret = lpass_restart_init();
+ ret = adsp_restart_init();
if (ret < 0) {
- pr_err("%s: Unable to reg with lpass ssr. (%d)\n",
+ pr_err("%s: Unable to reg with adsp ssr. (%d)\n",
__func__, ret);
goto out;
}
- lpass_ssr_8974.lpass_ramdump_dev = create_ramdump_device("lpass");
+ adsp_ssr_8974.adsp_ramdump_dev = create_ramdump_device("adsp");
- if (!lpass_ssr_8974.lpass_ramdump_dev) {
+ if (!adsp_ssr_8974.adsp_ramdump_dev) {
pr_err("%s: Unable to create ramdump device.\n",
__func__);
ret = -ENOMEM;
@@ -261,7 +263,7 @@
ret = PTR_ERR(ssr_notif_hdle);
pr_err("%s: subsys_register_notifier for Riva: err = %d\n",
__func__, ret);
- free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
+ free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
goto out;
}
@@ -272,24 +274,24 @@
pr_err("%s: subsys_register_notifier for Modem: err = %d\n",
__func__, ret);
subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
- free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
+ free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
goto out;
}
- pr_info("%s: lpass SSR driver init'ed.\n", __func__);
+ pr_info("%s: adsp ssr driver init'ed.\n", __func__);
out:
return ret;
}
-static void __exit lpass_fatal_exit(void)
+static void __exit adsp_fatal_exit(void)
{
subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
subsys_notif_unregister_notifier(ssr_modem_notif_hdle, &mnb);
- subsys_unregister(lpass_8974_dev);
- free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
+ subsys_unregister(adsp_8974_dev);
+ free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
}
-module_init(lpass_fatal_init);
-module_exit(lpass_fatal_exit);
+module_init(adsp_fatal_init);
+module_exit(adsp_fatal_exit);
MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 722b8ea..bc1eded 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -323,6 +323,40 @@
},
};
+static struct msm_bus_vectors cam_dual_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 348192000,
+ .ib = 1208286720,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 206807040,
+ .ib = 488816640,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
+};
+
+
static struct msm_bus_paths cam_bus_client_config[] = {
{
ARRAY_SIZE(cam_init_vectors),
@@ -348,6 +382,10 @@
ARRAY_SIZE(cam_video_ls_vectors),
cam_video_ls_vectors,
},
+ {
+ ARRAY_SIZE(cam_dual_vectors),
+ cam_dual_vectors,
+ },
};
static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 04326aa..3b47d2e 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -126,7 +126,7 @@
PM8921_GPIO_INPUT(35, PM_GPIO_PULL_UP_30),
PM8921_GPIO_INPUT(38, PM_GPIO_PULL_UP_30),
/* TABLA CODEC RESET */
- PM8921_GPIO_OUTPUT(34, 0, MED),
+ PM8921_GPIO_OUTPUT(34, 1, HIGH),
PM8921_GPIO_OUTPUT(13, 0, HIGH), /* PCIE_CLK_PWR_EN */
PM8921_GPIO_INPUT(12, PM_GPIO_PULL_UP_30), /* PCIE_WAKE_N */
};
@@ -142,6 +142,10 @@
PM8921_GPIO_INPUT(17, PM_GPIO_PULL_UP_1P5), /* SD_WP */
};
+static struct pm8xxx_gpio_init pm8921_mpq8064_hrd_gpios[] __initdata = {
+ PM8921_GPIO_OUTPUT(37, 0, LOW), /* MUX1_SEL */
+};
+
/* Initial PM8917 GPIO configurations */
static struct pm8xxx_gpio_init pm8917_gpios[] __initdata = {
PM8921_GPIO_OUTPUT(14, 1, HIGH), /* HDMI Mux Selector */
@@ -223,6 +227,10 @@
apq8064_configure_gpios(pm8921_mpq_gpios,
ARRAY_SIZE(pm8921_mpq_gpios));
+ if (machine_is_mpq8064_hrd())
+ apq8064_configure_gpios(pm8921_mpq8064_hrd_gpios,
+ ARRAY_SIZE(pm8921_mpq8064_hrd_gpios));
+
for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
&pm8xxx_mpps[i].config);
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 1a5924d..c1798bf 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -33,6 +33,9 @@
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.2"),
REGULATOR_SUPPLY("lvds_pll_vdda", "lvds.0"),
REGULATOR_SUPPLY("dsi1_pll_vdda", "mipi_dsi.1"),
+ REGULATOR_SUPPLY("HRD_VDDD_CDC_D", "tabla2x-slim"),
+ REGULATOR_SUPPLY("HRD_CDC_VDDA_A_1P2V", "tabla2x-slim"),
+ REGULATOR_SUPPLY("dsi_pll_vdda", "mdp.0"),
};
VREG_CONSUMERS(L3) = {
REGULATOR_SUPPLY("8921_l3", NULL),
@@ -225,6 +228,7 @@
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
REGULATOR_SUPPLY("lvds_vdda", "lvds.0"),
REGULATOR_SUPPLY("dsi1_vddio", "mipi_dsi.1"),
+ REGULATOR_SUPPLY("dsi_pll_vddio", "mdp.0"),
REGULATOR_SUPPLY("hdmi_vdda", "hdmi_msm.0"),
};
VREG_CONSUMERS(USB_OTG) = {
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f1143de..ec52d1a 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -217,6 +217,13 @@
#endif /* CONFIG_MSM_MULTIMEDIA_USE_ION */
#endif /* CONFIG_ANDROID_PMEM */
+#ifdef CONFIG_BATTERY_BCL
+static struct platform_device battery_bcl_device = {
+ .name = "battery_current_limit",
+ .id = -1,
+};
+#endif
+
struct fmem_platform_data apq8064_fmem_pdata = {
};
@@ -1222,6 +1229,74 @@
},
};
+static struct wcd9xxx_pdata mpq8064_ashiko20_platform_data = {
+ .slimbus_slave_device = {
+ .name = "tabla-slave",
+ .e_addr = {0, 0, 0x60, 0, 0x17, 2},
+ },
+ .irq = MSM_GPIO_TO_INT(42),
+ .irq_base = TABLA_INTERRUPT_BASE,
+ .num_irqs = NR_WCD9XXX_IRQS,
+ .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+ .micbias = {
+ .ldoh_v = TABLA_LDOH_2P85_V,
+ .cfilt1_mv = 1800,
+ .cfilt2_mv = 1800,
+ .cfilt3_mv = 1800,
+ .bias1_cfilt_sel = TABLA_CFILT1_SEL,
+ .bias2_cfilt_sel = TABLA_CFILT2_SEL,
+ .bias3_cfilt_sel = TABLA_CFILT3_SEL,
+ .bias4_cfilt_sel = TABLA_CFILT3_SEL,
+ },
+ .regulator = {
+ {
+ .name = "CDC_VDD_CP",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_RX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_TX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+ },
+ {
+ .name = "VDDIO_CDC",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+ },
+ {
+ .name = "HRD_VDDD_CDC_D",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+ },
+ {
+ .name = "HRD_CDC_VDDA_A_1P2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+ },
+ },
+};
+
+static struct slim_device mpq8064_slim_ashiko20 = {
+ .name = "tabla2x-slim",
+ .e_addr = {0, 1, 0x60, 0, 0x17, 2},
+ .dev = {
+ .platform_data = &mpq8064_ashiko20_platform_data,
+ },
+};
+
+
/* enable the level shifter for cs8427 to make sure the I2C
* clock is running at 100KHz and voltage levels are at 3.3
* and 5 volts
@@ -1631,10 +1706,16 @@
/* qseecom bus scaling */
static struct msm_bus_vectors qseecom_clks_init_vectors[] = {
{
- .src = MSM_BUS_MASTER_SPS,
+ .src = MSM_BUS_MASTER_ADM_PORT0,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ib = 0,
.ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_ADM_PORT1,
+ .dst = MSM_BUS_SLAVE_GSBI1_UART,
+ .ab = 0,
+ .ib = 0,
},
{
.src = MSM_BUS_MASTER_SPDM,
@@ -1646,10 +1727,16 @@
static struct msm_bus_vectors qseecom_enable_dfab_vectors[] = {
{
- .src = MSM_BUS_MASTER_SPS,
+ .src = MSM_BUS_MASTER_ADM_PORT0,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ib = (492 * 8) * 1000000UL,
- .ab = (492 * 8) * 100000UL,
+ .ab = 70000000UL,
+ .ib = 70000000UL,
+ },
+ {
+ .src = MSM_BUS_MASTER_ADM_PORT1,
+ .dst = MSM_BUS_SLAVE_GSBI1_UART,
+ .ab = 2480000000UL,
+ .ib = 2480000000UL,
},
{
.src = MSM_BUS_MASTER_SPDM,
@@ -1661,10 +1748,16 @@
static struct msm_bus_vectors qseecom_enable_sfpb_vectors[] = {
{
- .src = MSM_BUS_MASTER_SPS,
+ .src = MSM_BUS_MASTER_ADM_PORT0,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ib = 0,
.ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_ADM_PORT1,
+ .dst = MSM_BUS_SLAVE_GSBI1_UART,
+ .ab = 0,
+ .ib = 0,
},
{
.src = MSM_BUS_MASTER_SPDM,
@@ -1681,7 +1774,7 @@
},
{
ARRAY_SIZE(qseecom_enable_dfab_vectors),
- qseecom_enable_sfpb_vectors,
+ qseecom_enable_dfab_vectors,
},
{
ARRAY_SIZE(qseecom_enable_sfpb_vectors),
@@ -2469,6 +2562,9 @@
&msm_tsens_device,
&apq8064_cache_dump_device,
&msm_8064_device_tspp,
+#ifdef CONFIG_BATTERY_BCL
+ &battery_bcl_device,
+#endif
};
static struct platform_device *cdp_devices[] __initdata = {
@@ -2537,7 +2633,9 @@
static int rf4ce_gpio_init(void)
{
- if (!machine_is_mpq8064_cdp())
+ if (!machine_is_mpq8064_cdp() &&
+ !machine_is_mpq8064_hrd() &&
+ !machine_is_mpq8064_dtv())
return -EINVAL;
/* CC2533 SRDY Input */
@@ -3285,6 +3383,10 @@
}
}
platform_device_register(&apq8064_slim_ctrl);
+ if (machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
+ apq8064_slim_devices[ARRAY_SIZE(apq8064_slim_devices) - 1].\
+ slim_slave = &mpq8064_slim_ashiko20;
+ }
slim_register_board_info(apq8064_slim_devices,
ARRAY_SIZE(apq8064_slim_devices));
if (!PLATFORM_IS_MPQ8064()) {
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 1352928..883e04d 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -331,6 +331,28 @@
},
};
+static struct msm_bus_vectors cam_dual_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 302071680,
+ .ib = 1208286720,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 206807040,
+ .ib = 488816640,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+};
+
+
static struct msm_bus_paths cam_bus_client_config[] = {
{
ARRAY_SIZE(cam_init_vectors),
@@ -356,6 +378,10 @@
ARRAY_SIZE(cam_video_ls_vectors),
cam_video_ls_vectors,
},
+ {
+ ARRAY_SIZE(cam_dual_vectors),
+ cam_dual_vectors,
+ },
};
static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index b6e20fd..cc5651d 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -441,8 +441,22 @@
.priority = 0,
};
+/*
+ * 0x254=0xC8 (Threshold=110, preamp bias=01)
+ * 0x255=0xC1 (Hold=110, max attn=0000, mute=1)
+ * 0x256=0xB0 (decay=101, attack=10, delay=0)
+ */
+
static struct pm8xxx_spk_platform_data pm8xxx_spk_pdata = {
.spk_add_enable = false,
+ .cd_ng_threshold = 0x6,
+ .cd_nf_preamp_bias = 0x1,
+ .cd_ng_hold = 0x6,
+ .cd_ng_max_atten = 0x0,
+ .noise_mute = 1,
+ .cd_ng_decay_rate = 0x5,
+ .cd_ng_attack_rate = 0x2,
+ .cd_delay = 0x0,
};
static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
diff --git a/arch/arm/mach-msm/board-8930-regulator-pm8038.c b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
index ed9d802..208f15b 100644
--- a/arch/arm/mach-msm/board-8930-regulator-pm8038.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
@@ -35,6 +35,7 @@
REGULATOR_SUPPLY("8038_l2", NULL),
REGULATOR_SUPPLY("iris_vdddig", "wcnss_wlan.0"),
REGULATOR_SUPPLY("dsi_vdda", "mipi_dsi.1"),
+ REGULATOR_SUPPLY("dsi_pll_vdda", "mdp.0"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.0"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.1"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.2"),
@@ -146,6 +147,7 @@
VREG_CONSUMERS(L23) = {
REGULATOR_SUPPLY("8038_l23", NULL),
REGULATOR_SUPPLY("dsi_vddio", "mipi_dsi.1"),
+ REGULATOR_SUPPLY("dsi_pll_vddio", "mdp.0"),
REGULATOR_SUPPLY("hdmi_avdd", "hdmi_msm.0"),
REGULATOR_SUPPLY("hdmi_vcc", "hdmi_msm.0"),
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 3f530c7..aad0f3d 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -991,6 +991,12 @@
.ab = 0,
},
{
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ib = 0,
+ .ab = 0,
+ },
+ {
.src = MSM_BUS_MASTER_SPDM,
.dst = MSM_BUS_SLAVE_SPDM,
.ib = 0,
@@ -1006,6 +1012,12 @@
.ab = (492 * 8) * 100000UL,
},
{
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ib = (492 * 8) * 1000000UL,
+ .ab = (492 * 8) * 100000UL,
+ },
+ {
.src = MSM_BUS_MASTER_SPDM,
.dst = MSM_BUS_SLAVE_SPDM,
.ib = 0,
@@ -1021,6 +1033,12 @@
.ab = 0,
},
{
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ib = 0,
+ .ab = 0,
+ },
+ {
.src = MSM_BUS_MASTER_SPDM,
.dst = MSM_BUS_SLAVE_SPDM,
.ib = (64 * 8) * 1000000UL,
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index c00535b..792eea4 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -400,6 +400,40 @@
},
};
+static struct msm_bus_vectors cam_dual_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 348192000,
+ .ib = 1208286720,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 206807040,
+ .ib = 488816640,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
+};
+
+
static struct msm_bus_paths cam_bus_client_config[] = {
{
@@ -426,6 +460,10 @@
ARRAY_SIZE(cam_video_ls_vectors),
cam_video_ls_vectors,
},
+ {
+ ARRAY_SIZE(cam_dual_vectors),
+ cam_dual_vectors,
+ },
};
static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index ac4e363..3052902 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -586,6 +586,8 @@
.mem_hid = MEMTYPE_EBI1,
#endif
.cont_splash_enabled = 0x01,
+ .splash_screen_addr = 0x00,
+ .splash_screen_size = 0x00,
.mdp_iommu_split_domain = 0,
};
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 8fc26ea..2fa98b6 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -31,6 +31,7 @@
VREG_CONSUMERS(L2) = {
REGULATOR_SUPPLY("8921_l2", NULL),
REGULATOR_SUPPLY("dsi_vdda", "mipi_dsi.1"),
+ REGULATOR_SUPPLY("dsi_pll_vdda", "mdp.0"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.0"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.1"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.2"),
@@ -116,6 +117,7 @@
VREG_CONSUMERS(L23) = {
REGULATOR_SUPPLY("8921_l23", NULL),
REGULATOR_SUPPLY("dsi_vddio", "mipi_dsi.1"),
+ REGULATOR_SUPPLY("dsi_pll_vddio", "mdp.0"),
REGULATOR_SUPPLY("hdmi_avdd", "hdmi_msm.0"),
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.1"),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index dd4c30e..a54c3e2 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1056,6 +1056,12 @@
.ab = 0,
},
{
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ib = 0,
+ .ab = 0,
+ },
+ {
.src = MSM_BUS_MASTER_SPDM,
.dst = MSM_BUS_SLAVE_SPDM,
.ib = 0,
@@ -1071,6 +1077,12 @@
.ab = (492 * 8) * 100000UL,
},
{
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ib = (492 * 8) * 1000000UL,
+ .ab = (492 * 8) * 100000UL,
+ },
+ {
.src = MSM_BUS_MASTER_SPDM,
.dst = MSM_BUS_SLAVE_SPDM,
.ib = 0,
@@ -1086,6 +1098,12 @@
.ab = 0,
},
{
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ib = 0,
+ .ab = 0,
+ },
+ {
.src = MSM_BUS_MASTER_SPDM,
.dst = MSM_BUS_SLAVE_SPDM,
.ib = (64 * 8) * 1000000UL,
@@ -1100,7 +1118,7 @@
},
{
ARRAY_SIZE(qseecom_enable_dfab_vectors),
- qseecom_enable_sfpb_vectors,
+ qseecom_enable_dfab_vectors,
},
{
ARRAY_SIZE(qseecom_enable_sfpb_vectors),
@@ -2362,7 +2380,6 @@
static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi4_pdata = {
.clk_freq = 100000,
.src_clk_rate = 24000000,
- .keep_ahb_clk_on = 1,
};
static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi3_pdata = {
@@ -2448,6 +2465,13 @@
};
#endif
+#ifdef CONFIG_BATTERY_BCL
+static struct platform_device battery_bcl_device = {
+ .name = "battery_current_limit",
+ .id = -1,
+};
+#endif
+
static struct platform_device msm8960_device_ext_5v_vreg __devinitdata = {
.name = GPIO_REGULATOR_DEV_NAME,
.id = PM8921_MPP_PM_TO_SYS(7),
@@ -2672,6 +2696,9 @@
#ifdef CONFIG_MSM_FAKE_BATTERY
&fish_battery_device,
#endif
+#ifdef CONFIG_BATTERY_BCL
+ &battery_bcl_device,
+#endif
&msm8960_fmem_device,
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -2720,8 +2747,6 @@
static struct platform_device *cdp_devices[] __initdata = {
&msm_8960_q6_lpass,
- &msm_8960_q6_mss_fw,
- &msm_8960_q6_mss_sw,
&msm_8960_riva,
&msm_pil_tzapps,
&msm_pil_dsps,
@@ -2775,6 +2800,9 @@
static void __init msm8960_i2c_init(void)
{
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+ msm8960_i2c_qup_gsbi4_pdata.keep_ahb_clk_on = 1;
+
msm8960_device_qup_i2c_gsbi4.dev.platform_data =
&msm8960_i2c_qup_gsbi4_pdata;
@@ -3211,6 +3239,11 @@
msm8960_add_vidc_device();
msm8960_pm8921_gpio_mpp_init();
+ /* Don't add modem devices on APQ targets */
+ if (socinfo_get_id() != 124) {
+ platform_device_register(&msm_8960_q6_mss_fw);
+ platform_device_register(&msm_8960_q6_mss_sw);
+ }
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
msm8960_init_smsc_hub();
msm8960_init_hsic();
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 8d593f6..dcc0d01 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -268,11 +268,6 @@
msm_reserve();
}
-static struct platform_device android_usb_device = {
- .name = "android_usb",
- .id = -1,
-};
-
#define BIMC_BASE 0xfc380000
#define BIMC_SIZE 0x0006A000
#define SYS_NOC_BASE 0xfc460000
@@ -463,7 +458,6 @@
void __init msm_8974_add_devices(void)
{
platform_device_register(&msm_device_smd_8974);
- platform_device_register(&android_usb_device);
}
/*
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 92ceabe..01bc9dd 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4763,7 +4763,6 @@
static DEFINE_CLK_VOTER(dfab_sps_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c, 0);
-static DEFINE_CLK_VOTER(dfab_qseecom_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c, 0);
@@ -5483,7 +5482,6 @@
CLK_LOOKUP("dfab_clk", dfab_sps_clk.c, "msm_sps"),
CLK_LOOKUP("bus_clk", dfab_bam_dmux_clk.c, "BAM_RMNT"),
CLK_LOOKUP("bus_clk", dfab_scm_clk.c, "scm"),
- CLK_LOOKUP("bus_clk", dfab_qseecom_clk.c, "qseecom"),
CLK_LOOKUP("alt_core_clk", usb_hsic_xcvr_fs_clk.c, "msm_hsic_host"),
CLK_LOOKUP("phy_clk", usb_hsic_hsic_clk.c, "msm_hsic_host"),
@@ -5834,7 +5832,6 @@
CLK_LOOKUP("dfab_clk", dfab_sps_clk.c, "msm_sps"),
CLK_LOOKUP("bus_clk", dfab_bam_dmux_clk.c, "BAM_RMNT"),
CLK_LOOKUP("bus_clk", dfab_scm_clk.c, "scm"),
- CLK_LOOKUP("bus_clk", dfab_qseecom_clk.c, "qseecom"),
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
CLK_LOOKUP("mem_clk", ebi1_acpu_a_clk.c, ""),
@@ -6166,7 +6163,6 @@
CLK_LOOKUP("dfab_clk", dfab_sps_clk.c, "msm_sps"),
CLK_LOOKUP("bus_clk", dfab_bam_dmux_clk.c, "BAM_RMNT"),
CLK_LOOKUP("bus_clk", dfab_scm_clk.c, "scm"),
- CLK_LOOKUP("bus_clk", dfab_qseecom_clk.c, "qseecom"),
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
CLK_LOOKUP("mem_clk", ebi1_acpu_a_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index dc0a527..b054e08 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -35,7 +35,6 @@
GCC_BASE,
MMSS_BASE,
LPASS_BASE,
- MSS_BASE,
APCS_BASE,
N_BASES,
};
@@ -45,7 +44,6 @@
#define GCC_REG_BASE(x) (void __iomem *)(virt_bases[GCC_BASE] + (x))
#define MMSS_REG_BASE(x) (void __iomem *)(virt_bases[MMSS_BASE] + (x))
#define LPASS_REG_BASE(x) (void __iomem *)(virt_bases[LPASS_BASE] + (x))
-#define MSS_REG_BASE(x) (void __iomem *)(virt_bases[MSS_BASE] + (x))
#define APCS_REG_BASE(x) (void __iomem *)(virt_bases[APCS_BASE] + (x))
#define GPLL0_MODE_REG 0x0000
@@ -112,7 +110,6 @@
#define MMSS_DEBUG_CLK_CTL_REG 0x0900
#define LPASS_DEBUG_CLK_CTL_REG 0x29000
#define LPASS_LPA_PLL_VOTE_APPS_REG 0x2000
-#define MSS_DEBUG_CLK_CTL_REG 0x0078
#define GLB_CLK_DIAG_REG 0x001C
@@ -300,7 +297,6 @@
#define OXILI_BCR 0x4020
#define OXILICX_BCR 0x4030
#define LPASS_Q6SS_BCR 0x6000
-#define MSS_Q6SS_BCR 0x1068
#define OCMEM_SYS_NOC_AXI_CBCR 0x0244
#define OCMEM_NOC_CFG_AHB_CBCR 0x0248
@@ -498,8 +494,6 @@
#define LPASS_Q6_AXI_CBCR 0x11C0
#define Q6SS_AHBM_CBCR 0x22004
#define AUDIO_WRAPPER_BR_CBCR 0x24000
-#define MSS_XO_Q6_CBCR 0x108C
-#define MSS_BUS_Q6_CBCR 0x10A4
#define MSS_CFG_AHB_CBCR 0x0280
#define MSS_Q6_BIMC_AXI_CBCR 0x0284
@@ -4586,31 +4580,6 @@
},
};
-static struct branch_clk mss_xo_q6_clk = {
- .cbcr_reg = MSS_XO_Q6_CBCR,
- .bcr_reg = MSS_Q6SS_BCR,
- .has_sibling = 1,
- .base = &virt_bases[MSS_BASE],
- .c = {
- .dbg_name = "mss_xo_q6_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(mss_xo_q6_clk.c),
- .depends = &gcc_mss_cfg_ahb_clk.c,
- },
-};
-
-static struct branch_clk mss_bus_q6_clk = {
- .cbcr_reg = MSS_BUS_Q6_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[MSS_BASE],
- .c = {
- .dbg_name = "mss_bus_q6_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(mss_bus_q6_clk.c),
- .depends = &gcc_mss_cfg_ahb_clk.c,
- },
-};
-
static DEFINE_CLK_MEASURE(l2_m_clk);
static DEFINE_CLK_MEASURE(krait0_m_clk);
static DEFINE_CLK_MEASURE(krait1_m_clk);
@@ -4795,8 +4764,6 @@
{&q6ss_ahbm_clk.c, LPASS_BASE, 0x001d},
{&audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
{&audio_wrapper_br_clk.c, LPASS_BASE, 0x0022},
- {&mss_bus_q6_clk.c, MSS_BASE, 0x003b},
- {&mss_xo_q6_clk.c, MSS_BASE, 0x0007},
{&l2_m_clk, APCS_BASE, 0x0081},
{&krait0_m_clk, APCS_BASE, 0x0080},
@@ -4860,13 +4827,6 @@
writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
break;
- case MSS_BASE:
- writel_relaxed(0, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
- clk_sel = 0x32;
- regval = BVAL(5, 0, measure_mux[i].debug_mux);
- writel_relaxed(regval, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
- break;
-
case APCS_BASE:
clk->multiplier = 4;
clk_sel = 0x16A;
@@ -5376,10 +5336,9 @@
CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
"msm-dai-q6.4106"),
CLK_LOOKUP("br_clk", audio_wrapper_br_clk.c, "fdd00000.qcom,ocmem"),
- CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
+
CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "pil-q6v5-mss"),
- CLK_LOOKUP("reg_clk", mss_bus_q6_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("core_clk", q6ss_xo_clk.c, "pil-q6v5-lpass"),
@@ -5771,9 +5730,6 @@
#define LPASS_CC_PHYS 0xFE000000
#define LPASS_CC_SIZE SZ_256K
-#define MSS_CC_PHYS 0xFC980000
-#define MSS_CC_SIZE SZ_16K
-
#define APCS_GCC_CC_PHYS 0xF9011000
#define APCS_GCC_CC_SIZE SZ_4K
@@ -5809,10 +5765,6 @@
if (!virt_bases[LPASS_BASE])
panic("clock-8974: Unable to ioremap LPASS_CC memory!");
- virt_bases[MSS_BASE] = ioremap(MSS_CC_PHYS, MSS_CC_SIZE);
- if (!virt_bases[MSS_BASE])
- panic("clock-8974: Unable to ioremap MSS_CC memory!");
-
virt_bases[APCS_BASE] = ioremap(APCS_GCC_CC_PHYS, APCS_GCC_CC_SIZE);
if (!virt_bases[APCS_BASE])
panic("clock-8974: Unable to ioremap APCS_GCC_CC memory!");
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index dfef866..292f58d 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -543,8 +543,8 @@
};
static struct resource msm_rpm_rbcpr_resource = {
- .start = 0x0010CB00,
- .end = 0x0010CB00 + SZ_8K - 1,
+ .start = 0x0010DB00,
+ .end = 0x0010DB00 + SZ_8K - 1,
.flags = IORESOURCE_MEM,
};
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index ff7af32..8eed48d 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -128,6 +128,19 @@
bne skip
bl v7_flush_dcache_all
skip:
+ mrc p15, 0, r0, c0, c0, 5 /* MPIDR */
+ and r0, r0, #15 /* what CPU am I */
+
+ ldr r1, =msm_pc_debug_counters /*load the IMEM debug location */
+ ldr r1, [r1]
+ cmp r1, #0
+ beq skip_pc_debug1
+ add r1, r1, r0, LSL #4 /* debug location for this CPU */
+ ldr r2, [r1]
+ add r2, #1
+ str r2, [r1]
+skip_pc_debug1:
+
#ifdef CONFIG_ARCH_MSM_KRAIT
ldr r0, =SCM_SVC_BOOT
ldr r1, =SCM_CMD_TERMINATE_PC
@@ -155,6 +168,21 @@
#if defined(CONFIG_MSM_FIQ_SUPPORT)
cpsie f
#endif
+ mrc p15, 0, r0, c0, c0, 5 /* MPIDR */
+ and r0, r0, #15 /* what CPU am I */
+
+ ldr r1, =msm_pc_debug_counters /*load the IMEM debug location */
+ ldr r1, [r1]
+ cmp r1, #0
+ beq skip_pc_debug2
+ add r1, r1, r0, LSL #4 /* debug location for this CPU */
+ add r1, #8
+ ldr r2, [r1]
+ add r2, #1
+ str r2, [r1]
+
+skip_pc_debug2:
+
#ifdef CONFIG_MSM_JTAG
bl msm_jtag_restore_state
#endif
@@ -276,6 +304,22 @@
mrc p15, 0, r0, c0, c0, 5 /* MPIDR */
and r0, r0, #15 /* what CPU am I */
+ ldr r1, =msm_pc_debug_counters_phys /*phys addr for IMEM reg */
+ ldr r2, =msm_pm_boot_entry
+ adr r3, msm_pm_boot_entry
+ add r1, r1, r3 /* translate virt to phys addr */
+ sub r1, r1, r2
+ ldr r1,[r1]
+
+ cmp r1, #0
+ beq skip_pc_debug3
+ add r1, r1, r0, LSL #4 /* debug location for this CPU */
+ add r1, #4 /* warmboot entry counter*/
+ ldr r2, [r1]
+ add r2, #1
+ str r2, [r1]
+
+skip_pc_debug3:
ldr r1, =msm_pm_boot_vector
ldr r2, =msm_pm_boot_entry
adr r3, msm_pm_boot_entry
@@ -320,6 +364,14 @@
l2x0_base_addr:
.long 0x0
+ .globl msm_pc_debug_counters_phys
+msm_pc_debug_counters_phys:
+ .long 0x0
+
+ .globl msm_pc_debug_counters
+msm_pc_debug_counters:
+ .long 0x0
+
/*
* Default the l2 flush flag to 1 so that caches are flushed during power
* collapse unless the L2 driver decides to flush them only during L2
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 955cc93..5b8729a 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -395,6 +395,8 @@
u32 ov1_wb_size; /* overlay1 writeback size */
u32 mem_hid;
char cont_splash_enabled;
+ u32 splash_screen_addr;
+ u32 splash_screen_size;
char mdp_iommu_split_domain;
};
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 6298d94..60ccded 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -632,6 +632,7 @@
S_STEREO_CAPTURE,
S_DEFAULT,
S_LIVESHOT,
+ S_DUAL,
S_EXIT
};
diff --git a/arch/arm/mach-msm/include/mach/diag_dload.h b/arch/arm/mach-msm/include/mach/diag_dload.h
new file mode 100644
index 0000000..83c7f2d
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/diag_dload.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_DIAG_DLOAD_H__
+#define __LINUX_DIAG_DLOAD_H__
+
+
+#define PID_MAGIC_ID 0x71432909
+#define SERIAL_NUM_MAGIC_ID 0x61945374
+#define SERIAL_NUMBER_LENGTH 128
+
+struct magic_num_struct {
+ uint32_t pid;
+ uint32_t serial_num;
+};
+
+struct dload_struct {
+ uint32_t pid;
+ char serial_number[SERIAL_NUMBER_LENGTH];
+ struct magic_num_struct magic_struct;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memory_dump.h b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
index 3b8c9fd..5e686bf 100644
--- a/arch/arm/mach-msm/include/mach/msm_memory_dump.h
+++ b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
@@ -19,9 +19,13 @@
MSM_CPU_CTXT = 0,
MSM_CACHE,
MSM_OCMEM,
- MSM_ETB,
- MSM_ETM,
- MSM_TMC,
+ MSM_TMC_ETFETB,
+ MSM_ETM0_REG,
+ MSM_ETM1_REG,
+ MSM_ETM2_REG,
+ MSM_ETM3_REG,
+ MSM_TMC0_REG, /* TMC_ETR */
+ MSM_TMC1_REG, /* TMC_ETF */
MAX_NUM_CLIENTS,
};
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index 3b7c5d6..4f14b19 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.c
@@ -25,6 +25,12 @@
#include "cp14.h"
+/* DBGv7 with baseline CP14 registers implemented */
+#define ARM_DEBUG_ARCH_V7B (0x3)
+/* DBGv7 with all CP14 registers implemented */
+#define ARM_DEBUG_ARCH_V7 (0x4)
+#define ARM_DEBUG_ARCH_V7p1 (0x5)
+
#define BM(lsb, msb) ((BIT(msb) - BIT(lsb)) + BIT(msb))
#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
#define BVAL(val, n) ((val & BIT(n)) >> n)
@@ -363,7 +369,7 @@
static inline bool dbg_arch_supported(uint8_t arch)
{
switch (arch) {
- case ARM_DEBUG_ARCH_V7_1:
+ case ARM_DEBUG_ARCH_V7p1:
case ARM_DEBUG_ARCH_V7:
case ARM_DEBUG_ARCH_V7B:
break;
@@ -381,7 +387,7 @@
i = cpu * MAX_DBG_REGS;
switch (dbg.arch) {
- case ARM_DEBUG_ARCH_V7_1:
+ case ARM_DEBUG_ARCH_V7p1:
/* Set OS lock to inform the debugger that the OS is in the
* process of saving debug registers. It prevents accidental
* modification of the debug regs by the external debugger.
@@ -440,7 +446,7 @@
i = cpu * MAX_DBG_REGS;
switch (dbg.arch) {
- case ARM_DEBUG_ARCH_V7_1:
+ case ARM_DEBUG_ARCH_V7p1:
/* Clear the OS double lock */
isb();
dbg_write(0x0, DBGOSDLR);
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index 844a78b..f0a123b 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -258,8 +258,7 @@
{
int ret;
- if (!cpu_is_msm8960() && !cpu_is_msm8930() && !cpu_is_msm8930aa() &&
- !cpu_is_msm9615() && !cpu_is_msm8627())
+ if (cpu_is_apq8064())
return -ENODEV;
ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 1720729..1fdd342 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -84,18 +84,9 @@
ret = clk_prepare_enable(drv->ahb_clk);
if (ret)
goto err_ahb_clk;
- ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
- if (ret)
- goto err_reset;
- ret = clk_prepare_enable(drv->core_clk);
- if (ret)
- goto err_core_clk;
ret = clk_prepare_enable(drv->axi_clk);
if (ret)
goto err_axi_clk;
- ret = clk_prepare_enable(drv->reg_clk);
- if (ret)
- goto err_reg_clk;
ret = clk_prepare_enable(drv->rom_clk);
if (ret)
goto err_rom_clk;
@@ -109,14 +100,8 @@
return 0;
err_rom_clk:
- clk_disable_unprepare(drv->reg_clk);
-err_reg_clk:
clk_disable_unprepare(drv->axi_clk);
err_axi_clk:
- clk_disable_unprepare(drv->core_clk);
-err_core_clk:
- clk_reset(drv->core_clk, CLK_RESET_ASSERT);
-err_reset:
clk_disable_unprepare(drv->ahb_clk);
err_ahb_clk:
return ret;
@@ -125,10 +110,7 @@
static void pil_mss_disable_clks(struct q6v5_data *drv)
{
clk_disable_unprepare(drv->rom_clk);
- clk_disable_unprepare(drv->reg_clk);
clk_disable_unprepare(drv->axi_clk);
- clk_disable_unprepare(drv->core_clk);
- clk_reset(drv->core_clk, CLK_RESET_ASSERT);
clk_disable_unprepare(drv->ahb_clk);
}
@@ -321,18 +303,10 @@
if (IS_ERR(drv->ahb_clk))
return PTR_ERR(drv->ahb_clk);
- drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
- if (IS_ERR(drv->core_clk))
- return PTR_ERR(drv->core_clk);
-
drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(drv->axi_clk))
return PTR_ERR(drv->axi_clk);
- drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
- if (IS_ERR(drv->reg_clk))
- return PTR_ERR(drv->reg_clk);
-
drv->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
if (IS_ERR(drv->rom_clk))
return PTR_ERR(drv->rom_clk);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 8ddb9e1..dbb23d5 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -24,6 +24,7 @@
#include <linux/smp.h>
#include <linux/suspend.h>
#include <linux/tick.h>
+#include <linux/platform_device.h>
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <mach/system.h>
@@ -71,7 +72,6 @@
);
static int msm_pm_retention_tz_call;
-
/******************************************************************************
* Sleep Modes and Parameters
*****************************************************************************/
@@ -491,7 +491,6 @@
#ifdef CONFIG_VFP
vfp_pm_suspend();
#endif
-
collapsed = msm_pm_l2x0_power_collapse();
msm_pm_boot_config_after_pc(cpu);
@@ -950,6 +949,46 @@
msm_pm_retention_tz_call = flag;
}
+static int __devinit msm_pc_debug_probe(struct platform_device *pdev)
+{
+ struct resource *res = NULL;
+ int i ;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ goto fail;
+
+ msm_pc_debug_counters_phys = res->start;
+ WARN_ON(resource_size(res) < SZ_64);
+ msm_pc_debug_counters = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+
+ if (!msm_pc_debug_counters)
+ goto fail;
+
+ for (i = 0; i < resource_size(res)/4; i++)
+ __raw_writel(0, msm_pc_debug_counters + i * 4);
+ return 0;
+fail:
+ msm_pc_debug_counters = 0;
+ msm_pc_debug_counters_phys = 0;
+ return -EFAULT;
+}
+
+static struct of_device_id msm_pc_debug_table[] = {
+ {.compatible = "qcom,pc-cntr"},
+ {},
+};
+
+static struct platform_driver msm_pc_counter_driver = {
+ .probe = msm_pc_debug_probe,
+ .driver = {
+ .name = "pc-cntr",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_pc_debug_table,
+ },
+};
+
static int __init msm_pm_init(void)
{
pgd_t *pc_pgd;
@@ -965,6 +1004,7 @@
unsigned long exit_phys;
/* Page table for cores to come back up safely. */
+
pc_pgd = pgd_alloc(&init_mm);
if (!pc_pgd)
return -ENOMEM;
@@ -1007,6 +1047,7 @@
suspend_set_ops(&msm_pm_ops);
msm_pm_qtimer_available();
msm_cpuidle_init();
+ platform_driver_register(&msm_pc_counter_driver);
return 0;
}
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 552fb16..e2553e2 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -131,5 +131,6 @@
#endif
void msm_pm_set_cpr_ops(struct msm_pm_cpr_ops *ops);
-
+extern void *msm_pc_debug_counters;
+extern unsigned long msm_pc_debug_counters_phys;
#endif /* __ARCH_ARM_MACH_MSM_PM_H */
diff --git a/arch/arm/mach-msm/qdsp5/audio_mp3.c b/arch/arm/mach-msm/qdsp5/audio_mp3.c
index fb02729..cef3d99 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mp3.c
@@ -2298,7 +2298,10 @@
if (rc) {
MM_ERR("audmgr open failed, freeing instance \
0x%08x\n", (int)audio);
- goto err;
+ if (!(file->f_flags & O_NONBLOCK))
+ goto err;
+ else
+ goto resource_err;
}
}
@@ -2310,7 +2313,10 @@
audio->module_name, (int)audio);
if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
audmgr_close(&audio->audmgr);
- goto err;
+ if (!(file->f_flags & O_NONBLOCK))
+ goto err;
+ else
+ goto resource_err;
}
rc = rmt_get_resource(audio);
@@ -2320,7 +2326,10 @@
if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
audmgr_close(&audio->audmgr);
msm_adsp_put(audio->audplay);
- goto err;
+ if (!(file->f_flags & O_NONBLOCK))
+ goto err;
+ else
+ goto resource_err;
}
if (file->f_flags & O_NONBLOCK) {
@@ -2410,6 +2419,7 @@
output_buff_alloc_error:
ion_client_destroy(client);
client_create_error:
+resource_err:
audpp_adec_free(audio->dec_id);
kfree(audio);
return rc;
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 82aa14c..cae0f3a 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -353,7 +353,7 @@
return;
}
-static int get_voice_index(u32 cvs_handle)
+static int get_voice_index_cvs(u32 cvs_handle)
{
u32 i;
@@ -367,6 +367,32 @@
return 0;
}
+static int get_voice_index_cvp(u32 cvp_handle)
+{
+ u32 i;
+
+ for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
+ if (rtac_voice_data.voice[i].cvp_handle == cvp_handle)
+ return i;
+ }
+
+ pr_err("%s: No voice index for CVP handle %d found returning 0\n",
+ __func__, cvp_handle);
+ return 0;
+}
+
+static int get_voice_index(u32 mode, u32 handle)
+{
+ if (mode == RTAC_CVP)
+ return get_voice_index_cvp(handle);
+ if (mode == RTAC_CVS)
+ return get_voice_index_cvs(handle);
+
+ pr_err("%s: Invalid mode %d, returning 0\n",
+ __func__, mode);
+ return 0;
+}
+
/* ADM APR */
void rtac_set_adm_handle(void *handle)
@@ -752,7 +778,7 @@
u32 count = 0;
u32 bytes_returned = 0;
u32 payload_size;
- u16 dest_port;
+ u32 dest_port;
struct apr_hdr voice_params;
pr_debug("%s\n", __func__);
@@ -819,10 +845,10 @@
voice_params.src_svc = 0;
voice_params.src_domain = APR_DOMAIN_APPS;
voice_params.src_port = voice_session_id[
- get_voice_index(dest_port)];
+ get_voice_index(mode, dest_port)];
voice_params.dest_svc = 0;
voice_params.dest_domain = APR_DOMAIN_MODEM;
- voice_params.dest_port = dest_port;
+ voice_params.dest_port = (u16)dest_port;
voice_params.token = 0;
voice_params.opcode = opcode;
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index b112c90..a190342 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -823,7 +823,6 @@
unsigned long flags;
int rc = 0;
uint32_t id = 0;
- int count = 0;
if (!msg_id) {
pr_err("%s(): Invalid msg id\n", __func__);
@@ -853,7 +852,7 @@
goto wait_ack_cleanup;
}
- while ((id != msg_id) && (count++ < 10)) {
+ while (id != msg_id) {
if (smd_is_pkt_avail(msm_rpm_data.ch_info)) {
int errno;
char buf[MAX_ERR_BUFFER_SIZE] = {};
@@ -862,17 +861,11 @@
id = msm_rpm_get_msg_id_from_ack(buf);
errno = msm_rpm_get_error_from_ack(buf);
msm_rpm_process_ack(id, errno);
- } else
- udelay(100);
+ }
}
- if (count == 10) {
- rc = -ETIMEDOUT;
- pr_warn("%s(): Timed out after 1ms\n", __func__);
- } else {
- rc = elem->errno;
- msm_rpm_free_list_entry(elem);
- }
+ rc = elem->errno;
+ msm_rpm_free_list_entry(elem);
wait_ack_cleanup:
irq_process = false;
spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags);
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index af298d8..e33f87b 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -782,17 +782,21 @@
* @pid: Processor ID of processor on edge
* @local_ch: Channel that belongs to processor @pid
* @remote_ch: Other side of edge contained @pid
+ * @is_word_access_ch: Bool, is this a word aligned access channel
*
* Returns 0 for not on edge, 1 for found on edge
*/
-static int pid_is_on_edge(struct smd_shared_v2 *shared2,
+static int pid_is_on_edge(void *shared2,
uint32_t type, uint32_t pid,
- struct smd_half_channel **local_ch,
- struct smd_half_channel **remote_ch
+ void **local_ch,
+ void **remote_ch,
+ int is_word_access_ch
)
{
int ret = 0;
struct edge_to_pid *edge;
+ void *ch0;
+ void *ch1;
*local_ch = 0;
*remote_ch = 0;
@@ -800,15 +804,23 @@
if (!shared2 || (type >= ARRAY_SIZE(edge_to_pids)))
return 0;
+ if (is_word_access_ch) {
+ ch0 = &((struct smd_shared_v2_word_access *)(shared2))->ch0;
+ ch1 = &((struct smd_shared_v2_word_access *)(shared2))->ch1;
+ } else {
+ ch0 = &((struct smd_shared_v2 *)(shared2))->ch0;
+ ch1 = &((struct smd_shared_v2 *)(shared2))->ch1;
+ }
+
edge = &edge_to_pids[type];
if (edge->local_pid != edge->remote_pid) {
if (pid == edge->local_pid) {
- *local_ch = &shared2->ch0;
- *remote_ch = &shared2->ch1;
+ *local_ch = ch0;
+ *remote_ch = ch1;
ret = 1;
} else if (pid == edge->remote_pid) {
- *local_ch = &shared2->ch1;
- *remote_ch = &shared2->ch0;
+ *local_ch = ch1;
+ *remote_ch = ch0;
ret = 1;
}
}
@@ -860,14 +872,29 @@
}
EXPORT_SYMBOL(smd_pid_to_subsystem);
-static void smd_reset_edge(struct smd_half_channel *ch, unsigned new_state)
+static void smd_reset_edge(void *void_ch, unsigned new_state,
+ int is_word_access_ch)
{
- if (ch->state != SMD_SS_CLOSED) {
- ch->state = new_state;
- ch->fDSR = 0;
- ch->fCTS = 0;
- ch->fCD = 0;
- ch->fSTATE = 1;
+ if (is_word_access_ch) {
+ struct smd_half_channel_word_access *ch =
+ (struct smd_half_channel_word_access *)(void_ch);
+ if (ch->state != SMD_SS_CLOSED) {
+ ch->state = new_state;
+ ch->fDSR = 0;
+ ch->fCTS = 0;
+ ch->fCD = 0;
+ ch->fSTATE = 1;
+ }
+ } else {
+ struct smd_half_channel *ch =
+ (struct smd_half_channel *)(void_ch);
+ if (ch->state != SMD_SS_CLOSED) {
+ ch->state = new_state;
+ ch->fDSR = 0;
+ ch->fCTS = 0;
+ ch->fCD = 0;
+ ch->fSTATE = 1;
+ }
}
}
@@ -875,10 +902,11 @@
unsigned new_state, unsigned pid)
{
unsigned n;
- struct smd_shared_v2 *shared2;
+ void *shared2;
uint32_t type;
- struct smd_half_channel *local_ch;
- struct smd_half_channel *remote_ch;
+ void *local_ch;
+ void *remote_ch;
+ int is_word_access;
for (n = 0; n < SMD_CHANNELS; n++) {
if (!shared[n].ref_count)
@@ -887,12 +915,19 @@
continue;
type = SMD_CHANNEL_TYPE(shared[n].type);
- shared2 = smem_alloc(SMEM_SMD_BASE_ID + n, sizeof(*shared2));
+ is_word_access = is_word_access_ch(type);
+ if (is_word_access)
+ shared2 = smem_alloc(SMEM_SMD_BASE_ID + n,
+ sizeof(struct smd_shared_v2_word_access));
+ else
+ shared2 = smem_alloc(SMEM_SMD_BASE_ID + n,
+ sizeof(struct smd_shared_v2));
if (!shared2)
continue;
- if (pid_is_on_edge(shared2, type, pid, &local_ch, &remote_ch))
- smd_reset_edge(local_ch, new_state);
+ if (pid_is_on_edge(shared2, type, pid, &local_ch, &remote_ch,
+ is_word_access))
+ smd_reset_edge(local_ch, new_state, is_word_access);
/*
* ModemFW is in the same subsystem as ModemSW, but has
@@ -900,8 +935,8 @@
*/
if (pid == SMSM_MODEM &&
pid_is_on_edge(shared2, type, SMD_MODEM_Q6_FW,
- &local_ch, &remote_ch))
- smd_reset_edge(local_ch, new_state);
+ &local_ch, &remote_ch, is_word_access))
+ smd_reset_edge(local_ch, new_state, is_word_access);
}
}
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index cc3b956..0318a70 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -767,7 +767,7 @@
{
int ret;
- ssr_wq = alloc_workqueue("ssr_wq", 0, 0);
+ ssr_wq = alloc_workqueue("ssr_wq", WQ_CPU_INTENSIVE, 0);
BUG_ON(!ssr_wq);
ret = bus_register(&subsys_bus_type);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 884e5fe..c827ec7 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -16,6 +16,7 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
+#include <linux/ratelimit.h>
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include <linux/diagchar.h>
@@ -439,7 +440,8 @@
diagmem_free(driver,
write_ptr_mdm,
POOL_TYPE_HSIC_WRITE);
- pr_err("diag: HSIC write failure\n");
+ pr_err_ratelimited("diag: HSIC write failure, err: %d\n",
+ err);
}
} else {
pr_err("diag: allocate write fail\n");
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 0b1f720..3878a82 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -71,6 +71,13 @@
write_ptrs_available--;
+ /*
+ * No sense queuing a read if the hsic bridge was
+ * closed in another thread
+ */
+ if (!driver->hsic_ch)
+ break;
+
buf_in_hsic = diagmem_alloc(driver, READ_HSIC_BUF_SIZE,
POOL_TYPE_HSIC);
if (buf_in_hsic) {
@@ -107,7 +114,8 @@
* (-ENODEV is an unrecoverable error), then set up the next read
*/
if ((driver->count_hsic_pool < driver->poolsize_hsic) &&
- (num_reads_submitted == 0) && (err != -ENODEV))
+ (num_reads_submitted == 0) && (err != -ENODEV) &&
+ (driver->hsic_ch != 0))
queue_work(driver->diag_bridge_wq,
&driver->diag_read_hsic_work);
}
@@ -146,7 +154,7 @@
/* If an error, return buffer to the pool */
if (err) {
diagmem_free(driver, buf, POOL_TYPE_HSIC);
- pr_err("diag: In %s, error calling diag_device_write, err: %d\n",
+ pr_err_ratelimited("diag: In %s, error calling diag_device_write, err: %d\n",
__func__, err);
}
}
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 182e50c..f4c4d08 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -31,6 +31,7 @@
#include <linux/coresight.h>
#include <asm/sections.h>
#include <mach/socinfo.h>
+#include <mach/msm_memory_dump.h>
#include "coresight-priv.h"
@@ -131,6 +132,9 @@
#define ETM_SEQ_STATE_MAX_VAL (0x2)
+#define ETM_REG_DUMP_VER_OFF (4)
+#define ETM_REG_DUMP_VER (1)
+
enum etm_addr_type {
ETM_ADDR_TYPE_NONE,
ETM_ADDR_TYPE_SINGLE,
@@ -1412,9 +1416,8 @@
return true;
}
-static int __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
+static void __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
{
- int ret;
uint32_t etmidr;
uint32_t etmccr;
@@ -1432,10 +1435,6 @@
/* find all capabilities */
etmidr = etm_readl(drvdata, ETMIDR);
drvdata->arch = BMVAL(etmidr, 4, 11);
- if (etm_arch_supported(drvdata->arch) == false) {
- ret = -EINVAL;
- goto err;
- }
etmccr = etm_readl(drvdata, ETMCCR);
drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
@@ -1447,10 +1446,6 @@
/* Vote for ETM power/clock disable */
etm_set_pwrdwn(drvdata);
ETM_LOCK(drvdata);
-
- return 0;
-err:
- return ret;
}
static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
@@ -1517,7 +1512,10 @@
struct coresight_platform_data *pdata;
struct etm_drvdata *drvdata;
struct resource *res;
- static int etm_count;
+ uint32_t reg_size;
+ static int count;
+ void *baddr;
+ struct msm_client_dump dump;
struct coresight_desc *desc;
/* Fail probe for Krait pass3 until supported */
@@ -1542,6 +1540,7 @@
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
+ reg_size = resource_size(res);
drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
if (!drvdata->base)
@@ -1560,7 +1559,7 @@
if (ret)
goto err0;
- drvdata->cpu = etm_count++;
+ drvdata->cpu = count++;
ret = clk_prepare_enable(drvdata->clk);
if (ret)
@@ -1570,20 +1569,34 @@
* ETMs copy it over from ETM0.
*/
if (drvdata->cpu == 0) {
- ret = etm_init_arch_data(drvdata);
- if (ret)
- goto err1;
+ etm_init_arch_data(drvdata);
etm0drvdata = drvdata;
} else {
- if (etm0drvdata)
- etm_copy_arch_data(drvdata);
- else
- goto err1;
+ etm_copy_arch_data(drvdata);
+ }
+ if (etm_arch_supported(drvdata->arch) == false) {
+ ret = -EINVAL;
+ goto err1;
}
etm_init_default_data(drvdata);
clk_disable_unprepare(drvdata->clk);
+ baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
+ if (baddr) {
+ *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
+ dump.id = MSM_ETM0_REG + drvdata->cpu;
+ dump.start_addr = virt_to_phys(baddr);
+ dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
+ ret = msm_dump_table_register(&dump);
+ if (ret) {
+ devm_kfree(dev, baddr);
+ dev_err(dev, "ETM REG dump setup failed\n");
+ }
+ } else {
+ dev_err(dev, "ETM REG dump space allocation failed\n");
+ }
+
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc) {
ret = -ENOMEM;
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 995ad86..0be5882 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -32,6 +32,7 @@
#include <mach/memory.h>
#include <mach/sps.h>
#include <mach/usb_bam.h>
+#include <mach/msm_memory_dump.h>
#include "coresight-priv.h"
@@ -80,6 +81,11 @@
#define TMC_ETR_BAM_PIPE_INDEX 0
#define TMC_ETR_BAM_NR_PIPES 2
+#define TMC_ETFETB_DUMP_VER_OFF (4)
+#define TMC_ETFETB_DUMP_VER (1)
+#define TMC_REG_DUMP_VER_OFF (4)
+#define TMC_REG_DUMP_VER (1)
+
enum tmc_config_type {
TMC_CONFIG_TYPE_ETB,
TMC_CONFIG_TYPE_ETR,
@@ -986,6 +992,11 @@
struct coresight_platform_data *pdata;
struct tmc_drvdata *drvdata;
struct resource *res;
+ uint32_t reg_size;
+ static int etfetb_count;
+ static int count;
+ void *baddr;
+ struct msm_client_dump dump;
struct coresight_desc *desc;
if (pdev->dev.of_node) {
@@ -1004,6 +1015,7 @@
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
+ reg_size = resource_size(res);
drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
if (!drvdata->base)
@@ -1031,7 +1043,8 @@
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
drvdata->size = SZ_1M;
else
- drvdata->size = tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD;
+ drvdata->size = (tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD)
+ + PAGE_SIZE;
clk_disable_unprepare(drvdata->clk);
@@ -1053,11 +1066,40 @@
if (ret)
goto err0;
} else {
- drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
- if (!drvdata->buf)
+ baddr = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
+ if (!baddr)
return -ENOMEM;
+ drvdata->buf = baddr + PAGE_SIZE;
+ *(uint32_t *)(baddr + TMC_ETFETB_DUMP_VER_OFF) =
+ TMC_ETFETB_DUMP_VER;
+ dump.id = MSM_TMC_ETFETB + etfetb_count;
+ dump.start_addr = virt_to_phys(baddr);
+ dump.end_addr = dump.start_addr + drvdata->size;
+ ret = msm_dump_table_register(&dump);
+ /* Don't free the buffer in case of error since it can still
+ * be used to provide dump collection via the device node
+ */
+ if (ret)
+ dev_info(dev, "TMC ETF-ETB dump setup failed\n");
+ etfetb_count++;
}
+ baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
+ if (baddr) {
+ *(uint32_t *)(baddr + TMC_REG_DUMP_VER_OFF) = TMC_REG_DUMP_VER;
+ dump.id = MSM_TMC0_REG + count;
+ dump.start_addr = virt_to_phys(baddr);
+ dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
+ ret = msm_dump_table_register(&dump);
+ if (ret) {
+ devm_kfree(dev, baddr);
+ dev_info(dev, "TMC REG dump setup failed\n");
+ }
+ } else {
+ dev_info(dev, "TMC REG dump space allocation failed\n");
+ }
+ count++;
+
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc) {
ret = -ENOMEM;
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 31bbb1f..eb9598a 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -701,6 +701,8 @@
if (iommu_map->flags & ION_IOMMU_UNMAP_DELAYED)
kref_get(&iommu_map->ref);
+ } else {
+ ret = PTR_ERR(iommu_map);
}
} else {
if (iommu_map->flags != iommu_flags) {
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 7317702..cf7f3ce 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -336,13 +336,6 @@
device->mmu.setstate_memory.gpuaddr +
KGSL_IOMMU_SETSTATE_NOP_OFFSET);
}
- /* invalidate all base pointers */
- *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
- *cmds++ = 0x7fff;
-
- cmds += __adreno_add_idle_indirect_cmds(cmds,
- device->mmu.setstate_memory.gpuaddr +
- KGSL_IOMMU_SETSTATE_NOP_OFFSET);
}
if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
/*
@@ -386,6 +379,10 @@
sizedwords += (cmds - &link[0]);
if (sizedwords) {
+ /* invalidate all base pointers */
+ *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
+ *cmds++ = 0x7fff;
+ sizedwords += 2;
/*
* add an interrupt at the end of commands so that the smmu
* disable clock off function will get called
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index ea2cdc4..1f32e54 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1507,7 +1507,7 @@
{
struct kgsl_device *device = &adreno_dev->dev;
- if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTOYED))
+ if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED))
return;
if (context->flags & CTXT_FLAGS_GPU_HANG)
@@ -1983,10 +1983,10 @@
0x18000000);
}
- if (adreno_is_a203(adreno_dev))
- /* For A203 increase number of clocks that RBBM
- * will wait before de-asserting Register Clock
- * Active signal */
+ if (adreno_is_a20x(adreno_dev))
+ /* For A20X based targets increase number of clocks
+ * that RBBM will wait before de-asserting Register
+ * Clock Active signal */
adreno_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF);
else
adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 8611b6b..d89e882 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2355,7 +2355,7 @@
{
struct kgsl_device *device = &adreno_dev->dev;
- if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTOYED))
+ if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED))
return;
if (context->flags & CTXT_FLAGS_GPU_HANG)
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index a50747d..e5cf660 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -221,7 +221,7 @@
CTXT_FLAGS_GMEM_SHADOW |
CTXT_FLAGS_STATE_SHADOW);
- drawctxt->flags |= CTXT_FLAGS_BEING_DESTOYED;
+ drawctxt->flags |= CTXT_FLAGS_BEING_DESTROYED;
adreno_drawctxt_switch(adreno_dev, NULL, 0);
}
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index d58f2da..034d6e9 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -19,35 +19,35 @@
/* Flags */
#define CTXT_FLAGS_NOT_IN_USE 0x00000000
-#define CTXT_FLAGS_IN_USE 0x00000001
+#define CTXT_FLAGS_IN_USE BIT(0)
/* state shadow memory allocated */
-#define CTXT_FLAGS_STATE_SHADOW 0x00000010
+#define CTXT_FLAGS_STATE_SHADOW BIT(1)
/* gmem shadow memory allocated */
-#define CTXT_FLAGS_GMEM_SHADOW 0x00000100
+#define CTXT_FLAGS_GMEM_SHADOW BIT(2)
/* gmem must be copied to shadow */
-#define CTXT_FLAGS_GMEM_SAVE 0x00000200
+#define CTXT_FLAGS_GMEM_SAVE BIT(3)
/* gmem can be restored from shadow */
-#define CTXT_FLAGS_GMEM_RESTORE 0x00000400
+#define CTXT_FLAGS_GMEM_RESTORE BIT(4)
/* preamble packed in cmdbuffer for context switching */
-#define CTXT_FLAGS_PREAMBLE 0x00000800
+#define CTXT_FLAGS_PREAMBLE BIT(5)
/* shader must be copied to shadow */
-#define CTXT_FLAGS_SHADER_SAVE 0x00002000
+#define CTXT_FLAGS_SHADER_SAVE BIT(6)
/* shader can be restored from shadow */
-#define CTXT_FLAGS_SHADER_RESTORE 0x00004000
+#define CTXT_FLAGS_SHADER_RESTORE BIT(7)
/* Context has caused a GPU hang */
-#define CTXT_FLAGS_GPU_HANG 0x00008000
+#define CTXT_FLAGS_GPU_HANG BIT(8)
/* Specifies there is no need to save GMEM */
-#define CTXT_FLAGS_NOGMEMALLOC 0x00010000
+#define CTXT_FLAGS_NOGMEMALLOC BIT(9)
/* Trash state for context */
-#define CTXT_FLAGS_TRASHSTATE 0x00020000
+#define CTXT_FLAGS_TRASHSTATE BIT(10)
/* per context timestamps enabled */
-#define CTXT_FLAGS_PER_CONTEXT_TS 0x00040000
+#define CTXT_FLAGS_PER_CONTEXT_TS BIT(11)
/* Context has caused a GPU hang and recovered properly */
-#define CTXT_FLAGS_GPU_HANG_RECOVERED 0x00008000
+#define CTXT_FLAGS_GPU_HANG_RECOVERED BIT(12)
/* Context is being destroyed so dont save it */
-#define CTXT_FLAGS_BEING_DESTOYED 0x00010000
+#define CTXT_FLAGS_BEING_DESTROYED BIT(13)
struct kgsl_device;
struct adreno_device;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 7241201..f630f2a 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1380,104 +1380,6 @@
return vma;
}
-static long
-kgsl_ioctl_sharedmem_from_vmalloc(struct kgsl_device_private *dev_priv,
- unsigned int cmd, void *data)
-{
- int result = 0, len = 0;
- struct kgsl_process_private *private = dev_priv->process_priv;
- struct kgsl_sharedmem_from_vmalloc *param = data;
- struct kgsl_mem_entry *entry = NULL;
- struct vm_area_struct *vma;
-
- KGSL_DEV_ERR_ONCE(dev_priv->device, "IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC"
- " is deprecated\n");
- if (!kgsl_mmu_enabled())
- return -ENODEV;
-
- if (!param->hostptr) {
- KGSL_CORE_ERR("invalid hostptr %x\n", param->hostptr);
- result = -EINVAL;
- goto error;
- }
-
- vma = kgsl_get_vma_from_start_addr(param->hostptr);
- if (!vma) {
- result = -EINVAL;
- goto error;
- }
-
- /*
- * If the user specified a length, use it, otherwise try to
- * infer the length if the vma region
- */
- if (param->gpuaddr != 0) {
- len = param->gpuaddr;
- } else {
- /*
- * For this to work, we have to assume the VMA region is only
- * for this single allocation. If it isn't, then bail out
- */
- if (vma->vm_pgoff || (param->hostptr != vma->vm_start)) {
- KGSL_CORE_ERR("VMA region does not match hostaddr\n");
- result = -EINVAL;
- goto error;
- }
-
- len = vma->vm_end - vma->vm_start;
- }
-
- /* Make sure it fits */
- if (len == 0 || param->hostptr + len > vma->vm_end) {
- KGSL_CORE_ERR("Invalid memory allocation length %d\n", len);
- result = -EINVAL;
- goto error;
- }
-
- entry = kgsl_mem_entry_create();
- if (entry == NULL) {
- result = -ENOMEM;
- goto error;
- }
-
- result = kgsl_sharedmem_page_alloc_user(&entry->memdesc,
- private->pagetable, len,
- param->flags);
- if (result != 0)
- goto error_free_entry;
-
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-
- result = kgsl_sharedmem_map_vma(vma, &entry->memdesc);
- if (result) {
- KGSL_CORE_ERR("kgsl_sharedmem_map_vma failed: %d\n", result);
- goto error_free_alloc;
- }
-
- param->gpuaddr = entry->memdesc.gpuaddr;
-
- entry->memtype = KGSL_MEM_ENTRY_KERNEL;
-
- kgsl_mem_entry_attach_process(entry, private);
-
- trace_kgsl_mem_alloc(entry);
- /* Process specific statistics */
- kgsl_process_add_stats(private, entry->memtype, len);
-
- kgsl_check_idle(dev_priv->device);
- return 0;
-
-error_free_alloc:
- kgsl_sharedmem_free(&entry->memdesc);
-
-error_free_entry:
- kfree(entry);
-
-error:
- kgsl_check_idle(dev_priv->device);
- return result;
-}
-
static inline int _check_region(unsigned long start, unsigned long size,
uint64_t len)
{
@@ -2161,8 +2063,6 @@
kgsl_ioctl_map_user_mem, 0),
KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FREE,
kgsl_ioctl_sharedmem_free, 0),
- KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC,
- kgsl_ioctl_sharedmem_from_vmalloc, 0),
KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE,
kgsl_ioctl_sharedmem_flush_cache, 0),
KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 7618e68..739dcb5 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -459,6 +459,15 @@
clk_unprepare(pwr->grp_clks[i]);
}
kgsl_pwrctrl_busy_time(device, true);
+ } else if (requested_state == KGSL_STATE_SLEEP) {
+ /* High latency clock maintenance. */
+ if ((pwr->pwrlevels[0].gpu_freq > 0))
+ clk_set_rate(pwr->grp_clks[0],
+ pwr->pwrlevels[pwr->num_pwrlevels - 1].
+ gpu_freq);
+ for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
+ if (pwr->grp_clks[i])
+ clk_unprepare(pwr->grp_clks[i]);
}
} else if (state == KGSL_PWRFLAGS_ON) {
if (!test_and_set_bit(KGSL_PWRFLAGS_CLK_ON,
@@ -851,7 +860,6 @@
static int
_sleep(struct kgsl_device *device)
{
- struct kgsl_pwrctrl *pwr = &device->pwrctrl;
switch (device->state) {
case KGSL_STATE_ACTIVE:
if (!device->ftbl->isidle(device)) {
@@ -862,10 +870,6 @@
case KGSL_STATE_NAP:
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_OFF);
- if (pwr->pwrlevels[0].gpu_freq > 0)
- clk_set_rate(pwr->grp_clks[0],
- pwr->pwrlevels[pwr->num_pwrlevels - 1].
- gpu_freq);
_sleep_accounting(device);
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP);
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index f908181..a384103 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -299,6 +299,80 @@
{419, 128000}
};
+static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
+ {-40, 1758},
+ {-35, 1742},
+ {-30, 1719},
+ {-25, 1691},
+ {-20, 1654},
+ {-15, 1608},
+ {-10, 1551},
+ {-5, 1483},
+ {0, 1404},
+ {5, 1315},
+ {10, 1218},
+ {15, 1114},
+ {20, 1007},
+ {25, 900},
+ {30, 795},
+ {35, 696},
+ {40, 605},
+ {45, 522},
+ {50, 448},
+ {55, 383},
+ {60, 327},
+ {65, 278},
+ {70, 237},
+ {75, 202},
+ {80, 172},
+ {85, 146},
+ {90, 125},
+ {95, 107},
+ {100, 92},
+ {105, 79},
+ {110, 68},
+ {115, 59},
+ {120, 51},
+ {125, 44}
+};
+
+static const struct qpnp_vadc_map_pt adcmap_150k_104ef_104fb[] = {
+ {-40, 1738},
+ {-35, 1714},
+ {-30, 1682},
+ {-25, 1641},
+ {-20, 1589},
+ {-15, 1526},
+ {-10, 1451},
+ {-5, 1363},
+ {0, 1266},
+ {5, 1159},
+ {10, 1048},
+ {15, 936},
+ {20, 825},
+ {25, 720},
+ {30, 622},
+ {35, 533},
+ {40, 454},
+ {45, 385},
+ {50, 326},
+ {55, 275},
+ {60, 232},
+ {65, 195},
+ {70, 165},
+ {75, 139},
+ {80, 118},
+ {85, 100},
+ {90, 85},
+ {95, 73},
+ {100, 62},
+ {105, 53},
+ {110, 46},
+ {115, 40},
+ {120, 34},
+ {125, 30}
+};
+
static int32_t qpnp_adc_map_linear(const struct qpnp_vadc_map_pt *pts,
uint32_t tablesize, int32_t input, int64_t *output)
{
@@ -504,6 +578,42 @@
}
EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_therm);
+int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+ const struct qpnp_adc_properties *adc_properties,
+ const struct qpnp_vadc_chan_properties *chan_properties,
+ struct qpnp_vadc_result *adc_chan_result)
+{
+ int64_t therm_voltage = 0;
+
+ therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+ adc_properties, chan_properties);
+
+ qpnp_adc_map_linear(adcmap_150k_104ef_104fb,
+ ARRAY_SIZE(adcmap_150k_104ef_104fb),
+ therm_voltage, &adc_chan_result->physical);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu1);
+
+int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+ const struct qpnp_adc_properties *adc_properties,
+ const struct qpnp_vadc_chan_properties *chan_properties,
+ struct qpnp_vadc_result *adc_chan_result)
+{
+ int64_t therm_voltage = 0;
+
+ therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+ adc_properties, chan_properties);
+
+ qpnp_adc_map_linear(adcmap_100k_104ef_104fb,
+ ARRAY_SIZE(adcmap_100k_104ef_104fb),
+ therm_voltage, &adc_chan_result->physical);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu2);
+
int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
const struct qpnp_adc_properties *adc_properties,
const struct qpnp_vadc_chan_properties *chan_properties,
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index a0e7ab9..5690c88 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -119,6 +119,8 @@
[SCALE_BATT_THERM] = {qpnp_adc_scale_batt_therm},
[SCALE_PMIC_THERM] = {qpnp_adc_scale_pmic_therm},
[SCALE_XOTHERM] = {qpnp_adc_tdkntcg_therm},
+ [SCALE_THERM_100K_PULLUP] = {qpnp_adc_scale_therm_pu2},
+ [SCALE_THERM_150K_PULLUP] = {qpnp_adc_scale_therm_pu1},
};
static int32_t qpnp_vadc_read_reg(int16_t reg, u8 *data)
diff --git a/drivers/input/touchscreen/cyttsp-i2c-qc.c b/drivers/input/touchscreen/cyttsp-i2c-qc.c
index a3a12c6..e54a24a 100644
--- a/drivers/input/touchscreen/cyttsp-i2c-qc.c
+++ b/drivers/input/touchscreen/cyttsp-i2c-qc.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/irq.h>
@@ -1698,22 +1699,9 @@
cyttsp_debug("ST->F1:%3d X:%3d Y:%3d Z:%3d\n", \
cur_st_tch[CY_ST_FNGR1_IDX], \
st_x1, st_y1, st_z1);
- if (cur_st_tch[CY_ST_FNGR2_IDX] < CY_NUM_TRK_ID) {
- input_report_key(ts->input, BTN_2, CY_TCH);
- input_report_abs(ts->input, ABS_HAT0X, st_x2);
- input_report_abs(ts->input, ABS_HAT0Y, st_y2);
- cyttsp_debug("ST->F2:%3d X:%3d Y:%3d Z:%3d\n", \
- cur_st_tch[CY_ST_FNGR2_IDX],
- st_x2, st_y2, st_z2);
- } else {
- input_report_key(ts->input,
- BTN_2,
- CY_NTCH);
- }
} else {
input_report_abs(ts->input, ABS_PRESSURE, CY_NTCH);
input_report_key(ts->input, BTN_TOUCH, CY_NTCH);
- input_report_key(ts->input, BTN_2, CY_NTCH);
}
/* update platform data for the current single touch info */
ts->prv_st_tch[CY_ST_FNGR1_IDX] = cur_st_tch[CY_ST_FNGR1_IDX];
@@ -1857,6 +1845,9 @@
id, tmp_trk[id], \
id, snd_trk[id]);
if (snd_trk[id] < CY_NUM_TRK_ID) {
+ input_mt_slot(ts->input, snd_trk[id]);
+ input_mt_report_slot_state(ts->input,
+ MT_TOOL_FINGER, true);
input_report_abs(ts->input,
ABS_MT_TOUCH_MAJOR,
cur_mt_z[snd_trk[id]]);
@@ -1869,7 +1860,6 @@
input_report_abs(ts->input,
ABS_MT_POSITION_Y,
cur_mt_pos[snd_trk[id]][CY_YPOS]);
- CY_MT_SYNC(ts->input);
cyttsp_debug("MT1->TID:%2d X:%3d Y:%3d Z:%3d touch-sent\n", \
snd_trk[id], \
cur_mt_pos[snd_trk[id]][CY_XPOS], \
@@ -1877,19 +1867,10 @@
cur_mt_z[snd_trk[id]]);
} else if (ts->prv_mt_tch[id] < CY_NUM_TRK_ID) {
/* void out this touch */
- input_report_abs(ts->input,
- ABS_MT_TOUCH_MAJOR,
- CY_NTCH);
- input_report_abs(ts->input,
- ABS_MT_WIDTH_MAJOR,
- curr_tool_width);
- input_report_abs(ts->input,
- ABS_MT_POSITION_X,
- ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_XPOS]);
- input_report_abs(ts->input,
- ABS_MT_POSITION_Y,
- ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_YPOS]);
- CY_MT_SYNC(ts->input);
+ input_mt_slot(ts->input,
+ ts->prv_mt_tch[id]);
+ input_mt_report_slot_state(ts->input,
+ MT_TOOL_FINGER, false);
cyttsp_debug("MT2->TID:%2d X:%3d Y:%3d Z:%3d lift off-sent\n", \
ts->prv_mt_tch[id], \
ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_XPOS], \
@@ -2679,7 +2660,6 @@
set_bit(EV_KEY, input_device->evbit);
set_bit(EV_ABS, input_device->evbit);
set_bit(BTN_TOUCH, input_device->keybit);
- set_bit(BTN_2, input_device->keybit);
set_bit(INPUT_PROP_DIRECT, input_device->propbit);
if (ts->platform_data->use_gestures)
@@ -2693,10 +2673,6 @@
ABS_TOOL_WIDTH, 0, CY_LARGE_TOOL_WIDTH, 0 , 0);
input_set_abs_params(input_device,
ABS_PRESSURE, 0, CY_MAXZ, 0, 0);
- input_set_abs_params(input_device,
- ABS_HAT0X, 0, ts->platform_data->panel_maxx, 0, 0);
- input_set_abs_params(input_device,
- ABS_HAT0Y, 0, ts->platform_data->panel_maxy, 0, 0);
if (ts->platform_data->use_gestures) {
input_set_abs_params(input_device,
ABS_HAT1X, 0, CY_MAXZ, 0, 0);
@@ -2714,6 +2690,7 @@
ABS_MT_TOUCH_MAJOR, 0, CY_MAXZ, 0, 0);
input_set_abs_params(input_device,
ABS_MT_WIDTH_MAJOR, 0, CY_LARGE_TOOL_WIDTH, 0, 0);
+ input_mt_init_slots(input_device, CY_NUM_TRK_ID);
if (ts->platform_data->use_trk_id) {
input_set_abs_params(input_device,
ABS_MT_TRACKING_ID, 0, CY_NUM_TRK_ID, 0, 0);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index d596782..ac143b1 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -3479,12 +3479,20 @@
struct v4l2_buffer *buffer)
{
struct iris_device *radio = video_get_drvdata(video_devdata(file));
- enum iris_buf_t buf_type = buffer->index;
- struct kfifo *data_fifo;
- unsigned char *buf = (unsigned char *)buffer->m.userptr;
- unsigned int len = buffer->length;
- if (!access_ok(VERIFY_WRITE, buf, len))
- return -EFAULT;
+ enum iris_buf_t buf_type = -1;
+ unsigned char buf_fifo[STD_BUF_SIZE] = {0};
+ struct kfifo *data_fifo = NULL;
+ unsigned char *buf = NULL;
+ unsigned int len = 0, retval = -1;
+
+ if ((radio == NULL) || (buffer == NULL)) {
+ FMDERR("radio/buffer is NULL\n");
+ return -ENXIO;
+ }
+ buf_type = buffer->index;
+ buf = (unsigned char *)buffer->m.userptr;
+ len = buffer->length;
+
if ((buf_type < IRIS_BUF_MAX) && (buf_type >= 0)) {
data_fifo = &radio->data_buf[buf_type];
if (buf_type == IRIS_BUF_EVENTS)
@@ -3495,10 +3503,20 @@
FMDERR("invalid buffer type\n");
return -EINVAL;
}
- buffer->bytesused = kfifo_out_locked(data_fifo, buf, len,
- &radio->buf_lock[buf_type]);
+ if (len <= STD_BUF_SIZE) {
+ buffer->bytesused = kfifo_out_locked(data_fifo, &buf_fifo[0],
+ len, &radio->buf_lock[buf_type]);
+ } else {
+ FMDERR("kfifo_out_locked can not use len more than 128\n");
+ return -EINVAL;
+ }
+ retval = copy_to_user(buf, &buf_fifo[0], buffer->bytesused);
+ if (retval > 0) {
+ FMDERR("Failed to copy %d bytes of data\n", retval);
+ return -EAGAIN;
+ }
- return 0;
+ return retval;
}
static int iris_vidioc_g_fmt_type_private(struct file *file, void *priv,
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 6274a20..535ea0a 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -61,6 +61,7 @@
((csid_lut_params->vc_cfg[i].cid % 4) * 8));
msm_camera_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
(csid_lut_params->vc_cfg[i].cid >> 2) * 4);
+
val = (csid_lut_params->vc_cfg[i].decode_format << 4) | 0x3;
msm_camera_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
(csid_lut_params->vc_cfg[i].cid * 4));
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index e3f1ebe..62858a8 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -29,7 +29,6 @@
static atomic_t ispif_irq_cnt;
static spinlock_t ispif_tasklet_lock;
-static spinlock_t ispif_sof_lock;
static struct list_head ispif_tasklet_q;
static int msm_ispif_intf_reset(struct ispif_device *ispif,
@@ -343,10 +342,9 @@
static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint16_t intfmask,
uint8_t intf_cmd_mask, uint8_t vfe_intf)
{
- uint8_t vc = 0;
+ uint8_t vc = 0, val = 0;
uint16_t mask = intfmask, intfnum = 0;
uint32_t cid_mask = 0;
- uint32_t global_intf_cmd_mask = 0xFFFFFFFF;
uint32_t global_intf_cmd_mask1 = 0xFFFFFFFF;
while (mask != 0) {
if (!(intfmask & (0x1 << intfnum))) {
@@ -360,12 +358,15 @@
while (cid_mask != 0) {
if ((cid_mask & 0xf) != 0x0) {
- if (intfnum != RDI2)
- global_intf_cmd_mask &=
- ~((0x3 & ~intf_cmd_mask)
- << ((vc * 2) +
+ if (intfnum != RDI2) {
+ val = (intf_cmd_mask>>(vc*2)) & 0x3;
+ ispif->global_intf_cmd_mask |=
+ (0x3 << ((vc * 2) +
(intfnum * 8)));
- else
+ ispif->global_intf_cmd_mask &=
+ ~((0x3 & ~val) << ((vc * 2) +
+ (intfnum * 8)));
+ } else
global_intf_cmd_mask1 &=
~((0x3 & ~intf_cmd_mask)
<< ((vc * 2) + 8));
@@ -376,7 +377,7 @@
mask >>= 1;
intfnum++;
}
- msm_camera_io_w(global_intf_cmd_mask,
+ msm_camera_io_w(ispif->global_intf_cmd_mask,
ispif->base + ISPIF_INTF_CMD_ADDR + (0x200 * vfe_intf));
if (global_intf_cmd_mask1 != 0xFFFFFFFF)
msm_camera_io_w(global_intf_cmd_mask1,
@@ -388,11 +389,20 @@
uint16_t intfmask, uint8_t vfe_intf)
{
int rc = 0;
- uint8_t intf_cmd_mask = 0x02;
+ uint8_t intf_cmd_mask = 0xAA;
+ uint16_t intfnum = 0, mask = intfmask;
mutex_lock(&ispif->mutex);
CDBG("%s intfmask %x intf_cmd_mask %x\n", __func__, intfmask,
intf_cmd_mask);
msm_ispif_intf_cmd(ispif, intfmask, intf_cmd_mask, vfe_intf);
+ while (mask != 0) {
+ if (intfmask & (0x1 << intfnum))
+ ispif->global_intf_cmd_mask |= (0xFF << (intfnum * 8));
+ mask >>= 1;
+ intfnum++;
+ if (intfnum == RDI2)
+ break;
+ }
mutex_unlock(&ispif->mutex);
return rc;
}
@@ -400,11 +410,11 @@
static int msm_ispif_start_intf_transfer(struct ispif_device *ispif,
uint16_t intfmask, uint8_t vfe_intf)
{
- uint8_t intf_cmd_mask = 0x01;
+ uint8_t intf_cmd_mask = 0x55;
int rc = 0;
mutex_lock(&ispif->mutex);
rc = msm_ispif_intf_reset(ispif, intfmask, vfe_intf);
- CDBG("%s intfmask %x intf_cmd_mask %x\n", __func__, intfmask,
+ CDBG("%s intfmask start after%x intf_cmd_mask %x\n", __func__, intfmask,
intf_cmd_mask);
msm_ispif_intf_cmd(ispif, intfmask, intf_cmd_mask, vfe_intf);
mutex_unlock(&ispif->mutex);
@@ -472,6 +482,9 @@
default:
break;
}
+ if (intfnum != RDI2)
+ ispif->global_intf_cmd_mask |= (0xFF <<
+ (intfnum * 8));
}
mask >>= 1;
intfnum++;
@@ -547,26 +560,6 @@
spin_unlock_irqrestore(&ispif_tasklet_lock,
flags);
- spin_lock_irqsave(&ispif_sof_lock, flags);
- if (qcmd->ispifInterruptStatus0 &
- ISPIF_IRQ_STATUS_RDI0_SOF_MASK) {
- CDBG("%s: ispif RDI0 irq status", __func__);
- ispif->rdi0_sof_count++;
- send_rdi_sof(ispif, RDI_0, ispif->rdi0_sof_count);
- }
- if (qcmd->ispifInterruptStatus1 &
- ISPIF_IRQ_STATUS_RDI1_SOF_MASK) {
- CDBG("%s: ispif RDI1 irq status", __func__);
- ispif->rdi1_sof_count++;
- send_rdi_sof(ispif, RDI_1, ispif->rdi1_sof_count);
- }
- if (qcmd->ispifInterruptStatus2 &
- ISPIF_IRQ_STATUS_RDI2_SOF_MASK) {
- CDBG("%s: ispif RDI2 irq status", __func__);
- ispif->rdi2_sof_count++;
- send_rdi_sof(ispif, RDI_2, ispif->rdi2_sof_count);
- }
- spin_unlock_irqrestore(&ispif_sof_lock, flags);
kfree(qcmd);
}
}
@@ -586,6 +579,7 @@
qcmd->ispifInterruptStatus0 = out->ispifIrqStatus0;
qcmd->ispifInterruptStatus1 = out->ispifIrqStatus1;
qcmd->ispifInterruptStatus2 = out->ispifIrqStatus2;
+
if (qcmd->ispifInterruptStatus0 &
ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
CDBG("%s: ispif PIX irq status", __func__);
@@ -595,6 +589,25 @@
(void *)&ispif->pix_sof_count);
}
+ if (qcmd->ispifInterruptStatus0 &
+ ISPIF_IRQ_STATUS_RDI0_SOF_MASK) {
+ CDBG("%s: ispif RDI0 irq status", __func__);
+ ispif->rdi0_sof_count++;
+ send_rdi_sof(ispif, RDI_0, ispif->rdi0_sof_count);
+ }
+ if (qcmd->ispifInterruptStatus1 &
+ ISPIF_IRQ_STATUS_RDI1_SOF_MASK) {
+ CDBG("%s: ispif RDI1 irq status", __func__);
+ ispif->rdi1_sof_count++;
+ send_rdi_sof(ispif, RDI_1, ispif->rdi1_sof_count);
+ }
+ if (qcmd->ispifInterruptStatus2 &
+ ISPIF_IRQ_STATUS_RDI2_SOF_MASK) {
+ CDBG("%s: ispif RDI2 irq status", __func__);
+ ispif->rdi2_sof_count++;
+ send_rdi_sof(ispif, RDI_2, ispif->rdi2_sof_count);
+ }
+
spin_lock_irqsave(&ispif_tasklet_lock, flags);
list_add_tail(&qcmd->list, &ispif_tasklet_q);
@@ -693,6 +706,7 @@
INIT_LIST_HEAD(&ispif_tasklet_q);
rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
IRQF_TRIGGER_RISING, "ispif", ispif);
+ ispif->global_intf_cmd_mask = 0xFFFFFFFF;
init_completion(&ispif->reset_complete);
tasklet_init(&ispif->ispif_tasklet,
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
index ea69959..d4ca864 100644
--- a/drivers/media/video/msm/csi/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -44,6 +44,7 @@
uint32_t rdi0_sof_count;
uint32_t rdi1_sof_count;
uint32_t rdi2_sof_count;
+ uint32_t global_intf_cmd_mask;
struct tasklet_struct ispif_tasklet;
enum msm_ispif_state_t ispif_state;
};
diff --git a/drivers/media/video/msm/io/msm_io_8960.c b/drivers/media/video/msm/io/msm_io_8960.c
index 699425a..808cc32 100644
--- a/drivers/media/video/msm/io/msm_io_8960.c
+++ b/drivers/media/video/msm/io/msm_io_8960.c
@@ -95,6 +95,14 @@
} else
CDBG("%s: Bus Client NOT Registered!!!\n", __func__);
break;
+ case S_DUAL:
+ if (bus_perf_client) {
+ rc = msm_bus_scale_client_update_request(
+ bus_perf_client, 6);
+ CDBG("%s: S_DUAL rc = %d\n", __func__, rc);
+ } else
+ CDBG("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
case S_DEFAULT:
break;
default:
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 83f762c..2613986 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -640,6 +640,7 @@
{
struct msm_vfe_cfg_cmd cfgcmd;
int rc = 0;
+ v4l2_set_subdev_hostdata(sd, mctl);
switch (cmd) {
case MSM_CAM_IOCTL_STATS_REQBUF: {
struct msm_stats_reqbuf reqbuf;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 1897ee4..c94da2a 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -449,10 +449,11 @@
break;
/* ISFIF config*/
case MSM_CAM_IOCTL_AXI_CONFIG:
- if (p_mctl->axi_sdev)
+ if (p_mctl->axi_sdev) {
+ v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
VIDIOC_MSM_AXI_CFG, (void __user *)arg);
- else
+ } else
rc = p_mctl->isp_config(p_mctl, cmd, arg);
break;
case MSM_CAM_IOCTL_ISPIF_IO_CFG:
@@ -478,6 +479,22 @@
core, ioctl, VIDIOC_MSM_CSID_CFG, argp);
break;
+ case MSM_CAM_IOCTL_AXI_INIT:
+ if (p_mctl->axi_sdev) {
+ v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
+ rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+ VIDIOC_MSM_AXI_INIT, (void __user *)arg);
+ }
+ break;
+
+ case MSM_CAM_IOCTL_AXI_RELEASE:
+ if (p_mctl->axi_sdev) {
+ v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
+ rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+ VIDIOC_MSM_AXI_RELEASE, NULL);
+ }
+ break;
+
default:
/* ISP config*/
D("%s:%d: go to default. Calling msm_isp_config\n",
@@ -575,7 +592,6 @@
struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
struct msm_camera_sensor_info *sinfo =
(struct msm_camera_sensor_info *) s_ctrl->sensordata;
-
v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
VIDIOC_MSM_SENSOR_RELEASE, NULL);
@@ -590,6 +606,7 @@
}
if (p_mctl->axi_sdev) {
+ v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
VIDIOC_MSM_AXI_RELEASE, NULL);
}
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 03d666f..999783e 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -86,7 +86,10 @@
output_settings[s_ctrl->curr_res].vt_pixel_clk /
s_ctrl->curr_frame_length_lines /
s_ctrl->curr_line_length_pclk;
- delay = (1000 * s_ctrl->wait_num_frames) / fps / Q10;
+ if (fps == 0)
+ delay = s_ctrl->min_delay;
+ else
+ delay = (1000 * s_ctrl->wait_num_frames) / fps / Q10;
}
CDBG("%s fps = %ld, delay = %d, min_delay %d\n", __func__, fps,
delay, s_ctrl->min_delay);
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 8c9b602..bb9a9b7 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -342,6 +342,7 @@
uint32_t id, struct msm_ctrl_cmd *out)
{
int rc = 0;
+ uint8_t wait_count;
void *value;
struct msm_queue_cmd *rcmd;
struct msm_queue_cmd *event_qcmd;
@@ -409,9 +410,20 @@
/* wait for config return status */
D("Waiting for config status\n");
- rc = wait_event_interruptible_timeout(queue->wait,
- !list_empty_careful(&queue->list),
- msecs_to_jiffies(out->timeout_ms));
+ /* wait event may be interrupted by sugnal,
+ * in this case -ERESTARTSYS is returned and retry is needed.
+ * Now we only retry once. */
+ wait_count = 2;
+ do {
+ rc = wait_event_interruptible_timeout(queue->wait,
+ !list_empty_careful(&queue->list),
+ msecs_to_jiffies(out->timeout_ms));
+ wait_count--;
+ if (rc != -ERESTARTSYS)
+ break;
+ D("%s: wait_event interrupted by signal, remain_count = %d",
+ __func__, wait_count);
+ } while (wait_count > 0);
D("Waiting is over for config status\n");
if (list_empty_careful(&queue->list)) {
if (!rc)
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index 2a9c186..6e22388 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -412,28 +412,166 @@
}
}
+static void axi_enable_wm_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t irq_mask, irq_comp_mask = 0;
+ uint16_t vfe_output_mode =
+ share_ctrl->outpath.output_mode &
+ ~(VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
+
+ if (vfe_output_mode)
+ irq_comp_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_COMP_MASK);
+ irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ if (share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ if (share_ctrl->current_mode == VFE_OUTPUTS_RAW)
+ irq_comp_mask |= (
+ 0x1 << share_ctrl->outpath.out0.ch0);
+ else
+ irq_comp_mask |= (
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1);
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ } else if (share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ irq_comp_mask |= (
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1 |
+ 0x1 << share_ctrl->outpath.out0.ch2);
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ }
+ if (share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask |= (
+ 0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (share_ctrl->outpath.out1.ch1 + 8));
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ } else if (share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ irq_comp_mask |= (
+ 0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (share_ctrl->outpath.out1.ch1 + 8) |
+ 0x1 << (share_ctrl->outpath.out1.ch2 + 8));
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ }
+
+ if (share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_TERTIARY1) {
+ irq_mask |= (0x1 << (share_ctrl->outpath.out2.ch0 +
+ VFE_WM_OFFSET));
+ }
+
+ if (share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_TERTIARY2) {
+ irq_mask |= (0x1 << (share_ctrl->outpath.out3.ch0 +
+ VFE_WM_OFFSET));
+ }
+
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ if (vfe_output_mode)
+ msm_camera_io_w(irq_comp_mask,
+ share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+}
+
+static void axi_disable_wm_irq(struct vfe_share_ctrl_t *share_ctrl,
+ uint16_t output_mode)
+{
+ uint32_t irq_mask, irq_comp_mask = 0;
+ uint16_t vfe_output_mode =
+ output_mode &
+ ~(VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
+ if (vfe_output_mode)
+ irq_comp_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_COMP_MASK);
+ irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ if (output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ } else if (output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1 |
+ 0x1 << share_ctrl->outpath.out0.ch2);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ }
+ if (output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask &= ~(
+ 0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (share_ctrl->outpath.out1.ch1 + 8));
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ } else if (output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ irq_comp_mask &= ~(
+ 0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (share_ctrl->outpath.out1.ch1 + 8) |
+ 0x1 << (share_ctrl->outpath.out1.ch2 + 8));
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ }
+ if (output_mode &
+ VFE32_OUTPUT_MODE_TERTIARY1) {
+ irq_mask &= ~(0x1 << (share_ctrl->outpath.out2.ch0 +
+ VFE_WM_OFFSET));
+ }
+ if (output_mode &
+ VFE32_OUTPUT_MODE_TERTIARY2) {
+ irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
+ VFE_WM_OFFSET));
+ }
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ if (vfe_output_mode)
+ msm_camera_io_w(irq_comp_mask,
+ share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+}
+
static void axi_enable_irq(struct vfe_share_ctrl_t *share_ctrl)
{
uint32_t irq_mask, irq_mask1;
- uint16_t vfe_operation_mode =
+ uint32_t vfe_mode =
share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
VFE_OUTPUTS_RDI1);
- irq_mask1 =
- msm_camera_io_r(share_ctrl->vfebase +
+
+ if (share_ctrl->axi_ref_cnt == 1) {
+ irq_mask1 =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+
+ irq_mask1 |= VFE_IMASK_WHILE_STOPPING_1;
+ msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+ }
+
+ if (share_ctrl->current_mode & (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1)) {
+ irq_mask1 =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+ irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+ irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+
+ msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
VFE_IRQ_MASK_1);
+ }
- irq_mask1 |= VFE_IMASK_WHILE_STOPPING_1;
-
- if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
- irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
-
- if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
- irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
-
- msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
-
- if (vfe_operation_mode) {
+ if (vfe_mode) {
irq_mask =
msm_camera_io_r(share_ctrl->vfebase +
VFE_IRQ_MASK_0);
@@ -449,37 +587,39 @@
atomic_set(&share_ctrl->handle_common_irq, 1);
}
-static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl)
+static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl,
+ uint32_t mode)
{
/* disable all interrupts. */
- uint32_t irq_mask, irq_mask1;
- uint16_t vfe_operation_mode =
- share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
- VFE_OUTPUTS_RDI1);
+ uint32_t irq_mask = 0, irq_mask1 = 0, clear_mask1 = 0;
+ uint32_t vfe_mode =
+ (mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1));
- if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ if (mode & (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1)) {
irq_mask1 =
- msm_camera_io_r(share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
- irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK);
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+
+ if (mode & VFE_OUTPUTS_RDI0) {
+ irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK);
+ clear_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
+ }
+
+ if (mode & VFE_OUTPUTS_RDI1) {
+ irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK);
+ clear_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+ }
+
msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
VFE_IRQ_MASK_1);
- msm_camera_io_w(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK,
+ msm_camera_io_w(clear_mask1,
share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
}
- if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
- irq_mask1 =
- msm_camera_io_r(share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
- irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK);
- msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
- msm_camera_io_w(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK,
- share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
- }
- if (vfe_operation_mode) {
+
+ if (vfe_mode) {
atomic_set(&share_ctrl->vstate, 0);
irq_mask =
msm_camera_io_r(share_ctrl->vfebase +
@@ -492,7 +632,7 @@
msm_camera_io_w(irq_mask, share_ctrl->vfebase +
VFE_IRQ_MASK_0);
}
-
+ /*Dont Disable for concurrent*/
if (share_ctrl->axi_ref_cnt == 1) {
atomic_set(&share_ctrl->handle_common_irq, 0);
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
@@ -517,11 +657,14 @@
/* in either continuous or snapshot mode, stop command can be issued
* at any time. stop camif immediately. */
- msm_camera_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
- vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ if (!vfe32_ctrl->share_ctrl->dual_enabled)
+ msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ else
+ msm_camera_io_w(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
vfe32_ctrl->share_ctrl->operation_mode &=
- ~(vfe32_ctrl->share_ctrl->current_mode);
- vfe32_ctrl->share_ctrl->current_mode = 0;
+ (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
}
static void vfe32_subdev_notify(int id, int path, uint32_t inst_handle,
@@ -630,8 +773,6 @@
V32_AXI_BUS_CFG_LEN);
axi_cfg += V32_AXI_BUS_CFG_LEN/4;
for (i = 0; i < ARRAY_SIZE(vfe32_AXI_WM_CFG); i++) {
- msm_camera_io_w(*axi_cfg,
- axi_ctrl->share_ctrl->vfebase+vfe32_AXI_WM_CFG[i]);
axi_cfg += 3;
msm_camera_io_memcpy(
axi_ctrl->share_ctrl->vfebase+vfe32_AXI_WM_CFG[i]+12,
@@ -654,6 +795,33 @@
}
static void axi_reset_internal_variables(
+ struct axi_ctrl_t *axi_ctrl,
+ struct msm_camera_vfe_params_t vfe_params)
+{
+ if (vfe_params.operation_mode & VFE_OUTPUTS_RDI0) {
+ atomic_set(&axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+ axi_ctrl->share_ctrl->rdi0_capture_count = -1;
+ axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+ axi_ctrl->share_ctrl->rdi0FrameId = 0;
+ axi_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE32_OUTPUT_MODE_TERTIARY1;
+ axi_ctrl->share_ctrl->operation_mode &=
+ ~(VFE_OUTPUTS_RDI0);
+ }
+
+ if (vfe_params.operation_mode & VFE_OUTPUTS_RDI1) {
+ atomic_set(&axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+ axi_ctrl->share_ctrl->rdi1_capture_count = -1;
+ axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+ axi_ctrl->share_ctrl->rdi1FrameId = 0;
+ axi_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE32_OUTPUT_MODE_TERTIARY2;
+ axi_ctrl->share_ctrl->operation_mode &=
+ ~(VFE_OUTPUTS_RDI1);
+ }
+}
+
+static void axi_global_reset_internal_variables(
struct axi_ctrl_t *axi_ctrl)
{
unsigned long flags;
@@ -687,6 +855,12 @@
axi_ctrl->share_ctrl->outpath.output_mode = 0;
axi_ctrl->share_ctrl->comp_output_mode = 0;
axi_ctrl->share_ctrl->vfe_capture_count = 0;
+ axi_ctrl->share_ctrl->rdi0_capture_count = -1;
+ axi_ctrl->share_ctrl->rdi1_capture_count = -1;
+ axi_ctrl->share_ctrl->outpath.out0.capture_cnt = -1;
+ axi_ctrl->share_ctrl->outpath.out1.capture_cnt = -1;
+ axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+ axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
/* this is unsigned 32 bit integer. */
axi_ctrl->share_ctrl->vfeFrameId = 0;
@@ -695,6 +869,7 @@
axi_ctrl->share_ctrl->rdi2FrameId = 0;
}
+
static void vfe32_program_dmi_cfg(
enum VFE32_DMI_RAM_SEL bankSel,
struct vfe32_ctrl_type *vfe32_ctrl)
@@ -833,6 +1008,17 @@
static void vfe32_reset_internal_variables(
struct vfe32_ctrl_type *vfe32_ctrl)
{
+ unsigned long flags;
+ spin_lock_irqsave(&vfe32_ctrl->share_ctrl->update_ack_lock,
+ flags);
+ vfe32_ctrl->share_ctrl->update_ack_pending = FALSE;
+ spin_unlock_irqrestore(&vfe32_ctrl->share_ctrl->update_ack_lock,
+ flags);
+ vfe32_ctrl->share_ctrl->vfe_capture_count = 0;
+ /* this is unsigned 32 bit integer. */
+ vfe32_ctrl->share_ctrl->vfeFrameId = 0;
+ vfe32_ctrl->share_ctrl->update_counter = 0;
+
/* Stats control variables. */
memset(&(vfe32_ctrl->afbfStatsControl), 0,
sizeof(struct vfe_stats_control));
@@ -854,6 +1040,13 @@
memset(&(vfe32_ctrl->csStatsControl), 0,
sizeof(struct vfe_stats_control));
+ vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt = -1;
+ vfe32_ctrl->share_ctrl->outpath.out1.capture_cnt = -1;
+ vfe32_ctrl->share_ctrl->recording_state = VFE_STATE_IDLE;
+ vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
+
+ atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
+ atomic_set(&vfe32_ctrl->share_ctrl->pix0_update_ack_pending, 0);
vfe32_ctrl->frame_skip_cnt = 31;
vfe32_ctrl->frame_skip_pattern = 0xffffffff;
@@ -878,6 +1071,11 @@
msm_camera_io_w(irq_mask, vfe32_ctrl->share_ctrl->vfebase +
VFE_IRQ_MASK_0);
+ vfe32_ctrl->share_ctrl->operation_mode &=
+ (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
+ vfe32_ctrl->share_ctrl->comp_output_mode &=
+ (VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
/* enable reset_ack interrupt. */
irq_mask1 = msm_camera_io_r(
@@ -892,9 +1090,15 @@
&vfe32_ctrl->share_ctrl->reset_complete);
}
-static int axi_reset(struct axi_ctrl_t *axi_ctrl)
+static int axi_reset(struct axi_ctrl_t *axi_ctrl,
+ struct msm_camera_vfe_params_t vfe_params)
{
- axi_reset_internal_variables(axi_ctrl);
+ int rc = 0;
+ if (vfe_params.skip_reset) {
+ axi_reset_internal_variables(axi_ctrl, vfe_params);
+ return rc;
+ }
+ axi_global_reset_internal_variables(axi_ctrl);
/* disable all interrupts. vfeImaskLocal is also reset to 0
* to begin with. */
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
@@ -1256,17 +1460,11 @@
static void vfe32_start_common(struct vfe32_ctrl_type *vfe32_ctrl)
{
- uint16_t vfe_operation_mode =
- vfe32_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
- VFE_OUTPUTS_RDI1);
CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
- vfe32_ctrl->share_ctrl->current_mode,
+ vfe32_ctrl->share_ctrl->operation_mode,
vfe32_ctrl->share_ctrl->outpath.output_mode);
-
- if (vfe_operation_mode) {
msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
VFE_CAMIF_COMMAND);
- }
}
static int vfe32_start_recording(
@@ -2792,8 +2990,6 @@
goto proc_general_done;
}
- vfe32_ctrl->share_ctrl->current_mode =
- vfe_params.operation_mode;
vfe32_stop(vfe32_ctrl);
break;
@@ -3168,23 +3364,17 @@
}
-void axi_stop_pix(struct vfe_share_ctrl_t *share_ctrl)
+void axi_stop_pix(struct vfe_share_ctrl_t *share_ctrl,
+ uint32_t vfe_mode, uint8_t cmd_type)
{
- uint32_t operation_mode =
- share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
- VFE_OUTPUTS_RDI1);
- uint32_t irq_comp_mask, irq_mask;
uint32_t reg_update = 0x1;
-
- irq_comp_mask =
- msm_camera_io_r(share_ctrl->vfebase +
- VFE_IRQ_COMP_MASK);
- irq_mask = msm_camera_io_r(share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
-
- switch (share_ctrl->cmd_type) {
+ switch (cmd_type) {
+ case AXI_CMD_RAW_CAPTURE:
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->outpath.out0.ch0]);
+ break;
case AXI_CMD_PREVIEW: {
- switch (operation_mode) {
+ switch (vfe_mode) {
case VFE_OUTPUTS_PREVIEW:
case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
if (share_ctrl->comp_output_mode &
@@ -3195,11 +3385,6 @@
msm_camera_io_w(0, share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[share_ctrl->
outpath.out0.ch1]);
- irq_comp_mask &= ~(
- 0x1 << share_ctrl->outpath.out0.ch0 |
- 0x1 << share_ctrl->outpath.out0.ch1);
- share_ctrl->outpath.output_mode |=
- VFE32_OUTPUT_MODE_PRIMARY;
} else if (share_ctrl->comp_output_mode &
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
msm_camera_io_w(0, share_ctrl->vfebase
@@ -3211,14 +3396,7 @@
msm_camera_io_w(0, share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[share_ctrl->
outpath.out0.ch2]);
- irq_comp_mask &= ~(
- 0x1 << share_ctrl->outpath.out0.ch0 |
- 0x1 << share_ctrl->outpath.out0.ch1 |
- 0x1 << share_ctrl->outpath.out0.ch2);
- share_ctrl->outpath.output_mode |=
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
}
- irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
break;
default:
if (share_ctrl->comp_output_mode &
@@ -3229,11 +3407,6 @@
msm_camera_io_w(0, share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[share_ctrl->
outpath.out1.ch1]);
- irq_comp_mask &= ~(
- 0x1 << share_ctrl->outpath.out1.ch0 |
- 0x1 << share_ctrl->outpath.out1.ch1);
- share_ctrl->outpath.output_mode |=
- VFE32_OUTPUT_MODE_SECONDARY;
} else if (share_ctrl->comp_output_mode &
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
msm_camera_io_w(0, share_ctrl->vfebase
@@ -3245,14 +3418,7 @@
msm_camera_io_w(0, share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[share_ctrl->
outpath.out1.ch2]);
- irq_comp_mask &= ~(
- 0x1 << share_ctrl->outpath.out1.ch0 |
- 0x1 << share_ctrl->outpath.out1.ch1 |
- 0x1 << share_ctrl->outpath.out1.ch2);
- share_ctrl->outpath.output_mode |=
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
}
- irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
break;
}
}
@@ -3266,12 +3432,6 @@
msm_camera_io_w(0, share_ctrl->vfebase +
vfe32_AXI_WM_CFG[share_ctrl->
outpath.out0.ch1]);
- irq_comp_mask &= ~(
- 0x1 << share_ctrl->outpath.out0.ch0 |
- 0x1 << share_ctrl->outpath.out0.ch1);
- irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
- share_ctrl->outpath.output_mode |=
- VFE32_OUTPUT_MODE_PRIMARY;
} else if (share_ctrl->comp_output_mode &
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
msm_camera_io_w(0, share_ctrl->vfebase +
@@ -3283,13 +3443,6 @@
msm_camera_io_w(0, share_ctrl->vfebase +
vfe32_AXI_WM_CFG[share_ctrl->
outpath.out0.ch2]);
- irq_comp_mask &= ~(
- 0x1 << share_ctrl->outpath.out0.ch0 |
- 0x1 << share_ctrl->outpath.out0.ch1 |
- 0x1 << share_ctrl->outpath.out0.ch2);
- irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
- share_ctrl->outpath.output_mode |=
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
}
if (share_ctrl->comp_output_mode &
@@ -3299,12 +3452,6 @@
outpath.out1.ch0]);
msm_camera_io_w(0, share_ctrl->vfebase +
vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
- irq_comp_mask &= ~(
- 0x1 << share_ctrl->outpath.out1.ch0 |
- 0x1 << share_ctrl->outpath.out1.ch1);
- irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
- share_ctrl->outpath.output_mode |=
- VFE32_OUTPUT_MODE_SECONDARY;
} else if (share_ctrl->comp_output_mode &
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
msm_camera_io_w(0, share_ctrl->vfebase +
@@ -3313,82 +3460,63 @@
vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
msm_camera_io_w(0, share_ctrl->vfebase +
vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch2]);
- irq_comp_mask &= ~(
- 0x1 << share_ctrl->outpath.out1.ch0 |
- 0x1 << share_ctrl->outpath.out1.ch1 |
- 0x1 << share_ctrl->outpath.out1.ch2);
- irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
- share_ctrl->outpath.output_mode |=
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
}
break;
}
msm_camera_io_w_mb(reg_update,
share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- msm_camera_io_w(irq_comp_mask,
- share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- msm_camera_io_w(irq_mask, share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
}
void axi_stop_rdi0(struct vfe_share_ctrl_t *share_ctrl)
{
uint32_t reg_update = 0x2;
- uint32_t irq_mask;
- irq_mask = msm_camera_io_r(share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
-
- if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
- msm_camera_io_w(0, share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[share_ctrl->outpath.out2.ch0]);
- irq_mask &= ~(0x1 << (share_ctrl->outpath.out2.ch0 +
- VFE_WM_OFFSET));
- }
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out2.ch0]);
msm_camera_io_w_mb(reg_update,
share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- msm_camera_io_w(irq_mask, share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
}
void axi_stop_rdi1(struct vfe_share_ctrl_t *share_ctrl)
{
uint32_t reg_update = 0x4;
- uint32_t irq_mask;
- irq_mask = msm_camera_io_r(share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
-
- if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
- msm_camera_io_w(1, share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[share_ctrl->outpath.out3.ch0]);
- irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
- VFE_WM_OFFSET));
- }
-
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out3.ch0]);
msm_camera_io_w_mb(reg_update,
share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- msm_camera_io_w(irq_mask, share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
}
void axi_stop_process(struct vfe_share_ctrl_t *share_ctrl)
{
- uint32_t operation_mode =
+ uint32_t vfe_mode =
share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
VFE_OUTPUTS_RDI1);
if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
axi_stop_rdi0(share_ctrl);
+ axi_disable_wm_irq(share_ctrl,
+ VFE32_OUTPUT_MODE_TERTIARY1);
share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY1;
+ share_ctrl->operation_mode &=
+ ~(VFE_OUTPUTS_RDI0);
}
if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
axi_stop_rdi1(share_ctrl);
+ axi_disable_wm_irq(share_ctrl,
+ VFE32_OUTPUT_MODE_TERTIARY2);
share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY2;
+ share_ctrl->operation_mode &=
+ ~(VFE_OUTPUTS_RDI1);
}
- if (operation_mode) {
- axi_stop_pix(share_ctrl);
+ if (vfe_mode) {
+ uint16_t mode = share_ctrl->comp_output_mode &
+ ~(VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
+ axi_stop_pix(share_ctrl, vfe_mode, share_ctrl->cmd_type);
+ axi_disable_wm_irq(share_ctrl, mode);
share_ctrl->comp_output_mode &=
- ~(share_ctrl->outpath.output_mode);
+ (VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
}
}
@@ -3397,25 +3525,47 @@
{
unsigned long flags;
struct vfe_share_ctrl_t *share_ctrl = vfe32_ctrl->share_ctrl;
+ if (atomic_read(
+ &share_ctrl->pix0_update_ack_pending) == 2) {
+ uint32_t vfe_mode =
+ share_ctrl->operation_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
- if (atomic_cmpxchg(
- &share_ctrl->pix0_update_ack_pending, 2, 0) == 2) {
- axi_stop_pix(share_ctrl);
- msm_camera_io_w_mb(
- CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
- share_ctrl->vfebase + VFE_CAMIF_COMMAND);
- axi_disable_irq(share_ctrl);
- vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- share_ctrl->vfeFrameId,
- MSG_ID_PIX0_UPDATE_ACK);
- share_ctrl->comp_output_mode &=
- ~(share_ctrl->outpath.output_mode);
- share_ctrl->current_mode &=
- (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
+ if (share_ctrl->dual_enabled && !share_ctrl->update_counter) {
+ axi_stop_pix(share_ctrl, vfe_mode,
+ share_ctrl->cmd_type);
+ share_ctrl->update_counter++;
+ } else {
+ uint16_t output_mode =
+ share_ctrl->comp_output_mode &
+ ~(VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
+ share_ctrl->update_counter = 0;
+ if (!share_ctrl->dual_enabled)
+ axi_stop_pix(share_ctrl, vfe_mode,
+ share_ctrl->cmd_type);
+ axi_disable_wm_irq(share_ctrl, output_mode);
+ axi_disable_irq(share_ctrl, vfe_mode);
+ atomic_set(&share_ctrl->pix0_update_ack_pending, 0);
+ msm_camera_io_w_mb(
+ CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ share_ctrl->vfebase +
+ VFE_CAMIF_COMMAND);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ share_ctrl->vfeFrameId,
+ MSG_ID_PIX0_UPDATE_ACK);
+ share_ctrl->comp_output_mode &=
+ (VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
+ }
} else {
if (share_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
if (share_ctrl->operation_mode &
VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+ msm_camera_io_w((
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1),
+ share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1,
share_ctrl->vfebase + vfe32_AXI_WM_CFG[
share_ctrl->outpath.out0.ch0]);
@@ -3424,6 +3574,10 @@
share_ctrl->outpath.out0.ch1]);
} else if (share_ctrl->operation_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+ msm_camera_io_w((
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1),
+ share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1,
share_ctrl->vfebase + vfe32_AXI_WM_CFG[
share_ctrl->outpath.out1.ch0]);
@@ -3465,8 +3619,6 @@
VFE32_OUTPUT_MODE_TERTIARY2));
vfe32_send_isp_msg(&vfe32_ctrl->subdev,
share_ctrl->vfeFrameId, MSG_ID_PIX0_UPDATE_ACK);
- share_ctrl->current_mode &=
- (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
} else {
if (share_ctrl->recording_state ==
VFE_STATE_STOP_REQUESTED) {
@@ -3504,6 +3656,10 @@
CDBG("%s enabling liveshot output\n", __func__);
if (share_ctrl->comp_output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w((
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1),
+ share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1, share_ctrl->vfebase +
vfe32_AXI_WM_CFG[
share_ctrl->outpath.out0.ch0]);
@@ -3572,32 +3728,12 @@
/* if last frame to be captured: */
if (share_ctrl->vfe_capture_count == 0) {
/* stop the bus output: */
- if (share_ctrl->comp_output_mode
- & VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(0,
- share_ctrl->vfebase+
- vfe32_AXI_WM_CFG[
- share_ctrl->
- outpath.out0.ch0]);
- msm_camera_io_w(0,
- share_ctrl->vfebase+
- vfe32_AXI_WM_CFG[
- share_ctrl->
- outpath.out0.ch1]);
- }
- if (share_ctrl->comp_output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(0,
- share_ctrl->vfebase+
- vfe32_AXI_WM_CFG[
- share_ctrl->
- outpath.out1.ch0]);
- msm_camera_io_w(0,
- share_ctrl->vfebase+
- vfe32_AXI_WM_CFG[
- share_ctrl->
- outpath.out1.ch1]);
- }
+ uint32_t vfe_mode =
+ share_ctrl->operation_mode &
+ ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+ axi_stop_pix(share_ctrl, vfe_mode,
+ AXI_CMD_CAPTURE);
msm_camera_io_w_mb
(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
share_ctrl->vfebase +
@@ -3620,56 +3756,84 @@
struct vfe32_ctrl_type *vfe32_ctrl)
{
if (atomic_cmpxchg(
- &vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 2, 0) == 2) {
- axi_stop_rdi0(vfe32_ctrl->share_ctrl);
- axi_disable_irq(vfe32_ctrl->share_ctrl);
- vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId,
- MSG_ID_RDI0_UPDATE_ACK);
- vfe32_ctrl->share_ctrl->comp_output_mode &=
- ~VFE32_OUTPUT_MODE_TERTIARY1;
- vfe32_ctrl->share_ctrl->current_mode &=
- ~(VFE_OUTPUTS_RDI0);
- }
-
- if (atomic_cmpxchg(
&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 1, 0) == 1) {
vfe32_ctrl->share_ctrl->comp_output_mode |=
VFE32_OUTPUT_MODE_TERTIARY1;
vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId,
+ vfe32_ctrl->share_ctrl->rdi0FrameId,
MSG_ID_RDI0_UPDATE_ACK);
- vfe32_ctrl->share_ctrl->current_mode &=
+ }
+
+ if ((atomic_read(
+ &vfe32_ctrl->share_ctrl->rdi0_update_ack_pending) == 2)
+ || (vfe32_ctrl->share_ctrl->rdi0_capture_count == 0)) {
+ axi_disable_wm_irq(vfe32_ctrl->share_ctrl,
+ VFE32_OUTPUT_MODE_TERTIARY1);
+ axi_disable_irq(vfe32_ctrl->share_ctrl, VFE_OUTPUTS_RDI0);
+ atomic_set(&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->rdi0FrameId,
+ MSG_ID_RDI0_UPDATE_ACK);
+
+ if (vfe32_ctrl->share_ctrl->rdi0_capture_count == 0)
+ vfe32_ctrl->share_ctrl->rdi0_capture_count = -1;
+ if (vfe32_ctrl->share_ctrl->outpath.out2.capture_cnt
+ == 0)
+ vfe32_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+ vfe32_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE32_OUTPUT_MODE_TERTIARY1;
+ vfe32_ctrl->share_ctrl->operation_mode &=
~(VFE_OUTPUTS_RDI0);
}
+
+ if (vfe32_ctrl->share_ctrl->rdi0_capture_count > 0) {
+ vfe32_ctrl->share_ctrl->rdi0_capture_count--;
+ if (!vfe32_ctrl->share_ctrl->rdi0_capture_count)
+ axi_stop_rdi0(vfe32_ctrl->share_ctrl);
+ }
}
static void vfe32_process_rdi1_reg_update_irq(
struct vfe32_ctrl_type *vfe32_ctrl)
{
- if (atomic_cmpxchg(
- &vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 2, 0) == 2) {
- axi_stop_rdi1(vfe32_ctrl->share_ctrl);
- axi_disable_irq(vfe32_ctrl->share_ctrl);
- vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId,
- MSG_ID_RDI1_UPDATE_ACK);
- vfe32_ctrl->share_ctrl->comp_output_mode &=
- ~VFE32_OUTPUT_MODE_TERTIARY2;
- vfe32_ctrl->share_ctrl->current_mode &=
- ~(VFE_OUTPUTS_RDI1);
- }
if (atomic_cmpxchg(
- &vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0) == 1) {
+ &vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0)
+ == 1) {
vfe32_ctrl->share_ctrl->comp_output_mode |=
VFE32_OUTPUT_MODE_TERTIARY2;
vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId,
+ vfe32_ctrl->share_ctrl->rdi1FrameId,
MSG_ID_RDI1_UPDATE_ACK);
- vfe32_ctrl->share_ctrl->current_mode &=
+ }
+
+ if ((atomic_read(
+ &vfe32_ctrl->share_ctrl->rdi1_update_ack_pending) == 2)
+ || (vfe32_ctrl->share_ctrl->rdi1_capture_count == 0)) {
+ axi_disable_wm_irq(vfe32_ctrl->share_ctrl,
+ VFE32_OUTPUT_MODE_TERTIARY2);
+ axi_disable_irq(vfe32_ctrl->share_ctrl, VFE_OUTPUTS_RDI1);
+ atomic_set(&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->rdi1FrameId,
+ MSG_ID_RDI1_UPDATE_ACK);
+
+ if (vfe32_ctrl->share_ctrl->rdi1_capture_count == 0)
+ vfe32_ctrl->share_ctrl->rdi1_capture_count = -1;
+ if (vfe32_ctrl->share_ctrl->outpath.out3.capture_cnt
+ == 0)
+ vfe32_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+ vfe32_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE32_OUTPUT_MODE_TERTIARY2;
+ vfe32_ctrl->share_ctrl->operation_mode &=
~(VFE_OUTPUTS_RDI1);
}
+
+ if (vfe32_ctrl->share_ctrl->rdi1_capture_count > 0) {
+ vfe32_ctrl->share_ctrl->rdi1_capture_count--;
+ if (!vfe32_ctrl->share_ctrl->rdi1_capture_count)
+ axi_stop_rdi1(vfe32_ctrl->share_ctrl);
+ }
}
static void vfe32_process_reset_irq(
@@ -3714,9 +3878,18 @@
{
if (vfe32_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_RAW) {
- if (vfe32_ctrl->share_ctrl->start_ack_pending) {
- vfe32_ctrl->share_ctrl->start_ack_pending = FALSE;
+ if (atomic_cmpxchg(
+ &vfe32_ctrl->share_ctrl->pix0_update_ack_pending,
+ 1, 0) == 1) {
+ vfe32_ctrl->share_ctrl->comp_output_mode |=
+ (vfe32_ctrl->share_ctrl->outpath.output_mode
+ & ~(VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2));
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_PIX0_UPDATE_ACK);
}
+
vfe32_ctrl->share_ctrl->vfe_capture_count--;
/* if last frame to be captured: */
if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
@@ -3881,7 +4054,6 @@
uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
uint8_t out_bool = 0;
struct msm_free_buf *free_buf = NULL;
-
free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
@@ -4058,10 +4230,12 @@
/* this must be rdi image output. */
struct msm_free_buf *free_buf = NULL;
/*RDI0*/
+ CDBG("rdi0 out irq\n");
if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
VFE_MSG_OUTPUT_TERTIARY1, axi_ctrl);
- if (free_buf) {
+ if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt > 0 ||
+ free_buf) {
ping_pong = msm_camera_io_r(axi_ctrl->
share_ctrl->vfebase +
VFE_BUS_PING_PONG_STATUS);
@@ -4074,11 +4248,14 @@
pr_debug("%s ch0 = 0x%x\n",
__func__, ch0_paddr);
- /* Y channel */
- vfe32_put_ch_addr(ping_pong,
- axi_ctrl->share_ctrl->vfebase,
- axi_ctrl->share_ctrl->outpath.out2.ch0,
- free_buf->ch_paddr[0]);
+ if (free_buf)
+ vfe32_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out2.ch0,
+ free_buf->ch_paddr[0]);
+ if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt == 1)
+ axi_ctrl->share_ctrl->
+ outpath.out2.capture_cnt = 0;
vfe_send_outmsg(axi_ctrl,
MSG_ID_OUTPUT_TERTIARY1, ch0_paddr,
@@ -4103,7 +4280,8 @@
if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1) {
free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
VFE_MSG_OUTPUT_TERTIARY2, axi_ctrl);
- if (free_buf) {
+ if (axi_ctrl->share_ctrl->outpath.out3.capture_cnt > 0 ||
+ free_buf) {
ping_pong = msm_camera_io_r(axi_ctrl->
share_ctrl->vfebase +
VFE_BUS_PING_PONG_STATUS);
@@ -4115,11 +4293,15 @@
pr_debug("%s ch0 = 0x%x\n",
__func__, ch0_paddr);
- /* Y channel */
- vfe32_put_ch_addr(ping_pong,
- axi_ctrl->share_ctrl->vfebase,
- axi_ctrl->share_ctrl->outpath.out3.ch0,
- free_buf->ch_paddr[0]);
+ if (free_buf)
+ vfe32_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out3.ch0,
+ free_buf->ch_paddr[0]);
+ if (axi_ctrl->share_ctrl->
+ outpath.out3.capture_cnt == 1)
+ axi_ctrl->share_ctrl->
+ outpath.out3.capture_cnt = 0;
vfe_send_outmsg(axi_ctrl,
MSG_ID_OUTPUT_TERTIARY2, ch0_paddr,
@@ -5209,6 +5391,9 @@
int round_rate;
struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ if (axi_ctrl->share_ctrl->dual_enabled)
+ return rc;
+
round_rate = clk_round_rate(axi_ctrl->vfe_clk[0], freq);
if (rc < 0) {
pr_err("%s: clk_round_rate failed %d\n",
@@ -5233,21 +5418,22 @@
.core = &msm_vfe_subdev_core_ops,
};
-int msm_axi_subdev_init(struct v4l2_subdev *sd)
+int msm_axi_subdev_init(struct v4l2_subdev *sd,
+ uint8_t dual_enabled)
{
int rc = 0;
struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
- struct msm_cam_media_controller *mctl;
- mctl = v4l2_get_subdev_hostdata(sd);
+ struct msm_cam_media_controller *mctl =
+ v4l2_get_subdev_hostdata(sd);
if (mctl == NULL) {
- pr_err("%s: mctl is NULL\n", __func__);
rc = -EINVAL;
goto mctl_failed;
}
+
axi_ctrl->share_ctrl->axi_ref_cnt++;
if (axi_ctrl->share_ctrl->axi_ref_cnt > 1)
return rc;
-
+ axi_ctrl->share_ctrl->dual_enabled = dual_enabled;
spin_lock_init(&axi_ctrl->tasklet_lock);
INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
@@ -5290,8 +5476,13 @@
msm_camio_bus_scale_cfg(
mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
- msm_camio_bus_scale_cfg(
- mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+
+ if (axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ mctl->sdata->pdata->cam_bus_scale_table, S_DUAL);
+ else
+ msm_camio_bus_scale_cfg(
+ mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
if (msm_camera_io_r(
axi_ctrl->share_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
@@ -5351,18 +5542,19 @@
void msm_axi_subdev_release(struct v4l2_subdev *sd)
{
- struct msm_cam_media_controller *pmctl =
- (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ struct msm_cam_media_controller *pmctl =
+ v4l2_get_subdev_hostdata(sd);
+
if (!axi_ctrl->share_ctrl->vfebase) {
pr_err("%s: base address unmapped\n", __func__);
return;
}
- CDBG("%s, free_irq\n", __func__);
axi_ctrl->share_ctrl->axi_ref_cnt--;
if (axi_ctrl->share_ctrl->axi_ref_cnt > 0)
return;
+ axi_ctrl->share_ctrl->dual_enabled = 0;
disable_irq(axi_ctrl->vfeirq->start);
tasklet_kill(&axi_ctrl->vfe32_tasklet);
#ifdef CONFIG_MSM_IOMMU
@@ -5534,39 +5726,53 @@
}
break;
case AXI_CMD_CAPTURE:
- if (axi_ctrl->share_ctrl->current_mode ==
- VFE_OUTPUTS_JPEG_AND_THUMB ||
- axi_ctrl->share_ctrl->current_mode ==
- VFE_OUTPUTS_THUMB_AND_JPEG) {
+ if (vfe_mode) {
+ if (axi_ctrl->share_ctrl->current_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ axi_ctrl->share_ctrl->current_mode ==
+ VFE_OUTPUTS_THUMB_AND_JPEG) {
- /* Configure primary channel for JPEG */
+ /* Configure primary channel for JPEG */
+ rc = configure_pingpong_buffers(
+ VFE_MSG_JPEG_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY,
+ axi_ctrl);
+ } else {
+ /* Configure primary channel */
+ rc = configure_pingpong_buffers(
+ VFE_MSG_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY,
+ axi_ctrl);
+ }
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers for primary output",
+ __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ /* Configure secondary channel */
rc = configure_pingpong_buffers(
- VFE_MSG_JPEG_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY,
- axi_ctrl);
- } else {
- /* Configure primary channel */
+ VFE_MSG_CAPTURE,
+ VFE_MSG_OUTPUT_SECONDARY,
+ axi_ctrl);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers for secondary output",
+ __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ }
+
+ if (axi_ctrl->share_ctrl->current_mode &
+ VFE_OUTPUTS_RDI0)
rc = configure_pingpong_buffers(
- VFE_MSG_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY,
+ VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_TERTIARY1,
axi_ctrl);
- }
- if (rc < 0) {
- pr_err("%s error configuring pingpong buffers for primary output",
- __func__);
- rc = -EINVAL;
- goto config_done;
- }
- /* Configure secondary channel */
- rc = configure_pingpong_buffers(
- VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
+ if (axi_ctrl->share_ctrl->current_mode &
+ VFE_OUTPUTS_RDI1)
+ rc = configure_pingpong_buffers(
+ VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_TERTIARY2,
axi_ctrl);
- if (rc < 0) {
- pr_err("%s error configuring pingpong buffers for secondary output",
- __func__);
- rc = -EINVAL;
- goto config_done;
- }
break;
default:
rc = -EINVAL;
@@ -5580,10 +5786,9 @@
void axi_start(struct msm_cam_media_controller *pmctl,
struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
{
- uint32_t irq_comp_mask = 0, irq_mask = 0, irq_mask1 = 0;
int rc = 0;
uint32_t reg_update = 0;
- uint16_t operation_mode =
+ uint32_t vfe_mode =
(axi_ctrl->share_ctrl->current_mode &
~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
rc = axi_config_buffers(axi_ctrl, vfe_params);
@@ -5592,99 +5797,77 @@
switch (vfe_params.cmd_type) {
case AXI_CMD_PREVIEW:
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
break;
case AXI_CMD_CAPTURE:
case AXI_CMD_RAW_CAPTURE:
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+ if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
break;
case AXI_CMD_RECORD:
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+ if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
return;
case AXI_CMD_ZSL:
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
+ if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
break;
case AXI_CMD_LIVESHOT:
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_LIVESHOT);
+ if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table, S_LIVESHOT);
return;
default:
return;
}
-
- irq_comp_mask =
- msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_COMP_MASK);
- irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
-
- if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- if (vfe_params.cmd_type == AXI_CMD_RAW_CAPTURE)
- irq_comp_mask |= (
- 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0);
- else
- irq_comp_mask |= (
- 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
- 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
- irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
- } else if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- irq_comp_mask |= (
- 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
- 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
- 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2);
- irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
- }
- if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |= (
- 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8));
- irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
- } else if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- irq_comp_mask |= (
- 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
- 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch2 + 8));
- irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
- }
- if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_TERTIARY1) {
- irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0 +
- VFE_WM_OFFSET));
- }
- if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_TERTIARY2) {
- irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0 +
- VFE_WM_OFFSET));
- }
-
- msm_camera_io_w(irq_comp_mask,
- axi_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
+ axi_enable_wm_irq(axi_ctrl->share_ctrl);
switch (vfe_params.cmd_type) {
+ case AXI_CMD_RAW_CAPTURE:
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0),
+ axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ break;
case AXI_CMD_PREVIEW: {
- switch (operation_mode) {
+ switch (vfe_mode) {
case VFE_OUTPUTS_PREVIEW:
case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out0.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out0.ch1),
+ axi_ctrl->share_ctrl->vfebase +
+ VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out0.ch0]);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out0.ch1]);
+
+
} else if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out0.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out0.ch1 |
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out0.ch2),
+ axi_ctrl->share_ctrl->vfebase +
+ VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out0.ch0]);
@@ -5699,6 +5882,13 @@
default:
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out1.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out1.ch1),
+ axi_ctrl->share_ctrl->vfebase +
+ VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out1.ch0]);
@@ -5707,6 +5897,15 @@
share_ctrl->outpath.out1.ch1]);
} else if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out1.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out1.ch1 |
+ 0x1 << axi_ctrl->share_ctrl->
+ outpath.out1.ch2),
+ axi_ctrl->share_ctrl->vfebase +
+ VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out1.ch0]);
@@ -5724,6 +5923,10 @@
default:
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1),
+ axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out0.ch0]);
@@ -5732,6 +5935,11 @@
share_ctrl->outpath.out0.ch1]);
} else if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2),
+ axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out0.ch0]);
@@ -5745,6 +5953,10 @@
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->outpath.out1.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out1.ch1),
+ axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out1.ch0]);
@@ -5753,6 +5965,11 @@
share_ctrl->outpath.out1.ch1]);
} else if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->outpath.out1.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out1.ch1 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out1.ch2),
+ axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out1.ch0]);
@@ -5765,36 +5982,47 @@
}
break;
}
- if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ axi_ctrl->share_ctrl->outpath.out2.capture_cnt =
+ vfe_params.capture_count;
+ axi_ctrl->share_ctrl->rdi0_capture_count =
+ vfe_params.capture_count;
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->outpath.out2.ch0),
+ axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
outpath.out2.ch0]);
- if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+ }
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ axi_ctrl->share_ctrl->outpath.out3.capture_cnt =
+ vfe_params.capture_count;
+ axi_ctrl->share_ctrl->rdi1_capture_count =
+ vfe_params.capture_count;
+ msm_camera_io_w((
+ 0x1 << axi_ctrl->share_ctrl->outpath.out3.ch0),
+ axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
outpath.out3.ch0]);
+ }
- irq_mask1 =
- msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
+ axi_enable_irq(axi_ctrl->share_ctrl);
if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
- irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
if (!atomic_cmpxchg(
&axi_ctrl->share_ctrl->rdi0_update_ack_pending,
0, 1))
reg_update |= 0x2;
}
if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
- irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
if (!atomic_cmpxchg(
&axi_ctrl->share_ctrl->rdi1_update_ack_pending,
0, 1))
reg_update |= 0x4;
}
- msm_camera_io_w(irq_mask1, axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
- if (operation_mode) {
+
+ if (vfe_mode) {
if (!atomic_cmpxchg(
&axi_ctrl->share_ctrl->pix0_update_ack_pending,
0, 1))
@@ -5806,54 +6034,62 @@
VFE_REG_UPDATE_CMD);
axi_ctrl->share_ctrl->operation_mode |=
axi_ctrl->share_ctrl->current_mode;
- axi_enable_irq(axi_ctrl->share_ctrl);
}
void axi_stop(struct msm_cam_media_controller *pmctl,
struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
{
uint32_t reg_update = 0;
- uint32_t operation_mode =
+ uint32_t vfe_mode =
axi_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
VFE_OUTPUTS_RDI1);
-
switch (vfe_params.cmd_type) {
case AXI_CMD_PREVIEW:
case AXI_CMD_CAPTURE:
case AXI_CMD_RAW_CAPTURE:
case AXI_CMD_ZSL:
+ axi_ctrl->share_ctrl->cmd_type = vfe_params.cmd_type;
break;
case AXI_CMD_RECORD:
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
return;
case AXI_CMD_LIVESHOT:
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+ if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
return;
default:
return;
}
if (axi_ctrl->share_ctrl->stop_immediately) {
- axi_disable_irq(axi_ctrl->share_ctrl);
+ axi_disable_irq(axi_ctrl->share_ctrl,
+ axi_ctrl->share_ctrl->current_mode);
axi_stop_process(axi_ctrl->share_ctrl);
return;
}
if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
+ outpath.out2.ch0]);
if (!atomic_cmpxchg(
&axi_ctrl->share_ctrl->rdi0_update_ack_pending,
0, 2))
reg_update |= 0x2;
}
if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
+ outpath.out3.ch0]);
if (!atomic_cmpxchg(
&axi_ctrl->share_ctrl->rdi1_update_ack_pending,
0, 2))
reg_update |= 0x4;
}
- if (operation_mode) {
+ if (vfe_mode) {
if (!atomic_cmpxchg(
&axi_ctrl->share_ctrl->pix0_update_ack_pending,
0, 2))
@@ -6083,8 +6319,15 @@
axi_stop(pmctl, axi_ctrl, vfe_params);
}
break;
- case CMD_AXI_RESET:
- axi_reset(axi_ctrl);
+ case CMD_AXI_RESET: {
+ struct msm_camera_vfe_params_t vfe_params;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(vfecmd.value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ return -EFAULT;
+ }
+ axi_reset(axi_ctrl, vfe_params);
+ }
break;
case CMD_AXI_ABORT:
if (copy_from_user(&axi_ctrl->share_ctrl->sync_abort,
@@ -6151,19 +6394,44 @@
if ((axi_ctrl->share_ctrl->outpath.out0.capture_cnt == 0)
&& (axi_ctrl->share_ctrl->outpath.out1.
capture_cnt == 0)) {
- msm_camera_io_w_mb(
- CAMIF_COMMAND_STOP_IMMEDIATELY,
- axi_ctrl->share_ctrl->vfebase +
- VFE_CAMIF_COMMAND);
- axi_disable_irq(axi_ctrl->share_ctrl);
+ uint32_t mode =
+ (axi_ctrl->share_ctrl->operation_mode &
+ ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
+ uint16_t output_mode =
+ axi_ctrl->share_ctrl->comp_output_mode &
+ ~(VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
+ if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camera_io_w_mb(
+ CAMIF_COMMAND_STOP_IMMEDIATELY,
+ axi_ctrl->share_ctrl->vfebase +
+ VFE_CAMIF_COMMAND);
+ axi_disable_wm_irq(axi_ctrl->share_ctrl, output_mode);
+ axi_disable_irq(axi_ctrl->share_ctrl, mode);
vfe32_send_isp_msg(&axi_ctrl->subdev,
axi_ctrl->share_ctrl->vfeFrameId,
MSG_ID_PIX0_UPDATE_ACK);
- vfe32_send_isp_msg(&axi_ctrl->subdev,
- axi_ctrl->share_ctrl->vfeFrameId,
- MSG_ID_SNAPSHOT_DONE);
+ axi_ctrl->share_ctrl->outpath.out0.
+ capture_cnt = -1;
+ axi_ctrl->share_ctrl->outpath.out1.
+ capture_cnt = -1;
+ axi_ctrl->share_ctrl->comp_output_mode &=
+ (VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2);
}
}
+
+ if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt == 0) {
+ axi_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE32_OUTPUT_MODE_TERTIARY1;
+ axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+ }
+
+ if (axi_ctrl->share_ctrl->outpath.out3.capture_cnt == 0) {
+ axi_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE32_OUTPUT_MODE_TERTIARY2;
+ axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+ }
}
static int msm_axi_buf_cfg(struct v4l2_subdev *sd, void __user *arg)
@@ -6218,8 +6486,16 @@
{
int rc = -ENOIOCTLCMD;
switch (cmd) {
- case VIDIOC_MSM_AXI_INIT:
- rc = msm_axi_subdev_init(sd);
+ case VIDIOC_MSM_AXI_INIT: {
+ uint8_t dual_enabled;
+ if (copy_from_user(&dual_enabled,
+ (void __user *)(arg),
+ sizeof(uint8_t))) {
+ rc = -EFAULT;
+ break;
+ }
+ rc = msm_axi_subdev_init(sd, dual_enabled);
+ }
break;
case VIDIOC_MSM_AXI_CFG:
rc = msm_axi_config(sd, arg);
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/video/msm/vfe/msm_vfe32.h
index 985493e..f985221 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.h
+++ b/drivers/media/video/msm/vfe/msm_vfe32.h
@@ -782,7 +782,7 @@
int8_t ch0;
int8_t ch1;
int8_t ch2;
- uint32_t capture_cnt;
+ int32_t capture_cnt;
uint32_t frame_drop_cnt;
struct msm_free_buf ping;
struct msm_free_buf pong;
@@ -959,6 +959,9 @@
int8_t stop_ack_pending;
enum vfe_output_state liveshot_state;
uint32_t vfe_capture_count;
+ int32_t rdi0_capture_count;
+ int32_t rdi1_capture_count;
+ uint8_t update_counter;
uint32_t operation_mode; /* streaming or snapshot */
uint32_t current_mode;
@@ -969,6 +972,7 @@
uint8_t sync_abort;
uint16_t cmd_type;
uint8_t vfe_reset_flag;
+ uint8_t dual_enabled;
uint8_t axi_ref_cnt;
uint16_t comp_output_mode;
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index dd2a207..170322c 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -47,7 +47,7 @@
{
.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
.dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 414700000,
+ .ab = 138200000,
.ib = 1222000000,
},
};
@@ -56,7 +56,7 @@
{
.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
.dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 940000000,
+ .ab = 414700000,
.ib = 1222000000,
},
};
@@ -65,7 +65,7 @@
{
.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
.dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 1880000000,
+ .ab = 940000000,
.ib = 2444000000U,
},
};
@@ -111,7 +111,7 @@
{
.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
.dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 456200000,
+ .ab = 176900000,
.ib = 1556640000,
},
};
@@ -120,7 +120,7 @@
{
.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
.dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 864800000,
+ .ab = 456200000,
.ib = 1556640000,
},
};
@@ -129,8 +129,8 @@
{
.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
.dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 1729600000,
- .ib = 3113280000U,
+ .ab = 864800000,
+ .ib = 1556640000,
},
};
diff --git a/drivers/media/video/msm_vidc/vidc_hal.h b/drivers/media/video/msm_vidc/vidc_hal.h
index 8e7c3d3..c586172 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.h
+++ b/drivers/media/video/msm_vidc/vidc_hal.h
@@ -20,20 +20,6 @@
#include "msm_smem.h"
#include "vidc_hal_helper.h"
-#ifdef HAL_MSG_LOG
-#define HAL_MSG_LOW(x...) pr_info(KERN_INFO x)
-#define HAL_MSG_MEDIUM(x...) pr_info(KERN_INFO x)
-#define HAL_MSG_HIGH(x...) pr_info(KERN_INFO x)
-#else
-#define HAL_MSG_LOW(x...)
-#define HAL_MSG_MEDIUM(x...)
-#define HAL_MSG_HIGH(x...)
-#endif
-
-#define HAL_MSG_ERROR(x...) pr_err(KERN_INFO x)
-#define HAL_MSG_FATAL(x...) pr_err(KERN_INFO x)
-#define HAL_MSG_INFO(x...) pr_info(KERN_INFO x)
-
#define HFI_MASK_QHDR_TX_TYPE 0xFF000000
#define HFI_MASK_QHDR_RX_TYPE 0x00FF0000
#define HFI_MASK_QHDR_PRI_TYPE 0x0000FF00
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8c392fc..464f19f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -248,7 +248,7 @@
config MARIMBA_CORE
tristate "Marimba Core"
- depends on I2C && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A)
+ depends on I2C && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A || ARCH_MSM8960)
default n
help
Enables the Marimba Core driver. The core driver provides
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index 712a772..9815f6e 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -34,7 +34,7 @@
#define REG_IRQ_BASE 0x1BB
#define REG_SPK_BASE 0x253
-#define REG_SPK_REGISTERS 3
+#define REG_SPK_REGISTERS 6
#define REG_TEMP_ALARM_CTRL 0x01B
#define REG_TEMP_ALARM_PWM 0x09B
@@ -293,7 +293,7 @@
[0] = {
.name = PM8XXX_SPK_DEV_NAME,
.start = REG_SPK_BASE,
- .end = REG_SPK_BASE + REG_SPK_REGISTERS,
+ .end = REG_SPK_BASE + REG_SPK_REGISTERS - 1,
.flags = IORESOURCE_IO,
},
};
diff --git a/drivers/mfd/pm8xxx-spk.c b/drivers/mfd/pm8xxx-spk.c
index 7ce6b50..8ba7372 100644
--- a/drivers/mfd/pm8xxx-spk.c
+++ b/drivers/mfd/pm8xxx-spk.c
@@ -22,8 +22,11 @@
#include <linux/mfd/pm8xxx/spk.h>
#define PM8XXX_SPK_CTL1_REG_OFF 0
-#define PM8XXX_SPK_TEST_REG_1_OFF 1
-#define PM8XXX_SPK_TEST_REG_2_OFF 2
+#define PM8XXX_SPK_CTL2_REG_OFF 1
+#define PM8XXX_SPK_CTL3_REG_OFF 2
+#define PM8XXX_SPK_CTL4_REG_OFF 3
+#define PM8XXX_SPK_TEST_REG_1_OFF 4
+#define PM8XXX_SPK_TEST_REG_2_OFF 5
#define PM8XXX_SPK_BANK_SEL 4
#define PM8XXX_SPK_BANK_WRITE 0x80
@@ -194,6 +197,7 @@
{
const struct pm8xxx_spk_platform_data *pdata = pdev->dev.platform_data;
int ret = 0;
+ u8 value = 0;
if (!pdata) {
pr_err("missing platform data\n");
@@ -236,6 +240,23 @@
if (ret < 0)
goto err_handle;
}
+ value = ((the_spk_chip->pdata.cd_ng_threshold << 5) |
+ the_spk_chip->pdata.cd_nf_preamp_bias << 3);
+ pr_debug("Setting SPK_CTL2_REG = %02x\n", value);
+ pm8xxx_spk_write(PM8XXX_SPK_CTL2_REG_OFF, value);
+
+ value = ((the_spk_chip->pdata.cd_ng_hold << 5) |
+ (the_spk_chip->pdata.cd_ng_max_atten << 1) |
+ the_spk_chip->pdata.noise_mute);
+ pr_debug("Setting SPK_CTL3_REG = %02x\n", value);
+ pm8xxx_spk_write(PM8XXX_SPK_CTL3_REG_OFF, value);
+
+ value = ((the_spk_chip->pdata.cd_ng_decay_rate << 5) |
+ (the_spk_chip->pdata.cd_ng_attack_rate << 3) |
+ the_spk_chip->pdata.cd_delay << 2);
+ pr_debug("Setting SPK_CTL4_REG = %02x\n", value);
+ pm8xxx_spk_write(PM8XXX_SPK_CTL4_REG_OFF, value);
+
return pm8xxx_spk_config();
err_handle:
pr_err("pm8xxx_spk_probe failed."
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 35ae29a..0ea843c 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -253,6 +253,18 @@
},
};
+static struct wcd9xx_codec_type {
+ u8 byte[4];
+ struct mfd_cell *dev;
+ int size;
+} wcd9xxx_codecs[] = {
+ {{0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs)},
+ {{0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs)},
+ {{0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs)},
+ {{0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs)},
+ {{0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs)},
+};
+
static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
{
wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
@@ -298,6 +310,53 @@
wcd9xxx->reset_gpio = 0;
}
}
+static int wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx,
+ struct mfd_cell **wcd9xxx_dev,
+ int *wcd9xxx_dev_size)
+{
+ struct wcd9xx_codec_type *cdc = wcd9xxx_codecs;
+ int index;
+ int ret;
+ index = WCD9XXX_A_CHIP_ID_BYTE_0;
+ while (index <= WCD9XXX_A_CHIP_ID_BYTE_3) {
+ ret = wcd9xxx_reg_read(wcd9xxx, index);
+ if (ret < 0)
+ goto exit;
+ wcd9xxx->idbyte[index-WCD9XXX_A_CHIP_ID_BYTE_0] = (u8)ret;
+ pr_debug("%s: wcd9xx read = %x, byte = %x\n", __func__, ret,
+ index);
+ index++;
+ }
+
+ /* Read codec version */
+ ret = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
+ if (ret < 0)
+ goto exit;
+ wcd9xxx->version = (u8)ret & 0x1F;
+
+ while (cdc < (cdc + ARRAY_SIZE(wcd9xxx_codecs)) && cdc != NULL) {
+ if ((cdc->byte[0] == wcd9xxx->idbyte[0]) &&
+ (cdc->byte[1] == wcd9xxx->idbyte[1]) &&
+ (cdc->byte[2] == wcd9xxx->idbyte[2]) &&
+ (cdc->byte[3] == wcd9xxx->idbyte[3])) {
+ pr_info("%s: codec is %s", __func__, cdc->dev->name);
+ *wcd9xxx_dev = cdc->dev;
+ *wcd9xxx_dev_size = cdc->size;
+ break;
+ }
+ cdc++;
+ }
+ if (*wcd9xxx_dev == NULL || *wcd9xxx_dev_size == 0)
+ ret = -ENODEV;
+ pr_info("%s: Read codec idbytes & version\n"
+ "byte_0[%08x] byte_1[%08x] byte_2[%08x]\n"
+ " byte_3[%08x] version = %x\n", __func__,
+ wcd9xxx->idbyte[0], wcd9xxx->idbyte[1],
+ wcd9xxx->idbyte[2], wcd9xxx->idbyte[3],
+ wcd9xxx->version);
+exit:
+ return ret;
+}
static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx, int irq)
{
@@ -326,39 +385,11 @@
goto err;
}
}
+ ret = wcd9xxx_check_codec_type(wcd9xxx, &wcd9xxx_dev,
+ &wcd9xxx_dev_size);
- wcd9xxx->idbyte_0 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0);
- wcd9xxx->idbyte_1 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_1);
- wcd9xxx->idbyte_2 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2);
- wcd9xxx->idbyte_3 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_3);
-
- wcd9xxx->version = wcd9xxx_reg_read(wcd9xxx,
- WCD9XXX_A_CHIP_VERSION) & 0x1F;
- pr_info("%s : Codec version %u initialized\n",
- __func__, wcd9xxx->version);
- pr_info("idbyte_0[%08x] idbyte_1[%08x] idbyte_2[%08x] idbyte_3[%08x]\n",
- wcd9xxx->idbyte_0, wcd9xxx->idbyte_1,
- wcd9xxx->idbyte_2, wcd9xxx->idbyte_3);
-
- if (wcd9xxx->idbyte_0 == 0x2 && wcd9xxx->idbyte_1 == 0x0 &&
- wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) {
- wcd9xxx_dev = tabla_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
- } else if (wcd9xxx->idbyte_0 == 0x1 && wcd9xxx->idbyte_1 == 0x0 &&
- wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) {
- wcd9xxx_dev = tabla1x_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
- } else if (wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
- wcd9xxx->idbyte_2 == 0x2 && wcd9xxx->idbyte_3 == 0x1) {
- wcd9xxx_dev = taiko_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(taiko_devs);
- } else if ((wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
- wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) ||
- (wcd9xxx->idbyte_0 == 0x1 && wcd9xxx->idbyte_1 == 0x0 &&
- wcd9xxx->idbyte_2 == 0x1 && wcd9xxx->idbyte_3 == 0x1)) {
- wcd9xxx_dev = sitar_devs;
- wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
- }
+ if (ret < 0)
+ goto err_irq;
ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
NULL, 0);
if (ret != 0) {
@@ -772,9 +803,9 @@
goto err_device_init;
}
- if ((wcd9xxx->idbyte_0 == 0x2) || (wcd9xxx->idbyte_0 == 0x1))
+ if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
i2c_mode = TABLA_I2C_MODE;
- else if (wcd9xxx->idbyte_0 == 0x0)
+ else if (wcd9xxx->idbyte[0] == 0x0)
i2c_mode = SITAR_I2C_MODE;
ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 9b4f436..d6d209b 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -147,7 +147,6 @@
static int qsee_bw_count;
static int qsee_sfpb_bw_count;
-static struct clk *qseecom_bus_clk;
static uint32_t qsee_perf_client;
struct qseecom_registered_listener_list {
@@ -1201,11 +1200,6 @@
switch (clk_type) {
case CLK_DFAB:
- /* Check if the clk is valid */
- if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
- pr_warn("qseecom bus clock is null or error");
- return -EINVAL;
- }
mutex_lock(&qsee_bw_mutex);
if (!qsee_bw_count) {
ret = msm_bus_scale_client_update_request(
@@ -1247,11 +1241,6 @@
switch (clk_type) {
case CLK_DFAB:
- /* Check if the DFAB clk is valid */
- if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
- pr_warn("qseecom bus clock is null or error");
- return;
- }
mutex_lock(&qsee_bw_mutex);
if (qsee_bw_count > 0) {
if (qsee_bw_count-- == 1) {
@@ -1733,7 +1722,6 @@
uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
qsee_bw_count = 0;
- qseecom_bus_clk = NULL;
qsee_perf_client = 0;
rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
@@ -1801,17 +1789,8 @@
qsee_perf_client = msm_bus_scale_register_client(
qseecom_platform_support);
- if (!qsee_perf_client) {
+ if (!qsee_perf_client)
pr_err("Unable to register bus client\n");
- } else {
- qseecom_bus_clk = clk_get(class_dev, "bus_clk");
- if (IS_ERR(qseecom_bus_clk)) {
- qseecom_bus_clk = NULL;
- } else if (qseecom_bus_clk != NULL) {
- pr_debug("Enabled DFAB clock");
- clk_set_rate(qseecom_bus_clk, 64000000);
- }
- }
}
return 0;
@@ -1855,8 +1834,6 @@
static void __devexit qseecom_exit(void)
{
- clk_put(qseecom_bus_clk);
-
device_destroy(driver_class, qseecom_device_no);
class_destroy(driver_class);
unregister_chrdev_region(qseecom_device_no, 1);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index fe18a90..52fd5e8 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1159,15 +1159,16 @@
if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
*c |= MCI_CSPM_DATCMD;
- /* Check if AUTO CMD19 is required or not? */
- if (host->tuning_needed && host->en_auto_cmd19 &&
- !(host->mmc->ios.timing == MMC_TIMING_MMC_HS200)) {
-
+ /* Check if AUTO CMD19/CMD21 is required or not? */
+ if (host->tuning_needed &&
+ (host->en_auto_cmd19 || host->en_auto_cmd21)) {
/*
* For open ended block read operation (without CMD23),
- * AUTO_CMD19 bit should be set while sending the READ command.
+ * AUTO_CMD19/AUTO_CMD21 bit should be set while sending
+ * the READ command.
* For close ended block read operation (with CMD23),
- * AUTO_CMD19 bit should be set while sending CMD23.
+ * AUTO_CMD19/AUTO_CMD21 bit should be set while sending
+ * CMD23.
*/
if ((cmd->opcode == MMC_SET_BLOCK_COUNT &&
host->curr.mrq->cmd->opcode ==
@@ -1179,6 +1180,9 @@
if (host->en_auto_cmd19 &&
host->mmc->ios.timing == MMC_TIMING_UHS_SDR104)
*c |= MCI_CSPM_AUTO_CMD19;
+ else if (host->en_auto_cmd21 &&
+ host->mmc->ios.timing == MMC_TIMING_MMC_HS200)
+ *c |= MCI_CSPM_AUTO_CMD21;
}
}
@@ -4829,6 +4833,8 @@
spin_lock_irqsave(&host->lock, flags);
if (is_cmd19)
host->en_auto_cmd19 = !!temp;
+ else
+ host->en_auto_cmd21 = !!temp;
spin_unlock_irqrestore(&host->lock, flags);
}
}
@@ -4852,6 +4858,25 @@
return count;
}
+static ssize_t
+show_enable_auto_cmd21(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mmc_host *mmc = dev_get_drvdata(dev);
+ struct msmsdcc_host *host = mmc_priv(mmc);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", host->en_auto_cmd21);
+}
+
+static ssize_t
+store_enable_auto_cmd21(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ set_auto_cmd_setting(dev, buf, false);
+
+ return count;
+}
+
#ifdef CONFIG_HAS_EARLYSUSPEND
static void msmsdcc_early_suspend(struct early_suspend *h)
{
@@ -5998,7 +6023,7 @@
goto remove_polling_file;
if (!is_auto_cmd19(host))
- goto exit;
+ goto add_auto_cmd21_atrr;
/* Sysfs entry for AUTO CMD19 control */
host->auto_cmd19_attr.show = show_enable_auto_cmd19;
@@ -6010,9 +6035,26 @@
if (ret)
goto remove_idle_timeout_file;
+ add_auto_cmd21_atrr:
+ if (!is_auto_cmd21(host))
+ goto exit;
+
+ /* Sysfs entry for AUTO CMD21 control */
+ host->auto_cmd21_attr.show = show_enable_auto_cmd21;
+ host->auto_cmd21_attr.store = store_enable_auto_cmd21;
+ sysfs_attr_init(&host->auto_cmd21_attr.attr);
+ host->auto_cmd21_attr.attr.name = "enable_auto_cmd21";
+ host->auto_cmd21_attr.attr.mode = S_IRUGO | S_IWUSR;
+ ret = device_create_file(&pdev->dev, &host->auto_cmd21_attr);
+ if (ret)
+ goto remove_auto_cmd19_attr_file;
+
exit:
return 0;
+ remove_auto_cmd19_attr_file:
+ if (is_auto_cmd19(host))
+ device_remove_file(&pdev->dev, &host->auto_cmd19_attr);
remove_idle_timeout_file:
device_remove_file(&pdev->dev, &host->idle_timeout);
remove_polling_file:
@@ -6097,6 +6139,8 @@
if (is_auto_cmd19(host))
device_remove_file(&pdev->dev, &host->auto_cmd19_attr);
+ if (is_auto_cmd21(host))
+ device_remove_file(&pdev->dev, &host->auto_cmd21_attr);
device_remove_file(&pdev->dev, &host->max_bus_bw);
if (!plat->status_irq)
device_remove_file(&pdev->dev, &host->polling);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 30b1908..5779491 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -65,6 +65,7 @@
#define MCI_CSPM_CCSENABLE (1 << 14)
#define MCI_CSPM_CCSDISABLE (1 << 15)
#define MCI_CSPM_AUTO_CMD19 (1 << 16)
+#define MCI_CSPM_AUTO_CMD21 (1 << 21)
#define MMCIRESPCMD 0x010
@@ -402,6 +403,7 @@
bool tuning_in_progress;
bool tuning_needed;
bool en_auto_cmd19;
+ bool en_auto_cmd21;
bool sdio_gpio_lpm;
bool irq_wake_enabled;
struct pm_qos_request pm_qos_req_dma;
@@ -419,9 +421,14 @@
struct device_attribute polling;
struct device_attribute idle_timeout;
struct device_attribute auto_cmd19_attr;
+ struct device_attribute auto_cmd21_attr;
};
-#define MSMSDCC_VERSION_MASK 0xFFFF
+#define MSMSDCC_VERSION_STEP_MASK 0x0000FFFF
+#define MSMSDCC_VERSION_MINOR_MASK 0x0FFF0000
+#define MSMSDCC_VERSION_MINOR_SHIFT 16
+#define MSMSDCC_VERSION_MAJOR_MASK 0xF0000000
+#define MSMSDCC_VERSION_MAJOR_SHIFT 28
#define MSMSDCC_DMA_SUP (1 << 0)
#define MSMSDCC_SPS_BAM_SUP (1 << 1)
#define MSMSDCC_SOFT_RESET (1 << 2)
@@ -432,6 +439,7 @@
#define MSMSDCC_WAIT_FOR_TX_RX (1 << 7)
#define MSMSDCC_IO_PAD_PWR_SWITCH (1 << 8)
#define MSMSDCC_AUTO_CMD19 (1 << 9)
+#define MSMSDCC_AUTO_CMD21 (1 << 10)
#define set_hw_caps(h, val) ((h)->hw_caps |= val)
#define is_sps_mode(h) ((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -444,11 +452,14 @@
#define is_wait_for_tx_rx_active(h) ((h)->hw_caps & MSMSDCC_WAIT_FOR_TX_RX)
#define is_io_pad_pwr_switch(h) ((h)->hw_caps & MSMSDCC_IO_PAD_PWR_SWITCH)
#define is_auto_cmd19(h) ((h)->hw_caps & MSMSDCC_AUTO_CMD19)
+#define is_auto_cmd21(h) ((h)->hw_caps & MSMSDCC_AUTO_CMD21)
/* Set controller capabilities based on version */
static inline void set_default_hw_caps(struct msmsdcc_host *host)
{
u32 version;
+ u16 step, minor;
+
/*
* Lookup the Controller Version, to identify the supported features
* Version number read as 0 would indicate SDCC3 or earlier versions.
@@ -459,15 +470,21 @@
if (!version)
return;
- version &= MSMSDCC_VERSION_MASK;
+ step = version & MSMSDCC_VERSION_STEP_MASK;
+ minor = (version & MSMSDCC_VERSION_MINOR_MASK) >>
+ MSMSDCC_VERSION_MINOR_SHIFT;
+
if (version) /* SDCC v4 and greater */
host->hw_caps |= MSMSDCC_AUTO_PROG_DONE |
MSMSDCC_SOFT_RESET | MSMSDCC_REG_WR_ACTIVE
| MSMSDCC_WAIT_FOR_TX_RX | MSMSDCC_IO_PAD_PWR_SWITCH
| MSMSDCC_AUTO_CMD19;
- if (version >= 0x2D) /* SDCC v4 2.1.0 and greater */
- host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_SW_RST_CFG;
+ if ((step == 0x18) && (minor >= 3))
+ host->hw_caps |= MSMSDCC_AUTO_CMD21;
+
+ if (version >= 0x2b) /* SDCC v4 2.1.0 and greater */
+ host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_AUTO_CMD21;
}
int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index a263750..d8baa29 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -415,6 +415,14 @@
help
Say Y here to enable support for pm8921 chip bms subdevice
+config BATTERY_BCL
+ tristate "Battery Current Limit driver"
+ help
+ Say Y here to enable support for battery current limit
+ device. The BCL driver will poll BMS if
+ thermal daemon enables BCL.
+ It will notify thermal daemon if IBat crosses Imax threshold.
+
config CHARGER_SMB347
tristate "Summit Microelectronics SMB347 Battery Charger"
depends on I2C
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 007d75b..f84b527 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -58,3 +58,4 @@
obj-$(CONFIG_PM8921_CHARGER) += pm8921-charger.o
obj-$(CONFIG_LTC4088_CHARGER) += ltc4088-charger.o
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
+obj-$(CONFIG_BATTERY_BCL) += battery_current_limit.o
diff --git a/drivers/power/battery_current_limit.c b/drivers/power/battery_current_limit.c
new file mode 100644
index 0000000..d1750ec
--- /dev/null
+++ b/drivers/power/battery_current_limit.c
@@ -0,0 +1,534 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/power_supply.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#define BCL_DEV_NAME "battery_current_limit"
+#define BCL_NAME_LENGTH 20
+/*
+ * Default BCL poll interval 1000 msec
+ */
+#define BCL_POLL_INTERVAL 1000
+/*
+ * Mininum BCL poll interval 10 msec
+ */
+#define MIN_BCL_POLL_INTERVAL 10
+
+static const char bcl_type[] = "bcl";
+
+/*
+ * Battery Current Limit Enable or Not
+ */
+enum bcl_device_mode {
+ BCL_DEVICE_DISABLED = 0,
+ BCL_DEVICE_ENABLED,
+};
+
+/*
+ * Battery Current Limit IBat Imax Threshold Mode
+ */
+enum bcl_ibat_imax_threshold_mode {
+ BCL_IBAT_IMAX_THRESHOLD_DISABLED = 0,
+ BCL_IBAT_IMAX_THRESHOLD_ENABLED,
+};
+
+/*
+ * Battery Current Limit Ibat Imax Trip Type (High and Low Threshold)
+ */
+enum bcl_ibat_imax_threshold_type {
+ BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW = 0,
+ BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH,
+ BCL_IBAT_IMAX_THRESHOLD_TYPE_MAX,
+};
+
+/**
+ * BCL control block
+ *
+ */
+struct bcl_context {
+ /* BCL device */
+ struct device *dev;
+
+ /* BCL related config parameter */
+ /* BCL mode enable or not */
+ enum bcl_device_mode bcl_mode;
+ /* BCL Ibat/IMax Threshold Activate or Not */
+ enum bcl_ibat_imax_threshold_mode
+ bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_MAX];
+ /* BCL Ibat/IMax Threshold value in milli Amp */
+ int bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_MAX];
+ /* BCL Type */
+ char bcl_type[BCL_NAME_LENGTH];
+ /* BCL poll in usec */
+ int bcl_poll_interval_msec;
+
+ /* BCL realtime value based on poll */
+ /* BCL realtime ibat in milli Amp*/
+ int bcl_ibat_ma;
+ /* BCL realtime calculated imax in milli Amp*/
+ int bcl_imax_ma;
+ /* BCL realtime calculated ocv in uV*/
+ int bcl_ocv_uv;
+ /* BCL realtime vbat in mV*/
+ int bcl_vbat_mv;
+ /* BCL realtime rbat in mOhms*/
+ int bcl_rbat;
+ /* BCL period poll delay work structure */
+ struct delayed_work bcl_imax_work;
+
+};
+
+static struct bcl_context *gbcl;
+
+/*
+ * BCL imax calculation and trigger notification to user space
+ * if imax cross threshold
+ */
+static void bcl_calculate_imax_trigger(void)
+{
+ int ibatt_ua, vbatt_uv;
+ int imax_ma;
+ int ibatt_ma, vbatt_mv;
+ int imax_low_threshold;
+ int imax_high_threshold;
+ bool threshold_cross = false;
+ union power_supply_propval ret = {0,};
+ static struct power_supply *psy;
+
+ if (!gbcl) {
+ pr_err("called before initialization\n");
+ return;
+ }
+
+ if (psy == NULL) {
+ psy = power_supply_get_by_name("battery");
+ if (psy == NULL)
+ return;
+ }
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &ret))
+ return;
+ ibatt_ua = ret.intval;
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &ret))
+ return;
+ vbatt_uv = ret.intval;
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &ret))
+ return;
+ imax_ma = ret.intval/1000;
+
+ ibatt_ma = ibatt_ua/1000;
+ vbatt_mv = vbatt_uv/1000;
+
+ gbcl->bcl_ibat_ma = ibatt_ma;
+ gbcl->bcl_imax_ma = imax_ma;
+ gbcl->bcl_vbat_mv = vbatt_mv;
+
+ if (gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+ == BCL_IBAT_IMAX_THRESHOLD_ENABLED) {
+ imax_high_threshold =
+ imax_ma - gbcl->bcl_threshold_value_ma
+ [BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH];
+ if (ibatt_ma >= imax_high_threshold)
+ threshold_cross = true;
+ }
+
+ if (gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+ == BCL_IBAT_IMAX_THRESHOLD_ENABLED) {
+ imax_low_threshold =
+ imax_ma - gbcl->bcl_threshold_value_ma
+ [BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW];
+ if (ibatt_ma <= imax_low_threshold)
+ threshold_cross = true;
+ }
+
+ if (threshold_cross) {
+ sysfs_notify(&gbcl->dev->kobj,
+ NULL, "type");
+ }
+}
+
+/*
+ * BCL imax work
+ */
+static void bcl_imax_work(struct work_struct *work)
+{
+ struct bcl_context *bcl = container_of(work,
+ struct bcl_context, bcl_imax_work.work);
+
+ if (gbcl->bcl_mode == BCL_DEVICE_ENABLED) {
+ bcl_calculate_imax_trigger();
+ /* restart the delay work for caculating imax */
+ schedule_delayed_work(&bcl->bcl_imax_work,
+ round_jiffies_relative(msecs_to_jiffies
+ (bcl->bcl_poll_interval_msec)));
+ }
+}
+
+/*
+ * Set BCL mode
+ */
+static void bcl_mode_set(enum bcl_device_mode mode)
+{
+ if (!gbcl)
+ return;
+
+ if (gbcl->bcl_mode == mode)
+ return;
+
+ if (gbcl->bcl_mode == BCL_DEVICE_DISABLED
+ && mode == BCL_DEVICE_ENABLED) {
+ gbcl->bcl_mode = mode;
+ bcl_imax_work(&(gbcl->bcl_imax_work.work));
+ return;
+ } else if (gbcl->bcl_mode == BCL_DEVICE_ENABLED
+ && mode == BCL_DEVICE_DISABLED) {
+ gbcl->bcl_mode = mode;
+ cancel_delayed_work_sync(&(gbcl->bcl_imax_work));
+ return;
+ }
+
+ return;
+}
+
+#define show_bcl(name, variable, format) \
+static ssize_t \
+name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ if (gbcl) \
+ return snprintf(buf, PAGE_SIZE, format, gbcl->variable); \
+ else \
+ return -EPERM; \
+}
+
+show_bcl(type, bcl_type, "%s\n")
+show_bcl(ibat, bcl_ibat_ma, "%d\n")
+show_bcl(imax, bcl_imax_ma, "%d\n")
+show_bcl(vbat, bcl_vbat_mv, "%d\n")
+show_bcl(rbat, bcl_rbat, "%d\n")
+show_bcl(ocv, bcl_ocv_uv, "%d\n")
+show_bcl(poll_interval, bcl_poll_interval_msec, "%d\n")
+
+static ssize_t
+mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ if (!gbcl)
+ return -EPERM;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ gbcl->bcl_mode == BCL_DEVICE_ENABLED ? "enabled"
+ : "disabled");
+}
+
+static ssize_t
+mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (!gbcl)
+ return -EPERM;
+
+ if (!strncmp(buf, "enabled", 7))
+ bcl_mode_set(BCL_DEVICE_ENABLED);
+ else if (!strncmp(buf, "disabled", 8))
+ bcl_mode_set(BCL_DEVICE_DISABLED);
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t
+ibat_imax_low_threshold_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (!gbcl)
+ return -EPERM;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+ == BCL_IBAT_IMAX_THRESHOLD_ENABLED ? "enabled" : "disabled");
+}
+
+static ssize_t
+ibat_imax_low_threshold_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (!gbcl)
+ return -EPERM;
+
+ if (!strncmp(buf, "enabled", 7))
+ gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+ = BCL_IBAT_IMAX_THRESHOLD_ENABLED;
+ else if (!strncmp(buf, "disabled", 8))
+ gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+ = BCL_IBAT_IMAX_THRESHOLD_DISABLED;
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t
+ibat_imax_low_threshold_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (!gbcl)
+ return -EPERM;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ gbcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]);
+}
+
+static ssize_t
+ibat_imax_low_threshold_value_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int value;
+
+ if (!gbcl)
+ return -EPERM;
+
+ if (!sscanf(buf, "%d", &value))
+ return -EINVAL;
+
+ if (value < 0)
+ return -EINVAL;
+
+ gbcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+ = value;
+
+ return count;
+}
+
+static ssize_t
+ibat_imax_high_threshold_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (!gbcl)
+ return -EPERM;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+ == BCL_IBAT_IMAX_THRESHOLD_ENABLED ? "enabled" : "disabled");
+}
+
+static ssize_t
+ibat_imax_high_threshold_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (!gbcl)
+ return -EPERM;
+
+ if (!strncmp(buf, "enabled", 7))
+ gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+ = BCL_IBAT_IMAX_THRESHOLD_ENABLED;
+ else if (!strncmp(buf, "disabled", 8))
+ gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+ = BCL_IBAT_IMAX_THRESHOLD_DISABLED;
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t
+ibat_imax_high_threshold_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (!gbcl)
+ return -EPERM;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ gbcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]);
+}
+
+static ssize_t
+ibat_imax_high_threshold_value_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int value;
+
+ if (!gbcl)
+ return -EPERM;
+
+ if (!sscanf(buf, "%d", &value))
+ return -EINVAL;
+
+ if (value < 0)
+ return -EINVAL;
+
+ gbcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+ = value;
+
+ return count;
+}
+
+static ssize_t
+poll_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int value;
+
+ if (!gbcl)
+ return -EPERM;
+
+ if (!sscanf(buf, "%d", &value))
+ return -EINVAL;
+
+ if (value < MIN_BCL_POLL_INTERVAL)
+ return -EINVAL;
+
+ gbcl->bcl_poll_interval_msec = value;
+
+ return count;
+}
+
+/*
+ * BCL device attributes
+ */
+static struct device_attribute bcl_dev_attr[] = {
+ __ATTR(type, 0444, type_show, NULL),
+ __ATTR(ibat, 0444, ibat_show, NULL),
+ __ATTR(vbat, 0444, vbat_show, NULL),
+ __ATTR(rbat, 0444, rbat_show, NULL),
+ __ATTR(ocv, 0444, ocv_show, NULL),
+ __ATTR(imax, 0444, imax_show, NULL),
+ __ATTR(mode, 0644, mode_show, mode_store),
+ __ATTR(poll_interval, 0644,
+ poll_interval_show, poll_interval_store),
+ __ATTR(ibat_imax_low_threshold_mode, 0644,
+ ibat_imax_low_threshold_mode_show,
+ ibat_imax_low_threshold_mode_store),
+ __ATTR(ibat_imax_high_threshold_mode, 0644,
+ ibat_imax_high_threshold_mode_show,
+ ibat_imax_high_threshold_mode_store),
+ __ATTR(ibat_imax_low_threshold_value, 0644,
+ ibat_imax_low_threshold_value_show,
+ ibat_imax_low_threshold_value_store),
+ __ATTR(ibat_imax_high_threshold_value, 0644,
+ ibat_imax_high_threshold_value_show,
+ ibat_imax_high_threshold_value_store)
+};
+
+static int create_bcl_sysfs(struct bcl_context *bcl)
+{
+ int result = 0;
+ int num_attr = sizeof(bcl_dev_attr)/sizeof(struct device_attribute);
+ int i;
+
+ for (i = 0; i < num_attr; i++) {
+ result = device_create_file(bcl->dev, &bcl_dev_attr[i]);
+ if (result < 0)
+ return result;
+ }
+
+ return 0;
+}
+
+static void remove_bcl_sysfs(struct bcl_context *bcl)
+{
+ int num_attr = sizeof(bcl_dev_attr)/sizeof(struct device_attribute);
+ int i;
+
+ for (i = 0; i < num_attr; i++)
+ device_remove_file(bcl->dev, &bcl_dev_attr[i]);
+
+ return;
+}
+
+static int __devinit bcl_probe(struct platform_device *pdev)
+{
+ struct bcl_context *bcl;
+ int ret = 0;
+
+ bcl = kzalloc(sizeof(struct bcl_context), GFP_KERNEL);
+
+ if (!bcl) {
+ pr_err("Cannot allocate bcl_context\n");
+ return -ENOMEM;
+ }
+
+ gbcl = bcl;
+
+ /* For BCL */
+ /* Init default BCL params */
+ bcl->dev = &pdev->dev;
+ bcl->bcl_mode = BCL_DEVICE_DISABLED;
+ bcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+ = BCL_IBAT_IMAX_THRESHOLD_DISABLED;
+ bcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+ = BCL_IBAT_IMAX_THRESHOLD_DISABLED;
+ bcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW] = 0;
+ bcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH] = 0;
+ snprintf(bcl->bcl_type, BCL_NAME_LENGTH, "%s", bcl_type);
+ bcl->bcl_poll_interval_msec = BCL_POLL_INTERVAL;
+ ret = create_bcl_sysfs(bcl);
+ if (ret < 0) {
+ pr_err("Cannot create bcl sysfs\n");
+ kfree(bcl);
+ return ret;
+ }
+ platform_set_drvdata(pdev, bcl);
+ INIT_DELAYED_WORK(&bcl->bcl_imax_work, bcl_imax_work);
+
+ return 0;
+}
+
+static int __devexit bcl_remove(struct platform_device *pdev)
+{
+ remove_bcl_sysfs(gbcl);
+ kfree(gbcl);
+ gbcl = NULL;
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static struct platform_driver bcl_driver = {
+ .probe = bcl_probe,
+ .remove = __devexit_p(bcl_remove),
+ .driver = {
+ .name = BCL_DEV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init bcl_init(void)
+{
+ return platform_driver_register(&bcl_driver);
+}
+
+static void __exit bcl_exit(void)
+{
+ platform_driver_unregister(&bcl_driver);
+}
+
+late_initcall(bcl_init);
+module_exit(bcl_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("battery current limit driver");
+MODULE_ALIAS("platform:" BCL_DEV_NAME);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index d2227dc..813e40a 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1357,6 +1357,7 @@
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_ENERGY_FULL,
@@ -1418,6 +1419,36 @@
return percent_soc;
}
+static int get_prop_batt_current_max(struct pm8921_chg_chip *chip)
+{
+ int rbatt, ibatt_ua, vbatt_uv, ocv_uv;
+ int imax_ma;
+ int rc;
+
+ rbatt = pm8921_bms_get_rbatt();
+
+ if (rbatt < 0) {
+ rc = -ENXIO;
+ return rc;
+ }
+
+ rc = pm8921_bms_get_simultaneous_battery_voltage_and_current
+ (&ibatt_ua, &vbatt_uv);
+
+ if (rc)
+ return rc;
+
+ ocv_uv = vbatt_uv + ibatt_ua*rbatt/1000;
+
+ imax_ma = (ocv_uv - chip->min_voltage_mv*1000)/rbatt;
+
+ if (imax_ma < 0)
+ imax_ma = 0;
+
+ return imax_ma*1000;
+
+}
+
static int get_prop_batt_current(struct pm8921_chg_chip *chip)
{
int result_ua, rc;
@@ -1571,6 +1602,9 @@
case POWER_SUPPLY_PROP_CURRENT_NOW:
val->intval = get_prop_batt_current(chip);
break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = get_prop_batt_current_max(chip);
+ break;
case POWER_SUPPLY_PROP_TEMP:
val->intval = get_prop_batt_temp(chip);
break;
diff --git a/drivers/slimbus/Makefile b/drivers/slimbus/Makefile
index 436822d..674f057 100644
--- a/drivers/slimbus/Makefile
+++ b/drivers/slimbus/Makefile
@@ -2,4 +2,4 @@
# Makefile for kernel slimbus framework.
#
obj-$(CONFIG_SLIMBUS) += slimbus.o
-obj-$(CONFIG_SLIMBUS_MSM_CTRL) += slim-msm-ctrl.o
+obj-$(CONFIG_SLIMBUS_MSM_CTRL) += slim-msm.o slim-msm-ctrl.o
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 556e3ea..6cddf2d 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -16,7 +16,6 @@
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
#include <linux/slimbus/slimbus.h>
#include <linux/delay.h>
#include <linux/kthread.h>
@@ -26,61 +25,11 @@
#include <linux/of_slimbus.h>
#include <mach/sps.h>
#include <mach/qdsp6v2/apr.h>
-
-/* Per spec.max 40 bytes per received message */
-#define SLIM_RX_MSGQ_BUF_LEN 40
-
-#define SLIM_USR_MC_GENERIC_ACK 0x25
-#define SLIM_USR_MC_MASTER_CAPABILITY 0x0
-#define SLIM_USR_MC_REPORT_SATELLITE 0x1
-#define SLIM_USR_MC_ADDR_QUERY 0xD
-#define SLIM_USR_MC_ADDR_REPLY 0xE
-#define SLIM_USR_MC_DEFINE_CHAN 0x20
-#define SLIM_USR_MC_DEF_ACT_CHAN 0x21
-#define SLIM_USR_MC_CHAN_CTRL 0x23
-#define SLIM_USR_MC_RECONFIG_NOW 0x24
-#define SLIM_USR_MC_REQ_BW 0x28
-#define SLIM_USR_MC_CONNECT_SRC 0x2C
-#define SLIM_USR_MC_CONNECT_SINK 0x2D
-#define SLIM_USR_MC_DISCONNECT_PORT 0x2E
-
-/* MSM Slimbus peripheral settings */
-#define MSM_SLIM_PERF_SUMM_THRESHOLD 0x8000
-#define MSM_SLIM_NCHANS 32
-#define MSM_SLIM_NPORTS 24
-#define MSM_SLIM_AUTOSUSPEND MSEC_PER_SEC
-
-/*
- * Need enough descriptors to receive present messages from slaves
- * if received simultaneously. Present message needs 3 descriptors
- * and this size will ensure around 10 simultaneous reports.
- */
-#define MSM_SLIM_DESC_NUM 32
-
-#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
- ((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
+#include "slim-msm.h"
#define MSM_SLIM_NAME "msm_slim_ctrl"
#define SLIM_ROOT_FREQ 24576000
-#define MSM_CONCUR_MSG 8
-#define SAT_CONCUR_MSG 8
-#define DEF_WATERMARK (8 << 1)
-#define DEF_ALIGN 0
-#define DEF_PACK (1 << 6)
-#define ENABLE_PORT 1
-
-#define DEF_BLKSZ 0
-#define DEF_TRANSZ 0
-
-#define SAT_MAGIC_LSB 0xD9
-#define SAT_MAGIC_MSB 0xC5
-#define SAT_MSG_VER 0x1
-#define SAT_MSG_PROT 0x1
-#define MSM_SAT_SUCCSS 0x20
-#define MSM_MAX_NSATS 2
-#define MSM_MAX_SATCH 32
-
#define QC_MFGID_LSB 0x2
#define QC_MFGID_MSB 0x17
#define QC_CHIPID_SL 0x10
@@ -91,82 +40,6 @@
#define INIT_MX_RETRIES 10
#define DEF_RETRY_MS 10
-#define PGD_THIS_EE(r, v) ((v) ? PGD_THIS_EE_V2(r) : PGD_THIS_EE_V1(r))
-#define PGD_PORT(r, p, v) ((v) ? PGD_PORT_V2(r, p) : PGD_PORT_V1(r, p))
-#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r))
-
-#define PGD_THIS_EE_V2(r) (dev->base + (r ## _V2) + (dev->ee * 0x1000))
-#define PGD_PORT_V2(r, p) (dev->base + (r ## _V2) + ((p) * 0x1000))
-#define CFG_PORT_V2(r) ((r ## _V2))
-/* Component registers */
-enum comp_reg_v2 {
- COMP_CFG_V2 = 4,
- COMP_TRUST_CFG_V2 = 0x3000,
-};
-
-/* Manager PGD registers */
-enum pgd_reg_v2 {
- PGD_CFG_V2 = 0x800,
- PGD_STAT_V2 = 0x804,
- PGD_INT_EN_V2 = 0x810,
- PGD_INT_STAT_V2 = 0x814,
- PGD_INT_CLR_V2 = 0x818,
- PGD_OWN_EEn_V2 = 0x300C,
- PGD_PORT_INT_EN_EEn_V2 = 0x5000,
- PGD_PORT_INT_ST_EEn_V2 = 0x5004,
- PGD_PORT_INT_CL_EEn_V2 = 0x5008,
- PGD_PORT_CFGn_V2 = 0x14000,
- PGD_PORT_STATn_V2 = 0x14004,
- PGD_PORT_PARAMn_V2 = 0x14008,
- PGD_PORT_BLKn_V2 = 0x1400C,
- PGD_PORT_TRANn_V2 = 0x14010,
- PGD_PORT_MCHANn_V2 = 0x14014,
- PGD_PORT_PSHPLLn_V2 = 0x14018,
- PGD_PORT_PC_CFGn_V2 = 0x8000,
- PGD_PORT_PC_VALn_V2 = 0x8004,
- PGD_PORT_PC_VFR_TSn_V2 = 0x8008,
- PGD_PORT_PC_VFR_STn_V2 = 0x800C,
- PGD_PORT_PC_VFR_CLn_V2 = 0x8010,
- PGD_IE_STAT_V2 = 0x820,
- PGD_VE_STAT_V2 = 0x830,
-};
-
-#define PGD_THIS_EE_V1(r) (dev->base + (r ## _V1) + (dev->ee * 16))
-#define PGD_PORT_V1(r, p) (dev->base + (r ## _V1) + ((p) * 32))
-#define CFG_PORT_V1(r) ((r ## _V1))
-/* Component registers */
-enum comp_reg_v1 {
- COMP_CFG_V1 = 0,
- COMP_TRUST_CFG_V1 = 0x14,
-};
-
-/* Manager PGD registers */
-enum pgd_reg_v1 {
- PGD_CFG_V1 = 0x1000,
- PGD_STAT_V1 = 0x1004,
- PGD_INT_EN_V1 = 0x1010,
- PGD_INT_STAT_V1 = 0x1014,
- PGD_INT_CLR_V1 = 0x1018,
- PGD_OWN_EEn_V1 = 0x1020,
- PGD_PORT_INT_EN_EEn_V1 = 0x1030,
- PGD_PORT_INT_ST_EEn_V1 = 0x1034,
- PGD_PORT_INT_CL_EEn_V1 = 0x1038,
- PGD_PORT_CFGn_V1 = 0x1080,
- PGD_PORT_STATn_V1 = 0x1084,
- PGD_PORT_PARAMn_V1 = 0x1088,
- PGD_PORT_BLKn_V1 = 0x108C,
- PGD_PORT_TRANn_V1 = 0x1090,
- PGD_PORT_MCHANn_V1 = 0x1094,
- PGD_PORT_PSHPLLn_V1 = 0x1098,
- PGD_PORT_PC_CFGn_V1 = 0x1600,
- PGD_PORT_PC_VALn_V1 = 0x1604,
- PGD_PORT_PC_VFR_TSn_V1 = 0x1608,
- PGD_PORT_PC_VFR_STn_V1 = 0x160C,
- PGD_PORT_PC_VFR_CLn_V1 = 0x1610,
- PGD_IE_STAT_V1 = 0x1700,
- PGD_VE_STAT_V1 = 0x1710,
-};
-
/* Manager registers */
enum mgr_reg {
MGR_CFG = 0x200,
@@ -217,12 +90,6 @@
INTF_VE_STAT = 0x640,
};
-enum rsc_grp {
- EE_MGR_RSC_GRP = 1 << 10,
- EE_NGD_2 = 2 << 6,
- EE_NGD_1 = 0,
-};
-
enum mgr_intr {
MGR_INT_RECFG_DONE = 1 << 24,
MGR_INT_TX_NACKED_2 = 1 << 25,
@@ -239,118 +106,8 @@
INTR_WAKE = 19,
};
-enum msm_ctrl_state {
- MSM_CTRL_AWAKE,
- MSM_CTRL_SLEEPING,
- MSM_CTRL_ASLEEP,
-};
-
-struct msm_slim_sps_bam {
- u32 hdl;
- void __iomem *base;
- int irq;
-};
-
-struct msm_slim_endp {
- struct sps_pipe *sps;
- struct sps_connect config;
- struct sps_register_event event;
- struct sps_mem_buffer buf;
- struct completion *xcomp;
- bool connected;
-};
-
-struct msm_slim_ctrl {
- struct slim_controller ctrl;
- struct slim_framer framer;
- struct device *dev;
- void __iomem *base;
- struct resource *slew_mem;
- u32 curr_bw;
- u8 msg_cnt;
- u32 tx_buf[10];
- u8 rx_msgs[MSM_CONCUR_MSG][SLIM_RX_MSGQ_BUF_LEN];
- spinlock_t rx_lock;
- int head;
- int tail;
- int irq;
- int err;
- int ee;
- struct completion *wr_comp;
- struct msm_slim_sat *satd[MSM_MAX_NSATS];
- struct msm_slim_endp pipes[7];
- struct msm_slim_sps_bam bam;
- struct msm_slim_endp rx_msgq;
- struct completion rx_msgq_notify;
- struct task_struct *rx_msgq_thread;
- struct clk *rclk;
- struct clk *hclk;
- struct mutex tx_lock;
- u8 pgdla;
- bool use_rx_msgqs;
- int pipe_b;
- struct completion reconf;
- bool reconf_busy;
- bool chan_active;
- enum msm_ctrl_state state;
- int nsats;
- u32 ver;
-};
-
-struct msm_sat_chan {
- u8 chan;
- u16 chanh;
- int req_rem;
- int req_def;
- bool reconf;
-};
-
-struct msm_slim_sat {
- struct slim_device satcl;
- struct msm_slim_ctrl *dev;
- struct workqueue_struct *wq;
- struct work_struct wd;
- u8 sat_msgs[SAT_CONCUR_MSG][40];
- struct msm_sat_chan *satch;
- u8 nsatch;
- bool sent_capability;
- bool pending_reconf;
- bool pending_capability;
- int shead;
- int stail;
- spinlock_t lock;
-};
-
static struct msm_slim_sat *msm_slim_alloc_sat(struct msm_slim_ctrl *dev);
-static int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len)
-{
- spin_lock(&dev->rx_lock);
- if ((dev->tail + 1) % MSM_CONCUR_MSG == dev->head) {
- spin_unlock(&dev->rx_lock);
- dev_err(dev->dev, "RX QUEUE full!");
- return -EXFULL;
- }
- memcpy((u8 *)dev->rx_msgs[dev->tail], (u8 *)buf, len);
- dev->tail = (dev->tail + 1) % MSM_CONCUR_MSG;
- spin_unlock(&dev->rx_lock);
- return 0;
-}
-
-static int msm_slim_rx_dequeue(struct msm_slim_ctrl *dev, u8 *buf)
-{
- unsigned long flags;
- spin_lock_irqsave(&dev->rx_lock, flags);
- if (dev->tail == dev->head) {
- spin_unlock_irqrestore(&dev->rx_lock, flags);
- return -ENODATA;
- }
- memcpy(buf, (u8 *)dev->rx_msgs[dev->head], 40);
- dev->head = (dev->head + 1) % MSM_CONCUR_MSG;
- spin_unlock_irqrestore(&dev->rx_lock, flags);
- return 0;
-}
-
static int msm_sat_enqueue(struct msm_slim_sat *sat, u32 *buf, u8 len)
{
struct msm_slim_ctrl *dev = sat->dev;
@@ -399,36 +156,6 @@
return false;
}
-static int msm_slim_get_ctrl(struct msm_slim_ctrl *dev)
-{
-#ifdef CONFIG_PM_RUNTIME
- int ref = 0;
- int ret = pm_runtime_get_sync(dev->dev);
- if (ret >= 0) {
- ref = atomic_read(&dev->dev->power.usage_count);
- if (ref <= 0) {
- dev_err(dev->dev, "reference count -ve:%d", ref);
- ret = -ENODEV;
- }
- }
- return ret;
-#else
- return -ENODEV;
-#endif
-}
-static void msm_slim_put_ctrl(struct msm_slim_ctrl *dev)
-{
-#ifdef CONFIG_PM_RUNTIME
- int ref;
- pm_runtime_mark_last_busy(dev->dev);
- ref = atomic_read(&dev->dev->power.usage_count);
- if (ref <= 0)
- dev_err(dev->dev, "reference count mismatch:%d", ref);
- else
- pm_runtime_put(dev->dev);
-#endif
-}
-
static struct msm_slim_sat *addr_to_sat(struct msm_slim_ctrl *dev, u8 laddr)
{
struct msm_slim_sat *sat = NULL;
@@ -622,159 +349,6 @@
return IRQ_HANDLED;
}
-static int
-msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep)
-{
- int ret;
- struct sps_pipe *endpoint;
- struct sps_connect *config = &ep->config;
-
- /* Allocate the endpoint */
- endpoint = sps_alloc_endpoint();
- if (!endpoint) {
- dev_err(dev->dev, "sps_alloc_endpoint failed\n");
- return -ENOMEM;
- }
-
- /* Get default connection configuration for an endpoint */
- ret = sps_get_config(endpoint, config);
- if (ret) {
- dev_err(dev->dev, "sps_get_config failed 0x%x\n", ret);
- goto sps_config_failed;
- }
-
- ep->sps = endpoint;
- return 0;
-
-sps_config_failed:
- sps_free_endpoint(endpoint);
- return ret;
-}
-
-static void
-msm_slim_free_endpoint(struct msm_slim_endp *ep)
-{
- sps_free_endpoint(ep->sps);
- ep->sps = NULL;
-}
-
-static int msm_slim_sps_mem_alloc(
- struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem, u32 len)
-{
- dma_addr_t phys;
-
- mem->size = len;
- mem->min_size = 0;
- mem->base = dma_alloc_coherent(dev->dev, mem->size, &phys, GFP_KERNEL);
-
- if (!mem->base) {
- dev_err(dev->dev, "dma_alloc_coherent(%d) failed\n", len);
- return -ENOMEM;
- }
-
- mem->phys_base = phys;
- memset(mem->base, 0x00, mem->size);
- return 0;
-}
-
-static void
-msm_slim_sps_mem_free(struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem)
-{
- dma_free_coherent(dev->dev, mem->size, mem->base, mem->phys_base);
- mem->size = 0;
- mem->base = NULL;
- mem->phys_base = 0;
-}
-
-static void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn)
-{
- u32 set_cfg = DEF_WATERMARK | DEF_ALIGN | DEF_PACK | ENABLE_PORT;
- u32 int_port = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
- dev->ver));
- writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pn, dev->ver));
- writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pn, dev->ver));
- writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pn, dev->ver));
- writel_relaxed((int_port | 1 << pn) , PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
- dev->ver));
- /* Make sure that port registers are updated before returning */
- mb();
-}
-
-static int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
-{
- struct msm_slim_endp *endpoint = &dev->pipes[pn];
- struct sps_connect *cfg = &endpoint->config;
- u32 stat;
- int ret = sps_get_config(dev->pipes[pn].sps, cfg);
- if (ret) {
- dev_err(dev->dev, "sps pipe-port get config error%x\n", ret);
- return ret;
- }
- cfg->options = SPS_O_DESC_DONE | SPS_O_ERROR |
- SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
-
- if (dev->pipes[pn].connected) {
- ret = sps_set_config(dev->pipes[pn].sps, cfg);
- if (ret) {
- dev_err(dev->dev, "sps pipe-port set config erro:%x\n",
- ret);
- return ret;
- }
- }
-
- stat = readl_relaxed(PGD_PORT(PGD_PORT_STATn, (pn + dev->pipe_b),
- dev->ver));
- if (dev->ctrl.ports[pn].flow == SLIM_SRC) {
- cfg->destination = dev->bam.hdl;
- cfg->source = SPS_DEV_HANDLE_MEM;
- cfg->dest_pipe_index = ((stat & (0xFF << 4)) >> 4);
- cfg->src_pipe_index = 0;
- dev_dbg(dev->dev, "flow src:pipe num:%d",
- cfg->dest_pipe_index);
- cfg->mode = SPS_MODE_DEST;
- } else {
- cfg->source = dev->bam.hdl;
- cfg->destination = SPS_DEV_HANDLE_MEM;
- cfg->src_pipe_index = ((stat & (0xFF << 4)) >> 4);
- cfg->dest_pipe_index = 0;
- dev_dbg(dev->dev, "flow dest:pipe num:%d",
- cfg->src_pipe_index);
- cfg->mode = SPS_MODE_SRC;
- }
- /* Space for desciptor FIFOs */
- cfg->desc.size = MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec);
- cfg->config = SPS_CONFIG_DEFAULT;
- ret = sps_connect(dev->pipes[pn].sps, cfg);
- if (!ret) {
- dev->pipes[pn].connected = true;
- msm_hw_set_port(dev, pn + dev->pipe_b);
- }
- return ret;
-}
-
-static u32 *msm_get_msg_buf(struct slim_controller *ctrl, int len)
-{
- struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
- /*
- * Currently we block a transaction until the current one completes.
- * In case we need multiple transactions, use message Q
- */
- return dev->tx_buf;
-}
-
-static int msm_send_msg_buf(struct slim_controller *ctrl, u32 *buf, u8 len)
-{
- int i;
- struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
- for (i = 0; i < (len + 3) >> 2; i++) {
- dev_dbg(dev->dev, "TX data:0x%x\n", buf[i]);
- writel_relaxed(buf[i], dev->base + MGR_TX_MSG + (i * 4));
- }
- /* Guarantee that message is sent before returning */
- mb();
- return 0;
-}
-
static int msm_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
{
DECLARE_COMPLETION_ONSTACK(done);
@@ -820,7 +394,7 @@
}
}
txn->rl--;
- pbuf = msm_get_msg_buf(ctrl, txn->rl);
+ pbuf = msm_get_msg_buf(dev, txn->rl);
dev->wr_comp = NULL;
dev->err = 0;
@@ -890,7 +464,7 @@
mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION)
dev->reconf_busy = true;
dev->wr_comp = &done;
- msm_send_msg_buf(ctrl, pbuf, txn->rl);
+ msm_send_msg_buf(dev, pbuf, txn->rl, MGR_TX_MSG);
timeout = wait_for_completion_timeout(&done, HZ);
if (!timeout)
dev->wr_comp = NULL;
@@ -956,7 +530,7 @@
retry_laddr:
init_completion(&done);
mutex_lock(&dev->tx_lock);
- buf = msm_get_msg_buf(ctrl, 9);
+ buf = msm_get_msg_buf(dev, 9);
buf[0] = SLIM_MSG_ASM_FIRST_WORD(9, SLIM_MSG_MT_CORE,
SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS,
SLIM_MSG_DEST_LOGICALADDR,
@@ -965,7 +539,7 @@
buf[2] = laddr;
dev->wr_comp = &done;
- ret = msm_send_msg_buf(ctrl, buf, 9);
+ ret = msm_send_msg_buf(dev, buf, 9, MGR_TX_MSG);
timeout = wait_for_completion_timeout(&done, HZ);
if (!timeout)
dev->err = -ETIMEDOUT;
@@ -1009,74 +583,6 @@
return 0;
}
-static int msm_config_port(struct slim_controller *ctrl, u8 pn)
-{
- struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
- struct msm_slim_endp *endpoint;
- int ret = 0;
- if (ctrl->ports[pn].req == SLIM_REQ_HALF_DUP ||
- ctrl->ports[pn].req == SLIM_REQ_MULTI_CH)
- return -EPROTONOSUPPORT;
- if (pn >= (MSM_SLIM_NPORTS - dev->pipe_b))
- return -ENODEV;
-
- endpoint = &dev->pipes[pn];
- ret = msm_slim_init_endpoint(dev, endpoint);
- dev_dbg(dev->dev, "sps register bam error code:%x\n", ret);
- return ret;
-}
-
-static enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr,
- u8 pn, u8 **done_buf, u32 *done_len)
-{
- struct msm_slim_ctrl *dev = slim_get_ctrldata(ctr);
- struct sps_iovec sio;
- int ret;
- if (done_len)
- *done_len = 0;
- if (done_buf)
- *done_buf = NULL;
- if (!dev->pipes[pn].connected)
- return SLIM_P_DISCONNECT;
- ret = sps_get_iovec(dev->pipes[pn].sps, &sio);
- if (!ret) {
- if (done_len)
- *done_len = sio.size;
- if (done_buf)
- *done_buf = (u8 *)sio.addr;
- }
- dev_dbg(dev->dev, "get iovec returned %d\n", ret);
- return SLIM_P_INPROGRESS;
-}
-
-static int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, u8 *iobuf,
- u32 len, struct completion *comp)
-{
- struct sps_register_event sreg;
- int ret;
- struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
- if (pn >= 7)
- return -ENODEV;
-
-
- ctrl->ports[pn].xcomp = comp;
- sreg.options = (SPS_EVENT_DESC_DONE|SPS_EVENT_ERROR);
- sreg.mode = SPS_TRIGGER_WAIT;
- sreg.xfer_done = comp;
- sreg.callback = NULL;
- sreg.user = &ctrl->ports[pn];
- ret = sps_register_event(dev->pipes[pn].sps, &sreg);
- if (ret) {
- dev_dbg(dev->dev, "sps register event error:%x\n", ret);
- return ret;
- }
- ret = sps_transfer_one(dev->pipes[pn].sps, (u32)iobuf, len, NULL,
- SPS_IOVEC_FLAG_INT);
- dev_dbg(dev->dev, "sps submit xfer error code:%x\n", ret);
-
- return ret;
-}
-
static int msm_sat_define_ch(struct msm_slim_sat *sat, u8 *buf, u8 len, u8 mc)
{
struct msm_slim_ctrl *dev = sat->dev;
@@ -1521,95 +1027,6 @@
return sat;
}
-static void
-msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
-{
- u32 *buf = ev->data.transfer.user;
- struct sps_iovec *iovec = &ev->data.transfer.iovec;
-
- /*
- * Note the virtual address needs to be offset by the same index
- * as the physical address or just pass in the actual virtual address
- * if the sps_mem_buffer is not needed. Note that if completion is
- * used, the virtual address won't be available and will need to be
- * calculated based on the offset of the physical address
- */
- if (ev->event_id == SPS_EVENT_DESC_DONE) {
-
- pr_debug("buf = 0x%p, data = 0x%x\n", buf, *buf);
-
- pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
- iovec->addr, iovec->size, iovec->flags);
-
- } else {
- dev_err(dev->dev, "%s: unknown event %d\n",
- __func__, ev->event_id);
- }
-}
-
-static void msm_slim_rx_msgq_cb(struct sps_event_notify *notify)
-{
- struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)notify->user;
- msm_slim_rx_msgq_event(dev, notify);
-}
-
-/* Queue up Rx message buffer */
-static inline int
-msm_slim_post_rx_msgq(struct msm_slim_ctrl *dev, int ix)
-{
- int ret;
- u32 flags = SPS_IOVEC_FLAG_INT;
- struct msm_slim_endp *endpoint = &dev->rx_msgq;
- struct sps_mem_buffer *mem = &endpoint->buf;
- struct sps_pipe *pipe = endpoint->sps;
-
- /* Rx message queue buffers are 4 bytes in length */
- u8 *virt_addr = mem->base + (4 * ix);
- u32 phys_addr = mem->phys_base + (4 * ix);
-
- pr_debug("index:%d, phys:0x%x, virt:0x%p\n", ix, phys_addr, virt_addr);
-
- ret = sps_transfer_one(pipe, phys_addr, 4, virt_addr, flags);
- if (ret)
- dev_err(dev->dev, "transfer_one() failed 0x%x, %d\n", ret, ix);
-
- return ret;
-}
-
-static inline int
-msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset)
-{
- struct msm_slim_endp *endpoint = &dev->rx_msgq;
- struct sps_mem_buffer *mem = &endpoint->buf;
- struct sps_pipe *pipe = endpoint->sps;
- struct sps_iovec iovec;
- int index;
- int ret;
-
- ret = sps_get_iovec(pipe, &iovec);
- if (ret) {
- dev_err(dev->dev, "sps_get_iovec() failed 0x%x\n", ret);
- goto err_exit;
- }
-
- pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
- iovec.addr, iovec.size, iovec.flags);
- BUG_ON(iovec.addr < mem->phys_base);
- BUG_ON(iovec.addr >= mem->phys_base + mem->size);
-
- /* Calculate buffer index */
- index = (iovec.addr - mem->phys_base) / 4;
- *(data + offset) = *((u32 *)mem->base + index);
-
- pr_debug("buf = 0x%p, data = 0x%x\n", (u32 *)mem->base + index, *data);
-
- /* Add buffer back to the queue */
- (void)msm_slim_post_rx_msgq(dev, index);
-
-err_exit:
- return ret;
-}
-
static int msm_slim_rx_msgq_thread(void *data)
{
struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
@@ -1674,219 +1091,6 @@
return 0;
}
-static int __devinit msm_slim_init_rx_msgq(struct msm_slim_ctrl *dev)
-{
- int i, ret;
- u32 pipe_offset;
- struct msm_slim_endp *endpoint = &dev->rx_msgq;
- struct sps_connect *config = &endpoint->config;
- struct sps_mem_buffer *descr = &config->desc;
- struct sps_mem_buffer *mem = &endpoint->buf;
- struct completion *notify = &dev->rx_msgq_notify;
-
- struct sps_register_event sps_error_event; /* SPS_ERROR */
- struct sps_register_event sps_descr_event; /* DESCR_DONE */
-
- init_completion(notify);
- if (!dev->use_rx_msgqs)
- goto rx_thread_create;
-
- /* Allocate the endpoint */
- ret = msm_slim_init_endpoint(dev, endpoint);
- if (ret) {
- dev_err(dev->dev, "init_endpoint failed 0x%x\n", ret);
- goto sps_init_endpoint_failed;
- }
-
- /* Get the pipe indices for the message queues */
- pipe_offset = (readl_relaxed(dev->base + MGR_STATUS) & 0xfc) >> 2;
- dev_dbg(dev->dev, "Message queue pipe offset %d\n", pipe_offset);
-
- config->mode = SPS_MODE_SRC;
- config->source = dev->bam.hdl;
- config->destination = SPS_DEV_HANDLE_MEM;
- config->src_pipe_index = pipe_offset;
- config->options = SPS_O_DESC_DONE | SPS_O_ERROR |
- SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
-
- /* Allocate memory for the FIFO descriptors */
- ret = msm_slim_sps_mem_alloc(dev, descr,
- MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec));
- if (ret) {
- dev_err(dev->dev, "unable to allocate SPS descriptors\n");
- goto alloc_descr_failed;
- }
-
- ret = sps_connect(endpoint->sps, config);
- if (ret) {
- dev_err(dev->dev, "sps_connect failed 0x%x\n", ret);
- goto sps_connect_failed;
- }
-
- /* Register completion for DESC_DONE */
- init_completion(notify);
- memset(&sps_descr_event, 0x00, sizeof(sps_descr_event));
-
- sps_descr_event.mode = SPS_TRIGGER_CALLBACK;
- sps_descr_event.options = SPS_O_DESC_DONE;
- sps_descr_event.user = (void *)dev;
- sps_descr_event.xfer_done = notify;
-
- ret = sps_register_event(endpoint->sps, &sps_descr_event);
- if (ret) {
- dev_err(dev->dev, "sps_connect() failed 0x%x\n", ret);
- goto sps_reg_event_failed;
- }
-
- /* Register callback for errors */
- memset(&sps_error_event, 0x00, sizeof(sps_error_event));
- sps_error_event.mode = SPS_TRIGGER_CALLBACK;
- sps_error_event.options = SPS_O_ERROR;
- sps_error_event.user = (void *)dev;
- sps_error_event.callback = msm_slim_rx_msgq_cb;
-
- ret = sps_register_event(endpoint->sps, &sps_error_event);
- if (ret) {
- dev_err(dev->dev, "sps_connect() failed 0x%x\n", ret);
- goto sps_reg_event_failed;
- }
-
- /* Allocate memory for the message buffer(s), N descrs, 4-byte mesg */
- ret = msm_slim_sps_mem_alloc(dev, mem, MSM_SLIM_DESC_NUM * 4);
- if (ret) {
- dev_err(dev->dev, "dma_alloc_coherent failed\n");
- goto alloc_buffer_failed;
- }
-
- /*
- * Call transfer_one for each 4-byte buffer
- * Use (buf->size/4) - 1 for the number of buffer to post
- */
-
- /* Setup the transfer */
- for (i = 0; i < (MSM_SLIM_DESC_NUM - 1); i++) {
- ret = msm_slim_post_rx_msgq(dev, i);
- if (ret) {
- dev_err(dev->dev, "post_rx_msgq() failed 0x%x\n", ret);
- goto sps_transfer_failed;
- }
- }
-
-rx_thread_create:
- /* Fire up the Rx message queue thread */
- dev->rx_msgq_thread = kthread_run(msm_slim_rx_msgq_thread, dev,
- MSM_SLIM_NAME "_rx_msgq_thread");
- if (!dev->rx_msgq_thread) {
- dev_err(dev->dev, "Failed to start Rx message queue thread\n");
- /* Tear-down BAMs or return? */
- if (!dev->use_rx_msgqs)
- return -EIO;
- else
- ret = -EIO;
- } else
- return 0;
-
-sps_transfer_failed:
- msm_slim_sps_mem_free(dev, mem);
-alloc_buffer_failed:
- memset(&sps_error_event, 0x00, sizeof(sps_error_event));
- sps_register_event(endpoint->sps, &sps_error_event);
-sps_reg_event_failed:
- sps_disconnect(endpoint->sps);
-sps_connect_failed:
- msm_slim_sps_mem_free(dev, descr);
-alloc_descr_failed:
- msm_slim_free_endpoint(endpoint);
-sps_init_endpoint_failed:
- dev->use_rx_msgqs = 0;
- return ret;
-}
-
-/* Registers BAM h/w resource with SPS driver and initializes msgq endpoints */
-static int __devinit
-msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem)
-{
- int i, ret;
- u32 bam_handle;
- struct sps_bam_props bam_props = {0};
-
- static struct sps_bam_sec_config_props sec_props = {
- .ees = {
- [0] = { /* LPASS */
- .vmid = 0,
- .pipe_mask = 0xFFFF98,
- },
- [1] = { /* Krait Apps */
- .vmid = 1,
- .pipe_mask = 0x3F000007,
- },
- [2] = { /* Modem */
- .vmid = 2,
- .pipe_mask = 0x00000060,
- },
- },
- };
-
- bam_props.ee = dev->ee;
- bam_props.virt_addr = dev->bam.base;
- bam_props.phys_addr = bam_mem->start;
- bam_props.irq = dev->bam.irq;
- bam_props.manage = SPS_BAM_MGR_LOCAL;
- bam_props.summing_threshold = MSM_SLIM_PERF_SUMM_THRESHOLD;
-
- bam_props.sec_config = SPS_BAM_SEC_DO_CONFIG;
- bam_props.p_sec_config_props = &sec_props;
-
- bam_props.options = SPS_O_DESC_DONE | SPS_O_ERROR |
- SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
-
- /* First 7 bits are for message Qs */
- for (i = 7; i < 32; i++) {
- /* Check what pipes are owned by Apps. */
- if ((sec_props.ees[dev->ee].pipe_mask >> i) & 0x1)
- break;
- }
- dev->pipe_b = i - 7;
-
- /* Register the BAM device with the SPS driver */
- ret = sps_register_bam_device(&bam_props, &bam_handle);
- if (ret) {
- dev_err(dev->dev, "disabling BAM: reg-bam failed 0x%x\n", ret);
- dev->use_rx_msgqs = 0;
- goto init_rx_msgq;
- }
- dev->bam.hdl = bam_handle;
- dev_dbg(dev->dev, "SLIM BAM registered, handle = 0x%x\n", bam_handle);
-
-init_rx_msgq:
- ret = msm_slim_init_rx_msgq(dev);
- if (ret)
- dev_err(dev->dev, "msm_slim_init_rx_msgq failed 0x%x\n", ret);
- if (ret && bam_handle) {
- sps_deregister_bam_device(bam_handle);
- dev->bam.hdl = 0L;
- }
- return ret;
-}
-
-static void msm_slim_sps_exit(struct msm_slim_ctrl *dev)
-{
- if (dev->use_rx_msgqs) {
- struct msm_slim_endp *endpoint = &dev->rx_msgq;
- struct sps_connect *config = &endpoint->config;
- struct sps_mem_buffer *descr = &config->desc;
- struct sps_mem_buffer *mem = &endpoint->buf;
- struct sps_register_event sps_event;
- memset(&sps_event, 0x00, sizeof(sps_event));
- msm_slim_sps_mem_free(dev, mem);
- sps_register_event(endpoint->sps, &sps_event);
- sps_disconnect(endpoint->sps);
- msm_slim_sps_mem_free(dev, descr);
- msm_slim_free_endpoint(endpoint);
- sps_deregister_bam_device(dev->bam.hdl);
- }
-}
-
static void msm_slim_prg_slew(struct platform_device *pdev,
struct msm_slim_ctrl *dev)
{
@@ -2052,12 +1256,20 @@
else
clk_prepare_enable(dev->hclk);
- ret = msm_slim_sps_init(dev, bam_mem);
+ ret = msm_slim_sps_init(dev, bam_mem, MGR_STATUS);
if (ret != 0) {
dev_err(dev->dev, "error SPS init\n");
goto err_sps_init_failed;
}
+ /* Fire up the Rx message queue thread */
+ dev->rx_msgq_thread = kthread_run(msm_slim_rx_msgq_thread, dev,
+ MSM_SLIM_NAME "_rx_msgq_thread");
+ if (IS_ERR(dev->rx_msgq_thread)) {
+ ret = PTR_ERR(dev->rx_msgq_thread);
+ dev_err(dev->dev, "Failed to start Rx message queue thread\n");
+ goto err_thread_create_failed;
+ }
dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
dev->framer.superfreq =
@@ -2183,6 +1395,8 @@
err_clk_get_failed:
kfree(dev->satd);
err_request_irq_failed:
+ kthread_stop(dev->rx_msgq_thread);
+err_thread_create_failed:
msm_slim_sps_exit(dev);
err_sps_init_failed:
if (dev->hclk) {
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
new file mode 100644
index 0000000..8a1ea84
--- /dev/null
+++ b/drivers/slimbus/slim-msm.c
@@ -0,0 +1,578 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/slimbus/slimbus.h>
+#include <mach/sps.h>
+#include "slim-msm.h"
+
+int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len)
+{
+ spin_lock(&dev->rx_lock);
+ if ((dev->tail + 1) % MSM_CONCUR_MSG == dev->head) {
+ spin_unlock(&dev->rx_lock);
+ dev_err(dev->dev, "RX QUEUE full!");
+ return -EXFULL;
+ }
+ memcpy((u8 *)dev->rx_msgs[dev->tail], (u8 *)buf, len);
+ dev->tail = (dev->tail + 1) % MSM_CONCUR_MSG;
+ spin_unlock(&dev->rx_lock);
+ return 0;
+}
+
+int msm_slim_rx_dequeue(struct msm_slim_ctrl *dev, u8 *buf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&dev->rx_lock, flags);
+ if (dev->tail == dev->head) {
+ spin_unlock_irqrestore(&dev->rx_lock, flags);
+ return -ENODATA;
+ }
+ memcpy(buf, (u8 *)dev->rx_msgs[dev->head], 40);
+ dev->head = (dev->head + 1) % MSM_CONCUR_MSG;
+ spin_unlock_irqrestore(&dev->rx_lock, flags);
+ return 0;
+}
+
+int msm_slim_get_ctrl(struct msm_slim_ctrl *dev)
+{
+#ifdef CONFIG_PM_RUNTIME
+ int ref = 0;
+ int ret = pm_runtime_get_sync(dev->dev);
+ if (ret >= 0) {
+ ref = atomic_read(&dev->dev->power.usage_count);
+ if (ref <= 0) {
+ dev_err(dev->dev, "reference count -ve:%d", ref);
+ ret = -ENODEV;
+ }
+ }
+ return ret;
+#else
+ return -ENODEV;
+#endif
+}
+void msm_slim_put_ctrl(struct msm_slim_ctrl *dev)
+{
+#ifdef CONFIG_PM_RUNTIME
+ int ref;
+ pm_runtime_mark_last_busy(dev->dev);
+ ref = atomic_read(&dev->dev->power.usage_count);
+ if (ref <= 0)
+ dev_err(dev->dev, "reference count mismatch:%d", ref);
+ else
+ pm_runtime_put(dev->dev);
+#endif
+}
+
+int msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep)
+{
+ int ret;
+ struct sps_pipe *endpoint;
+ struct sps_connect *config = &ep->config;
+
+ /* Allocate the endpoint */
+ endpoint = sps_alloc_endpoint();
+ if (!endpoint) {
+ dev_err(dev->dev, "sps_alloc_endpoint failed\n");
+ return -ENOMEM;
+ }
+
+ /* Get default connection configuration for an endpoint */
+ ret = sps_get_config(endpoint, config);
+ if (ret) {
+ dev_err(dev->dev, "sps_get_config failed 0x%x\n", ret);
+ goto sps_config_failed;
+ }
+
+ ep->sps = endpoint;
+ return 0;
+
+sps_config_failed:
+ sps_free_endpoint(endpoint);
+ return ret;
+}
+
+void msm_slim_free_endpoint(struct msm_slim_endp *ep)
+{
+ sps_free_endpoint(ep->sps);
+ ep->sps = NULL;
+}
+
+int msm_slim_sps_mem_alloc(
+ struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem, u32 len)
+{
+ dma_addr_t phys;
+
+ mem->size = len;
+ mem->min_size = 0;
+ mem->base = dma_alloc_coherent(dev->dev, mem->size, &phys, GFP_KERNEL);
+
+ if (!mem->base) {
+ dev_err(dev->dev, "dma_alloc_coherent(%d) failed\n", len);
+ return -ENOMEM;
+ }
+
+ mem->phys_base = phys;
+ memset(mem->base, 0x00, mem->size);
+ return 0;
+}
+
+void
+msm_slim_sps_mem_free(struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem)
+{
+ dma_free_coherent(dev->dev, mem->size, mem->base, mem->phys_base);
+ mem->size = 0;
+ mem->base = NULL;
+ mem->phys_base = 0;
+}
+
+void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn)
+{
+ u32 set_cfg = DEF_WATERMARK | DEF_ALIGN | DEF_PACK | ENABLE_PORT;
+ u32 int_port = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
+ dev->ver));
+ writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pn, dev->ver));
+ writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pn, dev->ver));
+ writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pn, dev->ver));
+ writel_relaxed((int_port | 1 << pn) , PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
+ dev->ver));
+ /* Make sure that port registers are updated before returning */
+ mb();
+}
+
+int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
+{
+ struct msm_slim_endp *endpoint = &dev->pipes[pn];
+ struct sps_connect *cfg = &endpoint->config;
+ u32 stat;
+ int ret = sps_get_config(dev->pipes[pn].sps, cfg);
+ if (ret) {
+ dev_err(dev->dev, "sps pipe-port get config error%x\n", ret);
+ return ret;
+ }
+ cfg->options = SPS_O_DESC_DONE | SPS_O_ERROR |
+ SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+
+ if (dev->pipes[pn].connected) {
+ ret = sps_set_config(dev->pipes[pn].sps, cfg);
+ if (ret) {
+ dev_err(dev->dev, "sps pipe-port set config erro:%x\n",
+ ret);
+ return ret;
+ }
+ }
+
+ stat = readl_relaxed(PGD_PORT(PGD_PORT_STATn, (pn + dev->pipe_b),
+ dev->ver));
+ if (dev->ctrl.ports[pn].flow == SLIM_SRC) {
+ cfg->destination = dev->bam.hdl;
+ cfg->source = SPS_DEV_HANDLE_MEM;
+ cfg->dest_pipe_index = ((stat & (0xFF << 4)) >> 4);
+ cfg->src_pipe_index = 0;
+ dev_dbg(dev->dev, "flow src:pipe num:%d",
+ cfg->dest_pipe_index);
+ cfg->mode = SPS_MODE_DEST;
+ } else {
+ cfg->source = dev->bam.hdl;
+ cfg->destination = SPS_DEV_HANDLE_MEM;
+ cfg->src_pipe_index = ((stat & (0xFF << 4)) >> 4);
+ cfg->dest_pipe_index = 0;
+ dev_dbg(dev->dev, "flow dest:pipe num:%d",
+ cfg->src_pipe_index);
+ cfg->mode = SPS_MODE_SRC;
+ }
+ /* Space for desciptor FIFOs */
+ cfg->desc.size = MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec);
+ cfg->config = SPS_CONFIG_DEFAULT;
+ ret = sps_connect(dev->pipes[pn].sps, cfg);
+ if (!ret) {
+ dev->pipes[pn].connected = true;
+ msm_hw_set_port(dev, pn + dev->pipe_b);
+ }
+ return ret;
+}
+
+int msm_config_port(struct slim_controller *ctrl, u8 pn)
+{
+ struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+ struct msm_slim_endp *endpoint;
+ int ret = 0;
+ if (ctrl->ports[pn].req == SLIM_REQ_HALF_DUP ||
+ ctrl->ports[pn].req == SLIM_REQ_MULTI_CH)
+ return -EPROTONOSUPPORT;
+ if (pn >= (MSM_SLIM_NPORTS - dev->pipe_b))
+ return -ENODEV;
+
+ endpoint = &dev->pipes[pn];
+ ret = msm_slim_init_endpoint(dev, endpoint);
+ dev_dbg(dev->dev, "sps register bam error code:%x\n", ret);
+ return ret;
+}
+
+enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr,
+ u8 pn, u8 **done_buf, u32 *done_len)
+{
+ struct msm_slim_ctrl *dev = slim_get_ctrldata(ctr);
+ struct sps_iovec sio;
+ int ret;
+ if (done_len)
+ *done_len = 0;
+ if (done_buf)
+ *done_buf = NULL;
+ if (!dev->pipes[pn].connected)
+ return SLIM_P_DISCONNECT;
+ ret = sps_get_iovec(dev->pipes[pn].sps, &sio);
+ if (!ret) {
+ if (done_len)
+ *done_len = sio.size;
+ if (done_buf)
+ *done_buf = (u8 *)sio.addr;
+ }
+ dev_dbg(dev->dev, "get iovec returned %d\n", ret);
+ return SLIM_P_INPROGRESS;
+}
+
+int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, u8 *iobuf,
+ u32 len, struct completion *comp)
+{
+ struct sps_register_event sreg;
+ int ret;
+ struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+ if (pn >= 7)
+ return -ENODEV;
+
+
+ ctrl->ports[pn].xcomp = comp;
+ sreg.options = (SPS_EVENT_DESC_DONE|SPS_EVENT_ERROR);
+ sreg.mode = SPS_TRIGGER_WAIT;
+ sreg.xfer_done = comp;
+ sreg.callback = NULL;
+ sreg.user = &ctrl->ports[pn];
+ ret = sps_register_event(dev->pipes[pn].sps, &sreg);
+ if (ret) {
+ dev_dbg(dev->dev, "sps register event error:%x\n", ret);
+ return ret;
+ }
+ ret = sps_transfer_one(dev->pipes[pn].sps, (u32)iobuf, len, NULL,
+ SPS_IOVEC_FLAG_INT);
+ dev_dbg(dev->dev, "sps submit xfer error code:%x\n", ret);
+
+ return ret;
+}
+
+int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg)
+{
+ int i;
+ for (i = 0; i < (len + 3) >> 2; i++) {
+ dev_dbg(dev->dev, "TX data:0x%x\n", buf[i]);
+ writel_relaxed(buf[i], dev->base + tx_reg + (i * 4));
+ }
+ /* Guarantee that message is sent before returning */
+ mb();
+ return 0;
+}
+
+u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len)
+{
+ /*
+ * Currently we block a transaction until the current one completes.
+ * In case we need multiple transactions, use message Q
+ */
+ return dev->tx_buf;
+}
+
+static void
+msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
+{
+ u32 *buf = ev->data.transfer.user;
+ struct sps_iovec *iovec = &ev->data.transfer.iovec;
+
+ /*
+ * Note the virtual address needs to be offset by the same index
+ * as the physical address or just pass in the actual virtual address
+ * if the sps_mem_buffer is not needed. Note that if completion is
+ * used, the virtual address won't be available and will need to be
+ * calculated based on the offset of the physical address
+ */
+ if (ev->event_id == SPS_EVENT_DESC_DONE) {
+
+ pr_debug("buf = 0x%p, data = 0x%x\n", buf, *buf);
+
+ pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
+ iovec->addr, iovec->size, iovec->flags);
+
+ } else {
+ dev_err(dev->dev, "%s: unknown event %d\n",
+ __func__, ev->event_id);
+ }
+}
+
+static void msm_slim_rx_msgq_cb(struct sps_event_notify *notify)
+{
+ struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)notify->user;
+ msm_slim_rx_msgq_event(dev, notify);
+}
+
+/* Queue up Rx message buffer */
+static int msm_slim_post_rx_msgq(struct msm_slim_ctrl *dev, int ix)
+{
+ int ret;
+ u32 flags = SPS_IOVEC_FLAG_INT;
+ struct msm_slim_endp *endpoint = &dev->rx_msgq;
+ struct sps_mem_buffer *mem = &endpoint->buf;
+ struct sps_pipe *pipe = endpoint->sps;
+
+ /* Rx message queue buffers are 4 bytes in length */
+ u8 *virt_addr = mem->base + (4 * ix);
+ u32 phys_addr = mem->phys_base + (4 * ix);
+
+ pr_debug("index:%d, phys:0x%x, virt:0x%p\n", ix, phys_addr, virt_addr);
+
+ ret = sps_transfer_one(pipe, phys_addr, 4, virt_addr, flags);
+ if (ret)
+ dev_err(dev->dev, "transfer_one() failed 0x%x, %d\n", ret, ix);
+
+ return ret;
+}
+
+int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset)
+{
+ struct msm_slim_endp *endpoint = &dev->rx_msgq;
+ struct sps_mem_buffer *mem = &endpoint->buf;
+ struct sps_pipe *pipe = endpoint->sps;
+ struct sps_iovec iovec;
+ int index;
+ int ret;
+
+ ret = sps_get_iovec(pipe, &iovec);
+ if (ret) {
+ dev_err(dev->dev, "sps_get_iovec() failed 0x%x\n", ret);
+ goto err_exit;
+ }
+
+ pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
+ iovec.addr, iovec.size, iovec.flags);
+ BUG_ON(iovec.addr < mem->phys_base);
+ BUG_ON(iovec.addr >= mem->phys_base + mem->size);
+
+ /* Calculate buffer index */
+ index = (iovec.addr - mem->phys_base) / 4;
+ *(data + offset) = *((u32 *)mem->base + index);
+
+ pr_debug("buf = 0x%p, data = 0x%x\n", (u32 *)mem->base + index, *data);
+
+ /* Add buffer back to the queue */
+ (void)msm_slim_post_rx_msgq(dev, index);
+
+err_exit:
+ return ret;
+}
+
+static int msm_slim_init_rx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg)
+{
+ int i, ret;
+ u32 pipe_offset;
+ struct msm_slim_endp *endpoint = &dev->rx_msgq;
+ struct sps_connect *config = &endpoint->config;
+ struct sps_mem_buffer *descr = &config->desc;
+ struct sps_mem_buffer *mem = &endpoint->buf;
+ struct completion *notify = &dev->rx_msgq_notify;
+
+ struct sps_register_event sps_error_event; /* SPS_ERROR */
+ struct sps_register_event sps_descr_event; /* DESCR_DONE */
+
+ init_completion(notify);
+ if (!dev->use_rx_msgqs)
+ return 0;
+
+ /* Allocate the endpoint */
+ ret = msm_slim_init_endpoint(dev, endpoint);
+ if (ret) {
+ dev_err(dev->dev, "init_endpoint failed 0x%x\n", ret);
+ goto sps_init_endpoint_failed;
+ }
+
+ /* Get the pipe indices for the message queues */
+ pipe_offset = (readl_relaxed(dev->base + pipe_reg) & 0xfc) >> 2;
+ dev_dbg(dev->dev, "Message queue pipe offset %d\n", pipe_offset);
+
+ config->mode = SPS_MODE_SRC;
+ config->source = dev->bam.hdl;
+ config->destination = SPS_DEV_HANDLE_MEM;
+ config->src_pipe_index = pipe_offset;
+ config->options = SPS_O_DESC_DONE | SPS_O_ERROR |
+ SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+
+ /* Allocate memory for the FIFO descriptors */
+ ret = msm_slim_sps_mem_alloc(dev, descr,
+ MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec));
+ if (ret) {
+ dev_err(dev->dev, "unable to allocate SPS descriptors\n");
+ goto alloc_descr_failed;
+ }
+
+ ret = sps_connect(endpoint->sps, config);
+ if (ret) {
+ dev_err(dev->dev, "sps_connect failed 0x%x\n", ret);
+ goto sps_connect_failed;
+ }
+
+ memset(&sps_descr_event, 0x00, sizeof(sps_descr_event));
+
+ sps_descr_event.mode = SPS_TRIGGER_CALLBACK;
+ sps_descr_event.options = SPS_O_DESC_DONE;
+ sps_descr_event.user = (void *)dev;
+ sps_descr_event.xfer_done = notify;
+
+ ret = sps_register_event(endpoint->sps, &sps_descr_event);
+ if (ret) {
+ dev_err(dev->dev, "sps_connect() failed 0x%x\n", ret);
+ goto sps_reg_event_failed;
+ }
+
+ /* Register callback for errors */
+ memset(&sps_error_event, 0x00, sizeof(sps_error_event));
+ sps_error_event.mode = SPS_TRIGGER_CALLBACK;
+ sps_error_event.options = SPS_O_ERROR;
+ sps_error_event.user = (void *)dev;
+ sps_error_event.callback = msm_slim_rx_msgq_cb;
+
+ ret = sps_register_event(endpoint->sps, &sps_error_event);
+ if (ret) {
+ dev_err(dev->dev, "sps_connect() failed 0x%x\n", ret);
+ goto sps_reg_event_failed;
+ }
+
+ /* Allocate memory for the message buffer(s), N descrs, 4-byte mesg */
+ ret = msm_slim_sps_mem_alloc(dev, mem, MSM_SLIM_DESC_NUM * 4);
+ if (ret) {
+ dev_err(dev->dev, "dma_alloc_coherent failed\n");
+ goto alloc_buffer_failed;
+ }
+
+ /*
+ * Call transfer_one for each 4-byte buffer
+ * Use (buf->size/4) - 1 for the number of buffer to post
+ */
+
+ /* Setup the transfer */
+ for (i = 0; i < (MSM_SLIM_DESC_NUM - 1); i++) {
+ ret = msm_slim_post_rx_msgq(dev, i);
+ if (ret) {
+ dev_err(dev->dev, "post_rx_msgq() failed 0x%x\n", ret);
+ goto sps_transfer_failed;
+ }
+ }
+
+ return 0;
+
+sps_transfer_failed:
+ msm_slim_sps_mem_free(dev, mem);
+alloc_buffer_failed:
+ memset(&sps_error_event, 0x00, sizeof(sps_error_event));
+ sps_register_event(endpoint->sps, &sps_error_event);
+sps_reg_event_failed:
+ sps_disconnect(endpoint->sps);
+sps_connect_failed:
+ msm_slim_sps_mem_free(dev, descr);
+alloc_descr_failed:
+ msm_slim_free_endpoint(endpoint);
+sps_init_endpoint_failed:
+ dev->use_rx_msgqs = 0;
+ return ret;
+}
+
+/* Registers BAM h/w resource with SPS driver and initializes msgq endpoints */
+int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
+ u32 pipe_reg)
+{
+ int i, ret;
+ u32 bam_handle;
+ struct sps_bam_props bam_props = {0};
+
+ static struct sps_bam_sec_config_props sec_props = {
+ .ees = {
+ [0] = { /* LPASS */
+ .vmid = 0,
+ .pipe_mask = 0xFFFF98,
+ },
+ [1] = { /* Krait Apps */
+ .vmid = 1,
+ .pipe_mask = 0x3F000007,
+ },
+ [2] = { /* Modem */
+ .vmid = 2,
+ .pipe_mask = 0x00000060,
+ },
+ },
+ };
+
+ bam_props.ee = dev->ee;
+ bam_props.virt_addr = dev->bam.base;
+ bam_props.phys_addr = bam_mem->start;
+ bam_props.irq = dev->bam.irq;
+ bam_props.manage = SPS_BAM_MGR_LOCAL;
+ bam_props.summing_threshold = MSM_SLIM_PERF_SUMM_THRESHOLD;
+
+ bam_props.sec_config = SPS_BAM_SEC_DO_CONFIG;
+ bam_props.p_sec_config_props = &sec_props;
+
+ bam_props.options = SPS_O_DESC_DONE | SPS_O_ERROR |
+ SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+
+ /* First 7 bits are for message Qs */
+ for (i = 7; i < 32; i++) {
+ /* Check what pipes are owned by Apps. */
+ if ((sec_props.ees[dev->ee].pipe_mask >> i) & 0x1)
+ break;
+ }
+ dev->pipe_b = i - 7;
+
+ /* Register the BAM device with the SPS driver */
+ ret = sps_register_bam_device(&bam_props, &bam_handle);
+ if (ret) {
+ dev_err(dev->dev, "disabling BAM: reg-bam failed 0x%x\n", ret);
+ dev->use_rx_msgqs = 0;
+ goto init_rx_msgq;
+ }
+ dev->bam.hdl = bam_handle;
+ dev_dbg(dev->dev, "SLIM BAM registered, handle = 0x%x\n", bam_handle);
+
+init_rx_msgq:
+ ret = msm_slim_init_rx_msgq(dev, pipe_reg);
+ if (ret)
+ dev_err(dev->dev, "msm_slim_init_rx_msgq failed 0x%x\n", ret);
+ if (ret && bam_handle) {
+ sps_deregister_bam_device(bam_handle);
+ dev->bam.hdl = 0L;
+ }
+ return ret;
+}
+
+void msm_slim_sps_exit(struct msm_slim_ctrl *dev)
+{
+ if (dev->use_rx_msgqs) {
+ struct msm_slim_endp *endpoint = &dev->rx_msgq;
+ struct sps_connect *config = &endpoint->config;
+ struct sps_mem_buffer *descr = &config->desc;
+ struct sps_mem_buffer *mem = &endpoint->buf;
+ struct sps_register_event sps_event;
+ memset(&sps_event, 0x00, sizeof(sps_event));
+ msm_slim_sps_mem_free(dev, mem);
+ sps_register_event(endpoint->sps, &sps_event);
+ sps_disconnect(endpoint->sps);
+ msm_slim_sps_mem_free(dev, descr);
+ msm_slim_free_endpoint(endpoint);
+ sps_deregister_bam_device(dev->bam.hdl);
+ }
+}
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
new file mode 100644
index 0000000..f68475a
--- /dev/null
+++ b/drivers/slimbus/slim-msm.h
@@ -0,0 +1,251 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SLIM_MSM_H
+#define _SLIM_MSM_H
+/* Per spec.max 40 bytes per received message */
+#define SLIM_RX_MSGQ_BUF_LEN 40
+
+#define SLIM_USR_MC_GENERIC_ACK 0x25
+#define SLIM_USR_MC_MASTER_CAPABILITY 0x0
+#define SLIM_USR_MC_REPORT_SATELLITE 0x1
+#define SLIM_USR_MC_ADDR_QUERY 0xD
+#define SLIM_USR_MC_ADDR_REPLY 0xE
+#define SLIM_USR_MC_DEFINE_CHAN 0x20
+#define SLIM_USR_MC_DEF_ACT_CHAN 0x21
+#define SLIM_USR_MC_CHAN_CTRL 0x23
+#define SLIM_USR_MC_RECONFIG_NOW 0x24
+#define SLIM_USR_MC_REQ_BW 0x28
+#define SLIM_USR_MC_CONNECT_SRC 0x2C
+#define SLIM_USR_MC_CONNECT_SINK 0x2D
+#define SLIM_USR_MC_DISCONNECT_PORT 0x2E
+
+#define MSM_SLIM_AUTOSUSPEND MSEC_PER_SEC
+
+/*
+ * Messages that can be received simultaneously:
+ * Client reads, LPASS master responses, announcement messages
+ * Receive upto 10 messages simultaneously.
+ */
+#define MSM_SLIM_DESC_NUM 32
+
+/* MSM Slimbus peripheral settings */
+#define MSM_SLIM_PERF_SUMM_THRESHOLD 0x8000
+#define MSM_SLIM_NPORTS 24
+#define MSM_SLIM_NCHANS 32
+
+#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
+ ((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
+
+#define MSM_CONCUR_MSG 8
+#define SAT_CONCUR_MSG 8
+#define DEF_WATERMARK (8 << 1)
+#define DEF_ALIGN 0
+#define DEF_PACK (1 << 6)
+#define ENABLE_PORT 1
+
+#define DEF_BLKSZ 0
+#define DEF_TRANSZ 0
+
+#define SAT_MAGIC_LSB 0xD9
+#define SAT_MAGIC_MSB 0xC5
+#define SAT_MSG_VER 0x1
+#define SAT_MSG_PROT 0x1
+#define MSM_SAT_SUCCSS 0x20
+#define MSM_MAX_NSATS 2
+#define MSM_MAX_SATCH 32
+
+#define PGD_THIS_EE(r, v) ((v) ? PGD_THIS_EE_V2(r) : PGD_THIS_EE_V1(r))
+#define PGD_PORT(r, p, v) ((v) ? PGD_PORT_V2(r, p) : PGD_PORT_V1(r, p))
+#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r))
+
+#define PGD_THIS_EE_V2(r) (dev->base + (r ## _V2) + (dev->ee * 0x1000))
+#define PGD_PORT_V2(r, p) (dev->base + (r ## _V2) + ((p) * 0x1000))
+#define CFG_PORT_V2(r) ((r ## _V2))
+/* Component registers */
+enum comp_reg_v2 {
+ COMP_CFG_V2 = 4,
+ COMP_TRUST_CFG_V2 = 0x3000,
+};
+
+/* Manager PGD registers */
+enum pgd_reg_v2 {
+ PGD_CFG_V2 = 0x800,
+ PGD_STAT_V2 = 0x804,
+ PGD_INT_EN_V2 = 0x810,
+ PGD_INT_STAT_V2 = 0x814,
+ PGD_INT_CLR_V2 = 0x818,
+ PGD_OWN_EEn_V2 = 0x300C,
+ PGD_PORT_INT_EN_EEn_V2 = 0x5000,
+ PGD_PORT_INT_ST_EEn_V2 = 0x5004,
+ PGD_PORT_INT_CL_EEn_V2 = 0x5008,
+ PGD_PORT_CFGn_V2 = 0x14000,
+ PGD_PORT_STATn_V2 = 0x14004,
+ PGD_PORT_PARAMn_V2 = 0x14008,
+ PGD_PORT_BLKn_V2 = 0x1400C,
+ PGD_PORT_TRANn_V2 = 0x14010,
+ PGD_PORT_MCHANn_V2 = 0x14014,
+ PGD_PORT_PSHPLLn_V2 = 0x14018,
+ PGD_PORT_PC_CFGn_V2 = 0x8000,
+ PGD_PORT_PC_VALn_V2 = 0x8004,
+ PGD_PORT_PC_VFR_TSn_V2 = 0x8008,
+ PGD_PORT_PC_VFR_STn_V2 = 0x800C,
+ PGD_PORT_PC_VFR_CLn_V2 = 0x8010,
+ PGD_IE_STAT_V2 = 0x820,
+ PGD_VE_STAT_V2 = 0x830,
+};
+
+#define PGD_THIS_EE_V1(r) (dev->base + (r ## _V1) + (dev->ee * 16))
+#define PGD_PORT_V1(r, p) (dev->base + (r ## _V1) + ((p) * 32))
+#define CFG_PORT_V1(r) ((r ## _V1))
+/* Component registers */
+enum comp_reg_v1 {
+ COMP_CFG_V1 = 0,
+ COMP_TRUST_CFG_V1 = 0x14,
+};
+
+/* Manager PGD registers */
+enum pgd_reg_v1 {
+ PGD_CFG_V1 = 0x1000,
+ PGD_STAT_V1 = 0x1004,
+ PGD_INT_EN_V1 = 0x1010,
+ PGD_INT_STAT_V1 = 0x1014,
+ PGD_INT_CLR_V1 = 0x1018,
+ PGD_OWN_EEn_V1 = 0x1020,
+ PGD_PORT_INT_EN_EEn_V1 = 0x1030,
+ PGD_PORT_INT_ST_EEn_V1 = 0x1034,
+ PGD_PORT_INT_CL_EEn_V1 = 0x1038,
+ PGD_PORT_CFGn_V1 = 0x1080,
+ PGD_PORT_STATn_V1 = 0x1084,
+ PGD_PORT_PARAMn_V1 = 0x1088,
+ PGD_PORT_BLKn_V1 = 0x108C,
+ PGD_PORT_TRANn_V1 = 0x1090,
+ PGD_PORT_MCHANn_V1 = 0x1094,
+ PGD_PORT_PSHPLLn_V1 = 0x1098,
+ PGD_PORT_PC_CFGn_V1 = 0x1600,
+ PGD_PORT_PC_VALn_V1 = 0x1604,
+ PGD_PORT_PC_VFR_TSn_V1 = 0x1608,
+ PGD_PORT_PC_VFR_STn_V1 = 0x160C,
+ PGD_PORT_PC_VFR_CLn_V1 = 0x1610,
+ PGD_IE_STAT_V1 = 0x1700,
+ PGD_VE_STAT_V1 = 0x1710,
+};
+
+enum msm_ctrl_state {
+ MSM_CTRL_AWAKE,
+ MSM_CTRL_SLEEPING,
+ MSM_CTRL_ASLEEP,
+};
+
+struct msm_slim_sps_bam {
+ u32 hdl;
+ void __iomem *base;
+ int irq;
+};
+
+struct msm_slim_endp {
+ struct sps_pipe *sps;
+ struct sps_connect config;
+ struct sps_register_event event;
+ struct sps_mem_buffer buf;
+ struct completion *xcomp;
+ bool connected;
+};
+
+struct msm_slim_ctrl {
+ struct slim_controller ctrl;
+ struct slim_framer framer;
+ struct device *dev;
+ void __iomem *base;
+ struct resource *slew_mem;
+ u32 curr_bw;
+ u8 msg_cnt;
+ u32 tx_buf[10];
+ u8 rx_msgs[MSM_CONCUR_MSG][SLIM_RX_MSGQ_BUF_LEN];
+ spinlock_t rx_lock;
+ int head;
+ int tail;
+ int irq;
+ int err;
+ int ee;
+ struct completion *wr_comp;
+ struct msm_slim_sat *satd[MSM_MAX_NSATS];
+ struct msm_slim_endp pipes[7];
+ struct msm_slim_sps_bam bam;
+ struct msm_slim_endp rx_msgq;
+ struct completion rx_msgq_notify;
+ struct task_struct *rx_msgq_thread;
+ struct clk *rclk;
+ struct clk *hclk;
+ struct mutex tx_lock;
+ u8 pgdla;
+ bool use_rx_msgqs;
+ int pipe_b;
+ struct completion reconf;
+ bool reconf_busy;
+ bool chan_active;
+ enum msm_ctrl_state state;
+ int nsats;
+ u32 ver;
+};
+
+struct msm_sat_chan {
+ u8 chan;
+ u16 chanh;
+ int req_rem;
+ int req_def;
+ bool reconf;
+};
+
+struct msm_slim_sat {
+ struct slim_device satcl;
+ struct msm_slim_ctrl *dev;
+ struct workqueue_struct *wq;
+ struct work_struct wd;
+ u8 sat_msgs[SAT_CONCUR_MSG][40];
+ struct msm_sat_chan *satch;
+ u8 nsatch;
+ bool sent_capability;
+ bool pending_reconf;
+ bool pending_capability;
+ int shead;
+ int stail;
+ spinlock_t lock;
+};
+
+enum rsc_grp {
+ EE_MGR_RSC_GRP = 1 << 10,
+ EE_NGD_2 = 2 << 6,
+ EE_NGD_1 = 0,
+};
+
+
+int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len);
+int msm_slim_rx_dequeue(struct msm_slim_ctrl *dev, u8 *buf);
+int msm_slim_get_ctrl(struct msm_slim_ctrl *dev);
+void msm_slim_put_ctrl(struct msm_slim_ctrl *dev);
+int msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep);
+void msm_slim_free_endpoint(struct msm_slim_endp *ep);
+void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn);
+int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn);
+int msm_config_port(struct slim_controller *ctrl, u8 pn);
+enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr,
+ u8 pn, u8 **done_buf, u32 *done_len);
+int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, u8 *iobuf,
+ u32 len, struct completion *comp);
+int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg);
+u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len);
+int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset);
+int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
+ u32 pipe_reg);
+void msm_slim_sps_exit(struct msm_slim_ctrl *dev);
+#endif
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 4a79f76..c26da60 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1298,6 +1298,7 @@
container_of(work, struct msm_spi, work_data);
unsigned long flags;
u32 status_error = 0;
+ int rc = 0;
mutex_lock(&dd->core_lock);
@@ -1308,6 +1309,21 @@
if (dd->use_rlock)
remote_mutex_lock(&dd->r_lock);
+ /* Configure the spi clk, miso, mosi and cs gpio */
+ if (dd->pdata->gpio_config) {
+ rc = dd->pdata->gpio_config();
+ if (rc) {
+ dev_err(dd->dev,
+ "%s: error configuring GPIOs\n",
+ __func__);
+ status_error = 1;
+ }
+ }
+
+ rc = msm_spi_request_gpios(dd);
+ if (rc)
+ status_error = 1;
+
clk_prepare_enable(dd->clk);
clk_prepare_enable(dd->pclk);
msm_spi_enable_irqs(dd);
@@ -1339,6 +1355,12 @@
clk_disable_unprepare(dd->clk);
clk_disable_unprepare(dd->pclk);
+ /* Free the spi clk, miso, mosi, cs gpio */
+ if (!rc && dd->pdata && dd->pdata->gpio_release)
+ dd->pdata->gpio_release();
+ if (!rc)
+ msm_spi_free_gpios(dd);
+
if (dd->use_rlock)
remote_mutex_unlock(&dd->r_lock);
@@ -1425,6 +1447,24 @@
if (dd->use_rlock)
remote_mutex_lock(&dd->r_lock);
+ /* Configure the spi clk, miso, mosi, cs gpio */
+ if (dd->pdata->gpio_config) {
+ rc = dd->pdata->gpio_config();
+ if (rc) {
+ dev_err(&spi->dev,
+ "%s: error configuring GPIOs\n",
+ __func__);
+ rc = -ENXIO;
+ goto err_setup_gpio;
+ }
+ }
+
+ rc = msm_spi_request_gpios(dd);
+ if (rc) {
+ rc = -ENXIO;
+ goto err_setup_gpio;
+ }
+
clk_prepare_enable(dd->clk);
clk_prepare_enable(dd->pclk);
@@ -1457,10 +1497,15 @@
clk_disable_unprepare(dd->clk);
clk_disable_unprepare(dd->pclk);
+ /* Free the spi clk, miso, mosi, cs gpio */
+ if (dd->pdata && dd->pdata->gpio_release)
+ dd->pdata->gpio_release();
+ msm_spi_free_gpios(dd);
+
+err_setup_gpio:
if (dd->use_rlock)
remote_mutex_unlock(&dd->r_lock);
mutex_unlock(&dd->core_lock);
-
err_setup_exit:
return rc;
}
@@ -1897,22 +1942,9 @@
dd->use_dma = 1;
master->dma_alignment = dma_get_cache_alignment();
}
-
-skip_dma_resources:
- if (pdata->gpio_config) {
- rc = pdata->gpio_config();
- if (rc) {
- dev_err(&pdev->dev,
- "%s: error configuring GPIOs\n",
- __func__);
- goto err_probe_gpio;
- }
- }
}
- rc = msm_spi_request_gpios(dd);
- if (rc)
- goto err_probe_gpio;
+skip_dma_resources:
spin_lock_init(&dd->queue_lock);
mutex_init(&dd->core_lock);
@@ -1951,8 +1983,8 @@
dd->use_rlock = 1;
dd->pm_lat = pdata->pm_lat;
- pm_qos_add_request(&qos_req_list, PM_QOS_CPU_DMA_LATENCY,
- PM_QOS_DEFAULT_VALUE);
+ pm_qos_add_request(&qos_req_list, PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
}
mutex_lock(&dd->core_lock);
@@ -2082,10 +2114,6 @@
err_probe_reqmem:
destroy_workqueue(dd->workqueue);
err_probe_workq:
- msm_spi_free_gpios(dd);
-err_probe_gpio:
- if (pdata && pdata->gpio_release)
- pdata->gpio_release();
err_probe_res:
spi_master_put(master);
err_probe_exit:
@@ -2112,7 +2140,6 @@
/* Wait for transactions to end, or time out */
wait_event_interruptible(dd->continue_suspend, !dd->transfer_pending);
- msm_spi_free_gpios(dd);
suspend_exit:
return 0;
@@ -2129,7 +2156,6 @@
if (!dd)
goto resume_exit;
- BUG_ON(msm_spi_request_gpios(dd) != 0);
dd->suspended = 0;
resume_exit:
return 0;
@@ -2143,17 +2169,13 @@
{
struct spi_master *master = platform_get_drvdata(pdev);
struct msm_spi *dd = spi_master_get_devdata(master);
- struct msm_spi_platform_data *pdata = pdev->dev.platform_data;
pm_qos_remove_request(&qos_req_list);
spi_debugfs_exit(dd);
sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
msm_spi_teardown_dma(dd);
- if (pdata && pdata->gpio_release)
- pdata->gpio_release();
- msm_spi_free_gpios(dd);
clk_put(dd->clk);
clk_put(dd->pclk);
destroy_workqueue(dd->workqueue);
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index ae1eff8..45429a1 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -638,6 +638,12 @@
return -ENODEV;
pmic_arb->channel = (u8)prop;
+ ret = irq_set_irq_wake(pmic_arb->pic_irq, 1);
+ if (unlikely(ret)) {
+ pr_err("Unable to set wakeup irq, err=%d\n", ret);
+ return -ENODEV;
+ }
+
pmic_arb->dev = &pdev->dev;
platform_set_drvdata(pdev, pmic_arb);
spmi_set_ctrldata(&pmic_arb->controller, pmic_arb);
@@ -679,6 +685,7 @@
spmi_del_controller(&pmic_arb->controller);
err_add_controller:
platform_set_drvdata(pdev, NULL);
+ irq_set_irq_wake(pmic_arb->pic_irq, 0);
return ret;
}
@@ -686,7 +693,7 @@
{
struct spmi_pmic_arb_dev *pmic_arb = platform_get_drvdata(pdev);
- free_irq(pmic_arb->pic_irq, pmic_arb);
+ irq_set_irq_wake(pmic_arb->pic_irq, 0);
platform_set_drvdata(pdev, NULL);
spmi_del_controller(&pmic_arb->controller);
return 0;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 6917b2d..b71bd3e 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -34,6 +34,7 @@
#include <linux/regulator/consumer.h>
#include <mach/rpm-regulator.h>
+#include <mach/msm_bus.h>
#include "dwc3_otg.h"
#include "core.h"
@@ -103,10 +104,12 @@
*/
#define QSCRATCH_REG_OFFSET (0x000F8800)
#define QSCRATCH_GENERAL_CFG (QSCRATCH_REG_OFFSET + 0x08)
+#define HS_PHY_CTRL_REG (QSCRATCH_REG_OFFSET + 0x10)
#define CHARGING_DET_CTRL_REG (QSCRATCH_REG_OFFSET + 0x18)
#define CHARGING_DET_OUTPUT_REG (QSCRATCH_REG_OFFSET + 0x1C)
#define ALT_INTERRUPT_EN_REG (QSCRATCH_REG_OFFSET + 0x20)
#define HS_PHY_IRQ_STAT_REG (QSCRATCH_REG_OFFSET + 0x24)
+#define SS_PHY_CTRL_REG (QSCRATCH_REG_OFFSET + 0x30)
struct dwc3_msm_req_complete {
struct list_head list_item;
@@ -147,6 +150,8 @@
struct delayed_work chg_work;
enum usb_chg_state chg_state;
u8 dcd_retries;
+ u32 bus_perf_client;
+ struct msm_bus_scale_pdata *bus_scale_table;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -1224,6 +1229,8 @@
static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
{
+ int ret;
+
dev_dbg(mdwc->dev, "%s: entering lpm\n", __func__);
if (atomic_read(&mdwc->in_lpm)) {
@@ -1238,6 +1245,13 @@
dwc3_ssusb_ldo_enable(0);
wake_unlock(&mdwc->wlock);
+ if (mdwc->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ mdwc->bus_perf_client, 0);
+ if (ret)
+ dev_err(mdwc->dev, "Failed to reset bus bw vote\n");
+ }
+
atomic_set(&mdwc->in_lpm, 1);
dev_info(mdwc->dev, "DWC3 in low power mode\n");
@@ -1246,6 +1260,8 @@
static int dwc3_msm_resume(struct dwc3_msm *mdwc)
{
+ int ret;
+
dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
if (!atomic_read(&mdwc->in_lpm)) {
@@ -1253,6 +1269,13 @@
return 0;
}
+ if (mdwc->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ mdwc->bus_perf_client, 1);
+ if (ret)
+ dev_err(mdwc->dev, "Failed to vote for bus scaling\n");
+ }
+
wake_lock(&mdwc->wlock);
clk_prepare_enable(mdwc->ref_clk);
clk_prepare_enable(mdwc->core_clk);
@@ -1573,6 +1596,27 @@
msm->resource_size = resource_size(res);
msm->dwc3 = dwc3;
+ /* SSPHY Initialization: Use ref_clk from pads and set its parameters */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ msleep(30);
+ /* Assert SSPHY reset */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+ usleep_range(2000, 2200);
+ /* De-assert SSPHY reset - power and ref_clock must be ON */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ usleep_range(2000, 2200);
+ /* Ref clock must be stable now, enable ref clock for HS mode */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+ usleep_range(2000, 2200);
+ /*
+ * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
+ * and disable RETENTION (power-on default is ENABLED)
+ */
+ dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+ usleep_range(2000, 2200);
+ /* Disable (bypass) VBUS filter */
+ dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x38);
+
pm_runtime_set_active(msm->dev);
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
@@ -1604,6 +1648,18 @@
goto put_pdev;
}
+ msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+ if (!msm->bus_scale_table) {
+ dev_err(&pdev->dev, "bus scaling is disabled\n");
+ } else {
+ msm->bus_perf_client =
+ msm_bus_scale_register_client(msm->bus_scale_table);
+ ret = msm_bus_scale_client_update_request(
+ msm->bus_perf_client, 1);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
+ }
+
/* Reset the DBM */
dwc3_msm_dbm_soft_reset(1);
usleep_range(1000, 1200);
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 90de7a4..a50f76b 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -50,7 +50,7 @@
* space, see dwc3_probe in core.c.
* However, the offsets are given starting from xHCI address space.
*/
- return readl_relaxed(base + (offset - DWC3_GLOBALS_REGS_START));
+ return readl(base + (offset - DWC3_GLOBALS_REGS_START));
}
static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
@@ -60,7 +60,7 @@
* space, see dwc3_probe in core.c.
* However, the offsets are given starting from xHCI address space.
*/
- writel_relaxed(value, base + (offset - DWC3_GLOBALS_REGS_START));
+ writel(value, base + (offset - DWC3_GLOBALS_REGS_START));
}
#endif /* __DRIVERS_USB_DWC3_IO_H */
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 23f6ea3..a6eb335 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -30,6 +30,8 @@
#include <linux/usb/gadget.h>
#include <linux/usb/android.h>
+#include <mach/diag_dload.h>
+
#include "gadget_chips.h"
/*
@@ -163,6 +165,7 @@
struct list_head list_item;
};
+struct dload_struct __iomem *diag_dload;
static struct class *android_class;
static struct list_head android_dev_list;
static int android_dev_count;
@@ -173,6 +176,7 @@
(struct android_dev *dev);
static void free_android_config(struct android_dev *dev,
struct android_configuration *conf);
+static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum);
/* string IDs are assigned dynamically */
#define STRING_MANUFACTURER_IDX 0
@@ -741,8 +745,12 @@
notify = NULL;
name = strsep(&b, ",");
/* Allow only first diag channel to update pid and serial no */
- if (dev->pdata && !once++)
- notify = dev->pdata->update_pid_and_serial_num;
+ if (!once++) {
+ if (dev->pdata && dev->pdata->update_pid_and_serial_num)
+ notify = dev->pdata->update_pid_and_serial_num;
+ else
+ notify = usb_diag_update_pid_and_serial_num;
+ }
if (name) {
err = diag_function_add(c, name, notify);
@@ -2239,10 +2247,49 @@
kfree(conf);
}
+static int usb_diag_update_pid_and_serial_num(u32 pid, const char *snum)
+{
+ struct dload_struct local_diag_dload = { 0 };
+ int *src, *dst, i;
+
+ if (!diag_dload) {
+ pr_debug("%s: unable to update PID and serial_no\n", __func__);
+ return -ENODEV;
+ }
+
+ pr_debug("%s: dload:%p pid:%x serial_num:%s\n",
+ __func__, diag_dload, pid, snum);
+
+ /* update pid */
+ local_diag_dload.magic_struct.pid = PID_MAGIC_ID;
+ local_diag_dload.pid = pid;
+
+ /* update serial number */
+ if (!snum) {
+ local_diag_dload.magic_struct.serial_num = 0;
+ memset(&local_diag_dload.serial_number, 0,
+ SERIAL_NUMBER_LENGTH);
+ } else {
+ local_diag_dload.magic_struct.serial_num = SERIAL_NUM_MAGIC_ID;
+ strlcpy((char *)&local_diag_dload.serial_number, snum,
+ SERIAL_NUMBER_LENGTH);
+ }
+
+ /* Copy to shared struct (accesses need to be 32 bit aligned) */
+ src = (int *)&local_diag_dload;
+ dst = (int *)diag_dload;
+
+ for (i = 0; i < sizeof(*diag_dload) / 4; i++)
+ *dst++ = *src++;
+
+ return 0;
+}
+
static int __devinit android_probe(struct platform_device *pdev)
{
struct android_usb_platform_data *pdata = pdev->dev.platform_data;
struct android_dev *android_dev;
+ struct resource *res;
int ret = 0;
if (!android_class) {
@@ -2277,6 +2324,19 @@
else
composite_driver.usb_core_id = 0; /*To backward compatibility*/
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res) {
+ diag_dload = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!diag_dload) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_dev;
+ }
+ } else {
+ dev_dbg(&pdev->dev, "failed to get mem resource\n");
+ }
+
ret = android_create_device(android_dev, composite_driver.usb_core_id);
if (ret) {
pr_err("%s(): android_create_device failed\n", __func__);
@@ -2355,8 +2415,17 @@
},
};
+static struct of_device_id usb_android_dt_match[] = {
+ { .compatible = "qcom,android-usb",
+ },
+ {}
+};
+
static struct platform_driver android_platform_driver = {
- .driver = { .name = "android_usb"},
+ .driver = {
+ .name = "android_usb",
+ .of_match_table = usb_android_dt_match,
+ },
.probe = android_probe,
.remove = android_remove,
.id_table = android_id_table,
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 1d0b6d4..aa9daf3 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -488,6 +488,8 @@
break;
case USB_GADGET_XPORT_HSIC:
break;
+ case USB_GADGET_XPORT_HSUART:
+ break;
case USB_GADGET_XPORT_NONE:
break;
default:
@@ -515,6 +517,8 @@
break;
case USB_GADGET_XPORT_HSIC:
break;
+ case USB_GADGET_XPORT_HSUART:
+ break;
case USB_GADGET_XPORT_NONE:
break;
default:
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 59ff8d7..02f044e 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -25,6 +25,10 @@
#include "u_ether.h"
#include "rndis.h"
+static bool rndis_multipacket_dl_disable;
+module_param(rndis_multipacket_dl_disable, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(rndis_multipacket_dl_disable,
+ "Disable RNDIS Multi-packet support in DownLink");
/*
* This function is an RNDIS Ethernet port -- a Microsoft protocol that's
@@ -469,6 +473,8 @@
__func__, buf->MaxTransferSize,
rndis->port.multi_pkt_xfer ? "enabled" :
"disabled");
+ if (rndis_multipacket_dl_disable)
+ rndis->port.multi_pkt_xfer = 0;
}
// spin_unlock(&dev->lock);
}
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index fd10394..b84c74d 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -292,6 +292,10 @@
status = dev->unwrap(dev->port_usb,
skb,
&dev->rx_frames);
+ if (status == -EINVAL)
+ dev->net->stats.rx_errors++;
+ else if (status == -EOVERFLOW)
+ dev->net->stats.rx_over_errors++;
} else {
dev_kfree_skb_any(skb);
status = -ENOTCONN;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 3c39cc8..a6d8c17 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -3437,6 +3437,11 @@
pdata = msm_otg_dt_to_pdata(pdev);
if (!pdata)
return -ENOMEM;
+
+ pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+ if (!pdata->bus_scale_table)
+ dev_dbg(&pdev->dev, "bus scaling is disabled\n");
+
ret = msm_otg_setup_devices(pdev, pdata->mode, true);
if (ret) {
dev_err(&pdev->dev, "devices setup failed\n");
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 4fc78cd..6e3567f 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -53,7 +53,7 @@
u32 mdp_max_clk = 200000000;
static struct platform_device *mdp_init_pdev;
-static struct regulator *footswitch;
+static struct regulator *footswitch, *dsi_pll_vdda, *dsi_pll_vddio;
static unsigned int mdp_footswitch_on;
struct completion mdp_ppp_comp;
@@ -2244,18 +2244,40 @@
}
disable_irq(mdp_irq);
+ dsi_pll_vdda = regulator_get(&pdev->dev, "dsi_pll_vdda");
+ if (IS_ERR(dsi_pll_vdda)) {
+ dsi_pll_vdda = NULL;
+ } else {
+ if (mdp_rev == MDP_REV_42 || mdp_rev == MDP_REV_44) {
+ ret = regulator_set_voltage(dsi_pll_vdda, 1200000,
+ 1200000);
+ if (ret) {
+ pr_err("set_voltage failed for dsi_pll_vdda, ret=%d\n",
+ ret);
+ }
+ }
+ }
+
+ dsi_pll_vddio = regulator_get(&pdev->dev, "dsi_pll_vddio");
+ if (IS_ERR(dsi_pll_vddio)) {
+ dsi_pll_vddio = NULL;
+ } else {
+ if (mdp_rev == MDP_REV_42) {
+ ret = regulator_set_voltage(dsi_pll_vddio, 1800000,
+ 1800000);
+ if (ret) {
+ pr_err("set_voltage failed for dsi_pll_vddio, ret=%d\n",
+ ret);
+ }
+ }
+ }
+
footswitch = regulator_get(&pdev->dev, "vdd");
- if (IS_ERR(footswitch))
+ if (IS_ERR(footswitch)) {
footswitch = NULL;
- else {
+ } else {
regulator_enable(footswitch);
mdp_footswitch_on = 1;
-
- if (mdp_rev == MDP_REV_42 && !cont_splashScreen) {
- regulator_disable(footswitch);
- msleep(20);
- regulator_enable(footswitch);
- }
}
mdp_clk = clk_get(&pdev->dev, "core_clk");
@@ -2306,6 +2328,17 @@
MSM_FB_DEBUG("mdp_clk: mdp_clk=%d\n", (int)clk_get_rate(mdp_clk));
#endif
+
+ if (mdp_rev == MDP_REV_42 && !cont_splashScreen) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ /* DSI Video Timing generator disable */
+ outpdw(MDP_BASE + 0xE0000, 0x0);
+ /* Clear MDP Interrupt Enable register */
+ outpdw(MDP_BASE + 0x50, 0x0);
+ /* Set Overlay Proc 0 to reset state */
+ outpdw(MDP_BASE + 0x10004, 0x3);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
return 0;
}
@@ -2324,6 +2357,7 @@
struct mipi_panel_info *mipi;
#endif
static int contSplash_update_done;
+ char *cp;
if ((pdev->id == 0) && (pdev->num_resources > 0)) {
mdp_init_pdev = pdev;
@@ -2398,7 +2432,44 @@
if (mdp_pdata) {
if (mdp_pdata->cont_splash_enabled) {
mfd->cont_splash_done = 0;
+
if (!contSplash_update_done) {
+ uint32 bpp = 3;
+ /*read panel wxh and calculate splash screen
+ size*/
+ mdp_pdata->splash_screen_size =
+ inpdw(MDP_BASE + 0x90004);
+ mdp_pdata->splash_screen_size =
+ (((mdp_pdata->splash_screen_size >> 16) &
+ 0x00000FFF) * (
+ mdp_pdata->splash_screen_size &
+ 0x00000FFF)) * bpp;
+
+ mdp_pdata->splash_screen_addr =
+ inpdw(MDP_BASE + 0x90008);
+
+ mfd->copy_splash_buf = dma_alloc_coherent(NULL,
+ mdp_pdata->splash_screen_size,
+ (dma_addr_t *) &(mfd->copy_splash_phys),
+ GFP_KERNEL);
+
+ if (!mfd->copy_splash_buf) {
+ pr_err("DMA ALLOC FAILED for SPLASH\n");
+ return -ENOMEM;
+ }
+ cp = (char *)ioremap(
+ mdp_pdata->splash_screen_addr,
+ mdp_pdata->splash_screen_size);
+ if (!cp) {
+ pr_err("IOREMAP FAILED for SPLASH\n");
+ return -ENOMEM;
+ }
+ memcpy(mfd->copy_splash_buf, cp,
+ mdp_pdata->splash_screen_size);
+
+ MDP_OUTP(MDP_BASE + 0x90008,
+ mfd->copy_splash_phys);
+
if (mfd->panel.type == MIPI_VIDEO_PANEL ||
mfd->panel.type == LCDC_PANEL)
mdp_pipe_ctrl(MDP_CMD_BLOCK,
@@ -2774,6 +2845,17 @@
return;
}
+ if (dsi_pll_vddio)
+ regulator_enable(dsi_pll_vddio);
+
+ if (dsi_pll_vdda)
+ regulator_enable(dsi_pll_vdda);
+
+ mipi_dsi_prepare_clocks();
+ mipi_dsi_ahb_ctrl(1);
+ mipi_dsi_phy_ctrl(1);
+ mipi_dsi_clk_enable();
+
if (on && !mdp_footswitch_on) {
pr_debug("Enable MDP FS\n");
regulator_enable(footswitch);
@@ -2784,9 +2866,31 @@
mdp_footswitch_on = 0;
}
+ mipi_dsi_clk_disable();
+ mipi_dsi_phy_ctrl(0);
+ mipi_dsi_ahb_ctrl(0);
+ mipi_dsi_unprepare_clocks();
+
+ if (dsi_pll_vdda)
+ regulator_disable(dsi_pll_vdda);
+
+ if (dsi_pll_vddio)
+ regulator_disable(dsi_pll_vddio);
+
mutex_unlock(&mdp_suspend_mutex);
}
+void mdp_free_splash_buffer(struct msm_fb_data_type *mfd)
+{
+ if (mfd->copy_splash_buf) {
+ dma_free_coherent(NULL, mdp_pdata->splash_screen_size,
+ mfd->copy_splash_buf,
+ (dma_addr_t) mfd->copy_splash_phys);
+
+ mfd->copy_splash_buf = NULL;
+ }
+}
+
#ifdef CONFIG_PM
static void mdp_suspend_sub(void)
{
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index af5a661..2825f87 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -764,7 +764,7 @@
int mdp_lcdc_on(struct platform_device *pdev);
int mdp_lcdc_off(struct platform_device *pdev);
void mdp_lcdc_update(struct msm_fb_data_type *mfd);
-
+void mdp_free_splash_buffer(struct msm_fb_data_type *mfd);
#ifdef CONFIG_FB_MSM_MDP303
int mdp_dsi_video_on(struct platform_device *pdev);
int mdp_dsi_video_off(struct platform_device *pdev);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index b88ff72..9278029 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -1172,6 +1172,41 @@
return rc;
} /* hdmi_tx_clk_ctrl_update */
+static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl,
+ enum hdmi_tx_power_module_type module, int config)
+{
+ int rc = 0;
+ struct dss_module_power *power_data = NULL;
+
+ if (!hdmi_ctrl || module >= HDMI_TX_MAX_PM) {
+ DEV_ERR("%s: Error: invalid input\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ power_data = &hdmi_ctrl->pdata.power_data[module];
+ if (!power_data) {
+ DEV_ERR("%s: Error: invalid power data\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ if (config)
+ rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
+ power_data->vreg_config, power_data->num_vreg, 1);
+ else
+ rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
+ power_data->vreg_config, power_data->num_vreg, 0);
+
+ if (rc)
+ DEV_ERR("%s: Failed to %s %s vreg. Error=%d\n",
+ __func__, config ? "config" : "deconfig",
+ hdmi_pm_name(module), rc);
+
+exit:
+ return rc;
+} /* hdmi_tx_config_power */
+
static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
enum hdmi_tx_power_module_type module, int enable)
{
@@ -1192,20 +1227,12 @@
}
if (enable) {
- rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
- power_data->vreg_config, power_data->num_vreg, 1);
- if (rc) {
- DEV_ERR("%s: Failed to config %s vreg. Error=%d\n",
- __func__, hdmi_pm_name(module), rc);
- return rc;
- }
-
rc = msm_dss_enable_vreg(power_data->vreg_config,
power_data->num_vreg, 1);
if (rc) {
DEV_ERR("%s: Failed to enable %s vreg. Error=%d\n",
__func__, hdmi_pm_name(module), rc);
- goto deconfig_vreg;
+ goto error;
}
rc = msm_dss_enable_gpio(power_data->gpio_config,
@@ -1218,15 +1245,14 @@
} else {
msm_dss_enable_gpio(power_data->gpio_config,
power_data->num_gpio, 0);
+ msm_dss_enable_vreg(power_data->vreg_config,
+ power_data->num_vreg, 0);
}
return rc;
disable_vreg:
msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0);
-deconfig_vreg:
- msm_dss_config_vreg(&hdmi_ctrl->pdev->dev, power_data->vreg_config,
- power_data->num_vreg, 0);
error:
return rc;
} /* hdmi_tx_enable_power */
@@ -1833,6 +1859,84 @@
return rc;
} /* hdmi_tx_register_panel */
+static void hdmi_tx_deinit_resource(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int i;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ /* CLK */
+ hdmi_tx_clk_deinit(&hdmi_ctrl->pdata);
+
+ /* VREG */
+ for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--) {
+ if (hdmi_tx_config_power(hdmi_ctrl, i, 0))
+ DEV_ERR("%s: '%s' power deconfig fail\n",
+ __func__, hdmi_pm_name(i));
+ }
+
+ /* IO */
+ for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--) {
+ if (hdmi_ctrl->pdata.io[i].base)
+ iounmap(hdmi_ctrl->pdata.io[i].base);
+ hdmi_ctrl->pdata.io[i].base = NULL;
+ hdmi_ctrl->pdata.io[i].len = 0;
+ }
+} /* hdmi_tx_deinit_resource */
+
+static int hdmi_tx_init_resource(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int i, rc = 0;
+ struct hdmi_tx_platform_data *pdata = NULL;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ pdata = &hdmi_ctrl->pdata;
+
+ /* IO */
+ for (i = 0; i < HDMI_TX_MAX_IO; i++) {
+ rc = msm_dss_ioremap_byname(hdmi_ctrl->pdev, &pdata->io[i],
+ hdmi_tx_io_name(i));
+ if (rc) {
+ DEV_ERR("%s: '%s' remap failed\n", __func__,
+ hdmi_tx_io_name(i));
+ goto error;
+ }
+ DEV_INFO("%s: '%s': start = 0x%x, len=0x%x\n", __func__,
+ hdmi_tx_io_name(i), (u32)pdata->io[i].base,
+ pdata->io[i].len);
+ }
+
+ /* VREG */
+ for (i = 0; i < HDMI_TX_MAX_PM; i++) {
+ rc = hdmi_tx_config_power(hdmi_ctrl, i, 1);
+ if (rc) {
+ DEV_ERR("%s: '%s' power config failed.rc=%d\n",
+ __func__, hdmi_pm_name(i), rc);
+ goto error;
+ }
+ }
+
+ /* CLK */
+ rc = hdmi_tx_clk_init(hdmi_ctrl->pdev, pdata);
+ if (rc) {
+ DEV_ERR("%s: FAILED: clk init. rc=%d\n", __func__, rc);
+ goto error;
+ }
+
+ return rc;
+
+error:
+ hdmi_tx_deinit_resource(hdmi_ctrl);
+ return rc;
+} /* hdmi_tx_init_resource */
+
static void hdmi_tx_put_dt_vreg_data(struct device *dev,
struct dss_module_power *module_power)
{
@@ -2179,20 +2283,11 @@
return;
}
- hdmi_tx_clk_deinit(pdata);
-
for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
hdmi_tx_put_dt_vreg_data(dev, &pdata->power_data[i]);
for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
hdmi_tx_put_dt_gpio_data(dev, &pdata->power_data[i]);
-
- for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--) {
- if (pdata->io[i].base)
- iounmap(pdata->io[i].base);
- pdata->io[i].base = NULL;
- pdata->io[i].len = 0;
- }
} /* hdmi_tx_put_dt_data */
static int hdmi_tx_get_dt_data(struct platform_device *pdev,
@@ -2216,20 +2311,6 @@
}
DEV_DBG("%s: id=%d\n", __func__, pdev->id);
- /* IO */
- for (i = 0; i < HDMI_TX_MAX_IO; i++) {
- rc = msm_dss_ioremap_byname(pdev, &pdata->io[i],
- hdmi_tx_io_name(i));
- if (rc) {
- DEV_ERR("%s: '%s' remap failed\n", __func__,
- hdmi_tx_io_name(i));
- goto error;
- }
- DEV_INFO("%s: '%s': start = 0x%x, len=0x%x\n", __func__,
- hdmi_tx_io_name(i), (u32)pdata->io[i].base,
- pdata->io[i].len);
- }
-
/* GPIO */
for (i = 0; i < HDMI_TX_MAX_PM; i++) {
rc = hdmi_tx_get_dt_gpio_data(&pdev->dev,
@@ -2252,13 +2333,6 @@
}
}
- /* CLK */
- rc = hdmi_tx_clk_init(pdev, pdata);
- if (rc) {
- DEV_ERR("%s: FAILED: clk init. rc=%d\n", __func__, rc);
- goto error;
- }
-
return rc;
error:
@@ -2295,6 +2369,13 @@
goto failed_dt_data;
}
+ rc = hdmi_tx_init_resource(hdmi_ctrl);
+ if (rc) {
+ DEV_ERR("%s: FAILED: resource init. rc=%d\n",
+ __func__, rc);
+ goto failed_res_init;
+ }
+
rc = hdmi_tx_dev_init(hdmi_ctrl);
if (rc) {
DEV_ERR("%s: FAILED: hdmi_tx_dev_init. rc=%d\n", __func__, rc);
@@ -2327,6 +2408,8 @@
failed_reg_panel:
hdmi_tx_dev_deinit(hdmi_ctrl);
failed_dev_init:
+ hdmi_tx_deinit_resource(hdmi_ctrl);
+failed_res_init:
hdmi_tx_put_dt_data(&pdev->dev, &hdmi_ctrl->pdata);
failed_dt_data:
devm_kfree(&pdev->dev, hdmi_ctrl);
@@ -2344,6 +2427,7 @@
hdmi_tx_sysfs_remove(hdmi_ctrl);
hdmi_tx_dev_deinit(hdmi_ctrl);
+ hdmi_tx_deinit_resource(hdmi_ctrl);
hdmi_tx_put_dt_data(&pdev->dev, &hdmi_ctrl->pdata);
devm_kfree(&hdmi_ctrl->pdev->dev, hdmi_ctrl);
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index c121772..65d08d3 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -32,7 +32,7 @@
{
struct resource *res = NULL;
- if (!pdev) {
+ if (!pdev || !io_data) {
pr_err("%s: invalid input\n", __func__);
return -EINVAL;
}
@@ -65,10 +65,11 @@
curr_vreg = &in_vreg[i];
curr_vreg->vreg = regulator_get(dev,
curr_vreg->vreg_name);
- if (IS_ERR(curr_vreg->vreg)) {
- pr_err("%s: %s get failed\n",
+ rc = IS_ERR(curr_vreg->vreg);
+ if (rc) {
+ pr_err("%s: %s get failed. rc=%d\n",
__func__,
- curr_vreg->vreg_name);
+ curr_vreg->vreg_name, rc);
curr_vreg->vreg = NULL;
goto vreg_get_fail;
}
@@ -100,8 +101,7 @@
} else {
for (i = num_vreg-1; i >= 0; i--) {
curr_vreg = &in_vreg[i];
- if (curr_vreg->vreg &&
- regulator_is_enabled(curr_vreg->vreg)) {
+ if (curr_vreg->vreg) {
if (curr_vreg->type == DSS_REG_LDO) {
if (curr_vreg->optimum_voltage >= 0) {
regulator_set_optimum_mode(
@@ -134,7 +134,7 @@
curr_vreg = &in_vreg[i];
goto vreg_unconfig;
}
- return -EPERM;
+ return rc;
} /* msm_dss_config_vreg */
int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg, int enable)
@@ -142,9 +142,10 @@
int i = 0, rc = 0;
if (enable) {
for (i = 0; i < num_vreg; i++) {
- if (IS_ERR(in_vreg[i].vreg)) {
- pr_err("%s: %s null regulator\n",
- __func__, in_vreg[i].vreg_name);
+ rc = IS_ERR(in_vreg[i].vreg);
+ if (rc) {
+ pr_err("%s: %s regulator error. rc=%d\n",
+ __func__, in_vreg[i].vreg_name, rc);
goto disable_vreg;
}
rc = regulator_enable(in_vreg[i].vreg);
@@ -156,7 +157,8 @@
}
} else {
for (i = num_vreg-1; i >= 0; i--)
- regulator_disable(in_vreg[i].vreg);
+ if (regulator_is_enabled(in_vreg[i].vreg))
+ regulator_disable(in_vreg[i].vreg);
}
return rc;
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index a7832ed..0f37f6f 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -311,8 +311,6 @@
void mipi_dsi_set_tear_off(struct msm_fb_data_type *mfd);
void mipi_dsi_set_backlight(struct msm_fb_data_type *mfd, int level);
void mipi_dsi_cmd_backlight_tx(struct dsi_buf *dp);
-void mipi_dsi_clk_enable(void);
-void mipi_dsi_clk_disable(void);
void mipi_dsi_pre_kickoff_action(void);
void mipi_dsi_post_kickoff_action(void);
void mipi_dsi_pre_kickoff_add(struct dsi_kickoff_action *act);
@@ -326,16 +324,47 @@
irqreturn_t mipi_dsi_isr(int irq, void *ptr);
void mipi_set_tx_power_mode(int mode);
-void mipi_dsi_phy_ctrl(int on);
void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info,
int target_type);
int mipi_dsi_clk_div_config(uint8 bpp, uint8 lanes,
uint32 *expected_dsi_pclk);
int mipi_dsi_clk_init(struct platform_device *pdev);
void mipi_dsi_clk_deinit(struct device *dev);
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+void mipi_dsi_clk_enable(void);
+void mipi_dsi_clk_disable(void);
void mipi_dsi_prepare_clocks(void);
void mipi_dsi_unprepare_clocks(void);
void mipi_dsi_ahb_ctrl(u32 enable);
+void mipi_dsi_phy_ctrl(int on);
+#else
+static inline void mipi_dsi_clk_enable(void)
+{
+ /* empty */
+}
+void mipi_dsi_clk_disable(void)
+{
+ /* empty */
+}
+void mipi_dsi_prepare_clocks(void)
+{
+ /* empty */
+}
+void mipi_dsi_unprepare_clocks(void)
+{
+ /* empty */
+}
+void mipi_dsi_ahb_ctrl(u32 enable)
+{
+ /* empty */
+}
+void mipi_dsi_phy_ctrl(int on)
+{
+ /* empty */
+}
+#endif
+
void cont_splash_clk_ctrl(int enable);
void mipi_dsi_turn_on_clks(void);
void mipi_dsi_turn_off_clks(void);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 0f014cf..9c55fe8 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1820,6 +1820,9 @@
schedule_delayed_work(&mfd->backlight_worker,
backlight_duration);
+ if (info->node == 0 && (mfd->cont_splash_done)) /* primary */
+ mdp_free_splash_buffer(mfd);
+
++mfd->panel_info.frame_count;
return 0;
}
@@ -2993,6 +2996,9 @@
schedule_delayed_work(&mfd->backlight_worker,
backlight_duration);
+ if (info->node == 0 && (mfd->cont_splash_done)) /* primary */
+ mdp_free_splash_buffer(mfd);
+
return ret;
}
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 1696a1a..2896349 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -187,6 +187,8 @@
u32 writeback_state;
bool writeback_active_cnt;
int cont_splash_done;
+ void *copy_splash_buf;
+ unsigned char *copy_splash_phys;
};
struct dentry *msm_fb_get_debugfs_root(void);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index c1e460f..bfc27dc 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -1175,20 +1175,28 @@
&(decoder->dec_disp_info);
struct ddl_frame_data_tag *output_frame = &(ddl->output_frame);
struct vcd_frame_data *output_vcd_frm = &(output_frame->vcd_frm);
+ enum vidc_1080p_decode_frame frame_type = 0;
u32 vcd_status, free_luma_dpb = 0, disp_pict = 0, is_interlaced;
+ u32 idr_frame = 0, coded_frame = 0;
get_dec_op_done_data(dec_disp_info, decoder->output_order,
&output_vcd_frm->physical, &is_interlaced);
decoder->progressive_only = !(is_interlaced);
output_vcd_frm->frame = VCD_FRAME_YUV;
+ vidc_sm_get_displayed_picture_frame(&ddl->shared_mem
+ [ddl->command_channel], &disp_pict);
+ coded_frame = (disp_pict & 0x03);
+ idr_frame = (disp_pict & 0x20) >> 5;
+ if (idr_frame)
+ frame_type = VIDC_1080P_DECODE_FRAMETYPE_IDR;
+ else
+ frame_type = (disp_pict & 0x1c) >> 2;
if (decoder->codec.codec == VCD_CODEC_MPEG4 ||
decoder->codec.codec == VCD_CODEC_VC1 ||
decoder->codec.codec == VCD_CODEC_VC1_RCV ||
(decoder->codec.codec >= VCD_CODEC_DIVX_3 &&
decoder->codec.codec <= VCD_CODEC_XVID)) {
- vidc_sm_get_displayed_picture_frame(&ddl->shared_mem
- [ddl->command_channel], &disp_pict);
if (decoder->output_order == VCD_DEC_ORDER_DISPLAY) {
- if (!disp_pict) {
+ if (!coded_frame) {
output_vcd_frm->frame = VCD_FRAME_NOTCODED;
vidc_sm_get_available_luma_dpb_address(
&ddl->shared_mem[ddl->command_channel],
@@ -1213,6 +1221,7 @@
DDL_MSG_ERROR("CORRUPTED_OUTPUT_BUFFER_ADDRESS");
ddl_hw_fatal_cb(ddl);
} else {
+ ddl_get_decoded_frame(output_vcd_frm, frame_type);
vidc_sm_get_metadata_status(&ddl->shared_mem
[ddl->command_channel],
&decoder->meta_data_exists);
@@ -1347,6 +1356,10 @@
case VIDC_1080P_DECODE_FRAMETYPE_OTHERS:
frame->frame = VCD_FRAME_YUV;
break;
+ case VIDC_1080P_DECODE_FRAMETYPE_IDR:
+ frame->flags |= VCD_FRAME_FLAG_SYNCFRAME;
+ frame->frame = VCD_FRAME_IDR;
+ break;
case VIDC_1080P_DECODE_FRAMETYPE_32BIT:
default:
DDL_MSG_ERROR("UNKNOWN-FRAMETYPE");
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 07b2fe2..8099234 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
@@ -45,7 +45,7 @@
#define VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_PROFILE_SHFT 0
#define VIDC_SM_DISP_PIC_FRAME_TYPE_ADDR 0x00c0
-#define VIDC_SM_DISP_PIC_FRAME_TYPE_BMSK 0x00000003
+#define VIDC_SM_DISP_PIC_FRAME_TYPE_BMSK 0x0000003f
#define VIDC_SM_DISP_PIC_FRAME_TYPE_SHFT 0
#define VIDC_SM_FREE_LUMA_DPB_ADDR 0x00c4
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c
index d399847..3c445bc 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c
@@ -520,8 +520,12 @@
u32 frame = 0;
VIDC_HWIO_IN(REG_760102, &frame);
- *pe_frame = (enum vidc_1080p_decode_frame)
- (frame & VIDC_1080P_SI_RG8_DECODE_FRAMETYPE_MASK);
+ if (frame & 0x10)
+ *pe_frame = (enum vidc_1080p_decode_frame)
+ VIDC_1080P_DECODE_FRAMETYPE_IDR;
+ else
+ *pe_frame = (enum vidc_1080p_decode_frame)
+ (frame & VIDC_1080P_SI_RG8_DECODE_FRAMETYPE_MASK);
}
void vidc_1080p_get_decode_frame_result(
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
index 7b8dc6f..22fcd1c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -277,6 +277,7 @@
VIDC_1080P_DECODE_FRAMETYPE_P = 2,
VIDC_1080P_DECODE_FRAMETYPE_B = 3,
VIDC_1080P_DECODE_FRAMETYPE_OTHERS = 4,
+ VIDC_1080P_DECODE_FRAMETYPE_IDR = 5,
VIDC_1080P_DECODE_FRAMETYPE_32BIT = 0x7FFFFFFF
};
enum vidc_1080P_decode_frame_correct_type {
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 2064e01..3ac396c 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -537,9 +537,9 @@
u32 enc_perf_level = 0, dec_perf_level = 0;
u32 bus_clk_index, client_type = 0;
int rc = 0;
-
- if (dev_ctxt->turbo_mode_set)
- return rc;
+ bool turbo_enabled = false;
+ bool turbo_supported =
+ !resource_context.vidc_platform_data->disable_turbo;
cctxt_itr = dev_ctxt->cctxt_list_head;
while (cctxt_itr) {
@@ -547,6 +547,9 @@
dec_perf_level += cctxt_itr->reqd_perf_lvl;
else
enc_perf_level += cctxt_itr->reqd_perf_lvl;
+
+ if (cctxt_itr->is_turbo_enabled)
+ turbo_enabled = true;
cctxt_itr = cctxt_itr->next;
}
@@ -563,15 +566,17 @@
if (dev_ctxt->reqd_perf_lvl + dev_ctxt->curr_perf_lvl == 0)
bus_clk_index = 2;
- else if (resource_context.vidc_platform_data->disable_turbo
- && bus_clk_index == 3) {
- VCDRES_MSG_ERROR("Warning: Turbo mode not supported "
- " falling back to 1080p bus\n");
+ else if ((!turbo_supported || !turbo_enabled) && bus_clk_index == 3) {
+ if (!turbo_supported)
+ VCDRES_MSG_MED("Warning: Turbo mode not supported "\
+ " falling back to 1080p bus\n");
bus_clk_index = 2;
}
if (bus_clk_index == 3)
- dev_ctxt->turbo_mode_set = 1;
+ dev_ctxt->turbo_mode_set = true;
+ else
+ dev_ctxt->turbo_mode_set = false;
bus_clk_index = (bus_clk_index << 1) + (client_type + 1);
VCDRES_MSG_LOW("%s(), bus_clk_index = %d", __func__, bus_clk_index);
@@ -587,21 +592,18 @@
struct vcd_dev_ctxt *dev_ctxt)
{
u32 vidc_freq = 0;
+ bool turbo_supported =
+ !resource_context.vidc_platform_data->disable_turbo;
+
if (!pn_set_perf_lvl || !dev_ctxt) {
VCDRES_MSG_ERROR("%s(): NULL pointer! dev_ctxt(%p)\n",
__func__, dev_ctxt);
return false;
}
- if (dev_ctxt->turbo_mode_set &&
- (req_perf_lvl < RESTRK_1080P_TURBO_PERF_LEVEL)) {
- VCDRES_MSG_MED("%s(): TURBO MODE!!\n", __func__);
- return true;
- }
VCDRES_MSG_LOW("%s(), req_perf_lvl = %d", __func__, req_perf_lvl);
- if (resource_context.vidc_platform_data->disable_turbo
- && req_perf_lvl > RESTRK_1080P_MAX_PERF_LEVEL) {
+ if (!turbo_supported && req_perf_lvl > RESTRK_1080P_MAX_PERF_LEVEL) {
VCDRES_MSG_ERROR("%s(): Turbo not supported! dev_ctxt(%p)\n",
__func__, dev_ctxt);
}
@@ -631,10 +633,11 @@
*pn_set_perf_lvl = RESTRK_1080P_TURBO_PERF_LEVEL;
}
- if (resource_context.vidc_platform_data->disable_turbo &&
- *pn_set_perf_lvl == RESTRK_1080P_TURBO_PERF_LEVEL) {
- VCDRES_MSG_ERROR("Warning: Turbo mode not supported "
- " falling back to 1080p clocks\n");
+ if ((!turbo_supported || !dev_ctxt->turbo_mode_set) &&
+ *pn_set_perf_lvl == RESTRK_1080P_TURBO_PERF_LEVEL) {
+ if (!turbo_supported)
+ VCDRES_MSG_ERROR("Warning: Turbo mode not supported "\
+ " falling back to 1080p clocks\n");
vidc_freq = vidc_clk_table[2];
*pn_set_perf_lvl = RESTRK_1080P_MAX_PERF_LEVEL;
}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index 886956f..ae97561 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -147,7 +147,7 @@
u32 reqd_perf_lvl;
u32 curr_perf_lvl;
u32 set_perf_lvl_pending;
- u32 turbo_mode_set;
+ bool turbo_mode_set;
};
struct vcd_clnt_status {
@@ -214,6 +214,7 @@
u32 meta_mode;
int perf_set_by_client;
int secure;
+ bool is_turbo_enabled;
};
#define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index 1281127..0d13028 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -759,7 +759,6 @@
client = dev_ctxt->cctxt_list_head;
dev_ctxt->cctxt_list_head = cctxt;
cctxt->next = client;
- dev_ctxt->turbo_mode_set = 0;
*clnt_cctxt = cctxt;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index b97a58e..71e8df8 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -3051,6 +3051,7 @@
{
u32 rc;
u32 res_trk_perf_level;
+ u32 turbo_perf_level;
if (!perf_level) {
VCD_MSG_ERROR("Invalid parameters\n");
return -EINVAL;
@@ -3060,10 +3061,13 @@
rc = -ENOTSUPP;
goto perf_level_not_supp;
}
+ turbo_perf_level = get_res_trk_perf_level(VCD_PERF_LEVEL_TURBO);
rc = vcd_set_perf_level(cctxt->dev_ctxt, res_trk_perf_level);
if (!rc) {
cctxt->reqd_perf_lvl = res_trk_perf_level;
cctxt->perf_set_by_client = 1;
+ if (res_trk_perf_level == turbo_perf_level)
+ cctxt->is_turbo_enabled = true;
}
perf_level_not_supp:
return rc;
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 3bba69c..0bdacffa 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -30,11 +30,6 @@
#define CORESIGHT_COMPIDR2 (0xFF8)
#define CORESIGHT_COMPIDR3 (0xFFC)
-/* DBGv7 with baseline CP14 registers implemented */
-#define ARM_DEBUG_ARCH_V7B (0x3)
-/* DBGv7 with all CP14 registers implemented */
-#define ARM_DEBUG_ARCH_V7 (0x4)
-#define ARM_DEBUG_ARCH_V7_1 (0x5)
#define ETM_ARCH_V3_3 (0x23)
#define PFT_ARCH_V1_1 (0x31)
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index c953613..45d51ce 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -689,7 +689,7 @@
/* LOG CODES */
#define LOG_0 0x0
-#define LOG_1 0x15A7
+#define LOG_1 0x1636
#define LOG_2 0x0
#define LOG_3 0x0
#define LOG_4 0x4910
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 2519270..6ac2835 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -704,6 +704,7 @@
struct ion_allocation_data {
size_t len;
size_t align;
+ unsigned int heap_mask;
unsigned int flags;
struct ion_handle *handle;
};
@@ -824,7 +825,7 @@
* descriptor obtained from ION_IOC_SHARE and returns the struct with the handle
* filed set to the corresponding opaque handle.
*/
-#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, int)
+#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
/**
* DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl
@@ -840,21 +841,21 @@
*
* Clean the caches of the handle specified.
*/
-#define ION_IOC_CLEAN_CACHES _IOWR(ION_IOC_MAGIC, 7, \
+#define ION_IOC_CLEAN_CACHES _IOWR(ION_IOC_MAGIC, 20, \
struct ion_flush_data)
/**
* DOC: ION_MSM_IOC_INV_CACHES - invalidate the caches
*
* Invalidate the caches of the handle specified.
*/
-#define ION_IOC_INV_CACHES _IOWR(ION_IOC_MAGIC, 8, \
+#define ION_IOC_INV_CACHES _IOWR(ION_IOC_MAGIC, 21, \
struct ion_flush_data)
/**
* DOC: ION_MSM_IOC_CLEAN_CACHES - clean and invalidate the caches
*
* Clean and invalidate the caches of the handle specified.
*/
-#define ION_IOC_CLEAN_INV_CACHES _IOWR(ION_IOC_MAGIC, 9, \
+#define ION_IOC_CLEAN_INV_CACHES _IOWR(ION_IOC_MAGIC, 22, \
struct ion_flush_data)
/**
@@ -863,6 +864,6 @@
* Gets the flags of the current handle which indicate cachability,
* secure state etc.
*/
-#define ION_IOC_GET_FLAGS _IOWR(ION_IOC_MAGIC, 10, \
+#define ION_IOC_GET_FLAGS _IOWR(ION_IOC_MAGIC, 23, \
struct ion_flag_data)
#endif /* _LINUX_ION_H */
diff --git a/include/linux/mfd/pm8xxx/spk.h b/include/linux/mfd/pm8xxx/spk.h
index 1155d2f..2905a1d 100644
--- a/include/linux/mfd/pm8xxx/spk.h
+++ b/include/linux/mfd/pm8xxx/spk.h
@@ -21,6 +21,14 @@
*/
struct pm8xxx_spk_platform_data {
bool spk_add_enable;
+ int cd_ng_threshold;
+ int cd_nf_preamp_bias;
+ int cd_ng_hold;
+ int cd_ng_max_atten;
+ int noise_mute;
+ int cd_ng_decay_rate;
+ int cd_ng_attack_rate;
+ int cd_delay;
};
/*
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 105c2cb..f6d164d 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -157,10 +157,7 @@
int num_rx_port;
int num_tx_port;
- u8 idbyte_0;
- u8 idbyte_1;
- u8 idbyte_2;
- u8 idbyte_3;
+ u8 idbyte[4];
};
int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 7afc896..2253655 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -367,6 +367,12 @@
_IOW(KGSL_IOC_TYPE, 0x22, struct kgsl_bind_gmem_shadow)
/* add a block of memory into the GPU address space */
+
+/*
+ * IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC deprecated 09/2012
+ * use IOCTL_KGSL_GPUMEM_ALLOC instead
+ */
+
struct kgsl_sharedmem_from_vmalloc {
unsigned int gpuaddr; /*output param */
unsigned int hostptr;
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 19a1d97..f74db80 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -199,17 +199,21 @@
* digital data relative to ADC reference.
* %ADC_SCALE_DEFAULT: Default scaling to convert raw adc code to voltage.
* %ADC_SCALE_BATT_THERM: Conversion to temperature based on btm parameters.
- * %ADC_SCALE_PA_THERM: Returns temperature in degC.
+ * %ADC_SCALE_THERM_100K_PULLUP: Returns temperature in degC.
+ * Uses a mapping table with 100K pullup.
* %ADC_SCALE_PMIC_THERM: Returns result in milli degree's Centigrade.
* %ADC_SCALE_XOTHERM: Returns XO thermistor voltage in degree's Centigrade.
+ * %ADC_SCALE_THERM_150K_PULLUP: Returns temperature in degC.
+ * Uses a mapping table with 150K pullup.
* %ADC_SCALE_NONE: Do not use this scaling type.
*/
enum qpnp_adc_scale_fn_type {
SCALE_DEFAULT = 0,
SCALE_BATT_THERM,
- SCALE_PA_THERM,
+ SCALE_THERM_100K_PULLUP,
SCALE_PMIC_THERM,
SCALE_XOTHERM,
+ SCALE_THERM_150K_PULLUP,
SCALE_NONE,
};
@@ -766,6 +770,40 @@
const struct qpnp_vadc_chan_properties *chan_prop,
struct qpnp_vadc_result *chan_rslt);
/**
+ * qpnp_adc_scale_therm_pu1() - Scales the pre-calibrated digital output
+ * of an ADC to the ADC reference and compensates for the
+ * gain and offset. Returns the temperature of the therm in degC.
+ * It uses a mapping table computed for a 150K pull-up.
+ * Pull-up1 is an internal pull-up on the AMUX of 150K.
+ * @adc_code: pre-calibrated digital ouput of the ADC.
+ * @adc_prop: adc properties of the pm8xxx adc such as bit resolution,
+ * reference voltage.
+ * @chan_prop: individual channel properties to compensate the i/p scaling,
+ * slope and offset.
+ * @chan_rslt: physical result to be stored.
+ */
+int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+ const struct qpnp_adc_properties *adc_prop,
+ const struct qpnp_vadc_chan_properties *chan_prop,
+ struct qpnp_vadc_result *chan_rslt);
+/**
+ * qpnp_adc_scale_therm_pu2() - Scales the pre-calibrated digital output
+ * of an ADC to the ADC reference and compensates for the
+ * gain and offset. Returns the temperature of the therm in degC.
+ * It uses a mapping table computed for a 100K pull-up.
+ * Pull-up2 is an internal pull-up on the AMUX of 100K.
+ * @adc_code: pre-calibrated digital ouput of the ADC.
+ * @adc_prop: adc properties of the pm8xxx adc such as bit resolution,
+ * reference voltage.
+ * @chan_prop: individual channel properties to compensate the i/p scaling,
+ * slope and offset.
+ * @chan_rslt: physical result to be stored.
+ */
+int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+ const struct qpnp_adc_properties *adc_prop,
+ const struct qpnp_vadc_chan_properties *chan_prop,
+ struct qpnp_vadc_result *chan_rslt);
+/**
* qpnp_vadc_is_ready() - Clients can use this API to check if the
* device is ready to use.
* @result: 0 on success and -EPROBE_DEFER when probe for the device
@@ -806,6 +844,16 @@
const struct qpnp_vadc_chan_properties *chan_prop,
struct qpnp_vadc_result *chan_rslt)
{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+ const struct qpnp_adc_properties *adc_prop,
+ const struct qpnp_vadc_chan_properties *chan_prop,
+ struct qpnp_vadc_result *chan_rslt);
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+ const struct qpnp_adc_properties *adc_prop,
+ const struct qpnp_vadc_chan_properties *chan_prop,
+ struct qpnp_vadc_result *chan_rslt);
+{ return -ENXIO; }
static inline int32_t qpnp_vadc_is_read(void)
{ return -ENXIO; }
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5fb3719..2c9509d 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1819,6 +1819,7 @@
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_NPROC_EXCEEDED 0x00001000 /* set_user noticed that RLIMIT_NPROC was exceeded */
#define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */
+#define PF_WAKE_UP_IDLE 0x00004000 /* try to wake up on an idle CPU */
#define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */
#define PF_FROZEN 0x00010000 /* frozen for system suspend */
#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
@@ -1936,6 +1937,14 @@
}
#endif
+static inline void set_wake_up_idle(bool enabled)
+{
+ if (enabled)
+ current->flags |= PF_WAKE_UP_IDLE;
+ else
+ current->flags &= ~PF_WAKE_UP_IDLE;
+}
+
#ifndef CONFIG_CPUMASK_OFFSTACK
static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
{
diff --git a/include/linux/topology.h b/include/linux/topology.h
index e26db03..92a89f0 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -166,7 +166,7 @@
| 1*SD_WAKE_AFFINE \
| 0*SD_PREFER_LOCAL \
| 0*SD_SHARE_CPUPOWER \
- | 0*SD_SHARE_PKG_RESOURCES \
+ | 1*SD_SHARE_PKG_RESOURCES \
| 0*SD_SERIALIZE \
| sd_balance_for_package_power() \
| sd_power_saving_flags() \
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 1248789..0ace67a 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -229,6 +229,12 @@
#define MSM_CAM_IOCTL_OEM \
_IOW(MSM_CAM_IOCTL_MAGIC, 65, struct sensor_cfg_data *)
+#define MSM_CAM_IOCTL_AXI_INIT \
+ _IOWR(MSM_CAM_IOCTL_MAGIC, 66, uint8_t *)
+
+#define MSM_CAM_IOCTL_AXI_RELEASE \
+ _IO(MSM_CAM_IOCTL_MAGIC, 67)
+
struct v4l2_event_and_payload {
struct v4l2_event evt;
uint32_t payload_length;
@@ -2011,7 +2017,7 @@
_IOWR('V', BASE_VIDIOC_PRIVATE + 17, struct msm_mctl_pp_params *)
#define VIDIOC_MSM_AXI_INIT \
- _IO('V', BASE_VIDIOC_PRIVATE + 18)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 18, uint8_t *)
#define VIDIOC_MSM_AXI_RELEASE \
_IO('V', BASE_VIDIOC_PRIVATE + 19)
@@ -2044,7 +2050,7 @@
struct msm_camera_vfe_params_t {
uint32_t operation_mode;
uint32_t capture_count;
- uint32_t skip_abort;
+ uint8_t skip_reset;
uint8_t stop_immediately;
uint16_t port_info;
uint32_t inst_handle;
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index ba705bd..db69518 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -660,7 +660,7 @@
IRIS_REGION_OTHER
};
-#define STD_BUF_SIZE (64)
+#define STD_BUF_SIZE (128)
enum iris_buf_t {
IRIS_BUF_SRCH_LIST,
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index b1ed9a4..8ccc9f4 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -92,7 +92,7 @@
int afe_unregister_get_events(u16 port_id);
int afe_rt_proxy_port_write(u32 buf_addr_p, u32 mem_map_handle, int bytes);
int afe_rt_proxy_port_read(u32 buf_addr_p, u32 mem_map_handle, int bytes);
-int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
+int afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate);
int afe_port_stop_nowait(int port_id);
int afe_apply_gain(u16 port_id, u16 gain);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e955364..9885a9e 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2654,6 +2654,10 @@
if (target == prev_cpu && idle_cpu(prev_cpu))
return prev_cpu;
+ if (!(current->flags & PF_WAKE_UP_IDLE) &&
+ !(p->flags & PF_WAKE_UP_IDLE))
+ return target;
+
/*
* Otherwise, iterate the domains and find an elegible idle cpu.
*/
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 947bd85..b11118f 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2523,7 +2523,7 @@
runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
return 0;
}
-
+
static int snd_pcm_common_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
@@ -2592,6 +2592,7 @@
case SNDRV_COMPRESS_SET_PARAMS:
case SNDRV_COMPRESS_GET_PARAMS:
case SNDRV_COMPRESS_TSTAMP:
+ case SNDRV_COMPRESS_DRAIN:
return snd_compressed_ioctl(substream, cmd, arg);
}
snd_printd("unknown ioctl = 0x%x\n", cmd);
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 67572c3..9432a06 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -2560,6 +2560,40 @@
return 0;
}
+static void sitar_codec_pm_runtime_put(struct wcd9xxx *sitar)
+{
+ if (sitar->dev != NULL &&
+ sitar->dev->parent != NULL) {
+ pm_runtime_mark_last_busy(sitar->dev->parent);
+ pm_runtime_put(sitar->dev->parent);
+ }
+}
+
+static void sitar_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct wcd9xxx *sitar_core = dev_get_drvdata(dai->codec->dev->parent);
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
+ u32 active = 0;
+
+ pr_debug("%s(): substream = %s stream = %d\n" , __func__,
+ substream->name, substream->stream);
+ if (sitar->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ return;
+
+ if (dai->id <= NUM_CODEC_DAIS) {
+ if (sitar->dai[dai->id-1].ch_mask) {
+ active = 1;
+ pr_debug("%s(): Codec DAI: chmask[%d] = 0x%x\n",
+ __func__, dai->id-1,
+ sitar->dai[dai->id-1].ch_mask);
+ }
+ }
+
+ if (sitar_core != NULL && active == 0)
+ sitar_codec_pm_runtime_put(sitar_core);
+}
+
int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
{
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
@@ -2680,11 +2714,23 @@
sitar->dai[dai->id - 1].ch_tot = rx_num;
}
} else if (dai->id == AIF1_CAP) {
- for (i = 0; i < tx_num; i++) {
- sitar->dai[dai->id - 1].ch_num[i] = tx_slot[i];
- sitar->dai[dai->id - 1].ch_act = 0;
- sitar->dai[dai->id - 1].ch_tot = tx_num;
+ sitar->dai[dai->id - 1].ch_tot = tx_num;
+ /* If all channels are already active,
+ * Do not reset ch_act flag
+ */
+ if ((sitar->dai[dai->id - 1].ch_tot != 0)
+ && (sitar->dai[dai->id - 1].ch_act ==
+ sitar->dai[dai->id - 1].ch_tot)) {
+ pr_info("%s: ch_act = %d, ch_tot = %d\n", __func__,
+ sitar->dai[dai->id - 1].ch_act,
+ sitar->dai[dai->id - 1].ch_tot);
+
+ return 0;
}
+ sitar->dai[dai->id - 1].ch_act = 0;
+
+ for (i = 0; i < tx_num; i++)
+ sitar->dai[dai->id - 1].ch_num[i] = tx_slot[i];
}
return 0;
}
@@ -2855,6 +2901,7 @@
static struct snd_soc_dai_ops sitar_dai_ops = {
.startup = sitar_startup,
+ .shutdown = sitar_shutdown,
.hw_params = sitar_hw_params,
.set_sysclk = sitar_set_dai_sysclk,
.set_fmt = sitar_set_dai_fmt,
@@ -2952,29 +2999,22 @@
pr_err("%s: slim close tx/rx timeout\n",
__func__);
ret = -EINVAL;
+ } else {
+ ret = 0;
}
- ret = 0;
break;
}
return ret;
}
-static void sitar_codec_pm_runtime_put(struct wcd9xxx *sitar)
-{
- if (sitar->dev != NULL &&
- sitar->dev->parent != NULL) {
- pm_runtime_mark_last_busy(sitar->dev->parent);
- pm_runtime_put(sitar->dev->parent);
- }
-}
-
static int sitar_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct wcd9xxx *sitar;
struct snd_soc_codec *codec = w->codec;
struct sitar_priv *sitar_p = snd_soc_codec_get_drvdata(codec);
- u32 j = 0, ret = 0;
+ u32 j = 0;
+ int ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
sitar = codec->control_data;
@@ -3018,11 +3058,19 @@
wcd9xxx_close_slim_sch_rx(sitar,
sitar_p->dai[j].ch_num,
sitar_p->dai[j].ch_tot);
+ ret = sitar_codec_enable_chmask(sitar_p, event, j);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(sitar,
+ sitar_p->dai[j].ch_num,
+ sitar_p->dai[j].ch_tot,
+ 1);
+ pr_info("%s: Disconnect RX port ret = %d\n",
+ __func__, ret);
+ }
sitar_p->dai[j].rate = 0;
memset(sitar_p->dai[j].ch_num, 0, (sizeof(u32)*
sitar_p->dai[j].ch_tot));
sitar_p->dai[j].ch_tot = 0;
- ret = sitar_codec_enable_chmask(sitar_p, event, j);
if (sitar != NULL)
sitar_codec_pm_runtime_put(sitar);
}
@@ -3037,7 +3085,8 @@
struct snd_soc_codec *codec = w->codec;
struct sitar_priv *sitar_p = snd_soc_codec_get_drvdata(codec);
/* index to the DAI ID, for now hardcoding */
- u32 j = 0, ret = 0;
+ u32 j = 0;
+ int ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
sitar = codec->control_data;
@@ -3082,11 +3131,19 @@
wcd9xxx_close_slim_sch_tx(sitar,
sitar_p->dai[j].ch_num,
sitar_p->dai[j].ch_tot);
+ ret = sitar_codec_enable_chmask(sitar_p, event, j);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(sitar,
+ sitar_p->dai[j].ch_num,
+ sitar_p->dai[j].ch_tot,
+ 0);
+ pr_info("%s: Disconnect TX port, ret = %d\n",
+ __func__, ret);
+ }
sitar_p->dai[j].rate = 0;
memset(sitar_p->dai[j].ch_num, 0, (sizeof(u32)*
sitar_p->dai[j].ch_tot));
sitar_p->dai[j].ch_tot = 0;
- ret = sitar_codec_enable_chmask(sitar_p, event, j);
if (sitar != NULL)
sitar_codec_pm_runtime_put(sitar);
}
@@ -4744,12 +4801,12 @@
}
-static unsigned long slimbus_value;
static irqreturn_t sitar_slimbus_irq(int irq, void *data)
{
struct sitar_priv *priv = data;
struct snd_soc_codec *codec = priv->codec;
+ unsigned long slimbus_value;
int i, j, k, port_id, ch_mask_temp;
u8 val;
@@ -4784,7 +4841,8 @@
}
}
wcd9xxx_interface_reg_write(codec->control_data,
- SITAR_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+ SITAR_SLIM_PGD_PORT_INT_CLR0 + i, slimbus_value);
+ val = 0x0;
}
return IRQ_HANDLED;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 673b1bf..ac11f1a 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -64,7 +64,8 @@
#define NUM_ATTEMPTS_TO_REPORT 5
#define TABLA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | \
- SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED)
+ SND_JACK_OC_HPHR | SND_JACK_LINEOUT | \
+ SND_JACK_UNSUPPORTED)
#define TABLA_I2S_MASTER_MODE_MASK 0x08
@@ -5308,7 +5309,8 @@
enum snd_jack_types jack_type)
{
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-
+ pr_debug("%s: enter insertion %d hph_status %x\n",
+ __func__, insertion, tabla->hph_status);
if (!insertion) {
/* Report removal */
tabla->hph_status &= ~jack_type;
@@ -5343,6 +5345,18 @@
tabla->current_plug = PLUG_TYPE_NONE;
tabla->mbhc_polling_active = false;
} else {
+ if (tabla->mbhc_cfg.detect_extn_cable) {
+ /* Report removal of current jack type */
+ if (tabla->hph_status != jack_type &&
+ tabla->mbhc_cfg.headset_jack) {
+ pr_debug("%s: Reporting removal (%x)\n",
+ __func__, tabla->hph_status);
+ tabla_snd_soc_jack_report(tabla,
+ tabla->mbhc_cfg.headset_jack,
+ 0, TABLA_JACK_MASK);
+ tabla->hph_status = 0;
+ }
+ }
/* Report insertion */
tabla->hph_status |= jack_type;
@@ -5353,7 +5367,8 @@
else if (jack_type == SND_JACK_HEADSET) {
tabla->mbhc_polling_active = true;
tabla->current_plug = PLUG_TYPE_HEADSET;
- }
+ } else if (jack_type == SND_JACK_LINEOUT)
+ tabla->current_plug = PLUG_TYPE_HIGH_HPH;
if (tabla->mbhc_cfg.headset_jack) {
pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
jack_type, tabla->hph_status);
@@ -5364,6 +5379,7 @@
}
tabla_clr_and_turnon_hph_padac(tabla);
}
+ pr_debug("%s: leave hph_status %x\n", __func__, tabla->hph_status);
}
static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec,
@@ -5377,6 +5393,9 @@
const struct tabla_mbhc_plug_detect_cfg *plug_det =
TABLA_MBHC_CAL_PLUG_DET_PTR(tabla->mbhc_cfg.calibration);
+ pr_debug("%s: enter insertion(%d) trigger(0x%x)\n",
+ __func__, insertion, trigger);
+
if (!tabla->mbhc_cfg.calibration) {
pr_err("Error, no tabla calibration\n");
return -EINVAL;
@@ -5487,6 +5506,7 @@
wcd9xxx_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+ pr_debug("%s: leave\n", __func__);
return 0;
}
@@ -6391,6 +6411,9 @@
{
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ pr_debug("%s: enter current_plug(%d) new_plug(%d)\n",
+ __func__, tabla->current_plug, plug_type);
+
if (plug_type == PLUG_TYPE_HEADPHONE &&
tabla->current_plug == PLUG_TYPE_NONE) {
/* Nothing was reported previously
@@ -6399,11 +6422,14 @@
tabla_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
tabla_codec_cleanup_hs_polling(codec);
} else if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
- if (tabla->current_plug == PLUG_TYPE_HEADSET)
- tabla_codec_report_plug(codec, 0, SND_JACK_HEADSET);
- else if (tabla->current_plug == PLUG_TYPE_HEADPHONE)
- tabla_codec_report_plug(codec, 0, SND_JACK_HEADPHONE);
-
+ if (!tabla->mbhc_cfg.detect_extn_cable) {
+ if (tabla->current_plug == PLUG_TYPE_HEADSET)
+ tabla_codec_report_plug(codec, 0,
+ SND_JACK_HEADSET);
+ else if (tabla->current_plug == PLUG_TYPE_HEADPHONE)
+ tabla_codec_report_plug(codec, 0,
+ SND_JACK_HEADPHONE);
+ }
tabla_codec_report_plug(codec, 1, SND_JACK_UNSUPPORTED);
tabla_codec_cleanup_hs_polling(codec);
} else if (plug_type == PLUG_TYPE_HEADSET) {
@@ -6414,19 +6440,37 @@
msleep(100);
tabla_codec_start_hs_polling(codec);
} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
- if (tabla->current_plug == PLUG_TYPE_NONE)
- tabla_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
- tabla_codec_cleanup_hs_polling(codec);
- pr_debug("setup mic trigger for further detection\n");
- tabla->lpi_enabled = true;
- tabla_codec_enable_hs_detect(codec, 1,
- MBHC_USE_MB_TRIGGER |
- MBHC_USE_HPHL_TRIGGER,
- false);
+ if (tabla->mbhc_cfg.detect_extn_cable) {
+ /* High impedance device found. Report as LINEOUT*/
+ tabla_codec_report_plug(codec, 1, SND_JACK_LINEOUT);
+ tabla_codec_cleanup_hs_polling(codec);
+ pr_debug("%s: setup mic trigger for further detection\n",
+ __func__);
+ tabla->lpi_enabled = true;
+ /*
+ * Do not enable HPHL trigger. If playback is active,
+ * it might lead to continuous false HPHL triggers
+ */
+ tabla_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER,
+ false);
+ } else {
+ if (tabla->current_plug == PLUG_TYPE_NONE)
+ tabla_codec_report_plug(codec, 1,
+ SND_JACK_HEADPHONE);
+ tabla_codec_cleanup_hs_polling(codec);
+ pr_debug("setup mic trigger for further detection\n");
+ tabla->lpi_enabled = true;
+ tabla_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER |
+ MBHC_USE_HPHL_TRIGGER,
+ false);
+ }
} else {
WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
tabla->current_plug, plug_type);
}
+ pr_debug("%s: leave\n", __func__);
}
/* should be called under interrupt context that hold suspend */
@@ -6486,6 +6530,8 @@
bool ahighv = false, highv;
bool gndmicswapped = false;
+ pr_debug("%s: enter\n", __func__);
+
/* make sure override is on */
WARN_ON(!(snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x04));
@@ -6595,6 +6641,7 @@
}
pr_debug("%s: Detected plug type %d\n", __func__, plug_type[0]);
+ pr_debug("%s: leave\n", __func__);
return plug_type[0];
}
@@ -6604,7 +6651,7 @@
struct snd_soc_codec *codec;
int retry = 0, pt_gnd_mic_swap_cnt = 0;
bool correction = false;
- enum tabla_mbhc_plug_type plug_type;
+ enum tabla_mbhc_plug_type plug_type = PLUG_TYPE_INVALID;
unsigned long timeout;
tabla = container_of(work, struct tabla_priv, hs_correct_plug_work);
@@ -6644,16 +6691,23 @@
plug_type = tabla_codec_get_plug_type(codec, true);
TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+ pr_debug("%s: attempt(%d) current_plug(%d) new_plug(%d)\n",
+ __func__, retry, tabla->current_plug, plug_type);
if (plug_type == PLUG_TYPE_INVALID) {
pr_debug("Invalid plug in attempt # %d\n", retry);
- if (retry == NUM_ATTEMPTS_TO_REPORT &&
+ if (!tabla->mbhc_cfg.detect_extn_cable &&
+ retry == NUM_ATTEMPTS_TO_REPORT &&
tabla->current_plug == PLUG_TYPE_NONE) {
tabla_codec_report_plug(codec, 1,
SND_JACK_HEADPHONE);
}
} else if (plug_type == PLUG_TYPE_HEADPHONE) {
pr_debug("Good headphone detected, continue polling mic\n");
- if (tabla->current_plug == PLUG_TYPE_NONE)
+ if (tabla->mbhc_cfg.detect_extn_cable) {
+ if (tabla->current_plug != plug_type)
+ tabla_codec_report_plug(codec, 1,
+ SND_JACK_HEADPHONE);
+ } else if (tabla->current_plug == PLUG_TYPE_NONE)
tabla_codec_report_plug(codec, 1,
SND_JACK_HEADPHONE);
} else {
@@ -6694,7 +6748,21 @@
tabla_turn_onoff_override(codec, false);
tabla->mbhc_cfg.mclk_cb_fn(codec, 0, false);
- pr_debug("%s: leave\n", __func__);
+
+ if (tabla->mbhc_cfg.detect_extn_cable) {
+ TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
+ if (tabla->current_plug == PLUG_TYPE_HEADPHONE ||
+ tabla->current_plug == PLUG_TYPE_GND_MIC_SWAP ||
+ tabla->current_plug == PLUG_TYPE_INVALID ||
+ plug_type == PLUG_TYPE_INVALID) {
+ /* Enable removal detection */
+ tabla_codec_cleanup_hs_polling(codec);
+ tabla_codec_enable_hs_detect(codec, 0, 0, false);
+ }
+ TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+ }
+ pr_debug("%s: leave current_plug(%d)\n",
+ __func__, tabla->current_plug);
/* unlock sleep */
wcd9xxx_unlock_sleep(tabla->codec->control_data);
}
@@ -6731,6 +6799,7 @@
__func__, plug_type);
tabla_find_plug_and_report(codec, plug_type);
}
+ pr_debug("%s: leave\n", __func__);
}
/* called under codec_resource_lock acquisition */
@@ -6740,7 +6809,7 @@
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
const struct tabla_mbhc_plug_detect_cfg *plug_det =
TABLA_MBHC_CAL_PLUG_DET_PTR(tabla->mbhc_cfg.calibration);
-
+ pr_debug("%s: enter\n", __func__);
/* Turn on the override,
* tabla_codec_setup_hs_polling requires override on */
tabla_turn_onoff_override(codec, true);
@@ -6759,6 +6828,7 @@
"plug\n", __func__);
else
tabla_codec_decide_gpio_plug(codec);
+ pr_debug("%s: leave\n", __func__);
return;
}
@@ -6790,13 +6860,23 @@
/* avoid false button press detect */
msleep(50);
tabla_codec_start_hs_polling(codec);
+ } else if (tabla->mbhc_cfg.detect_extn_cable &&
+ plug_type == PLUG_TYPE_HIGH_HPH) {
+ pr_debug("%s: High impedance plug type detected\n", __func__);
+ tabla_codec_report_plug(codec, 1, SND_JACK_LINEOUT);
+ /* Enable insertion detection on the other end of cable */
+ tabla_codec_cleanup_hs_polling(codec);
+ tabla_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER, false);
}
+ pr_debug("%s: leave\n", __func__);
}
/* called only from interrupt which is under codec_resource_lock acquisition */
static void tabla_hs_insert_irq_gpio(struct tabla_priv *priv, bool is_removal)
{
struct snd_soc_codec *codec = priv->codec;
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
if (!is_removal) {
pr_debug("%s: MIC trigger insertion interrupt\n", __func__);
@@ -6817,6 +6897,19 @@
pr_debug("%s: Invalid insertion, "
"stop plug detection\n", __func__);
}
+ } else if (tabla->mbhc_cfg.detect_extn_cable) {
+ pr_debug("%s: Removal\n", __func__);
+ if (!tabla_hs_gpio_level_remove(tabla)) {
+ /*
+ * gpio says, something is still inserted, could be
+ * extension cable i.e. headset is removed from
+ * extension cable
+ */
+ /* cancel detect plug */
+ tabla_cancel_hs_detect_plug(tabla,
+ &tabla->hs_correct_plug_work);
+ tabla_codec_decide_gpio_plug(codec);
+ }
} else {
pr_err("%s: GPIO used, invalid MBHC Removal\n", __func__);
}
@@ -6882,6 +6975,29 @@
}
}
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void tabla_hs_insert_irq_extn(struct tabla_priv *priv,
+ bool is_mb_trigger)
+{
+ struct snd_soc_codec *codec = priv->codec;
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+ /* Cancel possibly running hs_detect_work */
+ tabla_cancel_hs_detect_plug(tabla,
+ &tabla->hs_correct_plug_work);
+
+ if (is_mb_trigger) {
+ pr_debug("%s: Waiting for Headphone left trigger\n",
+ __func__);
+ tabla_codec_enable_hs_detect(codec, 1, MBHC_USE_HPHL_TRIGGER,
+ false);
+ } else {
+ pr_debug("%s: HPHL trigger received, detecting plug type\n",
+ __func__);
+ tabla_codec_detect_plug_type(codec);
+ }
+}
+
static irqreturn_t tabla_hs_insert_irq(int irq, void *data)
{
bool is_mb_trigger, is_removal;
@@ -6902,7 +7018,10 @@
snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
snd_soc_update_bits(codec, priv->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
- if (priv->mbhc_cfg.gpio)
+ if (priv->mbhc_cfg.detect_extn_cable &&
+ priv->current_plug == PLUG_TYPE_HIGH_HPH)
+ tabla_hs_insert_irq_extn(priv, is_mb_trigger);
+ else if (priv->mbhc_cfg.gpio)
tabla_hs_insert_irq_gpio(priv, is_removal);
else
tabla_hs_insert_irq_nogpio(priv, is_removal, is_mb_trigger);
@@ -7006,10 +7125,10 @@
static void tabla_hs_remove_irq_gpio(struct tabla_priv *priv)
{
struct snd_soc_codec *codec = priv->codec;
-
+ pr_debug("%s: enter\n", __func__);
if (tabla_hs_remove_settle(codec))
tabla_codec_start_hs_polling(codec);
- pr_debug("%s: remove settle done\n", __func__);
+ pr_debug("%s: leave\n", __func__);
}
/* called only from interrupt which is under codec_resource_lock acquisition */
@@ -7022,6 +7141,7 @@
TABLA_MBHC_CAL_GENERAL_PTR(priv->mbhc_cfg.calibration);
int min_us = TABLA_FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
+ pr_debug("%s: enter\n", __func__);
if (priv->current_plug != PLUG_TYPE_HEADSET) {
pr_debug("%s(): Headset is not inserted, ignore removal\n",
__func__);
@@ -7049,25 +7169,41 @@
} while (min_us > 0);
if (removed) {
- /* Cancel possibly running hs_detect_work */
- tabla_cancel_hs_detect_plug(priv,
+ if (priv->mbhc_cfg.detect_extn_cable) {
+ if (!tabla_hs_gpio_level_remove(priv)) {
+ /*
+ * extension cable is still plugged in
+ * report it as LINEOUT device
+ */
+ tabla_codec_report_plug(codec, 1,
+ SND_JACK_LINEOUT);
+ tabla_codec_cleanup_hs_polling(codec);
+ tabla_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER,
+ false);
+ }
+ } else {
+ /* Cancel possibly running hs_detect_work */
+ tabla_cancel_hs_detect_plug(priv,
&priv->hs_correct_plug_work_nogpio);
- /*
- * If this removal is not false, first check the micbias
- * switch status and switch it to LDOH if it is already
- * switched to VDDIO.
- */
- tabla_codec_switch_micbias(codec, 0);
+ /*
+ * If this removal is not false, first check the micbias
+ * switch status and switch it to LDOH if it is already
+ * switched to VDDIO.
+ */
+ tabla_codec_switch_micbias(codec, 0);
- tabla_codec_report_plug(codec, 0, SND_JACK_HEADSET);
- tabla_codec_cleanup_hs_polling(codec);
- tabla_codec_enable_hs_detect(codec, 1,
- MBHC_USE_MB_TRIGGER |
- MBHC_USE_HPHL_TRIGGER,
- true);
+ tabla_codec_report_plug(codec, 0, SND_JACK_HEADSET);
+ tabla_codec_cleanup_hs_polling(codec);
+ tabla_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER |
+ MBHC_USE_HPHL_TRIGGER,
+ true);
+ }
} else {
tabla_codec_start_hs_polling(codec);
}
+ pr_debug("%s: leave\n", __func__);
}
static irqreturn_t tabla_hs_remove_irq(int irq, void *data)
@@ -7082,10 +7218,12 @@
if (vddio)
__tabla_codec_switch_micbias(priv->codec, 0, false, true);
- if (priv->mbhc_cfg.gpio)
- tabla_hs_remove_irq_gpio(priv);
- else
+ if ((priv->mbhc_cfg.detect_extn_cable &&
+ !tabla_hs_gpio_level_remove(priv)) ||
+ !priv->mbhc_cfg.gpio) {
tabla_hs_remove_irq_nogpio(priv);
+ } else
+ tabla_hs_remove_irq_gpio(priv);
/* if driver turned off vddio switch and headset is not removed,
* turn on the vddio switch back, if headset is removed then vddio
@@ -7173,6 +7311,9 @@
tabla_codec_cleanup_hs_polling(codec);
tabla_codec_report_plug(codec, 0, SND_JACK_HEADSET);
is_removed = true;
+ } else if (tabla->current_plug == PLUG_TYPE_HIGH_HPH) {
+ tabla_codec_report_plug(codec, 0, SND_JACK_LINEOUT);
+ is_removed = true;
}
if (is_removed) {
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 1cca360..4c9f8b4 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -176,6 +176,7 @@
unsigned int gpio;
unsigned int gpio_irq;
int gpio_level_insert;
+ bool detect_extn_cable;
/* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
bool (*swap_gnd_mic) (struct snd_soc_codec *);
};
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index ece0a15..e46064b 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -105,6 +105,10 @@
module_param(apq8064_hs_detect_use_gpio, int, 0444);
MODULE_PARM_DESC(apq8064_hs_detect_use_gpio, "Use GPIO for headset detection");
+static bool apq8064_hs_detect_extn_cable;
+module_param(apq8064_hs_detect_extn_cable, bool, 0444);
+MODULE_PARM_DESC(apq8064_hs_detect_extn_cable, "Enable extension cable feature");
+
static bool apq8064_hs_detect_use_firmware;
module_param(apq8064_hs_detect_use_firmware, bool, 0444);
MODULE_PARM_DESC(apq8064_hs_detect_use_firmware, "Use firmware for headset "
@@ -124,6 +128,7 @@
.gpio = 0,
.gpio_irq = 0,
.gpio_level_insert = 1,
+ .detect_extn_cable = false,
};
static struct mutex cdc_mclk_mutex;
@@ -1152,8 +1157,9 @@
snd_soc_dapm_sync(dapm);
err = snd_soc_jack_new(codec, "Headset Jack",
- (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
- SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED),
+ (SND_JACK_HEADSET | SND_JACK_LINEOUT |
+ SND_JACK_OC_HPHL | SND_JACK_OC_HPHR |
+ SND_JACK_UNSUPPORTED),
&hs_jack);
if (err) {
pr_err("failed to create new jack\n");
@@ -1206,6 +1212,8 @@
return err;
}
gpio_direction_input(JACK_DETECT_GPIO);
+ if (apq8064_hs_detect_extn_cable)
+ mbhc_cfg.detect_extn_cable = true;
} else
pr_debug("%s: Not using MBHC mechanical switch\n", __func__);
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index 05786a7..1000a8b 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -271,6 +271,9 @@
static struct snd_soc_jack hs_jack;
static struct snd_soc_jack button_jack;
+static struct platform_device *mdm9615_snd_device_slim;
+static struct platform_device *mdm9615_snd_device_i2s;
+
static bool hs_detect_use_gpio;
module_param(hs_detect_use_gpio, bool, 0444);
MODULE_PARM_DESC(hs_detect_use_gpio, "Use GPIO for headset detection");
@@ -1448,10 +1451,28 @@
pintf->intf_status[i2s_intf][MSM_DIR_TX]);
}
+static void mdm9615_install_codec_i2s_gpio(void)
+{
+ msm_gpiomux_install(msm9615_audio_prim_i2s_codec_configs,
+ ARRAY_SIZE(msm9615_audio_prim_i2s_codec_configs));
+}
+static int msm9615_i2s_prepare(struct snd_pcm_substream *substream)
+{
+ u8 ret = 0;
+
+ if (wcd9xxx_get_intf_type() < 0)
+ ret = -ENODEV;
+ else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+ mdm9615_install_codec_i2s_gpio();
+
+ return ret;
+}
+
static struct snd_soc_ops msm9615_i2s_be_ops = {
.startup = msm9615_i2s_startup,
.shutdown = msm9615_i2s_shutdown,
.hw_params = msm9615_i2s_hw_params,
+ .prepare = msm9615_i2s_prepare,
};
static int mdm9615_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -2068,14 +2089,19 @@
ARRAY_SIZE(mdm9615_dai_slimbus_tabla)];
-static struct snd_soc_card snd_soc_card_mdm9615 = {
- .name = "mdm9615-tabla-snd-card",
+static struct snd_soc_card snd_soc_card_mdm9615[] = {
+ [0] = {
+ .name = "mdm9615-tabla-snd-card",
.controls = tabla_mdm9615_controls,
.num_controls = ARRAY_SIZE(tabla_mdm9615_controls),
+ },
+ [1] = {
+ .name = "mdm9615-tabla-snd-card-i2s",
+ .controls = tabla_mdm9615_controls,
+ .num_controls = ARRAY_SIZE(tabla_mdm9615_controls),
+ },
};
-static struct platform_device *mdm9615_snd_device;
-
static int mdm9615_configure_headset_mic_gpios(void)
{
int ret;
@@ -2127,11 +2153,6 @@
}
}
-void __init install_codec_i2s_gpio(void)
-{
- msm_gpiomux_install(msm9615_audio_prim_i2s_codec_configs,
- ARRAY_SIZE(msm9615_audio_prim_i2s_codec_configs));
-}
static int __init mdm9615_audio_init(void)
{
int ret;
@@ -2146,53 +2167,69 @@
pr_err("Calibration data allocation failed\n");
return -ENOMEM;
}
+ mdm9615_snd_device_slim = platform_device_alloc("soc-audio", 0);
+ if (!mdm9615_snd_device_slim) {
+ pr_err("Platform device allocation failed\n");
+ kfree(mbhc_cfg.calibration);
+ return -ENOMEM;
+ }
- mdm9615_snd_device = platform_device_alloc("soc-audio", 0);
- if (!mdm9615_snd_device) {
+ /* Install SLIM specific links */
+ memcpy(mdm9615_slimbus_dai, mdm9615_dai_common,
+ sizeof(mdm9615_dai_common));
+ memcpy(mdm9615_slimbus_dai + ARRAY_SIZE(mdm9615_dai_common),
+ mdm9615_dai_slimbus_tabla,
+ sizeof(mdm9615_dai_slimbus_tabla));
+ snd_soc_card_mdm9615[0].dai_link = mdm9615_slimbus_dai;
+ snd_soc_card_mdm9615[0].num_links =
+ ARRAY_SIZE(mdm9615_slimbus_dai);
+
+ mdm9615_snd_device_i2s = platform_device_alloc("soc-audio", 1);
+ if (!mdm9615_snd_device_i2s) {
pr_err("Platform device allocation failed\n");
kfree(mbhc_cfg.calibration);
return -ENOMEM;
}
pr_err("%s: Interface Type = %d\n", __func__,
wcd9xxx_get_intf_type());
- if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
- memcpy(mdm9615_slimbus_dai, mdm9615_dai_common,
- sizeof(mdm9615_dai_common));
- memcpy(mdm9615_slimbus_dai + ARRAY_SIZE(mdm9615_dai_common),
- mdm9615_dai_slimbus_tabla,
- sizeof(mdm9615_dai_slimbus_tabla));
- snd_soc_card_mdm9615.dai_link = mdm9615_slimbus_dai;
- snd_soc_card_mdm9615.num_links =
- ARRAY_SIZE(mdm9615_slimbus_dai);
- } else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C) {
- install_codec_i2s_gpio();
- memcpy(mdm9615_i2s_dai, mdm9615_dai_common,
- sizeof(mdm9615_dai_common));
- memcpy(mdm9615_i2s_dai + ARRAY_SIZE(mdm9615_dai_common),
- mdm9615_dai_i2s_tabla,
- sizeof(mdm9615_dai_i2s_tabla));
- snd_soc_card_mdm9615.dai_link = mdm9615_i2s_dai;
- snd_soc_card_mdm9615.num_links =
- ARRAY_SIZE(mdm9615_i2s_dai);
- } else{
- snd_soc_card_mdm9615.dai_link = mdm9615_dai_common;
- snd_soc_card_mdm9615.num_links =
- ARRAY_SIZE(mdm9615_dai_common);
- }
- platform_set_drvdata(mdm9615_snd_device, &snd_soc_card_mdm9615);
- ret = platform_device_add(mdm9615_snd_device);
+ /* Install I2S specific links */
+ memcpy(mdm9615_i2s_dai, mdm9615_dai_common,
+ sizeof(mdm9615_dai_common));
+ memcpy(mdm9615_i2s_dai + ARRAY_SIZE(mdm9615_dai_common),
+ mdm9615_dai_i2s_tabla,
+ sizeof(mdm9615_dai_i2s_tabla));
+ snd_soc_card_mdm9615[1].dai_link = mdm9615_i2s_dai;
+ snd_soc_card_mdm9615[1].num_links =
+ ARRAY_SIZE(mdm9615_i2s_dai);
+ platform_set_drvdata(mdm9615_snd_device_slim, &snd_soc_card_mdm9615[0]);
+ ret = platform_device_add(mdm9615_snd_device_slim);
if (ret) {
- platform_device_put(mdm9615_snd_device);
+ pr_err("%s Slim platform_device_add fail\n", __func__);
+ platform_device_put(mdm9615_snd_device_slim);
kfree(mbhc_cfg.calibration);
return ret;
}
+ platform_set_drvdata(mdm9615_snd_device_i2s, &snd_soc_card_mdm9615[1]);
+ ret = platform_device_add(mdm9615_snd_device_i2s);
+ if (ret) {
+ pr_err("%s I2S platform_device_add fail\n", __func__);
+ platform_device_put(mdm9615_snd_device_i2s);
+ kfree(mbhc_cfg.calibration);
+ return ret;
+ }
+
if (mdm9615_configure_headset_mic_gpios()) {
pr_err("%s Fail to configure headset mic gpios\n", __func__);
mdm9615_headset_gpios_configured = 0;
} else
mdm9615_headset_gpios_configured = 1;
+ /*
+ * Irrespective of audio interface type get virtual address
+ * of LPAIF registers as it may not be guaranted that I2S
+ * will probed successfully in Init.
+ */
atomic_set(&msm9615_auxpcm_ref, 0);
atomic_set(&msm9615_sec_auxpcm_ref, 0);
msm9x15_i2s_ctl.sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
@@ -2214,7 +2251,8 @@
return ;
}
mdm9615_free_headset_mic_gpios();
- platform_device_unregister(mdm9615_snd_device);
+ platform_device_unregister(mdm9615_snd_device_slim);
+ platform_device_unregister(mdm9615_snd_device_i2s);
kfree(mbhc_cfg.calibration);
iounmap(msm9x15_i2s_ctl.sif_virt_addr);
iounmap(msm9x15_i2s_ctl.spare_virt_addr);
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 5ccf8ed..b76160e 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -42,6 +42,7 @@
#define COMPRE_CAPTURE_PERIOD_SIZE ((COMPRE_CAPTURE_MAX_FRAME_SIZE + \
COMPRE_CAPTURE_HEADER_SIZE) * \
MAX_NUM_FRAMES_PER_BUFFER)
+#define COMPRE_OUTPUT_METADATA_SIZE (sizeof(struct output_meta_data_st))
struct snd_msm {
struct msm_audio *prtd;
@@ -113,8 +114,11 @@
struct audio_aio_write_param param;
struct audio_aio_read_param read_param;
struct audio_buffer *buf = NULL;
+ struct output_meta_data_st output_meta_data;
uint32_t *ptrmem = (uint32_t *)payload;
int i = 0;
+ int time_stamp_flag = 0;
+ int buffer_length = 0;
pr_debug("%s opcode =%08x\n", __func__, opcode);
switch (opcode) {
@@ -143,14 +147,35 @@
((unsigned int)buf[0].phys
+ (prtd->out_head * prtd->pcm_count)));
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+ time_stamp_flag = SET_TIMESTAMP;
+ else
+ time_stamp_flag = NO_TIMESTAMP;
+ memcpy(&output_meta_data, (char *)(buf->data +
+ prtd->out_head * prtd->pcm_count),
+ COMPRE_OUTPUT_METADATA_SIZE);
+
+ buffer_length = output_meta_data.frame_size;
+ pr_debug("meta_data_length: %d, frame_length: %d\n",
+ output_meta_data.meta_data_length,
+ output_meta_data.frame_size);
+ pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
+ output_meta_data.timestamp_msw,
+ output_meta_data.timestamp_lsw);
+ if (buffer_length == 0) {
+ pr_debug("Recieved a zero length buffer-break out");
+ break;
+ }
param.paddr = (unsigned long)buf[0].phys
- + (prtd->out_head * prtd->pcm_count);
- param.len = prtd->pcm_count;
- param.msw_ts = 0;
- param.lsw_ts = 0;
- param.flags = NO_TIMESTAMP;
+ + (prtd->out_head * prtd->pcm_count)
+ + output_meta_data.meta_data_length;
+ param.len = buffer_length;
+ param.msw_ts = output_meta_data.timestamp_msw;
+ param.lsw_ts = output_meta_data.timestamp_lsw;
+ param.flags = time_stamp_flag;
param.uid = (unsigned long)buf[0].phys
- + (prtd->out_head * prtd->pcm_count);
+ + (prtd->out_head * prtd->pcm_count
+ + output_meta_data.meta_data_length);
for (i = 0; i < sizeof(struct audio_aio_write_param)/4;
i++, ++ptrmem)
pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
@@ -165,8 +190,12 @@
}
case ASM_DATA_CMDRSP_EOS:
pr_debug("ASM_DATA_CMDRSP_EOS\n");
- prtd->cmd_ack = 1;
- wake_up(&the_locks.eos_wait);
+ if (atomic_read(&prtd->eos)) {
+ pr_debug("ASM_DATA_CMDRSP_EOS wake up\n");
+ prtd->cmd_ack = 1;
+ wake_up(&the_locks.eos_wait);
+ atomic_set(&prtd->eos, 0);
+ }
break;
case ASM_DATA_EVENT_READ_DONE: {
pr_debug("ASM_DATA_EVENT_READ_DONE\n");
@@ -250,12 +279,28 @@
__func__, prtd->out_head,
((unsigned int)buf[0].phys
+ (prtd->out_head * prtd->pcm_count)));
- param.paddr = (unsigned long)buf[prtd->out_head].phys;
- param.len = prtd->pcm_count;
- param.msw_ts = 0;
- param.lsw_ts = 0;
- param.flags = NO_TIMESTAMP;
- param.uid = (unsigned long)buf[prtd->out_head].phys;
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+ time_stamp_flag = SET_TIMESTAMP;
+ else
+ time_stamp_flag = NO_TIMESTAMP;
+ memcpy(&output_meta_data, (char *)(buf->data +
+ prtd->out_head * prtd->pcm_count),
+ COMPRE_OUTPUT_METADATA_SIZE);
+ buffer_length = output_meta_data.frame_size;
+ pr_debug("meta_data_length: %d, frame_length: %d\n",
+ output_meta_data.meta_data_length,
+ output_meta_data.frame_size);
+ pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
+ output_meta_data.timestamp_msw,
+ output_meta_data.timestamp_lsw);
+ param.paddr = (unsigned long)buf[prtd->out_head].phys
+ + output_meta_data.meta_data_length;
+ param.len = buffer_length;
+ param.msw_ts = output_meta_data.timestamp_msw;
+ param.lsw_ts = output_meta_data.timestamp_lsw;
+ param.flags = time_stamp_flag;
+ param.uid = (unsigned long)buf[prtd->out_head].phys
+ + output_meta_data.meta_data_length;
if (q6asm_async_write(prtd->audio_client,
¶m) < 0)
pr_err("%s:q6asm_async_write failed\n",
@@ -270,7 +315,7 @@
case ASM_STREAM_CMD_FLUSH:
pr_debug("ASM_STREAM_CMD_FLUSH\n");
prtd->cmd_ack = 1;
- wake_up(&the_locks.eos_wait);
+ wake_up(&the_locks.flush_wait);
break;
default:
break;
@@ -653,6 +698,7 @@
compr->codec = FORMAT_MP3;
populate_codec_list(compr, runtime);
runtime->private_data = compr;
+ atomic_set(&prtd->eos, 0);
compressed_audio.prtd = &compr->prtd;
ret = compressed_set_volume(compressed_audio.volume);
if (ret < 0)
@@ -699,6 +745,7 @@
dir = IN;
atomic_set(&prtd->pending_buffer, 0);
+ prtd->pcm_irq_pos = 0;
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
compressed_audio.prtd = NULL;
q6asm_audio_client_buf_free_contiguous(dir,
@@ -1027,18 +1074,41 @@
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
(substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
atomic_read(&prtd->start))) {
+ if (atomic_read(&prtd->eos)) {
+ prtd->cmd_ack = 1;
+ wake_up(&the_locks.eos_wait);
+ atomic_set(&prtd->eos, 0);
+ }
+
+ /* A unlikely race condition possible with FLUSH
+ DRAIN if ack is set by flush and reset by drain */
prtd->cmd_ack = 0;
rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
- if (rc < 0)
+ if (rc < 0) {
pr_err("%s: flush cmd failed rc=%d\n",
- __func__, rc);
- rc = wait_event_timeout(the_locks.eos_wait,
- prtd->cmd_ack, 5 * HZ);
+ __func__, rc);
+ return rc;
+ }
+ rc = wait_event_timeout(the_locks.flush_wait,
+ prtd->cmd_ack, 5 * HZ);
if (rc < 0)
pr_err("Flush cmd timeout\n");
prtd->pcm_irq_pos = 0;
}
break;
+ case SNDRV_COMPRESS_DRAIN:
+ pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
+ atomic_set(&prtd->eos, 1);
+ atomic_set(&prtd->pending_buffer, 0);
+ prtd->cmd_ack = 0;
+ q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+ /* Wait indefinitely for DRAIN. Flush can also signal this*/
+ rc = wait_event_interruptible(the_locks.eos_wait,
+ prtd->cmd_ack);
+ if (rc < 0)
+ pr_err("EOS cmd interrupted\n");
+ pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait\n", __func__);
+ return 0;
default:
break;
}
@@ -1099,6 +1169,7 @@
init_waitqueue_head(&the_locks.eos_wait);
init_waitqueue_head(&the_locks.write_wait);
init_waitqueue_head(&the_locks.read_wait);
+ init_waitqueue_head(&the_locks.flush_wait);
return platform_driver_register(&msm_compr_driver);
}
diff --git a/sound/soc/msm/msm-pcm-q6.h b/sound/soc/msm/msm-pcm-q6.h
index 9e743a7..f1af99a 100644
--- a/sound/soc/msm/msm-pcm-q6.h
+++ b/sound/soc/msm/msm-pcm-q6.h
@@ -48,6 +48,7 @@
wait_queue_head_t write_wait;
wait_queue_head_t eos_wait;
wait_queue_head_t enable_wait;
+ wait_queue_head_t flush_wait;
};
struct msm_audio {
@@ -75,10 +76,19 @@
atomic_t out_count;
atomic_t in_count;
atomic_t out_needed;
+ atomic_t eos;
int out_head;
int periods;
int mmap_flag;
atomic_t pending_buffer;
};
+struct output_meta_data_st {
+ uint32_t meta_data_length;
+ uint32_t frame_size;
+ uint32_t timestamp_lsw;
+ uint32_t timestamp_msw;
+ uint32_t reserved[12];
+};
+
#endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index e98fe64..6bd6adc 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -88,6 +88,11 @@
module_param(hs_detect_use_gpio, bool, 0444);
MODULE_PARM_DESC(hs_detect_use_gpio, "Use GPIO for headset detection");
+static bool hs_detect_extn_cable;
+module_param(hs_detect_extn_cable, bool, 0444);
+MODULE_PARM_DESC(hs_detect_extn_cable, "Enable extension cable feature");
+
+
static bool hs_detect_use_firmware;
module_param(hs_detect_use_firmware, bool, 0444);
MODULE_PARM_DESC(hs_detect_use_firmware, "Use firmware for headset detection");
@@ -108,6 +113,7 @@
.gpio_irq = 0,
.gpio_level_insert = 1,
.swap_gnd_mic = NULL,
+ .detect_extn_cable = false,
};
static u32 us_euro_sel_gpio = PM8921_GPIO_PM_TO_SYS(JACK_US_EURO_SEL_GPIO);
@@ -911,9 +917,10 @@
snd_soc_dapm_sync(dapm);
err = snd_soc_jack_new(codec, "Headset Jack",
- (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
- SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED),
- &hs_jack);
+ (SND_JACK_HEADSET | SND_JACK_LINEOUT |
+ SND_JACK_OC_HPHL | SND_JACK_OC_HPHR |
+ SND_JACK_UNSUPPORTED),
+ &hs_jack);
if (err) {
pr_err("failed to create new jack\n");
return err;
@@ -934,6 +941,8 @@
if (hs_detect_use_gpio) {
mbhc_cfg.gpio = PM8921_GPIO_PM_TO_SYS(JACK_DETECT_GPIO);
mbhc_cfg.gpio_irq = JACK_DETECT_INT;
+ if (hs_detect_extn_cable)
+ mbhc_cfg.detect_extn_cable = true;
}
if (mbhc_cfg.gpio) {
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 485569b..3eab972 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -400,70 +400,23 @@
int rc = 0;
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
- /* PORT START should be set if prepare called in active state */
- rc = afe_q6_interface_prepare();
+ switch (dai->id) {
+ case VOICE_PLAYBACK_TX:
+ case VOICE_RECORD_TX:
+ case VOICE_RECORD_RX:
+ rc = afe_start_pseudo_port(dai->id);
+ default:
+ rc = afe_port_start(dai->id, &dai_data->port_config,
+ dai_data->rate);
+ }
+
if (IS_ERR_VALUE(rc))
- dev_err(dai->dev, "fail to open AFE APR\n");
- }
- return rc;
-}
-
-static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
- int rc = 0;
-
- /*
- * Start/stop port without waiting for Q6 AFE response. Need to have
- * native q6 AFE driver propagates AFE response in order to handle
- * port start/stop command error properly if error does arise.
- */
- pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
- __func__, dai->id, cmd, *dai_data->status_mask);
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
- switch (dai->id) {
- case VOICE_PLAYBACK_TX:
- case VOICE_RECORD_TX:
- case VOICE_RECORD_RX:
- afe_pseudo_port_start_nowait(dai->id);
- break;
- default:
- afe_port_start_nowait(dai->id,
- &dai_data->port_config, dai_data->rate);
- break;
- }
+ dev_err(dai->dev, "fail to open AFE port %x\n",
+ dai->id);
+ else
set_bit(STATUS_PORT_STARTED,
dai_data->status_mask);
- }
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
- switch (dai->id) {
- case VOICE_PLAYBACK_TX:
- case VOICE_RECORD_TX:
- case VOICE_RECORD_RX:
- afe_pseudo_port_stop_nowait(dai->id);
- break;
- default:
- afe_port_stop_nowait(dai->id);
- break;
- }
- clear_bit(STATUS_PORT_STARTED,
- dai_data->status_mask);
- }
- break;
-
- default:
- rc = -EINVAL;
}
-
return rc;
}
@@ -799,7 +752,6 @@
static struct snd_soc_dai_ops msm_dai_q6_ops = {
.prepare = msm_dai_q6_prepare,
- .trigger = msm_dai_q6_trigger,
.hw_params = msm_dai_q6_hw_params,
.shutdown = msm_dai_q6_shutdown,
.set_fmt = msm_dai_q6_set_fmt,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 54f379f..19e0464 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -233,11 +233,13 @@
pr_debug("SNDRV_PCM_TRIGGER_START\n");
q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
atomic_set(&prtd->start, 1);
+ atomic_set(&prtd->stop, 0);
break;
case SNDRV_PCM_TRIGGER_STOP:
pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
audio_ocmem_process_req(AUDIO, false);
atomic_set(&prtd->start, 0);
+ atomic_set(&prtd->stop, 1);
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
break;
break;
@@ -325,6 +327,7 @@
prtd->dsp_cnt = 0;
atomic_set(&prtd->pending_buffer, 1);
+ atomic_set(&prtd->stop, 1);
runtime->private_data = prtd;
lpa_audio.prtd = prtd;
lpa_set_volume(lpa_audio.volume);
@@ -368,7 +371,8 @@
To issue EOS to dsp, we need to be run state otherwise
EOS is not honored.
*/
- if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id)) {
+ if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id) &&
+ (!atomic_read(&prtd->stop))) {
rc = q6asm_run(prtd->audio_client, 0, 0, 0);
atomic_set(&prtd->pending_buffer, 0);
prtd->cmd_ack = 0;
@@ -388,6 +392,7 @@
q6asm_audio_client_buf_free_contiguous(dir,
prtd->audio_client);
+ atomic_set(&prtd->stop, 1);
pr_debug("%s\n", __func__);
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
SNDRV_PCM_STREAM_PLAYBACK);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index 44395b7..22bf0cc 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -72,6 +72,7 @@
int close_ack;
int cmd_ack;
atomic_t start;
+ atomic_t stop;
atomic_t out_count;
atomic_t in_count;
atomic_t out_needed;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 2e58e1b..0b25545 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -30,6 +30,7 @@
atomic_t state;
atomic_t status;
wait_queue_head_t wait[AFE_MAX_PORTS];
+ struct task_struct *task;
void (*tx_cb) (uint32_t opcode,
uint32_t token, uint32_t *payload, void *priv);
void (*rx_cb) (uint32_t opcode,
@@ -58,6 +59,9 @@
atomic_set(&this_afe.state, 0);
this_afe.apr = NULL;
}
+ /* send info to user */
+ pr_debug("task_name = %s pid = %d\n",
+ this_afe.task->comm, this_afe.task->pid);
return 0;
}
pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x\n",
@@ -248,7 +252,7 @@
afe_send_cal_block(RX_CAL, port_id);
}
-int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
+int afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate) /* This function is no blocking */
{
struct afe_port_cmd_device_start start;
@@ -274,8 +278,9 @@
port_id = VIRTUAL_ID_TO_PORTID(port_id);
ret = afe_q6_interface_prepare();
- if (ret != 0)
+ if (IS_ERR_VALUE(ret))
return ret;
+
if (q6audio_validate_port(port_id) < 0) {
pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
port_id);
@@ -338,6 +343,8 @@
config.port = *afe_config;
+ atomic_set(&this_afe.state, 1);
+ atomic_set(&this_afe.status, 0);
ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
if (ret < 0) {
pr_err("%s: AFE enable for port %d failed\n", __func__,
@@ -345,7 +352,20 @@
ret = -EINVAL;
goto fail_cmd;
}
+ ret = wait_event_timeout(this_afe.wait[index],
+ (atomic_read(&this_afe.state) == 0),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout IF CONFIG\n", __func__);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ if (atomic_read(&this_afe.status) != 0) {
+ pr_err("%s: config cmd failed\n", __func__);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
/* send AFE cal */
afe_send_cal(port_id);
@@ -360,6 +380,7 @@
pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
__func__, start.hdr.opcode, start.port_id);
+ atomic_set(&this_afe.state, 1);
ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
if (IS_ERR_VALUE(ret)) {
@@ -369,6 +390,21 @@
goto fail_cmd;
}
+ ret = wait_event_timeout(this_afe.wait[index],
+ (atomic_read(&this_afe.state) == 0),
+ msecs_to_jiffies(TIMEOUT_MS));
+
+ if (!ret) {
+ pr_err("%s: wait_event timeout PORT START\n", __func__);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ if (this_afe.task != current)
+ this_afe.task = current;
+
+ pr_debug("task_name = %s pid = %d\n",
+ this_afe.task->comm, this_afe.task->pid);
+
return 0;
fail_cmd:
@@ -506,8 +542,7 @@
config.pdata.param_size = sizeof(config.port);
config.port = *afe_config;
- pr_debug("%s: param PL size=%d iparam_size[%d][%d %d %d %d]"
- " param_id[%x]\n",
+ pr_debug("%s: param PL size=%d iparam_size[%d][%d %d %d %d] param_id[%x]\n",
__func__, config.param.payload_size, config.pdata.param_size,
sizeof(config), sizeof(config.param), sizeof(config.port),
sizeof(struct apr_hdr), config.pdata.param_id);
@@ -653,8 +688,8 @@
/* RX ports numbers are even .TX ports numbers are odd. */
if (port_id % 2 == 0) {
- pr_err("%s: Failed : afe loopback gain only for TX ports."
- " port_id %d\n", __func__, port_id);
+ pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n",
+ __func__, port_id);
ret = -EINVAL;
goto fail_cmd;
}
@@ -1319,7 +1354,7 @@
else
base = 10;
- if (strict_strtoul(token, base, ¶m1[cnt]) != 0)
+ if (kstrtoul(token, base, ¶m1[cnt]) != 0)
return -EINVAL;
token = strsep(&buf, " ");
@@ -1389,8 +1424,7 @@
}
if (param[1] < 0 || param[1] > 100) {
- pr_err("%s: Error, volume shoud be 0 to 100"
- " percentage param = %lu\n",
+ pr_err("%s: Error, volume shoud be 0 to 100 percentage param = %lu\n",
__func__, param[1]);
rc = -EINVAL;
goto afe_error;