Merge "ASoC: msm: qdsp6v2: Wait for stream to be available in gapless playback"
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
index 01cc798..2ae9821 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
@@ -16,6 +16,12 @@
Optional properties:
- qcom,ce-hw-shared : optional, indicates if the hardware is shared between EE.
- qcom,ce-hw-key : optional, indicates if the hardware supports use of HW KEY.
+ - qcom,use-sw-aes-cbc-ecb-ctr-algo : optional, indicates if use SW aes-cbc/ecb/ctr algorithm.
+ - qcom,use-sw-aes-xts-algo : optional, indicates if use SW aes-xts algorithm.
+ - qcom,use-sw-aead-algo : optional, indicates if use SW aead algorithm.
+ - qcom,use-sw-ahash-algo : optional, indicates if use SW hash algorithm.
+ - qcom,use-sw-hmac-algo : optional, indicates if use SW hmac algorithm.
+ - qcom,use-sw-aes-ccm-algo : optional, indicates if use SW aes-ccm algorithm.
Example:
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 191db07..8174d1b 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -117,6 +117,39 @@
- "edp"
- "hdmi"
+Bus Scaling Data:
+- qcom,msm-bus,name: String property describing MDSS client.
+- qcom,msm-bus,num-cases: This is the the number of Bus Scaling use cases
+ defined in the vectors property. This must be
+ set to <3> for MDSS driver where use-case 0 is
+ used to take off MDSS BW votes from the system.
+ And use-case 1 & 2 are used in ping-pong fashion
+ to generate run-time BW requests.
+- qcom,msm-bus,active-only: A boolean flag indicating if it is active only.
+- qcom,msm-bus,num-paths: This represents the number of paths in each
+ Bus Scaling Usecase. This value depends on
+ how many number of AXI master ports are
+ dedicated to MDSS for particular chipset.
+- qcom,msm-bus,vectors-KBps: * A series of 4 cell properties, with a format
+ of (src, dst, ab, ib) which is defined at
+ Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+ * Current values of src & dst are defined at
+ arch/arm/mach-msm/msm_bus_board.h
+ src values allowed for MDSS are:
+ 22 = MSM_BUS_MASTER_MDP_PORT0
+ 23 = MSM_BUS_MASTER_MDP_PORT1
+ dst values allowed for MDSS are:
+ 512 = MSM_BUS_SLAVE_EBI_CH0
+ ab: Represents aggregated bandwidth.
+ ib: Represents instantaneous bandwidth.
+ * Total number of 4 cell properties will be
+ (number of use-cases * number of paths).
+ * These values will be overridden by the driver
+ based on the run-time requirements. So initial
+ ab and ib values defined here are random and
+ bare no logic except for the use-case 0 where ab
+ and ib values needs to be 0.
+
Optional properties:
- vdd-cx-supply : Phandle for vdd CX regulator device node.
- batfet-supply : Phandle for battery FET regulator device node.
@@ -170,6 +203,30 @@
applied in scenarios where panel interface can
be more tolerant to memory latency such as
command mode panels.
+
+Fudge Factors: Fudge factors are used to boost demand for
+ resources like bus bandswidth, clk rate etc. to
+ overcome system inefficiencies and avoid any
+ glitches. These fudge factors are expressed in
+ terms of numerator and denominator. First value
+ is numerator followed by denominator. They all
+ are optional but highly recommended.
+ Ex:
+ x = value to be fudged
+ a = numerator, default value is 1
+ b = denominator, default value is 1
+ FUDGE(x, a, b) = ((x * a) / b)
+- qcom,mdss-ib-factor: This fudge factor is applied to calculated ib
+ values in default conditions.
+- qcom,mdss-high-ib-factor: This fudge factor is applied to calculated ib
+ values. Use of this factor is determined by the
+ driver and open new use-cases.
+- qcom,mdss-clk-factor: This fudge factor is applied to calculated mdp
+ clk rate in default conditions.
+- qcom,mdss-highest-bank-bit: Property to indicate tile format as opposed to usual
+ linear format. The value tells the GPU highest memory
+ bank bit used.
+
Optional subnodes:
Child nodes representing the frame buffer virtual devices.
@@ -198,6 +255,12 @@
This property is required whenever the continuous splash
screen feature is enabled for the corresponding
framebuffer device.
+- qcom,mdss-fb-splash-logo-enabled: The boolean entry enables the framebuffer
+ driver to display the splash logo image.
+ It is independent of continuous splash
+ screen feature and has no relation with
+ qcom,cont-splash-enabled entry present in
+ panel configuration.
Example:
mdss_mdp: qcom,mdss_mdp@fd900000 {
@@ -213,6 +276,21 @@
qcom,max-bandwidth-low-kbps = <2300000>;
qcom,max-bandwidth-high-kbps = <3000000>;
+ /* Bus Scale Settings */
+ qcom,msm-bus,name = "mdss_mdp";
+ qcom,msm-bus,num-cases = <3>;
+ qcom,msm-bus,num-paths = <2>;
+ qcom,msm-bus,vectors-KBps =
+ <22 512 0 0>, <23 512 0 0>,
+ <22 512 0 6400000>, <23 512 0 6400000>,
+ <22 512 0 6400000>, <23 512 0 6400000>;
+
+ /* Fudge factors */
+ qcom,mdss-ab-factor = <2 1>; /* 2 times */
+ qcom,mdss-ib-factor = <3 2>; /* 1.5 times */
+ qcom,mdss-high-ib-factor = <2 1>; /* 2 times */
+ qcom,mdss-clk-factor = <5 4>; /* 1.25 times */
+
qcom,max-clk-rate = <320000000>;
qcom,vbif-settings = <0x0004 0x00000001>,
<0x00D8 0x00000707>;
@@ -260,6 +338,7 @@
compatible = "qcom,mdss-fb";
qcom,mdss-mixer-swap;
qcom,mdss-fb-split = <480 240>
+ qcom,mdss-fb-splash-logo-enabled:
};
};
diff --git a/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt b/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt
index 8579ec0..b4bfb92 100644
--- a/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt
+++ b/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt
@@ -28,6 +28,7 @@
- qcom,hdmi-tx-mux-sel: gpio required to toggle HDMI output between
docking station, type A, and liquid device, type D, ports. Required
property for liquid devices.
+- qcom,hdmi-tx-ddc-mux-sel: gpio for ddc mux select.
- qcom,hdmi-tx-mux-en: gpio required to enable mux for HDMI output
on liquid devices. Required property for liquid devices.
@@ -57,6 +58,7 @@
qcom,hdmi-tx-max-voltage-level = <0 0 1800000 1800000>;
qcom,hdmi-tx-peak-current = <0 0 1800000 0>;
+ qcom,hdmi-tx-ddc-mux-sel = <&pma8084_gpios 6 0>;
qcom,hdmi-tx-cec = <&msmgpio 31 0>;
qcom,hdmi-tx-ddc-clk = <&msmgpio 32 0>;
qcom,hdmi-tx-ddc-data = <&msmgpio 33 0>;
diff --git a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
index 1be5504..dd0c440 100644
--- a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
+++ b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
@@ -49,6 +49,7 @@
2 : {1, 4}
3 : {1, 6}
4 : {1, 20}
+ 5 : {1, 8}
- qcom,calibration-type : Reference voltage to use for channel calibration.
Channel calibration is dependendent on the channel.
Certain channels like XO_THERM, BATT_THERM use ratiometric
diff --git a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
index e1681ca..e4e05d1 100644
--- a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
+++ b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
@@ -53,6 +53,7 @@
2 : pre-div ratio of {1, 4}
3 : pre-div ratio of {1, 6}
4 : pre-div ratio of {1, 20}
+ 5 : pre-div ratio of {1, 8}
- qcom,calibration-type : Reference voltage to use for channel calibration.
Channel calibration is dependendent on the channel.
Certain channels like XO_THERM, BATT_THERM use ratiometric
diff --git a/arch/arm/boot/dts/apq8084-mdss.dtsi b/arch/arm/boot/dts/apq8084-mdss.dtsi
index 0e771ce..2cd75e4 100644
--- a/arch/arm/boot/dts/apq8084-mdss.dtsi
+++ b/arch/arm/boot/dts/apq8084-mdss.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -24,6 +24,21 @@
qcom,max-bandwidth-low-kbps = <6000000>;
qcom,max-bandwidth-high-kbps = <6000000>;
+ /* Bus Scale Settings */
+ qcom,msm-bus,name = "mdss_mdp";
+ qcom,msm-bus,num-cases = <3>;
+ qcom,msm-bus,num-paths = <2>;
+ qcom,msm-bus,vectors-KBps =
+ <22 512 0 0>, <23 512 0 0>,
+ <22 512 0 6400000>, <23 512 0 6400000>,
+ <22 512 0 6400000>, <23 512 0 6400000>;
+
+ /* Fudge factors */
+ qcom,mdss-ab-factor = <2 1>; /* 2 times */
+ qcom,mdss-ib-factor = <3 2>; /* 1.5 times */
+ qcom,mdss-high-ib-factor = <2 1>; /* 2 times */
+ qcom,mdss-clk-factor = <105 100>; /* 1.05 times */
+
qcom,max-clk-rate = <320000000>;
qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 84bb234..55631ee 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -21,6 +21,22 @@
qcom,max-bandwidth-low-kbps = <1660000>;
qcom,max-bandwidth-high-kbps = <1660000>;
+
+ /* Bus Scale Settings */
+ qcom,msm-bus,name = "mdss_mdp";
+ qcom,msm-bus,num-cases = <3>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <22 512 0 0>,
+ <22 512 0 6400000>,
+ <22 512 0 6400000>;
+
+ /* Fudge factors */
+ qcom,mdss-ab-factor = <2 1>; /* 2 times */
+ qcom,mdss-ib-factor = <3 2>; /* 1.5 times */
+ qcom,mdss-high-ib-factor = <2 1>; /* 2 times */
+ qcom,mdss-clk-factor = <5 4>; /* 1.25 times */
+
qcom,max-clk-rate = <200000000>;
qcom,mdss-pipe-vig-off = <0x00001200>;
qcom,mdss-pipe-rgb-off = <0x00001E00>;
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index bf330f3..7e7302e 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -21,6 +21,22 @@
qcom,max-bandwidth-low-kbps = <2300000>;
qcom,max-bandwidth-high-kbps = <3000000>;
+
+ /* Bus Scale Settings */
+ qcom,msm-bus,name = "mdss_mdp";
+ qcom,msm-bus,num-cases = <3>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <22 512 0 0>,
+ <22 512 0 6400000>,
+ <22 512 0 6400000>;
+
+ /* Fudge factors */
+ qcom,mdss-ab-factor = <2 1>; /* 2 times */
+ qcom,mdss-ib-factor = <3 2>; /* 1.5 times */
+ qcom,mdss-high-ib-factor = <2 1>; /* 2 times */
+ qcom,mdss-clk-factor = <5 4>; /* 1.25 times */
+
qcom,max-clk-rate = <320000000>;
qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
0x00001A00>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 7dc59113..f4aa25b 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -215,7 +215,7 @@
vdd-supply = <&gdsc_venus>;
qcom,hfi = "venus";
qcom,has-ocmem;
- qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/
+ qcom,max-hw-load = <1216800>; /* 3840 x 2160 @ 30 + 1080p @ 30*/
};
qcom,vidc {
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 8ab916c..cec1a8f 100755
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -22,27 +22,28 @@
static struct gpiomux_setting ap2mdm_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
};
static struct gpiomux_setting mdm2ap_status_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_DOWN,
- .dir = GPIOMUX_IN,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
};
static struct gpiomux_setting mdm2ap_errfatal_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_DOWN,
- .dir = GPIOMUX_IN,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
};
static struct gpiomux_setting mdm2ap_pblrdy = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_NONE,
.dir = GPIOMUX_IN,
};
@@ -50,14 +51,16 @@
static struct gpiomux_setting ap2mdm_soft_reset_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
};
static struct gpiomux_setting ap2mdm_wakeup = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_DOWN,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
};
static struct msm_gpiomux_config mdm_configs[] __initdata = {
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 06160f7..7553f82 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -271,7 +271,7 @@
{
int best_level = -1;
int i;
- uint32_t best_level_pwr = ~0UL;
+ uint32_t best_level_pwr = ~0U;
uint32_t pwr;
uint32_t latency_us = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
@@ -490,7 +490,7 @@
static noinline int lpm_cpu_power_select(struct cpuidle_device *dev, int *index)
{
int best_level = -1;
- uint32_t best_level_pwr = ~0UL;
+ uint32_t best_level_pwr = ~0U;
uint32_t latency_us = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
uint32_t sleep_us =
(uint32_t)(ktime_to_us(tick_nohz_get_sleep_length()));
@@ -720,8 +720,6 @@
int idx;
struct lpm_cpu_level *cpu_level = &system_state->cpu_level[cpu_index];
- cpu_level = &system_state->cpu_level[cpu_index];
-
lpm_cpu_prepare(system_state, cpu_index, from_idle);
idx = lpm_system_select(system_state, cpu_index, from_idle);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index 696103c..72e3ec3 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -299,12 +299,16 @@
static uint64_t get_node_maxib(struct msm_bus_inode_info *info)
{
- int i;
+ int i, ctx;
uint64_t maxib = 0;
- for (i = 0; i <= info->num_pnodes; i++)
- maxib = max(*info->pnode[i].sel_clk, maxib);
+ for (i = 0; i <= info->num_pnodes; i++) {
+ for (ctx = 0; ctx < NUM_CTX; ctx++)
+ maxib = max(info->pnode[i].clk[ctx], maxib);
+ }
+ MSM_BUS_DBG("%s: Node %d numpnodes %d maxib %llu", __func__,
+ info->num_pnodes, info->node_info->id, maxib);
return maxib;
}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_of.c b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
index 5e803a1..52195c7 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_of.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -173,7 +173,7 @@
of_node = pdev->dev.of_node;
pdata = get_pdata(pdev, of_node);
if (!pdata) {
- pr_err("Error getting bus pdata!\n");
+ pr_err("client has to provide missing entry for successful registration\n");
return NULL;
}
@@ -214,7 +214,7 @@
pdata = get_pdata(pdev, of_node);
if (!pdata) {
- pr_err("Error getting bus pdata!\n");
+ pr_err("client has to provide missing entry for successful registration\n");
return NULL;
}
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index ead2e95..979c5bb 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -478,8 +478,9 @@
wdog_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pdata->size = resource_size(wdog_resource);
pdata->phys_base = wdog_resource->start;
- if (unlikely(!(devm_request_region(&pdev->dev, pdata->phys_base,
- pdata->size, "msm-watchdog")))) {
+ if (unlikely(!(devm_request_mem_region(&pdev->dev, pdata->phys_base,
+ pdata->size, "msm-watchdog")))) {
+
dev_err(&pdev->dev, "%s cannot reserve watchdog region\n",
__func__);
return -ENXIO;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 12f448f..37c236d 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -282,7 +282,7 @@
{
uint16_t event_id, event_id_packet, length, temp_len;
uint8_t *event_mask_ptr, byte_mask, payload_len, payload_len_field;
- uint8_t timestamp[8], bit_index, timestamp_len;
+ uint8_t timestamp[8] = {0}, bit_index, timestamp_len;
uint8_t event_data[MAX_EVENT_SIZE];
unsigned int byte_index, total_event_len, i;
struct diag_dci_client_tbl *entry;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 0e27693..0c9797e 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -342,6 +342,9 @@
else if (subsys_id == 0x32 && cmd_code_hi >= 0x03 &&
cmd_code_lo <= 0x03)
return 1;
+ else if (subsys_id == 0x57 && cmd_code_hi >= 0x0E &&
+ cmd_code_lo <= 0x0E)
+ return 1;
}
return 0;
}
diff --git a/drivers/crypto/msm/qce.h b/drivers/crypto/msm/qce.h
index afd5141..4250202 100644
--- a/drivers/crypto/msm/qce.h
+++ b/drivers/crypto/msm/qce.h
@@ -1,6 +1,6 @@
/* Qualcomm Crypto Engine driver API
*
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, 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
@@ -116,6 +116,12 @@
bool bam;
bool is_shared;
bool hw_key;
+ bool use_sw_aes_cbc_ecb_ctr_algo;
+ bool use_sw_aead_algo;
+ bool use_sw_aes_xts_algo;
+ bool use_sw_ahash_algo;
+ bool use_sw_hmac_algo;
+ bool use_sw_aes_ccm_algo;
};
/* Sha operation parameters */
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 3a8d206..63e18c9 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -101,6 +101,13 @@
dma_addr_t phy_ota_src;
dma_addr_t phy_ota_dst;
unsigned int ota_size;
+
+ bool use_sw_aes_cbc_ecb_ctr_algo;
+ bool use_sw_aead_algo;
+ bool use_sw_aes_xts_algo;
+ bool use_sw_ahash_algo;
+ bool use_sw_hmac_algo;
+ bool use_sw_aes_ccm_algo;
};
/* Standard initialization vector for SHA-1, source: FIPS 180-2 */
@@ -5078,6 +5085,26 @@
"qcom,ce-hw-shared");
pce_dev->support_hw_key = of_property_read_bool((&pdev->dev)->of_node,
"qcom,ce-hw-key");
+
+ pce_dev->use_sw_aes_cbc_ecb_ctr_algo =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,use-sw-aes-cbc-ecb-ctr-algo");
+ pce_dev->use_sw_aead_algo =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,use-sw-aead-algo");
+ pce_dev->use_sw_aes_xts_algo =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,use-sw-aes-xts-algo");
+ pce_dev->use_sw_ahash_algo =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,use-sw-ahash-algo");
+ pce_dev->use_sw_hmac_algo =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,use-sw-hmac-algo");
+ pce_dev->use_sw_aes_ccm_algo =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,use-sw-aes-ccm-algo");
+
if (of_property_read_u32((&pdev->dev)->of_node,
"qcom,bam-pipe-pair",
&pce_dev->ce_sps.pipe_pair_index)) {
@@ -5409,6 +5436,19 @@
ce_support->aligned_only = false;
else
ce_support->aligned_only = true;
+
+ ce_support->use_sw_aes_cbc_ecb_ctr_algo =
+ pce_dev->use_sw_aes_cbc_ecb_ctr_algo;
+ ce_support->use_sw_aead_algo =
+ pce_dev->use_sw_aead_algo;
+ ce_support->use_sw_aes_xts_algo =
+ pce_dev->use_sw_aes_xts_algo;
+ ce_support->use_sw_ahash_algo =
+ pce_dev->use_sw_ahash_algo;
+ ce_support->use_sw_hmac_algo =
+ pce_dev->use_sw_hmac_algo;
+ ce_support->use_sw_aes_ccm_algo =
+ pce_dev->use_sw_aes_ccm_algo;
return 0;
}
EXPORT_SYMBOL(qce_hw_support);
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 7553e98..974606d 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -1,6 +1,6 @@
/* Qualcomm Crypto driver
*
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, 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
@@ -3237,6 +3237,16 @@
return _sha_digest(req);
}
+static int _qcrypto_prefix_alg_cra_name(char cra_name[], unsigned int size)
+{
+ char new_cra_name[CRYPTO_MAX_ALG_NAME] = "qcom-";
+ if (CRYPTO_MAX_ALG_NAME < size + 5)
+ return -EINVAL;
+ strlcat(new_cra_name, cra_name, CRYPTO_MAX_ALG_NAME);
+ strlcpy(cra_name, new_cra_name, CRYPTO_MAX_ALG_NAME);
+ return 0;
+}
+
int qcrypto_cipher_set_flag(struct ablkcipher_request *req, unsigned int flags)
{
struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
@@ -3868,6 +3878,17 @@
rc = PTR_ERR(q_alg);
goto err;
}
+ if (cp->ce_support.use_sw_aes_cbc_ecb_ctr_algo) {
+ rc = _qcrypto_prefix_alg_cra_name(
+ q_alg->cipher_alg.cra_name,
+ strlen(q_alg->cipher_alg.cra_name));
+ if (rc) {
+ dev_err(&pdev->dev,
+ "The algorithm name %s is too long.\n",
+ q_alg->cipher_alg.cra_name);
+ goto err;
+ }
+ }
rc = crypto_register_alg(&q_alg->cipher_alg);
if (rc) {
dev_err(&pdev->dev, "%s alg registration failed\n",
@@ -3890,6 +3911,17 @@
rc = PTR_ERR(q_alg);
goto err;
}
+ if (cp->ce_support.use_sw_aes_xts_algo) {
+ rc = _qcrypto_prefix_alg_cra_name(
+ q_alg->cipher_alg.cra_name,
+ strlen(q_alg->cipher_alg.cra_name));
+ if (rc) {
+ dev_err(&pdev->dev,
+ "The algorithm name %s is too long.\n",
+ q_alg->cipher_alg.cra_name);
+ goto err;
+ }
+ }
rc = crypto_register_alg(&q_alg->cipher_alg);
if (rc) {
dev_err(&pdev->dev, "%s alg registration failed\n",
@@ -3915,7 +3947,17 @@
rc = PTR_ERR(q_alg);
goto err;
}
-
+ if (cp->ce_support.use_sw_ahash_algo) {
+ rc = _qcrypto_prefix_alg_cra_name(
+ q_alg->sha_alg.halg.base.cra_name,
+ strlen(q_alg->sha_alg.halg.base.cra_name));
+ if (rc) {
+ dev_err(&pdev->dev,
+ "The algorithm name %s is too long.\n",
+ q_alg->sha_alg.halg.base.cra_name);
+ goto err;
+ }
+ }
rc = crypto_register_ahash(&q_alg->sha_alg);
if (rc) {
dev_err(&pdev->dev, "%s alg registration failed\n",
@@ -3941,7 +3983,17 @@
rc = PTR_ERR(q_alg);
goto err;
}
-
+ if (cp->ce_support.use_sw_aead_algo) {
+ rc = _qcrypto_prefix_alg_cra_name(
+ q_alg->cipher_alg.cra_name,
+ strlen(q_alg->cipher_alg.cra_name));
+ if (rc) {
+ dev_err(&pdev->dev,
+ "The algorithm name %s is too long.\n",
+ q_alg->cipher_alg.cra_name);
+ goto err;
+ }
+ }
rc = crypto_register_alg(&q_alg->cipher_alg);
if (rc) {
dev_err(&pdev->dev,
@@ -3968,7 +4020,18 @@
rc = PTR_ERR(q_alg);
goto err;
}
-
+ if (cp->ce_support.use_sw_hmac_algo) {
+ rc = _qcrypto_prefix_alg_cra_name(
+ q_alg->sha_alg.halg.base.cra_name,
+ strlen(
+ q_alg->sha_alg.halg.base.cra_name));
+ if (rc) {
+ dev_err(&pdev->dev,
+ "The algorithm name %s is too long.\n",
+ q_alg->sha_alg.halg.base.cra_name);
+ goto err;
+ }
+ }
rc = crypto_register_ahash(&q_alg->sha_alg);
if (rc) {
dev_err(&pdev->dev,
@@ -3994,6 +4057,17 @@
rc = PTR_ERR(q_alg);
goto err;
}
+ if (cp->ce_support.use_sw_aes_ccm_algo) {
+ rc = _qcrypto_prefix_alg_cra_name(
+ q_alg->cipher_alg.cra_name,
+ strlen(q_alg->cipher_alg.cra_name));
+ if (rc) {
+ dev_err(&pdev->dev,
+ "The algorithm name %s is too long.\n",
+ q_alg->cipher_alg.cra_name);
+ goto err;
+ }
+ }
rc = crypto_register_alg(&q_alg->cipher_alg);
if (rc) {
dev_err(&pdev->dev, "%s alg registration failed\n",
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index 73dd868..6261d89 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -240,43 +240,6 @@
return ret;
}
-int ion_heap_buffer_zero_old(struct ion_buffer *buffer)
-{
- struct sg_table *table = buffer->sg_table;
- pgprot_t pgprot;
- struct scatterlist *sg;
- struct vm_struct *vm_struct;
- int i, j, ret = 0;
-
- if (buffer->flags & ION_FLAG_CACHED)
- pgprot = PAGE_KERNEL;
- else
- pgprot = pgprot_writecombine(PAGE_KERNEL);
-
- vm_struct = get_vm_area(PAGE_SIZE, VM_ALLOC);
- if (!vm_struct)
- return -ENOMEM;
-
- for_each_sg(table->sgl, sg, table->nents, i) {
- struct page *page = sg_page(sg);
- unsigned long len = sg_dma_len(sg);
-
- for (j = 0; j < len / PAGE_SIZE; j++) {
- struct page *sub_page = page + j;
- struct page **pages = &sub_page;
- ret = map_vm_area(vm_struct, pgprot, &pages);
- if (ret)
- goto end;
- memset(vm_struct->addr, 0, PAGE_SIZE);
- unmap_kernel_range((unsigned long)vm_struct->addr,
- PAGE_SIZE);
- }
- }
-end:
- free_vm_area(vm_struct);
- return ret;
-}
-
void ion_heap_free_page(struct ion_buffer *buffer, struct page *page,
unsigned int order)
{
@@ -327,11 +290,11 @@
if (total_drained >= size)
break;
list_del(&buffer->list);
- ion_buffer_destroy(buffer);
heap->free_list_size -= buffer->size;
if (skip_pools)
buffer->flags |= ION_FLAG_FREED_FROM_SHRINKER;
total_drained += buffer->size;
+ ion_buffer_destroy(buffer);
}
rt_mutex_unlock(&heap->lock);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index eba60ea..10eaf4e 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -3069,7 +3069,7 @@
return -EINVAL;
ret = adreno_drawctxt_wait(ADRENO_DEVICE(device), context,
- timestamp, msecs_to_jiffies(msecs));
+ timestamp, msecs);
/* If the context got invalidated then return a specific error */
drawctxt = ADRENO_CONTEXT(context);
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index d727423..1b5573f 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -429,7 +429,8 @@
/* Always enable per-context timestamps */
drawctxt->base.flags |= KGSL_CONTEXT_PER_CONTEXT_TS;
-
+ drawctxt->type = (drawctxt->base.flags & KGSL_CONTEXT_TYPE_MASK)
+ >> KGSL_CONTEXT_TYPE_SHIFT;
mutex_init(&drawctxt->mutex);
init_waitqueue_head(&drawctxt->wq);
init_waitqueue_head(&drawctxt->waiting);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 1383a20..b23d3ab 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -665,7 +665,8 @@
total_sizedwords += (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) ? 2 : 0;
/* Add two dwords for the CP_INTERRUPT */
- total_sizedwords += drawctxt ? 2 : 0;
+ total_sizedwords +=
+ (drawctxt || (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) ? 2 : 0;
if (adreno_is_a3xx(adreno_dev))
total_sizedwords += 7;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index edc42f9..1743e4a 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1462,7 +1462,7 @@
* @timestamp: Pending timestamp for the event
* @handle: Pointer to a sync fence handle
* @device: Pointer to the KGSL device
- * @lock: Spin lock to protect the sync event list
+ * @refcount: Allow event to be destroyed asynchronously
*/
struct kgsl_cmdbatch_sync_event {
int type;
@@ -1472,10 +1472,37 @@
unsigned int timestamp;
struct kgsl_sync_fence_waiter *handle;
struct kgsl_device *device;
- spinlock_t lock;
+ struct kref refcount;
};
/**
+ * kgsl_cmdbatch_sync_event_destroy() - Destroy a sync event object
+ * @kref: Pointer to the kref structure for this object
+ *
+ * Actually destroy a sync event object. Called from
+ * kgsl_cmdbatch_sync_event_put.
+ */
+static void kgsl_cmdbatch_sync_event_destroy(struct kref *kref)
+{
+ struct kgsl_cmdbatch_sync_event *event = container_of(kref,
+ struct kgsl_cmdbatch_sync_event, refcount);
+
+ kgsl_cmdbatch_put(event->cmdbatch);
+ kfree(event);
+}
+
+/**
+ * kgsl_cmdbatch_sync_event_put() - Decrement the refcount for a
+ * sync event object
+ * @event: Pointer to the sync event object
+ */
+static inline void kgsl_cmdbatch_sync_event_put(
+ struct kgsl_cmdbatch_sync_event *event)
+{
+ kref_put(&event->refcount, kgsl_cmdbatch_sync_event_destroy);
+}
+
+/**
* kgsl_cmdbatch_destroy_object() - Destroy a cmdbatch object
* @kref: Pointer to the kref structure for this object
*
@@ -1500,10 +1527,25 @@
static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device,
struct kgsl_cmdbatch_sync_event *event)
{
+ struct kgsl_cmdbatch_sync_event *e, *tmp;
int sched = 0;
+ int removed = 0;
spin_lock(&event->cmdbatch->lock);
- list_del(&event->node);
+
+ /*
+ * sync events that are contained by a cmdbatch which has been
+ * destroyed may have already been removed from the synclist
+ */
+
+ list_for_each_entry_safe(e, tmp, &event->cmdbatch->synclist, node) {
+ if (e == event) {
+ list_del_init(&event->node);
+ removed = 1;
+ break;
+ }
+ }
+
sched = list_empty(&event->cmdbatch->synclist) ? 1 : 0;
spin_unlock(&event->cmdbatch->lock);
@@ -1514,6 +1556,10 @@
if (sched && device->ftbl->drawctxt_sched)
device->ftbl->drawctxt_sched(device, event->cmdbatch->context);
+
+ /* Put events that have been removed from the synclist */
+ if (removed)
+ kgsl_cmdbatch_sync_event_put(event);
}
@@ -1527,11 +1573,9 @@
struct kgsl_cmdbatch_sync_event *event = priv;
kgsl_cmdbatch_sync_expire(device, event);
-
kgsl_context_put(event->context);
- kgsl_cmdbatch_put(event->cmdbatch);
-
- kfree(event);
+ /* Put events that have signaled */
+ kgsl_cmdbatch_sync_event_put(event);
}
/**
@@ -1539,32 +1583,48 @@
* @cmdbatch: Pointer to the command batch object to destroy
*
* Start the process of destroying a command batch. Cancel any pending events
- * and decrement the refcount.
+ * and decrement the refcount. Asynchronous events can still signal after
+ * kgsl_cmdbatch_destroy has returned.
*/
void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch)
{
struct kgsl_cmdbatch_sync_event *event, *tmp;
+ LIST_HEAD(cancel_synclist);
+ /*
+ * Empty the synclist before canceling events
+ */
spin_lock(&cmdbatch->lock);
+ list_splice_init(&cmdbatch->synclist, &cancel_synclist);
+ spin_unlock(&cmdbatch->lock);
- /* Delete any pending sync points for this command batch */
- list_for_each_entry_safe(event, tmp, &cmdbatch->synclist, node) {
+ /*
+ * Finish canceling events outside the cmdbatch spinlock and
+ * require the cancel function to return if the event was
+ * successfully canceled meaning that the event is guaranteed
+ * not to signal the callback. This guarantee ensures that
+ * the reference count for the event and cmdbatch is correct.
+ */
+ list_for_each_entry_safe(event, tmp, &cancel_synclist, node) {
if (event->type == KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP) {
- /* Cancel the event if it still exists */
+ /*
+ * Timestamp events are guaranteed to signal
+ * when canceled
+ */
kgsl_cancel_event(cmdbatch->device, event->context,
event->timestamp, kgsl_cmdbatch_sync_func,
event);
} else if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE) {
- if (kgsl_sync_fence_async_cancel(event->handle)) {
- list_del(&event->node);
- kfree(event);
- kgsl_cmdbatch_put(cmdbatch);
- }
+ /* Put events that are successfully canceled */
+ if (kgsl_sync_fence_async_cancel(event->handle))
+ kgsl_cmdbatch_sync_event_put(event);
}
- }
- spin_unlock(&cmdbatch->lock);
+ /* Put events that have been removed from the synclist */
+ list_del_init(&event->node);
+ kgsl_cmdbatch_sync_event_put(event);
+ }
kgsl_cmdbatch_put(cmdbatch);
}
EXPORT_SYMBOL(kgsl_cmdbatch_destroy);
@@ -1577,11 +1637,9 @@
{
struct kgsl_cmdbatch_sync_event *event = priv;
- spin_lock(&event->lock);
kgsl_cmdbatch_sync_expire(event->device, event);
- kgsl_cmdbatch_put(event->cmdbatch);
- spin_unlock(&event->lock);
- kfree(event);
+ /* Put events that have signaled */
+ kgsl_cmdbatch_sync_event_put(event);
}
/* kgsl_cmdbatch_add_sync_fence() - Add a new sync fence syncpoint
@@ -1607,28 +1665,33 @@
event->type = KGSL_CMD_SYNCPOINT_TYPE_FENCE;
event->cmdbatch = cmdbatch;
event->device = device;
- spin_lock_init(&event->lock);
+ event->context = NULL;
+
+ /*
+ * Initial kref is to ensure async callback does not free the
+ * event before this function sets the event handle
+ */
+ kref_init(&event->refcount);
/*
* Add it to the list first to account for the possiblity that the
* callback will happen immediately after the call to
- * kgsl_sync_fence_async_wait
+ * kgsl_sync_fence_async_wait. Decrement the event refcount when
+ * removing from the synclist.
*/
spin_lock(&cmdbatch->lock);
+ kref_get(&event->refcount);
list_add(&event->node, &cmdbatch->synclist);
spin_unlock(&cmdbatch->lock);
/*
- * There is a distinct race condition that can occur if the fence
- * callback is fired before the function has a chance to return. The
- * event struct would be freed before we could write event->handle and
- * hilarity ensued. Protect against this by protecting the call to
- * kgsl_sync_fence_async_wait and the kfree in the callback with a lock.
+ * Increment the reference count for the async callback.
+ * Decrement when the callback is successfully canceled, when
+ * the callback is signaled or if the async wait fails.
*/
- spin_lock(&event->lock);
-
+ kref_get(&event->refcount);
event->handle = kgsl_sync_fence_async_wait(sync->fd,
kgsl_cmdbatch_sync_fence_func, event);
@@ -1636,18 +1699,27 @@
if (IS_ERR_OR_NULL(event->handle)) {
int ret = PTR_ERR(event->handle);
+ /* Failed to add the event to the async callback */
+ kgsl_cmdbatch_sync_event_put(event);
+
+ /* Remove event from the synclist */
spin_lock(&cmdbatch->lock);
list_del(&event->node);
+ kgsl_cmdbatch_sync_event_put(event);
spin_unlock(&cmdbatch->lock);
- kgsl_cmdbatch_put(cmdbatch);
- spin_unlock(&event->lock);
- kfree(event);
+ /* Event no longer needed by this function */
+ kgsl_cmdbatch_sync_event_put(event);
return ret;
}
- spin_unlock(&event->lock);
+ /*
+ * Event was successfully added to the synclist, the async
+ * callback and handle to cancel event has been set.
+ */
+ kgsl_cmdbatch_sync_event_put(event);
+
return 0;
}
@@ -1702,6 +1774,17 @@
event->context = context;
event->timestamp = sync->timestamp;
+ /*
+ * Two krefs are required to support events. The first kref is for
+ * the synclist which holds the event in the cmdbatch. The second
+ * kref is for the callback which can be asynchronous and be called
+ * after kgsl_cmdbatch_destroy. The kref should be put when the event
+ * is removed from the synclist, if the callback is successfully
+ * canceled or when the callback is signaled.
+ */
+ kref_init(&event->refcount);
+ kref_get(&event->refcount);
+
spin_lock(&cmdbatch->lock);
list_add(&event->node, &cmdbatch->synclist);
spin_unlock(&cmdbatch->lock);
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c
index a71526a..912d87c 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.c
@@ -1,6 +1,6 @@
/* drivers/input/touchscreen/gt9xx.c
*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* Linux Foundation chooses to take subject only to the GPLv2 license
* terms, and distributes only under these terms.
@@ -121,6 +121,8 @@
#define GTP_DEBUGFS_DIR "ts_debug"
#define GTP_DEBUGFS_FILE_SUSPEND "suspend"
+#define GTP_DEBUGFS_FILE_DATA "data"
+#define GTP_DEBUGFS_FILE_ADDR "addr"
/*******************************************************
Function:
@@ -1528,12 +1530,62 @@
return size;
}
+static ssize_t gtp_fw_upgrade_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct goodix_ts_data *ts = dev_get_drvdata(dev);
+ return snprintf(buf, 2, "%d\n", ts->fw_loading);
+}
+
+static ssize_t gtp_fw_upgrade_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct goodix_ts_data *ts = dev_get_drvdata(dev);
+ unsigned long val;
+ int ret;
+
+ if (size > 2)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret != 0)
+ return ret;
+
+ if (ts->gtp_is_suspend) {
+ dev_err(&ts->client->dev,
+ "Can't start fw upgrade. Device is in suspend state.");
+ return -EBUSY;
+ }
+
+ mutex_lock(&ts->input_dev->mutex);
+ if (!ts->fw_loading && val) {
+ disable_irq(ts->client->irq);
+ ts->fw_loading = true;
+ if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
+ ret = gup_update_proc(NULL);
+ if (ret == FAIL)
+ dev_err(&ts->client->dev,
+ "Fail to update GTP firmware.\n");
+ }
+ ts->fw_loading = false;
+ enable_irq(ts->client->irq);
+ }
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return size;
+}
+
static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR | S_IWGRP),
gtp_fw_name_show,
gtp_fw_name_store);
+static DEVICE_ATTR(fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP),
+ gtp_fw_upgrade_show,
+ gtp_fw_upgrade_store);
static struct attribute *gtp_attrs[] = {
&dev_attr_fw_name.attr,
+ &dev_attr_fw_upgrade.attr,
NULL
};
@@ -1541,6 +1593,84 @@
.attrs = gtp_attrs,
};
+static int gtp_debug_addr_is_valid(u16 addr)
+{
+ if (addr < GTP_VALID_ADDR_START || addr > GTP_VALID_ADDR_END) {
+ pr_err("GTP reg address is invalid: 0x%x\n", addr);
+ return false;
+ }
+
+ return true;
+}
+
+static int gtp_debug_data_set(void *_data, u64 val)
+{
+ struct goodix_ts_data *ts = _data;
+
+ mutex_lock(&ts->input_dev->mutex);
+ if (gtp_debug_addr_is_valid(ts->addr))
+ dev_err(&ts->client->dev,
+ "Writing to GTP registers not supported.\n");
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return 0;
+}
+
+static int gtp_debug_data_get(void *_data, u64 *val)
+{
+ struct goodix_ts_data *ts = _data;
+ int ret;
+ u8 buf[3] = {0};
+
+ mutex_lock(&ts->input_dev->mutex);
+ buf[0] = ts->addr >> 8;
+ buf[1] = ts->addr & 0x00ff;
+
+ if (gtp_debug_addr_is_valid(ts->addr)) {
+ ret = gtp_i2c_read(ts->client, buf, 3);
+ if (ret < 0)
+ dev_err(&ts->client->dev,
+ "GTP read register 0x%x failed (%d)\n",
+ ts->addr, ret);
+ else
+ *val = buf[2];
+ }
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, gtp_debug_data_get,
+ gtp_debug_data_set, "%llx\n");
+
+static int gtp_debug_addr_set(void *_data, u64 val)
+{
+ struct goodix_ts_data *ts = _data;
+
+ if (gtp_debug_addr_is_valid(val)) {
+ mutex_lock(&ts->input_dev->mutex);
+ ts->addr = val;
+ mutex_unlock(&ts->input_dev->mutex);
+ }
+
+ return 0;
+}
+
+static int gtp_debug_addr_get(void *_data, u64 *val)
+{
+ struct goodix_ts_data *ts = _data;
+
+ mutex_lock(&ts->input_dev->mutex);
+ if (gtp_debug_addr_is_valid(ts->addr))
+ *val = ts->addr;
+ mutex_unlock(&ts->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, gtp_debug_addr_get,
+ gtp_debug_addr_set, "%llx\n");
+
static int gtp_debug_suspend_set(void *_data, u64 val)
{
struct goodix_ts_data *ts = _data;
@@ -1574,7 +1704,7 @@
data->debug_base = debugfs_create_dir(GTP_DEBUGFS_DIR, NULL);
if (IS_ERR_OR_NULL(data->debug_base)) {
- pr_err("Failed to create debugfs dir.\n");
+ dev_err(&data->client->dev, "Failed to create debugfs dir.\n");
return -EINVAL;
}
@@ -1583,7 +1713,27 @@
data->debug_base,
data,
&debug_suspend_fops)))) {
- pr_err("Failed to create suspend file.\n");
+ dev_err(&data->client->dev, "Failed to create suspend file.\n");
+ debugfs_remove_recursive(data->debug_base);
+ return -EINVAL;
+ }
+
+ if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_DATA,
+ S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+ data->debug_base,
+ data,
+ &debug_data_fops)))) {
+ dev_err(&data->client->dev, "Failed to create data file.\n");
+ debugfs_remove_recursive(data->debug_base);
+ return -EINVAL;
+ }
+
+ if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_ADDR,
+ S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+ data->debug_base,
+ data,
+ &debug_addr_fops)))) {
+ dev_err(&data->client->dev, "Failed to create addr file.\n");
debugfs_remove_recursive(data->debug_base);
return -EINVAL;
}
@@ -1771,9 +1921,7 @@
return -EINVAL;
}
-#if GTP_ESD_PROTECT
i2c_connect_client = client;
-#endif
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "GTP I2C not supported\n");
@@ -1827,15 +1975,14 @@
strlcpy(ts->fw_name, pdata->fw_name,
strlen(pdata->fw_name) + 1);
-#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
- ret = gup_init_update_proc(ts);
- if (ret < 0) {
- dev_err(&client->dev,
- "GTP Create firmware update thread error.\n");
- goto exit_power_off;
+ if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
+ ret = gup_init_update_proc(ts);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "GTP Create firmware update thread error.\n");
+ goto exit_power_off;
+ }
}
-#endif
-
ret = gtp_init_panel(ts);
if (ret < 0) {
dev_err(&client->dev, "GTP init panel failed.\n");
@@ -2032,6 +2179,14 @@
}
mutex_lock(&ts->lock);
+
+ if (ts->fw_loading) {
+ dev_info(&ts->client->dev,
+ "Fw upgrade in progress, can't go to suspend.");
+ mutex_unlock(&ts->lock);
+ return 0;
+ }
+
#if GTP_ESD_PROTECT
gtp_esd_switch(ts->client, SWITCH_OFF);
#endif
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h
index 4d656dd..7a1af23 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.h
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.h
@@ -1,6 +1,6 @@
/* drivers/input/touchscreen/gt9xx.h
*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* Linux Foundation chooses to take subject only to the GPLv2 license
* terms, and distributes only under these terms.
@@ -78,6 +78,7 @@
s32 use_irq;
u16 abs_x_max;
u16 abs_y_max;
+ u16 addr;
u8 max_touch_num;
u8 int_trigger_type;
u8 green_wake_mode;
@@ -92,6 +93,7 @@
u8 fw_error;
bool power_on;
struct mutex lock;
+ bool fw_loading;
struct regulator *avdd;
struct regulator *vdd;
struct regulator *vcc_i2c;
@@ -175,6 +177,8 @@
/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
#define GTP_I2C_ADDRESS_HIGH 0x14
#define GTP_I2C_ADDRESS_LOW 0x5D
+#define GTP_VALID_ADDR_START 0x8040
+#define GTP_VALID_ADDR_END 0x8177
#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
@@ -215,11 +219,9 @@
void uninit_wr_node(void);
#endif
-#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
-extern u8 gup_init_update_proc(struct goodix_ts_data *ts);
+u8 gup_init_update_proc(struct goodix_ts_data *ts);
s32 gup_enter_update_mode(struct i2c_client *client);
void gup_leave_update_mode(struct i2c_client *client);
s32 gup_update_proc(void *dir);
extern struct i2c_client *i2c_connect_client;
-#endif
#endif /* _GOODIX_GT9XX_H_ */
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 7152ec8..ca47547 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -113,16 +113,15 @@
static void synaptics_rmi4_sensor_wake(struct synaptics_rmi4_data *rmi4_data);
-static void synaptics_rmi4_sensor_sleep(struct synaptics_rmi4_data *rmi4_data);
-
static int synaptics_rmi4_check_configuration(struct synaptics_rmi4_data
*rmi4_data);
-#ifdef CONFIG_PM
+
static int synaptics_rmi4_suspend(struct device *dev);
static int synaptics_rmi4_resume(struct device *dev);
+#ifdef CONFIG_PM
static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
struct device_attribute *attr, char *buf);
@@ -425,6 +424,31 @@
static bool exp_fn_inited;
static struct mutex exp_fn_list_mutex;
static struct list_head exp_fn_list;
+
+static int synaptics_rmi4_debug_suspend_set(void *_data, u64 val)
+{
+ struct synaptics_rmi4_data *rmi4_data = _data;
+
+ if (val)
+ synaptics_rmi4_suspend(&rmi4_data->input_dev->dev);
+ else
+ synaptics_rmi4_resume(&rmi4_data->input_dev->dev);
+
+ return 0;
+}
+
+static int synaptics_rmi4_debug_suspend_get(void *_data, u64 *val)
+{
+ struct synaptics_rmi4_data *rmi4_data = _data;
+
+ *val = rmi4_data->suspended;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, synaptics_rmi4_debug_suspend_get,
+ synaptics_rmi4_debug_suspend_set, "%lld\n");
+
#ifdef CONFIG_PM
static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -449,30 +473,6 @@
return count;
}
-static int synaptics_rmi4_debug_suspend_set(void *_data, u64 val)
-{
- struct synaptics_rmi4_data *rmi4_data = _data;
-
- if (val)
- synaptics_rmi4_suspend(&rmi4_data->input_dev->dev);
- else
- synaptics_rmi4_resume(&rmi4_data->input_dev->dev);
-
- return 0;
-}
-
-static ssize_t synaptics_rmi4_debug_suspend_get(void *_data, u64 *val)
-{
- struct synaptics_rmi4_data *rmi4_data = _data;
-
- *val = rmi4_data->suspended;
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, synaptics_rmi4_debug_suspend_get,
- synaptics_rmi4_debug_suspend_set, "%lld\n");
-
#ifdef CONFIG_FB
static void configure_sleep(struct synaptics_rmi4_data *rmi4_data)
{
@@ -502,6 +502,11 @@
return;
}
#endif
+#else
+static void configure_sleep(struct synaptics_rmi4_data *rmi4_data)
+{
+ return;
+}
#endif
static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
@@ -3665,6 +3670,14 @@
{
return 0;
};
+static int synaptics_rmi4_suspend(struct device *dev);
+{
+ return 0;
+}
+static int synaptics_rmi4_resume(struct device *dev);
+{
+ return 0;
+}
#endif
static const struct i2c_device_id synaptics_rmi4_id_table[] = {
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index 7abd909..8478b24 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -461,7 +461,7 @@
return;
}
-static char *rmi_char_devnode(struct device *dev, mode_t *mode)
+static char *rmi_char_devnode(struct device *dev, umode_t *mode)
{
if (!mode)
return NULL;
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index e293279..38dd41b 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -61,6 +61,12 @@
static struct iommu_access_ops *iommu_access_ops;
+static const struct of_device_id msm_smmu_list[] = {
+ { .compatible = "qcom,msm-smmu-v1", },
+ { .compatible = "qcom,msm-smmu-v2", },
+ { }
+};
+
struct msm_scm_paddr_list {
unsigned int list;
unsigned int list_size;
@@ -296,8 +302,9 @@
int ret, ptbl_ret = 0;
int version;
- for_each_compatible_node(np, NULL, "qcom,msm-smmu-v1")
- if (of_find_property(np, "qcom,iommu-secure-id", NULL))
+ for_each_matching_node(np, msm_smmu_list)
+ if (of_find_property(np, "qcom,iommu-secure-id", NULL) &&
+ of_device_is_available(np))
break;
if (!np)
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index da90440..9208599 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -136,11 +136,11 @@
#define FLASH_SELFCHECK_ENABLE 0x80
#define FLASH_RAMP_STEP_27US 0xBF
-#define FLASH_STROBE_SW 0xC0
-#define FLASH_STROBE_HW 0x04
+#define FLASH_HW_SW_STROBE_SEL_MASK 0x04
#define FLASH_STROBE_MASK 0xC7
#define FLASH_LED_0_OUTPUT 0x80
#define FLASH_LED_1_OUTPUT 0x40
+#define FLASH_TORCH_OUTPUT 0xC0
#define FLASH_CURRENT_PRGM_MIN 1
#define FLASH_CURRENT_PRGM_SHIFT 1
@@ -1001,6 +1001,13 @@
goto error_reg_write;
}
+ if (!led->flash_cfg->strobe_type)
+ led->flash_cfg->trigger_flash &=
+ ~FLASH_HW_SW_STROBE_SEL_MASK;
+ else
+ led->flash_cfg->trigger_flash |=
+ FLASH_HW_SW_STROBE_SEL_MASK;
+
rc = qpnp_led_masked_write(led,
FLASH_LED_STROBE_CTRL(led->base),
led->flash_cfg->trigger_flash,
@@ -1080,30 +1087,22 @@
*/
usleep(FLASH_RAMP_UP_DELAY_US);
- if (!led->flash_cfg->strobe_type) {
- rc = qpnp_led_masked_write(led,
- FLASH_LED_STROBE_CTRL(led->base),
- led->flash_cfg->trigger_flash,
- led->flash_cfg->trigger_flash);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "LED %d strobe reg write failed(%d)\n",
- led->id, rc);
- goto error_flash_set;
- }
- } else {
- rc = qpnp_led_masked_write(led,
- FLASH_LED_STROBE_CTRL(led->base),
- (led->flash_cfg->trigger_flash |
- FLASH_STROBE_HW),
- (led->flash_cfg->trigger_flash |
- FLASH_STROBE_HW));
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "LED %d strobe reg write failed(%d)\n",
- led->id, rc);
- goto error_flash_set;
- }
+ if (!led->flash_cfg->strobe_type)
+ led->flash_cfg->trigger_flash &=
+ ~FLASH_HW_SW_STROBE_SEL_MASK;
+ else
+ led->flash_cfg->trigger_flash |=
+ FLASH_HW_SW_STROBE_SEL_MASK;
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_STROBE_CTRL(led->base),
+ led->flash_cfg->trigger_flash,
+ led->flash_cfg->trigger_flash);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "LED %d strobe reg write failed(%d)\n",
+ led->id, rc);
+ goto error_flash_set;
}
}
} else {
@@ -1614,6 +1613,15 @@
}
+ /* Reset WLED enable register */
+ rc = qpnp_led_masked_write(led, WLED_MOD_CTRL_REG(led->base),
+ WLED_8_BIT_MASK, WLED_BOOST_OFF);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED write ctrl reg failed(%d)\n", rc);
+ return rc;
+ }
+
/* dump wled registers */
qpnp_dump_regs(led, wled_debug_regs, ARRAY_SIZE(wled_debug_regs));
@@ -2733,7 +2741,7 @@
led->flash_cfg->enable_module = FLASH_ENABLE_MODULE;
} else
led->flash_cfg->enable_module = FLASH_ENABLE_ALL;
- led->flash_cfg->trigger_flash = FLASH_STROBE_SW;
+ led->flash_cfg->trigger_flash = FLASH_TORCH_OUTPUT;
}
rc = of_property_read_u32(node, "qcom,current", &val);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index ef8b996..ea16ebd 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -411,43 +411,6 @@
return rc;
}
-static int32_t msm_actuator_set_position(
- struct msm_actuator_ctrl_t *a_ctrl,
- struct msm_actuator_set_position_t *set_pos)
-{
- int32_t rc = 0;
- int32_t index;
- uint16_t next_lens_position;
- uint16_t delay;
- uint32_t hw_params = 0;
- struct msm_camera_i2c_reg_setting reg_setting;
- CDBG("%s Enter %d\n", __func__, __LINE__);
- if (set_pos->number_of_steps == 0)
- return rc;
-
- a_ctrl->i2c_tbl_index = 0;
- for (index = 0; index < set_pos->number_of_steps; index++) {
- next_lens_position = set_pos->pos[index];
- delay = set_pos->delay[index];
- a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
- next_lens_position, hw_params, delay);
-
- reg_setting.reg_setting = a_ctrl->i2c_reg_tbl;
- reg_setting.size = a_ctrl->i2c_tbl_index;
- reg_setting.data_type = a_ctrl->i2c_data_type;
-
- rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write_table_w_microdelay(
- &a_ctrl->i2c_client, ®_setting);
- if (rc < 0) {
- pr_err("%s Failed I2C write Line %d\n", __func__, __LINE__);
- return rc;
- }
- a_ctrl->i2c_tbl_index = 0;
- }
- CDBG("%s exit %d\n", __func__, __LINE__);
- return rc;
-}
-
static int32_t msm_actuator_init(struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_set_info_t *set_info) {
struct reg_settings_t *init_settings = NULL;
@@ -602,12 +565,6 @@
pr_err("move focus failed %d\n", rc);
break;
- case CFG_SET_POSITION:
- rc = a_ctrl->func_tbl->actuator_set_position(a_ctrl,
- &cdata->cfg.setpos);
- if (rc < 0)
- pr_err("actuator_set_position failed %d\n", rc);
- break;
default:
break;
}
@@ -962,7 +919,6 @@
.actuator_set_default_focus = msm_actuator_set_default_focus,
.actuator_init_focus = msm_actuator_init_focus,
.actuator_parse_i2c_params = msm_actuator_parse_i2c_params,
- .actuator_set_position = msm_actuator_set_position,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
index 7ec9a49..809c9cf 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
@@ -43,8 +43,6 @@
struct damping_params_t *,
int8_t,
int16_t);
- int32_t (*actuator_set_position)(struct msm_actuator_ctrl_t *,
- struct msm_actuator_set_position_t *);
};
struct msm_actuator {
diff --git a/drivers/media/platform/msm/wfd/vsg-subdev.c b/drivers/media/platform/msm/wfd/vsg-subdev.c
index 1f827bb..433468e 100644
--- a/drivers/media/platform/msm/wfd/vsg-subdev.c
+++ b/drivers/media/platform/msm/wfd/vsg-subdev.c
@@ -26,12 +26,6 @@
#define TICKS_PER_TIMEOUT 2
-static void vsg_reset_timer(struct hrtimer *timer, ktime_t time)
-{
- hrtimer_forward_now(timer, time);
- hrtimer_restart(timer);
-}
-
static int vsg_release_input_buffer(struct vsg_context *context,
struct vsg_buf_info *buf)
{
@@ -467,7 +461,7 @@
* otherwise, diff between two consecutive frames might
* be less than max_frame_interval (for just one sample)
*/
- vsg_reset_timer(&context->threshold_timer,
+ hrtimer_forward_now(&context->threshold_timer,
ns_to_ktime(context->max_frame_interval));
}
}
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index 9f06258..7ec317a 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -341,6 +341,8 @@
if (bam_ret != 0 && bam_ret != -EAGAIN && bam_ret != -EFAULT) {
pr_err("[%s] %s: write returned error %d",
dev->name, __func__, bam_ret);
+ if (RMNET_IS_MODE_QOS(opmode))
+ skb_pull(skb, sizeof(struct QMI_QOS_HDR_S));
return -EPERM;
}
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index bd4328a..ad5e241 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -169,6 +169,7 @@
list_for_each_entry(pipe, &dev->pipes_q, list) {
/* Check this pipe's bit in the source mask */
if (BAM_PIPE_IS_ASSIGNED(pipe)
+ && (!pipe->disconnecting)
&& (source & pipe->pipe_index_mask)) {
/* This pipe has an interrupt pending */
pipe_handler(dev, pipe);
@@ -585,6 +586,7 @@
pipe->mode = -1;
pipe->num_descs = 0;
pipe->desc_size = 0;
+ pipe->disconnecting = false;
memset(&pipe->sys, 0, sizeof(pipe->sys));
INIT_LIST_HEAD(&pipe->sys.events_q);
}
diff --git a/drivers/platform/msm/sps/sps_bam.h b/drivers/platform/msm/sps/sps_bam.h
index da5dafd..a20156b 100644
--- a/drivers/platform/msm/sps/sps_bam.h
+++ b/drivers/platform/msm/sps/sps_bam.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -185,6 +185,7 @@
/* System mode control */
struct sps_bam_sys_mode sys;
+ bool disconnecting;
};
/* BAM device descriptor */
diff --git a/drivers/platform/msm/sps/sps_rm.c b/drivers/platform/msm/sps/sps_rm.c
index 7d7e1a6..d8c7a4d 100644
--- a/drivers/platform/msm/sps/sps_rm.c
+++ b/drivers/platform/msm/sps/sps_rm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -556,11 +556,8 @@
{
struct sps_connection *map = (void *)pipe->map;
struct sps_connect *cfg = &pipe->connect;
- struct sps_bam *bam = pipe->bam;
- unsigned long flags;
mutex_lock(&sps_rm->lock);
- spin_lock_irqsave(&bam->isr_lock, flags);
/* Free this connection */
if (cfg->mode == SPS_MODE_SRC)
@@ -574,7 +571,6 @@
sps_rm_remove_ref(map);
- spin_unlock_irqrestore(&bam->isr_lock, flags);
mutex_unlock(&sps_rm->lock);
return 0;
@@ -800,8 +796,9 @@
synchronize_irq(bam->props.irq);
spin_lock_irqsave(&bam->isr_lock, flags);
- result = sps_bam_pipe_disconnect(pipe->bam, pipe_index);
+ pipe->disconnecting = true;
spin_unlock_irqrestore(&bam->isr_lock, flags);
+ result = sps_bam_pipe_disconnect(pipe->bam, pipe_index);
if (result) {
SPS_ERR("sps:Failed to disconnect BAM 0x%x pipe %d",
pipe->bam->props.phys_addr,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b743bd6..48959ab 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1773,6 +1773,12 @@
*hba_handle = hba;
+ /*
+ * The device-initialize-sequence hasn't been invoked yet.
+ * Set the device to power-off state
+ */
+ ufshcd_set_ufs_dev_poweroff(hba);
+
async_schedule(ufshcd_async_scan, hba);
return 0;
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index adca457..e65c8cf 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -268,8 +268,28 @@
* Messages related to data channel management can't
* wait since they are holding reconfiguration lock.
* clk_pause in resume (which can change state back to
- * MSM_CTRL_AWAKE), will need that lock
+ * MSM_CTRL_AWAKE), will need that lock.
+ * Port disconnection, channel removal calls should pass
+ * through since there is no activity on the bus and
+ * those calls are triggered by clients due to
+ * device_down callback in that situation.
+ * Returning 0 on the disconnections and
+ * removals will ensure consistent state of channels,
+ * ports with the HW
+ * Remote requests to remove channel/port will be
+ * returned from the path where they wait on
+ * acknowledgement from ADSP
*/
+ if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
+ ((mc == SLIM_USR_MC_CHAN_CTRL ||
+ mc == SLIM_USR_MC_DISCONNECT_PORT ||
+ mc == SLIM_USR_MC_RECONFIG_NOW)))
+ return -EREMOTEIO;
+ if ((txn->mt == SLIM_MSG_MT_CORE) &&
+ ((mc == SLIM_MSG_MC_DISCONNECT_PORT ||
+ mc == SLIM_MSG_MC_NEXT_REMOVE_CHANNEL ||
+ mc == SLIM_USR_MC_RECONFIG_NOW)))
+ return 0;
if ((txn->mt == SLIM_MSG_MT_CORE) &&
((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
@@ -278,11 +298,11 @@
return -EREMOTEIO;
if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
((mc >= SLIM_USR_MC_DEFINE_CHAN &&
- mc <= SLIM_USR_MC_DISCONNECT_PORT)))
+ mc < SLIM_USR_MC_DISCONNECT_PORT)))
return -EREMOTEIO;
timeout = wait_for_completion_timeout(&dev->ctrl_up,
HZ);
- if (!timeout)
+ if (!timeout && dev->state == MSM_CTRL_DOWN)
return -ETIMEDOUT;
}
msm_slim_get_ctrl(dev);
@@ -487,10 +507,17 @@
ret = -ETIMEDOUT;
else
ret = txn->ec;
+ } else if (ret == -EREMOTEIO &&
+ (txn->mc == SLIM_USR_MC_CHAN_CTRL ||
+ txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
+ /* HW restarting, channel/port removal should succeed */
+ return 0;
}
+
if (ret) {
pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
txn->tid, ret);
+ WARN(1, "timeout during xfer and wait");
mutex_lock(&ctrl->m_ctrl);
ctrl->txnt[txn->tid] = NULL;
mutex_unlock(&ctrl->m_ctrl);
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index f6594c8..96fe2a8 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -313,14 +313,12 @@
sbdrv->device_down(sbdev);
return;
}
- if (sbdev->notified)
+ if (sbdev->notified || !sbdrv)
return;
ret = slim_get_logical_addr(sbdev, sbdev->e_addr, 6, &laddr);
if (!ret) {
- if (sbdrv)
- sbdev->notified = true;
- if (sbdrv->device_up)
- sbdrv->device_up(sbdev);
+ sbdev->notified = true;
+ sbdrv->device_up(sbdev);
}
}
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 61217dc..891eb2f 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -2426,8 +2426,8 @@
key = "qcom,cpu-sensors";
cpu_cnt = of_property_count_strings(node, key);
- if (cpu_cnt != num_possible_cpus()) {
- pr_err("%s: Wrong number of cpu\n", KBUILD_MODNAME);
+ if (cpu_cnt < num_possible_cpus()) {
+ pr_err("%s: Wrong number of cpu sensors\n", KBUILD_MODNAME);
ret = -EINVAL;
goto hotplug_node_fail;
}
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 739696d..21863e8 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -70,16 +70,19 @@
list_for_each_entry_safe(pos, var, &sensor_info_list, sensor_list) {
if (pos->sensor_id == sensor_id)
- break;
+ return pos;
}
- return pos;
+ return NULL;
}
int sensor_get_id(char *name)
{
struct sensor_info *pos, *var;
+ if (!name)
+ return -ENODEV;
+
list_for_each_entry_safe(pos, var, &sensor_info_list, sensor_list) {
if (!strcmp(pos->tz->type, name))
return pos->sensor_id;
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
index 1af076b..69f4b1c 100644
--- a/drivers/usb/gadget/f_qc_rndis.c
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -347,7 +347,7 @@
};
static struct usb_descriptor_header *eth_qc_ss_function[] = {
- (struct usb_descriptor_header *) &rndis_iad_descriptor,
+ (struct usb_descriptor_header *) &rndis_qc_iad_descriptor,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_qc_control_intf,
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 8287ad7..47b8e59 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2013, Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2014, 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
@@ -2551,6 +2551,8 @@
bool work = 0, srp_reqd, dcp;
pm_runtime_resume(otg->phy->dev);
+ if (motg->pm_done)
+ pm_runtime_get_sync(otg->phy->dev);
pr_debug("%s work\n", otg_state_string(otg->phy->state));
switch (otg->phy->state) {
case OTG_STATE_UNDEFINED:
@@ -2696,6 +2698,7 @@
*/
pm_runtime_mark_last_busy(otg->phy->dev);
pm_runtime_autosuspend(otg->phy->dev);
+ motg->pm_done = 1;
}
break;
case OTG_STATE_B_SRP_INIT:
@@ -4842,6 +4845,7 @@
dev_dbg(dev, "OTG runtime resume\n");
pm_runtime_get_noresume(dev);
+ motg->pm_done = 0;
return msm_otg_resume(motg);
}
#endif
@@ -4869,6 +4873,7 @@
dev_dbg(dev, "OTG PM resume\n");
+ motg->pm_done = 0;
atomic_set(&motg->pm_suspended, 0);
if (motg->async_int || motg->sm_work_pending) {
pm_runtime_get_noresume(dev);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index ad33ba3..8b390ca 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -892,11 +892,7 @@
mdp3_session->overlay = *req;
if (req->id == MSMFB_NEW_REQUEST) {
if (dma->source_config.stride != stride ||
- dma->source_config.width != req->src.width ||
- dma->source_config.height != req->src.height ||
dma->source_config.format != format) {
- dma->source_config.width = req->src.width;
- dma->source_config.height = req->src.height,
dma->source_config.format = format;
dma->source_config.stride = stride;
mdp3_clk_enable(1, 0);
@@ -918,7 +914,6 @@
struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
struct fb_info *fbi = mfd->fbi;
struct fb_fix_screeninfo *fix;
- struct mdss_panel_info *panel_info = mfd->panel_info;
int format;
fix = &fbi->fix;
@@ -927,8 +922,6 @@
if (mdp3_session->overlay.id == ndx && ndx == 1) {
struct mdp3_dma *dma = mdp3_session->dma;
- dma->source_config.width = panel_info->xres,
- dma->source_config.height = panel_info->yres,
dma->source_config.format = format;
dma->source_config.stride = fix->line_length;
mdp3_clk_enable(1, 0);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index ab54cbe..bc4ba6c 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -79,6 +79,11 @@
spinlock_t lock;
};
+struct mdss_fudge_factor {
+ u32 numer;
+ u32 denom;
+};
+
struct mdss_data_type {
u32 mdp_rev;
struct clk *mdp_clk[MDSS_MAX_CLK];
@@ -114,8 +119,8 @@
unsigned long min_mdp_clk;
u32 res_init;
- u32 bus_hdl;
+ u32 highest_bank_bit;
u32 smp_mb_cnt;
u32 smp_mb_size;
u32 smp_mb_per_pipe;
@@ -125,6 +130,16 @@
u32 max_bw_low;
u32 max_bw_high;
+ u32 axi_port_cnt;
+ u32 curr_bw_uc_idx;
+ u32 bus_hdl;
+ struct msm_bus_scale_pdata *bus_scale_table;
+
+ struct mdss_fudge_factor ab_factor;
+ struct mdss_fudge_factor ib_factor;
+ struct mdss_fudge_factor high_ib_factor;
+ struct mdss_fudge_factor clk_factor;
+
struct mdss_hw_settings *hw_settings;
struct mdss_mdp_pipe *vig_pipes;
@@ -162,9 +177,10 @@
struct early_suspend early_suspend;
struct mdss_debug_inf debug_inf;
- int current_bus_idx;
bool mixer_switched;
struct mdss_panel_cfg pan_cfg;
+
+ int handoff_pending;
};
extern struct mdss_data_type *mdss_res;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 08cdcef..41aaf61 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -2,7 +2,7 @@
* Core MDSS framebuffer driver.
*
* Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2014, 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
@@ -121,7 +121,11 @@
if (notify > NOTIFY_UPDATE_POWER_OFF)
return -EINVAL;
- if (notify == NOTIFY_UPDATE_START) {
+ if (mfd->update.is_suspend) {
+ to_user = NOTIFY_TYPE_SUSPEND;
+ mfd->update.is_suspend = 0;
+ ret = 1;
+ } else if (notify == NOTIFY_UPDATE_START) {
INIT_COMPLETION(mfd->update.comp);
ret = wait_for_completion_timeout(
&mfd->update.comp, 4 * HZ);
@@ -264,10 +268,14 @@
return ret;
}
-static void mdss_fb_parse_dt_split(struct msm_fb_data_type *mfd)
+static void mdss_fb_parse_dt(struct msm_fb_data_type *mfd)
{
u32 data[2];
struct platform_device *pdev = mfd->pdev;
+
+ mfd->splash_logo_enabled = of_property_read_bool(pdev->dev.of_node,
+ "qcom,mdss-fb-splash-logo-enabled");
+
if (of_property_read_u32_array(pdev->dev.of_node, "qcom,mdss-fb-split",
data, 2))
return;
@@ -439,19 +447,29 @@
mfd->mdp_sync_pt_data.timeline =
sw_sync_timeline_create(timeline_name);
if (mfd->mdp_sync_pt_data.timeline == NULL) {
- pr_err("%s: cannot create time line", __func__);
+ pr_err("cannot create release fence time line\n");
return -ENOMEM;
}
mfd->mdp_sync_pt_data.notifier.notifier_call =
__mdss_fb_sync_buf_done_callback;
}
- if ((mfd->panel.type == WRITEBACK_PANEL) ||
- (mfd->panel.type == MIPI_CMD_PANEL))
- mfd->mdp_sync_pt_data.threshold = 1;
- else
- mfd->mdp_sync_pt_data.threshold = 2;
- if (mfd->index == 0) {
+ switch (mfd->panel.type) {
+ case WRITEBACK_PANEL:
+ mfd->mdp_sync_pt_data.threshold = 1;
+ mfd->mdp_sync_pt_data.retire_threshold = 0;
+ break;
+ case MIPI_CMD_PANEL:
+ mfd->mdp_sync_pt_data.threshold = 1;
+ mfd->mdp_sync_pt_data.retire_threshold = 1;
+ break;
+ default:
+ mfd->mdp_sync_pt_data.threshold = 2;
+ mfd->mdp_sync_pt_data.retire_threshold = 0;
+ break;
+ }
+
+ if (mfd->splash_logo_enabled) {
mfd->splash_thread = kthread_run(mdss_fb_splash_thread, mfd,
"mdss_fb_splash");
if (IS_ERR(mfd->splash_thread)) {
@@ -773,6 +791,7 @@
}
mutex_lock(&mfd->update.lock);
mfd->update.type = NOTIFY_TYPE_UPDATE;
+ mfd->update.is_suspend = 0;
mutex_unlock(&mfd->update.lock);
}
break;
@@ -787,7 +806,9 @@
mutex_lock(&mfd->update.lock);
mfd->update.type = NOTIFY_TYPE_SUSPEND;
+ mfd->update.is_suspend = 1;
mutex_unlock(&mfd->update.lock);
+ complete(&mfd->update.comp);
del_timer(&mfd->no_update.timer);
mfd->no_update.value = NOTIFY_TYPE_SUSPEND;
complete(&mfd->no_update.comp);
@@ -1144,7 +1165,7 @@
mfd->panel_power_on = false;
mfd->dcm_state = DCM_UNINIT;
- mdss_fb_parse_dt_split(mfd);
+ mdss_fb_parse_dt(mfd);
if (mdss_fb_alloc_fbmem(mfd)) {
pr_err("unable to allocate framebuffer memory\n");
@@ -1993,42 +2014,37 @@
}
/**
- * mdss_fb_sync_get_rel_fence() - get release fence from sync pt timeline
- * @sync_pt_data: Sync pt structure holding timeline and fence info.
+ * mdss_fb_sync_get_fence() - get fence from timeline
+ * @timeline: Timeline to create the fence on
+ * @fence_name: Name of the fence that will be created for debugging
+ * @val: Timeline value at which the fence will be signaled
*
- * Function returns a release fence on the timeline associated with the
- * sync pt struct given and it's associated information. The release fence
- * created can be used to signal when buffers provided will be released.
+ * Function returns a fence on the timeline given with the name provided.
+ * The fence created will be signaled when the timeline is advanced.
*/
-static struct sync_fence *__mdss_fb_sync_get_rel_fence(
- struct msm_sync_pt_data *sync_pt_data)
+struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline,
+ const char *fence_name, int val)
{
- struct sync_pt *rel_sync_pt;
- struct sync_fence *rel_fence;
- int val;
+ struct sync_pt *sync_pt;
+ struct sync_fence *fence;
- val = sync_pt_data->timeline_value + sync_pt_data->threshold +
- atomic_read(&sync_pt_data->commit_cnt);
+ pr_debug("%s: buf sync fence timeline=%d\n", fence_name, val);
- pr_debug("%s: buf sync rel fence timeline=%d\n",
- sync_pt_data->fence_name, val);
-
- rel_sync_pt = sw_sync_pt_create(sync_pt_data->timeline, val);
- if (rel_sync_pt == NULL) {
- pr_err("%s: cannot create sync point\n",
- sync_pt_data->fence_name);
+ sync_pt = sw_sync_pt_create(timeline, val);
+ if (sync_pt == NULL) {
+ pr_err("%s: cannot create sync point\n", fence_name);
return NULL;
}
/* create fence */
- rel_fence = sync_fence_create(sync_pt_data->fence_name, rel_sync_pt);
- if (rel_fence == NULL) {
- sync_pt_free(rel_sync_pt);
- pr_err("%s: cannot create fence\n", sync_pt_data->fence_name);
+ fence = sync_fence_create(fence_name, sync_pt);
+ if (fence == NULL) {
+ sync_pt_free(sync_pt);
+ pr_err("%s: cannot create fence\n", fence_name);
return NULL;
}
- return rel_fence;
+ return fence;
}
static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data,
@@ -2036,8 +2052,10 @@
{
int i, ret = 0;
int acq_fen_fd[MDP_MAX_FENCE_FD];
- struct sync_fence *fence, *rel_fence;
+ struct sync_fence *fence, *rel_fence, *retire_fence;
int rel_fen_fd;
+ int retire_fen_fd;
+ int val;
if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
(sync_pt_data->timeline == NULL))
@@ -2074,7 +2092,12 @@
if (ret)
goto buf_sync_err_1;
- rel_fence = __mdss_fb_sync_get_rel_fence(sync_pt_data);
+ val = sync_pt_data->timeline_value + sync_pt_data->threshold +
+ atomic_read(&sync_pt_data->commit_cnt);
+
+ /* Set release fence */
+ rel_fence = mdss_fb_sync_get_fence(sync_pt_data->timeline,
+ sync_pt_data->fence_name, val);
if (IS_ERR_OR_NULL(rel_fence)) {
pr_err("%s: unable to retrieve release fence\n",
sync_pt_data->fence_name);
@@ -2098,6 +2121,50 @@
pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name);
goto buf_sync_err_3;
}
+
+ if (!(buf_sync->flags & MDP_BUF_SYNC_FLAG_RETIRE_FENCE))
+ goto skip_retire_fence;
+
+ if (sync_pt_data->get_retire_fence)
+ retire_fence = sync_pt_data->get_retire_fence(sync_pt_data);
+ else
+ retire_fence = NULL;
+
+ if (IS_ERR_OR_NULL(retire_fence)) {
+ val += sync_pt_data->retire_threshold;
+ retire_fence = mdss_fb_sync_get_fence(
+ sync_pt_data->timeline, "mdp-retire", val);
+ }
+
+ if (IS_ERR_OR_NULL(retire_fence)) {
+ pr_err("%s: unable to retrieve retire fence\n",
+ sync_pt_data->fence_name);
+ ret = retire_fence ? PTR_ERR(rel_fence) : -ENOMEM;
+ goto buf_sync_err_3;
+ }
+ retire_fen_fd = get_unused_fd_flags(0);
+
+ if (retire_fen_fd < 0) {
+ pr_err("%s: get_unused_fd_flags failed for retire fence\n",
+ sync_pt_data->fence_name);
+ ret = -EIO;
+ sync_fence_put(retire_fence);
+ goto buf_sync_err_3;
+ }
+
+ sync_fence_install(retire_fence, retire_fen_fd);
+
+ ret = copy_to_user(buf_sync->retire_fen_fd, &retire_fen_fd,
+ sizeof(int));
+ if (ret) {
+ pr_err("%s: copy_to_user failed for retire fence\n",
+ sync_pt_data->fence_name);
+ put_unused_fd(retire_fen_fd);
+ sync_fence_put(retire_fence);
+ goto buf_sync_err_3;
+ }
+
+skip_retire_fence:
mutex_unlock(&sync_pt_data->sync_mutex);
if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
@@ -2355,3 +2422,27 @@
}
module_init(mdss_fb_init);
+
+int mdss_fb_suspres_panel(struct device *dev, void *data)
+{
+ struct msm_fb_data_type *mfd;
+ int rc;
+ u32 event;
+
+ if (!data) {
+ pr_err("Device state not defined\n");
+ return -EINVAL;
+ }
+ mfd = dev_get_drvdata(dev);
+ if (!mfd)
+ return 0;
+
+ event = *((bool *) data) ? MDSS_EVENT_RESUME : MDSS_EVENT_SUSPEND;
+
+ rc = mdss_fb_send_panel_event(mfd, event, NULL);
+ if (rc)
+ pr_warn("unable to %s fb%d (%d)\n",
+ event == MDSS_EVENT_RESUME ? "resume" : "suspend",
+ mfd->index, rc);
+ return rc;
+}
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index e796fc6..2e024c9 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, 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
@@ -85,6 +85,7 @@
struct completion comp;
struct mutex lock;
int value;
+ int is_suspend;
};
struct msm_sync_pt_data {
@@ -95,13 +96,16 @@
struct sw_sync_timeline *timeline;
int timeline_value;
u32 threshold;
-
+ u32 retire_threshold;
atomic_t commit_cnt;
bool flushed;
bool async_wait_fences;
struct mutex sync_mutex;
struct notifier_block notifier;
+
+ struct sync_fence *(*get_retire_fence)
+ (struct msm_sync_pt_data *sync_pt_data);
};
struct msm_fb_data_type;
@@ -211,6 +215,7 @@
bool shutdown_pending;
struct task_struct *splash_thread;
+ bool splash_logo_enabled;
struct msm_fb_backup_type msm_fb_backup;
struct completion power_set_comp;
@@ -244,6 +249,9 @@
void mdss_fb_update_backlight(struct msm_fb_data_type *mfd);
void mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data);
void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data);
+struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline,
+ const char *fence_name, int val);
int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp);
int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state);
+int mdss_fb_suspres_panel(struct device *dev, void *data);
#endif /* MDSS_FB_H */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 9985c71..357cf89 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -120,6 +120,7 @@
static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
int val, bool force);
static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
+static void hdmi_tx_en_encryption(struct hdmi_tx_ctrl *hdmi_ctrl, u32 on);
struct mdss_hw hdmi_tx_hw = {
.hw_ndx = MDSS_HW_HDMI,
@@ -134,6 +135,7 @@
};
struct dss_gpio ddc_gpio_config[] = {
+ {0, 1, COMPATIBLE_NAME "-ddc-mux-sel"},
{0, 1, COMPATIBLE_NAME "-ddc-clk"},
{0, 1, COMPATIBLE_NAME "-ddc-data"}
};
@@ -915,11 +917,11 @@
switch (status) {
case HDCP_STATE_AUTHENTICATED:
if (hdmi_ctrl->hpd_state) {
- /* Clear AV Mute */
- rc = hdmi_tx_config_avmute(hdmi_ctrl, 0);
- if (rc)
- DEV_ERR("%s: Failed to clear av mute. rc=%d\n",
- __func__, rc);
+ if (hdmi_ctrl->pdata.primary)
+ hdmi_tx_en_encryption(hdmi_ctrl, true);
+ else
+ /* Clear AV Mute */
+ rc = hdmi_tx_config_avmute(hdmi_ctrl, 0);
hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1, false);
}
break;
@@ -927,11 +929,11 @@
hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
if (hdmi_ctrl->hpd_state) {
- /* Set AV Mute */
- rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
- if (rc)
- DEV_ERR("%s: Failed to set av mute. rc=%d\n",
- __func__, rc);
+ if (hdmi_ctrl->pdata.primary)
+ hdmi_tx_en_encryption(hdmi_ctrl, false);
+ else
+ /* Set AV Mute */
+ rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
DEV_DBG("%s: Reauthenticating\n", __func__);
rc = hdmi_hdcp_reauthenticate(
@@ -1645,6 +1647,28 @@
DSS_REG_W(io, HDMI_GEN_PKT_CTRL, packet_control);
} /* hdmi_tx_set_spd_infoframe */
+static void hdmi_tx_en_encryption(struct hdmi_tx_ctrl *hdmi_ctrl, u32 on)
+{
+ u32 reg_val;
+ struct dss_io_data *io = NULL;
+
+ if (!hdmi_ctrl->hdcp_feature_on || !hdmi_ctrl->present_hdcp)
+ return;
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+
+ mutex_lock(&hdmi_ctrl->mutex);
+ reg_val = DSS_REG_R_ND(io, HDMI_CTRL);
+
+ if (on)
+ reg_val |= BIT(2);
+ else
+ reg_val &= ~BIT(2);
+ DSS_REG_W(io, HDMI_CTRL, reg_val);
+
+ mutex_unlock(&hdmi_ctrl->mutex);
+} /* hdmi_tx_en_encryption */
+
static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
{
struct dss_io_data *io = NULL;
@@ -1661,12 +1685,14 @@
return;
}
+ mutex_lock(&hdmi_ctrl->mutex);
if (power_on) {
/* Enable the block */
reg_val |= BIT(0);
/* HDMI Encryption, if HDCP is enabled */
- if (hdmi_ctrl->hdcp_feature_on && hdmi_ctrl->present_hdcp)
+ if (hdmi_ctrl->hdcp_feature_on &&
+ hdmi_ctrl->present_hdcp && !hdmi_ctrl->pdata.primary)
reg_val |= BIT(2);
/* Set transmission mode to DVI based in EDID info */
@@ -1676,6 +1702,7 @@
}
DSS_REG_W(io, HDMI_CTRL, reg_val);
+ mutex_unlock(&hdmi_ctrl->mutex);
DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
power_on ? "Enable" : "Disable", reg_val);
@@ -3108,10 +3135,10 @@
case MDSS_EVENT_PANEL_ON:
if (hdmi_ctrl->hdcp_feature_on && hdmi_ctrl->present_hdcp) {
/* Set AV Mute before starting authentication */
- rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
- if (rc)
- DEV_ERR("%s: Failed to set av mute. rc=%d\n",
- __func__, rc);
+ if (hdmi_ctrl->pdata.primary)
+ hdmi_tx_en_encryption(hdmi_ctrl, false);
+ else
+ rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
DEV_DBG("%s: Starting HDCP authentication\n", __func__);
rc = hdmi_hdcp_authenticate(
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index fe33331..a9f6dbc 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1,7 +1,7 @@
/*
* MDSS MDP Interface (used by framebuffer core)
*
- * Copyright (c) 2007-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2007-2014, The Linux Foundation. All rights reserved.
* Copyright (C) 2007 Google Incorporated
*
* This software is licensed under the terms of the GNU General Public
@@ -80,21 +80,7 @@
static DEFINE_SPINLOCK(mdp_lock);
static DEFINE_MUTEX(mdp_clk_lock);
static DEFINE_MUTEX(bus_bw_lock);
-
-#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \
- { \
- .src = MSM_BUS_MASTER_MDP_PORT0, \
- .dst = MSM_BUS_SLAVE_EBI_CH0, \
- .ab = (ab_val), \
- .ib = (ib_val), \
- }
-
-static struct msm_bus_vectors mdp_bus_vectors[] = {
- MDP_BUS_VECTOR_ENTRY(0, 0),
- MDP_BUS_VECTOR_ENTRY(SZ_128M, SZ_256M),
- MDP_BUS_VECTOR_ENTRY(SZ_256M, SZ_512M),
-};
-static struct msm_bus_paths mdp_bus_usecases[ARRAY_SIZE(mdp_bus_vectors)];
+static DEFINE_MUTEX(mdp_iommu_lock);
static struct mdss_panel_intf pan_types[] = {
{"dsi", MDSS_PANEL_INTF_DSI},
@@ -102,12 +88,6 @@
{"hdmi", MDSS_PANEL_INTF_HDMI},
};
-static struct msm_bus_scale_pdata mdp_bus_scale_table = {
- .usecase = mdp_bus_usecases,
- .num_usecases = ARRAY_SIZE(mdp_bus_usecases),
- .name = "mdss_mdp",
-};
-
struct mdss_iommu_map_type mdss_iommu_map[MDSS_IOMMU_MAX_DOMAIN] = {
[MDSS_IOMMU_DOMAIN_UNSECURE] = {
.client_name = "mdp_ns",
@@ -155,6 +135,7 @@
static int mdss_mdp_parse_dt_smp(struct platform_device *pdev);
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev);
static int mdss_mdp_parse_dt_ad_cfg(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_bus_scale(struct platform_device *pdev);
u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp)
{
@@ -331,23 +312,17 @@
static int mdss_mdp_bus_scale_register(struct mdss_data_type *mdata)
{
if (!mdata->bus_hdl) {
- struct msm_bus_scale_pdata *bus_pdata = &mdp_bus_scale_table;
- int i;
-
- for (i = 0; i < bus_pdata->num_usecases; i++) {
- mdp_bus_usecases[i].num_paths = 1;
- mdp_bus_usecases[i].vectors = &mdp_bus_vectors[i];
- }
-
- mdata->bus_hdl = msm_bus_scale_register_client(bus_pdata);
- if (!mdata->bus_hdl) {
- pr_err("not able to get bus scale\n");
- return -ENOMEM;
+ mdata->bus_hdl =
+ msm_bus_scale_register_client(mdata->bus_scale_table);
+ if (IS_ERR_VALUE(mdata->bus_hdl)) {
+ pr_err("bus_client register failed\n");
+ return -EINVAL;
}
pr_debug("register bus_hdl=%x\n", mdata->bus_hdl);
}
- return 0;
+
+ return mdss_mdp_bus_scale_set_quota(AB_QUOTA, IB_QUOTA);
}
static void mdss_mdp_bus_scale_unregister(struct mdss_data_type *mdata)
@@ -360,7 +335,7 @@
int mdss_mdp_bus_scale_set_quota(u64 ab_quota, u64 ib_quota)
{
- int bus_idx;
+ int new_uc_idx;
if (mdss_res->bus_hdl < 1) {
pr_err("invalid bus handle %d\n", mdss_res->bus_hdl);
@@ -368,32 +343,50 @@
}
if ((ab_quota | ib_quota) == 0) {
- bus_idx = 0;
+ new_uc_idx = 0;
} else {
- int num_cases = mdp_bus_scale_table.num_usecases;
+ int i;
struct msm_bus_vectors *vect = NULL;
+ struct msm_bus_scale_pdata *bw_table =
+ mdss_res->bus_scale_table;
+ unsigned long size;
- bus_idx = (mdss_res->current_bus_idx % (num_cases - 1)) + 1;
-
- vect = mdp_bus_scale_table.usecase[mdss_res->current_bus_idx].
- vectors;
-
- /* avoid performing updates for small changes */
- if ((ALIGN(ab_quota, SZ_64M) == ALIGN(vect->ab, SZ_64M)) &&
- (ALIGN(ib_quota, SZ_64M) == ALIGN(vect->ib, SZ_64M))) {
- pr_debug("skip bus scaling, no change in vectors\n");
- return 0;
+ if (!bw_table || !mdss_res->axi_port_cnt) {
+ pr_err("invalid input\n");
+ return -EINVAL;
}
- vect = mdp_bus_scale_table.usecase[bus_idx].vectors;
- vect->ab = ab_quota;
- vect->ib = ib_quota;
+ size = SZ_64M / mdss_res->axi_port_cnt;
- pr_debug("bus scale idx=%d ab=%llu ib=%llu\n", bus_idx,
- vect->ab, vect->ib);
+ ab_quota = div_u64(ab_quota, mdss_res->axi_port_cnt);
+ ib_quota = div_u64(ib_quota, mdss_res->axi_port_cnt);
+
+ new_uc_idx = (mdss_res->curr_bw_uc_idx %
+ (bw_table->num_usecases - 1)) + 1;
+
+ for (i = 0; i < mdss_res->axi_port_cnt; i++) {
+ vect = &bw_table->usecase[mdss_res->curr_bw_uc_idx].
+ vectors[i];
+
+ /* avoid performing updates for small changes */
+ if ((ALIGN(ab_quota, size) == ALIGN(vect->ab, size)) &&
+ (ALIGN(ib_quota, size) == ALIGN(vect->ib, size))) {
+ pr_debug("skip bus scaling, no changes\n");
+ return 0;
+ }
+
+ vect = &bw_table->usecase[new_uc_idx].vectors[i];
+ vect->ab = ab_quota;
+ vect->ib = ib_quota;
+
+ pr_debug("uc_idx=%d path_idx=%d ab=%llu ib=%llu\n",
+ new_uc_idx, i, vect->ab, vect->ib);
+ }
}
- mdss_res->current_bus_idx = bus_idx;
- return msm_bus_scale_client_update_request(mdss_res->bus_hdl, bus_idx);
+ mdss_res->curr_bw_uc_idx = new_uc_idx;
+
+ return msm_bus_scale_client_update_request(mdss_res->bus_hdl,
+ new_uc_idx);
}
static inline u32 mdss_mdp_irq_mask(u32 intr_type, u32 intf_num)
@@ -653,7 +646,9 @@
} else {
pm_runtime_get_sync(&mdata->pdev->dev);
msm_bus_scale_client_update_request(
- mdata->bus_hdl, mdata->current_bus_idx);
+ mdata->bus_hdl, mdata->curr_bw_uc_idx);
+ if (!mdata->handoff_pending)
+ mdss_iommu_attach(mdata);
}
}
@@ -784,8 +779,10 @@
struct mdss_iommu_map_type *iomap;
int i;
+ mutex_lock(&mdp_iommu_lock);
if (mdata->iommu_attached) {
pr_debug("mdp iommu already attached\n");
+ mutex_unlock(&mdp_iommu_lock);
return 0;
}
@@ -802,6 +799,7 @@
}
mdata->iommu_attached = true;
+ mutex_unlock(&mdp_iommu_lock);
return 0;
}
@@ -812,8 +810,10 @@
struct mdss_iommu_map_type *iomap;
int i;
+ mutex_lock(&mdp_iommu_lock);
if (!mdata->iommu_attached) {
pr_debug("mdp iommu already dettached\n");
+ mutex_unlock(&mdp_iommu_lock);
return 0;
}
@@ -830,6 +830,7 @@
}
mdata->iommu_attached = false;
+ mutex_unlock(&mdp_iommu_lock);
return 0;
}
@@ -1048,11 +1049,13 @@
if (mdata != NULL) {
if (on) {
pr_debug("Enable MDP FS for splash.\n");
+ mdata->handoff_pending = true;
regulator_enable(mdata->fs);
mdss_hw_init(mdata);
} else {
pr_debug("Disable MDP FS for splash.\n");
regulator_disable(mdata->fs);
+ mdata->handoff_pending = false;
}
} else {
pr_warn("mdss mdata not initialized\n");
@@ -1087,6 +1090,8 @@
SPRINT(" bwc");
if (mdata->has_decimation)
SPRINT(" decimation");
+ if (mdata->highest_bank_bit)
+ SPRINT(" tile_format");
SPRINT("\n");
return cnt;
@@ -1207,7 +1212,6 @@
pr_err("unable to register bus scaling\n");
goto probe_done;
}
- mdss_mdp_bus_scale_set_quota(AB_QUOTA, IB_QUOTA);
rc = mdss_mdp_debug_init(mdata);
if (rc) {
@@ -1547,6 +1551,12 @@
return rc;
}
+ rc = mdss_mdp_parse_dt_bus_scale(pdev);
+ if (rc) {
+ pr_err("Error in device tree : bus scale\n");
+ return rc;
+ }
+
return 0;
}
@@ -2003,6 +2013,24 @@
return rc;
}
+static void mdss_mdp_parse_dt_fudge_factors(struct platform_device *pdev,
+ char *prop_name, struct mdss_fudge_factor *ff)
+{
+ int rc;
+ u32 data[2] = {0, 0};
+
+ ff->numer = 1;
+ ff->denom = 1;
+
+ rc = mdss_mdp_parse_dt_handler(pdev, prop_name, data, 2);
+ if (rc) {
+ pr_debug("err reading %s\n", prop_name);
+ } else {
+ ff->numer = data[0];
+ ff->denom = data[1];
+ }
+}
+
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
{
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
@@ -2022,6 +2050,10 @@
"qcom,mdss-has-wfd-blk");
prop = of_find_property(pdev->dev.of_node, "batfet-supply", NULL);
mdata->batfet_required = prop ? true : false;
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,mdss-highest-bank-bit", &(mdata->highest_bank_bit));
+ if (rc)
+ pr_debug("Could not read optional property: highest bank bit\n");
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,max-bandwidth-low-kbps", &mdata->max_bw_low);
@@ -2033,6 +2065,15 @@
if (rc)
pr_debug("max bandwidth (high) property not specified\n");
+ mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-ab-factor",
+ &mdata->ab_factor);
+ mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-ib-factor",
+ &mdata->ib_factor);
+ mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-high-ib-factor",
+ &mdata->high_ib_factor);
+ mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-clk-factor",
+ &mdata->clk_factor);
+
return 0;
}
@@ -2076,6 +2117,31 @@
return rc;
}
+static int mdss_mdp_parse_dt_bus_scale(struct platform_device *pdev)
+{
+ int rc;
+ struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,msm-bus,num-paths",
+ &mdata->axi_port_cnt);
+ if (rc) {
+ pr_err("Error. qcom,msm-bus,num-paths prop not found.rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ mdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+ if (IS_ERR_OR_NULL(mdata->bus_scale_table)) {
+ rc = PTR_ERR(mdata->bus_scale_table);
+ if (!rc)
+ rc = -EINVAL;
+ pr_err("msm_bus_cl_get_pdata failed. rc=%d\n", rc);
+ mdata->bus_scale_table = NULL;
+ }
+
+ return rc;
+}
+
static int mdss_mdp_parse_dt_handler(struct platform_device *pdev,
char *prop_name, u32 *offsets, int len)
{
@@ -2339,11 +2405,12 @@
static int mdss_mdp_runtime_resume(struct device *dev)
{
struct mdss_data_type *mdata = dev_get_drvdata(dev);
+ bool device_on = true;
if (!mdata)
return -ENODEV;
dev_dbg(dev, "pm_runtime: resuming...\n");
-
+ device_for_each_child(dev, &device_on, mdss_fb_suspres_panel);
mdss_mdp_footswitch_ctrl(mdata, true);
return 0;
@@ -2363,6 +2430,7 @@
static int mdss_mdp_runtime_suspend(struct device *dev)
{
struct mdss_data_type *mdata = dev_get_drvdata(dev);
+ bool device_on = false;
if (!mdata)
return -ENODEV;
dev_dbg(dev, "pm_runtime: suspending...\n");
@@ -2371,6 +2439,7 @@
pr_err("MDP suspend failed\n");
return -EBUSY;
}
+ device_for_each_child(dev, &device_on, mdss_fb_suspres_panel);
mdss_mdp_footswitch_ctrl(mdata, false);
return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 1c4efb4..4f1da63 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -237,7 +237,7 @@
u8 unpack_count; /* 0 = 1 component, 1 = 2 component ... */
u8 bpp;
u8 alpha_enable; /* source has alpha */
-
+ u8 tile;
u8 bits[MAX_PLANES];
u8 element[MAX_PLANES];
};
@@ -422,6 +422,11 @@
u32 splash_mem_addr;
u32 splash_mem_size;
u32 sd_enabled;
+
+ struct sw_sync_timeline *vsync_timeline;
+ struct mdss_mdp_vsync_handler vsync_retire_handler;
+ struct work_struct retire_work;
+ int retire_cnt;
};
struct mdss_mdp_perf_params {
@@ -520,7 +525,7 @@
int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl);
int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg);
int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
- struct mdss_mdp_perf_params *perf);
+ struct mdss_mdp_perf_params *perf, struct mdss_mdp_img_rect *roi);
int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event);
void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl,
struct notifier_block *notifier);
@@ -632,6 +637,10 @@
void mdss_mdp_intersect_rect(struct mdss_mdp_img_rect *res_rect,
const struct mdss_mdp_img_rect *dst_rect,
const struct mdss_mdp_img_rect *sci_rect);
+void mdss_mdp_crop_rect(struct mdss_mdp_img_rect *src_rect,
+ struct mdss_mdp_img_rect *dst_rect,
+ const struct mdss_mdp_img_rect *sci_rect);
+
int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd);
int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index db67773..d96ac45 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -24,14 +24,26 @@
/* truncate at 1k */
#define MDSS_MDP_BUS_FACTOR_SHIFT 10
-/* 1.5 bus fudge factor */
-#define MDSS_MDP_BUS_FUDGE_FACTOR_IB(val) (((val) / 2) * 3)
-#define MDSS_MDP_BUS_FUDGE_FACTOR_HIGH_IB(val) (val << 1)
-#define MDSS_MDP_BUS_FUDGE_FACTOR_AB(val) (val << 1)
#define MDSS_MDP_BUS_FLOOR_BW (1600000000ULL >> MDSS_MDP_BUS_FACTOR_SHIFT)
-/* 1.25 clock fudge factor */
-#define MDSS_MDP_CLK_FUDGE_FACTOR(val) (((val) * 5) / 4)
+static inline u64 fudge_factor(u64 val, u32 numer, u32 denom)
+{
+ u64 result = (val * (u64)numer);
+ do_div(result, denom);
+ return result;
+}
+
+#define AB_FUDGE_FACTOR(val) fudge_factor((val), \
+ (mdss_res->ab_factor.numer), (mdss_res->ab_factor.denom))
+
+#define IB_FUDGE_FACTOR(val) fudge_factor((val), \
+ (mdss_res->ib_factor.numer), (mdss_res->ib_factor.denom))
+
+#define HIGH_IB_FUDGE_FACTOR(val) fudge_factor((val), \
+ (mdss_res->high_ib_factor.numer), (mdss_res->high_ib_factor.denom))
+
+#define CLK_FUDGE_FACTOR(val) fudge_factor((val), \
+ (mdss_res->clk_factor.numer), (mdss_res->clk_factor.denom))
enum {
MDSS_MDP_PERF_UPDATE_SKIP,
@@ -63,6 +75,25 @@
pinfo->clk_rate;
}
+static inline u32 mdss_mdp_clk_fudge_factor(struct mdss_mdp_mixer *mixer,
+ u32 rate)
+{
+ struct mdss_panel_info *pinfo = &mixer->ctl->panel_data->panel_info;
+
+ rate = CLK_FUDGE_FACTOR(rate);
+
+ /*
+ * If the panel is video mode and its back porch period is
+ * small, the workaround of increasing mdp clk is needed to
+ * avoid underrun.
+ */
+ if (mixer->ctl->is_video_mode && pinfo &&
+ (pinfo->lcdc.v_back_porch < MDP_MIN_VBP))
+ rate = CLK_FUDGE_FACTOR(rate);
+
+ return rate;
+}
+
static u32 __mdss_mdp_ctrl_perf_ovrd_helper(struct mdss_mdp_mixer *mixer,
u32 *npipe)
{
@@ -116,11 +147,11 @@
ctl->mixer_right, &npipe);
}
- *ab_quota = MDSS_MDP_BUS_FUDGE_FACTOR_AB(*ab_quota);
+ *ab_quota = AB_FUDGE_FACTOR(*ab_quota);
if (npipe > 1)
- *ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_HIGH_IB(*ib_quota);
+ *ib_quota = HIGH_IB_FUDGE_FACTOR(*ib_quota);
else
- *ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_IB(*ib_quota);
+ *ib_quota = IB_FUDGE_FACTOR(*ib_quota);
if (ovrd && (*ib_quota < MDSS_MDP_BUS_FLOOR_BW)) {
*ib_quota = MDSS_MDP_BUS_FLOOR_BW;
@@ -162,7 +193,6 @@
mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
}
if (flags & MDSS_MDP_PERF_UPDATE_CLK) {
- clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(clk_rate);
pr_debug("update clk rate = %lu HZ\n", clk_rate);
mdss_mdp_set_clk_rate(clk_rate);
}
@@ -183,16 +213,20 @@
* (MDP clock requirement) based on frame size and scaling requirements.
*/
int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
- struct mdss_mdp_perf_params *perf)
+ struct mdss_mdp_perf_params *perf, struct mdss_mdp_img_rect *roi)
{
struct mdss_mdp_mixer *mixer;
int fps = DEFAULT_FRAME_RATE;
u32 quota, rate, v_total, src_h;
+ struct mdss_mdp_img_rect src, dst;
if (!pipe || !perf || !pipe->mixer)
return -EINVAL;
mixer = pipe->mixer;
+ dst = pipe->dst;
+ src = pipe->src;
+
if (mixer->rotator_mode) {
v_total = pipe->flags & MDP_ROT_90 ? pipe->dst.w : pipe->dst.h;
} else if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
@@ -205,14 +239,17 @@
v_total = mixer->height;
}
+ if (roi)
+ mdss_mdp_crop_rect(&src, &dst, roi);
+
/*
* when doing vertical decimation lines will be skipped, hence there is
* no need to account for these lines in MDP clock or request bus
* bandwidth to fetch them.
*/
- src_h = pipe->src.h >> pipe->vert_deci;
+ src_h = src.h >> pipe->vert_deci;
- quota = fps * pipe->src.w * src_h;
+ quota = fps * src.w * src_h;
if (pipe->src_fmt->chroma_sample == MDSS_MDP_CHROMA_420)
/*
* with decimation, chroma is not downsampled, this means we
@@ -225,9 +262,9 @@
else
quota *= pipe->src_fmt->bpp;
- rate = pipe->dst.w;
- if (src_h > pipe->dst.h)
- rate = (rate * src_h) / pipe->dst.h;
+ rate = dst.w;
+ if (src_h > dst.h)
+ rate = (rate * src_h) / dst.h;
rate *= v_total * fps;
if (mixer->rotator_mode) {
@@ -235,11 +272,16 @@
quota *= 2; /* bus read + write */
perf->ib_quota = quota;
} else {
- perf->ib_quota = (quota / pipe->dst.h) * v_total;
+ perf->ib_quota = (quota / dst.h) * v_total;
}
+
perf->ab_quota = quota;
+ rate = mdss_mdp_clk_fudge_factor(mixer, rate);
perf->mdp_clk_rate = rate;
+ pr_debug("src(w,h)(%d,%d) dst(w,h)(%d,%d) v_total=%d v_deci=%d fps=%d\n",
+ pipe->src.w, pipe->src.h, pipe->dst.w, pipe->dst.h, v_total,
+ pipe->vert_deci, fps);
pr_debug("mixer=%d pnum=%d clk_rate=%u bus ab=%u ib=%u\n",
mixer->num, pipe->num, rate, perf->ab_quota, perf->ib_quota);
@@ -273,8 +315,7 @@
v_total = mixer->height;
}
*clk_rate = mixer->width * v_total * fps;
- if (pinfo && pinfo->lcdc.v_back_porch < MDP_MIN_VBP)
- *clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(*clk_rate);
+ *clk_rate = mdss_mdp_clk_fudge_factor(mixer, *clk_rate);
if (!pinfo) {
/* perf for bus writeback */
@@ -290,7 +331,7 @@
if (pipe == NULL)
continue;
- if (mdss_mdp_perf_calc_pipe(pipe, &perf))
+ if (mdss_mdp_perf_calc_pipe(pipe, &perf, &mixer->roi))
continue;
ab_total += perf.ab_quota >> MDSS_MDP_BUS_FACTOR_SHIFT;
diff --git a/drivers/video/msm/mdss/mdss_mdp_formats.h b/drivers/video/msm/mdss/mdss_mdp_formats.h
index a2edf90..dcbff88 100644
--- a/drivers/video/msm/mdss/mdss_mdp_formats.h
+++ b/drivers/video/msm/mdss/mdss_mdp_formats.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -81,6 +81,25 @@
}, \
}
+#define FMT_RGB_8888_TILE(fmt, alpha_en, e0, e1, e2, e3) \
+ { \
+ .format = (fmt), \
+ .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, \
+ .unpack_tight = 1, \
+ .unpack_align_msb = 0, \
+ .alpha_enable = (alpha_en), \
+ .unpack_count = 4, \
+ .bpp = 4, \
+ .tile = 1, \
+ .element = { (e0), (e1), (e2), (e3) }, \
+ .bits = { \
+ [C3_ALPHA] = COLOR_8BIT, \
+ [C2_R_Cr] = COLOR_8BIT, \
+ [C0_G_Y] = COLOR_8BIT, \
+ [C1_B_Cb] = COLOR_8BIT, \
+ }, \
+ }
+
#define FMT_YUV_COMMON(fmt) \
.format = (fmt), \
.is_yuv = 1, \
@@ -125,6 +144,22 @@
FMT_RGB_8888(MDP_RGBX_8888, 0, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA),
FMT_RGB_8888(MDP_BGRA_8888, 1, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
FMT_RGB_8888(MDP_BGRX_8888, 0, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
+ FMT_RGB_8888_TILE(MDP_RGBA_8888_TILE, 1, C2_R_Cr, C0_G_Y, C1_B_Cb,
+ C3_ALPHA),
+ FMT_RGB_8888_TILE(MDP_ARGB_8888_TILE, 1, C3_ALPHA, C2_R_Cr, C0_G_Y,
+ C1_B_Cb),
+ FMT_RGB_8888_TILE(MDP_ABGR_8888_TILE, 1, C3_ALPHA, C1_B_Cb, C0_G_Y,
+ C2_R_Cr),
+ FMT_RGB_8888_TILE(MDP_BGRA_8888_TILE, 1, C1_B_Cb, C0_G_Y, C2_R_Cr,
+ C3_ALPHA),
+ FMT_RGB_8888_TILE(MDP_RGBX_8888_TILE, 0, C2_R_Cr, C0_G_Y, C1_B_Cb,
+ C3_ALPHA),
+ FMT_RGB_8888_TILE(MDP_XRGB_8888_TILE, 0, C3_ALPHA, C2_R_Cr, C0_G_Y,
+ C1_B_Cb),
+ FMT_RGB_8888_TILE(MDP_XBGR_8888_TILE, 0, C3_ALPHA, C1_B_Cb, C0_G_Y,
+ C2_R_Cr),
+ FMT_RGB_8888_TILE(MDP_BGRX_8888_TILE, 0, C1_B_Cb, C0_G_Y, C2_R_Cr,
+ C3_ALPHA),
FMT_YUV_PSEUDO(MDP_Y_CRCB_H1V1, MDSS_MDP_CHROMA_RGB, C2_R_Cr, C1_B_Cb),
FMT_YUV_PSEUDO(MDP_Y_CBCR_H1V1, MDSS_MDP_CHROMA_RGB, C1_B_Cb, C2_R_Cr),
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 9948738..bff56d2 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -25,6 +25,8 @@
#define MDSS_MDP_HW_REV_102 0x10020000
#define MDSS_MDP_HW_REV_103 0x10030000
+#define MDSS_MDP_FETCH_CONFIG_RESET_VALUE 0x00000087
+
#define MDSS_REG_HW_VERSION 0x0
#define MDSS_REG_HW_INTR_STATUS 0x10
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 51ecdbd..9365be8 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/msm_mdp.h>
#include <linux/memblock.h>
+#include <linux/sw_sync.h>
#include <mach/iommu_domains.h>
#include <mach/event_timer.h>
@@ -261,7 +262,7 @@
int rc;
for (;;) {
- rc = mdss_mdp_perf_calc_pipe(pipe, &perf);
+ rc = mdss_mdp_perf_calc_pipe(pipe, &perf, NULL);
if (!rc && (perf.mdp_clk_rate <= mdata->max_mdp_clk_rate))
break;
@@ -598,12 +599,6 @@
!mdp5_data->mdata->has_wfd_blk)
mdss_mdp_smp_release(pipe);
- /*
- * Clear previous SMP reservations and reserve according to the
- * latest configuration
- */
- mdss_mdp_smp_unreserve(pipe);
-
ret = mdss_mdp_smp_reserve(pipe);
if (ret) {
pr_debug("mdss_mdp_smp_reserve failed. ret=%d\n", ret);
@@ -2550,8 +2545,8 @@
* increasing ref_cnt to help balance clocks once done.
*/
if (pdata->panel_info.cont_splash_enabled) {
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdss_mdp_footswitch_ctrl_splash(1);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
}
return 0;
}
@@ -2709,6 +2704,107 @@
return rc;
}
+static void __vsync_retire_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t)
+{
+ struct msm_fb_data_type *mfd = ctl->mfd;
+ struct mdss_overlay_private *mdp5_data;
+
+ if (!mfd || !mfd->mdp.private1) {
+ pr_warn("Invalid handle for vsync\n");
+ return;
+ }
+
+ mdp5_data = mfd_to_mdp5_data(mfd);
+ schedule_work(&mdp5_data->retire_work);
+}
+
+static void __vsync_retire_work_handler(struct work_struct *work)
+{
+ struct mdss_overlay_private *mdp5_data =
+ container_of(work, typeof(*mdp5_data), retire_work);
+ struct msm_sync_pt_data *sync_pt_data;
+
+ if (!mdp5_data->ctl || !mdp5_data->ctl->mfd)
+ return;
+
+ if (!mdp5_data->ctl->remove_vsync_handler)
+ return;
+
+ sync_pt_data = &mdp5_data->ctl->mfd->mdp_sync_pt_data;
+ mutex_lock(&sync_pt_data->sync_mutex);
+ if (mdp5_data->retire_cnt > 0) {
+ sw_sync_timeline_inc(mdp5_data->vsync_timeline, 1);
+
+ mdp5_data->retire_cnt--;
+ if (mdp5_data->retire_cnt == 0) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ mdp5_data->ctl->remove_vsync_handler(mdp5_data->ctl,
+ &mdp5_data->vsync_retire_handler);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ }
+ }
+ mutex_unlock(&sync_pt_data->sync_mutex);
+}
+
+static struct sync_fence *
+__vsync_retire_get_fence(struct msm_sync_pt_data *sync_pt_data)
+{
+ struct msm_fb_data_type *mfd;
+ struct mdss_overlay_private *mdp5_data;
+ struct mdss_mdp_ctl *ctl;
+ int rc, value;
+
+ mfd = container_of(sync_pt_data, typeof(*mfd), mdp_sync_pt_data);
+ mdp5_data = mfd_to_mdp5_data(mfd);
+
+ if (!mdp5_data || !mdp5_data->ctl)
+ return ERR_PTR(-ENODEV);
+
+ ctl = mdp5_data->ctl;
+ if (!ctl->add_vsync_handler)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ if (!ctl->power_on) {
+ pr_debug("fb%d vsync pending first update\n", mfd->index);
+ return ERR_PTR(-EPERM);
+ }
+
+ if (mdp5_data->retire_cnt == 0) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ rc = ctl->add_vsync_handler(ctl,
+ &mdp5_data->vsync_retire_handler);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ if (IS_ERR_VALUE(rc))
+ return ERR_PTR(rc);
+ }
+ value = mdp5_data->vsync_timeline->value + 1 + mdp5_data->retire_cnt;
+ mdp5_data->retire_cnt++;
+
+ return mdss_fb_sync_get_fence(mdp5_data->vsync_timeline,
+ "mdp-retire", value);
+}
+
+static int __vsync_retire_setup(struct msm_fb_data_type *mfd)
+{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ char name[24];
+
+ snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index);
+ mdp5_data->vsync_timeline = sw_sync_timeline_create(name);
+ if (mdp5_data->vsync_timeline == NULL) {
+ pr_err("cannot vsync create time line");
+ return -ENOMEM;
+ }
+ mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence;
+
+ mdp5_data->vsync_retire_handler.vsync_handler =
+ __vsync_retire_handle_vsync;
+ mdp5_data->vsync_retire_handler.cmd_post_flush = false;
+ INIT_WORK(&mdp5_data->retire_work, __vsync_retire_work_handler);
+
+ return 0;
+}
+
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
{
struct device *dev = mfd->fbi->dev;
@@ -2775,6 +2871,12 @@
pr_err("Error dfps sysfs creation ret=%d\n", rc);
goto init_fail;
}
+ } else if (mfd->panel_info->type == MIPI_CMD_PANEL) {
+ rc = __vsync_retire_setup(mfd);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("unable to create vsync timeline\n");
+ goto init_fail;
+ }
}
mfd->mdp_sync_pt_data.async_wait_fences = true;
rc = sysfs_create_link_nowarn(&dev->kobj,
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 88a2a69..1b1f686 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -32,6 +32,8 @@
static DEFINE_MUTEX(mdss_mdp_smp_lock);
static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+static int mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp);
+static void mdss_mdp_smp_mmb_free(unsigned long *smp, bool write);
static struct mdss_mdp_pipe *mdss_mdp_pipe_search_by_client_id(
struct mdss_data_type *mdata, int client_id);
@@ -58,8 +60,27 @@
else
n -= fixed_cnt;
- /* reserve more blocks if needed, but can't free mmb at this point */
- for (i = bitmap_weight(smp_map->allocated, SMP_MB_CNT); i < n; i++) {
+ i = bitmap_weight(smp_map->allocated, SMP_MB_CNT);
+
+ /*
+ * SMP programming is not double buffered. Fail the request,
+ * that calls for change in smp configuration (addition/removal
+ * of smp blocks), so that fallback solution happens.
+ */
+ if (i != 0 && n != i) {
+ pr_debug("Can't change mmb config, num_blks: %d alloc: %d\n",
+ n, i);
+ return 0;
+ }
+
+ /*
+ * Clear previous SMP reservations and reserve according to the
+ * latest configuration
+ */
+ mdss_mdp_smp_mmb_free(smp_map->reserved, false);
+
+ /* Reserve mmb blocks*/
+ for (; i < n; i++) {
if (bitmap_full(mdata->mmb_alloc_map, SMP_MB_CNT))
break;
@@ -249,9 +270,21 @@
}
}
- nlines = pipe->bwc_mode ? 1 : 2;
+ if (pipe->src_fmt->tile)
+ nlines = 8;
+ else
+ nlines = pipe->bwc_mode ? 1 : 2;
mutex_lock(&mdss_mdp_smp_lock);
+ for (i = (MAX_PLANES - 1); i >= ps.num_planes; i--) {
+ if (bitmap_weight(pipe->smp_map[i].allocated, SMP_MB_CNT)) {
+ pr_debug("Extra mmb identified for pnum=%d plane=%d\n",
+ pipe->num, i);
+ mutex_unlock(&mdss_mdp_smp_lock);
+ return -EAGAIN;
+ }
+ }
+
for (i = 0; i < ps.num_planes; i++) {
if (rot_mode) {
num_blks = 1;
@@ -505,7 +538,7 @@
* shared as long as its attached to a writeback mixer
*/
pipe = mdata->dma_pipes + mixer->num;
- mdss_mdp_pipe_map(pipe);
+ atomic_inc(&pipe->ref_cnt);
pr_debug("pipe sharing for pipe=%d\n", pipe->num);
} else {
pr_err("no %d type pipes available\n", type);
@@ -624,6 +657,7 @@
mdss_mdp_smp_free(pipe);
pipe->flags = 0;
pipe->bwc_mode = 0;
+ pipe->mfd = NULL;
memset(&pipe->scale, 0, sizeof(struct mdp_scale_data));
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
@@ -767,25 +801,7 @@
return rc;
}
-void mdss_mdp_crop_rect(struct mdss_mdp_img_rect *src_rect,
- struct mdss_mdp_img_rect *dst_rect,
- const struct mdss_mdp_img_rect *sci_rect)
-{
- struct mdss_mdp_img_rect res;
- mdss_mdp_intersect_rect(&res, dst_rect, sci_rect);
- if (res.w && res.h) {
- if ((res.w != dst_rect->w) || (res.h != dst_rect->h)) {
- src_rect->x = src_rect->x + (res.x - dst_rect->x);
- src_rect->y = src_rect->y + (res.y - dst_rect->y);
- src_rect->w = res.w;
- src_rect->h = res.h;
- }
- *dst_rect = (struct mdss_mdp_img_rect)
- {(res.x - sci_rect->x), (res.y - sci_rect->y),
- res.w, res.h};
- }
-}
static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe,
struct mdss_mdp_data *data)
@@ -888,6 +904,7 @@
u32 chroma_samp, unpack, src_format;
u32 secure = 0;
u32 opmode;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
fmt = pipe->src_fmt;
@@ -918,6 +935,9 @@
(fmt->bits[C1_B_Cb] << 2) |
(fmt->bits[C0_G_Y] << 0);
+ if (fmt->tile)
+ src_format |= BIT(30);
+
if (pipe->flags & MDP_ROT_90)
src_format |= BIT(11); /* ROT90 */
@@ -937,6 +957,11 @@
if (pipe->scale.enable_pxl_ext)
opmode |= (1 << 31);
+ if (fmt->tile && mdata->highest_bank_bit) {
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_FETCH_CONFIG,
+ MDSS_MDP_FETCH_CONFIG_RESET_VALUE |
+ mdata->highest_bank_bit << 18);
+ }
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, src_format);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN, unpack);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_OP_MODE, opmode);
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 588e217..91e6373 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -224,12 +224,6 @@
pipe->params_changed++;
rot->params_changed = 0;
- /*
- * Clear previous SMP reservations and reserve according
- * to the latest configuration
- */
- mdss_mdp_smp_unreserve(pipe);
-
ret = mdss_mdp_smp_reserve(pipe);
if (ret) {
pr_err("unable to mdss_mdp_smp_reserve rot data\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 79873b6..69506d4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -257,6 +257,27 @@
else
*res_rect = (struct mdss_mdp_img_rect){l, t, (r-l), (b-t)};
}
+
+void mdss_mdp_crop_rect(struct mdss_mdp_img_rect *src_rect,
+ struct mdss_mdp_img_rect *dst_rect,
+ const struct mdss_mdp_img_rect *sci_rect)
+{
+ struct mdss_mdp_img_rect res;
+ mdss_mdp_intersect_rect(&res, dst_rect, sci_rect);
+
+ if (res.w && res.h) {
+ if ((res.w != dst_rect->w) || (res.h != dst_rect->h)) {
+ src_rect->x = src_rect->x + (res.x - dst_rect->x);
+ src_rect->y = src_rect->y + (res.y - dst_rect->y);
+ src_rect->w = res.w;
+ src_rect->h = res.h;
+ }
+ *dst_rect = (struct mdss_mdp_img_rect)
+ {(res.x - sci_rect->x), (res.y - sci_rect->y),
+ res.w, res.h};
+ }
+}
+
int mdss_mdp_get_rau_strides(u32 w, u32 h,
struct mdss_mdp_format_params *fmt,
struct mdss_mdp_plane_sizes *ps)
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 761b85a..6eb4d6e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -61,11 +61,14 @@
struct msmfb_data buf_info;
struct mdss_mdp_data buf_data;
int state;
+ bool user_alloc;
};
static DEFINE_MUTEX(mdss_mdp_wb_buf_lock);
static struct mdss_mdp_wb mdss_mdp_wb_info;
+static void mdss_mdp_wb_free_node(struct mdss_mdp_wb_data *node);
+
#ifdef DEBUG_WRITEBACK
/* for debugging: writeback output buffer to allocated memory */
static inline
@@ -285,6 +288,7 @@
struct mdss_mdp_wb_data *node, *temp;
list_for_each_entry_safe(node, temp, &wb->register_queue,
registered_entry) {
+ mdss_mdp_wb_free_node(node);
list_del(&node->registered_entry);
kfree(node);
}
@@ -401,12 +405,24 @@
struct mdss_mdp_img_data *buf;
int ret;
+ if (!list_empty(&wb->register_queue)) {
+ list_for_each_entry(node, &wb->register_queue, registered_entry)
+ if ((node->buf_info.memory_id == data->memory_id) &&
+ (node->buf_info.offset == data->offset)) {
+ pr_debug("found node fd=%x off=%x addr=%x\n",
+ data->memory_id, data->offset,
+ node->buf_data.p[0].addr);
+ return node;
+ }
+ }
+
node = kzalloc(sizeof(struct mdss_mdp_wb_data), GFP_KERNEL);
if (node == NULL) {
pr_err("out of memory\n");
return NULL;
}
+ node->user_alloc = true;
node->buf_data.num_planes = 1;
buf = &node->buf_data.p[0];
if (wb->is_secure)
@@ -434,6 +450,22 @@
return NULL;
}
+static void mdss_mdp_wb_free_node(struct mdss_mdp_wb_data *node)
+{
+ struct mdss_mdp_img_data *buf;
+
+ if (node->user_alloc) {
+ buf = &node->buf_data.p[0];
+ pr_debug("free user node mem_id=%d offset=%u addr=0x%x\n",
+ node->buf_info.memory_id,
+ node->buf_info.offset,
+ buf->addr);
+
+ mdss_mdp_put_img(&node->buf_data.p[0]);
+ node->user_alloc = false;
+ }
+}
+
static int mdss_mdp_wb_queue(struct msm_fb_data_type *mfd,
struct msmfb_data *data, int local)
{
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index b7f9b86..f36ee04 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -984,6 +984,7 @@
#define MDP_MAX_FENCE_FD 32
#define MDP_BUF_SYNC_FLAG_WAIT 1
+#define MDP_BUF_SYNC_FLAG_RETIRE_FENCE 0x10
struct mdp_buf_sync {
uint32_t flags;
@@ -991,6 +992,7 @@
uint32_t session_id;
int *acq_fen_fd;
int *rel_fen_fd;
+ int *retire_fen_fd;
};
struct mdp_async_blit_req_list {
@@ -1000,19 +1002,11 @@
};
#define MDP_DISPLAY_COMMIT_OVERLAY 1
-struct mdp_buf_fence {
- uint32_t flags;
- uint32_t acq_fen_fd_cnt;
- int acq_fen_fd[MDP_MAX_FENCE_FD];
- int rel_fen_fd[MDP_MAX_FENCE_FD];
-};
-
struct mdp_display_commit {
uint32_t flags;
uint32_t wait_for_finish;
struct fb_var_screeninfo var;
- struct mdp_buf_fence buf_fence;
struct mdp_rect roi;
};
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 6a68b72..7be6cd2 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1380,6 +1380,28 @@
* allowed to be used with the first @NL80211_CMD_SET_STATION command to
* update a TDLS peer STA entry.
*
+ * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information.
+ *
+ * @NL80211_ATTR_CH_SWITCH_COUNT: u32 attribute specifying the number of TBTT's
+ * until the channel switch event.
+ * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission
+ * must be blocked on the current channel (before the channel switch
+ * operation).
+ * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
+ * for the time while performing a channel switch.
+ * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter
+ * field in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
+ * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter
+ * field in the probe response (%NL80211_ATTR_PROBE_RESP).
+ *
+ * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
+ * As specified in the &enum nl80211_rxmgmt_flags.
+ *
+ * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels.
+ *
+ * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported
+ * supported operating classes.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1680,6 +1702,19 @@
NL80211_ATTR_PEER_AID,
+ NL80211_ATTR_COALESCE_RULE,
+
+ NL80211_ATTR_CH_SWITCH_COUNT,
+ NL80211_ATTR_CH_SWITCH_BLOCK_TX,
+ NL80211_ATTR_CSA_IES,
+ NL80211_ATTR_CSA_C_OFF_BEACON,
+ NL80211_ATTR_CSA_C_OFF_PRESP,
+
+ NL80211_ATTR_RXMGMT_FLAGS,
+
+ NL80211_ATTR_STA_SUPPORTED_CHANNELS,
+
+ NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index e6dcc3b..2b47b88 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -190,6 +190,7 @@
* %CHAN_PATH_SCALING2: ratio of {1, 4}
* %CHAN_PATH_SCALING3: ratio of {1, 6}
* %CHAN_PATH_SCALING4: ratio of {1, 20}
+ * %CHAN_PATH_SCALING5: ratio of {1, 8}
* %CHAN_PATH_NONE: Do not use this pre-scaling ratio type.
*
* The pre-scaling is applied for signals to be within the voltage range
@@ -201,6 +202,7 @@
PATH_SCALING2,
PATH_SCALING3,
PATH_SCALING4,
+ PATH_SCALING5,
PATH_SCALING_NONE,
};
@@ -893,7 +895,8 @@
{1, 3},
{1, 4},
{1, 6},
- {1, 20}
+ {1, 20},
+ {1, 8}
};
/**
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 045a58b..862a0cc 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2014, 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
@@ -346,6 +346,7 @@
* @chg_check_timer: The timer used to implement the workaround to detect
* very slow plug in of wall charger.
* @ui_enabled: USB Intterupt is enabled or disabled.
+ * @pm_done: Indicates whether USB is PM resumed
*/
struct msm_otg {
struct usb_phy phy;
@@ -462,6 +463,7 @@
bool ext_chg_active;
struct completion ext_chg_wait;
int ui_enabled;
+ bool pm_done;
};
struct ci13xxx_platform_data {
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index c0df1d7..38d3aab 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -47,7 +47,6 @@
#define MAX_EEPROM_NAME 32
#define MAX_AF_ITERATIONS 3
-#define MAX_NUMBER_OF_STEPS 47
enum flash_type {
LED_FLASH = 1,
@@ -441,7 +440,6 @@
CFG_GET_ACTUATOR_INFO,
CFG_SET_ACTUATOR_INFO,
CFG_SET_DEFAULT_FOCUS,
- CFG_SET_POSITION,
CFG_MOVE_FOCUS,
};
@@ -540,13 +538,6 @@
ACTUATOR_WEB_CAM_2,
};
-
-struct msm_actuator_set_position_t {
- uint16_t number_of_steps;
- uint16_t pos[MAX_NUMBER_OF_STEPS];
- uint16_t delay[MAX_NUMBER_OF_STEPS];
-};
-
struct msm_actuator_cfg_data {
int cfgtype;
uint8_t is_af_supported;
@@ -554,7 +545,6 @@
struct msm_actuator_move_params_t move;
struct msm_actuator_set_info_t set_info;
struct msm_actuator_get_info_t get_info;
- struct msm_actuator_set_position_t setpos;
enum af_camera_name cam_name;
} cfg;
};
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7932ba1..77084ed 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -524,6 +524,10 @@
* @capability: station capability
* @ext_capab: extended capabilities of the station
* @ext_capab_len: number of extended capabilities
+ * @supported_channels: supported channels in IEEE 802.11 format
+ * @supported_channels_len: number of supported channels
+ * @supported_oper_classes: supported oper classes in IEEE 802.11 format
+ * @supported_oper_classes_len: number of supported operating classes
*/
struct station_parameters {
u8 *supported_rates;
@@ -542,6 +546,10 @@
u16 capability;
u8 *ext_capab;
u8 ext_capab_len;
+ const u8 *supported_channels;
+ u8 supported_channels_len;
+ const u8 *supported_oper_classes;
+ u8 supported_oper_classes_len;
};
/**
diff --git a/lib/Kconfig b/lib/Kconfig
index 8437e36..09f0d8a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -379,7 +379,7 @@
Implementation is done using GnuPG MPI library
config QMI_ENCDEC
- bool
+ bool "QMI Encode/Decode Library"
help
Library to encode & decode QMI messages from within
the kernel. The kernel drivers encode the C structure into
@@ -388,7 +388,7 @@
and then decode it into a C structure.
config QMI_ENCDEC_DEBUG
- bool
+ bool "QMI Encode/Decode Library Debug"
help
Kernel config option to enable debugging QMI Encode/Decode
library. This will log the information regarding the element
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 24bb5d0..0e44fa8 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -14,14 +14,6 @@
(57240 - 63720 @ 2160), (N/A, 0)
-country AD:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
- # 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
country AE:
(2402 - 2482 @ 40), (N/A, 20)
(5170 - 5250 @ 80), (3, 17)
@@ -126,11 +118,6 @@
(5250 - 5330 @ 20), (N/A, 20), DFS
(5735 - 5835 @ 20), (N/A, 20)
-country BL:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 18)
- (5250 - 5330 @ 40), (N/A, 18), DFS
-
country BM:
(2402 - 2472 @ 40), (N/A, 30)
(5150 - 5250 @ 80), (6, 17)
@@ -909,7 +896,7 @@
(5250 - 5330 @ 80), (3, 24), DFS
(5490 - 5600 @ 80), (3, 24), DFS
(5650 - 5710 @ 40), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (5710 - 5835 @ 80), (3, 30)
# 60g band
# reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255
# channels 1,2,3, EIRP=40dBm(43dBm peak)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7db02f3..a251231 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -223,6 +223,8 @@
[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_DATA_LEN },
[NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
+ [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
+ [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
};
/* policy for the key attributes */
@@ -2774,6 +2776,41 @@
return ERR_PTR(ret);
}
+static int nl80211_parse_sta_channel_info(struct genl_info *info,
+ struct station_parameters *params)
+{
+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
+ params->supported_channels =
+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
+ params->supported_channels_len =
+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
+ /*
+ * Need to include at least one (first channel, number of
+ * channels) tuple for each subband, and must have proper
+ * tuples for the rest of the data as well.
+ */
+ if (params->supported_channels_len < 2)
+ return -EINVAL;
+ if (params->supported_channels_len % 2)
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
+ params->supported_oper_classes =
+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
+ params->supported_oper_classes_len =
+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
+ /*
+ * The value of the Length field of the Supported Operating
+ * Classes element is between 2 and 253.
+ */
+ if (params->supported_oper_classes_len < 2 ||
+ params->supported_oper_classes_len > 253)
+ return -EINVAL;
+ }
+ return 0;
+}
+
static struct nla_policy
nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
@@ -2797,6 +2834,10 @@
params->vht_capa =
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
+ err = nl80211_parse_sta_channel_info(info, params);
+ if (err)
+ return err;
+
/* parse WME attributes if present */
if (!info->attrs[NL80211_ATTR_STA_WME])
return 0;
@@ -3063,6 +3104,10 @@
params.plink_action =
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+ err = nl80211_parse_sta_channel_info(info, ¶ms);
+ if (err)
+ return err;
+
if (!rdev->ops->add_station)
return -EOPNOTSUPP;
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index 3fe8033..5be880d 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, 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
@@ -79,7 +79,7 @@
#define clear_bit_pos(x, y) (atomic_set(&x, (atomic_read(&x) & (~(1 << y)))))
#define test_bit_pos(x, y) ((atomic_read(&x)) & (1 << y))
-static int enable_ocmem_audio_voice;
+static int enable_ocmem_audio_voice = 1;
module_param(enable_ocmem_audio_voice, int,
S_IRUGO | S_IWUSR | S_IWGRP);
MODULE_PARM_DESC(enable_ocmem_audio_voice, "control OCMEM usage for audio/voice");
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index d3122ece..d2352ff 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -49,8 +49,13 @@
#define PARTIAL_DRAIN_ACK_EARLY_BY_MSEC 150
#define MP3_OUTPUT_FRAME_SZ 1152
#define AAC_OUTPUT_FRAME_SZ 1024
+#define AC3_OUTPUT_FRAME_SZ 1536
+#define EAC3_OUTPUT_FRAME_SZ 1536
#define DSP_NUM_OUTPUT_FRAME_BUFFERED 2
+/* decoder parameter length */
+#define DDP_DEC_MAX_NUM_PARAM 18
+
/* Default values used if user space does not set */
#define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
@@ -76,6 +81,7 @@
uint32_t volume[MSM_FRONTEND_DAI_MAX][2]; /* For both L & R */
struct msm_compr_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX];
bool use_dsp_gapless_mode;
+ struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX];
};
struct msm_compr_audio {
@@ -134,6 +140,10 @@
struct eq_params equalizer;
};
+struct msm_compr_dec_params {
+ struct snd_dec_ddp ddp_params;
+};
+
static int msm_compr_set_volume(struct snd_compr_stream *cstream,
uint32_t volume_l, uint32_t volume_r)
{
@@ -161,6 +171,23 @@
return rc;
}
+static int msm_compr_send_ddp_cfg(struct audio_client *ac,
+ struct snd_dec_ddp *ddp)
+{
+ int i, rc;
+ pr_debug("%s\n", __func__);
+ for (i = 0; i < ddp->params_length; i++) {
+ rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i],
+ ddp->params_value[i]);
+ if (rc) {
+ pr_err("sending params_id: %d failed\n",
+ ddp->params_id[i]);
+ return rc;
+ }
+ }
+ return 0;
+}
+
static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
{
int buffer_length;
@@ -557,11 +584,20 @@
kfree(prtd);
return -ENOMEM;
}
+ pdata->dec_params[rtd->dai_link->be_id] =
+ kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL);
+ if (!pdata->dec_params[rtd->dai_link->be_id]) {
+ pr_err("%s: Could not allocate memory for dec params\n",
+ __func__);
+ kfree(prtd);
+ return -ENOMEM;
+ }
prtd->audio_client = q6asm_audio_client_alloc(
(app_cb)compr_event_handler, prtd);
if (!prtd->audio_client) {
pr_err("%s: Could not allocate memory for client\n", __func__);
kfree(pdata->audio_effects[rtd->dai_link->be_id]);
+ kfree(pdata->dec_params[rtd->dai_link->be_id]);
kfree(prtd);
return -ENOMEM;
}
@@ -685,6 +721,7 @@
q6asm_audio_client_free(ac);
kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]);
+ kfree(pdata->dec_params[soc_prtd->dai_link->be_id]);
kfree(prtd);
return 0;
@@ -749,11 +786,13 @@
case SND_AUDIOCODEC_AC3: {
prtd->codec = FORMAT_AC3;
+ frame_sz = AC3_OUTPUT_FRAME_SZ;
break;
}
case SND_AUDIOCODEC_EAC3: {
prtd->codec = FORMAT_EAC3;
+ frame_sz = EAC3_OUTPUT_FRAME_SZ;
break;
}
@@ -1568,6 +1607,74 @@
return 0;
}
+static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+ unsigned long fe_id = kcontrol->private_value;
+ struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+ snd_soc_platform_get_drvdata(platform);
+ struct msm_compr_dec_params *dec_params = NULL;
+ struct snd_compr_stream *cstream = NULL;
+ struct msm_compr_audio *prtd = NULL;
+ long *values = &(ucontrol->value.integer.value[0]);
+
+ pr_debug("%s\n", __func__);
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds fe_id %lu\n",
+ __func__, fe_id);
+ return -EINVAL;
+ }
+
+ cstream = pdata->cstream[fe_id];
+ dec_params = pdata->dec_params[fe_id];
+
+ if (!cstream || !dec_params) {
+ pr_err("%s: stream or dec_params inactive\n", __func__);
+ return -EINVAL;
+ }
+ prtd = cstream->runtime->private_data;
+ if (!prtd) {
+ pr_err("%s: cannot set dec_params\n", __func__);
+ return -EINVAL;
+ }
+ switch (prtd->codec) {
+ case FORMAT_MP3:
+ case FORMAT_MPEG4_AAC:
+ pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
+ prtd->codec);
+ break;
+ case FORMAT_AC3:
+ case FORMAT_EAC3: {
+ struct snd_dec_ddp *ddp = &dec_params->ddp_params;
+ int cnt;
+ ddp->params_length = (*values++);
+ if (ddp->params_length > DDP_DEC_MAX_NUM_PARAM) {
+ pr_err("%s: invalid num of params:: %d\n", __func__,
+ ddp->params_length);
+ return -EINVAL;
+ }
+ for (cnt = 0; cnt < ddp->params_length; cnt++) {
+ ddp->params_id[cnt] = *values++;
+ ddp->params_value[cnt] = *values++;
+ }
+ if (msm_compr_send_ddp_cfg(prtd->audio_client, ddp) < 0)
+ pr_err("%s: DDP CMD CFG failed\n", __func__);
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ /* dummy function */
+ return 0;
+}
+
static int msm_compr_probe(struct snd_soc_platform *platform)
{
struct msm_compr_pdata *pdata;
@@ -1587,6 +1694,7 @@
pdata->volume[i][0] = COMPRESSED_LR_VOL_MAX_STEPS;
pdata->volume[i][1] = COMPRESSED_LR_VOL_MAX_STEPS;
pdata->audio_effects[i] = NULL;
+ pdata->dec_params[i] = NULL;
pdata->cstream[i] = NULL;
}
@@ -1620,6 +1728,16 @@
return 0;
}
+static int msm_compr_dec_params_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 128;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xFFFFFFFF;
+ return 0;
+}
+
static int msm_compr_add_volume_control(struct snd_soc_pcm_runtime *rtd)
{
const char *mixer_ctl_name = "Compress Playback";
@@ -1746,6 +1864,57 @@
msm_compr_gapless_put),
};
+static int msm_compr_add_dec_runtime_params_control(
+ struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Audio Stream";
+ const char *deviceNo = "NN";
+ const char *suffix = "Dec Params";
+ char *mixer_str = NULL;
+ int ctl_len;
+ struct snd_kcontrol_new fe_dec_params_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_compr_dec_params_info,
+ .get = msm_compr_dec_params_get,
+ .put = msm_compr_dec_params_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\n", __func__);
+ return 0;
+ }
+
+ pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
+ __func__, rtd->dai_link->name, rtd->dai_link->be_id,
+ rtd->dai_link->cpu_dai_name, rtd->pcm->device);
+
+ ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
+ strlen(suffix) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+
+ if (!mixer_str) {
+ pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
+ return 0;
+ }
+
+ snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
+ rtd->pcm->device, suffix);
+
+ fe_dec_params_control[0].name = mixer_str;
+ fe_dec_params_control[0].private_value = rtd->dai_link->be_id;
+ pr_debug("Registering new mixer ctl %s", mixer_str);
+ snd_soc_add_platform_controls(rtd->platform,
+ fe_dec_params_control,
+ ARRAY_SIZE(fe_dec_params_control));
+ kfree(mixer_str);
+ return 0;
+}
+
static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
{
int rc;
@@ -1757,6 +1926,10 @@
if (rc)
pr_err("%s: Could not add Compr Audio Effects Control\n",
__func__);
+ rc = msm_compr_add_dec_runtime_params_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add Compr Dec runtime params Control\n",
+ __func__);
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index dc57996..ee26f2e 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1066,8 +1066,11 @@
{
uint32_t sid = 0;
uint32_t dir = 0;
+ uint32_t i = IN;
uint32_t *payload;
unsigned long dsp_flags;
+ struct asm_buffer_node *buf_node = NULL;
+ struct list_head *ptr, *next;
struct audio_client *ac = NULL;
struct audio_port_data *port;
@@ -1086,6 +1089,20 @@
data->reset_proc,
this_mmap.apr);
apr_reset(this_mmap.apr);
+ for (; i <= OUT; i++) {
+ list_for_each_safe(ptr, next,
+ &common_client.port[i].mem_map_handle) {
+ buf_node = list_entry(ptr,
+ struct asm_buffer_node,
+ list);
+ if (buf_node->buf_addr_lsw ==
+ common_client.port[i].buf->phys) {
+ list_del(&buf_node->list);
+ kfree(buf_node);
+ }
+ }
+ pr_debug("%s:Clearing custom topology\n", __func__);
+ }
this_mmap.apr = NULL;
reset_custom_topology_flags();
set_custom_topology = 1;
@@ -3086,6 +3103,9 @@
rc = -EINVAL;
goto fail_cmd;
}
+
+ rc = 0;
+fail_cmd:
list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
buf_node = list_entry(ptr, struct asm_buffer_node,
list);
@@ -3095,9 +3115,6 @@
break;
}
}
-
- rc = 0;
-fail_cmd:
return rc;
}
@@ -3265,6 +3282,9 @@
pr_err("timeout. waited for memory_unmap\n");
goto fail_cmd;
}
+ rc = 0;
+
+fail_cmd:
list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
buf_node = list_entry(ptr, struct asm_buffer_node,
list);
@@ -3274,9 +3294,6 @@
break;
}
}
- rc = 0;
-
-fail_cmd:
return rc;
}
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index c4395c2..0c7472f 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -29,7 +29,7 @@
#include "q6voice.h"
-#define TIMEOUT_MS 200
+#define TIMEOUT_MS 300
#define CMD_STATUS_SUCCESS 0