Merge "arm/dt: msm-8974: Add PMIC PM8941 PWM device tree information"
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index cb2c1e1..5df0101 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -71,6 +71,7 @@
Value is from 16384 to 16393
BT SCO port ID value from 12288 to 12289
RT Proxy port ID values from 224 to 225 and 240 to 241
+ FM Rx and TX port ID values from 12292 to 12293
* msm-auxpcm
@@ -206,6 +207,16 @@
qcom,msm-dai-q6-dev-id = <12289>;
};
+ qcom,msm-dai-q6-int-fm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12292>;
+ };
+
+ qcom,msm-dai-q6-int-fm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12293>;
+ };
+
qcom,msm-dai-q6-be-afe-pcm-rx {
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <224>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 5613fcb..1b18d25 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -102,11 +102,12 @@
qcom,cxo-freq = <19200000>;
};
- pm8941-chg {
+ pm8941_chg: qcom,charger {
spmi-dev-container;
compatible = "qcom,qpnp-charger";
#address-cells = <1>;
#size-cells = <1>;
+ status = "disabled";
qcom,chg-vddmax-mv = <4200>;
qcom,chg-vddsafe-mv = <4200>;
@@ -115,6 +116,7 @@
qcom,chg-ibatterm-ma = <200>;
qcom,chg-chgr@1000 {
+ status = "disabled";
reg = <0x1000 0x100>;
interrupts = <0x0 0x10 0x0>,
<0x0 0x10 0x1>,
@@ -136,6 +138,7 @@
};
qcom,chg-buck@1100 {
+ status = "disabled";
reg = <0x1100 0x100>;
interrupts = <0x0 0x11 0x0>,
<0x0 0x11 0x1>,
@@ -155,6 +158,7 @@
};
qcom,chg-bat-if@1200 {
+ status = "disabled";
reg = <0x1200 0x100>;
interrupts = <0x0 0x12 0x0>,
<0x0 0x12 0x1>,
@@ -170,6 +174,7 @@
};
qcom,chg-usb-chgpth@1300 {
+ status = "disabled";
reg = <0x1300 0x100>;
interrupts = <0 0x13 0x0>,
<0 0x13 0x1>,
@@ -181,6 +186,7 @@
};
qcom,chg-dc-chgpth@1400 {
+ status = "disabled";
reg = <0x1400 0x100>;
interrupts = <0x0 0x14 0x0>,
<0x0 0x14 0x1>;
@@ -190,6 +196,7 @@
};
qcom,chg-boost@1500 {
+ status = "disabled";
reg = <0x1500 0x100>;
interrupts = <0x0 0x15 0x0>,
<0x0 0x15 0x1>;
@@ -199,6 +206,7 @@
};
qcom,chg-misc@1600 {
+ status = "disabled";
reg = <0x1600 0x100>;
};
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index 05fcc4f..0e0f6cf 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -30,6 +30,10 @@
};
};
+ qcom,hdmi_tx@fd922100 {
+ status = "ok";
+ };
+
i2c@f9924000 {
atmel_mxt_ts@4a {
compatible = "atmel,mxt-ts";
diff --git a/arch/arm/boot/dts/msm8974-fluid.dts b/arch/arm/boot/dts/msm8974-fluid.dts
index b1d467e..3a7c19d 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-fluid.dts
@@ -30,6 +30,10 @@
};
};
+ qcom,hdmi_tx@fd922100 {
+ status = "ok";
+ };
+
i2c@f9924000 {
atmel_mxt_ts@4a {
compatible = "atmel,mxt-ts";
diff --git a/arch/arm/boot/dts/msm8974-liquid.dts b/arch/arm/boot/dts/msm8974-liquid.dts
index bf4adaf..bc682ea 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-liquid.dts
@@ -54,6 +54,10 @@
debounce-interval = <15>;
};
};
+
+ qcom,hdmi_tx@fd922100 {
+ status = "ok";
+ };
};
&pm8941_gpios {
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index e0d6ad3..f75ebbe 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -30,6 +30,10 @@
};
};
+ qcom,hdmi_tx@fd922100 {
+ status = "disabled";
+ };
+
i2c@f9924000 {
atmel_mxt_ts@4a {
compatible = "atmel,mxt-ts";
@@ -169,6 +173,42 @@
cd-gpios = <&msmgpio 62 0x1>;
};
+&usb_otg {
+ qcom,hsusb-otg-otg-control = <2>;
+};
+
+&pm8941_chg {
+ status = "ok";
+
+ qcom,chg-chgr@1000 {
+ status = "ok";
+ };
+
+ qcom,chg-buck@1100 {
+ status = "ok";
+ };
+
+ qcom,chg-bat-if@1200 {
+ status = "ok";
+ };
+
+ qcom,chg-usb-chgpth@1300 {
+ status = "ok";
+ };
+
+ qcom,chg-dc-chgpth@1400 {
+ status = "ok";
+ };
+
+ qcom,chg-boost@1500 {
+ status = "ok";
+ };
+
+ qcom,chg-misc@1600 {
+ status = "ok";
+ };
+};
+
&pm8941_gpios {
gpio@c000 { /* GPIO 1 */
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 23635de..07b824d 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -94,7 +94,7 @@
status = "disabled";
};
- usb@f9a55000 {
+ usb_otg: usb@f9a55000 {
compatible = "qcom,hsusb-otg";
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0 0 140 0>;
@@ -726,6 +726,16 @@
qcom,msm-dai-q6-dev-id = <12289>;
};
+ qcom,msm-dai-q6-int-fm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12292>;
+ };
+
+ qcom,msm-dai-q6-int-fm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12293>;
+ };
+
qcom,msm-dai-q6-be-afe-pcm-rx {
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <224>;
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 1230fbe..f0d60c5 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -278,6 +278,7 @@
CONFIG_QPNP_BMS=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_QPNP_CHARGER=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
CONFIG_WCD9320_CODEC=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 7ee0eb2..f8e01b6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -669,6 +669,18 @@
help
Support for the Qualcomm MSM8625 Reference Design.
+config MACH_QRD_SKUD_PRIME
+ depends on ARCH_MSM8625
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM8625 SKUD PRIME"
+ help
+ Support for the Qualcomm MSM8625 SKUD prime Reference Design.
+ Add support for a SKUD prime reference design based on MSM8x25
+ chipset. This device is much closer to a phone than regular form
+ factor devices, with new touch, display panel and other hardware
+ configurations.
+
config MACH_MSM7X30_SURF
depends on ARCH_MSM7X30
depends on !MSM_STACKED_MEMORY
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f073e70..34a81da 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -256,6 +256,7 @@
obj-$(CONFIG_MACH_MSM8625_SURF) += board-msm7x27a.o board-7627a-all.o
obj-$(CONFIG_MACH_MSM8625_EVB) += board-qrd7627a.o board-7627a-all.o
obj-$(CONFIG_MACH_MSM8625_QRD7) += board-qrd7627a.o board-7627a-all.o
+obj-$(CONFIG_MACH_QRD_SKUD_PRIME) += board-qrd7627a.o board-7627a-all.o
obj-$(CONFIG_MACH_MSM8625_FFA) += board-msm7x27a.o board-7627a-all.o
obj-$(CONFIG_MACH_MSM8625_EVT) += board-msm7x27a.o board-7627a-all.o
obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o memory_topology.o
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index e4edf9b..bcc9645 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -103,7 +103,8 @@
if (machine_is_msm7627a_qrd1())
gpio_bt_sys_rest_en = 114;
if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
- || machine_is_msm8625_evt())
+ || machine_is_msm8625_evt()
+ || machine_is_qrd_skud_prime())
gpio_bt_sys_rest_en = 16;
if (machine_is_msm8625_qrd7())
gpio_bt_sys_rest_en = 88;
@@ -975,6 +976,8 @@
int i, rc = 0;
struct device *dev;
+ if (machine_is_qrd_skud_prime())
+ return;
gpio_bt_config();
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index b5f214b..79ad996 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -403,7 +403,8 @@
if (machine_is_msm8625_evb() || machine_is_msm7627a_evb()
|| machine_is_msm8625_evt()
|| machine_is_msm7627a_qrd3()
- || machine_is_msm8625_qrd7()) {
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime()) {
sensor_board_info_ov7692.cam_vreg =
ov7692_gpio_vreg;
sensor_board_info_ov7692.num_vreg =
@@ -420,7 +421,8 @@
platform_device_register(&msm_camera_server);
if (machine_is_msm8625_surf() || machine_is_msm8625_evb()
|| machine_is_msm8625_evt()
- || machine_is_msm8625_qrd7()) {
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime()) {
platform_device_register(&msm8625_device_csic0);
platform_device_register(&msm8625_device_csic1);
} else {
@@ -429,7 +431,8 @@
}
if (machine_is_msm8625_evb()
|| machine_is_msm8625_evt()
- || machine_is_msm8625_qrd7())
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime())
*(int *) msm7x27a_device_clkctl.dev.platform_data = 1;
platform_device_register(&msm7x27a_device_clkctl);
platform_device_register(&msm7x27a_device_vfe);
@@ -1175,7 +1178,6 @@
#ifndef CONFIG_MSM_CAMERA_V4L2
int rc;
#endif
-
pr_debug("msm7627a_camera_init Entered\n");
if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
@@ -1194,7 +1196,8 @@
if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
|| machine_is_msm8625_evt()
|| machine_is_msm7627a_qrd3()
- || machine_is_msm8625_qrd7()) {
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime()) {
#ifndef CONFIG_MSM_CAMERA_V4L2
lcd_camera_power_init();
#endif
@@ -1210,7 +1213,8 @@
|| machine_is_msm8625_evb()
|| machine_is_msm8625_evt()
|| machine_is_msm7627a_qrd3()
- || machine_is_msm8625_qrd7()) {
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime()) {
platform_add_devices(camera_devices_evb,
ARRAY_SIZE(camera_devices_evb));
} else if (machine_is_msm7627a_qrd3())
@@ -1223,7 +1227,8 @@
|| !machine_is_msm8625_evb()
|| !machine_is_msm8625_evt()
|| !machine_is_msm7627a_qrd3()
- || !machine_is_msm8625_qrd7())
+ || !machine_is_msm8625_qrd7()
+ || !machine_is_qrd_skud_prime())
register_i2c_devices();
#ifndef CONFIG_MSM_CAMERA_V4L2
rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
@@ -1253,7 +1258,8 @@
|| machine_is_msm8625_evb()
|| machine_is_msm8625_evt()
|| machine_is_msm7627a_qrd3()
- || machine_is_msm8625_qrd7()) {
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime()) {
pr_debug("machine_is_msm7627a_evb i2c_register_board_info\n");
i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
i2c_camera_devices_evb,
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 2db074d..1249c7b 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -542,7 +542,8 @@
if (!strncmp(name, "lcdc_truly_hvga_ips3p2335_pt", 28))
ret = 0;
} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
- machine_is_msm8625_evt()) {
+ machine_is_msm8625_evt() ||
+ machine_is_qrd_skud_prime()) {
if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
ret = 0;
}
@@ -796,7 +797,8 @@
if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa())
fb_size = MSM7x25A_MSM_FB_SIZE;
else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
- || machine_is_msm8625_evt())
+ || machine_is_msm8625_evt()
+ || machine_is_qrd_skud_prime())
fb_size = MSM8x25_MSM_FB_SIZE;
else
fb_size = MSM_FB_SIZE;
@@ -1017,7 +1019,8 @@
if (machine_is_msm7627a_qrd1())
rc = msm_fb_dsi_client_qrd1_reset();
else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
- || machine_is_msm8625_evt())
+ || machine_is_msm8625_evt()
+ || machine_is_qrd_skud_prime())
rc = msm_fb_dsi_client_qrd3_reset();
else
rc = msm_fb_dsi_client_msm_reset();
@@ -1327,7 +1330,8 @@
if (machine_is_msm7627a_qrd1())
rc = mipi_dsi_panel_qrd1_power(on);
else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
- || machine_is_msm8625_evt())
+ || machine_is_msm8625_evt()
+ || machine_is_qrd_skud_prime())
rc = mipi_dsi_panel_qrd3_power(on);
else
rc = mipi_dsi_panel_msm_power(on);
@@ -1391,7 +1395,8 @@
platform_add_devices(qrd_fb_devices,
ARRAY_SIZE(qrd_fb_devices));
} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
- || machine_is_msm8625_evt()) {
+ || machine_is_msm8625_evt()
+ || machine_is_qrd_skud_prime()) {
mipi_NT35510_pdata.bl_lock = 1;
mipi_NT35516_pdata.bl_lock = 1;
if (disable_splash)
@@ -1423,7 +1428,8 @@
msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
#endif
if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
- || machine_is_msm8625_evt()) {
+ || machine_is_msm8625_evt()
+ || machine_is_qrd_skud_prime()) {
gpio_reg_2p85v = regulator_get(&mipi_dsi_device.dev,
"lcd_vdd");
if (IS_ERR(gpio_reg_2p85v))
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 49ff393..07ff389 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -378,9 +378,9 @@
if (mmc_regulator_init(1, "mmc", 2850000))
return;
/* 8x25 EVT do not use hw detector */
- if (!(machine_is_msm8625_evt()))
+ if (!((machine_is_msm8625_evt() || machine_is_qrd_skud_prime())))
sdc1_plat_data.status_irq = MSM_GPIO_TO_INT(gpio_sdc1_hw_det);
- if (machine_is_msm8625_evt())
+ if (machine_is_msm8625_evt() || machine_is_qrd_skud_prime())
sdc1_plat_data.status = NULL;
msm_add_sdcc(1, &sdc1_plat_data);
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index 79f213e..ab29fc5 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -23,6 +23,7 @@
#define GPIO_WLAN_3V3_EN 119
static const char *id = "WLAN";
+static bool wlan_powered_up;
enum {
WLAN_VREG_S3 = 0,
@@ -52,7 +53,8 @@
|| machine_is_msm8625_evb()
|| machine_is_msm8625_evt()
|| machine_is_msm7627a_qrd3()
- || machine_is_msm8625_qrd7())
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime())
gpio_wlan_sys_rest_en = 124;
}
@@ -199,6 +201,11 @@
int rc = 0;
static bool init_done;
+ if (wlan_powered_up) {
+ pr_info("WLAN already powered up\n");
+ return 0;
+ }
+
if (unlikely(!init_done)) {
gpio_wlan_config();
rc = qrf6285_init_regs();
@@ -237,7 +244,8 @@
|| machine_is_msm8625_evb()
|| machine_is_msm8625_evt()
|| machine_is_msm7627a_qrd3()
- || machine_is_msm8625_qrd7()) {
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime()) {
rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_2MA), GPIO_CFG_ENABLE);
@@ -279,13 +287,17 @@
}
pr_info("WLAN power-up success\n");
+ wlan_powered_up = true;
return 0;
set_clock_fail:
setup_wlan_clock(0);
set_gpio_fail:
setup_wlan_gpio(0);
gpio_fail:
- gpio_free(gpio_wlan_sys_rest_en);
+ if (!(machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb() ||
+ machine_is_msm8625_evb() || machine_is_msm8625_evt() ||
+ machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()))
+ gpio_free(gpio_wlan_sys_rest_en);
qrd_gpio_fail:
/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
if (machine_is_msm7627a_qrd1())
@@ -294,6 +306,7 @@
wlan_switch_regulators(0);
out:
pr_info("WLAN power-up failed\n");
+ wlan_powered_up = false;
return rc;
}
@@ -301,6 +314,11 @@
{
int rc = 0;
+ if (!wlan_powered_up) {
+ pr_info("WLAN is not powered up, returning success\n");
+ return 0;
+ }
+
/* Disable the A0 clock */
rc = setup_wlan_clock(on);
if (rc) {
@@ -316,7 +334,8 @@
|| machine_is_msm8625_evb()
|| machine_is_msm8625_evt()
|| machine_is_msm7627a_qrd3()
- || machine_is_msm8625_qrd7()) {
+ || machine_is_msm8625_qrd7()
+ || machine_is_qrd_skud_prime()) {
rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_2MA), GPIO_CFG_ENABLE);
@@ -327,20 +346,12 @@
}
gpio_set_value(gpio_wlan_sys_rest_en, 0);
} else {
- rc = gpio_request(gpio_wlan_sys_rest_en, "WLAN_DEEP_SLEEP_N");
- if (!rc) {
- rc = setup_wlan_gpio(on);
- if (rc) {
- pr_err("%s: setup_wlan_gpio = %d\n",
- __func__, rc);
- goto set_gpio_fail;
- }
- gpio_free(gpio_wlan_sys_rest_en);
- } else {
- pr_err("%s: WLAN sys_rest_en GPIO %d request failed %d\n",
- __func__, gpio_wlan_sys_rest_en, rc);
- goto out;
+ rc = setup_wlan_gpio(on);
+ if (rc) {
+ pr_err("%s: setup_wlan_gpio = %d\n", __func__, rc);
+ goto set_gpio_fail;
}
+ gpio_free(gpio_wlan_sys_rest_en);
}
/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
@@ -362,7 +373,7 @@
__func__, rc);
goto reg_disable;
}
-
+ wlan_powered_up = false;
pr_info("WLAN power-down success\n");
return 0;
set_clock_fail:
@@ -370,14 +381,16 @@
set_gpio_fail:
setup_wlan_gpio(0);
gpio_fail:
- gpio_free(gpio_wlan_sys_rest_en);
+ if (!(machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb() ||
+ machine_is_msm8625_evb() || machine_is_msm8625_evt() ||
+ machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()))
+ gpio_free(gpio_wlan_sys_rest_en);
qrd_gpio_fail:
/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
if (machine_is_msm7627a_qrd1())
gpio_free(GPIO_WLAN_3V3_EN);
reg_disable:
wlan_switch_regulators(0);
-out:
pr_info("WLAN power-down failed\n");
return rc;
}
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index ec8e438..3045f07 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -884,7 +884,8 @@
static void __init add_platform_devices(void)
{
if (machine_is_msm8625_evb() || machine_is_msm8625_qrd7()
- || machine_is_msm8625_evt()) {
+ || machine_is_msm8625_evt()
+ || machine_is_qrd_skud_prime()) {
platform_add_devices(msm8625_evb_devices,
ARRAY_SIZE(msm8625_evb_devices));
platform_add_devices(qrd3_devices,
@@ -899,7 +900,8 @@
ARRAY_SIZE(qrd3_devices));
if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
- || machine_is_msm8625_evt())
+ || machine_is_msm8625_evt()
+ || machine_is_qrd_skud_prime())
platform_add_devices(msm8625_lcd_camera_devices,
ARRAY_SIZE(msm8625_lcd_camera_devices));
else if (machine_is_msm8625_qrd7())
@@ -1070,3 +1072,13 @@
.init_early = qrd7627a_init_early,
.handle_irq = gic_handle_irq,
MACHINE_END
+MACHINE_START(QRD_SKUD_PRIME, "QRD MSM8625 SKUD PRIME")
+ .atag_offset = 0x100,
+ .map_io = msm8625_map_io,
+ .reserve = msm8625_reserve,
+ .init_irq = msm8625_init_irq,
+ .init_machine = msm_qrd_init,
+ .timer = &msm_timer,
+ .init_early = qrd7627a_init_early,
+ .handle_irq = gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 364f297..2db92f3 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -387,7 +387,7 @@
static bool msm_lpm_beyond_limits_l2(struct msm_rpmrs_limits *limits)
{
uint32_t l2;
- bool ret = true;
+ bool ret = false;
struct msm_lpm_resource *rs = &msm_lpm_l2;
if (rs->valid) {
@@ -669,7 +669,7 @@
msm_lpm_get_rpm_notif = false;
for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
rs = msm_lpm_resources[i];
- if (rs->flush)
+ if (rs->valid && rs->flush)
rs->flush(notify_rpm);
}
msm_lpm_get_rpm_notif = true;
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index d283705..2b31f47 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1196,3 +1196,4 @@
msm8625_qrd7 MACH_MSM8625_QRD7 MSM8625_QRD7 4095
msm8625_ffa MACH_MSM8625_FFA MSM8625_FFA 4166
msm8625_evt MACH_MSM8625_EVT MSM8625_EVT 4193
+qrd_skud_prime MACH_QRD_SKUD_PRIME QRD_SKUD_PRIME 4393
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index df66a3a..63a027b 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -1122,7 +1122,12 @@
}
SET_FSR(base, num, fsr);
- SET_RESUME(base, num, 1);
+ /*
+ * Only resume fetches if the registered fault handler
+ * allows it
+ */
+ if (ret != -EBUSY)
+ SET_RESUME(base, num, 1);
ret = IRQ_HANDLED;
} else
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 6de0a77..740c717 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1168,6 +1168,7 @@
usb_anchor_urb(urb, &dev->deferred);
/* no use to process more packets */
netif_stop_queue(net);
+ usb_put_urb(urb);
spin_unlock_irqrestore(&dev->txq.lock, flags);
netdev_dbg(dev->net, "Delaying transmission for resumption\n");
goto deferred;
@@ -1317,6 +1318,8 @@
cancel_work_sync(&dev->kevent);
+ usb_scuttle_anchored_urbs(&dev->deferred);
+
if (dev->driver_info->unbind)
dev->driver_info->unbind (dev, intf);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 352e60e..24918ca 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -51,6 +51,23 @@
* @psy: the power supply to control
* @enable: sets online property of power supply
*/
+int power_supply_set_present(struct power_supply *psy, bool enable)
+{
+ const union power_supply_propval ret = {enable,};
+
+ if (psy->set_property)
+ return psy->set_property(psy, POWER_SUPPLY_PROP_PRESENT,
+ &ret);
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(power_supply_set_present);
+
+/**
+ * power_supply_set_online - set online state of the power supply
+ * @psy: the power supply to control
+ * @enable: sets online property of power supply
+ */
int power_supply_set_online(struct power_supply *psy, bool enable)
{
const union power_supply_propval ret = {enable,};
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index dda8976..0185a3e 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -20,6 +20,7 @@
#include <linux/of_device.h>
#include <linux/radix-tree.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/power_supply.h>
#include <linux/bitops.h>
@@ -69,14 +70,17 @@
#define CHGR_CHG_WDOG_PET 0x64
#define CHGR_CHG_WDOG_EN 0x65
#define CHGR_USB_IUSB_MAX 0x44
+#define CHGR_USB_USB_SUSP 0x47
#define CHGR_USB_ENUM_T_STOP 0x4E
#define CHGR_CHG_TEMP_THRESH 0x66
#define CHGR_BAT_IF_PRES_STATUS 0x08
-#define CHGR_BAT_TEMP_STATUS 0x09
+#define CHGR_STATUS 0x09
#define CHGR_BAT_IF_VCP 0x42
#define CHGR_BAT_IF_BATFET_CTRL1 0x90
#define CHGR_MISC_BOOT_DONE 0x42
+#define CHGR_BUCK_COMPARATOR_OVRIDE_3 0xED
#define MISC_REVISION2 0x01
+#define SEC_ACCESS 0xD0
/* SMBB peripheral subtype values */
#define REG_OFFSET_PERP_SUBTYPE 0x05
@@ -133,6 +137,9 @@
/* smbb_misc_interrupts */
#define TFTWDOG_IRQ BIT(0)
+/* Workaround flags */
+#define CHG_FLAGS_VCP_WA BIT(0)
+
/**
* struct qpnp_chg_chip - device information
* @dev: device pointer to access the parent
@@ -156,6 +163,8 @@
* @usb_psy power supply to export information to userspace
* @bms_psy power supply to export information to userspace
* @batt_psy: power supply to export information to userspace
+ * @flags: flags to activate specific workarounds
+ * throughout the driver
*
*/
struct qpnp_chg_chip {
@@ -185,6 +194,7 @@
struct power_supply *usb_psy;
struct power_supply *bms_psy;
struct power_supply batt_psy;
+ uint32_t flags;
};
static struct qpnp_chg_chip *the_chip;
@@ -258,6 +268,7 @@
return 0;
}
+#define USB_VALID_BIT BIT(7)
static int
qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
{
@@ -265,16 +276,16 @@
int rc;
rc = qpnp_chg_read(chip, &usbin_valid_rt_sts,
- INT_RT_STS(chip->usb_chgpth_base), 1);
+ chip->usb_chgpth_base + CHGR_STATUS , 1);
if (rc) {
pr_err("spmi read failed: addr=%03X, rc=%d\n",
- INT_RT_STS(chip->usb_chgpth_base), rc);
+ chip->usb_chgpth_base + CHGR_STATUS, rc);
return rc;
}
pr_debug("chgr usb sts 0x%x\n", usbin_valid_rt_sts);
- return (usbin_valid_rt_sts & USBIN_VALID_IRQ) ? 1 : 0;
+ return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
}
static int
@@ -294,7 +305,6 @@
return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
}
-#define VCP_IUSBMAX_SETTING_MA 2000
#define QPNP_CHG_IUSB_MAX_MIN_100 100
#define QPNP_CHG_IUSB_MAX_MIN_150 150
#define QPNP_CHG_IUSB_MAX_MIN_MA 200
@@ -303,7 +313,8 @@
static int
qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
{
- u8 usb_reg = 0;
+ int rc = 0;
+ u8 usb_reg = 0, temp = 8;
if (mA == QPNP_CHG_IUSB_MAX_MIN_100) {
usb_reg = 0x00;
@@ -323,17 +334,42 @@
return -EINVAL;
}
- /* Hack for VCP issue make sure IUSBMAX setting
- * is at least 2 A to not brown out device */
- mA = VCP_IUSBMAX_SETTING_MA;
-
usb_reg = mA / QPNP_CHG_IUSB_MAX_STEP_MA;
+ if (chip->flags & CHG_FLAGS_VCP_WA) {
+ temp = 0xA5;
+ rc = qpnp_chg_write(chip, &temp,
+ chip->buck_base + SEC_ACCESS, 1);
+ rc = qpnp_chg_masked_write(chip,
+ chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
+ 0x0C, 0x0C, 1);
+ }
+
pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
- return qpnp_chg_write(chip, &usb_reg,
+ rc = qpnp_chg_write(chip, &usb_reg,
chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
- pr_debug("done\n");
- return 0;
+
+ if (chip->flags & CHG_FLAGS_VCP_WA) {
+ temp = 0xA5;
+ udelay(200);
+ rc = qpnp_chg_write(chip, &temp,
+ chip->buck_base + SEC_ACCESS, 1);
+ rc = qpnp_chg_masked_write(chip,
+ chip->buck_base + CHGR_BUCK_COMPARATOR_OVRIDE_3,
+ 0x0C, 0x00, 1);
+ }
+
+ return rc;
+}
+
+#define USB_SUSPEND_BIT BIT(0)
+static int
+qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
+{
+ return qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + CHGR_USB_USB_SUSP,
+ USB_SUSPEND_BIT,
+ enable ? USB_SUSPEND_BIT : 0, 1);
}
#define ENUM_T_STOP_BIT BIT(0)
@@ -350,11 +386,6 @@
chip->usb_present = usb_present;
power_supply_set_present(chip->usb_psy,
chip->usb_present);
- } else if (!(chip->usb_present && usb_present)) {
- qpnp_chg_masked_write(chip,
- chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
- ENUM_T_STOP_BIT,
- ENUM_T_STOP_BIT, 1);
}
return IRQ_HANDLED;
@@ -368,7 +399,7 @@
int rc, usb_present;
rc = qpnp_chg_masked_write(chip,
- chip->usb_chgpth_base + CHGR_CHG_FAILED,
+ chip->chgr_base + CHGR_CHG_FAILED,
CHGR_CHG_FAILED_BIT,
CHGR_CHG_FAILED_BIT, 1);
if (rc)
@@ -488,7 +519,7 @@
int rc;
rc = qpnp_chg_read(chip, &batt_health,
- chip->bat_if_base + CHGR_BAT_TEMP_STATUS, 1);
+ chip->bat_if_base + CHGR_STATUS, 1);
if (rc) {
pr_err("Couldn't read battery health read failed rc=%d\n", rc);
return POWER_SUPPLY_HEALTH_UNKNOWN;
@@ -647,8 +678,13 @@
chip->usb_psy->get_property(chip->usb_psy,
POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
+ if ((ret.intval / 1000) <= QPNP_CHG_IUSB_MAX_MIN_MA)
+ qpnp_chg_usb_suspend_enable(chip, 1);
+ else
+ qpnp_chg_usb_suspend_enable(chip, 0);
} else {
- qpnp_chg_iusbmax_set(chip, QPNP_CHG_IUSB_MAX_MIN_MA);
+ qpnp_chg_iusbmax_set(chip, QPNP_CHG_IUSB_MAX_MIN_100);
+ qpnp_chg_usb_suspend_enable(chip, 0);
}
pr_debug("end of power supply changed\n");
@@ -863,6 +899,14 @@
chip->chgr_base + CHGR_VDD_MAX, 1);
}
+
+static void
+qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
+{
+ if (chip->revision > 0)
+ chip->flags |= CHG_FLAGS_VCP_WA;
+}
+
#define WDOG_EN_BIT BIT(7)
static int
qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
@@ -944,7 +988,7 @@
case SMBB_BAT_IF_SUBTYPE:
/* HACK: Unlock secure access to override temp comparator */
rc = qpnp_chg_masked_write(chip,
- chip->bat_if_base + 0xD0,
+ chip->bat_if_base + SEC_ACCESS,
0xA5, 0xA5, 1);
pr_debug("override hot cold\n");
rc = qpnp_chg_masked_write(chip,
@@ -980,6 +1024,12 @@
return -ENXIO;
}
}
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
+ ENUM_T_STOP_BIT,
+ ENUM_T_STOP_BIT, 1);
+
break;
case SMBB_DC_CHGPTH_SUBTYPE:
break;
@@ -1199,6 +1249,9 @@
goto unregister_dc;
}
+ /* Turn on appropriate workaround flags */
+ qpnp_chg_setup_flags(chip);
+
power_supply_set_present(chip->usb_psy,
qpnp_chg_is_usb_chg_plugged_in(chip));
diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c
index 61e6891..410b5c4 100644
--- a/drivers/usb/misc/ks_bridge.c
+++ b/drivers/usb/misc/ks_bridge.c
@@ -287,6 +287,9 @@
unsigned long flags;
struct ks_bridge *ksb = fp->private_data;
+ if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
+ return -ENODEV;
+
pkt = ksb_alloc_data_pkt(count, GFP_KERNEL, ksb);
if (IS_ERR(pkt)) {
pr_err("unable to allocate data packet");
@@ -570,6 +573,8 @@
struct usb_endpoint_descriptor *ep_desc;
int i;
struct ks_bridge *ksb;
+ unsigned long flags;
+ struct data_pkt *pkt;
ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
@@ -625,6 +630,23 @@
dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
+ /*free up stale buffers if any from previous disconnect*/
+ spin_lock_irqsave(&ksb->lock, flags);
+ while (!list_empty(&ksb->to_ks_list)) {
+ pkt = list_first_entry(&ksb->to_ks_list,
+ struct data_pkt, list);
+ list_del_init(&pkt->list);
+ ksb_free_data_pkt(pkt);
+ ksb->alloced_read_pkts--;
+ }
+ while (!list_empty(&ksb->to_mdm_list)) {
+ pkt = list_first_entry(&ksb->to_mdm_list,
+ struct data_pkt, list);
+ list_del_init(&pkt->list);
+ ksb_free_data_pkt(pkt);
+ }
+ spin_unlock_irqrestore(&ksb->lock, flags);
+
ksb->fs_dev = (struct miscdevice *)id->driver_info;
misc_register(ksb->fs_dev);
@@ -674,6 +696,8 @@
cancel_work_sync(&ksb->to_mdm_work);
cancel_work_sync(&ksb->start_rx_work);
+ misc_deregister(ksb->fs_dev);
+
usb_kill_anchored_urbs(&ksb->submitted);
wait_event_interruptible_timeout(
@@ -688,6 +712,7 @@
struct data_pkt, list);
list_del_init(&pkt->list);
ksb_free_data_pkt(pkt);
+ ksb->alloced_read_pkts--;
}
while (!list_empty(&ksb->to_mdm_list)) {
pkt = list_first_entry(&ksb->to_mdm_list,
@@ -697,7 +722,6 @@
}
spin_unlock_irqrestore(&ksb->lock, flags);
- misc_deregister(ksb->fs_dev);
ifc->needs_remote_wakeup = 0;
usb_put_dev(ksb->udev);
ksb->ifc = NULL;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index c43f6b6..26f1b84 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -39,7 +39,6 @@
#include <linux/regulator/consumer.h>
#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/mfd/pm8xxx/misc.h>
-#include <linux/power_supply.h>
#include <linux/mhl_8334.h>
#include <mach/scm.h>
@@ -97,6 +96,7 @@
static struct power_supply *psy;
static bool aca_id_turned_on;
+static bool legacy_power_supply;
static inline bool aca_enabled(void)
{
#ifdef CONFIG_USB_MSM_ACA
@@ -1116,24 +1116,32 @@
}
#endif
-static int msm_otg_notify_host_mode(struct msm_otg *motg, bool host_mode)
+static void msm_otg_notify_host_mode(struct msm_otg *motg, bool host_mode)
{
- if (!psy)
- goto psy_not_supported;
+ struct power_supply *usb = psy ? psy : &motg->usb_psy;
- if (host_mode)
- power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_SYSTEM);
- else
- power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_DEVICE);
+ if (!usb) {
+ pr_err("No USB power supply registered!\n");
+ return;
+ }
-psy_not_supported:
- dev_dbg(motg->phy.dev, "Power Supply doesn't support USB charger\n");
- return -ENXIO;
+ if (psy) {
+ /* legacy support */
+ if (host_mode)
+ power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_SYSTEM);
+ else
+ power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_DEVICE);
+ return;
+ } else {
+ motg->host_mode = host_mode;
+ power_supply_changed(usb);
+ }
}
static int msm_otg_notify_chg_type(struct msm_otg *motg)
{
static int charger_type;
+ struct power_supply *usb = psy ? psy : &motg->usb_psy;
/*
* TODO
@@ -1157,40 +1165,44 @@
else
charger_type = POWER_SUPPLY_TYPE_BATTERY;
- if (!psy) {
+ if (!usb) {
pr_err("No USB power supply registered!\n");
return -EINVAL;
}
pr_debug("setting usb power supply type %d\n", charger_type);
- power_supply_set_supply_type(psy, charger_type);
+ power_supply_set_supply_type(usb, charger_type);
return 0;
}
static int msm_otg_notify_power_supply(struct msm_otg *motg, unsigned mA)
{
+ struct power_supply *usb = psy ? psy : &motg->usb_psy;
- if (!psy)
- goto psy_not_supported;
-
- if (motg->cur_power == 0 && mA > 0) {
- /* Enable charging */
- if (power_supply_set_online(psy, true))
- goto psy_not_supported;
- } else if (motg->cur_power > 0 && mA == 0) {
- /* Disable charging */
- if (power_supply_set_online(psy, false))
- goto psy_not_supported;
- return 0;
+ if (!usb) {
+ dev_dbg(motg->phy.dev, "no usb power supply registered\n");
+ goto psy_error;
}
- /* Set max current limit */
- if (power_supply_set_current_limit(psy, 1000*mA))
- goto psy_not_supported;
+ if (motg->cur_power == 0 && mA > 2) {
+ /* Enable charging */
+ if (power_supply_set_online(usb, true))
+ goto psy_error;
+ if (power_supply_set_current_limit(usb, 1000*mA))
+ goto psy_error;
+ } else if (motg->cur_power > 0 && (mA == 0 || mA == 2)) {
+ /* Disable charging */
+ if (power_supply_set_online(usb, false))
+ goto psy_error;
+ /* Set max current limit */
+ if (power_supply_set_current_limit(usb, 0))
+ goto psy_error;
+ }
+ power_supply_changed(usb);
return 0;
-psy_not_supported:
- dev_dbg(motg->phy.dev, "Power Supply doesn't support USB charger\n");
+psy_error:
+ dev_dbg(motg->phy.dev, "power supply error when setting property\n");
return -ENXIO;
}
@@ -2321,9 +2333,13 @@
case OTG_STATE_UNDEFINED:
msm_otg_reset(otg->phy);
msm_otg_init_sm(motg);
- psy = power_supply_get_by_name("usb");
- if (!psy)
- pr_err("couldn't get usb power supply\n");
+ if (!psy && legacy_power_supply) {
+ psy = power_supply_get_by_name("usb");
+
+ if (!psy)
+ pr_err("couldn't get usb power supply\n");
+ }
+
otg->phy->state = OTG_STATE_B_IDLE;
if (!test_bit(B_SESS_VLD, &motg->inputs) &&
test_bit(ID, &motg->inputs)) {
@@ -3364,6 +3380,71 @@
return count;
}
+static int otg_power_get_property_usb(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct msm_otg *motg = container_of(psy, struct msm_otg,
+ usb_psy);
+ switch (psp) {
+ case POWER_SUPPLY_PROP_SCOPE:
+ if (motg->host_mode)
+ val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
+ else
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = motg->current_max;
+ break;
+ /* Reflect USB enumeration */
+ case POWER_SUPPLY_PROP_PRESENT:
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = motg->online;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int otg_power_set_property_usb(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct msm_otg *motg = container_of(psy, struct msm_otg,
+ usb_psy);
+
+ switch (psp) {
+ /* Process PMIC notification in PRESENT prop */
+ case POWER_SUPPLY_PROP_PRESENT:
+ msm_otg_set_vbus_state(val->intval);
+ break;
+ /* The ONLINE property reflects if usb has enumerated */
+ case POWER_SUPPLY_PROP_ONLINE:
+ motg->online = val->intval;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ motg->current_max = val->intval;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ power_supply_changed(&motg->usb_psy);
+ return 0;
+}
+
+static char *otg_pm_power_supplied_to[] = {
+ "battery",
+};
+
+static enum power_supply_property otg_pm_power_props_usb[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_SCOPE,
+};
+
const struct file_operations msm_otg_bus_fops = {
.open = msm_otg_bus_open,
.read = seq_read,
@@ -3550,6 +3631,23 @@
return retval;
}
+static int msm_otg_register_power_supply(struct platform_device *pdev,
+ struct msm_otg *motg)
+{
+ int ret;
+
+ ret = power_supply_register(&pdev->dev, &motg->usb_psy);
+ if (ret < 0) {
+ dev_err(motg->phy.dev,
+ "%s:power_supply_register usb failed\n",
+ __func__);
+ return ret;
+ }
+
+ legacy_power_supply = false;
+ return 0;
+}
+
struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -3873,9 +3971,6 @@
dev_dbg(&pdev->dev, "mode debugfs file is"
"not available\n");
- if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
- pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
-
if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
(!(motg->pdata->mode == USB_OTG) ||
@@ -3905,6 +4000,32 @@
debug_bus_voting_enabled = true;
}
+ motg->usb_psy.name = "usb";
+ motg->usb_psy.type = POWER_SUPPLY_TYPE_USB;
+ motg->usb_psy.supplied_to = otg_pm_power_supplied_to;
+ motg->usb_psy.num_supplicants = ARRAY_SIZE(otg_pm_power_supplied_to);
+ motg->usb_psy.properties = otg_pm_power_props_usb;
+ motg->usb_psy.num_properties = ARRAY_SIZE(otg_pm_power_props_usb);
+ motg->usb_psy.get_property = otg_power_get_property_usb;
+ motg->usb_psy.set_property = otg_power_set_property_usb;
+
+ if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ /* if pm8921 use legacy implementation */
+ if (!pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state)) {
+ dev_dbg(motg->phy.dev, "%s: legacy support\n",
+ __func__);
+ legacy_power_supply = true;
+ } else {
+ ret = msm_otg_register_power_supply(pdev, motg);
+ if (ret)
+ goto remove_phy;
+ }
+ } else {
+ ret = msm_otg_register_power_supply(pdev, motg);
+ if (ret)
+ goto remove_phy;
+ }
+
return 0;
remove_phy:
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 03390b1..730c7b2 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -218,6 +218,7 @@
extern int power_supply_set_battery_charged(struct power_supply *psy);
extern int power_supply_set_current_limit(struct power_supply *psy, int limit);
extern int power_supply_set_online(struct power_supply *psy, bool enable);
+extern int power_supply_set_present(struct power_supply *psy, bool enable);
extern int power_supply_set_scope(struct power_supply *psy, int scope);
extern int power_supply_set_charge_type(struct power_supply *psy, int type);
extern int power_supply_set_supply_type(struct power_supply *psy,
@@ -241,6 +242,9 @@
static inline int power_supply_set_online(struct power_supply *psy,
bool enable)
{ return -ENOSYS; }
+static inline int power_supply_set_present(struct power_supply *psy,
+ bool enable)
+ { return -ENOSYS; }
static inline int power_supply_set_scope(struct power_supply *psy,
int scope)
{ return -ENOSYS; }
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 9294c27..a998ac2 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -25,7 +25,7 @@
#include <linux/wakelock.h>
#include <linux/pm_qos.h>
#include <linux/hrtimer.h>
-
+#include <linux/power_supply.h>
/*
* The following are bit fields describing the usb_request.udc_priv word.
* These bit fields are set by function drivers that wish to queue
@@ -383,6 +383,10 @@
u8 active_tmout;
struct hrtimer timer;
enum usb_vdd_type vdd_type;
+ struct power_supply usb_psy;
+ unsigned int online;
+ unsigned int host_mode;
+ unsigned int current_max;
};
struct msm_hsic_host_platform_data {
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 4aab4c7..57a7fa7 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -639,6 +639,18 @@
return 0;
}
+static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ pr_debug("%s()\n", __func__);
+ rate->min = rate->max = 48000;
+
+ return 0;
+}
+
static const struct soc_enum msm_snd_enum[] = {
SOC_ENUM_SINGLE_EXT(2, spk_function),
SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
@@ -983,6 +995,30 @@
.be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
},
+ {
+ .name = LPASS_BE_INT_FM_RX,
+ .stream_name = "Internal FM Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.12292",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INT_FM_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_INT_FM_TX,
+ .stream_name = "Internal FM Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.12293",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INT_FM_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ },
/* Backend AFE DAI Links */
{
.name = LPASS_BE_AFE_PCM_RX,
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index dacd59c..354dece 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -899,6 +899,36 @@
.remove = msm_dai_q6_dai_remove,
};
+static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
+ .capture = {
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
+
static int __devinit msm_auxpcm_dev_probe(struct platform_device *pdev)
{
int id;
@@ -1158,6 +1188,12 @@
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_bt_sco_tx_dai);
break;
+ case INT_FM_RX:
+ rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
+ break;
+ case INT_FM_TX:
+ rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
+ break;
case RT_PROXY_DAI_001_RX:
case RT_PROXY_DAI_002_RX:
rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index f0465a5..4819e0a 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -344,6 +344,8 @@
break;
case INT_BT_SCO_RX:
case INT_BT_SCO_TX:
+ case INT_FM_RX:
+ case INT_FM_TX:
cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
break;
default: