Merge "msm: vidc: Amend Q6 HFI session id entry to session list"
diff --git a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
index fdba7c2..f2ca95b 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
@@ -30,6 +30,7 @@
min y, max x and max y values.
- goodix,i2c-pull-up : To specify pull up is required.
- goodix,no-force-update : To specify force update is allowed.
+ - goodix,enable-power-off : Power off touchscreen during suspend.
- goodix,button-map : Button map of key codes. The number of key codes
depend on panel.
- goodix,cfg-data0 : Touch screen controller config data group 0. Ask vendor
@@ -50,6 +51,7 @@
to provide that.
- goodix,cfg-data5 : Touch screen controller config data group 5. Ask vendor
to provide that.
+ - goodix,fw-name : Touch screen controller firmware file name.
Example:
i2c@f9927000 {
goodix@5d {
@@ -84,5 +86,6 @@
20 21 22 24 26 28 29 2A FF FF
FF FF FF FF FF FF FF 22 22 22
22 22 22 FF 07 01];
+ goodix,fw_name = "gtp_fw.bin";
};
};
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index af6a0b5..749c594 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -10,13 +10,13 @@
node will further contain the type of LED supported and its
properties. At least one child node is required for each LED
module. Each must have the required properties below, in addition
-to the properties for the LED type, WLED, Flash or RGB.
+to the properties for the LED type, WLED, Flash, RGB and MPP.
Required properties for each child node, WLED, Flash and RGB:
- compatible : should be "qcom,leds-qpnp"
- qcom,id : must be one of values supported in enum qpnp_led
- label : type of led that will be used, ie "wled"
-- qcom,max-current : maximum current that the LED can sustain
+- qcom,max-current : maximum current that the LED can sustain in mA
- linux,name : name of the led that is used in led framework
WLED is primarily used as display backlight. Display subsystem uses
@@ -85,6 +85,7 @@
- qcom,vin-ctrl: select input source, supported values are 0 to 3
- qcom,use-blink: Use blink sysfs entry for switching into lpg mode. For optimal use, set default mode to pwm. All required lpg parameters must be supplied.
- qcom,min-brightness - Lowest possible brightness supported on this LED other than 0.
+- qcom,current-setting: default current value for wled used as button backlight in mA
Required properties for PWM mode only:
- qcom,pwm-channel: pwm channel the led will operate on
@@ -131,6 +132,22 @@
Example:
+ qcom,leds@a100 {
+ status = "okay";
+ qcom,led_mpp_2 {
+ label = "mpp";
+ linux,name = "button-backlight";
+ linux,default-trigger = "hr-trigger";
+ qcom,default-state = "off";
+ qcom,current-setting = <20>;
+ qcom,max-current = <40>;
+ qcom,id = <6>;
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x61>;
+ qcom,mode = "manual";
+ };
+ };
+
qcom,leds@a200 {
status = "okay";
qcom,led_mpp_3 {
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 5e686a4f..56bdc59 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -407,6 +407,17 @@
Required properties:
- compatible : "qcom,msm8974-audio-taiko"
- qcom,model : The user-visible name of this sound card.
+- reg : Offset and length of the register region(s) for MI2S/PCM MUX
+- reg-names : Register region name(s) referenced in reg above
+ Required register resource entries are:
+ "lpaif_pri_mode_muxsel": Physical address of MUX to select between
+ Primary PCM and Primary MI2S
+ "lpaif_sec_mode_muxsel": Physical address of MUX to select between
+ Secondary PCM and Secondary MI2S
+ "lpaif_tert_mode_muxsel": Physical address of MUX to select between
+ Primary PCM and Tertiary MI2S
+ "lpaif_quat_mode_muxsel": Physical address of MUX to select between
+ Secondary PCM and Quarternary MI2S
- qcom,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source.
diff --git a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
index bb8389f..b510e6b 100644
--- a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
@@ -30,9 +30,9 @@
qcom,mdss-dsi-h-back-porch = <24>;
qcom,mdss-dsi-h-pulse-width = <14>;
qcom,mdss-dsi-h-sync-skew = <0>;
- qcom,mdss-dsi-v-back-porch = <15>;
- qcom,mdss-dsi-v-front-porch = <12>;
- qcom,mdss-dsi-v-pulse-width = <10>;
+ qcom,mdss-dsi-v-back-porch = <14>;
+ qcom,mdss-dsi-v-front-porch = <11>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
qcom,mdss-dsi-h-left-border = <0>;
qcom,mdss-dsi-h-right-border = <0>;
qcom,mdss-dsi-v-top-border = <0>;
diff --git a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
index 66f5095..76bd262 100755
--- a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
@@ -124,6 +124,7 @@
20 21 22 24 26 28 29 2A FF FF
FF FF FF FF FF FF FF FF FF FF
FF FF FF FF 3E 01];
+ goodix,fw_name = "gtp_fw.bin";
};
};
};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 023371b..71748ea 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -210,8 +210,9 @@
status = "okay";
qcom,led_mpp_2 {
label = "mpp";
- linux,name = "wled-homerow";
- linux-default-trigger = "hr-trigger";
+ linux,name = "button-backlight";
+ linux,default-trigger = "hr-trigger";
+ qcom,current-setting = <20>;
qcom,default-state = "off";
qcom,max-current = <40>;
qcom,id = <6>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 311944c..e612df7 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -741,6 +741,14 @@
sound {
compatible = "qcom,msm8974-audio-taiko";
qcom,model = "msm8974-taiko-snd-card";
+ reg = <0xfe02b000 0x4>,
+ <0xfe02c000 0x4>,
+ <0xfe02d000 0x4>,
+ <0xfe02e000 0x4>;
+ reg-names = "lpaif_pri_mode_muxsel",
+ "lpaif_sec_mode_muxsel",
+ "lpaif_tert_mode_muxsel",
+ "lpaif_quat_mode_muxsel";
qcom,audio-routing =
"RX_BIAS", "MCLK",
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 6d5c862..174cee6 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -39,6 +39,17 @@
/delete-property/ qcom,pmic-sw-mode-temp-hysteresis;
/delete-property/ qcom,pmic-sw-mode-regs;
};
+
+ sound {
+ reg = <0xfe02c000 0x4>,
+ <0xfe02d000 0x4>,
+ <0xfe02e000 0x4>,
+ <0xfe02f000 0x4>;
+ reg-names = "lpaif_pri_mode_muxsel",
+ "lpaif_sec_mode_muxsel",
+ "lpaif_tert_mode_muxsel",
+ "lpaif_quat_mode_muxsel";
+ };
};
/* GPU overrides */
@@ -48,20 +59,29 @@
qcom,initial-pwrlevel = <6>;
+ qcom,msm-bus,num-cases = <10>;
/* Updated bus bandwidth requirements */
qcom,msm-bus,vectors-KBps =
/* Off */
<26 512 0 0>, <89 604 0 0>,
/* SVS */
- <26 512 0 2400000>, <89 604 0 3000000>,
+ <26 512 0 2400000>, <89 604 0 3200000>,
/* Nominal / SVS */
- <26 512 0 4656000>, <89 604 0 3000000>,
- /* Nominal */
- <26 512 0 4656000>, <89 604 0 5120000>,
- /* Turbo / Nominal */
- <26 512 0 7464000>, <89 604 0 5120000>,
+ <26 512 0 3680000>, <89 604 0 3200000>,
+ /* Nominal / Nominal */
+ <26 512 0 3680000>, <89 604 0 5280000>,
+ /* Nominal / Nominal */
+ <26 512 0 4912000>, <89 604 0 5280000>,
+ /* Nominal / Turbo */
+ <26 512 0 4912000>, <89 604 0 6224000>,
+ /* Turbo / Turbo */
+ <26 512 0 7464000>, <89 604 0 6224000>,
+ /* Nominal / Turbo */
+ <26 512 0 4912000>, <89 604 0 7400000>,
/* Turbo */
- <26 512 0 7464000>, <89 604 0 6400000>;
+ <26 512 0 7464000>, <89 604 0 7400000>,
+ /* Turbo */
+ <26 512 0 7464000>, <89 604 0 9248000>;
qcom,gpu-pwrlevels {
#address-cells = <1>;
@@ -72,35 +92,35 @@
qcom,gpu-pwrlevel@0 {
reg = <0>;
qcom,gpu-freq = <578000000>;
- qcom,bus-freq = <5>;
+ qcom,bus-freq = <9>;
qcom,io-fraction = <33>;
};
qcom,gpu-pwrlevel@1 {
reg = <1>;
qcom,gpu-freq = <462400000>;
- qcom,bus-freq = <4>;
+ qcom,bus-freq = <8>;
qcom,io-fraction = <33>;
};
qcom,gpu-pwrlevel@2 {
reg = <2>;
qcom,gpu-freq = <462400000>;
- qcom,bus-freq = <3>;
+ qcom,bus-freq = <7>;
qcom,io-fraction = <66>;
};
qcom,gpu-pwrlevel@3 {
reg = <3>;
qcom,gpu-freq = <389000000>;
- qcom,bus-freq = <4>;
+ qcom,bus-freq = <6>;
qcom,io-fraction = <66>;
};
qcom,gpu-pwrlevel@4 {
reg = <4>;
qcom,gpu-freq = <389000000>;
- qcom,bus-freq = <3>;
+ qcom,bus-freq = <5>;
qcom,io-fraction = <66>;
};
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 7c1af1a..cda1e59 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -90,6 +90,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_ENABLE_VMALLOC_SAVING=y
CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 265234b..7d7bf46 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -81,6 +81,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_ENABLE_VMALLOC_SAVING=y
CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 55627a3..c1f2ca2 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -82,6 +82,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_ENABLE_VMALLOC_SAVING=y
CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 2160c79..efdd8de 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -82,6 +82,7 @@
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
CONFIG_CC_STACKPROTECTOR=y
+CONFIG_ENABLE_VMALLOC_SAVING=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 8e6f5f9..c140a46 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -83,6 +83,7 @@
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
CONFIG_CC_STACKPROTECTOR=y
+CONFIG_ENABLE_VMALLOC_SAVING=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 87c2f8c..a341c23 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -280,11 +280,11 @@
select MEMORY_HOLE_CARVEOUT
select MSM_RPM_STATS_LOG
select QMI_ENCDEC
- select DONT_MAP_HOLE_AFTER_MEMBANK0
select MSM_ULTRASOUND_B
select MSM_RPM_LOG
select ARCH_WANT_KMAP_ATOMIC_FLUSH
select KRAIT_REGULATOR
+ select ENABLE_VMALLOC_SAVINGS
config ARCH_APQ8084
bool "APQ8084"
@@ -305,12 +305,12 @@
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_KMAP_ATOMIC_FLUSH
select MEMORY_HOLE_CARVEOUT
- select DONT_MAP_HOLE_AFTER_MEMBANK0
select QMI_ENCDEC
select MSM_SPM_V2
select MSM_L2_SPM
select MSM_PM8X60 if PM
select MSM_RPM_SMD
+ select ENABLE_VMALLOC_SAVINGS
config ARCH_MPQ8092
bool "MPQ8092"
@@ -460,7 +460,6 @@
select MSM_L2_SPM
select MSM_PM8X60 if PM
select MEMORY_HOLE_CARVEOUT
- select DONT_MAP_HOLE_AFTER_MEMBANK0
select MSM_BUS_SCALING
select CPU_FREQ_MSM
select CPU_FREQ
@@ -475,6 +474,7 @@
select MSM_RPM_LOG
select MSM_IOMMU_SYNC
select MSM_RPM_STATS_LOG
+ select ENABLE_VMALLOC_SAVINGS
config ARCH_MSM8226
bool "MSM8226"
@@ -500,7 +500,6 @@
select MSM_L2_SPM
select MSM_PM8X60 if PM
select MEMORY_HOLE_CARVEOUT
- select DONT_MAP_HOLE_AFTER_MEMBANK0
select MSM_BUS_SCALING
select CPU_FREQ_MSM
select CPU_FREQ
@@ -515,6 +514,7 @@
select MSM_RPM_LOG
select MSM_RPM_STATS_LOG
select ARCH_WANT_KMAP_ATOMIC_FLUSH
+ select ENABLE_VMALLOC_SAVINGS
config ARCH_MSMSAMARIUM
bool "MSMSAMARIUM"
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 4dcbc3a..34e23d1 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -303,13 +303,13 @@
static struct gpiomux_setting goodix_ldo_en_sus_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_UP,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
};
static struct gpiomux_setting goodix_int_act_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_6MA,
.pull = GPIOMUX_PULL_UP,
};
@@ -321,14 +321,14 @@
static struct gpiomux_setting goodix_reset_act_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_6MA,
.pull = GPIOMUX_PULL_UP,
};
static struct gpiomux_setting goodix_reset_sus_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_UP,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
};
static struct msm_gpiomux_config msm_skuf_blsp_configs[] __initdata = {
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index e3c11c5..6063302 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -557,7 +557,7 @@
return -ENOSYS;
mutex_lock(&clk->prepare_lock);
- if (clk->parent == parent)
+ if (clk->parent == parent && !(clk->flags & CLKFLAG_NO_RATE_CACHE))
goto out;
rc = clk->ops->set_parent(clk, parent);
if (!rc)
diff --git a/arch/arm/mach-msm/sensors_adsp.c b/arch/arm/mach-msm/sensors_adsp.c
index 1534358..fab10b8 100644
--- a/arch/arm/mach-msm/sensors_adsp.c
+++ b/arch/arm/mach-msm/sensors_adsp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -355,6 +355,7 @@
if (temp == NULL) {
pr_err("%s: allocation failure\n", __func__);
rv = -ENOMEM;
+ goto out;
}
hdr->dst_module = SNS_OCMEM_MODULE_ADSP;
@@ -387,6 +388,7 @@
kfree(temp);
+out:
return rv;
}
@@ -874,7 +876,7 @@
vectors = ocmem_get_vectors(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
if ((vectors != NULL)) {
- memcpy(&msg.vectors, vectors, sizeof(vectors));
+ memcpy(&msg.vectors, vectors, sizeof(*vectors));
/* TODO: set vectors_len */
msg.vectors_valid = true;
msg.vectors_len = 0;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index cdd315e..2beb143 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1051,9 +1051,10 @@
return is_mode_reset;
}
-void diag_send_data(struct diag_master_table entry, unsigned char *buf,
+int diag_send_data(struct diag_master_table entry, unsigned char *buf,
int len, int type)
{
+ int success = 1;
driver->pkt_length = len;
/* If the process_id corresponds to an apps process */
@@ -1069,13 +1070,19 @@
if (entry.client_id < NUM_SMD_DATA_CHANNELS) {
struct diag_smd_info *smd_info;
int index = entry.client_id;
+ if (!driver->rcvd_feature_mask[
+ entry.client_id]) {
+ pr_debug("diag: In %s, feature mask for peripheral: %d not received yet\n",
+ __func__, entry.client_id);
+ return 0;
+ }
/*
* Mode reset should work even if
* modem is down
*/
if ((index == MODEM_DATA) &&
diag_check_mode_reset(buf)) {
- return;
+ return 1;
}
smd_info = (driver->separate_cmdrsp[index] &&
index < NUM_SMD_CMD_CHANNELS) ?
@@ -1095,9 +1102,12 @@
} else {
pr_alert("diag: In %s, incorrect channel: %d",
__func__, entry.client_id);
+ success = 0;
}
}
}
+
+ return success;
}
void diag_process_stm_mask(uint8_t cmd, uint8_t data_mask, int data_type,
@@ -1191,6 +1201,7 @@
unsigned char *temp = buf;
int data_type;
int mask_ret;
+ int status = 0;
#if defined(CONFIG_DIAG_OVER_USB)
unsigned char *ptr;
#endif
@@ -1217,14 +1228,15 @@
pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
for (i = 0; i < diag_max_reg; i++) {
entry = driver->table[i];
- if (entry.process_id != NO_PROCESS &&
- driver->rcvd_feature_mask[entry.client_id]) {
+ if (entry.process_id != NO_PROCESS) {
if (entry.cmd_code == cmd_code && entry.subsys_id ==
subsys_id && entry.cmd_code_lo <=
subsys_cmd_code &&
entry.cmd_code_hi >= subsys_cmd_code) {
- diag_send_data(entry, buf, len, data_type);
- packet_type = 0;
+ status = diag_send_data(entry, buf, len,
+ data_type);
+ if (status)
+ packet_type = 0;
} else if (entry.cmd_code == 255
&& cmd_code == 75) {
if (entry.subsys_id ==
@@ -1233,9 +1245,10 @@
subsys_cmd_code &&
entry.cmd_code_hi >=
subsys_cmd_code) {
- diag_send_data(entry, buf, len,
- data_type);
- packet_type = 0;
+ status = diag_send_data(entry, buf,
+ len, data_type);
+ if (status)
+ packet_type = 0;
}
} else if (entry.cmd_code == 255 &&
entry.subsys_id == 255) {
@@ -1243,9 +1256,10 @@
cmd_code &&
entry.
cmd_code_hi >= cmd_code) {
- diag_send_data(entry, buf, len,
+ status = diag_send_data(entry, buf, len,
data_type);
- packet_type = 0;
+ if (status)
+ packet_type = 0;
}
}
}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 50a0d12..becb611 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2304,12 +2304,18 @@
_adreno_ft_restart_device(struct kgsl_device *device,
struct kgsl_context *context)
{
- /* If device soft reset fails try hard reset */
- if (adreno_soft_reset(device))
- KGSL_DEV_ERR_ONCE(device, "Device soft reset failed\n");
- else
- /* Soft reset is successful */
- goto reset_done;
+ /*
+ * If device soft reset fails try hard reset, but don't attempt
+ * soft reset on page faults. In cases of page faults, go straight
+ * to hard reset.
+ */
+ if (!(device->mmu.fault)) {
+ if (adreno_soft_reset(device))
+ KGSL_DEV_ERR_ONCE(device, "Device soft reset failed\n");
+ else
+ /* Soft reset is successful */
+ goto reset_done;
+ }
/* restart device */
if (adreno_stop(device)) {
@@ -2432,7 +2438,6 @@
struct adreno_context *last_active_ctx = adreno_dev->drawctxt_active;
unsigned int long_ib = 0;
static int no_context_ft;
- struct kgsl_mmu *mmu = &device->mmu;
context = kgsl_context_get(device, ft_data->context_id);
@@ -2507,8 +2512,6 @@
/* Do not try to replay if hang is due to a pagefault */
if (context && test_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv)) {
- /* Resume MMU */
- mmu->mmu_ops->mmu_pagefault_resume(mmu);
if ((ft_data->context_id == context->id) &&
(ft_data->global_eop == context->pagefault_ts)) {
ft_data->ft_policy &= ~KGSL_FT_REPLAY;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index acb3b17..6275a72 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -2052,7 +2052,6 @@
.mmu_setstate = kgsl_iommu_setstate,
.mmu_device_setstate = kgsl_iommu_default_setstate,
.mmu_pagefault = NULL,
- .mmu_pagefault_resume = kgsl_iommu_pagefault_resume,
.mmu_get_current_ptbase = kgsl_iommu_get_current_ptbase,
.mmu_enable_clk = kgsl_iommu_enable_clk,
.mmu_disable_clk_on_ts = kgsl_iommu_disable_clk_on_ts,
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index faba81e..64705f8 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -141,8 +141,6 @@
void (*mmu_pagefault) (struct kgsl_mmu *mmu);
phys_addr_t (*mmu_get_current_ptbase)
(struct kgsl_mmu *mmu);
- void (*mmu_pagefault_resume)
- (struct kgsl_mmu *mmu);
void (*mmu_disable_clk_on_ts)
(struct kgsl_mmu *mmu, uint32_t ts, bool ts_valid);
int (*mmu_enable_clk)
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index ef76e69..f366364 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -131,8 +131,9 @@
#define FT_FW_PKT_DLY_MS 20
#define FT_FW_LAST_PKT 0x6ffa
#define FT_EARSE_DLY_MS 100
+#define FT_55_AA_DLY_NS 5000
-#define FT_UPGRADE_LOOP 10
+#define FT_UPGRADE_LOOP 30
#define FT_CAL_START 0x04
#define FT_CAL_FIN 0x00
#define FT_CAL_STORE 0x05
@@ -142,6 +143,30 @@
#define FT_INFO_MAX_LEN 512
+#define FT_BLOADER_SIZE_OFF 12
+#define FT_BLOADER_NEW_SIZE 30
+#define FT_DATA_LEN_OFF_OLD_FW 8
+#define FT_DATA_LEN_OFF_NEW_FW 14
+#define FT_FINISHING_PKT_LEN_OLD_FW 6
+#define FT_FINISHING_PKT_LEN_NEW_FW 12
+#define FT_MAGIC_BLOADER_Z7 0x7bfa
+#define FT_MAGIC_BLOADER_LZ4 0x6ffa
+#define FT_MAGIC_BLOADER_GZF_30 0x7ff4
+#define FT_MAGIC_BLOADER_GZF 0x7bf4
+
+enum {
+ FT_BLOADER_VERSION_LZ4 = 0,
+ FT_BLOADER_VERSION_Z7 = 1,
+ FT_BLOADER_VERSION_GZF = 2,
+};
+
+enum {
+ FT_FT5336_FAMILY_ID_0x11 = 0x11,
+ FT_FT5336_FAMILY_ID_0x12 = 0x12,
+ FT_FT5336_FAMILY_ID_0x13 = 0x13,
+ FT_FT5336_FAMILY_ID_0x14 = 0x14,
+};
+
#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_vkey_support, \
fw_name, fw_maj, fw_min, fw_sub_min) \
snprintf(buf, FT_INFO_MAX_LEN, \
@@ -645,11 +670,20 @@
u8 reset_reg;
u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
- int rc, i, j, temp;
+ int i, j, temp;
u32 pkt_num, pkt_len;
+ u8 is_5336_new_bootloader = false;
+ u8 is_5336_fwsize_30 = false;
u8 fw_ecc;
+ /* determine firmware size */
+ if (*(data + data_len - FT_BLOADER_SIZE_OFF) == FT_BLOADER_NEW_SIZE)
+ is_5336_fwsize_30 = true;
+ else
+ is_5336_fwsize_30 = false;
+
for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
+ msleep(FT_EARSE_DLY_MS);
/* reset - write 0xaa and 0x55 to reset register */
if (ts_data->family_id == FT6X06_ID)
reset_reg = FT_RST_CMD_REG2;
@@ -660,16 +694,17 @@
msleep(info.delay_aa);
ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55);
- msleep(info.delay_55);
+ if (i <= (FT_UPGRADE_LOOP / 2))
+ msleep(info.delay_55 + i * 3);
+ else
+ msleep(info.delay_55 - (i - (FT_UPGRADE_LOOP / 2)) * 2);
/* Enter upgrade mode */
w_buf[0] = FT_UPGRADE_55;
- w_buf[1] = FT_UPGRADE_AA;
- do {
- j++;
- rc = ft5x06_i2c_write(client, w_buf, 2);
- msleep(FT_RETRY_DLY);
- } while (rc <= 0 && j < FT_MAX_TRIES);
+ ft5x06_i2c_write(client, w_buf, 1);
+ usleep(FT_55_AA_DLY_NS);
+ w_buf[0] = FT_UPGRADE_AA;
+ ft5x06_i2c_write(client, w_buf, 1);
/* check READ_ID */
msleep(info.delay_readid);
@@ -692,17 +727,40 @@
return -EIO;
}
+ w_buf[0] = 0xcd;
+ ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
+
+ if (r_buf[0] <= 4)
+ is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
+ else if (r_buf[0] == 7)
+ is_5336_new_bootloader = FT_BLOADER_VERSION_Z7;
+ else if (r_buf[0] >= 0x0f &&
+ ((ts_data->family_id == FT_FT5336_FAMILY_ID_0x11) ||
+ (ts_data->family_id == FT_FT5336_FAMILY_ID_0x12) ||
+ (ts_data->family_id == FT_FT5336_FAMILY_ID_0x13) ||
+ (ts_data->family_id == FT_FT5336_FAMILY_ID_0x14)))
+ is_5336_new_bootloader = FT_BLOADER_VERSION_GZF;
+ else
+ is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
+
/* erase app and panel paramenter area */
w_buf[0] = FT_ERASE_APP_REG;
ft5x06_i2c_write(client, w_buf, 1);
msleep(info.delay_erase_flash);
- w_buf[0] = FT_ERASE_PANEL_REG;
- ft5x06_i2c_write(client, w_buf, 1);
+ if (is_5336_fwsize_30) {
+ w_buf[0] = FT_ERASE_PANEL_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ }
msleep(FT_EARSE_DLY_MS);
/* program firmware */
- data_len = data_len - 8;
+ if (is_5336_new_bootloader == FT_BLOADER_VERSION_LZ4
+ || is_5336_new_bootloader == FT_BLOADER_VERSION_Z7)
+ data_len = data_len - FT_DATA_LEN_OFF_OLD_FW;
+ else
+ data_len = data_len - FT_DATA_LEN_OFF_NEW_FW;
+
pkt_num = (data_len) / FT_FW_PKT_LEN;
pkt_len = FT_FW_PKT_LEN;
pkt_buf[0] = FT_FW_START_REG;
@@ -745,17 +803,45 @@
}
/* send the finishing packet */
- for (i = 0; i < 6; i++) {
- temp = FT_FW_LAST_PKT + i;
- pkt_buf[2] = (u8) (temp >> 8);
- pkt_buf[3] = (u8) temp;
- temp = 1;
- pkt_buf[4] = (u8) (temp >> 8);
- pkt_buf[5] = (u8) temp;
- pkt_buf[6] = data[data_len + i];
- fw_ecc ^= pkt_buf[6];
- ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
- msleep(FT_FW_PKT_DLY_MS);
+ if (is_5336_new_bootloader == FT_BLOADER_VERSION_LZ4 ||
+ is_5336_new_bootloader == FT_BLOADER_VERSION_Z7) {
+ for (i = 0; i < FT_FINISHING_PKT_LEN_OLD_FW; i++) {
+ if (is_5336_new_bootloader == FT_BLOADER_VERSION_Z7)
+ temp = FT_MAGIC_BLOADER_Z7 + i;
+ else if (is_5336_new_bootloader ==
+ FT_BLOADER_VERSION_LZ4)
+ temp = FT_MAGIC_BLOADER_LZ4 + i;
+ pkt_buf[2] = (u8)(temp >> 8);
+ pkt_buf[3] = (u8)temp;
+ temp = 1;
+ pkt_buf[4] = (u8)(temp >> 8);
+ pkt_buf[5] = (u8)temp;
+ pkt_buf[6] = data[data_len + i];
+ fw_ecc ^= pkt_buf[6];
+
+ ft5x06_i2c_write(client,
+ pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+ } else if (is_5336_new_bootloader == FT_BLOADER_VERSION_GZF) {
+ for (i = 0; i < FT_FINISHING_PKT_LEN_NEW_FW; i++) {
+ if (is_5336_fwsize_30)
+ temp = FT_MAGIC_BLOADER_GZF_30 + i;
+ else
+ temp = FT_MAGIC_BLOADER_GZF + i;
+ pkt_buf[2] = (u8)(temp >> 8);
+ pkt_buf[3] = (u8)temp;
+ temp = 1;
+ pkt_buf[4] = (u8)(temp >> 8);
+ pkt_buf[5] = (u8)temp;
+ pkt_buf[6] = data[data_len + i];
+ fw_ecc ^= pkt_buf[6];
+
+ ft5x06_i2c_write(client,
+ pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+
+ }
}
/* verify checksum */
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c
index 8b08ac9..ba38061 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.c
@@ -95,6 +95,8 @@
static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms);
static void gtp_int_sync(struct goodix_ts_data *ts, int ms);
static int gtp_i2c_test(struct i2c_client *client);
+static int goodix_power_off(struct goodix_ts_data *ts);
+static int goodix_power_on(struct goodix_ts_data *ts);
#if defined(CONFIG_FB)
static int fb_notifier_callback(struct notifier_block *self,
@@ -758,7 +760,7 @@
ts: private data.
Output:
Executive outcomes.
- 1: succeed, otherwise failed.
+ >0: succeed, otherwise failed.
*******************************************************/
static s8 gtp_enter_sleep(struct goodix_ts_data *ts)
{
@@ -769,20 +771,37 @@
(u8)GTP_REG_SLEEP, 5};
ret = gpio_direction_output(ts->pdata->irq_gpio, 0);
- usleep(5000);
- while (retry++ < 5) {
- ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
- if (ret > 0) {
- dev_dbg(&ts->client->dev,
- "GTP enter sleep!");
- return ret;
+ if (ret)
+ dev_err(&ts->client->dev,
+ "GTP sleep: Cannot reconfig gpio %d.\n",
+ ts->pdata->irq_gpio);
+ if (ts->pdata->enable_power_off) {
+ ret = gpio_direction_output(ts->pdata->reset_gpio, 0);
+ if (ret)
+ dev_err(&ts->client->dev,
+ "GTP sleep: Cannot reconfig gpio %d.\n",
+ ts->pdata->reset_gpio);
+ ret = goodix_power_off(ts);
+ if (ret) {
+ dev_err(&ts->client->dev, "GTP power off failed.\n");
+ return 0;
}
- msleep(20);
+ return 1;
+ } else {
+ usleep(5000);
+ while (retry++ < 5) {
+ ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+ if (ret == 1) {
+ dev_dbg(&ts->client->dev, "GTP enter sleep!");
+ return ret;
+ }
+ msleep(20);
+ }
+ dev_err(&ts->client->dev, "GTP send sleep cmd failed.\n");
+ return ret;
}
- dev_err(&ts->client->dev, "GTP send sleep cmd failed.\n");
- return ret;
}
-#endif
+#endif /* !GTP_SLIDE_WAKEUP */
/*******************************************************
Function:
@@ -798,17 +817,36 @@
u8 retry = 0;
s8 ret = -1;
-#if GTP_POWER_CTRL_SLEEP
- gtp_reset_guitar(ts, 20);
+ if (ts->pdata->enable_power_off) {
+ ret = gpio_direction_output(ts->pdata->irq_gpio, 0);
+ if (ret)
+ dev_err(&ts->client->dev,
+ "GTP wakeup: Cannot reconfig gpio %d.\n",
+ ts->pdata->irq_gpio);
+ ret = gpio_direction_output(ts->pdata->reset_gpio, 0);
+ if (ret)
+ dev_err(&ts->client->dev,
+ "GTP wakeup: Cannot reconfig gpio %d.\n",
+ ts->pdata->reset_gpio);
+ ret = goodix_power_on(ts);
+ if (ret) {
+ dev_err(&ts->client->dev, "GTP power on failed.\n");
+ return 0;
+ }
- ret = gtp_send_cfg(ts);
- if (ret > 0) {
+ gtp_reset_guitar(ts, 20);
+
+ ret = gtp_send_cfg(ts);
+ if (ret <= 0) {
+ dev_err(&ts->client->dev,
+ "GTP wakeup sleep failed.\n");
+ return ret;
+ }
+
dev_dbg(&ts->client->dev,
- "Wakeup sleep send config success.");
- return 1;
- }
-#else
- while (retry++ < 10) {
+ "Wakeup sleep send config success.");
+ } else {
+err_retry:
#if GTP_SLIDE_WAKEUP
/* wakeup not by slide */
if (DOZE_WAKEUP != doze_status)
@@ -825,7 +863,7 @@
}
#endif
ret = gtp_i2c_test(ts->client);
- if (ret > 0) {
+ if (ret == 2) {
dev_dbg(&ts->client->dev, "GTP wakeup sleep.");
#if (!GTP_SLIDE_WAKEUP)
if (chip_gt9xxs == 0) {
@@ -839,10 +877,10 @@
return ret;
}
gtp_reset_guitar(ts, 20);
+ if (retry++ < 10)
+ goto err_retry;
+ dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n");
}
-#endif
-
- dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n");
return ret;
}
#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/
@@ -1055,9 +1093,7 @@
dev_info(&client->dev, "Goodix Product ID = %s\n", product_id);
- if (!IS_ERR(ts->pdata->product_id))
- ret = strcmp(product_id, ts->pdata->product_id);
-
+ ret = strcmp(product_id, ts->pdata->product_id);
if (ret != 0)
return -EINVAL;
@@ -1292,6 +1328,12 @@
{
int ret;
+ if (ts->power_on) {
+ dev_info(&ts->client->dev,
+ "Device already power on\n");
+ return 0;
+ }
+
if (!IS_ERR(ts->avdd)) {
ret = reg_set_optimum_mode_check(ts->avdd,
GOODIX_VDD_LOAD_MAX_UA);
@@ -1358,6 +1400,7 @@
}
}
+ ts->power_on = true;
return 0;
err_enable_vcc_i2c:
@@ -1376,6 +1419,7 @@
regulator_disable(ts->avdd);
err_enable_avdd:
err_set_opt_avdd:
+ ts->power_on = false;
return ret;
}
@@ -1389,6 +1433,12 @@
{
int ret;
+ if (!ts->power_on) {
+ dev_info(&ts->client->dev,
+ "Device already power off\n");
+ return 0;
+ }
+
if (!IS_ERR(ts->vcc_i2c)) {
ret = regulator_set_voltage(ts->vcc_i2c, 0,
GOODIX_I2C_VTG_MAX_UV);
@@ -1421,6 +1471,7 @@
"Regulator avdd disable failed ret=%d\n", ret);
}
+ ts->power_on = false;
return 0;
}
@@ -1473,6 +1524,50 @@
return 0;
}
+static ssize_t gtp_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct goodix_ts_data *ts = dev_get_drvdata(dev);
+
+ if (!strlen(ts->fw_name))
+ return snprintf(buf, GTP_FW_NAME_MAXSIZE - 1,
+ "No fw name has been given.");
+ else
+ return snprintf(buf, GTP_FW_NAME_MAXSIZE - 1,
+ "%s\n", ts->fw_name);
+}
+
+static ssize_t gtp_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct goodix_ts_data *ts = dev_get_drvdata(dev);
+
+ if (size > GTP_FW_NAME_MAXSIZE - 1) {
+ dev_err(dev, "FW name size exceeds the limit.");
+ return -EINVAL;
+ }
+
+ strlcpy(ts->fw_name, buf, size);
+ if (ts->fw_name[size-1] == '\n')
+ ts->fw_name[size-1] = '\0';
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR | S_IWGRP),
+ gtp_fw_name_show,
+ gtp_fw_name_store);
+
+static struct attribute *gtp_attrs[] = {
+ &dev_attr_fw_name.attr,
+ NULL
+};
+
+static const struct attribute_group gtp_attr_grp = {
+ .attrs = gtp_attrs,
+};
+
static int goodix_ts_get_dt_coords(struct device *dev, char *name,
struct goodix_ts_platform_data *pdata)
{
@@ -1536,6 +1631,9 @@
pdata->no_force_update = of_property_read_bool(np,
"goodix,no-force-update");
+
+ pdata->enable_power_off = of_property_read_bool(np,
+ "goodix,enable-power-off");
/* reset, irq gpio info */
pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios",
0, &pdata->reset_gpio_flags);
@@ -1549,8 +1647,17 @@
rc = of_property_read_string(np, "goodix,product-id",
&pdata->product_id);
- if (rc < 0 || strlen(pdata->product_id) > GTP_PRODUCT_ID_MAXSIZE)
- return rc;
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Failed to parse product_id.");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_string(np, "goodix,fw_name",
+ &pdata->fw_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Failed to parse firmware name.\n");
+ return -EINVAL;
+ }
prop = of_find_property(np, "goodix,button-map", NULL);
if (prop) {
@@ -1662,6 +1769,7 @@
spin_lock_init(&ts->irq_lock);
i2c_set_clientdata(client, ts);
ts->gtp_rawdiff_mode = 0;
+ ts->power_on = false;
ret = goodix_power_init(ts);
if (ret) {
@@ -1689,12 +1797,16 @@
goto exit_free_io_port;
}
+ if (pdata->fw_name)
+ strlcpy(ts->fw_name, pdata->fw_name,
+ strlen(pdata->fw_name) + 1);
+
#if GTP_AUTO_UPDATE
ret = gup_init_update_proc(ts);
if (ret < 0) {
dev_err(&client->dev,
"GTP Create firmware update thread error.\n");
- goto exit_free_io_port;
+ goto exit_power_off;
}
#endif
@@ -1711,7 +1823,9 @@
dev_err(&client->dev, "GTP request input dev failed.\n");
goto exit_free_inputdev;
}
+ input_set_drvdata(ts->input_dev, ts);
+ mutex_init(&ts->lock);
#if defined(CONFIG_FB)
ts->fb_notif.notifier_call = fb_notifier_callback;
ret = fb_register_client(&ts->fb_notif);
@@ -1754,9 +1868,16 @@
#if GTP_ESD_PROTECT
gtp_esd_switch(client, SWITCH_ON);
#endif
+ ret = sysfs_create_group(&client->dev.kobj, >p_attr_grp);
+ if (ret < 0) {
+ dev_err(&client->dev, "sys file creation failed.\n");
+ goto exit_free_irq;
+ }
+
init_done = true;
return 0;
exit_free_irq:
+ mutex_destroy(&ts->lock);
#if defined(CONFIG_FB)
if (fb_unregister_client(&ts->fb_notif))
dev_err(&client->dev,
@@ -1806,6 +1927,8 @@
{
struct goodix_ts_data *ts = i2c_get_clientdata(client);
+ sysfs_remove_group(&ts->input_dev->dev.kobj, >p_attr_grp);
+
#if defined(CONFIG_FB)
if (fb_unregister_client(&ts->fb_notif))
dev_err(&client->dev,
@@ -1813,6 +1936,7 @@
#elif defined(CONFIG_HAS_EARLYSUSPEND)
unregister_early_suspend(&ts->early_suspend);
#endif
+ mutex_destroy(&ts->lock);
#if GTP_CREATE_WR_NODE
uninit_wr_node();
@@ -1868,6 +1992,7 @@
{
int ret = -1, i;
+ mutex_lock(&ts->lock);
#if GTP_ESD_PROTECT
ts->gtp_is_suspend = 1;
gtp_esd_switch(ts->client, SWITCH_OFF);
@@ -1888,12 +2013,13 @@
ret = gtp_enter_sleep(ts);
#endif
- if (ret < 0)
+ if (ret <= 0)
dev_err(&ts->client->dev, "GTP early suspend failed.\n");
/* to avoid waking up while not sleeping,
* delay 48 + 10ms to ensure reliability
*/
msleep(58);
+ mutex_unlock(&ts->lock);
}
/*******************************************************
@@ -1908,13 +2034,14 @@
{
int ret = -1;
+ mutex_lock(&ts->lock);
ret = gtp_wakeup_sleep(ts);
#if GTP_SLIDE_WAKEUP
doze_status = DOZE_DISABLED;
#endif
- if (ret < 0)
+ if (ret <= 0)
dev_err(&ts->client->dev, "GTP resume failed.\n");
if (ts->use_irq)
@@ -1927,6 +2054,7 @@
ts->gtp_is_suspend = 0;
gtp_esd_switch(ts->client, SWITCH_ON);
#endif
+ mutex_unlock(&ts->lock);
}
#if defined(CONFIG_FB)
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h
index 1fdbfa3..1d31f2a 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.h
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.h
@@ -36,6 +36,7 @@
#include <linux/regulator/consumer.h>
#include <linux/firmware.h>
#include <linux/debugfs.h>
+#include <linux/mutex.h>
#if defined(CONFIG_FB)
#include <linux/notifier.h>
@@ -46,12 +47,15 @@
#endif
#define GOODIX_MAX_CFG_GROUP 6
+#define GTP_FW_NAME_MAXSIZE 50
+
struct goodix_ts_platform_data {
int irq_gpio;
u32 irq_gpio_flags;
int reset_gpio;
u32 reset_gpio_flags;
const char *product_id;
+ const char *fw_name;
u32 x_max;
u32 y_max;
u32 x_min;
@@ -62,6 +66,7 @@
u32 panel_maxy;
bool no_force_update;
bool i2c_pull_up;
+ bool enable_power_off;
size_t config_data_len[GOODIX_MAX_CFG_GROUP];
u8 *config_data[GOODIX_MAX_CFG_GROUP];
};
@@ -73,6 +78,7 @@
struct hrtimer timer;
struct workqueue_struct *goodix_wq;
struct work_struct work;
+ char fw_name[GTP_FW_NAME_MAXSIZE];
s32 irq_is_disabled;
s32 use_irq;
u16 abs_x_max;
@@ -89,6 +95,8 @@
u8 fixed_cfg;
u8 esd_running;
u8 fw_error;
+ bool power_on;
+ struct mutex lock;
struct regulator *avdd;
struct regulator *vdd;
struct regulator *vcc_i2c;
@@ -107,7 +115,6 @@
#define GTP_CHANGE_X2Y 0
#define GTP_DRIVER_SEND_CFG 1
#define GTP_HAVE_TOUCH_KEY 1
-#define GTP_POWER_CTRL_SLEEP 0
/* auto updated by .bin file as default */
#define GTP_AUTO_UPDATE 0
@@ -119,6 +126,7 @@
#define GTP_ESD_PROTECT 0
#define GTP_WITH_PEN 0
+/* This cannot work when enable-power-off is on */
#define GTP_SLIDE_WAKEUP 0
/* double-click wakeup, function together with GTP_SLIDE_WAKEUP */
#define GTP_DBL_CLK_WAKEUP 0
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 5f36a4a..fb1caea 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -513,7 +513,9 @@
}
lo_tbl_ptr = cfg_data +
reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4;
-
+ if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT)
+ reg_cfg_cmd->u.dmi_info.len =
+ reg_cfg_cmd->u.dmi_info.len / 2;
for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) {
lo_val = *lo_tbl_ptr++;
if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_16BIT) {
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 30ada3e..ae94287 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -803,7 +803,8 @@
pkt->rg_property_data[0] =
HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE;
hfi = (struct hfi_enable_picture *) &pkt->rg_property_data[1];
- hfi->picture_type = (u32) pdata;
+ hfi->picture_type =
+ ((struct hfi_enable_picture *)pdata)->picture_type;
pkt->size += sizeof(u32) * 2;
break;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index f4fdfe7..502d4bc 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -686,6 +686,7 @@
int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
{
const struct msm_vidc_format *fmt = NULL;
+ unsigned int *plane_sizes = NULL;
struct hfi_device *hdev;
int stride, scanlines;
int extra_idx = 0;
@@ -741,9 +742,19 @@
goto exit;
}
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ plane_sizes =
+ &inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[0];
for (i = 0; i < fmt->num_planes; ++i) {
- f->fmt.pix_mp.plane_fmt[i].sizeimage =
- inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[i];
+ if (plane_sizes[i] == 0) {
+ f->fmt.pix_mp.plane_fmt[i].sizeimage =
+ fmt->get_frame_size(i,
+ inst->capability.height.max,
+ inst->capability.width.max);
+ plane_sizes[i] =
+ f->fmt.pix_mp.plane_fmt[i].sizeimage;
+ } else
+ f->fmt.pix_mp.plane_fmt[i].sizeimage =
+ plane_sizes[i];
}
} else {
switch (fmt->fourcc) {
@@ -979,8 +990,10 @@
inst->capability.height.max,
inst->capability.width.max);
- if (f->fmt.pix_mp.plane_fmt[0].sizeimage > max_input_size)
+ if (f->fmt.pix_mp.plane_fmt[0].sizeimage > max_input_size ||
+ f->fmt.pix_mp.plane_fmt[0].sizeimage == 0) {
f->fmt.pix_mp.plane_fmt[0].sizeimage = max_input_size;
+ }
f->fmt.pix_mp.num_planes = fmt->num_planes;
for (i = 0; i < fmt->num_planes; ++i) {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b01abe7..513ddfb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -746,6 +746,12 @@
if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
return 0xE;
+ /* During initialization, don't use max timeout as the clock is slow */
+ if ((host->quirks2 & SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT) &&
+ (host->clock > 400000)) {
+ return 0xF;
+ }
+
/* Unspecified timeout, assume max */
if (!data && !cmd->cmd_timeout_ms)
return 0xE;
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 6a16cf3..1ef1f1b 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -963,7 +963,7 @@
enum ipa_pipe_mem_type mem_type;
if (!pipe_connection || !node)
- goto err;
+ return -EINVAL;
key = "qcom,src-bam-physical-address";
rc = of_property_read_u32(node, key, &val);
diff --git a/drivers/platform/msm/ipa/ipa_flt.c b/drivers/platform/msm/ipa/ipa_flt.c
index 2d75141..c3db716 100644
--- a/drivers/platform/msm/ipa/ipa_flt.c
+++ b/drivers/platform/msm/ipa/ipa_flt.c
@@ -802,8 +802,11 @@
IPADBG("reset flt ip=%d\n", ip);
list_for_each_entry_safe(entry, next, &tbl->head_flt_rule_list, link) {
node = ipa_search(&ipa_ctx->flt_rule_hdl_tree, (u32)entry);
- if (node == NULL)
+ if (node == NULL) {
WARN_ON(1);
+ mutex_unlock(&ipa_ctx->lock);
+ return -EFAULT;
+ }
if ((ip == IPA_IP_v4 &&
entry->rule.attrib.attrib_mask == IPA_FLT_PROTOCOL &&
@@ -833,8 +836,11 @@
link) {
node = ipa_search(&ipa_ctx->flt_rule_hdl_tree,
(u32)entry);
- if (node == NULL)
+ if (node == NULL) {
WARN_ON(1);
+ mutex_unlock(&ipa_ctx->lock);
+ return -EFAULT;
+ }
list_del(&entry->link);
entry->tbl->rule_cnt--;
if (entry->rt_tbl)
diff --git a/drivers/platform/msm/ipa/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_hdr.c
index 9618da2..54cbf5f 100644
--- a/drivers/platform/msm/ipa/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_hdr.c
@@ -450,8 +450,11 @@
continue;
node = ipa_search(&ipa_ctx->hdr_hdl_tree, (u32) entry);
- if (node == NULL)
+ if (node == NULL) {
WARN_ON(1);
+ mutex_unlock(&ipa_ctx->lock);
+ return -EFAULT;
+ }
list_del(&entry->link);
entry->cookie = 0;
kmem_cache_free(ipa_ctx->hdr_cache, entry);
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 8d6d5e6..f453010 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -843,8 +843,11 @@
&tbl->head_rt_rule_list, link) {
node = ipa_search(&ipa_ctx->rt_rule_hdl_tree,
(u32)rule);
- if (node == NULL)
+ if (node == NULL) {
WARN_ON(1);
+ mutex_unlock(&ipa_ctx->lock);
+ return -EFAULT;
+ }
/*
* for the "default" routing tbl, remove all but the
@@ -866,8 +869,11 @@
}
node = ipa_search(&ipa_ctx->rt_tbl_hdl_tree, (u32)tbl);
- if (node == NULL)
+ if (node == NULL) {
WARN_ON(1);
+ mutex_unlock(&ipa_ctx->lock);
+ return -EFAULT;
+ }
/* do not remove the "default" routing tbl which has index 0 */
if (tbl->idx != 0) {
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 0c9959c..67cf049 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -1065,7 +1065,7 @@
}
dev = kzalloc(sizeof(struct msm_slim_ctrl), GFP_KERNEL);
- if (IS_ERR(dev)) {
+ if (IS_ERR_OR_NULL(dev)) {
dev_err(&pdev->dev, "no memory for MSM slimbus controller\n");
return PTR_ERR(dev);
}
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 44949d2..91d94b5 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -440,6 +440,14 @@
goto out;
}
+ /*
+ * zram_slot_free_notify could miss free so that let's
+ * double check.
+ */
+ if (unlikely(meta->table[index].handle ||
+ zram_test_flag(meta, index, ZRAM_ZERO)))
+ zram_free_page(zram, index);
+
ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
meta->compress_workmem);
@@ -505,6 +513,20 @@
return ret;
}
+static void handle_pending_slot_free(struct zram *zram)
+{
+ struct zram_slot_free *free_rq;
+
+ spin_lock(&zram->slot_free_lock);
+ while (zram->slot_free_rq) {
+ free_rq = zram->slot_free_rq;
+ zram->slot_free_rq = free_rq->next;
+ zram_free_page(zram, free_rq->index);
+ kfree(free_rq);
+ }
+ spin_unlock(&zram->slot_free_lock);
+}
+
static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
int offset, struct bio *bio, int rw)
{
@@ -512,10 +534,12 @@
if (rw == READ) {
down_read(&zram->lock);
+ handle_pending_slot_free(zram);
ret = zram_bvec_read(zram, bvec, index, offset, bio);
up_read(&zram->lock);
} else {
down_write(&zram->lock);
+ handle_pending_slot_free(zram);
ret = zram_bvec_write(zram, bvec, index, offset);
up_write(&zram->lock);
}
@@ -523,11 +547,13 @@
return ret;
}
-static void zram_reset_device(struct zram *zram)
+static void zram_reset_device(struct zram *zram, bool reset_capacity)
{
size_t index;
struct zram_meta *meta;
+ flush_work(&zram->free_work);
+
down_write(&zram->init_lock);
if (!zram->init_done) {
up_write(&zram->init_lock);
@@ -552,7 +578,8 @@
memset(&zram->stats, 0, sizeof(zram->stats));
zram->disksize = 0;
- set_capacity(zram->disk, 0);
+ if (reset_capacity)
+ set_capacity(zram->disk, 0);
up_write(&zram->init_lock);
}
@@ -636,7 +663,7 @@
if (bdev)
fsync_bdev(bdev);
- zram_reset_device(zram);
+ zram_reset_device(zram, true);
return len;
}
@@ -721,16 +748,40 @@
bio_io_error(bio);
}
+static void zram_slot_free(struct work_struct *work)
+{
+ struct zram *zram;
+
+ zram = container_of(work, struct zram, free_work);
+ down_write(&zram->lock);
+ handle_pending_slot_free(zram);
+ up_write(&zram->lock);
+}
+
+static void add_slot_free(struct zram *zram, struct zram_slot_free *free_rq)
+{
+ spin_lock(&zram->slot_free_lock);
+ free_rq->next = zram->slot_free_rq;
+ zram->slot_free_rq = free_rq;
+ spin_unlock(&zram->slot_free_lock);
+}
+
static void zram_slot_free_notify(struct block_device *bdev,
unsigned long index)
{
struct zram *zram;
+ struct zram_slot_free *free_rq;
zram = bdev->bd_disk->private_data;
- down_write(&zram->lock);
- zram_free_page(zram, index);
- up_write(&zram->lock);
atomic64_inc(&zram->stats.notify_free);
+
+ free_rq = kmalloc(sizeof(struct zram_slot_free), GFP_ATOMIC);
+ if (!free_rq)
+ return;
+
+ free_rq->index = index;
+ add_slot_free(zram, free_rq);
+ schedule_work(&zram->free_work);
}
static const struct block_device_operations zram_devops = {
@@ -777,6 +828,10 @@
init_rwsem(&zram->lock);
init_rwsem(&zram->init_lock);
+ INIT_WORK(&zram->free_work, zram_slot_free);
+ spin_lock_init(&zram->slot_free_lock);
+ zram->slot_free_rq = NULL;
+
zram->queue = blk_alloc_queue(GFP_KERNEL);
if (!zram->queue) {
pr_err("Error allocating disk queue for device %d\n",
@@ -903,10 +958,12 @@
for (i = 0; i < num_devices; i++) {
zram = &zram_devices[i];
- get_disk(zram->disk);
destroy_device(zram);
- zram_reset_device(zram);
- put_disk(zram->disk);
+ /*
+ * Shouldn't access zram->disk after destroy_device
+ * because destroy_device already released zram->disk.
+ */
+ zram_reset_device(zram, false);
}
unregister_blkdev(zram_major, "zram");
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
index 9e57bfb..97a3acf 100644
--- a/drivers/staging/zram/zram_drv.h
+++ b/drivers/staging/zram/zram_drv.h
@@ -94,11 +94,20 @@
struct zs_pool *mem_pool;
};
+struct zram_slot_free {
+ unsigned long index;
+ struct zram_slot_free *next;
+};
+
struct zram {
struct zram_meta *meta;
struct rw_semaphore lock; /* protect compression buffers, table,
* 32bit stat counters against concurrent
* notifications, reads and writes */
+
+ struct work_struct free_work; /* handle pending free request */
+ struct zram_slot_free *slot_free_rq; /* list head of free request */
+
struct request_queue *queue;
struct gendisk *disk;
int init_done;
@@ -109,6 +118,7 @@
* we can store in a disk.
*/
u64 disksize; /* bytes */
+ spinlock_t slot_free_lock;
struct zram_stats stats;
};
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index e416a55..7d57f64 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -77,7 +77,7 @@
if (status) {
MIPI_OUTP(ctrl_base + DSI_ACK_ERR_STATUS, status);
- pr_debug("%s: status=%x\n", __func__, status);
+ pr_err("%s: status=%x\n", __func__, status);
}
}
@@ -88,7 +88,7 @@
status = MIPI_INP(ctrl_base + DSI_TIMEOUT_STATUS);
if (status & 0x0111) {
MIPI_OUTP(ctrl_base + DSI_TIMEOUT_STATUS, status);
- pr_debug("%s: status=%x\n", __func__, status);
+ pr_err("%s: status=%x\n", __func__, status);
}
}
@@ -100,7 +100,7 @@
if (status & 0x011111) {
MIPI_OUTP(ctrl_base + DSI_DLN0_PHY_ERR, status);
- pr_debug("%s: status=%x\n", __func__, status);
+ pr_err("%s: status=%x\n", __func__, status);
}
}
@@ -112,7 +112,7 @@
if (status & 0x44444489) {
MIPI_OUTP(ctrl_base + DSI_FIFO_STATUS, status);
- pr_debug("%s: status=%x\n", __func__, status);
+ pr_err("%s: status=%x\n", __func__, status);
}
}
@@ -124,7 +124,7 @@
if (status & 0x80000000) {
MIPI_OUTP(ctrl_base + DSI_STATUS, status);
- pr_debug("%s: status=%x\n", __func__, status);
+ pr_err("%s: status=%x\n", __func__, status);
}
}
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 638fcb3..fe8c528 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -1859,6 +1859,52 @@
mdp3_res->underrun_cnt);
}
+static ssize_t mdp3_show_capabilities(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ size_t len = PAGE_SIZE;
+ int cnt = 0;
+
+#define SPRINT(fmt, ...) \
+ (cnt += scnprintf(buf + cnt, len - cnt, fmt, ##__VA_ARGS__))
+
+ SPRINT("mdp_version=3\n");
+ SPRINT("hw_rev=%d\n", 304);
+ SPRINT("dma_pipes=%d\n", 1);
+ SPRINT("\n");
+
+ return cnt;
+}
+
+static DEVICE_ATTR(caps, S_IRUGO, mdp3_show_capabilities, NULL);
+
+static struct attribute *mdp3_fs_attrs[] = {
+ &dev_attr_caps.attr,
+ NULL
+};
+
+static struct attribute_group mdp3_fs_attr_group = {
+ .attrs = mdp3_fs_attrs
+};
+
+static int mdp3_register_sysfs(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ int rc;
+
+ rc = sysfs_create_group(&dev->kobj, &mdp3_fs_attr_group);
+
+ return rc;
+}
+
+int mdp3_create_sysfs_link(struct device *dev)
+{
+ int rc;
+ rc = sysfs_create_link_nowarn(&dev->kobj,
+ &mdp3_res->pdev->dev.kobj, "mdp");
+
+ return rc;
+}
static int mdp3_probe(struct platform_device *pdev)
{
@@ -1918,6 +1964,10 @@
goto probe_done;
}
+ rc = mdp3_register_sysfs(pdev);
+ if (rc)
+ pr_err("unable to register mdp sysfs nodes\n");
+
rc = mdss_fb_register_mdp_instance(&mdp3_interface);
if (rc)
pr_err("unable to register mdp instance\n");
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 4480c20..e66b5ac 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -186,6 +186,7 @@
void mdp3_free(void);
int mdp3_parse_dt_splash(struct msm_fb_data_type *mfd);
void mdp3_release_splash_memory(void);
+int mdp3_create_sysfs_link(struct device *dev);
#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index e92e178..e6ba9e9 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -1525,6 +1525,10 @@
goto init_done;
}
+ rc = mdp3_create_sysfs_link(dev);
+ if (rc)
+ pr_warn("problem creating link to mdp sysfs\n");
+
kobject_uevent(&dev->kobj, KOBJ_ADD);
pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 105dd1a..047c0f0 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -616,11 +616,11 @@
* scaling fraction (x/1024)
*/
temp = (temp * mfd->bl_scale) / 1024;
- }
- /*if less than minimum level, use min level*/
- else if ((temp < mfd->bl_min_lvl) && (0 != temp))
- temp = mfd->bl_min_lvl;
+ /*if less than minimum level, use min level*/
+ if (temp < mfd->bl_min_lvl)
+ temp = mfd->bl_min_lvl;
+ }
pr_debug("output = %d", temp);
(*bl_lvl) = temp;
@@ -635,11 +635,8 @@
if (((!mfd->panel_power_on && mfd->dcm_state != DCM_ENTER)
|| !mfd->bl_updated) && !IS_CALIB_MODE_BL(mfd)) {
- if (bkl_lvl < mfd->bl_min_lvl)
- mfd->unset_bl_level = mfd->bl_min_lvl;
- else
- mfd->unset_bl_level = bkl_lvl;
- return;
+ mfd->unset_bl_level = bkl_lvl;
+ return;
} else {
mfd->unset_bl_level = 0;
}
@@ -1972,7 +1969,8 @@
return -EINVAL;
mfd = (struct msm_fb_data_type *)info->par;
mdss_fb_power_setting_idle(mfd);
- if ((cmd != MSMFB_VSYNC_CTRL) && (cmd != MSMFB_OVERLAY_VSYNC_CTRL))
+ if ((cmd != MSMFB_VSYNC_CTRL) && (cmd != MSMFB_OVERLAY_VSYNC_CTRL) &&
+ (cmd != MSMFB_ASYNC_BLIT) && (cmd != MSMFB_BLIT))
mdss_fb_pan_idle(mfd);
switch (cmd) {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index cf0c287..5174cab 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -16,6 +16,13 @@
#include "mdss_hdmi_edid.h"
#define DBC_START_OFFSET 4
+
+/*
+ * As per CEA-861-E specification 7.5.2, there can be
+ * upto 31 bytes following any tag (data block type).
+ */
+#define MAX_DATA_BLOCK_SIZE 31
+
#define HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd) \
(!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
@@ -32,6 +39,19 @@
/* Support for first 5 EDID blocks */
#define MAX_EDID_BLOCK_SIZE (0x80 * 5)
+#define BUFF_SIZE_3D 128
+
+enum data_block_types {
+ RESERVED,
+ AUDIO_DATA_BLOCK,
+ VIDEO_DATA_BLOCK,
+ VENDOR_SPECIFIC_DATA_BLOCK,
+ SPEAKER_ALLOCATION_DATA_BLOCK,
+ VESA_DTC_DATA_BLOCK,
+ RESERVED2,
+ USE_EXTENDED_TAG
+};
+
struct hdmi_edid_sink_data {
u32 disp_mode_list[HDMI_VFRMT_MAX];
u32 disp_3d_mode_list[HDMI_VFRMT_MAX];
@@ -524,7 +544,8 @@
}
/* A Tage code of 7 identifies extended data blocks */
- etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+ etag = hdmi_edid_find_block(in_buf, start_offset, USE_EXTENDED_TAG,
+ &len);
while (etag != NULL) {
/* The extended data block should at least be 2 bytes long */
@@ -570,7 +591,8 @@
/* There could be more that one extended data block */
start_offset = etag - in_buf + len + 1;
- etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+ etag = hdmi_edid_find_block(in_buf, start_offset,
+ USE_EXTENDED_TAG, &len);
}
} /* hdmi_edid_extract_extended_data_blocks */
@@ -585,11 +607,12 @@
return;
}
- vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
+ vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+ VENDOR_SPECIFIC_DATA_BLOCK, &len);
edid_ctrl->present_3d = 0;
- if (vsd == NULL || len < 9) {
- DEV_DBG("%s: blk-id 3 not found or not long enough\n",
+ if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
+ DEV_DBG("%s: No/Invalid vendor Specific Data Block\n",
__func__);
return;
}
@@ -616,9 +639,13 @@
return;
}
- adb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 1, &len);
- if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE))
+ adb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, AUDIO_DATA_BLOCK,
+ &len);
+ if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE)) {
+ DEV_DBG("%s: No/Invalid Audio Data Block\n",
+ __func__);
return;
+ }
memcpy(edid_ctrl->audio_data_block, adb + 1, len);
edid_ctrl->adb_size = len;
@@ -644,9 +671,13 @@
return;
}
- sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 4, &len);
- if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE))
+ sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+ SPEAKER_ALLOCATION_DATA_BLOCK, &len);
+ if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) {
+ DEV_DBG("%s: No/Invalid Speaker Allocation Data Block\n",
+ __func__);
return;
+ }
memcpy(edid_ctrl->spkr_alloc_data_block, sadb + 1, len);
edid_ctrl->sadb_size = len;
@@ -673,9 +704,11 @@
return;
}
- vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
+ vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+ VENDOR_SPECIFIC_DATA_BLOCK, &len);
- if (vsd == NULL || len < 12 || !(vsd[8] & BIT(7))) {
+ if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE ||
+ !(vsd[8] & BIT(7))) {
edid_ctrl->video_latency = (u16)-1;
edid_ctrl->audio_latency = (u16)-1;
DEV_DBG("%s: EDID: No audio/video latency present\n", __func__);
@@ -699,9 +732,14 @@
return 0;
}
- vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
- if (vsd == NULL || len < 8)
+ vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+ VENDOR_SPECIFIC_DATA_BLOCK, &len);
+
+ if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
+ DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
+ __func__);
return 0;
+ }
DEV_DBG("%s: EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n", __func__,
((u32)vsd[4] << 8) + (u32)vsd[5], (u32)vsd[7] * 5);
@@ -898,11 +936,14 @@
u16 structure_all, structure_mask;
const u8 *vsd = num_of_cea_blocks ?
hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
- 3, &len) : NULL;
+ VENDOR_SPECIFIC_DATA_BLOCK, &len) : NULL;
int i;
- if (!vsd)
+ if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
+ DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
+ __func__);
return -ENXIO;
+ }
offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
if (offset >= len - 1)
@@ -1044,10 +1085,11 @@
return;
}
- vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &db_len);
+ vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+ VENDOR_SPECIFIC_DATA_BLOCK, &db_len);
- if (vsd == NULL || db_len < 9) {
- DEV_DBG("%s: blk-id 3 not found or not long enough\n",
+ if (vsd == NULL || db_len == 0 || db_len > MAX_DATA_BLOCK_SIZE) {
+ DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
__func__);
return;
}
@@ -1097,8 +1139,14 @@
edid_blk0 = &data_buf[0x0];
edid_blk1 = &data_buf[0x80];
svd = num_of_cea_blocks ?
- hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, 2,
- &len) : NULL;
+ hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
+ VIDEO_DATA_BLOCK, &len) : NULL;
+
+ if (svd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
+ DEV_DBG("%s: No/Invalid Video Data Block\n",
+ __func__);
+ return;
+ }
sink_data = &edid_ctrl->sink_data;
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index d8dc6ca..a9667a4 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -374,7 +374,6 @@
struct mdss_mdp_writeback_arg {
struct mdss_mdp_data *data;
- void (*callback_fnc) (void *arg);
void *priv_data;
};
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 7c79ceb..8f7905a 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -294,6 +294,7 @@
struct mdss_mdp_video_ctx *ctx;
struct mdss_mdp_vsync_handler *tmp, *handle;
int rc;
+ u32 frame_rate = 0;
pr_debug("stop ctl=%d\n", ctl->num);
@@ -313,6 +314,14 @@
WARN(rc, "intf %d blank error (%d)\n", ctl->intf_num, rc);
mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
+ /* wait for at least one VSYNC on HDMI intf for proper TG OFF */
+ if (MDSS_INTF_HDMI == ctx->intf_type) {
+ frame_rate = mdss_panel_get_framerate
+ (&(ctl->panel_data->panel_info));
+ if (!(frame_rate >= 24 && frame_rate <= 240))
+ frame_rate = 24;
+ msleep((1000/frame_rate) + 1);
+ }
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ctx->timegen_en = false;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 3929501..ff55c57 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -46,8 +46,6 @@
struct mdss_mdp_plane_sizes dst_planes;
- void (*callback_fnc) (void *arg);
- void *callback_arg;
spinlock_t wb_lock;
struct list_head vsync_handlers;
};
@@ -365,6 +363,8 @@
mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
NULL, NULL);
+ complete_all(&ctx->wb_comp);
+
ctl->priv_data = NULL;
ctx->ref_cnt--;
}
@@ -389,9 +389,6 @@
mdss_mdp_irq_disable_nosync(ctx->intr_type, ctx->intf_num);
- if (ctx->callback_fnc)
- ctx->callback_fnc(ctx->callback_arg);
-
spin_lock(&ctx->wb_lock);
list_for_each_entry(tmp, &ctx->vsync_handlers, list) {
tmp->vsync_handler(ctl, vsync_time);
@@ -467,9 +464,6 @@
mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
mdss_mdp_writeback_intr_done, ctl);
- ctx->callback_fnc = wb_args->callback_fnc;
- ctx->callback_arg = wb_args->priv_data;
-
flush_bits = BIT(16); /* WB */
mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_ADDR_SW_STATUS, ctl->is_secure);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, flush_bits);
@@ -529,6 +523,8 @@
int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
{
+ int ret = 0;
+
if (ctl->shared_lock && !mutex_is_locked(ctl->shared_lock)) {
pr_err("shared mutex is not locked before commit on ctl=%d\n",
ctl->num);
@@ -542,5 +538,10 @@
ctl->mixer_right->params_changed++;
}
- return mdss_mdp_display_commit(ctl, arg);
+ ret = mdss_mdp_display_commit(ctl, arg);
+
+ if (!IS_ERR_VALUE(ret))
+ mdss_mdp_display_wait4comp(ctl);
+
+ return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 1d172f3..057914b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -137,7 +137,6 @@
{
int ret;
struct mdss_mdp_writeback_arg wb_args = {
- .callback_fnc = NULL,
.data = dst_data,
.priv_data = rot,
};
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 58acb8e..c4e1956 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -476,23 +476,13 @@
return ret;
}
-static void mdss_mdp_wb_callback(void *arg)
-{
- if (arg)
- complete((struct completion *) arg);
-}
-
int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd)
{
struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_mdp_wb_data *node = NULL;
int ret = 0;
- DECLARE_COMPLETION_ONSTACK(comp);
- struct mdss_mdp_writeback_arg wb_args = {
- .callback_fnc = mdss_mdp_wb_callback,
- .priv_data = &comp,
- };
+ struct mdss_mdp_writeback_arg wb_args;
if (!ctl->power_on)
return 0;
@@ -534,12 +524,6 @@
goto kickoff_fail;
}
- ret = wait_for_completion_timeout(&comp, KOFF_TIMEOUT);
- if (ret == 0)
- WARN(1, "wfd kick off time out=%d ctl=%d", ret, ctl->num);
- else
- ret = 0;
-
if (wb && node) {
mutex_lock(&wb->lock);
list_add_tail(&node->active_entry, &wb->busy_queue);
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index a759e86..ab01566 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -1463,7 +1463,7 @@
static struct regulator *reg_8941_l02;
static struct regulator *reg_8941_smps3a;
static struct regulator *reg_8941_vdda;
- int rc;
+ int rc = -EINVAL;
pr_debug("%s\n", __func__);
if (!reg_8941_l24) {
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index fed2e0a..4a606af 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -442,6 +442,11 @@
snd_soc_dapm_siggen, /* signal generator */
};
+enum snd_soc_dapm_subclass {
+ SND_SOC_DAPM_CLASS_INIT = 0,
+ SND_SOC_DAPM_CLASS_PCM = 1,
+};
+
/*
* DAPM audio route definition.
*
diff --git a/mm/page_io.c b/mm/page_io.c
index dc76b4d..e60e43f 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -1,3 +1,4 @@
+
/*
* linux/mm/page_io.c
*
@@ -18,6 +19,7 @@
#include <linux/bio.h>
#include <linux/swapops.h>
#include <linux/writeback.h>
+#include <linux/blkdev.h>
#include <asm/pgtable.h>
static struct bio *get_swap_bio(gfp_t gfp_flags,
@@ -78,9 +80,54 @@
imajor(bio->bi_bdev->bd_inode),
iminor(bio->bi_bdev->bd_inode),
(unsigned long long)bio->bi_sector);
- } else {
- SetPageUptodate(page);
+ goto out;
}
+
+ SetPageUptodate(page);
+
+ /*
+ * There is no guarantee that the page is in swap cache - the software
+ * suspend code (at least) uses end_swap_bio_read() against a non-
+ * swapcache page. So we must check PG_swapcache before proceeding with
+ * this optimization.
+ */
+ if (likely(PageSwapCache(page))) {
+ struct swap_info_struct *sis;
+
+ sis = page_swap_info(page);
+ if (sis->flags & SWP_BLKDEV) {
+ /*
+ * The swap subsystem performs lazy swap slot freeing,
+ * expecting that the page will be swapped out again.
+ * So we can avoid an unnecessary write if the page
+ * isn't redirtied.
+ * This is good for real swap storage because we can
+ * reduce unnecessary I/O and enhance wear-leveling
+ * if an SSD is used as the as swap device.
+ * But if in-memory swap device (eg zram) is used,
+ * this causes a duplicated copy between uncompressed
+ * data in VM-owned memory and compressed data in
+ * zram-owned memory. So let's free zram-owned memory
+ * and make the VM-owned decompressed page *dirty*,
+ * so the page should be swapped out somewhere again if
+ * we again wish to reclaim it.
+ */
+ struct gendisk *disk = sis->bdev->bd_disk;
+ if (disk->fops->swap_slot_free_notify) {
+ swp_entry_t entry;
+ unsigned long offset;
+
+ entry.val = page_private(page);
+ offset = swp_offset(entry);
+
+ SetPageDirty(page);
+ disk->fops->swap_slot_free_notify(sis->bdev,
+ offset);
+ }
+ }
+ }
+
+out:
unlock_page(page);
bio_put(bio);
}
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index da99254..aaa132e 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -3154,13 +3154,27 @@
struct snd_soc_dai *dai)
{
struct wcd9xxx *tapan_core = dev_get_drvdata(dai->codec->dev->parent);
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(dai->codec);
+ u32 active = 0;
+
dev_dbg(dai->codec->dev, "%s(): substream = %s stream = %d\n",
__func__, substream->name, substream->stream);
+
+ if (dai->id <= NUM_CODEC_DAIS) {
+ if (tapan->dai[dai->id].ch_mask) {
+ active = 1;
+ dev_dbg(dai->codec->dev, "%s(): Codec DAI: chmask[%d] = 0x%lx\n",
+ __func__, dai->id,
+ tapan->dai[dai->id].ch_mask);
+ }
+ }
if ((tapan_core != NULL) &&
(tapan_core->dev != NULL) &&
- (tapan_core->dev->parent != NULL)) {
+ (tapan_core->dev->parent != NULL) &&
+ (active == 0)) {
pm_runtime_mark_last_busy(tapan_core->dev->parent);
pm_runtime_put(tapan_core->dev->parent);
+ dev_dbg(dai->codec->dev, "%s: unvote requested", __func__);
}
}
@@ -3920,6 +3934,13 @@
dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
__func__, ret);
}
+ if ((core != NULL) &&
+ (core->dev != NULL) &&
+ (core->dev->parent != NULL)) {
+ pm_runtime_mark_last_busy(core->dev->parent);
+ pm_runtime_put(core->dev->parent);
+ dev_dbg(codec->dev, "%s: unvote requested", __func__);
+ }
break;
}
return ret;
@@ -3967,6 +3988,13 @@
dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
__func__, ret);
}
+ if ((core != NULL) &&
+ (core->dev != NULL) &&
+ (core->dev->parent != NULL)) {
+ pm_runtime_mark_last_busy(core->dev->parent);
+ pm_runtime_put(core->dev->parent);
+ dev_dbg(codec->dev, "%s: unvote requested", __func__);
+ }
break;
}
return ret;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 673b634..725c51f 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -1235,49 +1235,49 @@
SOC_SINGLE_TLV("HPHR Volume", TABLA_A_RX_HPH_R_GAIN, 0, 12, 1,
line_gain),
- SOC_SINGLE_S8_TLV("RX1 Digital Volume", TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
- -84, 40, digital_gain),
- SOC_SINGLE_S8_TLV("RX2 Digital Volume", TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
- -84, 40, digital_gain),
- SOC_SINGLE_S8_TLV("RX3 Digital Volume", TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
- -84, 40, digital_gain),
- SOC_SINGLE_S8_TLV("RX4 Digital Volume", TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
- -84, 40, digital_gain),
- SOC_SINGLE_S8_TLV("RX5 Digital Volume", TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
- -84, 40, digital_gain),
- SOC_SINGLE_S8_TLV("RX6 Digital Volume", TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
- -84, 40, digital_gain),
- SOC_SINGLE_S8_TLV("RX7 Digital Volume", TABLA_A_CDC_RX7_VOL_CTL_B2_CTL,
- -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX1 Digital Volume", TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX2 Digital Volume", TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX3 Digital Volume", TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX4 Digital Volume", TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX5 Digital Volume", TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX6 Digital Volume", TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX7 Digital Volume", TABLA_A_CDC_RX7_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
- SOC_SINGLE_S8_TLV("DEC1 Volume", TABLA_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC2 Volume", TABLA_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC3 Volume", TABLA_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC4 Volume", TABLA_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC5 Volume", TABLA_A_CDC_TX5_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC6 Volume", TABLA_A_CDC_TX6_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC7 Volume", TABLA_A_CDC_TX7_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC8 Volume", TABLA_A_CDC_TX8_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC9 Volume", TABLA_A_CDC_TX9_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC10 Volume", TABLA_A_CDC_TX10_VOL_CTL_GAIN, -84,
+ SOC_SINGLE_SX_TLV("DEC1 Volume", TABLA_A_CDC_TX1_VOL_CTL_GAIN, 0, -84,
40, digital_gain),
- SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TABLA_A_CDC_IIR1_GAIN_B1_CTL, -84,
+ SOC_SINGLE_SX_TLV("DEC2 Volume", TABLA_A_CDC_TX2_VOL_CTL_GAIN, 0, -84,
40, digital_gain),
- SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TABLA_A_CDC_IIR1_GAIN_B2_CTL, -84,
+ SOC_SINGLE_SX_TLV("DEC3 Volume", TABLA_A_CDC_TX3_VOL_CTL_GAIN, 0, -84,
40, digital_gain),
- SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TABLA_A_CDC_IIR1_GAIN_B3_CTL, -84,
+ SOC_SINGLE_SX_TLV("DEC4 Volume", TABLA_A_CDC_TX4_VOL_CTL_GAIN, 0, -84,
40, digital_gain),
- SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TABLA_A_CDC_IIR1_GAIN_B4_CTL, -84,
+ SOC_SINGLE_SX_TLV("DEC5 Volume", TABLA_A_CDC_TX5_VOL_CTL_GAIN, 0, -84,
40, digital_gain),
+ SOC_SINGLE_SX_TLV("DEC6 Volume", TABLA_A_CDC_TX6_VOL_CTL_GAIN, 0, -84,
+ 40, digital_gain),
+ SOC_SINGLE_SX_TLV("DEC7 Volume", TABLA_A_CDC_TX7_VOL_CTL_GAIN, 0, -84,
+ 40, digital_gain),
+ SOC_SINGLE_SX_TLV("DEC8 Volume", TABLA_A_CDC_TX8_VOL_CTL_GAIN, 0, -84,
+ 40, digital_gain),
+ SOC_SINGLE_SX_TLV("DEC9 Volume", TABLA_A_CDC_TX9_VOL_CTL_GAIN, 0, -84,
+ 40, digital_gain),
+ SOC_SINGLE_SX_TLV("DEC10 Volume", TABLA_A_CDC_TX10_VOL_CTL_GAIN, 0,
+ -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", TABLA_A_CDC_IIR1_GAIN_B1_CTL, 0,
+ -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", TABLA_A_CDC_IIR1_GAIN_B2_CTL, 0,
+ -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", TABLA_A_CDC_IIR1_GAIN_B3_CTL, 0,
+ -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP4 Volume", TABLA_A_CDC_IIR1_GAIN_B4_CTL, 0,
+ -84, 40, digital_gain),
SOC_SINGLE_TLV("ADC1 Volume", TABLA_A_TX_1_2_EN, 5, 3, 0, analog_gain),
SOC_SINGLE_TLV("ADC2 Volume", TABLA_A_TX_1_2_EN, 1, 3, 0, analog_gain),
SOC_SINGLE_TLV("ADC3 Volume", TABLA_A_TX_3_4_EN, 5, 3, 0, analog_gain),
@@ -2155,7 +2155,7 @@
goto err;
}
rtn:
- snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
mutex_unlock(&codec->mutex);
return 0;
err:
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index d726af2..ec99c5f 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -1302,6 +1302,7 @@
const struct wcd9xxx_mbhc_plug_type_cfg *plug_type =
WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
s16 hs_max, no_mic, dce_z;
+ int highhph_cnt = 0;
pr_debug("%s: enter\n", __func__);
pr_debug("%s: event_state 0x%lx\n", __func__, event_state);
@@ -1326,9 +1327,10 @@
d->_vdces = vdce;
if (d->_vdces < no_mic)
d->_type = PLUG_TYPE_HEADPHONE;
- else if (d->_vdces >= hs_max)
+ else if (d->_vdces >= hs_max) {
d->_type = PLUG_TYPE_HIGH_HPH;
- else
+ highhph_cnt++;
+ } else
d->_type = PLUG_TYPE_HEADSET;
pr_debug("%s: DCE #%d, %04x, V %04d(%04d), HPHL %d TYPE %d\n",
@@ -1363,7 +1365,8 @@
goto exit;
}
- delta_thr = highhph ? WCD9XXX_MB_MEAS_DELTA_MAX_MV :
+ delta_thr = ((highhph_cnt == sz) || highhph) ?
+ WCD9XXX_MB_MEAS_DELTA_MAX_MV :
WCD9XXX_CS_MEAS_DELTA_MAX_MV;
for (i = 0, d = dt; i < sz; i++, d++) {
@@ -2855,6 +2858,10 @@
if (wcd9xxx_cancel_btn_work(mbhc))
pr_debug("%s: button press is canceled\n", __func__);
+ /* cancel detect plug */
+ wcd9xxx_cancel_hs_detect_plug(mbhc,
+ &mbhc->correct_plug_swch);
+
insert = !wcd9xxx_swch_level_remove(mbhc);
pr_debug("%s: Current plug type %d, insert %d\n", __func__,
mbhc->current_plug, insert);
@@ -2862,9 +2869,6 @@
mbhc->lpi_enabled = false;
wmb();
- /* cancel detect plug */
- wcd9xxx_cancel_hs_detect_plug(mbhc,
- &mbhc->correct_plug_swch);
if ((mbhc->current_plug != PLUG_TYPE_NONE) &&
!(snd_soc_read(codec, WCD9XXX_A_MBHC_INSERT_DETECT) &
(1 << 1)))
@@ -2879,10 +2883,6 @@
mbhc->lpi_enabled = false;
wmb();
- /* cancel detect plug */
- wcd9xxx_cancel_hs_detect_plug(mbhc,
- &mbhc->correct_plug_swch);
-
if (mbhc->current_plug == PLUG_TYPE_HEADPHONE) {
wcd9xxx_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
is_removed = true;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index d7ddca2..7f8736c 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -58,16 +58,9 @@
#define LO_2_SPK_AMP 0x4
#define LO_4_SPK_AMP 0x8
-#define LPAIF_OFFSET 0xFE000000
-#define LPAIF_PRI_MODE_MUXSEL (LPAIF_OFFSET + 0x2B000)
-#define LPAIF_SEC_MODE_MUXSEL (LPAIF_OFFSET + 0x2C000)
-#define LPAIF_TER_MODE_MUXSEL (LPAIF_OFFSET + 0x2D000)
-#define LPAIF_QUAD_MODE_MUXSEL (LPAIF_OFFSET + 0x2E000)
-
#define I2S_PCM_SEL 1
#define I2S_PCM_SEL_OFFSET 1
-
#define WCD9XXX_MBHC_DEF_BUTTONS 8
#define WCD9XXX_MBHC_DEF_RLOADS 5
#define TAIKO_EXT_CLK_RATE 9600000
@@ -146,6 +139,7 @@
struct msm_auxpcm_ctrl {
struct msm_auxpcm_gpio *pin_data;
u32 cnt;
+ void __iomem *mux;
};
struct msm8974_asoc_mach_data {
@@ -173,9 +167,6 @@
{"SEC_AUXPCM_DOUT", "qcom,sec-auxpcm-gpio-dout"},
};
-void *lpaif_pri_muxsel_virt_addr;
-void *lpaif_sec_muxsel_virt_addr;
-
struct msm8974_liquid_dock_dev {
int dock_plug_gpio;
int dock_plug_irq;
@@ -1192,12 +1183,14 @@
goto err;
}
if (atomic_inc_return(&prim_auxpcm_rsc_ref) == 1) {
- if (lpaif_pri_muxsel_virt_addr != NULL)
+ if (auxpcm_ctrl->mux != NULL) {
iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
- lpaif_pri_muxsel_virt_addr);
- else
- pr_err("%s lpaif_pri_muxsel_virt_addr is NULL\n",
- __func__);
+ auxpcm_ctrl->mux);
+ } else {
+ pr_err("%s: Pri AUXPCM MUX addr is NULL\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
}
if (ret < 0) {
@@ -1247,12 +1240,14 @@
goto err;
}
if (atomic_inc_return(&sec_auxpcm_rsc_ref) == 1) {
- if (lpaif_sec_muxsel_virt_addr != NULL)
+ if (auxpcm_ctrl->mux != NULL) {
iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
- lpaif_sec_muxsel_virt_addr);
- else
- pr_err("%s lpaif_sec_muxsel_virt_addr is NULL\n",
- __func__);
+ auxpcm_ctrl->mux);
+ } else {
+ pr_err("%s Sec AUXPCM MUX addr is NULL\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
}
if (ret < 0) {
@@ -2667,6 +2662,8 @@
int ret;
const char *auxpcm_pri_gpio_set = NULL;
const char *prop_name_ult_lo_gpio = "qcom,ext-ult-lo-amp-gpio";
+ struct resource *pri_muxsel;
+ struct resource *sec_muxsel;
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "No platform supplied from device tree\n");
@@ -2794,7 +2791,6 @@
}
}
-
pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,us-euro-gpios", 0);
if (pdata->us_euro_gpio < 0) {
@@ -2821,28 +2817,49 @@
goto err1;
}
if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-prim")) {
- lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
+ pri_muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "lpaif_pri_mode_muxsel");
} else if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-tert")) {
- lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_TER_MODE_MUXSEL, 4);
+ pri_muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "lpaif_tert_mode_muxsel");
} else {
dev_err(&pdev->dev, "Invalid value %s for AUXPCM GPIO set\n",
auxpcm_pri_gpio_set);
ret = -EINVAL;
goto err1;
}
- if (lpaif_pri_muxsel_virt_addr == NULL) {
- pr_err("%s Pri muxsel virt addr is null\n", __func__);
- ret = -EINVAL;
- goto err1;
+ if (!pri_muxsel) {
+ dev_err(&pdev->dev, "MUX addr invalid for primary AUXPCM\n");
+ ret = -ENODEV;
+ goto err1;
+ } else {
+ pdata->pri_auxpcm_ctrl->mux = ioremap(pri_muxsel->start,
+ resource_size(pri_muxsel));
+ if (pdata->pri_auxpcm_ctrl->mux == NULL) {
+ pr_err("%s Pri muxsel virt addr is null\n", __func__);
+ ret = -EINVAL;
+ goto err1;
+ }
}
- lpaif_sec_muxsel_virt_addr = ioremap(LPAIF_SEC_MODE_MUXSEL, 4);
- if (lpaif_sec_muxsel_virt_addr == NULL) {
+
+ sec_muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "lpaif_sec_mode_muxsel");
+ if (!sec_muxsel) {
+ dev_err(&pdev->dev, "MUX addr invalid for secondary AUXPCM\n");
+ ret = -ENODEV;
+ goto err2;
+ }
+ pdata->sec_auxpcm_ctrl->mux = ioremap(sec_muxsel->start,
+ resource_size(sec_muxsel));
+ if (pdata->sec_auxpcm_ctrl->mux == NULL) {
pr_err("%s Sec muxsel virt addr is null\n", __func__);
ret = -EINVAL;
- goto err1;
+ goto err2;
}
return 0;
+err2:
+ iounmap(pdata->pri_auxpcm_ctrl->mux);
err1:
if (ext_ult_lo_amp_gpio >= 0)
gpio_free(ext_ult_lo_amp_gpio);
@@ -2896,8 +2913,8 @@
msm8974_liquid_dock_dev = NULL;
}
- iounmap(lpaif_pri_muxsel_virt_addr);
- iounmap(lpaif_sec_muxsel_virt_addr);
+ iounmap(pdata->pri_auxpcm_ctrl->mux);
+ iounmap(pdata->sec_auxpcm_ctrl->mux);
snd_soc_unregister_card(card);
return 0;
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index 93b3597..4a25606 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -879,6 +879,15 @@
pr_debug("%s\n", __func__);
+ audio_ocmem_lcl.audio_hdl = ocmem_notifier_register(OCMEM_LP_AUDIO,
+ &audio_ocmem_client_nb);
+ if (PTR_RET(audio_ocmem_lcl.audio_hdl) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ else if (!audio_ocmem_lcl.audio_hdl) {
+ pr_err("%s: Failed to get ocmem handle %d\n", __func__,
+ OCMEM_LP_AUDIO);
+ return -ENODEV;
+ }
subsys_notif_register_notifier("adsp", &anb);
audio_ocmem_lcl.ocmem_dump_addr =
@@ -944,12 +953,6 @@
ret = -EFAULT;
goto destroy_voice_wq;
}
- audio_ocmem_lcl.audio_hdl = ocmem_notifier_register(OCMEM_LP_AUDIO,
- &audio_ocmem_client_nb);
- if (audio_ocmem_lcl.audio_hdl == NULL) {
- pr_err("%s: Failed to get ocmem handle %d\n", __func__,
- OCMEM_LP_AUDIO);
- }
audio_ocmem_lcl.lp_memseg_ptr = NULL;
return 0;
destroy_voice_wq:
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 55f8dc8..f3f9725 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3229,7 +3229,7 @@
mutex_init(&card->mutex);
mutex_init(&card->dpcm_mutex);
mutex_init(&card->dapm_power_mutex);
-
+ mutex_init(&card->dapm_mutex);
ret = snd_soc_instantiate_card(card);
if (ret != 0) {
soc_cleanup_card_debugfs(card);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 99047178..bc3f6a7 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1866,7 +1866,7 @@
#endif
/* test and update the power status of a mux widget */
-int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int change,
int mux, struct soc_enum *e)
{
@@ -1915,10 +1915,22 @@
return 0;
}
+
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int change,
+ int mux, struct soc_enum *e)
+{
+ struct snd_soc_card *card = widget->dapm->card;
+ int ret;
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ ret = soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ mutex_unlock(&card->dapm_mutex);
+ return ret;
+}
EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
/* test and update the power status of a mixer or switch widget */
-int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int connect)
{
struct snd_soc_dapm_path *path;
@@ -1952,6 +1964,17 @@
return 0;
}
+
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int connect)
+{
+ struct snd_soc_card *card = widget->dapm->card;
+ int ret;
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ ret = soc_dapm_mixer_update_power(widget, kcontrol, connect);
+ mutex_unlock(&card->dapm_mutex);
+ return ret;
+}
EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
/* show dapm widget status in sys fs */
@@ -2108,6 +2131,8 @@
*/
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
{
+ int ret;
+
/*
* Suppress early reports (eg, jacks syncing their state) to avoid
* silly DAPM runs during card startup.
@@ -2115,7 +2140,10 @@
if (!dapm->card || !dapm->card->instantiated)
return 0;
- return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
+ ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
+ mutex_unlock(&dapm->card->dapm_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
@@ -2279,6 +2307,7 @@
{
int i, ret;
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
ret = snd_soc_dapm_add_route(dapm, route);
if (ret < 0) {
@@ -2288,6 +2317,7 @@
}
route++;
}
+ mutex_unlock(&dapm->card->dapm_mutex);
return 0;
}
@@ -2360,12 +2390,14 @@
int i, err;
int ret = 0;
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
err = snd_soc_dapm_weak_route(dapm, route);
if (err)
ret = err;
route++;
}
+ mutex_unlock(&dapm->card->dapm_mutex);
return ret;
}
@@ -2384,6 +2416,8 @@
struct snd_soc_dapm_widget *w;
unsigned int val;
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
+
list_for_each_entry(w, &dapm->card->widgets, list)
{
if (w->new)
@@ -2393,8 +2427,10 @@
w->kcontrols = kzalloc(w->num_kcontrols *
sizeof(struct snd_kcontrol *),
GFP_KERNEL);
- if (!w->kcontrols)
+ if (!w->kcontrols) {
+ mutex_unlock(&dapm->card->dapm_mutex);
return -ENOMEM;
+ }
}
switch(w->id) {
@@ -2434,6 +2470,7 @@
}
dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
+ mutex_unlock(&dapm->card->dapm_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
@@ -2493,6 +2530,7 @@
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
struct snd_soc_codec *codec = widget->codec;
+ struct snd_soc_card *card = codec->card;
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
@@ -2519,7 +2557,7 @@
/* old connection must be powered down */
connect = invert ? 1 : 0;
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
change = snd_soc_test_bits(widget->codec, reg, mask, val);
if (change) {
@@ -2535,13 +2573,13 @@
update.val = val;
widget->dapm->update = &update;
- snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
+ soc_dapm_mixer_update_power(widget, kcontrol, connect);
widget->dapm->update = NULL;
}
}
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
@@ -2590,6 +2628,7 @@
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
struct snd_soc_codec *codec = widget->codec;
+ struct snd_soc_card *card = codec->card;
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int val, mux, change;
unsigned int mask, bitmask;
@@ -2610,7 +2649,7 @@
mask |= (bitmask - 1) << e->shift_r;
}
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
if (change) {
@@ -2626,13 +2665,13 @@
update.val = val;
widget->dapm->update = &update;
- snd_soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
widget->dapm->update = NULL;
}
}
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return change;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
@@ -2669,6 +2708,7 @@
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
struct snd_soc_codec *codec = widget->codec;
+ struct snd_soc_card *card = codec->card;
struct soc_enum *e =
(struct soc_enum *)kcontrol->private_value;
int change;
@@ -2678,7 +2718,7 @@
if (ucontrol->value.enumerated.item[0] >= e->max)
return -EINVAL;
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
change = widget->value != ucontrol->value.enumerated.item[0];
if (change) {
@@ -2687,12 +2727,12 @@
widget->value = ucontrol->value.enumerated.item[0];
- snd_soc_dapm_mux_update_power(widget, kcontrol, change,
+ soc_dapm_mux_update_power(widget, kcontrol, change,
widget->value, e);
}
}
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
@@ -2757,6 +2797,7 @@
struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_widget *widget = wlist->widgets[0];
struct snd_soc_codec *codec = widget->codec;
+ struct snd_soc_card *card = codec->card;
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int val, mux, change;
unsigned int mask;
@@ -2775,7 +2816,7 @@
mask |= e->mask << e->shift_r;
}
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
if (change) {
@@ -2791,13 +2832,13 @@
update.val = val;
widget->dapm->update = &update;
- snd_soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
widget->dapm->update = NULL;
}
}
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return change;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
@@ -2831,15 +2872,15 @@
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
ucontrol->value.integer.value[0] =
- snd_soc_dapm_get_pin_status(&codec->dapm, pin);
+ snd_soc_dapm_get_pin_status(&card->dapm, pin);
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->dapm_mutex);
return 0;
}
@@ -2854,20 +2895,19 @@
int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&codec->mutex);
+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
if (ucontrol->value.integer.value[0])
- snd_soc_dapm_enable_pin(&codec->dapm, pin);
+ snd_soc_dapm_enable_pin(&card->dapm, pin);
else
- snd_soc_dapm_disable_pin(&codec->dapm, pin);
+ snd_soc_dapm_disable_pin(&card->dapm, pin);
- snd_soc_dapm_sync(&codec->dapm);
+ mutex_unlock(&card->dapm_mutex);
- mutex_unlock(&codec->mutex);
-
+ snd_soc_dapm_sync(&card->dapm);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
@@ -2975,6 +3015,7 @@
{
int i, ret;
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
ret = snd_soc_dapm_new_control(dapm, widget);
if (ret < 0) {
@@ -2985,6 +3026,7 @@
}
widget++;
}
+ mutex_unlock(&dapm->card->dapm_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
@@ -3099,7 +3141,6 @@
mutex_lock(&codec->mutex);
soc_dapm_stream_event(&codec->dapm, stream, event);
mutex_unlock(&codec->mutex);
-
return 0;
}