Merge "ASoC: wcd9xxx: don't release mbhc firmware while it's still in use"
diff --git a/Documentation/devicetree/bindings/input/misc/cm36283.txt b/Documentation/devicetree/bindings/input/misc/cm36283.txt
new file mode 100644
index 0000000..b5ee7d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/cm36283.txt
@@ -0,0 +1,40 @@
+Capella cm36283 L/P sensor
+
+Required properties:
+
+ - compatible : Should be "capella,cm36283".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : Parent of interrupt.
+ - interrupts : L/P sample interrupt to indicate new data ready.
+ - vdd-supply : Power supply needed to power up the device.
+ - vio-supply : IO power supply needed for IO and I2C.
+ - capella,interrupt-gpio : The gpio pin for the interrupt.
+ - capella,levels : The adc value for light sensor to trigger different light level.
+ - capella,ps_close_thd_set : The threshold adc value for proximity sensor to trigger close interrupt.
+ - capella,ps_away_thd_set: The threshold adc value for proximity sensor to trigger away interrupt.
+ - capella,ls_cmd : The initial value to configure cm36283 ALS_CONF register.
+ - capella,ps_conf1_val : The initial value to configure cm36283 PS_CONF1 register.
+ - capella,ps_conf3_val : The initial value to configure cm36283 PS_CONF3 register.
+
+Optional properties:
+
+ - capella,use-polling : Property to specify if using polling instead of interrupt for adc value report.
+
+Example:
+
+ capella@60 {
+ compatible = "capella,cm36283";
+ reg = <0x60>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <80 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ capella,use-polling;
+ capella,interrupt-gpio = <80>;
+ capella,levels = <0x0A 0xA0 0xE1 0x140 0x280 0x500 0xA28 0x16A8 0x1F40 0x2800>;
+ capella,ps_close_thd_set = <0xa>;
+ capella,ps_away_thd_set = <0x5>;
+ capella,ls_cmd = <0x44>; /* PS_IT=160ms, INT_PERS=2*/
+ capella,ps_conf1_val = <0x0006>; /*CM36283_PS_ITB_1_2 | CM36283_PS_DR_1_40| CM36283_PS_IT_1T | CM36283_PS_PERS_2 | CM36283_PS_RES_1*/
+ capella,ps_conf3_val = <0x3010>; /* CM36283_PS_MS_NORMAL | CM36283_PS_PROL_255 | CM36283_PS_SMART_PERS_ENABLE, */
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 8827983..9fd3afe 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -9,6 +9,7 @@
arm ARM Ltd.
atmel Atmel Corporation
bosch Bosch Sensortec GmbH
+capella Capella Microsystems, Inc.
cavium Cavium, Inc.
chrp Common Hardware Reference Platform
cortina Cortina Systems, Inc.
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 7e80d19..8ed6ae2 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -114,6 +114,23 @@
fsl,irq-gpio = <&msmgpio 81 0x00>;
fsl,sensors-position = <5>;
};
+ capella@60 {
+ compatible = "capella,cm36283";
+ reg = <0x60>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <80 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ capella,use-polling;
+ capella,interrupt-gpio = <&msmgpio 80 0x2>;
+ capella,levels = <0x0A 0xA0 0xE1 0x140 0x280 0x500 0xA28 0x16A8 0x1F40
+ 0x2800>;
+ capella,ps_close_thd_set = <0xa>;
+ capella,ps_away_thd_set = <0x5>;
+ capella,ls_cmd = <0x44>; /* PS_IT=160ms, INT_PERS=2*/
+ capella,ps_conf1_val = <0x0006>;
+ capella,ps_conf3_val = <0x3010>;
+ };
};
gen-vkeys {
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index 68841bc..dba3da4 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -24,7 +24,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -41,7 +41,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -58,7 +58,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 06 26 30 0f];
};
@@ -75,7 +75,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 7bf8edbe..7d96cb1 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -98,14 +98,17 @@
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
CONFIG_INET=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
@@ -142,6 +145,7 @@
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -417,8 +421,10 @@
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
+CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_NFC_QNCI=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index a9f18fd..1d5c492 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -99,14 +99,17 @@
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
CONFIG_INET=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
@@ -143,6 +146,7 @@
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -468,8 +472,10 @@
CONFIG_EARLY_PRINTK=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
+CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_NFC_QNCI=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 2b76ba8..03ddb3a 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -391,3 +391,4 @@
CONFIG_SENSORS_STK3X1X=y
CONFIG_SENSORS_MMA8X5X=y
CONFIG_LOGCAT_SIZE=64
+CONFIG_SENSORS_CAPELLA_CM36283=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 0f4e4c6..9788e7c 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -438,3 +438,4 @@
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_SENSORS_STK3X1X=y
CONFIG_SENSORS_MMA8X5X=y
+CONFIG_SENSORS_CAPELLA_CM36283=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 6ad1b12..3bc159a 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -159,6 +159,7 @@
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 2976ee8..118fdd4 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -165,6 +165,7 @@
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
diff --git a/arch/arm/mach-msm/include/mach/qpnp-int.h b/arch/arm/mach-msm/include/mach/qpnp-int.h
index 2b86216..1f31ea5 100644
--- a/arch/arm/mach-msm/include/mach/qpnp-int.h
+++ b/arch/arm/mach-msm/include/mach/qpnp-int.h
@@ -71,6 +71,28 @@
*/
int qpnpint_handle_irq(struct spmi_controller *spmi_ctrl,
struct qpnp_irq_spec *spec);
+
+/**
+ * qpnpint_show_irq - Prints the Linux interrupt number
+ *
+ * Pass a PMIC Arbiter interrupt to Linux.
+ */
+int qpnpint_show_irq(struct spmi_controller *spmi_ctrl,
+ struct qpnp_irq_spec *spec);
+
+#ifdef CONFIG_MSM_SHOW_RESUME_IRQ
+extern int msm_show_resume_irq_mask;
+static inline bool qpnpint_show_resume_irq(void)
+{
+ return msm_show_resume_irq_mask;
+}
+#else
+static inline bool qpnpint_show_resume_irq(void)
+{
+ return false;
+}
+#endif
+
#else
static inline int __init qpnpint_of_init(struct device_node *node,
struct device_node *parent)
@@ -97,5 +119,15 @@
{
return -ENXIO;
}
+int qpnpint_show_irq(struct spmi_controller *spmi_ctrl,
+ struct qpnp_irq_spec *spec)
+{
+ return -ENXIO;
+}
+
+static inline bool qpnpint_show_resume_irq(void)
+{
+ return false;
+}
#endif /* CONFIG_MSM_QPNP_INT */
#endif /* QPNPINT_H */
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index aaa2fc8..716ea0d 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -704,4 +704,14 @@
To compile this driver as a module, choose M here: the
module will be called stk3x1x.
+config SENSORS_CAPELLA_CM36283
+ tristate "CM36283 proximity and light sensor"
+ depends on I2C
+ default n
+ help
+ Say Y here to enable the CM36283 Proximity
+ Sensor with Ambient Light Sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called CM36283.
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 445fba0..c927e0e 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -65,3 +65,4 @@
obj-$(CONFIG_BMP18X_I2C) += bmp18x-i2c.o
obj-$(CONFIG_SENSORS_MMA8X5X) += mma8x5x.o
obj-$(CONFIG_SENSORS_STK3X1X) += stk3x1x.o
+obj-$(CONFIG_SENSORS_CAPELLA_CM36283) += cm36283.o
diff --git a/drivers/input/misc/cm36283.c b/drivers/input/misc/cm36283.c
index a9f8140..d850a0e 100644
--- a/drivers/input/misc/cm36283.c
+++ b/drivers/input/misc/cm36283.c
@@ -2,7 +2,9 @@
*
* Copyright (C) 2012 Capella Microsystems Inc.
* Author: Frank Hsieh <pengyueh@gmail.com>
- *
+ *
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
@@ -32,6 +34,7 @@
#include <linux/wakelock.h>
#include <linux/jiffies.h>
#include <linux/cm36283.h>
+#include <linux/of_gpio.h>
#include <asm/uaccess.h>
#include <asm/mach-types.h>
@@ -53,7 +56,31 @@
#define CM36283_VI2C_MIN_UV 1750000
#define CM36283_VI2C_MAX_UV 1950000
+/* cm36283 polling rate in ms */
+#define CM36283_LS_MIN_POLL_DELAY 1
+#define CM36283_LS_MAX_POLL_DELAY 1000
+#define CM36283_LS_DEFAULT_POLL_DELAY 100
+
+#define CM36283_PS_MIN_POLL_DELAY 1
+#define CM36283_PS_MAX_POLL_DELAY 1000
+#define CM36283_PS_DEFAULT_POLL_DELAY 100
+
static int record_init_fail = 0;
+
+static const int als_range[] = {
+ [CM36283_ALS_IT0] = 6554,
+ [CM36283_ALS_IT1] = 3277,
+ [CM36283_ALS_IT2] = 1638,
+ [CM36283_ALS_IT3] = 819,
+};
+
+static const int als_sense[] = {
+ [CM36283_ALS_IT0] = 10,
+ [CM36283_ALS_IT1] = 20,
+ [CM36283_ALS_IT2] = 40,
+ [CM36283_ALS_IT3] = 80,
+};
+
static void sensor_irq_do_work(struct work_struct *work);
static DECLARE_WORK(sensor_irq_work, sensor_irq_do_work);
@@ -101,23 +128,30 @@
uint16_t ls_cmd;
uint8_t record_clear_int_fail;
-
+ bool polling;
+ atomic_t ls_poll_delay;
+ atomic_t ps_poll_delay;
struct regulator *vdd;
struct regulator *vio;
+ struct delayed_work ldwork;
+ struct delayed_work pdwork;
};
struct cm36283_info *lp_info;
int fLevel=-1;
static struct mutex als_enable_mutex, als_disable_mutex, als_get_adc_mutex;
static struct mutex ps_enable_mutex, ps_disable_mutex, ps_get_adc_mutex;
static struct mutex CM36283_control_mutex;
+static struct mutex wq_lock;
static int lightsensor_enable(struct cm36283_info *lpi);
static int lightsensor_disable(struct cm36283_info *lpi);
static int initial_cm36283(struct cm36283_info *lpi);
static void psensor_initial_cmd(struct cm36283_info *lpi);
+static int cm36283_power_set(struct cm36283_info *info, bool on);
int32_t als_kadc;
-static int control_and_report(struct cm36283_info *lpi, uint8_t mode, uint16_t param);
+static int control_and_report(struct cm36283_info *lpi, uint8_t mode,
+ uint16_t param, int report);
static int I2C_RxData(uint16_t slaveAddr, uint8_t cmd, uint8_t *rxData, int length)
{
@@ -382,12 +416,91 @@
{
struct cm36283_info *lpi = lp_info;
uint16_t intFlag;
- _cm36283_I2C_Read_Word(lpi->slave_addr, INT_FLAG, &intFlag);
- control_and_report(lpi, CONTROL_INT_ISR_REPORT, intFlag);
-
+ _cm36283_I2C_Read_Word(lpi->slave_addr, INT_FLAG, &intFlag);
+ control_and_report(lpi, CONTROL_INT_ISR_REPORT, intFlag, 1);
+
enable_irq(lpi->irq);
}
+static int get_als_range(void)
+{
+ uint16_t ls_conf;
+ int ret = 0;
+ int index = 0;
+ struct cm36283_info *lpi = lp_info;
+
+ ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_CONF, &ls_conf);
+ if (ret) {
+ dev_err(&lpi->i2c_client->dev, "read ALS_CONF from i2c error. %d\n",
+ ret);
+ return -EIO;
+ }
+
+ index = (ls_conf & 0xC0) >> 0x06;
+ return als_range[index];
+}
+
+static int get_als_sense(void)
+{
+ uint16_t ls_conf;
+ int ret = 0;
+ int index = 0;
+ struct cm36283_info *lpi = lp_info;
+
+ ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_CONF, &ls_conf);
+ if (ret) {
+ dev_err(&lpi->i2c_client->dev, "read ALS_CONF from i2c error. %d\n",
+ ret);
+ return -EIO;
+ }
+
+ index = (ls_conf & 0xC0) >> 0x06;
+ return als_sense[index];
+}
+
+static void psensor_delay_work_handler(struct work_struct *work)
+{
+ struct cm36283_info *lpi = lp_info;
+ uint16_t adc_value = 0;
+ int ret;
+
+ mutex_lock(&wq_lock);
+
+ ret = get_ps_adc_value(&adc_value);
+
+ mutex_unlock(&wq_lock);
+
+ if (ret >= 0) {
+ input_report_abs(lpi->ps_input_dev, ABS_DISTANCE,
+ adc_value > lpi->ps_close_thd_set ? 0 : 1);
+ input_sync(lpi->ps_input_dev);
+ }
+ schedule_delayed_work(&lpi->pdwork,
+ msecs_to_jiffies(atomic_read(&lpi->ps_poll_delay)));
+}
+
+static void lsensor_delay_work_handler(struct work_struct *work)
+{
+ struct cm36283_info *lpi = lp_info;
+ uint16_t adc_value = 0;
+ int sense;
+
+ mutex_lock(&wq_lock);
+
+ get_ls_adc_value(&adc_value, 0);
+ sense = get_als_sense();
+
+ mutex_unlock(&wq_lock);
+
+ if (sense > 0) {
+ lpi->current_adc = adc_value;
+ input_report_abs(lpi->ls_input_dev, ABS_MISC, adc_value/sense);
+ input_sync(lpi->ls_input_dev);
+ }
+ schedule_delayed_work(&lpi->ldwork,
+ msecs_to_jiffies(atomic_read(&lpi->ls_poll_delay)));
+}
+
static irqreturn_t cm36283_irq_handler(int irq, void *data)
{
struct cm36283_info *lpi = data;
@@ -431,33 +544,44 @@
static int psensor_enable(struct cm36283_info *lpi)
{
int ret = -EIO;
+ unsigned int delay;
mutex_lock(&ps_enable_mutex);
D("[PS][CM36283] %s\n", __func__);
- if ( lpi->ps_enable ) {
+ if (lpi->ps_enable) {
D("[PS][CM36283] %s: already enabled\n", __func__);
ret = 0;
- } else
- ret = control_and_report(lpi, CONTROL_PS, 1);
-
+ } else {
+ ret = control_and_report(lpi, CONTROL_PS, 1, 0);
+ }
+
mutex_unlock(&ps_enable_mutex);
+
+ delay = atomic_read(&lpi->ps_poll_delay);
+ if (lpi->polling)
+ schedule_delayed_work(&lpi->pdwork, msecs_to_jiffies(delay));
+
return ret;
}
static int psensor_disable(struct cm36283_info *lpi)
{
int ret = -EIO;
-
+
+ if (lpi->polling)
+ cancel_delayed_work_sync(&lpi->pdwork);
+
mutex_lock(&ps_disable_mutex);
D("[PS][CM36283] %s\n", __func__);
- if ( lpi->ps_enable == 0 ) {
+ if (lpi->ps_enable == 0) {
D("[PS][CM36283] %s: already disabled\n", __func__);
ret = 0;
- } else
- ret = control_and_report(lpi, CONTROL_PS,0);
-
+ } else {
+ ret = control_and_report(lpi, CONTROL_PS, 0, 0);
+ }
+
mutex_unlock(&ps_disable_mutex);
return ret;
}
@@ -581,6 +705,7 @@
static int lightsensor_enable(struct cm36283_info *lpi)
{
int ret = -EIO;
+ unsigned int delay;
mutex_lock(&als_enable_mutex);
D("[LS][CM36283] %s\n", __func__);
@@ -588,10 +713,17 @@
if (lpi->als_enable) {
D("[LS][CM36283] %s: already enabled\n", __func__);
ret = 0;
- } else
- ret = control_and_report(lpi, CONTROL_ALS, 1);
+ } else {
+ ret = control_and_report(lpi, CONTROL_ALS, 1, 0);
+ }
mutex_unlock(&als_enable_mutex);
+
+ delay = atomic_read(&lpi->ls_poll_delay);
+ if (lpi->polling)
+ schedule_delayed_work(&lpi->ldwork,
+ msecs_to_jiffies(delay));
+
return ret;
}
@@ -601,11 +733,15 @@
mutex_lock(&als_disable_mutex);
D("[LS][CM36283] %s\n", __func__);
+ if (lpi->polling)
+ cancel_delayed_work_sync(&lpi->ldwork);
+
if ( lpi->als_enable == 0 ) {
D("[LS][CM36283] %s: already disabled\n", __func__);
ret = 0;
- } else
- ret = control_and_report(lpi, CONTROL_ALS, 0);
+ } else {
+ ret = control_and_report(lpi, CONTROL_ALS, 0, 0);
+ }
mutex_unlock(&als_disable_mutex);
return ret;
@@ -688,13 +824,14 @@
uint16_t value;
int ret;
struct cm36283_info *lpi = lp_info;
- int intr_val;
-
- intr_val = gpio_get_value(lpi->intr_pin);
+ int intr_val = -1;
get_ps_adc_value(&value);
+ if (gpio_is_valid(lpi->intr_pin))
+ intr_val = gpio_get_value(lpi->intr_pin);
- ret = sprintf(buf, "ADC[0x%04X], ENABLE = %d, intr_pin = %d\n", value, lpi->ps_enable, intr_val);
+ ret = snprintf(buf, PAGE_SIZE, "ADC[0x%04X], ENABLE=%d intr_pin=%d\n",
+ value, lpi->ps_enable, intr_val);
return ret;
}
@@ -1076,6 +1213,62 @@
}
static DEVICE_ATTR(ls_conf, 0664, ls_conf_show, ls_conf_store);
+static ssize_t ls_poll_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cm36283_info *lpi = lp_info;
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ atomic_read(&lpi->ls_poll_delay));
+}
+
+static ssize_t ls_poll_delay_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct cm36283_info *lpi = lp_info;
+ unsigned long interval_ms;
+
+ if (kstrtoul(buf, 10, &interval_ms))
+ return -EINVAL;
+
+ if ((interval_ms < CM36283_LS_MIN_POLL_DELAY) ||
+ (interval_ms > CM36283_LS_MAX_POLL_DELAY))
+ return -EINVAL;
+
+ atomic_set(&lpi->ls_poll_delay, (unsigned int) interval_ms);
+ return count;
+}
+
+static DEVICE_ATTR(ls_poll_delay, 0664, ls_poll_delay_show,
+ ls_poll_delay_store);
+
+static ssize_t ps_poll_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cm36283_info *lpi = lp_info;
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ atomic_read(&lpi->ps_poll_delay));
+}
+
+static ssize_t ps_poll_delay_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct cm36283_info *lpi = lp_info;
+ unsigned long interval_ms;
+
+ if (kstrtoul(buf, 10, &interval_ms))
+ return -EINVAL;
+
+ if ((interval_ms < CM36283_PS_MIN_POLL_DELAY) ||
+ (interval_ms > CM36283_PS_MAX_POLL_DELAY))
+ return -EINVAL;
+
+ atomic_set(&lpi->ps_poll_delay, (unsigned int) interval_ms);
+ return count;
+}
+
+static DEVICE_ATTR(ps_poll_delay, 0664, ps_poll_delay_show,
+ ps_poll_delay_store);
+
static ssize_t ls_fLevel_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1103,6 +1296,7 @@
static int lightsensor_setup(struct cm36283_info *lpi)
{
int ret;
+ int range;
lpi->ls_input_dev = input_allocate_device();
if (!lpi->ls_input_dev) {
@@ -1113,7 +1307,9 @@
}
lpi->ls_input_dev->name = "cm36283-ls";
set_bit(EV_ABS, lpi->ls_input_dev->evbit);
- input_set_abs_params(lpi->ls_input_dev, ABS_MISC, 0, 9, 0, 0);
+
+ range = get_als_range();
+ input_set_abs_params(lpi->ls_input_dev, ABS_MISC, 0, range, 0, 0);
ret = input_register_device(lpi->ls_input_dev);
if (ret < 0) {
@@ -1188,13 +1384,8 @@
D("[PS][CM36283] %s, INTERRUPT GPIO val = %d\n", __func__, val);
ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ID_REG, &idReg);
- if ((ret < 0) || (idReg != 0xC082)) {
- if (record_init_fail == 0)
- record_init_fail = 1;
- return -ENOMEM;/*If devices without cm36283 chip and did not probe driver*/
- }
-
- return 0;
+
+ return ret;
}
static int cm36283_setup(struct cm36283_info *lpi)
@@ -1228,14 +1419,15 @@
}
/*Default disable P sensor and L sensor*/
- ls_initial_cmd(lpi);
+ ls_initial_cmd(lpi);
psensor_initial_cmd(lpi);
- ret = request_any_context_irq(lpi->irq,
- cm36283_irq_handler,
- IRQF_TRIGGER_LOW,
- "cm36283",
- lpi);
+ if (!lpi->polling)
+ ret = request_any_context_irq(lpi->irq,
+ cm36283_irq_handler,
+ IRQF_TRIGGER_LOW,
+ "cm36283",
+ lpi);
if (ret < 0) {
pr_err(
"[PS][CM36283 error]%s: req_irq(%d) fail for gpio %d (%d)\n",
@@ -1274,6 +1466,78 @@
}
#endif
+static int cm36283_parse_dt(struct device *dev,
+ struct cm36283_platform_data *pdata)
+{
+ struct device_node *np = dev->of_node;
+ u32 levels[CM36283_LEVELS_SIZE], i;
+ u32 temp_val;
+ int rc;
+
+ rc = of_get_named_gpio_flags(np, "capella,interrupt-gpio",
+ 0, NULL);
+ if (rc < 0) {
+ dev_err(dev, "Unable to read interrupt pin number\n");
+ return rc;
+ } else {
+ pdata->intr = rc;
+ }
+
+ rc = of_property_read_u32_array(np, "capella,levels", levels,
+ CM36283_LEVELS_SIZE);
+ if (rc) {
+ dev_err(dev, "Unable to read levels data\n");
+ return rc;
+ } else {
+ for (i = 0; i < CM36283_LEVELS_SIZE; i++)
+ pdata->levels[i] = levels[i];
+ }
+
+ rc = of_property_read_u32(np, "capella,ps_close_thd_set", &temp_val);
+ if (rc) {
+ dev_err(dev, "Unable to read ps_close_thd_set\n");
+ return rc;
+ } else {
+ pdata->ps_close_thd_set = (u8)temp_val;
+ }
+
+ rc = of_property_read_u32(np, "capella,ps_away_thd_set", &temp_val);
+ if (rc) {
+ dev_err(dev, "Unable to read ps_away_thd_set\n");
+ return rc;
+ } else {
+ pdata->ps_away_thd_set = (u8)temp_val;
+ }
+
+ rc = of_property_read_u32(np, "capella,ls_cmd", &temp_val);
+ if (rc) {
+ dev_err(dev, "Unable to read ls_cmd\n");
+ return rc;
+ } else {
+ pdata->ls_cmd = (u16)temp_val;
+ }
+
+ rc = of_property_read_u32(np, "capella,ps_conf1_val", &temp_val);
+ if (rc) {
+ dev_err(dev, "Unable to read ps_conf1_val\n");
+ return rc;
+ } else {
+ pdata->ps_conf1_val = (u16)temp_val;
+ }
+
+ rc = of_property_read_u32(np, "capella,ps_conf3_val", &temp_val);
+ if (rc) {
+ dev_err(dev, "Unable to read ps_conf3_val\n");
+ return rc;
+ } else {
+ pdata->ps_conf3_val = (u16)temp_val;
+ }
+
+ pdata->polling = of_property_read_bool(np, "capella,use-polling");
+
+ return 0;
+}
+
static int cm36283_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -1291,12 +1555,29 @@
/*D("[CM36283] %s: client->irq = %d\n", __func__, client->irq);*/
lpi->i2c_client = client;
- pdata = client->dev.platform_data;
- if (!pdata) {
- pr_err("[PS][CM36283 error]%s: Assign platform_data error!!\n",
- __func__);
- ret = -EBUSY;
- goto err_platform_data_null;
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&client->dev, "Failed to allocate memory for pdata\n");
+ ret = -ENOMEM;
+ goto err_platform_data_null;
+ }
+
+ ret = cm36283_parse_dt(&client->dev, pdata);
+ pdata->slave_addr = client->addr;
+ if (ret) {
+ dev_err(&client->dev, "Failed to get pdata from device tree\n");
+ goto err_parse_dt;
+ }
+ } else {
+ pdata = client->dev.platform_data;
+ if (!pdata) {
+ dev_err(&client->dev, "%s: Assign platform_data error!!\n",
+ __func__);
+ ret = -EBUSY;
+ goto err_platform_data_null;
+ }
}
lpi->irq = client->irq;
@@ -1313,6 +1594,12 @@
lpi->ps_close_thd_set = pdata->ps_close_thd_set;
lpi->ps_conf1_val = pdata->ps_conf1_val;
lpi->ps_conf3_val = pdata->ps_conf3_val;
+ lpi->polling = pdata->polling;
+ atomic_set(&lpi->ls_poll_delay,
+ (unsigned int) CM36283_LS_DEFAULT_POLL_DELAY);
+ atomic_set(&lpi->ps_poll_delay,
+ (unsigned int) CM36283_PS_DEFAULT_POLL_DELAY);
+
lpi->ls_cmd = pdata->ls_cmd;
@@ -1333,23 +1620,11 @@
mutex_init(&als_disable_mutex);
mutex_init(&als_get_adc_mutex);
- ret = lightsensor_setup(lpi);
- if (ret < 0) {
- pr_err("[LS][CM36283 error]%s: lightsensor_setup error!!\n",
- __func__);
- goto err_lightsensor_setup;
- }
mutex_init(&ps_enable_mutex);
mutex_init(&ps_disable_mutex);
mutex_init(&ps_get_adc_mutex);
- ret = psensor_setup(lpi);
- if (ret < 0) {
- pr_err("[PS][CM36283 error]%s: psensor_setup error!!\n",
- __func__);
- goto err_psensor_setup;
- }
//SET LUX STEP FACTOR HERE
// if adc raw value one step = 5/100 = 1/20 = 0.05 lux
@@ -1379,11 +1654,32 @@
}
wake_lock_init(&(lpi->ps_wake_lock), WAKE_LOCK_SUSPEND, "proximity");
+ ret = cm36283_power_set(lpi, true);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s:cm36283 power on error!\n", __func__);
+ goto err_cm36283_power_on;
+ }
+
ret = cm36283_setup(lpi);
if (ret < 0) {
pr_err("[PS_ERR][CM36283 error]%s: cm36283_setup error!\n", __func__);
goto err_cm36283_setup;
}
+
+ ret = lightsensor_setup(lpi);
+ if (ret < 0) {
+ pr_err("[LS][CM36283 error]%s: lightsensor_setup error!!\n",
+ __func__);
+ goto err_lightsensor_setup;
+ }
+
+ ret = psensor_setup(lpi);
+ if (ret < 0) {
+ pr_err("[PS][CM36283 error]%s: psensor_setup error!!\n",
+ __func__);
+ goto err_psensor_setup;
+ }
+
lpi->cm36283_class = class_create(THIS_MODULE, "optical_sensors");
if (IS_ERR(lpi->cm36283_class)) {
ret = PTR_ERR(lpi->cm36283_class);
@@ -1430,37 +1726,45 @@
if (ret)
goto err_create_ls_device_file;
+ ret = device_create_file(lpi->ls_dev, &dev_attr_ls_poll_delay);
+ if (ret)
+ goto err_create_ls_device_file;
+
lpi->ps_dev = device_create(lpi->cm36283_class,
NULL, 0, "%s", "proximity");
if (unlikely(IS_ERR(lpi->ps_dev))) {
ret = PTR_ERR(lpi->ps_dev);
lpi->ps_dev = NULL;
- goto err_create_ls_device_file;
+ goto err_create_ps_device;
}
/* register the attributes */
ret = device_create_file(lpi->ps_dev, &dev_attr_ps_adc);
if (ret)
- goto err_create_ps_device;
+ goto err_create_ps_device_file;
ret = device_create_file(lpi->ps_dev,
&dev_attr_ps_parameters);
if (ret)
- goto err_create_ps_device;
+ goto err_create_ps_device_file;
/* register the attributes */
ret = device_create_file(lpi->ps_dev, &dev_attr_ps_conf);
if (ret)
- goto err_create_ps_device;
+ goto err_create_ps_device_file;
/* register the attributes */
ret = device_create_file(lpi->ps_dev, &dev_attr_ps_thd);
if (ret)
- goto err_create_ps_device;
+ goto err_create_ps_device_file;
ret = device_create_file(lpi->ps_dev, &dev_attr_ps_hw);
if (ret)
- goto err_create_ps_device;
+ goto err_create_ps_device_file;
+
+ ret = device_create_file(lpi->ps_dev, &dev_attr_ps_poll_delay);
+ if (ret)
+ goto err_create_ps_device_file;
#ifdef CONFIG_HAS_EARLYSUSPEND
lpi->early_suspend.level =
@@ -1470,47 +1774,59 @@
register_early_suspend(&lpi->early_suspend);
#endif
+ mutex_init(&wq_lock);
+ INIT_DELAYED_WORK(&lpi->ldwork, lsensor_delay_work_handler);
+ INIT_DELAYED_WORK(&lpi->pdwork, psensor_delay_work_handler);
D("[PS][CM36283] %s: Probe success!\n", __func__);
return ret;
-err_create_ps_device:
+err_create_ps_device_file:
device_unregister(lpi->ps_dev);
+err_create_ps_device:
err_create_ls_device_file:
device_unregister(lpi->ls_dev);
err_create_ls_device:
class_destroy(lpi->cm36283_class);
err_create_class:
-err_cm36283_setup:
- destroy_workqueue(lpi->lp_wq);
- wake_lock_destroy(&(lpi->ps_wake_lock));
-
- input_unregister_device(lpi->ls_input_dev);
- input_free_device(lpi->ls_input_dev);
+ misc_deregister(&psensor_misc);
input_unregister_device(lpi->ps_input_dev);
input_free_device(lpi->ps_input_dev);
+err_psensor_setup:
+ misc_deregister(&lightsensor_misc);
+ input_unregister_device(lpi->ls_input_dev);
+ input_free_device(lpi->ls_input_dev);
+err_lightsensor_setup:
+err_cm36283_setup:
+ cm36283_power_set(lpi, false);
+err_cm36283_power_on:
+ wake_lock_destroy(&(lpi->ps_wake_lock));
+ destroy_workqueue(lpi->lp_wq);
err_create_singlethread_workqueue:
err_lightsensor_update_table:
- misc_deregister(&psensor_misc);
-err_psensor_setup:
mutex_destroy(&CM36283_control_mutex);
- mutex_destroy(&ps_enable_mutex);
- mutex_destroy(&ps_disable_mutex);
- mutex_destroy(&ps_get_adc_mutex);
- misc_deregister(&lightsensor_misc);
-err_lightsensor_setup:
mutex_destroy(&als_enable_mutex);
mutex_destroy(&als_disable_mutex);
mutex_destroy(&als_get_adc_mutex);
+ mutex_destroy(&ps_enable_mutex);
+ mutex_destroy(&ps_disable_mutex);
+ mutex_destroy(&ps_get_adc_mutex);
+err_parse_dt:
+ if (client->dev.of_node && (pdata != NULL))
+ devm_kfree(&client->dev, pdata);
err_platform_data_null:
kfree(lpi);
+ dev_err(&client->dev, "%s:error exit! ret = %d\n", __func__, ret);
+
return ret;
}
-
-static int control_and_report( struct cm36283_info *lpi, uint8_t mode, uint16_t param ) {
- int ret=0;
+
+static int control_and_report(struct cm36283_info *lpi, uint8_t mode,
+ uint16_t param, int report)
+{
+ int ret = 0;
uint16_t adc_value = 0;
- uint16_t ps_data = 0;
+ uint16_t ps_data = 0;
int level = 0, i, val;
mutex_lock(&CM36283_control_mutex);
@@ -1575,63 +1891,62 @@
}
}
}
-
- ret = set_lsensor_range(((i == 0) || (adc_value == 0)) ? 0 :
- *(lpi->cali_table + (i - 1)) + 1,
- *(lpi->cali_table + i));
-
- lpi->ls_cmd |= CM36283_ALS_INT_EN;
-
- ret = _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
-
- if ((i == 0) || (adc_value == 0))
- D("[LS][CM3628] %s: ADC=0x%03X, Level=%d, l_thd equal 0, h_thd = 0x%x \n",
- __func__, adc_value, level, *(lpi->cali_table + i));
- else
- D("[LS][CM3628] %s: ADC=0x%03X, Level=%d, l_thd = 0x%x, h_thd = 0x%x \n",
- __func__, adc_value, level, *(lpi->cali_table + (i - 1)) + 1, *(lpi->cali_table + i));
- lpi->current_level = level;
- lpi->current_adc = adc_value;
- input_report_abs(lpi->ls_input_dev, ABS_MISC, level);
- input_sync(lpi->ls_input_dev);
+ if (!lpi->polling) {
+ ret = set_lsensor_range(((i == 0) ||
+ (adc_value == 0)) ? 0 :
+ *(lpi->cali_table + (i - 1)) + 1,
+ *(lpi->cali_table + i));
+
+ lpi->ls_cmd |= CM36283_ALS_INT_EN;
+ }
+
+ ret = _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF,
+ lpi->ls_cmd);
+
+ if (report) {
+ lpi->current_level = level;
+ lpi->current_adc = adc_value;
+ input_report_abs(lpi->ls_input_dev, ABS_MISC, level);
+ input_sync(lpi->ls_input_dev);
+ }
}
}
#define PS_CLOSE 1
#define PS_AWAY (1<<1)
#define PS_CLOSE_AND_AWAY PS_CLOSE+PS_AWAY
+ if (report && (lpi->ps_enable)) {
+ int ps_status = 0;
+ if (mode == CONTROL_PS)
+ ps_status = PS_CLOSE_AND_AWAY;
+ else if (mode == CONTROL_INT_ISR_REPORT) {
+ if (param & INT_FLAG_PS_IF_CLOSE)
+ ps_status |= PS_CLOSE;
+ if (param & INT_FLAG_PS_IF_AWAY)
+ ps_status |= PS_AWAY;
+ }
- if(lpi->ps_enable){
- int ps_status = 0;
- if( mode == CONTROL_PS )
- ps_status = PS_CLOSE_AND_AWAY;
- else if(mode == CONTROL_INT_ISR_REPORT ){
- if ( param & INT_FLAG_PS_IF_CLOSE )
- ps_status |= PS_CLOSE;
- if ( param & INT_FLAG_PS_IF_AWAY )
- ps_status |= PS_AWAY;
- }
-
- if (ps_status!=0){
- switch(ps_status){
- case PS_CLOSE_AND_AWAY:
- get_stable_ps_adc_value(&ps_data);
- val = (ps_data >= lpi->ps_close_thd_set) ? 0 : 1;
- break;
- case PS_AWAY:
- val = 1;
- break;
- case PS_CLOSE:
- val = 0;
- break;
- };
- input_report_abs(lpi->ps_input_dev, ABS_DISTANCE, val);
- input_sync(lpi->ps_input_dev);
- }
- }
+ if (ps_status != 0) {
+ switch (ps_status) {
+ case PS_CLOSE_AND_AWAY:
+ get_stable_ps_adc_value(&ps_data);
+ val = (ps_data >= lpi->ps_close_thd_set)
+ ? 0 : 1;
+ break;
+ case PS_AWAY:
+ val = 1;
+ break;
+ case PS_CLOSE:
+ val = 0;
+ break;
+ };
+ input_report_abs(lpi->ps_input_dev, ABS_DISTANCE, val);
+ input_sync(lpi->ps_input_dev);
+ }
+ }
- mutex_unlock(&CM36283_control_mutex);
- return ret;
+ mutex_unlock(&CM36283_control_mutex);
+ return ret;
}
static int cm36283_power_set(struct cm36283_info *info, bool on)
@@ -1769,6 +2084,11 @@
{}
};
+static struct of_device_id cm36283_match_table[] = {
+ { .compatible = "capella,cm36283",},
+ { },
+};
+
static struct i2c_driver cm36283_driver = {
.id_table = cm36283_i2c_id,
.probe = cm36283_probe,
@@ -1776,6 +2096,7 @@
.name = CM36283_I2C_NAME,
.owner = THIS_MODULE,
.pm = &cm36283_pm,
+ .of_match_table = cm36283_match_table,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index 32cf0d3..9384a5b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -124,7 +124,6 @@
j++;
lane_mask >>= 1;
}
- msleep(20);
return rc;
}
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index 03e9021..3e14333 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -591,8 +591,9 @@
}
EXPORT_SYMBOL(qpnpint_unregister_controller);
-int qpnpint_handle_irq(struct spmi_controller *spmi_ctrl,
- struct qpnp_irq_spec *spec)
+static int __qpnpint_handle_irq(struct spmi_controller *spmi_ctrl,
+ struct qpnp_irq_spec *spec,
+ bool show)
{
struct irq_domain *domain;
unsigned long hwirq, busno;
@@ -617,12 +618,40 @@
domain = chip_lookup[busno]->domain;
irq = irq_radix_revmap_lookup(domain, hwirq);
- generic_handle_irq(irq);
+ if (show) {
+ struct irq_desc *desc;
+ const char *name = "null";
+
+ desc = irq_to_desc(irq);
+ if (desc == NULL)
+ name = "stray irq";
+ else if (desc->action && desc->action->name)
+ name = desc->action->name;
+
+ pr_warn("%d triggered [0x%01x, 0x%02x,0x%01x] %s\n",
+ irq, spec->slave, spec->per, spec->irq, name);
+ } else {
+ generic_handle_irq(irq);
+ }
return 0;
}
+
+int qpnpint_handle_irq(struct spmi_controller *spmi_ctrl,
+ struct qpnp_irq_spec *spec)
+{
+ return __qpnpint_handle_irq(spmi_ctrl, spec, false);
+}
+
EXPORT_SYMBOL(qpnpint_handle_irq);
+int qpnpint_show_irq(struct spmi_controller *spmi_ctrl,
+ struct qpnp_irq_spec *spec)
+{
+ return __qpnpint_handle_irq(spmi_ctrl, spec, true);
+}
+EXPORT_SYMBOL(qpnpint_show_irq);
+
int __init qpnpint_of_init(struct device_node *node, struct device_node *parent)
{
struct q_chip_data *chip_d;
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index f85a576..bc328e0 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -24,6 +24,7 @@
#include <linux/of_spmi.h>
#include <linux/module.h>
#include <linux/seq_file.h>
+#include <linux/syscore_ops.h>
#include <mach/qpnp-int.h>
#include "spmi-dbgfs.h"
@@ -126,9 +127,12 @@
u32 mapping_table[SPMI_MAPPING_TABLE_LEN];
};
+static struct spmi_pmic_arb_dev *the_pmic_arb;
+
static u32 pmic_arb_read(struct spmi_pmic_arb_dev *dev, u32 offset)
{
u32 val = readl_relaxed(dev->base + offset);
+
pr_debug("address 0x%p, val 0x%x\n", dev->base + offset, val);
return val;
}
@@ -485,7 +489,7 @@
}
static irqreturn_t
-periph_interrupt(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+periph_interrupt(struct spmi_pmic_arb_dev *pmic_arb, u8 apid, bool show)
{
u16 ppid = get_peripheral_id(pmic_arb, apid);
void __iomem *intr = pmic_arb->intr;
@@ -511,10 +515,12 @@
/* Read the peripheral specific interrupt bits */
status = readl_relaxed(intr + SPMI_PIC_IRQ_STATUS(apid));
- /* Clear the peripheral interrupts */
- writel_relaxed(status, intr + SPMI_PIC_IRQ_CLEAR(apid));
- /* Interrupt needs to be cleared/acknowledged before exiting ISR */
- mb();
+ if (!show) {
+ /* Clear the peripheral interrupts */
+ writel_relaxed(status, intr + SPMI_PIC_IRQ_CLEAR(apid));
+ /* Irq needs to be cleared/acknowledged before exiting ISR */
+ mb();
+ }
dev_dbg(pmic_arb->dev,
"interrupt, apid:0x%x, sid:0x%x, pid:0x%x, intr:0x%x\n",
@@ -528,14 +534,20 @@
.per = pid,
.irq = i,
};
- qpnpint_handle_irq(&pmic_arb->controller, &irq_spec);
+ if (show)
+ qpnpint_show_irq(&pmic_arb->controller,
+ &irq_spec);
+ else
+ qpnpint_handle_irq(&pmic_arb->controller,
+ &irq_spec);
}
}
return IRQ_HANDLED;
}
/* Peripheral interrupt handler */
-static irqreturn_t pmic_arb_periph_irq(int irq, void *dev_id)
+static irqreturn_t
+__pmic_arb_periph_irq(int irq, void *dev_id, bool show)
{
struct spmi_pmic_arb_dev *pmic_arb = dev_id;
void __iomem *intr = pmic_arb->intr;
@@ -556,7 +568,8 @@
for (j = 0; status && j < 32; ++j, status >>= 1) {
if (status & 0x1) {
u8 id = (i * 32) + j;
- ret |= periph_interrupt(pmic_arb, id);
+
+ ret |= periph_interrupt(pmic_arb, id, show);
}
}
}
@@ -564,6 +577,22 @@
return ret;
}
+static irqreturn_t pmic_arb_periph_irq(int irq, void *dev_id)
+{
+ return __pmic_arb_periph_irq(irq, dev_id, false);
+}
+
+static void spmi_pmic_arb_resume(void)
+{
+ if (qpnpint_show_resume_irq())
+ __pmic_arb_periph_irq(the_pmic_arb->pic_irq,
+ the_pmic_arb, true);
+}
+
+static struct syscore_ops spmi_pmic_arb_syscore_ops = {
+ .resume = spmi_pmic_arb_resume,
+};
+
/* Callback to register an APID for specific slave/peripheral */
static int pmic_arb_intr_priv_data(struct spmi_controller *ctrl,
struct qpnp_irq_spec *spec, uint32_t *data)
@@ -766,6 +795,9 @@
pr_debug("PMIC Arb Version 0x%x\n",
pmic_arb_read(pmic_arb, PMIC_ARB_VERSION));
+ the_pmic_arb = pmic_arb;
+ register_syscore_ops(&spmi_pmic_arb_syscore_ops);
+
return 0;
err_reg_controller:
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index fcc5a8d..613af4e 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -164,7 +164,7 @@
#define TSENS10_POINT2_BACKUP_MASK 0x3f000000
#define TSENS_8X26_BASE0_MASK 0x1fe000
-#define TSENS0_8X26_POINT1_MASK 0x7f00000
+#define TSENS0_8X26_POINT1_MASK 0x7e00000
#define TSENS1_8X26_POINT1_MASK 0x3f
#define TSENS2_8X26_POINT1_MASK 0xfc0
#define TSENS3_8X26_POINT1_MASK 0x3f000
@@ -174,11 +174,11 @@
#define TSENS_8X26_TSENS_CAL_SEL 0xe0000000
#define TSENS_8X26_BASE1_MASK 0xff
#define TSENS0_8X26_POINT2_MASK 0x3f00
-#define TSENS1_8X26_POINT2_MASK 0xfc00
+#define TSENS1_8X26_POINT2_MASK 0xfc000
#define TSENS2_8X26_POINT2_MASK 0x3f00000
#define TSENS3_8X26_POINT2_MASK 0xfc000000
-#define TSENS4_8X26_POINT2_MASK 0xfc000000
-#define TSENS5_8X26_POINT2_MASK 0x3f00000
+#define TSENS4_8X26_POINT2_MASK 0x3f00000
+#define TSENS5_8X26_POINT2_MASK 0xfc000000
#define TSENS6_8X26_POINT2_MASK 0x7e0000
#define TSENS_8X26_CAL_SEL_SHIFT 29
diff --git a/include/linux/cm36283.h b/include/linux/cm36283.h
index 362b709..2872d04 100644
--- a/include/linux/cm36283.h
+++ b/include/linux/cm36283.h
@@ -120,6 +120,15 @@
extern unsigned int ps_kparam1;
extern unsigned int ps_kparam2;
+#define CM36283_LEVELS_SIZE 10
+
+enum {
+ CM36283_ALS_IT0 = 0,
+ CM36283_ALS_IT1,
+ CM36283_ALS_IT2,
+ CM36283_ALS_IT3,
+};
+
struct cm36283_platform_data {
int intr;
uint16_t levels[10];
@@ -131,6 +140,7 @@
uint16_t ls_cmd;
uint16_t ps_conf1_val;
uint16_t ps_conf3_val;
+ bool polling;
};
#endif
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 88fcf61..fb58d12 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -82,14 +82,15 @@
*/
#define ADM_CMD_DEVICE_OPEN_V5 0x00010326
-#define ADM_BIT_SHIFT_DEVICE_PERF_MODE_FLAG 13
+/* Definition for a low latency stream session. */
+#define ADM_LOW_LATENCY_DEVICE_SESSION 0x2000
+
+/* Definition for a ultra low latency stream session. */
+#define ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION 0x4000
/* Definition for a legacy device session. */
#define ADM_LEGACY_DEVICE_SESSION 0
-/* Definition for a low latency stream session. */
-#define ADM_LOW_LATENCY_DEVICE_SESSION 1
-
/* Indicates that endpoint_id_2 is to be ignored.*/
#define ADM_CMD_COPP_OPEN_END_POINT_ID_2_IGNORE 0xFFFF
@@ -3816,11 +3817,12 @@
#define ASM_STREAM_CMD_OPEN_WRITE_V2 0x00010D8F
#define ASM_STREAM_CMD_OPEN_WRITE_V3 0x00010DB3
-#define ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_WRITE 28
+#define ASM_LOW_LATENCY_STREAM_SESSION 0x10000000
+
+#define ASM_ULTRA_LOW_LATENCY_STREAM_SESSION 0x20000000
#define ASM_LEGACY_STREAM_SESSION 0
-#define ASM_LOW_LATENCY_STREAM_SESSION 1
struct asm_stream_cmd_open_write_v3 {
struct apr_hdr hdr;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index de60430..62fe6d2 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -371,8 +371,12 @@
msm_send_eq_values(fedai_id);
topology = get_topology(path_type);
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
- if (test_bit(fedai_id, &msm_bedais[i].fe_sessions) && perf_mode)
- set_bit(fedai_id, &msm_bedais[i].perf_mode);
+ if (test_bit(fedai_id, &msm_bedais[i].fe_sessions)) {
+ if (perf_mode)
+ set_bit(fedai_id, &msm_bedais[i].perf_mode);
+ else
+ clear_bit(fedai_id, &msm_bedais[i].perf_mode);
+ }
if (!is_be_dai_extproc(i) &&
(afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
(msm_bedais[i].active) &&
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index b1f968d..d99812f 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -522,7 +522,6 @@
/* Should only come here if there is an APR */
/* error or malformed APR packet. Otherwise */
/* response will be returned as */
- /* ADM_CMDRSP_SHARED_MEM_MAP_REGIONS */
if (payload[1] != 0) {
pr_err("%s: ADM map error, resuming\n",
__func__);
@@ -967,11 +966,9 @@
open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
open.flags = 0x00;
if (perf_mode) {
- open.flags |= ADM_LOW_LATENCY_DEVICE_SESSION <<
- ADM_BIT_SHIFT_DEVICE_PERF_MODE_FLAG;
+ open.flags |= ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
} else {
- open.flags |= ADM_LEGACY_DEVICE_SESSION <<
- ADM_BIT_SHIFT_DEVICE_PERF_MODE_FLAG;
+ open.flags |= ADM_LEGACY_DEVICE_SESSION;
}
open.mode_of_operation = path;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 6a34470..1abc47d 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1504,11 +1504,9 @@
open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;
open.mode_flags = 0x00;
if (ac->perf_mode)
- open.mode_flags |= (ASM_LOW_LATENCY_STREAM_SESSION <<
- ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_WRITE);
+ open.mode_flags |= ASM_ULTRA_LOW_LATENCY_STREAM_SESSION;
else
- open.mode_flags |= (ASM_LEGACY_STREAM_SESSION <<
- ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_WRITE);
+ open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
/* source endpoint : matrix */
open.sink_endpointype = ASM_END_POINT_DEVICE_MATRIX;