Merge "ASoC: msm: Add volume control to set volume on platform driver"
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 6e125f2..66949af 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -65,6 +65,15 @@
detection, "bpd_thm_id" selects both.
If the property is not set, the temperatue pin will
be used.
+- qcom,btc-disabled: If flag is set battery hot and cold monitoring is
+ disabled in hardware. This monitoring is turned on
+ by default.
+- qcom,batt-hot-percent: Specify a supported hot threshold percentage.
+ Supported thresholds: 25% and 35%. If none is specified
+ hardware defaults will be used.
+- qcom,batt-cold-percent: Specify a supported cold threshold percentage.
+ Supported thresholds: 70% and 80%. If none is specified
+ hardware defaults will be used.
- otg-parent-supply Specify a phandle to a parent supply regulator
for the OTG regulator.
- boost-parent-supply Specify a phandle to a parent supply regulator
@@ -182,6 +191,9 @@
qcom,warm-bat-mv = <4100>;
qcom,ibatmax-cool-ma = <350>;
qcom,vbatdet-delta-mv = <60>;
+ qcom,batt-hot-percent = <25>;
+ qcom,batt-cold-percent = <85>;
+ qcom,btc-disabled = <0>;
qcom,chgr@1000 {
reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt b/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
index 6b090fa..64f2ddd 100644
--- a/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
+++ b/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
@@ -44,6 +44,17 @@
- qcom,rxreg-access: This boolean indicates that slimbus RX should use direct
register access to receive data. This flag is only needed if
BAM pipe is not available to receive data from slimbus
+ - qcom,apps-ch-pipes: This value represents BAM pipe-mask used by application
+ processor for data channels. If this property is not defined,
+ default mask of 0x3F000000 is used indicating apps can use 6
+ pipes from 24-29.
+ - qcom,ea-pc: This value represents product code (PC) field of enumeration
+ address (EA) for the Qualcomm slimbus controller hardware.
+ This value is needed if data-channels originating from apps
+ are to be used, so that application processor can query
+ logical address of the ported generic device to be used.
+ Other than PC, fields of EA are same across platforms.
+
Example:
slim@fe12f000 {
cell-index = <1>;
@@ -55,4 +66,6 @@
interrupt-names = "slimbus_irq", "slimbus_bam_irq";
qcom,min-clk-gear = <10>;
qcom,rxreg-access;
+ qcom,apps-ch-pipes = <0x60000000>;
+ qcom,ea-pc = <0x30>;
};
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index 311e968..32322e3 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -14,6 +14,10 @@
/include/ "msm8974-camera-sensor-dragonboard.dtsi"
/include/ "msm8974-leds.dtsi"
+&vph_pwr_vreg {
+ status = "ok";
+};
+
&soc {
serial@f991e000 {
status = "ok";
@@ -62,6 +66,10 @@
#size-cells = <1>;
ranges;
smsc,reset-gpio = <&pm8941_gpios 8 0x00>;
+ /* Dragonboard has an always-on VBUS supply for HSIC hub,
+ * providing a dummy regulator for the hub driver
+ */
+ hub_vbus-supply = <&vph_pwr_vreg>;
hsic_host: hsic@f9a00000 {
compatible = "qcom,hsic-host";
@@ -525,22 +533,7 @@
};
&spi_epm {
- epm-adc@0 {
- compatible = "cy,epm-adc-cy8c5568lti-114";
- reg = <0>;
- interrupt-parent = <&msmgpio>;
- spi-max-frequency = <960000>;
- qcom,channels = <31>;
- qcom,gain = <50 50 50 50 50 100 50 50 50 50
- 50 50 50 50 100 50 50 50 50 100
- 50 50 50 100 50 50 50 1 1 1
- 1>;
- qcom,rsense = <40 10 10 25 10 1000 75 25 10 25
- 33 500 200 10 500 100 33 200 25 100
- 75 500 50 200 5 5 3 1 1 1
- 1>;
- qcom,channel-type = <0xf0000000>;
- };
+ status = "disabled";
};
&spmi_bus {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index b801da8..40f9a7c 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -555,7 +555,7 @@
};
};
- vadc@3100 {
+ pm8941_vadc: vadc@3100 {
compatible = "qcom,qpnp-vadc";
reg = <0x3100 0x100>;
#address-cells = <1>;
@@ -797,7 +797,7 @@
};
};
- iadc@3600 {
+ pm8941_iadc: iadc@3600 {
compatible = "qcom,qpnp-iadc";
reg = <0x3600 0x100>;
#address-cells = <1>;
@@ -819,7 +819,7 @@
};
};
- qcom,vadc@3400 {
+ pm8941_adc_tm: qcom,vadc@3400 {
compatible = "qcom,qpnp-adc-tm";
reg = <0x3400 0x100>;
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
index bf94d04..a081308 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
@@ -28,5 +28,6 @@
&soc {
qcom,mdss_dsi_nt35590_720p_video {
status = "ok";
+ qcom,cont-splash-enabled;
};
};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
index 3b09d92..a2ad682 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
@@ -29,5 +29,6 @@
&soc {
qcom,mdss_dsi_nt35590_720p_video {
status = "ok";
+ qcom,cont-splash-enabled;
};
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 527a582..39e0c27 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -891,6 +891,9 @@
qcom,temp-hysteresis = <10>;
qcom,freq-step = <2>;
qcom,freq-control-mask = <0xf>;
+ qcom,core-limit-temp = <80>;
+ qcom,core-temp-hysteresis = <10>;
+ qcom,core-control-mask = <0xe>;
};
spi_0: spi@f9923000 { /* BLSP1 QUP1 */
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 4a2c57c..86294df 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -12,7 +12,7 @@
/dts-v1/;
-/include/ "msm8610.dtsi"
+/include/ "msm8610-qrd.dtsi"
/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
/include/ "msm8610-qrd-camera-sensor.dtsi"
@@ -23,308 +23,3 @@
<163 11 0>, <164 11 0>, <166 11 0>;
};
-&soc {
- i2c@f9923000{
- focaltech@38{
- compatible = "focaltech,5x06";
- reg = <0x38>;
- interrupt-parent = <&msmgpio>;
- interrupts = <1 0x2>;
- vdd-supply = <&pm8110_l19>;
- vcc_i2c-supply = <&pm8110_l14>;
- focaltech,family-id = <0x06>;
- focaltech,reset-gpio = <&msmgpio 0 0x00>;
- focaltech,irq-gpio = <&msmgpio 1 0x00>;
- focaltech,display-coords = <0 0 480 800>;
- focaltech,panel-coords = <0 0 480 800>;
- focaltech,button-map= <139 102 158>;
- focaltech,no-force-update;
- focaltech,i2c-pull-up;
- };
- };
-
- gen-vkeys {
- compatible = "qcom,gen-vkeys";
- label = "ft5x06_ts";
- qcom,disp-maxx = <480>;
- qcom,disp-maxy = <800>;
- qcom,panel-maxx = <481>;
- qcom,panel-maxy = <940>;
- qcom,key-codes = <139 0 102 158 0 0 0>;
- qcom,y-offset = <0>;
- };
- serial@f991e000 {
- status = "ok";
- };
-
- i2c@f9925000 { /* BLSP-1 QUP-3 */
- kionix@f {
- compatible = "kionix,kxtj9";
- reg = <0x0f>;
- interrupt-parent = <&msmgpio>;
- interrupts = <81 0x2>;
- vdd-supply = <&pm8110_l19>;
- vio-supply = <&pm8110_l14>;
- kionix,min-interval = <5>;
- kionix,init-interval = <200>;
- kionix,axis-map-x = <1>;
- kionix,axis-map-y = <0>;
- kionix,axis-map-z = <2>;
- kionix,g-range = <2>;
- kionix,negate-x;
- kionix,negate-y;
- kionix,negate-z;
- kionix,res-12bit;
- };
- };
-
- flashlight {
- compatible = "qcom,leds-gpio-flash";
- status = "okay";
- qcom,flash-en = <&msmgpio 18 0>;
- qcom,flash-now = <&msmgpio 19 0>;
- linux,name = "flashlight";
- linux,default-trigger = "flashlight-trigger";
- };
-
- gpio_keys {
- compatible = "gpio-keys";
- input-name = "gpio-keys";
-
- camera_snapshot {
- label = "camera_snapshot";
- gpios = <&msmgpio 73 0x1>;
- linux,input-type = <1>;
- linux,code = <0x2fe>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
-
- camera_focus {
- label = "camera_focus";
- gpios = <&msmgpio 74 0x1>;
- linux,input-type = <1>;
- linux,code = <0x210>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
-
- vol_up {
- label = "volume_up";
- gpios = <&msmgpio 72 0x1>;
- linux,input-type = <1>;
- linux,code = <115>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
- };
-
- i2c@f9927000 {
- msm8x10_wcd_codec@0d{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x0d>;
- cdc-vdda-cp-supply = <&pm8110_s4>;
- qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
- qcom,cdc-vdda-cp-current = <650000>;
-
- cdc-vdda-h-supply = <&pm8110_l6>;
- qcom,cdc-vdda-h-voltage = <1800000 1800000>;
- qcom,cdc-vdda-h-current = <250000>;
-
- cdc-vdd-px-supply = <&pm8110_l6>;
- qcom,cdc-vdd-px-voltage = <1800000 1800000>;
- qcom,cdc-vdd-px-current = <10000>;
-
- cdc-vdd-1p2v-supply = <&pm8110_l4>;
- qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
- qcom,cdc-vdd-1p2v-current = <5000>;
-
- cdc-vdd-mic-bias-supply = <&pm8110_l20>;
- qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
- qcom,cdc-vdd-mic-bias-current = <25000>;
-
- qcom,cdc-micbias-cfilt-sel = <0x0>;
- qcom,cdc-micbias-cfilt-mv = <1800000>;
- qcom,cdc-mclk-clk-rate = <12288000>;
- };
-
- msm8x10_wcd_codec@77{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x77>;
- };
-
- msm8x10_wcd_codec@66{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x66>;
- };
-
- msm8x10_wcd_codec@55{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x55>;
- };
- };
-
- sound {
- qcom,audio-routing =
- "RX_BIAS", "MCLK",
- "INT_LDO_H", "MCLK",
- "MIC BIAS Internal1", "Handset Mic",
- "MIC BIAS Internal2", "Headset Mic",
- "AMIC1", "MIC BIAS Internal1",
- "AMIC2", "MIC BIAS Internal2";
- };
-};
-
-&spmi_bus {
- qcom,pm8110@0 {
- qcom,leds@a100 {
- status = "okay";
- qcom,led_mpp_2 {
- label = "mpp";
- linux,name = "wled-homerow";
- linux-default-trigger = "hr-trigger";
- qcom,default-state = "off";
- qcom,max-current = <40>;
- qcom,id = <6>;
- qcom,source-sel = <1>;
- qcom,mode-ctrl = <0x61>;
- qcom,mode = "manual";
- };
- };
-
- qcom,leds@a200 {
- status = "okay";
- qcom,led_mpp_3 {
- label = "mpp";
- linux,name = "wled-backlight";
- linux,default-trigger = "bkl-trigger";
- qcom,default-state = "on";
- qcom,max-current = <40>;
- qcom,id = <6>;
- qcom,source-sel = <1>;
- qcom,mode-ctrl = <0x10>;
- qcom,mode = "manual";
- };
- };
- };
-};
-
-&spmi_bus {
- qcom,pm8110@1 {
- qcom,vibrator@c000 {
- status = "okay";
- qcom,vib-timeout-ms = <15000>;
- qcom,vib-vtg-level-mV = <3100>;
- };
- };
-};
-
-&sdhc_1 {
- vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
- qcom,vdd-voltage-level = <2900000 2900000>;
- qcom,vdd-current-level = <200 400000>;
-
- vdd-io-supply = <&pm8110_l6>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-voltage-level = <1800000 1800000>;
- qcom,vdd-io-current-level = <200 60000>;
-
- qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
- qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
- qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
- qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
-
- qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
- qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
- qcom,nonremovable;
-
- status = "ok";
-};
-
-&sdhc_2 {
- vdd-supply = <&pm8110_l18>;
- qcom,vdd-voltage-level = <2950000 2950000>;
- qcom,vdd-current-level = <15000 400000>;
-
- vdd-io-supply = <&pm8110_l21>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
- qcom,vdd-io-voltage-level = <1800000 2950000>;
- qcom,vdd-io-current-level = <200 50000>;
-
- qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
- qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
- qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
- qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
-
- qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
-
- #address-cells = <0>;
- interrupt-parent = <&sdhc_2>;
- interrupts = <0 1 2>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0xffffffff>;
- interrupt-map = <0 &intc 0 125 0
- 1 &intc 0 221 0
- 2 &msmgpio 42 0x3>;
- interrupt-names = "hc_irq", "pwr_irq", "status_irq";
- cd-gpios = <&msmgpio 42 0x1>;
-
- status = "ok";
-};
-
-&pm8110_chg {
- status = "ok";
-
- qcom,chgr@1000 {
- status = "ok";
- };
-
- qcom,buck@1100 {
- status = "ok";
- };
-
- qcom,bat-if@1200 {
- status = "ok";
- };
-
- qcom,usb-chgpth@1300 {
- status = "ok";
- };
-
- qcom,chg-misc@1600 {
- status = "ok";
- };
-};
-
-&pm8110_gpios {
- gpio@c000 { /* GPIO 1 */
- };
-
- gpio@c100 { /* GPIO 2 */
- };
-
- gpio@c200 { /* GPIO 3 */
- };
-
- gpio@c300 { /* GPIO 4 */
- };
-};
-
-&pm8110_mpps {
- mpp@a000 { /* MPP 1 */
- };
-
- mpp@a100 { /* MPP 2 */
- status = "disabled";
- };
-
- mpp@a200 { /* MPP 3 */
- status = "disabled";
- };
-
- mpp@a300 { /* MPP 4 */
- };
-};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
new file mode 100644
index 0000000..7a93c49
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -0,0 +1,335 @@
+/* Copyright (c) 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/* This is a QRD reference design common file. The common device
+ * tree approach would help OEM during development of their extended
+ * device tree. Each new QRD OEM target can select its own include
+ * files and provide board specific overrides in the top level DTS
+ * file.
+ *
+ * For example:
+ * msm8xxx-qrd.dtsi: QRD reference common node
+ * msm8xxx-qrd-skuxx.dts:
+ * /include/ "msm8610-qrd.dtsi"
+ * / {
+ * List skuxx specific node which is different with QRD
+ * reference design.
+ * };
+ */
+
+/include/ "msm8610.dtsi"
+
+&soc {
+ i2c@f9923000{
+ focaltech@38{
+ compatible = "focaltech,5x06";
+ reg = <0x38>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <1 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,family-id = <0x06>;
+ focaltech,reset-gpio = <&msmgpio 0 0x00>;
+ focaltech,irq-gpio = <&msmgpio 1 0x00>;
+ focaltech,display-coords = <0 0 480 800>;
+ focaltech,panel-coords = <0 0 480 800>;
+ focaltech,button-map= <139 102 158>;
+ focaltech,no-force-update;
+ focaltech,i2c-pull-up;
+ };
+ };
+
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "ft5x06_ts";
+ qcom,disp-maxx = <480>;
+ qcom,disp-maxy = <800>;
+ qcom,panel-maxx = <481>;
+ qcom,panel-maxy = <940>;
+ qcom,key-codes = <139 0 102 158 0 0 0>;
+ qcom,y-offset = <0>;
+ };
+ serial@f991e000 {
+ status = "ok";
+ };
+
+ i2c@f9925000 { /* BLSP-1 QUP-3 */
+ kionix@f {
+ compatible = "kionix,kxtj9";
+ reg = <0x0f>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <81 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ kionix,min-interval = <5>;
+ kionix,init-interval = <200>;
+ kionix,axis-map-x = <1>;
+ kionix,axis-map-y = <0>;
+ kionix,axis-map-z = <2>;
+ kionix,g-range = <2>;
+ kionix,negate-x;
+ kionix,negate-y;
+ kionix,negate-z;
+ kionix,res-12bit;
+ };
+ };
+
+ flashlight {
+ compatible = "qcom,leds-gpio-flash";
+ status = "okay";
+ qcom,flash-en = <&msmgpio 18 0>;
+ qcom,flash-now = <&msmgpio 19 0>;
+ linux,name = "flashlight";
+ linux,default-trigger = "flashlight-trigger";
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+
+ camera_snapshot {
+ label = "camera_snapshot";
+ gpios = <&msmgpio 73 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x2fe>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ camera_focus {
+ label = "camera_focus";
+ gpios = <&msmgpio 74 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x210>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&msmgpio 72 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
+
+ i2c@f9927000 {
+ msm8x10_wcd_codec@0d{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x0d>;
+ cdc-vdda-cp-supply = <&pm8110_s4>;
+ qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
+ qcom,cdc-vdda-cp-current = <650000>;
+
+ cdc-vdda-h-supply = <&pm8110_l6>;
+ qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdda-h-current = <250000>;
+
+ cdc-vdd-px-supply = <&pm8110_l6>;
+ qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-px-current = <10000>;
+
+ cdc-vdd-1p2v-supply = <&pm8110_l4>;
+ qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+ qcom,cdc-vdd-1p2v-current = <5000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+ qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+ qcom,cdc-vdd-mic-bias-current = <25000>;
+
+ qcom,cdc-micbias-cfilt-sel = <0x0>;
+ qcom,cdc-micbias-cfilt-mv = <1800000>;
+ qcom,cdc-mclk-clk-rate = <12288000>;
+ };
+
+ msm8x10_wcd_codec@77{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x77>;
+ };
+
+ msm8x10_wcd_codec@66{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x66>;
+ };
+
+ msm8x10_wcd_codec@55{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x55>;
+ };
+ };
+
+ sound {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "MIC BIAS Internal1", "Handset Mic",
+ "MIC BIAS Internal2", "Headset Mic",
+ "AMIC1", "MIC BIAS Internal1",
+ "AMIC2", "MIC BIAS Internal2";
+ };
+};
+
+&spmi_bus {
+ qcom,pm8110@0 {
+ qcom,leds@a100 {
+ status = "okay";
+ qcom,led_mpp_2 {
+ label = "mpp";
+ linux,name = "wled-homerow";
+ linux-default-trigger = "hr-trigger";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,id = <6>;
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x61>;
+ qcom,mode = "manual";
+ };
+ };
+
+ qcom,leds@a200 {
+ status = "okay";
+ qcom,led_mpp_3 {
+ label = "mpp";
+ linux,name = "wled-backlight";
+ linux,default-trigger = "bkl-trigger";
+ qcom,default-state = "on";
+ qcom,max-current = <40>;
+ qcom,id = <6>;
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x10>;
+ qcom,mode = "manual";
+ };
+ };
+ };
+};
+
+&spmi_bus {
+ qcom,pm8110@1 {
+ qcom,vibrator@c000 {
+ status = "okay";
+ qcom,vib-timeout-ms = <15000>;
+ qcom,vib-vtg-level-mV = <3100>;
+ };
+ };
+};
+
+&sdhc_1 {
+ vdd-supply = <&pm8110_l17>;
+ qcom,vdd-always-on;
+ qcom,vdd-lpm-sup;
+ qcom,vdd-voltage-level = <2900000 2900000>;
+ qcom,vdd-current-level = <200 400000>;
+
+ vdd-io-supply = <&pm8110_l6>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 60000>;
+
+ qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+ qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+ qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+ qcom,nonremovable;
+
+ status = "ok";
+};
+
+&sdhc_2 {
+ vdd-supply = <&pm8110_l18>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <15000 400000>;
+
+ vdd-io-supply = <&pm8110_l21>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 50000>;
+
+ qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+ qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+ qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0
+ 2 &msmgpio 42 0x3>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&msmgpio 42 0x1>;
+
+ status = "ok";
+};
+
+&pm8110_chg {
+ status = "ok";
+
+ qcom,chgr@1000 {
+ status = "ok";
+ };
+
+ qcom,buck@1100 {
+ status = "ok";
+ };
+
+ qcom,bat-if@1200 {
+ status = "ok";
+ };
+
+ qcom,usb-chgpth@1300 {
+ status = "ok";
+ };
+
+ qcom,chg-misc@1600 {
+ status = "ok";
+ };
+};
+
+&pm8110_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ };
+};
+
+&pm8110_mpps {
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ status = "disabled";
+ };
+
+ mpp@a200 { /* MPP 3 */
+ status = "disabled";
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index b99e6f8..4eca5bb 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -219,6 +219,8 @@
HSUSB_1p8-supply = <&pm8110_l10>;
HSUSB_3p3-supply = <&pm8110_l20>;
+ qcom,hsusb-otg-phy-init-seq =
+ <0x44 0x80 0x68 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
qcom,hsusb-otg-phy-type = <2>;
qcom,hsusb-otg-mode = <1>;
qcom,hsusb-otg-otg-control = <2>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 89cbc4c..0e720c7 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -648,6 +648,8 @@
reg-names = "slimbus_physical", "slimbus_bam_physical";
interrupts = <0 163 0 0 164 0>;
interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+ qcom,apps-ch-pipes = <0x60000000>;
+ qcom,ea-pc = <0x30>;
taiko_codec {
compatible = "qcom,taiko-slim-pgd";
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 8eb1119..24c6143 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -294,4 +294,10 @@
reg-names = "phys_addr_base";
qcom,sleep-stats-version = <2>;
};
+
+ qcom,rpm-rbcpr-stats@fc000000 {
+ compatible = "qcom,rpmrbcpr-stats";
+ reg = <0xfc000000 0x1a0000>;
+ qcom,start-offset = <0x190010>;
+ };
};
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 010bc10..29ef385 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -385,3 +385,4 @@
CONFIG_INPUT_KXTJ9=y
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_SENSORS_STK3X1X=y
+CONFIG_SENSORS_MMA8X5X=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 7225ec5..77a1048 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -428,3 +428,4 @@
CONFIG_INPUT_KXTJ9=y
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_SENSORS_STK3X1X=y
+CONFIG_SENSORS_MMA8X5X=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index d02f5da..6471673 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -317,3 +317,4 @@
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 64c8535..0ff4efa 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -327,3 +327,4 @@
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index cdee5b7..1ec850f 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -119,6 +119,7 @@
zreladdr-$(CONFIG_ARCH_MSM8610) := 0x00008000
dtb-$(CONFIG_ARCH_MSM8610) += msm8610-rumi.dtb
dtb-$(CONFIG_ARCH_MSM8610) += msm8610-sim.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-qrd.dtb
# MSMSAMARIUM
zreladdr-$(CONFIG_ARCH_MSMSAMARIUM) := 0x00008000
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index ef8b5bb..605a7ae 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -307,8 +307,9 @@
CLK_DUMMY("", camss_vfe_vfe1_clk.c, "", OFF),
CLK_DUMMY("", camss_vfe_vfe_ahb_clk.c, "", OFF),
CLK_DUMMY("", camss_vfe_vfe_axi_clk.c, "", OFF),
- CLK_DUMMY("", mdss_ahb_clk.c, "", OFF),
- CLK_DUMMY("", mdss_axi_clk.c, "", OFF),
+ CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+ CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+ CLK_DUMMY("core_clk_src", mdp_clk_src.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("", mdss_byte0_clk.c, "", OFF),
CLK_DUMMY("", mdss_byte1_clk.c, "", OFF),
CLK_DUMMY("", mdss_edpaux_clk.c, "", OFF),
@@ -319,11 +320,11 @@
CLK_DUMMY("", mdss_extpclk_clk.c, "", OFF),
CLK_DUMMY("", mdss_hdmi_ahb_clk.c, "", OFF),
CLK_DUMMY("", mdss_hdmi_clk.c, "", OFF),
- CLK_DUMMY("", mdss_mdp_clk.c, "", OFF),
- CLK_DUMMY("", mdss_mdp_lut_clk.c, "", OFF),
+ CLK_DUMMY("core_clk", mdss_mdp_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+ CLK_DUMMY("lut_clk", mdss_mdp_lut_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("", mdss_pclk0_clk.c, "", OFF),
CLK_DUMMY("", mdss_pclk1_clk.c, "", OFF),
- CLK_DUMMY("", mdss_vsync_clk.c, "", OFF),
+ CLK_DUMMY("vsync_clk", mdss_vsync_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("", mmss_misc_ahb_clk.c, "", OFF),
CLK_DUMMY("", mmss_mmssnoc_ahb_clk.c, "", OFF),
CLK_DUMMY("", mmss_mmssnoc_axi_clk.c, "", OFF),
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 6877b4d9..70b6bea 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -854,11 +854,24 @@
return div;
}
+static void dsi_pll_toggle_lock_detect(void)
+{
+ DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+ 0x05);
+ DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+ 0x04);
+ udelay(1);
+ DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+ 0x05);
+}
+
static int dsi_pll_lock_status(void)
{
u32 status;
int pll_locked = 0;
+ dsi_pll_toggle_lock_detect();
+
/* poll for PLL ready status */
if (readl_poll_timeout_noirq((mdss_dsi_base +
DSI_0_PHY_PLL_UNIPHY_PLL_STATUS),
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 52102e3..830992c 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -32,6 +32,7 @@
#define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
#ifdef CONFIG_OF
+#define of_board_is_cdp() of_machine_is_compatible("qcom,cdp")
#define of_board_is_sim() of_machine_is_compatible("qcom,sim")
#define of_board_is_rumi() of_machine_is_compatible("qcom,rumi")
#define of_board_is_fluid() of_machine_is_compatible("qcom,fluid")
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
index 5303009..a7c1be2 100644
--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -143,8 +143,12 @@
goto err_ion_handle;
}
- if (bufsz != 0)
- memset((void *)*vaddr, 0, bufsz);
+ *vaddr = ion_map_kernel(*client, *handle);
+ if (IS_ERR_OR_NULL((void *)*vaddr)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto err_ion_handle;
+ }
+ pr_debug("%s: mapped address = %p, size=%d\n", __func__, *vaddr, bufsz);
return 0;
diff --git a/block/test-iosched.c b/block/test-iosched.c
index b1e5492..07b36b8 100644
--- a/block/test-iosched.c
+++ b/block/test-iosched.c
@@ -101,8 +101,8 @@
goto exit;
}
- ptd->test_info.test_duration = jiffies -
- ptd->test_info.test_duration;
+ ptd->test_info.test_duration = ktime_sub(ktime_get(),
+ ptd->test_info.test_duration);
test_pr_info("%s: Test is completed, test_count=%d, reinsert_count=%d,",
__func__, ptd->test_count, ptd->reinsert_count);
@@ -774,7 +774,7 @@
goto error;
}
- ptd->test_info.test_duration = jiffies;
+ ptd->test_info.test_duration = ktime_get();
ret = run_test(ptd);
if (ret) {
test_pr_err("%s: failed to run the test\n", __func__);
@@ -784,10 +784,10 @@
test_pr_info("%s: Waiting for the test completion", __func__);
wait_event(ptd->wait_q, ptd->test_state == TEST_COMPLETED);
- t_info->test_duration = ptd->test_info.test_duration;
- t_info->test_byte_count = ptd->test_info.test_byte_count;
del_timer_sync(&ptd->timeout_timer);
+ memcpy(t_info, &ptd->test_info, sizeof(struct test_info));
+
ret = check_test_result(ptd);
if (ret) {
test_pr_err("%s: check_test_result failed\n",
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 1af9399..d01496e 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -515,6 +515,7 @@
if (!temp) {
pr_err("diag: Invalid buffer in %s\n", __func__);
+ return -ENOMEM;
}
/* This is Pkt request/response transaction */
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index f22b4c2..a6ef3ca 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -151,8 +151,9 @@
if (diag_hsic[index].diag_hsic_pool &&
(diag_hsic[index].hsic_inited == 0)) {
if (diag_hsic[index].count_hsic_pool == 0) {
- mempool_destroy(driver->diag_hdlc_pool);
- driver->diag_hdlc_pool = NULL;
+ mempool_destroy(
+ diag_hsic[index].diag_hsic_pool);
+ diag_hsic[index].diag_hsic_pool = NULL;
} else if (pool_type == POOL_TYPE_ALL)
pr_err("Unable to destroy HDLC mempool for ch %d"
, index);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 2fd8bef..96e759b 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -610,6 +610,9 @@
if (dbs_info->cur_policy) {
/* restart dbs timer */
dbs_timer_init(dbs_info);
+ /* Enable frequency synchronization
+ * of CPUs */
+ atomic_set(&dbs_info->sync_enabled, 1);
}
skip_this_cpu:
unlock_policy_rwsem_write(cpu);
@@ -639,15 +642,19 @@
if (dbs_info->cur_policy) {
/* cpu using ondemand, cancel dbs timer */
- mutex_lock(&dbs_info->timer_mutex);
dbs_timer_exit(dbs_info);
+ /* Disable frequency synchronization of
+ * CPUs to avoid re-queueing of work from
+ * sync_thread */
+ atomic_set(&dbs_info->sync_enabled, 0);
+ mutex_lock(&dbs_info->timer_mutex);
ondemand_powersave_bias_setspeed(
dbs_info->cur_policy,
NULL,
input);
-
mutex_unlock(&dbs_info->timer_mutex);
+
}
skip_this_cpu_bypass:
unlock_policy_rwsem_write(cpu);
@@ -1075,18 +1082,6 @@
get_online_cpus();
- /* TODO: cur_policy is currently set for all CPUs when
- * a policy is started but cleared only on the current
- * CPU when the policy is stopped. If/when this is
- * resolved, sync_enabled can be removed and
- * cur_policy can be used instead.
- */
- if (!atomic_read(&this_dbs_info->sync_enabled)) {
- atomic_set(&this_dbs_info->src_sync_cpu, -1);
- put_online_cpus();
- continue;
- }
-
src_cpu = atomic_read(&this_dbs_info->src_sync_cpu);
src_dbs_info = &per_cpu(od_cpu_dbs_info, src_cpu);
if (src_dbs_info != NULL &&
@@ -1101,6 +1096,13 @@
if (lock_policy_rwsem_write(cpu) < 0)
goto bail_acq_sema_failed;
+ if (!atomic_read(&this_dbs_info->sync_enabled)) {
+ atomic_set(&this_dbs_info->src_sync_cpu, -1);
+ put_online_cpus();
+ unlock_policy_rwsem_write(cpu);
+ continue;
+ }
+
policy = this_dbs_info->cur_policy;
if (!policy) {
/* CPU not using ondemand governor */
@@ -1238,7 +1240,8 @@
kcpustat_cpu(j).cpustat[CPUTIME_NICE];
set_cpus_allowed(j_dbs_info->sync_thread,
*cpumask_of(j));
- atomic_set(&j_dbs_info->sync_enabled, 1);
+ if (!dbs_tuners_ins.powersave_bias)
+ atomic_set(&j_dbs_info->sync_enabled, 1);
}
this_dbs_info->cpu = cpu;
this_dbs_info->rate_mult = 1;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 9113605..aeafb01 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1534,6 +1534,7 @@
KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit,
iommu_unit->dev[j].ctx_id,
V2PUR, v2pxx);
+ mb();
vaddr += PAGE_SIZE;
for (l = 0; l < iommu_unit->dev_count; l++) {
tlblkcr = KGSL_IOMMU_GET_CTX_REG(iommu,
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 2c2b339..189418a 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -246,6 +246,8 @@
enum dmx_tsp_format_t tsp_format);
int (*set_secure_mode)(struct dmx_ts_feed *feed,
struct dmx_secure_mode *sec_mode);
+ int (*set_cipher_ops)(struct dmx_ts_feed *feed,
+ struct dmx_cipher_operations *cipher_ops);
int (*oob_command) (struct dmx_ts_feed *feed,
struct dmx_oob_command *cmd);
int (*ts_insertion_init)(struct dmx_ts_feed *feed);
@@ -301,6 +303,8 @@
u32 bytes_num);
int (*set_secure_mode)(struct dmx_section_feed *feed,
struct dmx_secure_mode *sec_mode);
+ int (*set_cipher_ops)(struct dmx_section_feed *feed,
+ struct dmx_cipher_operations *cipher_ops);
int (*oob_command) (struct dmx_section_feed *feed,
struct dmx_oob_command *cmd);
int (*get_scrambling_bits)(struct dmx_section_feed *feed, u8 *value);
@@ -388,6 +392,7 @@
struct dmx_frontend* frontend; /* Front-end connected to the demux */
void* priv; /* Pointer to private data of the API client */
struct data_buffer dvr_input; /* DVR input buffer */
+ int dvr_input_protected;
struct dentry *debugfs_demux_dir; /* debugfs dir */
int (*open) (struct dmx_demux* demux);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 28e8092..a1cac54 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -566,6 +566,7 @@
int bytes_written = 0;
size_t split;
size_t tsp_size;
+ u8 *data_start;
struct dvb_ringbuffer *src = &dmxdev->dvr_input_buffer;
todo = dvr_cmd->cmd.data_feed_count;
@@ -578,15 +579,15 @@
/* wait for input */
ret = wait_event_interruptible(
src->queue,
- (dvb_ringbuffer_avail(src) >= tsp_size) || (!src->data)
- || (dmxdev->dvr_in_exit) || (src->error));
+ (dvb_ringbuffer_avail(src) >= tsp_size) ||
+ dmxdev->dvr_in_exit || src->error);
if (ret < 0)
break;
spin_lock(&dmxdev->dvr_in_lock);
- if (!src->data || dmxdev->exit || dmxdev->dvr_in_exit) {
+ if (dmxdev->exit || dmxdev->dvr_in_exit) {
spin_unlock(&dmxdev->dvr_in_lock);
ret = -ENODEV;
break;
@@ -609,12 +610,20 @@
* Lock on DVR buffer is released before calling to
* write, if DVR was released meanwhile, dvr_in_exit is
* prompted. Lock is acquired when updating the read pointer
- * again to preserve read/write pointers consistency
+ * again to preserve read/write pointers consistency.
+ *
+ * In protected input mode, DVR input buffer is not mapped
+ * to kernel memory. Underlying demux implementation
+ * should trigger HW to read from DVR input buffer
+ * based on current read offset.
*/
if (split > 0) {
+ data_start = (dmxdev->demux->dvr_input_protected) ?
+ NULL : (src->data + src->pread);
+
spin_unlock(&dmxdev->dvr_in_lock);
ret = dmxdev->demux->write(dmxdev->demux,
- src->data + src->pread,
+ data_start,
split);
if (ret < 0) {
@@ -641,9 +650,12 @@
}
}
+ data_start = (dmxdev->demux->dvr_input_protected) ?
+ NULL : (src->data + src->pread);
+
spin_unlock(&dmxdev->dvr_in_lock);
ret = dmxdev->demux->write(dmxdev->demux,
- src->data + src->pread, todo);
+ data_start, todo);
if (ret < 0) {
printk(KERN_ERR "dmxdev: dvr write error %d\n",
@@ -708,8 +720,7 @@
ret = dvb_dvr_feed_cmd(dmxdev, &dvr_cmd);
if (ret < 0) {
- printk(KERN_ERR
- "%s: DVR data feed failed, ret=%d\n",
+ dprintk("%s: DVR data feed failed, ret=%d\n",
__func__, ret);
continue;
}
@@ -825,6 +836,7 @@
dmxdev->demux->dvr_input.priv_handle = NULL;
dmxdev->demux->dvr_input.ringbuff = &dmxdev->dvr_input_buffer;
+ dmxdev->demux->dvr_input_protected = 0;
mem = vmalloc(DVR_CMDS_BUFFER_SIZE);
if (!mem) {
vfree(dmxdev->dvr_input_buffer.data);
@@ -936,7 +948,8 @@
if ((dmxdev->dvr_input_buffer_mode ==
DMX_BUFFER_MODE_EXTERNAL) &&
(dmxdev->demux->dvr_input.priv_handle)) {
- dmxdev->demux->unmap_buffer(dmxdev->demux,
+ if (!dmxdev->demux->dvr_input_protected)
+ dmxdev->demux->unmap_buffer(dmxdev->demux,
dmxdev->demux->dvr_input.priv_handle);
dmxdev->demux->dvr_input.priv_handle = NULL;
}
@@ -1130,8 +1143,8 @@
for (todo = count; todo > 0; todo -= ret) {
ret = wait_event_interruptible(src->queue,
(dvb_ringbuffer_free(src)) ||
- (!src->data) || (!cmdbuf->data) ||
- (src->error != 0) || (dmxdev->dvr_in_exit));
+ !src->data || !cmdbuf->data ||
+ (src->error != 0) || dmxdev->dvr_in_exit);
if (ret < 0)
return ret;
@@ -1314,6 +1327,7 @@
enum dmx_buffer_mode *buffer_mode;
void **buff_handle;
void *oldmem;
+ int *is_protected;
if ((mode != DMX_BUFFER_MODE_INTERNAL) &&
(mode != DMX_BUFFER_MODE_EXTERNAL))
@@ -1328,11 +1342,13 @@
lock = &dmxdev->lock;
buffer_mode = &dmxdev->dvr_buffer_mode;
buff_handle = &dmxdev->dvr_priv_buff_handle;
+ is_protected = NULL;
} else {
buf = &dmxdev->dvr_input_buffer;
lock = &dmxdev->dvr_in_lock;
buffer_mode = &dmxdev->dvr_input_buffer_mode;
buff_handle = &dmxdev->demux->dvr_input.priv_handle;
+ is_protected = &dmxdev->demux->dvr_input_protected;
}
if (mode == *buffer_mode)
@@ -1353,6 +1369,9 @@
*buff_handle = NULL;
}
+ if (is_protected)
+ *is_protected = 0;
+
/* set default internal buffer */
dvb_dvr_set_buffer_size(dmxdev, f_flags, DVR_BUFFER_SIZE);
} else if (oldmem) {
@@ -1372,31 +1391,56 @@
void **buff_handle;
void *newmem;
void *oldmem;
+ int *is_protected;
+ struct dmx_caps caps;
+
+ if (dmxdev->demux->get_caps)
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+ else
+ caps.caps = 0;
if ((f_flags & O_ACCMODE) == O_RDONLY) {
buf = &dmxdev->dvr_buffer;
lock = &dmxdev->lock;
buffer_mode = dmxdev->dvr_buffer_mode;
buff_handle = &dmxdev->dvr_priv_buff_handle;
+ is_protected = NULL;
} else {
buf = &dmxdev->dvr_input_buffer;
lock = &dmxdev->dvr_in_lock;
buffer_mode = dmxdev->dvr_input_buffer_mode;
buff_handle = &dmxdev->demux->dvr_input.priv_handle;
+ is_protected = &dmxdev->demux->dvr_input_protected;
+ if (!(caps.caps & DMX_CAP_SECURED_INPUT_PLAYBACK) &&
+ dmx_buffer->is_protected)
+ return -EINVAL;
}
- if ((!dmx_buffer->size) ||
+ if (!dmx_buffer->size ||
(buffer_mode == DMX_BUFFER_MODE_INTERNAL))
return -EINVAL;
oldmem = *buff_handle;
- if (dmxdev->demux->map_buffer(dmxdev->demux, dmx_buffer,
- buff_handle, &newmem))
- return -ENOMEM;
+
+ /*
+ * Protected buffer is relevant only for DVR input buffer
+ * when DVR device is opened for write. In such case,
+ * buffer is mapped only if the buffer is not protected one.
+ */
+ if (!is_protected || !dmx_buffer->is_protected) {
+ if (dmxdev->demux->map_buffer(dmxdev->demux, dmx_buffer,
+ buff_handle, &newmem))
+ return -ENOMEM;
+ } else {
+ newmem = NULL;
+ *buff_handle = NULL;
+ }
spin_lock_irq(lock);
buf->data = newmem;
buf->size = dmx_buffer->size;
+ if (is_protected)
+ *is_protected = dmx_buffer->is_protected;
dvb_ringbuffer_reset(buf);
spin_unlock_irq(lock);
@@ -1717,19 +1761,20 @@
static int dvb_dmxdev_set_source(struct dmxdev_filter *dmxdevfilter,
dmx_source_t *source)
{
+ int ret = 0;
struct dmxdev *dev;
if (dmxdevfilter->state == DMXDEV_STATE_GO)
return -EBUSY;
dev = dmxdevfilter->dev;
-
- dev->source = *source;
-
if (dev->demux->set_source)
- return dev->demux->set_source(dev->demux, source);
+ ret = dev->demux->set_source(dev->demux, source);
- return 0;
+ if (!ret)
+ dev->source = *source;
+
+ return ret;
}
static int dvb_dmxdev_reuse_decoder_buf(struct dmxdev_filter *dmxdevfilter,
@@ -3105,7 +3150,10 @@
tsfeed->set_tsp_out_format(tsfeed, filter->dmx_tsp_format);
if (tsfeed->set_secure_mode)
- tsfeed->set_secure_mode(tsfeed, &feed->sec_mode);
+ tsfeed->set_secure_mode(tsfeed, &filter->sec_mode);
+
+ if (tsfeed->set_cipher_ops)
+ tsfeed->set_cipher_ops(tsfeed, &feed->cipher_ops);
if ((para->pes_type == DMX_PES_VIDEO0) ||
(para->pes_type == DMX_PES_VIDEO1) ||
@@ -3265,7 +3313,11 @@
if ((*secfeed)->set_secure_mode)
(*secfeed)->set_secure_mode(*secfeed,
- &filter->feed.sec.sec_mode);
+ &filter->sec_mode);
+
+ if ((*secfeed)->set_cipher_ops)
+ (*secfeed)->set_cipher_ops(*secfeed,
+ &filter->feed.sec.cipher_ops);
} else {
dvb_dmxdev_feed_stop(filter);
}
@@ -3434,6 +3486,8 @@
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
init_timer(&dmxdevfilter->timer);
+ dmxdevfilter->sec_mode.is_secured = 0;
+
INIT_LIST_HEAD(&dmxdevfilter->insertion_buffers);
dmxdevfilter->dmx_tsp_format = DMX_TSP_FORMAT_188;
@@ -3513,7 +3567,7 @@
return -ENOMEM;
feed->pid = pid;
- feed->sec_mode.is_secured = 0;
+ feed->cipher_ops.operations_count = 0;
feed->idx_params.enable = 0;
list_add(&feed->next, &filter->feed.ts);
@@ -3568,7 +3622,7 @@
memcpy(&dmxdevfilter->params.sec,
params, sizeof(struct dmx_sct_filter_params));
invert_mode(&dmxdevfilter->params.sec.filter);
- dmxdevfilter->feed.sec.sec_mode.is_secured = 0;
+ dmxdevfilter->feed.sec.cipher_ops.operations_count = 0;
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
if (params->flags & DMX_IMMEDIATE_START)
@@ -3582,43 +3636,78 @@
struct dmxdev_filter *filter,
struct dmx_secure_mode *sec_mode)
{
+ if (!dmxdev || !filter || !sec_mode)
+ return -EINVAL;
+
+ if (filter->state == DMXDEV_STATE_GO) {
+ printk(KERN_ERR "%s: invalid filter state\n", __func__);
+ return -EBUSY;
+ }
+
+ dprintk(KERN_DEBUG "%s: secure=%d\n", __func__, sec_mode->is_secured);
+
+ filter->sec_mode = *sec_mode;
+
+ return 0;
+}
+
+static int dvb_dmxdev_set_cipher(struct dmxdev *dmxdev,
+ struct dmxdev_filter *filter,
+ struct dmx_cipher_operations *cipher_ops)
+{
struct dmxdev_feed *feed;
struct dmxdev_feed *ts_feed = NULL;
struct dmxdev_sec_feed *sec_feed = NULL;
+ struct dmx_caps caps;
- if (NULL == dmxdev || NULL == filter || NULL == sec_mode)
+ if (!dmxdev || !dmxdev->demux->get_caps)
return -EINVAL;
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+ if (!filter || !cipher_ops ||
+ (cipher_ops->operations_count > caps.num_cipher_ops) ||
+ (cipher_ops->operations_count >
+ DMX_MAX_CIPHER_OPERATIONS_COUNT))
+ return -EINVAL;
+
+ dprintk(KERN_DEBUG "%s: pid=%d, operations=%d\n", __func__,
+ cipher_ops->pid, cipher_ops->operations_count);
+
if (filter->state < DMXDEV_STATE_SET ||
filter->state > DMXDEV_STATE_GO) {
printk(KERN_ERR "%s: invalid filter state\n", __func__);
return -EPERM;
}
- dprintk(KERN_DEBUG "%s: key_id=%d, secure=%d, looking for pid=%d\n",
- __func__, sec_mode->key_ladder_id, sec_mode->is_secured,
- sec_mode->pid);
+
+ if (!filter->sec_mode.is_secured && cipher_ops->operations_count) {
+ printk(KERN_ERR "%s: secure mode must be enabled to set cipher ops\n",
+ __func__);
+ return -EPERM;
+ }
+
switch (filter->type) {
case DMXDEV_TYPE_PES:
list_for_each_entry(feed, &filter->feed.ts, next) {
- if (feed->pid == sec_mode->pid) {
+ if (feed->pid == cipher_ops->pid) {
ts_feed = feed;
- ts_feed->sec_mode = *sec_mode;
+ ts_feed->cipher_ops = *cipher_ops;
if (filter->state == DMXDEV_STATE_GO &&
- ts_feed->ts->set_secure_mode)
- ts_feed->ts->set_secure_mode(
- ts_feed->ts, sec_mode);
+ ts_feed->ts->set_cipher_ops)
+ ts_feed->ts->set_cipher_ops(
+ ts_feed->ts, cipher_ops);
break;
}
}
break;
case DMXDEV_TYPE_SEC:
- if (filter->params.sec.pid == sec_mode->pid) {
+ if (filter->params.sec.pid == cipher_ops->pid) {
sec_feed = &filter->feed.sec;
- sec_feed->sec_mode = *sec_mode;
+ sec_feed->cipher_ops = *cipher_ops;
if (filter->state == DMXDEV_STATE_GO &&
- sec_feed->feed->set_secure_mode)
- sec_feed->feed->set_secure_mode(sec_feed->feed,
- sec_mode);
+ sec_feed->feed->set_cipher_ops)
+ sec_feed->feed->set_cipher_ops(sec_feed->feed,
+ cipher_ops);
}
break;
@@ -3628,7 +3717,7 @@
if (!ts_feed && !sec_feed) {
printk(KERN_ERR "%s: pid %d is undefined for this filter\n",
- __func__, sec_mode->pid);
+ __func__, cipher_ops->pid);
return -EINVAL;
}
@@ -4029,6 +4118,15 @@
mutex_unlock(&dmxdevfilter->mutex);
break;
+ case DMX_SET_CIPHER:
+ if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ ret = dvb_dmxdev_set_cipher(dmxdev, dmxdevfilter, parg);
+ mutex_unlock(&dmxdevfilter->mutex);
+ break;
+
case DMX_REUSE_DECODER_BUFFER:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
@@ -4384,13 +4482,12 @@
buffer_status.fullness);
seq_printf(s, "error: %d, ",
buffer_status.error);
- seq_printf(s, "scramble: %d\n",
- scrambling_bits.value);
-
- } else {
- seq_printf(s, "scramble: %d\n",
- scrambling_bits.value);
}
+
+ seq_printf(s, "scramble: %d, ",
+ scrambling_bits.value);
+ seq_printf(s, "secured: %d\n",
+ filter->sec_mode.is_secured);
}
}
@@ -4425,6 +4522,7 @@
return -ENOMEM;
dmxdev->playback_mode = DMX_PB_MODE_PUSH;
+ dmxdev->demux->dvr_input_protected = 0;
mutex_init(&dmxdev->mutex);
spin_lock_init(&dmxdev->lock);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 4e306e8..6747ca7 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -58,15 +58,15 @@
struct dmxdev_feed {
u16 pid;
- struct dmx_secure_mode sec_mode;
struct dmx_indexing_params idx_params;
+ struct dmx_cipher_operations cipher_ops;
struct dmx_ts_feed *ts;
struct list_head next;
};
struct dmxdev_sec_feed {
- struct dmx_secure_mode sec_mode;
struct dmx_section_feed *feed;
+ struct dmx_cipher_operations cipher_ops;
};
#define DMX_EVENT_QUEUE_SIZE 500 /* number of events */
@@ -182,6 +182,8 @@
int todo;
u8 secheader[3];
+ struct dmx_secure_mode sec_mode;
+
/* Decoder buffer(s) related */
struct dmx_decoder_buffers decoder_buffers;
};
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index bbf2470..692a04e 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -2262,19 +2262,36 @@
{
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+
+ if (mutex_lock_interruptible(&dvbdmx->mutex))
+ return -ERESTARTSYS;
+
+ if (dvbdmxfeed->state == DMX_STATE_GO) {
+ mutex_unlock(&dvbdmx->mutex);
+ return -EBUSY;
+ }
+
+ dvbdmxfeed->secure_mode = *secure_mode;
+ mutex_unlock(&dvbdmx->mutex);
+ return 0;
+}
+
+static int dmx_ts_set_cipher_ops(struct dmx_ts_feed *feed,
+ struct dmx_cipher_operations *cipher_ops)
+{
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret = 0;
- mutex_lock(&dvbdmx->mutex);
+ if (mutex_lock_interruptible(&dvbdmx->mutex))
+ return -ERESTARTSYS;
if ((dvbdmxfeed->state == DMX_STATE_GO) &&
- dvbdmxfeed->demux->set_secure_mode) {
- ret = dvbdmxfeed->demux->set_secure_mode(dvbdmxfeed,
- secure_mode);
- if (!ret)
- dvbdmxfeed->secure_mode = *secure_mode;
- } else {
- dvbdmxfeed->secure_mode = *secure_mode;
- }
+ dvbdmx->set_cipher_op)
+ ret = dvbdmx->set_cipher_op(dvbdmxfeed, cipher_ops);
+
+ if (!ret)
+ dvbdmxfeed->cipher_ops = *cipher_ops;
mutex_unlock(&dvbdmx->mutex);
return ret;
@@ -2481,6 +2498,7 @@
(*ts_feed)->data_ready_cb = dmx_ts_feed_data_ready_cb;
(*ts_feed)->notify_data_read = NULL;
(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
+ (*ts_feed)->set_cipher_ops = dmx_ts_set_cipher_ops;
(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
(*ts_feed)->get_scrambling_bits = dvbdmx_ts_get_scrambling_bits;
(*ts_feed)->ts_insertion_init = NULL;
@@ -2724,15 +2742,38 @@
mutex_lock(&dvbdmx->mutex);
- dvbdmxfeed->secure_mode = *secure_mode;
- if ((dvbdmxfeed->state == DMX_STATE_GO) &&
- dvbdmxfeed->demux->set_secure_mode)
- dvbdmxfeed->demux->set_secure_mode(dvbdmxfeed, secure_mode);
+ if (dvbdmxfeed->state == DMX_STATE_GO) {
+ mutex_unlock(&dvbdmx->mutex);
+ return -EBUSY;
+ }
+ dvbdmxfeed->secure_mode = *secure_mode;
mutex_unlock(&dvbdmx->mutex);
return 0;
}
+static int dmx_section_set_cipher_ops(struct dmx_section_feed *feed,
+ struct dmx_cipher_operations *cipher_ops)
+{
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+ int ret = 0;
+
+ if (mutex_lock_interruptible(&dvbdmx->mutex))
+ return -ERESTARTSYS;
+
+ if ((dvbdmxfeed->state == DMX_STATE_GO) &&
+ dvbdmx->set_cipher_op) {
+ ret = dvbdmx->set_cipher_op(dvbdmxfeed, cipher_ops);
+ }
+
+ if (!ret)
+ dvbdmxfeed->cipher_ops = *cipher_ops;
+
+ mutex_unlock(&dvbdmx->mutex);
+ return ret;
+}
+
static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
struct dmx_section_filter *filter)
{
@@ -2875,6 +2916,7 @@
(*feed)->data_ready_cb = dmx_section_feed_data_ready_cb;
(*feed)->notify_data_read = NULL;
(*feed)->set_secure_mode = dmx_section_set_secure_mode;
+ (*feed)->set_cipher_ops = dmx_section_set_cipher_ops;
(*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
(*feed)->get_scrambling_bits = dvbdmx_section_get_scrambling_bits;
@@ -2939,8 +2981,10 @@
{
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
- if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
+ if (!demux->frontend || !buf || demux->dvr_input_protected ||
+ (demux->frontend->source != DMX_MEMORY_FE)) {
return -EINVAL;
+ }
dvb_dmx_swfilter_format(dvbdemux, buf, count, dvbdemux->tsp_format);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index aeafa57..835e7b8 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -176,6 +176,7 @@
int buffer_size;
enum dmx_tsp_format_t tsp_out_format;
struct dmx_secure_mode secure_mode;
+ struct dmx_cipher_operations cipher_ops;
struct timespec timeout;
struct dvb_demux_filter *filter;
@@ -233,8 +234,8 @@
struct dmx_buffer_status *dmx_buffer_status);
int (*reuse_decoder_buffer)(struct dvb_demux_feed *feed,
int cookie);
- int (*set_secure_mode)(struct dvb_demux_feed *feed,
- struct dmx_secure_mode *secure_mode);
+ int (*set_cipher_op)(struct dvb_demux_feed *feed,
+ struct dmx_cipher_operations *cipher_ops);
u32 (*check_crc32)(struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 23e05e2..75b75ea 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -3650,16 +3650,18 @@
* If pid has a key ladder id associated, we need to
* set it to SDMX.
*/
- if (dvbdmx_feed->secure_mode.is_secured) {
+ if (dvbdmx_feed->secure_mode.is_secured &&
+ dvbdmx_feed->cipher_ops.operations_count) {
MPQ_DVB_DBG_PRINT(
- "%s: set key-ladder %d to PID %d\n",
- __func__,
- dvbdmx_feed->secure_mode.key_ladder_id,
- dvbdmx_feed->secure_mode.pid);
- ret = sdmx_set_kl_ind(
- mpq_demux->sdmx_session_handle,
- dvbdmx_feed->secure_mode.pid,
- dvbdmx_feed->secure_mode.key_ladder_id);
+ "%s: set key-ladder %d to PID %d\n",
+ __func__,
+ dvbdmx_feed->cipher_ops.operations[0].key_ladder_id,
+ dvbdmx_feed->cipher_ops.pid);
+
+ ret = sdmx_set_kl_ind(mpq_demux->sdmx_session_handle,
+ dvbdmx_feed->cipher_ops.pid,
+ dvbdmx_feed->cipher_ops.operations[0].key_ladder_id);
+
if (ret) {
MPQ_DVB_ERR_PRINT(
"%s: FAILED to set key ladder, ret=%d\n",
@@ -3789,14 +3791,14 @@
/**
* Note: Called only when filter is in "GO" state - after feed has been started.
*/
-int mpq_dmx_set_secure_mode(struct dvb_demux_feed *feed,
- struct dmx_secure_mode *sec_mode)
+int mpq_dmx_set_cipher_ops(struct dvb_demux_feed *feed,
+ struct dmx_cipher_operations *cipher_ops)
{
struct mpq_feed *mpq_feed;
struct mpq_demux *mpq_demux;
int ret = 0;
- if (!feed || !feed->priv || !sec_mode) {
+ if (!feed || !feed->priv || !cipher_ops) {
MPQ_DVB_ERR_PRINT(
"%s: invalid parameters\n",
__func__);
@@ -3804,37 +3806,45 @@
}
MPQ_DVB_DBG_PRINT("%s(%d, %d, %d)\n",
- __func__, sec_mode->pid,
- sec_mode->is_secured,
- sec_mode->key_ladder_id);
+ __func__, cipher_ops->pid,
+ cipher_ops->operations_count,
+ cipher_ops->operations[0].key_ladder_id);
+
+ if ((cipher_ops->operations_count > 1) ||
+ (cipher_ops->operations_count &&
+ cipher_ops->operations[0].encrypt)) {
+ MPQ_DVB_ERR_PRINT(
+ "%s: Invalid cipher operations, count=%d, encrypt=%d\n",
+ __func__, cipher_ops->operations_count,
+ cipher_ops->operations[0].encrypt);
+ return -EINVAL;
+ }
+
+ if (!feed->secure_mode.is_secured) {
+ /*
+ * Filter is not configured as secured, setting cipher
+ * operations is not allowed.
+ */
+ MPQ_DVB_ERR_PRINT(
+ "%s: Cannot set cipher operations to non-secure filter\n",
+ __func__);
+ return -EPERM;
+ }
mpq_feed = feed->priv;
mpq_demux = mpq_feed->mpq_demux;
mutex_lock(&mpq_demux->mutex);
- if (feed->secure_mode.is_secured != sec_mode->is_secured) {
- /*
- * Switching between secure & non-secure mode is not allowed
- * while filter is running
- */
- MPQ_DVB_ERR_PRINT(
- "%s: Cannot switch between secure mode while filter is running\n",
- __func__);
- mutex_unlock(&mpq_demux->mutex);
- return -EPERM;
- }
-
/*
* Feed is running in secure mode, this secure mode request is to
* update the key ladder id
*/
- if (feed->secure_mode.pid == sec_mode->pid && sec_mode->is_secured &&
- feed->secure_mode.key_ladder_id != sec_mode->key_ladder_id &&
- mpq_demux->sdmx_session_handle != SDMX_INVALID_SESSION_HANDLE) {
+ if ((mpq_demux->sdmx_session_handle != SDMX_INVALID_SESSION_HANDLE) &&
+ cipher_ops->operations_count) {
ret = sdmx_set_kl_ind(mpq_demux->sdmx_session_handle,
- sec_mode->pid,
- sec_mode->key_ladder_id);
+ cipher_ops->pid,
+ cipher_ops->operations[0].key_ladder_id);
if (ret) {
MPQ_DVB_ERR_PRINT(
"%s: FAILED to set key ladder, ret=%d\n",
@@ -3847,7 +3857,7 @@
return ret;
}
-EXPORT_SYMBOL(mpq_dmx_set_secure_mode);
+EXPORT_SYMBOL(mpq_dmx_set_cipher_ops);
static void mpq_sdmx_prepare_filter_status(struct mpq_demux *mpq_demux,
struct sdmx_filter_status *filter_sts,
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index 31fd9b5..f095e00 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -654,15 +654,19 @@
void mpq_dmx_update_hw_statistics(struct mpq_demux *mpq_demux);
/**
- * mpq_dmx_set_secure_mode - Handles set secure mode command from demux device
+ * mpq_dmx_set_cipher_ops - Handles setting of cipher operations
*
- * @feed: The feed to set its secure mode
- * @sec_mode: Secure mode details (key ladder info)
+ * @feed: The feed to set its cipher operations
+ * @cipher_ops: Cipher operations to be set
+ *
+ * This common function handles only the case when working with
+ * secure-demux. When working with secure demux a single decrypt cipher
+ * operation is allowed.
*
* Return error code
-*/
-int mpq_dmx_set_secure_mode(struct dvb_demux_feed *feed,
- struct dmx_secure_mode *secure_mode);
+ */
+int mpq_dmx_set_cipher_ops(struct dvb_demux_feed *feed,
+ struct dmx_cipher_operations *cipher_ops);
/**
* mpq_dmx_convert_tts - Convert timestamp attached by HW to each TS
@@ -673,7 +677,7 @@
* @timestampIn27Mhz: Timestamp result in 27MHz
*
* Return error code
-*/
+ */
void mpq_dmx_convert_tts(struct dvb_demux_feed *feed,
const u8 timestamp[TIMESTAMP_LEN],
u64 *timestampIn27Mhz);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 5daa842..40445b0 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -561,6 +561,7 @@
caps->max_bitrate = 144;
caps->demod_input_max_bitrate = 72;
caps->memory_input_max_bitrate = 72;
+ caps->num_cipher_ops = 0;
/* TSIF reports 3 bytes STC at unit of 27MHz/256 */
caps->max_stc = (u64)0xFFFFFF * 256;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 5bd008d..940a4bc 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1627,6 +1627,7 @@
caps->max_bitrate = 192;
caps->demod_input_max_bitrate = 96;
caps->memory_input_max_bitrate = 96;
+ caps->num_cipher_ops = 1;
/* TSIF reports 3 bytes STC at unit of 27MHz/256 */
caps->max_stc = (u64)0xFFFFFF * 256;
@@ -1747,7 +1748,7 @@
mpq_dmx_decoder_fullness_abort;
mpq_demux->demux.decoder_buffer_status = mpq_dmx_decoder_buffer_status;
mpq_demux->demux.reuse_decoder_buffer = mpq_dmx_reuse_decoder_buffer;
- mpq_demux->demux.set_secure_mode = mpq_dmx_set_secure_mode;
+ mpq_demux->demux.set_cipher_op = mpq_dmx_set_cipher_ops;
mpq_demux->demux.oob_command = mpq_dmx_oob_command;
mpq_demux->demux.convert_ts = mpq_dmx_convert_tts;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index 9837e9f..c2e37a4 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
@@ -73,7 +73,8 @@
}
caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_INDEXING |
- DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION;
+ DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION |
+ DMX_CAP_SECURED_INPUT_PLAYBACK;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -85,6 +86,7 @@
caps->max_bitrate = 320;
caps->demod_input_max_bitrate = 96;
caps->memory_input_max_bitrate = 80;
+ caps->num_cipher_ops = DMX_MAX_CIPHER_OPERATIONS_COUNT;
/* TSIF reports 7 bytes STC at unit of 27MHz */
caps->max_stc = 0x00FFFFFFFFFFFFFF;
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 7a4d19e..e9ac2fc 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -20,7 +20,6 @@
#include <linux/mmc/host.h>
#include <linux/delay.h>
#include <linux/test-iosched.h>
-#include <linux/jiffies.h>
#include "queue.h"
#include <linux/mmc/mmc.h>
@@ -2787,7 +2786,7 @@
if (ret)
break;
- mtime = jiffies_to_msecs(mbtd->test_info.test_duration);
+ mtime = ktime_to_ms(mbtd->test_info.test_duration);
test_pr_info("%s: time is %lu msec, size is %u.%u MiB",
__func__, mtime,
@@ -2946,7 +2945,7 @@
if (ret)
break;
- mtime = jiffies_to_msecs(mbtd->test_info.test_duration);
+ mtime = ktime_to_ms(mbtd->test_info.test_duration);
byte_count = mbtd->test_info.test_byte_count;
test_pr_info("%s: time is %lu msec, size is %lu.%lu MiB",
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index efa09f6..16012bd 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -694,7 +694,7 @@
dma_addr_t dma_addr_param_info = 0;
struct onfi_param_page *onfi_param_page_ptr;
struct msm_nand_flash_onfi_data data;
- uint32_t onfi_signature;
+ uint32_t onfi_signature = 0;
/* SPS command/data descriptors */
uint32_t total_cnt = 13;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 983a901..e05c866 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -98,6 +98,7 @@
#define BOOST_VSET 0x41
#define BOOST_ENABLE_CONTROL 0x46
#define COMP_OVR1 0xEA
+#define BAT_IF_BTC_CTRL 0x49
#define REG_OFFSET_PERP_SUBTYPE 0x05
@@ -222,6 +223,7 @@
* @dc_present: present status of dc
* @batt_present: present status of battery
* @use_default_batt_values: flag to report default battery properties
+ * @btc_disabled Flag to disable btc (disables hot and cold irqs)
* @max_voltage_mv: the max volts the batt should be charged up to
* @min_voltage_mv: min battery voltage before turning the FET on
* @max_bat_chg_current: maximum battery charge current in mA
@@ -234,6 +236,8 @@
* @safe_current: battery safety current setting
* @maxinput_usb_ma: Maximum Input current USB
* @maxinput_dc_ma: Maximum Input current DC
+ * @hot_batt_p Hot battery threshold setting
+ * @cold_batt_p Cold battery threshold setting
* @warm_bat_decidegc Warm battery temperature in degree Celsius
* @cool_bat_decidegc Cool battery temperature in degree Celsius
* @revision: PMIC revision
@@ -276,6 +280,7 @@
bool dc_present;
bool batt_present;
bool charging_disabled;
+ bool btc_disabled;
bool use_default_batt_values;
bool duty_cycle_100p;
unsigned int bpd_detection;
@@ -293,6 +298,8 @@
int term_current;
unsigned int maxinput_usb_ma;
unsigned int maxinput_dc_ma;
+ unsigned int hot_batt_p;
+ unsigned int cold_batt_p;
unsigned int warm_bat_decidegc;
unsigned int cool_bat_decidegc;
unsigned int safe_current;
@@ -334,7 +341,21 @@
[BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
};
-static inline int
+enum btc_type {
+ HOT_THD_25_PCT = 25,
+ HOT_THD_35_PCT = 35,
+ COLD_THD_70_PCT = 70,
+ COLD_THD_80_PCT = 80,
+};
+
+static u8 btc_value[] = {
+ [HOT_THD_25_PCT] = 0x0,
+ [HOT_THD_35_PCT] = BIT(0),
+ [COLD_THD_70_PCT] = 0x0,
+ [COLD_THD_80_PCT] = BIT(1),
+};
+
+ static inline int
get_bpd(const char *name)
{
int i = 0;
@@ -1416,7 +1437,39 @@
return 0;
}
-#define QPNP_CHG_VINMIN_MIN_MV 3400
+#define BTC_CONFIG_ENABLED BIT(7)
+#define BTC_COLD BIT(1)
+#define BTC_HOT BIT(0)
+static int
+qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
+{
+ u8 btc_cfg = 0, mask = 0;
+
+ /* Do nothing if battery peripheral not present */
+ if (!chip->bat_if_base)
+ return 0;
+
+ if ((chip->hot_batt_p == HOT_THD_25_PCT)
+ || (chip->hot_batt_p == HOT_THD_35_PCT)) {
+ btc_cfg |= btc_value[chip->hot_batt_p];
+ mask |= BTC_HOT;
+ }
+
+ if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
+ (chip->cold_batt_p == COLD_THD_80_PCT)) {
+ btc_cfg |= btc_value[chip->cold_batt_p];
+ mask |= BTC_COLD;
+ }
+
+ if (chip->btc_disabled)
+ mask |= BTC_CONFIG_ENABLED;
+
+ return qpnp_chg_masked_write(chip,
+ chip->bat_if_base + BAT_IF_BTC_CTRL,
+ mask, btc_cfg, 1);
+}
+
+#define QPNP_CHG_VINMIN_MIN_MV 4200
#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
#define QPNP_CHG_VINMIN_MAX_MV 9600
@@ -2637,6 +2690,8 @@
OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
+ OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
+ OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
if (rc)
return rc;
@@ -2669,6 +2724,10 @@
return rc;
}
+ /* Get the btc-disabled property */
+ chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
+ "qcom,btc-disabled");
+
/* Get the charging-disabled property */
chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
"qcom,charging-disabled");
@@ -2992,6 +3051,11 @@
}
}
}
+ rc = qpnp_chg_bat_if_configure_btc(chip);
+ if (rc) {
+ pr_err("failed to configure btc %d\n", rc);
+ goto unregister_batt;
+ }
qpnp_chg_charge_en(chip, !chip->charging_disabled);
qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c
index e0bffb9..bfbae78 100644
--- a/drivers/rtc/qpnp-rtc.c
+++ b/drivers/rtc/qpnp-rtc.c
@@ -45,6 +45,11 @@
#define TO_SECS(arr) (arr[0] | (arr[1] << 8) | (arr[2] << 16) | \
(arr[3] << 24))
+/* Module parameter to control power-on-alarm */
+static bool poweron_alarm;
+module_param(poweron_alarm, bool, 0644);
+MODULE_PARM_DESC(poweron_alarm, "Enable/Disable power-on alarm");
+
/* rtc driver internal structure */
struct qpnp_rtc {
u8 rtc_ctrl_reg;
@@ -586,7 +591,7 @@
struct qpnp_rtc *rtc_dd = dev_get_drvdata(&spmi->dev);
bool rtc_alarm_powerup = rtc_dd->rtc_alarm_powerup;
- if (!rtc_alarm_powerup) {
+ if (!rtc_alarm_powerup && !poweron_alarm) {
spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
dev_dbg(&spmi->dev, "Disabling alarm interrupts\n");
diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c
index 03c58a4..dbab808 100644
--- a/drivers/scsi/ufs/ufs_test.c
+++ b/drivers/scsi/ufs/ufs_test.c
@@ -18,13 +18,27 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <../sd.h>
+#include <linux/delay.h>
#define MODULE_NAME "ufs_test"
-#define TEST_MAX_BIOS_PER_REQ 120
+#define TEST_MAX_BIOS_PER_REQ 16
#define LARGE_PRIME_1 1103515367
#define LARGE_PRIME_2 35757
-#define DEFAULT_NUM_OF_BIOS 2
+#define DEFAULT_NUM_OF_BIOS 2
+
+/* the amount of requests that will be inserted */
+#define LONG_SEQ_TEST_NUM_REQS 256
+/* request queue limitation is 128 requests, and we leave 10 spare requests */
+#define QUEUE_MAX_REQUESTS 118
+#define MB_MSEC_RATIO_APPROXIMATION ((1024 * 1024) / 1000)
+/* actual number of MiB in test multiplied by 10, for single digit precision*/
+#define BYTE_TO_MB_x_10(x) ((x * 10) / (1024 * 1024))
+/* extract integer value */
+#define LONG_TEST_SIZE_INTEGER(x) (BYTE_TO_MB_x_10(x) / 10)
+/* and calculate the MiB value fraction */
+#define LONG_TEST_SIZE_FRACTION(x) (BYTE_TO_MB_x_10(x) - \
+ (LONG_TEST_SIZE_INTEGER(x) * 10))
#define test_pr_debug(fmt, args...) pr_debug("%s: "fmt"\n", MODULE_NAME, args)
#define test_pr_info(fmt, args...) pr_info("%s: "fmt"\n", MODULE_NAME, args)
@@ -32,11 +46,16 @@
enum ufs_test_testcases {
UFS_TEST_WRITE_READ_TEST,
+
+ TEST_LONG_SEQUENTIAL_READ,
+ TEST_LONG_SEQUENTIAL_WRITE,
};
struct ufs_test_debug {
struct dentry *write_read_test; /* basic test */
struct dentry *random_test_seed; /* parameters in utils */
+ struct dentry *long_sequential_read_test;
+ struct dentry *long_sequential_write_test;
};
struct ufs_test_data {
@@ -60,6 +79,8 @@
* disabled and 2 BIOs are written.
*/
unsigned int random_test_seed;
+ /* A counter for the number of test requests completed */
+ unsigned int completed_req_count;
};
static struct ufs_test_data *utd;
@@ -77,6 +98,12 @@
case UFS_TEST_WRITE_READ_TEST:
return "UFS write read test";
break;
+ case TEST_LONG_SEQUENTIAL_READ:
+ return "UFS long sequential read test";
+ break;
+ case TEST_LONG_SEQUENTIAL_WRITE:
+ return "UFS long sequential write test";
+ break;
default:
return "Unknown test";
}
@@ -166,8 +193,9 @@
num_bios = DEFAULT_NUM_OF_BIOS;
/* Adding a write request */
- test_pr_info("%s: Adding a write requests to Q, first req_id=%d",
- __func__, td->wr_rd_next_req_id);
+ test_pr_info(
+ "%s: Adding a write request with %d bios to Q, req_id=%d"
+ , __func__, num_bios, td->wr_rd_next_req_id);
utd->write_completed = false;
ret = test_iosched_add_wr_rd_test_req(0, WRITE, start_sec,
@@ -265,21 +293,290 @@
.read = ufs_test_write_read_test_read_cb,
};
+static void long_seq_test_free_end_io_fn(struct request *rq, int err)
+{
+ struct test_request *test_rq;
+ struct test_data *ptd = test_get_test_data();
+
+ if (rq)
+ test_rq = (struct test_request *)rq->elv.priv[0];
+ else {
+ test_pr_err("%s: error: NULL request", __func__);
+ return;
+ }
+
+ BUG_ON(!test_rq);
+
+ spin_lock_irq(&ptd->lock);
+ ptd->dispatched_count--;
+ list_del_init(&test_rq->queuelist);
+ __blk_put_request(ptd->req_q, test_rq->rq);
+ spin_unlock_irq(&ptd->lock);
+
+ kfree(test_rq->bios_buffer);
+ kfree(test_rq);
+ utd->completed_req_count++;
+
+ test_pr_err("%s: request %d completed, err=%d",
+ __func__, test_rq->req_id, err);
+
+ check_test_completion();
+
+}
+
+static int run_long_seq_test(struct test_data *td)
+{
+ int ret = 0;
+ int direction;
+ static unsigned int inserted_requests;
+
+ BUG_ON(!td);
+ td->test_count = 0;
+ utd->completed_req_count = 0;
+ inserted_requests = 0;
+
+ if (td->test_info.testcase == TEST_LONG_SEQUENTIAL_READ)
+ direction = READ;
+ else
+ direction = WRITE;
+
+ test_pr_info("%s: Adding %d requests, first req_id=%d",
+ __func__, LONG_SEQ_TEST_NUM_REQS,
+ td->wr_rd_next_req_id);
+
+ do {
+ /*
+ * since our requests come from a pool containing 128
+ * requests, we don't want to exhaust this quantity,
+ * therefore we add up to QUEUE_MAX_REQUESTS (which
+ * includes a safety margin) and then call the mmc layer
+ * to fetch them
+ */
+ if (td->test_count >= QUEUE_MAX_REQUESTS) {
+ blk_run_queue(td->req_q);
+ continue;
+ }
+
+ ret = test_iosched_add_wr_rd_test_req(0, direction,
+ td->start_sector, TEST_MAX_BIOS_PER_REQ,
+ TEST_PATTERN_5A,
+ long_seq_test_free_end_io_fn);
+ if (ret) {
+ test_pr_err("%s: failed to create request" , __func__);
+ break;
+ }
+ inserted_requests++;
+ td->test_info.test_byte_count +=
+ (TEST_MAX_BIOS_PER_REQ * sizeof(unsigned int) *
+ BIO_U32_SIZE);
+
+ } while (inserted_requests < LONG_SEQ_TEST_NUM_REQS);
+
+ /* in this case the queue will not run in the above loop */
+ if (LONG_SEQ_TEST_NUM_REQS < QUEUE_MAX_REQUESTS)
+ blk_run_queue(td->req_q);
+
+ return ret;
+}
+
+
+void long_seq_test_calc_throughput(unsigned long mtime,
+ unsigned long byte_count)
+{
+ unsigned long fraction, integer;
+
+ test_pr_info("%s: time is %lu msec, size is %lu.%lu MiB",
+ __func__, mtime, LONG_TEST_SIZE_INTEGER(byte_count),
+ LONG_TEST_SIZE_FRACTION(byte_count));
+
+ /* we first multiply in order not to lose precision */
+ mtime *= MB_MSEC_RATIO_APPROXIMATION;
+ /* divide values to get a MiB/sec integer value with one
+ digit of precision
+ */
+ fraction = integer = (byte_count * 10) / mtime;
+ integer /= 10;
+ /* and calculate the MiB value fraction */
+ fraction -= integer * 10;
+
+ test_pr_info("%s: Throughput: %lu.%lu MiB/sec\n",
+ __func__, integer, fraction);
+}
+
+static ssize_t long_sequential_read_test_write(struct file *file,
+ const char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ int ret = 0;
+ int i = 0;
+ int number = -1;
+ unsigned long mtime, byte_count;
+
+ test_pr_info("%s: -- UFS Long Sequential Read TEST --", __func__);
+
+ sscanf(buf, "%d", &number);
+
+ if (number <= 0)
+ number = 1;
+
+ memset(&utd->test_info, 0, sizeof(struct test_info));
+
+ utd->test_info.data = utd;
+ utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk;
+ utd->test_info.run_test_fn = run_long_seq_test;
+ utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str;
+ utd->test_info.testcase = TEST_LONG_SEQUENTIAL_READ;
+
+ for (i = 0 ; i < number ; ++i) {
+ test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
+ test_pr_info("%s: ====================", __func__);
+
+ ret = test_iosched_start_test(&utd->test_info);
+ if (ret)
+ break;
+
+ mtime = ktime_to_ms(utd->test_info.test_duration);
+ byte_count = utd->test_info.test_byte_count;
+
+ long_seq_test_calc_throughput(mtime, byte_count);
+
+ /* Allow FS requests to be dispatched */
+ msleep(1000);
+ }
+
+ return count;
+}
+
+static ssize_t long_sequential_read_test_read(struct file *file,
+ char __user *buffer,
+ size_t count,
+ loff_t *offset)
+{
+ memset((void *)buffer, 0, count);
+
+ snprintf(buffer, count,
+ "\nufs_long_sequential_read_test\n"
+ "=========\n"
+ "Description:\n"
+ "This test runs the following scenarios\n"
+ "- Long Sequential Read Test: this test measures read "
+ "throughput at the driver level by sequentially reading many "
+ "large requests.\n");
+
+ if (message_repeat == 1) {
+ message_repeat = 0;
+ return strnlen(buffer, count);
+ } else
+ return 0;
+}
+
+static bool message_repeat;
+static int test_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ message_repeat = 1;
+ return 0;
+}
+
+const struct file_operations long_sequential_read_test_ops = {
+ .open = test_open,
+ .write = long_sequential_read_test_write,
+ .read = long_sequential_read_test_read,
+};
+
+static ssize_t long_sequential_write_test_write(struct file *file,
+ const char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ int ret = 0;
+ int i = 0;
+ int number = -1;
+ unsigned long mtime, byte_count;
+
+ test_pr_info("%s: -- UFS Long Sequential Write TEST --", __func__);
+
+ sscanf(buf, "%d", &number);
+
+ if (number <= 0)
+ number = 1;
+
+ memset(&utd->test_info, 0, sizeof(struct test_info));
+
+ utd->test_info.data = utd;
+ utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk;
+ utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str;
+ utd->test_info.run_test_fn = run_long_seq_test;
+ utd->test_info.testcase = TEST_LONG_SEQUENTIAL_WRITE;
+
+ for (i = 0 ; i < number ; ++i) {
+ test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
+ test_pr_info("%s: ====================", __func__);
+
+ utd->test_info.test_byte_count = 0;
+ ret = test_iosched_start_test(&utd->test_info);
+ if (ret)
+ break;
+
+ mtime = ktime_to_ms(utd->test_info.test_duration);
+ byte_count = utd->test_info.test_byte_count;
+
+ long_seq_test_calc_throughput(mtime, byte_count);
+
+ /* Allow FS requests to be dispatched */
+ msleep(1000);
+ }
+
+ return count;
+}
+
+static ssize_t long_sequential_write_test_read(struct file *file,
+ char __user *buffer,
+ size_t count,
+ loff_t *offset)
+{
+ memset((void *)buffer, 0, count);
+
+ snprintf(buffer, count,
+ "\nufs_long_sequential_write_test\n"
+ "=========\n"
+ "Description:\n"
+ "This test runs the following scenarios\n"
+ "- Long Sequential Write Test: this test measures write "
+ "throughput at the driver level by sequentially writing many "
+ "large requests\n");
+
+ if (message_repeat == 1) {
+ message_repeat = 0;
+ return strnlen(buffer, count);
+ } else
+ return 0;
+}
+
+const struct file_operations long_sequential_write_test_ops = {
+ .open = test_open,
+ .write = long_sequential_write_test_write,
+ .read = long_sequential_write_test_read,
+};
+
static void ufs_test_debugfs_cleanup(void)
{
- debugfs_remove(utd->debug.write_read_test);
+ debugfs_remove_recursive(test_iosched_get_debugfs_tests_root());
}
static int ufs_test_debugfs_init(void)
{
struct dentry *utils_root, *tests_root;
+ int ret = 0;
utils_root = test_iosched_get_debugfs_utils_root();
tests_root = test_iosched_get_debugfs_tests_root();
if (!utils_root || !tests_root) {
test_pr_err("%s: Failed to create debugfs root.", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
utd->debug.random_test_seed = debugfs_create_u32("random_test_seed",
@@ -288,21 +585,49 @@
if (!utd->debug.random_test_seed) {
test_pr_err("%s: Could not create debugfs random_test_seed.",
__func__);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto exit;
}
- utd->debug.write_read_test = debugfs_create_file("write_read_test",
+ utd->debug.write_read_test = debugfs_create_file("ufs_write_read_test",
S_IRUGO | S_IWUGO, tests_root,
NULL, &write_read_test_ops);
if (!utd->debug.write_read_test) {
- debugfs_remove(utd->debug.random_test_seed);
- test_pr_err("%s: Could not create debugfs write_read_test.",
- __func__);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto exit_err;
}
- return 0;
+ utd->debug.long_sequential_read_test = debugfs_create_file(
+ "ufs_long_sequential_read_test",
+ S_IRUGO | S_IWUGO,
+ tests_root,
+ NULL,
+ &long_sequential_read_test_ops);
+
+ if (!utd->debug.long_sequential_read_test) {
+ ret = -ENOMEM;
+ goto exit_err;
+ }
+
+ utd->debug.long_sequential_write_test = debugfs_create_file(
+ "ufs_long_sequential_write_test",
+ S_IRUGO | S_IWUGO,
+ tests_root,
+ NULL,
+ &long_sequential_write_test_ops);
+
+ if (!utd->debug.long_sequential_write_test) {
+ ret = -ENOMEM;
+ goto exit_err;
+ }
+
+ goto exit;
+
+exit_err:
+ debugfs_remove_recursive(tests_root);
+exit:
+ return ret;
}
static void ufs_test_probe(void)
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 97d47db..6e7a815 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -30,12 +30,6 @@
#define MSM_SLIM_NAME "msm_slim_ctrl"
#define SLIM_ROOT_FREQ 24576000
-#define QC_MFGID_LSB 0x2
-#define QC_MFGID_MSB 0x17
-#define QC_CHIPID_SL 0x10
-#define QC_DEVID_SAT1 0x3
-#define QC_DEVID_SAT2 0x4
-#define QC_DEVID_PGD 0x5
#define QC_MSM_DEVS 5
/* Manager registers */
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 509c1e8..2f19863 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -306,8 +306,26 @@
txn->mc = SLIM_USR_MC_CONNECT_SINK;
else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
- if (txn->la == SLIM_LA_MGR)
+ if (txn->la == SLIM_LA_MGR) {
+ if (dev->pgdla == SLIM_LA_MGR) {
+ u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
+ QC_MFGID_LSB};
+ ea[2] = (u8)(dev->pdata.eapc & 0xFF);
+ ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
+ mutex_unlock(&dev->tx_lock);
+ ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
+ &dev->pgdla);
+ pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
+ ret);
+ if (ret) {
+ pr_err("Incorrect SLIM-PGD EAPC:0x%x",
+ dev->pdata.eapc);
+ return ret;
+ }
+ mutex_lock(&dev->tx_lock);
+ }
txn->la = dev->pgdla;
+ }
wbuf[i++] = txn->la;
la = SLIM_LA_MGR;
wbuf[i++] = txn->wbuf[0];
@@ -380,6 +398,8 @@
dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
goto ngd_xfer_err;
}
+ /* Add port-base to port number if this is manager side port */
+ puc[1] += dev->port_b;
}
dev->err = 0;
dev->wr_comp = &tx_sent;
@@ -1070,9 +1090,18 @@
}
rxreg_access = of_property_read_bool(pdev->dev.of_node,
"qcom,rxreg-access");
+ of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
+ &dev->pdata.apps_pipes);
+ of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
+ &dev->pdata.eapc);
} else {
dev->ctrl.nr = pdev->id;
}
+ /*
+ * Keep PGD's logical address as manager's. Query it when first data
+ * channel request comes in
+ */
+ dev->pgdla = SLIM_LA_MGR;
dev->ctrl.nchans = MSM_SLIM_NCHANS;
dev->ctrl.nports = MSM_SLIM_NPORTS;
dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index a63ee76..37bc883 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -788,6 +788,10 @@
bam_props.options = SPS_O_DESC_DONE | SPS_O_ERROR |
SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+ /* override apps channel pipes if specified in platform-data or DT */
+ if (dev->pdata.apps_pipes)
+ sec_props.ees[dev->ee].pipe_mask = dev->pdata.apps_pipes;
+
/* First 7 bits are for message Qs */
for (i = 7; i < 32; i++) {
/* Check what pipes are owned by Apps. */
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 896e196..b5c41ed 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -50,6 +50,13 @@
#define MSM_SLIM_NPORTS 24
#define MSM_SLIM_NCHANS 32
+#define QC_MFGID_LSB 0x2
+#define QC_MFGID_MSB 0x17
+#define QC_CHIPID_SL 0x10
+#define QC_DEVID_SAT1 0x3
+#define QC_DEVID_SAT2 0x4
+#define QC_DEVID_PGD 0x5
+
#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
@@ -198,6 +205,11 @@
struct work_struct ssr_up;
};
+struct msm_slim_pdata {
+ u32 apps_pipes;
+ u32 eapc;
+};
+
struct msm_slim_ctrl {
struct slim_controller ctrl;
struct slim_framer framer;
@@ -240,6 +252,7 @@
u32 ver;
struct work_struct slave_notify;
struct msm_slim_qmi qmi;
+ struct msm_slim_pdata pdata;
};
struct msm_sat_chan {
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 39952c9..8ecc861 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -567,6 +567,8 @@
int mdss_panel_register_done(struct mdss_panel_data *pdata);
int mdss_mdp_limited_lut_igc_config(struct mdss_mdp_ctl *ctl);
int mdss_mdp_calib_config(struct mdp_calib_config_data *cfg, u32 *copyback);
+int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
+ u32 *copyback);
int mdss_mdp_pipe_is_staged(struct mdss_mdp_pipe *pipe);
int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 953cbff..24b27b4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1241,7 +1241,7 @@
static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
{
- struct mdss_mdp_data data;
+ struct mdss_mdp_data *buf;
struct mdss_mdp_pipe *pipe;
struct fb_info *fbi;
struct mdss_overlay_private *mdp5_data;
@@ -1271,8 +1271,6 @@
return;
}
- memset(&data, 0, sizeof(data));
-
bpp = fbi->var.bits_per_pixel / 8;
offset = fbi->var.xoffset * bpp +
fbi->var.yoffset * fbi->fix.line_length;
@@ -1289,18 +1287,6 @@
goto pan_display_error;
}
- if (is_mdss_iommu_attached()) {
- if (!mfd->iova) {
- pr_err("mfd iova is zero\n");
- goto pan_display_error;
- }
- data.p[0].addr = mfd->iova;
- } else
- data.p[0].addr = fbi->fix.smem_start;
-
- data.p[0].addr += offset;
- data.p[0].len = fbi->fix.smem_len - offset;
- data.num_planes = 1;
ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe, MDSS_MDP_MIXER_MUX_LEFT);
if (ret) {
@@ -1312,13 +1298,23 @@
pr_err("unable to map base pipe\n");
goto pan_display_error;
}
- ret = mdss_mdp_pipe_queue_data(pipe, &data);
- mdss_mdp_pipe_unmap(pipe);
- if (ret) {
- pr_err("unable to queue data\n");
- goto pan_display_error;
+
+ buf = &pipe->back_buf;
+ if (is_mdss_iommu_attached()) {
+ if (!mfd->iova) {
+ pr_err("mfd iova is zero\n");
+ goto pan_display_error;
+ }
+ buf->p[0].addr = mfd->iova;
+ } else {
+ buf->p[0].addr = fbi->fix.smem_start;
}
+ buf->p[0].addr += offset;
+ buf->p[0].len = fbi->fix.smem_len - offset;
+ buf->num_planes = 1;
+ mdss_mdp_pipe_unmap(pipe);
+
if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
MDSS_MDP_MIXER_MUX_RIGHT);
@@ -1330,12 +1326,8 @@
pr_err("unable to map right base pipe\n");
goto pan_display_error;
}
- ret = mdss_mdp_pipe_queue_data(pipe, &data);
+ pipe->back_buf = *buf;
mdss_mdp_pipe_unmap(pipe);
- if (ret) {
- pr_err("unable to queue right data\n");
- goto pan_display_error;
- }
}
mutex_unlock(&mdp5_data->ov_lock);
@@ -1684,6 +1676,11 @@
case mdp_op_calib_mode:
ret = mdss_mdp_calib_mode(mfd, &mdp_pp.data.mdss_calib_cfg);
break;
+ case mdp_op_calib_buffer:
+ ret = mdss_mdp_calib_config_buffer(
+ (struct mdp_calib_config_buffer *)
+ &mdp_pp.data.calib_buffer, ©back);
+ break;
default:
pr_err("Unsupported request to MDP_PP IOCTL. %d = op\n",
mdp_pp.op);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 4dd9dcb..6cedd98 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -3376,3 +3376,69 @@
mutex_unlock(&mdss_pp_mutex);
return 0;
}
+
+int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
+ u32 *copyback)
+{
+ int ret = -1;
+ int counter = cfg->size / (sizeof(uint32_t) * 2);
+ uint32_t *buff = NULL, *buff_org = NULL;
+ void *ptr;
+ int i = 0;
+
+ buff_org = buff = kzalloc(cfg->size, GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("Allocation failed");
+ return ret;
+ }
+
+ if (copy_from_user(buff, cfg->buffer, cfg->size)) {
+ kfree(buff);
+ pr_err("Copy failed");
+ return ret;
+ }
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+ if (cfg->ops & MDP_PP_OPS_READ) {
+ for (i = 0 ; i < counter ; i++) {
+ if (is_valid_calib_addr((void *) *buff)) {
+ ret = 0;
+ } else {
+ ret = -1;
+ pr_err("Address validation failed");
+ break;
+ }
+
+ ptr = (void *)(((unsigned int) *buff) +
+ (mdss_res->mdp_base));
+ buff++;
+ *buff = readl_relaxed(ptr);
+ buff++;
+ }
+ if (!ret)
+ ret = copy_to_user(cfg->buffer, buff_org, cfg->size);
+ *copyback = 1;
+ } else if (cfg->ops & MDP_PP_OPS_WRITE) {
+ for (i = 0 ; i < counter ; i++) {
+ if (is_valid_calib_addr((void *) *buff)) {
+ ret = 0;
+ } else {
+ ret = -1;
+ pr_err("Address validation failed");
+ break;
+ }
+
+ ptr = (void *)(((unsigned int) *buff) +
+ (mdss_res->mdp_base));
+ buff++;
+ writel_relaxed(*buff, ptr);
+ buff++;
+ }
+ }
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+ kfree(buff_org);
+ return ret;
+}
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 3ae83d6..dd675f3 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -531,6 +531,9 @@
/* Indicates whether TS insertion is supported */
#define DMX_CAP_TS_INSERTION 0x20
+/* Indicates whether playback from secured input is supported */
+#define DMX_CAP_SECURED_INPUT_PLAYBACK 0x40
+
/* Number of decoders demux can output data to */
int num_decoders;
@@ -570,6 +573,9 @@
/* Max bitrate from single memory input. Mbit/sec */
int memory_input_max_bitrate;
+ /* Max number of supported cipher operations per PID */
+ int num_cipher_ops;
+
/* Max possible value of STC reported by demux, in 27MHz */
__u64 max_stc;
@@ -660,6 +666,15 @@
struct dmx_buffer {
unsigned int size;
int handle;
+
+ /*
+ * The following indication is relevant only when setting
+ * DVR input buffer. It indicates whether the input buffer
+ * being set is secured one or not. Secured (locked) buffers
+ * are required for playback from secured input. In such case
+ * write() syscall is not allowed.
+ */
+ int is_protected;
};
struct dmx_decoder_buffers {
@@ -684,16 +699,41 @@
struct dmx_secure_mode {
/*
- * Specifies whether secure mode should be set or not for the filter's
- * pid. Note that DMX_OUT_TSDEMUX_TAP filters can have more than 1 pid
+ * Specifies whether the filter is secure or not.
+ * Filter should be set as secured if the filter's data *may* include
+ * encrypted data that would require decryption configured through
+ * DMX_SET_CIPHER ioctl. The setting may be done while
+ * filter is in idle state only.
*/
int is_secured;
+};
- /* PID to associate with key ladder id */
+struct dmx_cipher_operation {
+ /* Indication whether the operation is encryption or decryption */
+ int encrypt;
+
+ /* The ID of the key used for decryption or encryption */
+ __u32 key_ladder_id;
+};
+
+#define DMX_MAX_CIPHER_OPERATIONS_COUNT 5
+struct dmx_cipher_operations {
+ /*
+ * The PID to perform the cipher operations on.
+ * In case of recording filter, multiple PIDs may exist in the same
+ * filter through DMX_ADD_PID ioctl, each may have different
+ * cipher operations.
+ */
__u16 pid;
- /* key ladder information to associate with the specified pid */
- __u32 key_ladder_id;
+ /* Total number of operations */
+ __u8 operations_count;
+
+ /*
+ * Cipher operation to perform on the given PID.
+ * The operations are performed in the order they are given.
+ */
+ struct dmx_cipher_operation operations[DMX_MAX_CIPHER_OPERATIONS_COUNT];
};
struct dmx_events_mask {
@@ -825,5 +865,7 @@
#define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
#define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
#define DMX_GET_SCRAMBLING_BITS _IOWR('o', 72, struct dmx_scrambling_bits)
+#define DMX_SET_CIPHER _IOW('o', 73, struct dmx_cipher_operations)
+
#endif /*_DVBDMX_H_*/
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 18921a0..c3ff9de 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -606,6 +606,12 @@
uint32_t data;
};
+struct mdp_calib_config_buffer {
+ uint32_t ops;
+ uint32_t size;
+ uint32_t *buffer;
+};
+
#define MDSS_MAX_BL_BRIGHTNESS 255
#define AD_BL_LIN_LEN (MDSS_MAX_BL_BRIGHTNESS + 1)
@@ -697,6 +703,7 @@
mdp_op_ad_cfg,
mdp_op_ad_input,
mdp_op_calib_mode,
+ mdp_op_calib_buffer,
mdp_op_max,
};
@@ -724,6 +731,7 @@
struct mdss_ad_init_cfg ad_init_cfg;
struct mdss_calib_cfg mdss_calib_cfg;
struct mdss_ad_input ad_input;
+ struct mdp_calib_config_buffer calib_buffer;
} data;
};
diff --git a/include/linux/test-iosched.h b/include/linux/test-iosched.h
index 89d3b30..5b05b7a 100644
--- a/include/linux/test-iosched.h
+++ b/include/linux/test-iosched.h
@@ -130,7 +130,7 @@
* @check_test_result_fn: Test specific test result checking
* callback
* @get_test_case_str_fn: Test specific function to get the test name
- * @test_duration: A jiffies value saved for timing
+ * @test_duration: A ktime value saved for timing
* calculations
* @data: Test specific private data
* @test_byte_count: Total number of bytes dispatched in
@@ -144,7 +144,7 @@
check_test_result_fn *check_test_result_fn;
post_test_fn *post_test_fn;
get_test_case_str_fn *get_test_case_str_fn;
- unsigned long test_duration;
+ ktime_t test_duration;
get_rq_disk_fn *get_rq_disk_fn;
void *data;
unsigned long test_byte_count;
@@ -263,4 +263,6 @@
void test_iosched_add_urgent_req(struct test_request *test_rq);
int test_is_req_urgent(struct request *rq);
+
+void check_test_completion(void);
#endif /* _LINUX_TEST_IOSCHED_H */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2356791..d85cf09 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -648,6 +648,9 @@
struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
int err;
+ if (addr_len < sizeof(struct sockaddr_nl))
+ return -EINVAL;
+
if (nladdr->nl_family != AF_NETLINK)
return -EINVAL;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index f67af9b..0b7e7f2 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -208,6 +208,7 @@
static int msm_hdmi_rx_ch = 2;
static int slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
static int msm_proxy_rx_ch = 2;
+static int hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
static struct mutex cdc_mclk_mutex;
static struct clk *codec_clk;
@@ -720,6 +721,8 @@
static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight"};
+static char const *hdmi_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
+ "KHZ_192"};
static const char *const btsco_rate_text[] = {"8000", "16000"};
static const struct soc_enum msm_btsco_enum[] = {
SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
@@ -940,6 +943,57 @@
return 1;
}
+static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int sample_rate_val = 0;
+
+ switch (hdmi_rx_sample_rate) {
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 2;
+ break;
+
+ case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 1;
+ break;
+
+ case SAMPLING_RATE_48KHZ:
+ default:
+ sample_rate_val = 0;
+ break;
+ }
+
+ ucontrol->value.integer.value[0] = sample_rate_val;
+ pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
+ hdmi_rx_sample_rate);
+
+ return 0;
+}
+
+static int hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: ucontrol value = %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 2:
+ hdmi_rx_sample_rate = SAMPLING_RATE_192KHZ;
+ break;
+ case 1:
+ hdmi_rx_sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 0:
+ default:
+ hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
+ }
+
+ pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
+ hdmi_rx_sample_rate);
+
+ return 0;
+}
+
static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -1055,7 +1109,7 @@
hdmi_rx_bit_format);
if (channels->max < 2)
channels->min = channels->max = 2;
- rate->min = rate->max = 48000;
+ rate->min = rate->max = hdmi_rx_sample_rate;
channels->min = channels->max = msm_hdmi_rx_ch;
return 0;
@@ -1324,6 +1378,7 @@
SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
+ SOC_ENUM_SINGLE_EXT(3, hdmi_rx_sample_rate_text),
};
static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1347,6 +1402,8 @@
msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
msm_btsco_rate_get, msm_btsco_rate_put),
+ SOC_ENUM_EXT("HDMI_RX SampleRate", msm_snd_enum[7],
+ hdmi_rx_sample_rate_get, hdmi_rx_sample_rate_put),
};
static bool msm8974_swap_gnd_mic(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 60f4669..094c58b 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -2356,10 +2356,11 @@
}
if (common.ec_ref_ext == true) {
ret = voice_send_set_device_cmd_v2(v);
- if (ret < 0)
+ if (ret < 0) {
pr_err("%s: set device V2 failed rc =%x\n",
__func__, ret);
goto fail;
+ }
}
/* send cvs cal */
ret = voice_send_cvs_map_memory_cmd(v);
@@ -3354,10 +3355,11 @@
if (v->voc_state == VOC_CHANGE) {
if (common.ec_ref_ext == true) {
ret = voice_send_set_device_cmd_v2(v);
- if (ret < 0)
+ if (ret < 0) {
pr_err("%s: set device V2 failed\n"
"rc =%x\n", __func__, ret);
goto fail;
+ }
} else {
ret = voice_send_set_device_cmd(v);
if (ret < 0) {
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 16df886..0cf044c 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -264,11 +264,12 @@
static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
.playback = {
- .rates = SNDRV_PCM_RATE_48000,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
.channels_min = 2,
.channels_max = 8,
- .rate_max = 48000,
+ .rate_max = 192000,
.rate_min = 48000,
},
.ops = &msm_dai_q6_hdmi_ops,
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index d31e2c5..1434970 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -42,6 +42,10 @@
};
enum {
STATUS_PORT_STARTED, /* track if AFE port has started */
+ /* track AFE Tx port status for bi-directional transfers */
+ STATUS_TX_PORT,
+ /* track AFE Rx port status for bi-directional transfers */
+ STATUS_RX_PORT,
STATUS_MAX
};
@@ -70,8 +74,9 @@
};
struct msm_dai_q6_auxpcm_dai_data {
+ /* BITMAP to track Rx and Tx port usage count */
+ DECLARE_BITMAP(auxpcm_port_status, STATUS_MAX);
struct mutex rlock; /* auxpcm dev resource lock */
- int rcnt; /* auxpcm dev resource usage count */
u16 rx_pid; /* AUXPCM RX AFE port ID */
u16 tx_pid; /* AUXPCM TX AFE port ID */
struct afe_clk_cfg clk_cfg; /* hold LPASS clock configuration */
@@ -116,7 +121,8 @@
mutex_lock(&aux_dai_data->rlock);
- if (aux_dai_data->rcnt) {
+ if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+ test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
/* AUXPCM DAI in use */
if (dai_data->rate != params_rate(params)) {
dev_err(dai->dev, "%s: rate mismatch of running DAI\n",
@@ -184,36 +190,46 @@
{
int rc = 0;
struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
- struct afe_clk_cfg lpass_pcm_oe_clk;
struct msm_dai_q6_auxpcm_dai_data *aux_dai_data =
dev_get_drvdata(dai->dev);
mutex_lock(&aux_dai_data->rlock);
- if (aux_dai_data->rcnt == 0) {
- dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just return\n",
+ if (!(test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+ test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status))) {
+ dev_dbg(dai->dev, "%s(): dai->id %d PCM ports already closed\n",
__func__, dai->id);
- mutex_unlock(&aux_dai_data->rlock);
- return;
+ goto exit;
}
- aux_dai_data->rcnt--;
-
- if (aux_dai_data->rcnt > 0) {
- dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
- __func__, dai->id, aux_dai_data->rcnt);
- mutex_unlock(&aux_dai_data->rlock);
- return;
- } else if (aux_dai_data->rcnt < 0) {
- dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d < 0\n",
- __func__, dai->id, aux_dai_data->rcnt);
- aux_dai_data->rcnt = 0;
- mutex_unlock(&aux_dai_data->rlock);
- return;
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status))
+ clear_bit(STATUS_TX_PORT,
+ aux_dai_data->auxpcm_port_status);
+ else {
+ dev_dbg(dai->dev, "%s(): PCM_TX port already closed\n",
+ __func__);
+ goto exit;
+ }
+ } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status))
+ clear_bit(STATUS_RX_PORT,
+ aux_dai_data->auxpcm_port_status);
+ else {
+ dev_dbg(dai->dev, "%s(): PCM_RX port already closed\n",
+ __func__);
+ goto exit;
+ }
+ }
+ if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+ test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+ dev_dbg(dai->dev, "%s(): cannot shutdown PCM ports\n",
+ __func__);
+ goto exit;
}
- dev_dbg(dai->dev, "%s: dai->id = %d aux_pcm_count = %d\n", __func__,
- dai->id, aux_dai_data->rcnt);
+ dev_dbg(dai->dev, "%s: dai->id = %d closing PCM AFE ports\n",
+ __func__, dai->id);
lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
@@ -229,12 +245,9 @@
afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
- memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
- sizeof(struct afe_clk_cfg));
- lpass_pcm_oe_clk.clk_val1 = 0;
- afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
-
+exit:
mutex_unlock(&aux_dai_data->rlock);
+ return;
}
static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
@@ -246,7 +259,6 @@
struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
int rc = 0;
unsigned long pcm_clk_rate;
- struct afe_clk_cfg lpass_pcm_oe_clk;
struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
auxpcm_pdata = dai->dev->platform_data;
@@ -254,32 +266,39 @@
mutex_lock(&aux_dai_data->rlock);
- if (aux_dai_data->rcnt == 2) { /* xrun case ? */
- dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just return.\n",
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ if (test_bit(STATUS_TX_PORT,
+ aux_dai_data->auxpcm_port_status)) {
+ dev_dbg(dai->dev, "%s(): PCM_TX port already ON\n",
+ __func__);
+ goto exit;
+ } else
+ set_bit(STATUS_TX_PORT,
+ aux_dai_data->auxpcm_port_status);
+ } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (test_bit(STATUS_RX_PORT,
+ aux_dai_data->auxpcm_port_status)) {
+ dev_dbg(dai->dev, "%s(): PCM_RX port already ON\n",
+ __func__);
+ goto exit;
+ } else
+ set_bit(STATUS_RX_PORT,
+ aux_dai_data->auxpcm_port_status);
+ }
+ if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) &&
+ test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+ dev_dbg(dai->dev, "%s(): PCM ports already set\n", __func__);
+ goto exit;
+ }
+
+ dev_dbg(dai->dev, "%s: dai->id:%d opening afe ports\n",
__func__, dai->id);
- mutex_unlock(&aux_dai_data->rlock);
- return 0;
- } else if (aux_dai_data->rcnt > 2) {
- dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d > 2\n",
- __func__, dai->id, aux_dai_data->rcnt);
- mutex_unlock(&aux_dai_data->rlock);
- return 0;
- }
-
- aux_dai_data->rcnt++;
- if (aux_dai_data->rcnt == 2) {
- dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after increment\n",
- __func__, dai->id, aux_dai_data->rcnt);
- mutex_unlock(&aux_dai_data->rlock);
- return 0;
- }
-
- dev_dbg(dai->dev, "%s:dai->id:%d aux_pcm_count = %d. opening afe\n",
- __func__, dai->id, aux_dai_data->rcnt);
rc = afe_q6_interface_prepare();
- if (IS_ERR_VALUE(rc))
+ if (IS_ERR_VALUE(rc)) {
dev_err(dai->dev, "fail to open AFE APR\n");
+ goto fail;
+ }
/*
* For AUX PCM Interface the below sequence of clk
@@ -300,18 +319,14 @@
} else {
dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
dai_data->rate);
- mutex_unlock(&aux_dai_data->rlock);
- return -EINVAL;
+ rc = -EINVAL;
+ goto fail;
}
memcpy(lpass_pcm_src_clk, &lpass_clk_cfg_default,
sizeof(struct afe_clk_cfg));
lpass_pcm_src_clk->clk_val1 = pcm_clk_rate;
- memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
- sizeof(struct afe_clk_cfg));
- lpass_pcm_oe_clk.clk_val1 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
-
rc = afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
if (rc < 0) {
dev_err(dai->dev,
@@ -328,18 +343,17 @@
goto fail;
}
- rc = afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
- if (rc < 0) {
- dev_err(dai->dev,
- "%s:afe_set_lpass_clock on pcm_oe_clk failed\n",
- __func__);
- goto fail;
- }
-
afe_open(aux_dai_data->rx_pid, &dai_data->port_config, dai_data->rate);
afe_open(aux_dai_data->tx_pid, &dai_data->port_config, dai_data->rate);
+ goto exit;
fail:
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ clear_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status);
+ else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ clear_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status);
+
+exit:
mutex_unlock(&aux_dai_data->rlock);
return rc;
}
@@ -377,40 +391,30 @@
{
struct msm_dai_q6_auxpcm_dai_data *aux_dai_data;
struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
- struct afe_clk_cfg lpass_pcm_oe_clk;
int rc;
aux_dai_data = dev_get_drvdata(dai->dev);
- if (aux_dai_data->rcnt == 0) {
- dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean up and return\n",
- __func__, dai->id);
- goto done;
- }
-
dev_dbg(dai->dev, "%s(): dai->id %d closing afe\n",
__func__, dai->id);
- rc = afe_close(aux_dai_data->rx_pid); /* can block */
- if (IS_ERR_VALUE(rc))
- dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
-
- rc = afe_close(aux_dai_data->tx_pid);
- if (IS_ERR_VALUE(rc))
- dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
+ if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+ test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+ rc = afe_close(aux_dai_data->rx_pid); /* can block */
+ if (IS_ERR_VALUE(rc))
+ dev_err(dai->dev, "fail to close AUXPCM RX AFE port\n");
+ rc = afe_close(aux_dai_data->tx_pid);
+ if (IS_ERR_VALUE(rc))
+ dev_err(dai->dev, "fail to close AUXPCM TX AFE port\n");
+ clear_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status);
+ clear_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status);
+ }
lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
-
lpass_pcm_src_clk->clk_val1 = 0;
afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
- memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
- sizeof(struct afe_clk_cfg));
- lpass_pcm_oe_clk.clk_val1 = 0;
- afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
-
-done:
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 9fb4eae..0735b7a 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -4291,9 +4291,14 @@
apr_reset(c->apr_q6_mvm);
c->apr_q6_mvm = NULL;
+ /* clean up memory handle */
+ c->cal_mem_handle = 0;
+
/* Sub-system restart is applicable to all sessions. */
- for (i = 0; i < MAX_VOC_SESSIONS; i++)
+ for (i = 0; i < MAX_VOC_SESSIONS; i++) {
c->voice[i].mvm_handle = 0;
+ c->voice[i].shmem_info.mem_handle = 0;
+ }
}
return 0;
}