Merge "msm: pm: Rearchitect power management code"
diff --git a/Documentation/devicetree/bindings/arm/msm/acpuclock/clock-a7.txt b/Documentation/devicetree/bindings/arm/msm/acpuclock/clock-a7.txt
new file mode 100644
index 0000000..10eb0fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/acpuclock/clock-a7.txt
@@ -0,0 +1,37 @@
+* Qualcomm Application CPU clock driver
+
+clock-a7 is the driver for the Root Clock Generator (rcg) hw which controls
+the cpu rate. RCGs support selecting one of several clock inputs, as well as
+a configurable divider. This hw is different than normal rcgs in that it may
+optionally have a register which encodes the maximum rate supported by hw.
+
+Required properties:
+- compatible: "qcom,clock-a7-8226"
+- reg: pairs of physical address and region size
+- reg-names: "rcg-base" is expected
+- clock-names: list of names of clock inputs
+- qcom,speedX-bin-vZ:
+ A table of CPU frequency (Hz) to regulator voltage (uV) mapping.
+ Format: <freq uV>
+ This represents the max frequency possible for each possible
+ power configuration for a CPU that's binned as speed bin X,
+ speed bin revision Z. Speed bin values can be between [0-7]
+ and the version can be between [0-3].
+
+- cpu-vdd-supply: regulator phandle for cpu power domain.
+
+Optional properties:
+- reg-names: "efuse"
+
+Example:
+ qcom,acpuclk@f9011050 {
+ compatible = "qcom,clock-a7-8226";
+ reg = <0xf9011050 0x8>;
+ reg-names = "rcg_base";
+ cpu-vdd-supply = <&apc_vreg_corner>;
+
+ clock-names = "clk-4", "clk-5";
+ qcom,speed0-bin-v0 =
+ <384000000 1150000>,
+ <600000000 1200000>;
+ };
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 08d2c2d..0e236f2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -178,34 +178,33 @@
- qcom,mdss-dsi-bllp-power-mode: Boolean to determine DSI lane state during
blanking low power period (BLLP) mode.
- qcom,mdss-dsi-traffic-mode: Specifies the panel traffic mode.
- 0 = non burst with sync pulses (default mode).
- 1 = non burst with sync start event.
- 2 = burst mode.
+ "non_burst_sync_pulse" = non burst with sync pulses (default).
+ "non_burst_sync_event" = non burst with sync start event.
+ "burst_mode" = burst mode.
- qcom,mdss-dsi-pixel-packing: Specifies if pixel packing is used (in case of RGB666).
- 0 = Tight packing (default value).
- 1 = Loose packing.
+ "tight" = Tight packing (default value).
+ "loose" = Loose packing.
- qcom,mdss-dsi-virtual-channel-id: Specifies the virtual channel identefier.
0 = default value.
- qcom,mdss-dsi-color-order: Specifies the R, G and B channel ordering.
- 0 = DSI_RGB_SWAP_RGB (default value)
- 1 = DSI_RGB_SWAP_RBG
- 2 = DSI_RGB_SWAP_BGR
- 3 = DSI_RGB_SWAP_BRG
- 4 = DSI_RGB_SWAP_GRB
- 5 = DSI_RGB_SWAP_GBR
+ "rgb_swap_rgb" = DSI_RGB_SWAP_RGB (default value)
+ "rgb_swap_rbg" = DSI_RGB_SWAP_RBG
+ "rgb_swap_brg" = DSI_RGB_SWAP_BRG
+ "rgb_swap_grb" = DSI_RGB_SWAP_GRB
+ "rgb_swap_gbr" = DSI_RGB_SWAP_GBR
- qcom,mdss-dsi-lane-0-state: Boolean that specifies whether data lane 0 is enabled.
- qcom,mdss-dsi-lane-1-state: Boolean that specifies whether data lane 1 is enabled.
- qcom,mdss-dsi-lane-2-state: Boolean that specifies whether data lane 2 is enabled.
- qcom,mdss-dsi-lane-3-state: Boolean that specifies whether data lane 3 is enabled.
- qcom,mdss-dsi-lane-map: Specifies the data lane swap configuration.
- 0 = <0 1 2 3> (default value)
- 1 = <3 0 1 2>
- 2 = <2 3 0 1>
- 3 = <1 2 3 0>
- 4 = <0 3 2 1>
- 5 = <1 0 3 2>
- 6 = <2 1 0 3>
- 7 = <3 2 1 0>
+ "lane_map_0123" = <0 1 2 3> (default value)
+ "lane_map_3012" = <3 0 1 2>
+ "lane_map_2301" = <2 3 0 1>
+ "lane_map_1230" = <1 2 3 0>
+ "lane_map_0321" = <0 3 2 1>
+ "lane_map_1032" = <1 0 3 2>
+ "lane_map_2103" = <2 1 0 3>
+ "lane_map_3210" = <3 2 1 0>
- qcom,mdss-dsi-t-clk-post: Specifies the byte clock cycles after mode switch.
0x03 = default value.
- qcom,mdss-dsi-t-clk-pre: Specifies the byte clock cycles before mode switch.
@@ -214,16 +213,16 @@
0 = stream 0 (default)
1 = stream 1
- qcom,mdss-dsi-mdp-trigger: Specifies the trigger mechanism to be used for MDP path.
- 0 = no trigger
- 2 = Tear check signal line used for trigger
- 4 = Triggered by software (default)
- 6 = Software trigger and TE
+ "none" = no trigger
+ "trigger_te" = Tear check signal line used for trigger
+ "trigger_sw" = Triggered by software (default)
+ "trigger_sw_te" = Software trigger and TE
- qcom,mdss-dsi-dma-trigger: Specifies the trigger mechanism to be used for DMA path.
- 0 = no trigger
- 2 = Tear check signal line used for trigger
- 4 = Triggered by software (default)
- 5 = Software trigger and start/end of frame trigger.
- 6 = Software trigger and TE
+ "none" = no trigger
+ "trigger_te" = Tear check signal line used for trigger
+ "trigger_sw" = Triggered by software (default)
+ "trigger_sw_seof" = Software trigger and start/end of frame trigger.
+ "trigger_sw_te" = Software trigger and TE
- qcom,mdss-dsi-panel-framerate: Specifies the frame rate for the panel.
60 = 60 frames per second (default)
- qcom,mdss-dsi-panel-clockrate: Specifies the panel clock speed in Hz.
diff --git a/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
index 2963d15..17e6e94 100644
--- a/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
@@ -37,7 +37,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [05 01 00 00 78 00 01 11
@@ -52,8 +51,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <0>;
- qcom,mdss-dsi-traffic-mode = <1>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -73,8 +71,8 @@
qcom,mdss-dsi-bl-max-level = <255>;
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
qcom,mdss-dsi-bl-pmic-bank-select = <7>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
};
diff --git a/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
index 92e6fc1..88ccd08 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [
@@ -137,8 +136,8 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <1>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-lane-map = "lane_map_3012";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -148,8 +147,8 @@
qcom,mdss-dsi-t-clk-pre = <0x1b>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <255>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
diff --git a/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
index 8f94502..8c79bb9 100755
--- a/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [
@@ -115,8 +114,8 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <1>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-lane-map = "lane_map_3012";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -126,8 +125,8 @@
qcom,mdss-dsi-t-clk-pre = <0x1b>;
qcom,mdss-dsi-bl-min-level = <26>;
qcom,mdss-dsi-bl-max-level = <255>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
diff --git a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
index 83351ca..5302d8ae 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [39 01 00 00 00 00 04 b9 ff 83 94
@@ -62,8 +61,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -75,8 +73,8 @@
qcom,mdss-dsi-t-clk-pre = <0x2d>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
diff --git a/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi
index 1b64cf7..be42509 100644
--- a/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [15 01 00 00 00 00 02 55 00
@@ -51,8 +50,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <0>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -64,8 +62,8 @@
qcom,mdss-dsi-t-clk-pre = <0x1b>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
- qcom,mdss-dsi-dma-trigger = <0x04>;
- qcom,mdss-dsi-mdp-trigger = <0x0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
};
diff --git a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
index 9bb11da..8be4e34 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
@@ -38,10 +38,9 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
- qcom,mdss-dsi-pixel-packing = <0>;
+ qcom,mdss-dsi-pixel-packing = "tight";
qcom,mdss-dsi-on-command = [29 01 00 00 00 00 06 F0 55 AA 52 08 00
29 01 00 00 00 00 03 B1 68 21
23 01 00 00 00 00 02 B5 C8
@@ -252,8 +251,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -265,8 +263,8 @@
qcom,mdss-dsi-t-clk-pre = <0x2D>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <255>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
index a24cb58..d3547d8 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 FF EE
@@ -510,8 +509,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -528,8 +526,8 @@
qcom,mdss-dsi-t-clk-pre = <0x2c>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
qcom,mdss-pan-physical-width-dimension = <59>;
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index 79618b9..8d28996 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 FF EE
@@ -511,8 +510,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -524,8 +522,8 @@
qcom,mdss-dsi-t-clk-pre = <0x2c>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
qcom,mdss-pan-physical-width-dimension = <59>;
diff --git a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
index 2312b37..770bac4 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 FF EE
@@ -566,8 +565,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -579,8 +577,8 @@
qcom,mdss-dsi-t-clk-pre = <0x38>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
diff --git a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
index 393419b..8d6e703 100644
--- a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [
@@ -247,8 +246,8 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-h-sync-pulse = <0>;
- qcom,mdss-dsi-traffic-mode = <1>;
- qcom,mdss-dsi-lane-map = <1>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
+ qcom,mdss-dsi-lane-map = "lane_map_3012";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -258,8 +257,8 @@
qcom,mdss-dsi-t-clk-pre = <0x1b>;
qcom,mdss-dsi-bl-min-level = <26>;
qcom,mdss-dsi-bl-max-level = <255>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
diff --git a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
index 285d8fc..d23e3de 100644
--- a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -38,7 +38,7 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <2>;
+ qcom,mdss-dsi-color-order = "rgb_swap_bgr";
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [05 01 00 00 32 00 02 01 00
@@ -53,8 +53,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <0>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_pulse";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -64,8 +63,8 @@
qcom,mdss-dsi-t-clk-pre = <0x1c>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <4>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "trigger_sw";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
diff --git a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
index b510e6b..60bba5d 100644
--- a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
@@ -31,16 +31,17 @@
qcom,mdss-dsi-h-pulse-width = <14>;
qcom,mdss-dsi-h-sync-skew = <0>;
qcom,mdss-dsi-v-back-porch = <14>;
- qcom,mdss-dsi-v-front-porch = <11>;
+ qcom,mdss-dsi-v-front-porch = <30>;
qcom,mdss-dsi-v-pulse-width = <2>;
qcom,mdss-dsi-h-left-border = <0>;
qcom,mdss-dsi-h-right-border = <0>;
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-color-order = "rgb_swap_rgb";
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-pixel-packing = "tight";
qcom,mdss-dsi-on-command = [15 01 00 00 00 00 02 FF 01
29 01 00 00 00 00 05 C6 63 00 81 31
29 01 00 00 00 00 05 CB E7 80 73 33
@@ -81,40 +82,38 @@
29 01 00 00 00 00 05 F6 00 00 00 00
29 01 00 00 00 00 05 F7 00 00 00 00
29 01 00 00 00 00 03 E1 90 00
- 29 01 00 00 00 00 03 DE 95 CF
+ 29 01 00 00 00 00 07 DE 95 CF E2 CE 11 15
29 01 00 00 00 00 02 CF 46
29 01 00 00 00 00 03 C5 77 47
29 01 00 00 00 00 03 ED 00 20
05 01 00 00 B4 00 02 11 00
05 01 00 00 82 00 02 29 00
15 01 00 00 00 00 02 53 2c];
-
- qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 10 00
- 05 01 00 00 32 00 02 53 00
- 05 01 00 00 00 00 02 c2 00
+ qcom,mdss-dsi-off-command = [15 01 00 00 32 00 02 10 00
+ 15 01 00 00 32 00 02 53 00
+ 15 01 00 00 00 00 02 c2 00
39 01 00 00 00 00 02 cf 40
- 05 01 00 00 50 00 03 de 84 00
+ 15 01 00 00 50 00 03 de 84 00
39 01 00 00 00 00 02 cb 22
- 05 01 00 00 00 00 02 c3 00];
-
+ 15 01 00 00 00 00 02 c3 00];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-lane-0-state;
qcom,mdss-dsi-lane-1-state;
qcom,mdss-dsi-lane-2-state;
qcom,mdss-dsi-lane-3-state;
- qcom,mdss-dsi-panel-timings = [a8 1f 17 00 2f 2d 1c 21 29 03 04 00];
+ qcom,mdss-dsi-panel-timings = [68 1d 15 00 2e 2d 19 1f 24 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x20>;
qcom,mdss-dsi-t-clk-pre = <0x2f>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
- qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
index f7de416..10f53b9 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -38,7 +38,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [23 01 00 00 0a 00 02 b0 00
@@ -74,8 +73,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <0>;
- qcom,mdss-dsi-traffic-mode = <1>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -87,8 +85,8 @@
qcom,mdss-dsi-t-clk-pre = <0x1b>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
- qcom,mdss-dsi-dma-trigger = <0x04>;
- qcom,mdss-dsi-mdp-trigger = <0x0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode";
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
index d170833..168dda4 100644
--- a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
@@ -39,7 +39,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [
@@ -146,8 +145,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-h-sync-pulse = <0>;
- qcom,mdss-dsi-traffic-mode = <1>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -163,8 +161,8 @@
qcom,mdss-dsi-t-clk-pre = <0x1b>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <255>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <2>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "trigger_te";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
};
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
index 546a90f..121e54d 100644
--- a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
@@ -39,7 +39,6 @@
qcom,mdss-dsi-v-top-border = <0>;
qcom,mdss-dsi-v-bottom-border = <0>;
qcom,mdss-dsi-bpp = <24>;
- qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-on-command = [
@@ -150,8 +149,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-h-sync-pulse = <0>;
- qcom,mdss-dsi-traffic-mode = <1>;
- qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
@@ -161,8 +159,8 @@
qcom,mdss-dsi-t-clk-pre = <0x1b>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <255>;
- qcom,mdss-dsi-dma-trigger = <4>;
- qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
};
diff --git a/arch/arm/boot/dts/msm8226-v1-pm.dtsi b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
index 799381a..55b33d8 100644
--- a/arch/arm/boot/dts/msm8226-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
@@ -298,6 +298,8 @@
qcom,pc-mode = "tz_l2_int";
qcom,use-sync-timer;
qcom,pc-resets-timer;
+ qcom,cpus-as-clocks;
+ qcom,synced-clocks;
};
qcom,cpu-sleep-status@f9088008{
diff --git a/arch/arm/boot/dts/msm8226-v2-pm.dtsi b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
index 079cd0e..95dbe75 100644
--- a/arch/arm/boot/dts/msm8226-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
@@ -300,6 +300,8 @@
qcom,pc-mode = "tz_l2_int";
qcom,use-sync-timer;
qcom,pc-resets-timer;
+ qcom,cpus-as-clocks;
+ qcom,synced-clocks;
};
qcom,cpu-sleep-status@f9088008{
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index a57adcd..d74554f 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -74,10 +74,45 @@
};
&soc {
- qcom,acpuclk@f9011050 {
+ qcom,clock-a7@f9011050 {
reg = <0xf9011050 0x8>,
<0xfc4b80b0 0x8>;
- reg-names = "rcg_base", "pte_efuse";
+ reg-names = "rcg-base", "efuse";
+ qcom,speed0-bin-v2 =
+ < 0 0>,
+ < 384000000 1>,
+ < 787200000 2>,
+ <1190400000 3>;
+ qcom,speed6-bin-v2 =
+ < 0 0>,
+ < 384000000 1>,
+ < 787200000 2>,
+ <1190400000 3>;
+ qcom,speed2-bin-v2 =
+ < 0 0>,
+ < 384000000 1>,
+ < 787200000 2>,
+ <1401600000 3>;
+ qcom,speed5-bin-v2 =
+ < 0 0>,
+ < 384000000 1>,
+ < 787200000 2>,
+ <1401600000 3>;
+ qcom,speed4-bin-v2 =
+ < 0 0>,
+ < 384000000 1>,
+ < 787200000 2>,
+ <149700000 3>;
+ qcom,speed7-bin-v2 =
+ < 0 0>,
+ < 384000000 1>,
+ < 787200000 2>,
+ <1497600000 3>;
+ qcom,speed1-bin-v2 =
+ < 0 0>,
+ < 384000000 1>,
+ < 787200000 2>,
+ <1593600000 3>;
};
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index c78dacd..c86d3f3 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -1000,11 +1000,37 @@
qcom,scl-gpio = <&msmgpio 19 0>;
};
- qcom,acpuclk@f9011050 {
- compatible = "qcom,acpuclk-a7";
+ qcom,clock-a7@f9011050 {
+ compatible = "qcom,clock-a7-8226";
reg = <0xf9011050 0x8>;
- reg-names = "rcg_base";
- a7_cpu-supply = <&apc_vreg_corner>;
+ reg-names = "rcg-base";
+ clock-names = "clk-4", "clk-5";
+ qcom,speed0-bin-v0 =
+ < 0 0>,
+ < 384000000 1>,
+ < 787200000 2>,
+ <1190400000 3>;
+
+ cpu-vdd-supply = <&apc_vreg_corner>;
+ };
+
+ qcom,msm-cpufreq@0 {
+ reg = <0 4>;
+ compatible = "qcom,msm-cpufreq";
+ qcom,cpu-mem-ports = <1 512>;
+ qcom,cpufreq-table =
+ < 300000 1600 /* 200 MHz */ >,
+ < 384000 1600 /* 200 MHz */ >,
+ < 600000 3200 /* 320 MHz */ >,
+ < 787200 4264 /* 533 MHz */ >,
+ < 998400 4264 /* 533 MHz */ >,
+ < 1094400 4264 /* 533 MHz */ >,
+ < 1190400 4264 /* 533 MHz */ >,
+ < 1305600 4264 /* 533 MHz */ >,
+ < 1344000 4264 /* 533 MHz */ >,
+ < 1401600 4264 /* 533 MHz */ >,
+ < 1497600 4264 /* 533 MHz */ >,
+ < 1593600 4264 /* 533 MHz */ >;
};
qcom,ocmem@fdd00000 {
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 6ce0109..3b0f2a2 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -142,7 +142,7 @@
0x2800>;
capella,ps_close_thd_set = <0xa>;
capella,ps_away_thd_set = <0x5>;
- capella,ls_cmd = <0x44>; /* PS_IT=160ms, INT_PERS=2*/
+ capella,ls_cmd = <0x04>; /* ALS_IT=80ms, INT_PERS=2*/
capella,ps_conf1_val = <0x0006>;
capella,ps_conf3_val = <0x3010>;
};
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 0d443a6..c5f0ddd 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -374,6 +374,7 @@
CONFIG_QPNP_VIBRATOR=y
CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V0=y
+CONFIG_SENSORS=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index f467b95..303e911 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -412,6 +412,7 @@
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
+CONFIG_SENSORS=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 090f51d..4b8d443 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -434,6 +434,7 @@
select SPARSE_IRQ
select MEMORY_HOLE_CARVEOUT
select QMI_ENCDEC
+ select MSM_CORTEX_A7
config ARCH_MSM8610
bool "MSM8610"
@@ -460,6 +461,7 @@
select MSM_PM if PM
select MEMORY_HOLE_CARVEOUT
select MSM_BUS_SCALING
+ select MSM_CORTEX_A7
select CPU_FREQ_MSM
select CPU_FREQ
select MSM_PIL
@@ -500,6 +502,7 @@
select MSM_PM if PM
select MEMORY_HOLE_CARVEOUT
select MSM_BUS_SCALING
+ select MSM_CORTEX_A7
select CPU_FREQ_MSM
select CPU_FREQ
select MSM_PIL
@@ -572,6 +575,9 @@
bool
select ARM_L1_CACHE_SHIFT_6
+config MSM_CORTEX_A7
+ bool
+
config MSM_SMP
select HAVE_SMP
bool
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 4111420..4fc1590 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -23,6 +23,7 @@
endif
obj-y += acpuclock.o
+obj-$(CONFIG_MSM_CORTEX_A7) += clock-a7.o
obj-$(CONFIG_HW_PERF_EVENTS) += perf_trace_counters.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += acpuclock-krait.o clock-krait.o
ifdef CONFIG_ARCH_MSM_KRAIT
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index a883e39..53cea4e 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3163,6 +3163,8 @@
CLK_LOOKUP("xo", xo_a_clk.c, "f9011050.qcom,acpuclk"),
CLK_LOOKUP("gpll0", gpll0_ao.c, "f9011050.qcom,acpuclk"),
CLK_LOOKUP("a7sspll", a7sspll.c, "f9011050.qcom,acpuclk"),
+ CLK_LOOKUP("clk-4", gpll0_ao.c, "f9011050.qcom,clock-a7"),
+ CLK_LOOKUP("clk-5", a7sspll.c, "f9011050.qcom,clock-a7"),
CLK_LOOKUP("kpss_ahb", kpss_ahb_clk_src.c, ""),
/* WCNSS CLOCKS */
diff --git a/arch/arm/mach-msm/clock-a7.c b/arch/arm/mach-msm/clock-a7.c
new file mode 100644
index 0000000..5b8dc4e
--- /dev/null
+++ b/arch/arm/mach-msm/clock-a7.c
@@ -0,0 +1,387 @@
+/*
+ * 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+
+#include <mach/clock-generic.h>
+#include "clock-local2.h"
+
+#define UPDATE_CHECK_MAX_LOOPS 200
+
+struct cortex_reg_data {
+ u32 cmd_offset;
+ u32 update_mask;
+ u32 poll_mask;
+};
+
+#define DIV_REG(x) ((x)->base + (x)->div_offset)
+#define SRC_REG(x) ((x)->base + (x)->src_offset)
+#define CMD_REG(x) ((x)->base + \
+ ((struct cortex_reg_data *)(x)->priv)->cmd_offset)
+
+static int update_config(struct mux_div_clk *md)
+{
+ u32 regval, count;
+ struct cortex_reg_data *r = md->priv;
+
+ /* Update the configuration */
+ regval = readl_relaxed(CMD_REG(md));
+ regval |= r->update_mask;
+ writel_relaxed(regval, CMD_REG(md));
+
+ /* Wait for update to take effect */
+ for (count = UPDATE_CHECK_MAX_LOOPS; count > 0; count--) {
+ if (!(readl_relaxed(CMD_REG(md)) &
+ r->poll_mask))
+ return 0;
+ udelay(1);
+ }
+
+ CLK_WARN(&md->c, true, "didn't update its configuration.");
+
+ return -EINVAL;
+}
+
+static void cortex_get_config(struct mux_div_clk *md, u32 *src_sel, u32 *div)
+{
+ u32 regval;
+
+ regval = readl_relaxed(DIV_REG(md));
+ regval &= (md->div_mask << md->div_shift);
+ *div = regval >> md->div_shift;
+ *div = max((u32)1, (*div + 1) / 2);
+
+ regval = readl_relaxed(SRC_REG(md));
+ regval &= (md->src_mask << md->src_shift);
+ *src_sel = regval >> md->src_shift;
+}
+
+static int cortex_set_config(struct mux_div_clk *md, u32 src_sel, u32 div)
+{
+ u32 regval;
+
+ div = div ? ((2 * div) - 1) : 0;
+ regval = readl_relaxed(DIV_REG(md));
+ regval &= ~(md->div_mask << md->div_shift);
+ regval |= div << md->div_shift;
+ writel_relaxed(regval, DIV_REG(md));
+
+ regval = readl_relaxed(SRC_REG(md));
+ regval &= ~(md->src_mask << md->src_shift);
+ regval |= src_sel << md->src_shift;
+ writel_relaxed(regval, SRC_REG(md));
+
+ return update_config(md);
+}
+
+static int cortex_enable(struct mux_div_clk *md)
+{
+ u32 src_sel = parent_to_src_sel(md->parents, md->num_parents,
+ md->c.parent);
+ return cortex_set_config(md, src_sel, md->data.div);
+}
+
+static void cortex_disable(struct mux_div_clk *md)
+{
+ u32 src_sel = parent_to_src_sel(md->parents, md->num_parents,
+ md->safe_parent);
+ cortex_set_config(md, src_sel, md->safe_div);
+}
+
+static bool cortex_is_enabled(struct mux_div_clk *md)
+{
+ return true;
+}
+
+struct mux_div_ops cortex_mux_div_ops = {
+ .set_src_div = cortex_set_config,
+ .get_src_div = cortex_get_config,
+ .is_enabled = cortex_is_enabled,
+ .enable = cortex_enable,
+ .disable = cortex_disable,
+};
+
+static struct cortex_reg_data a7ssmux_priv = {
+ .cmd_offset = 0x0,
+ .update_mask = BIT(0),
+ .poll_mask = BIT(0),
+};
+
+DEFINE_VDD_REGS_INIT(vdd_cpu, 1);
+
+static struct mux_div_clk a7ssmux = {
+ .ops = &cortex_mux_div_ops,
+ .safe_freq = 300000000,
+ .data = {
+ .max_div = 8,
+ .min_div = 1,
+ },
+ .c = {
+ .dbg_name = "a7ssmux",
+ .ops = &clk_ops_mux_div_clk,
+ .vdd_class = &vdd_cpu,
+ CLK_INIT(a7ssmux.c),
+ },
+ .parents = (struct clk_src[8]) {},
+ .priv = &a7ssmux_priv,
+ .div_offset = 0x4,
+ .div_mask = BM(4, 0),
+ .div_shift = 0,
+ .src_offset = 0x4,
+ .src_mask = BM(10, 8) >> 8,
+ .src_shift = 8,
+};
+
+static struct clk_lookup clock_tbl_a7[] = {
+ CLK_LOOKUP("cpu0_clk", a7ssmux.c, "0.qcom,msm-cpufreq"),
+ CLK_LOOKUP("cpu0_clk", a7ssmux.c, "fe805664.qcom,pm-8x60"),
+};
+
+static int of_get_fmax_vdd_class(struct platform_device *pdev, struct clk *c,
+ char *prop_name)
+{
+ struct device_node *of = pdev->dev.of_node;
+ int prop_len, i;
+ struct clk_vdd_class *vdd = c->vdd_class;
+ u32 *array;
+
+ if (!of_find_property(of, prop_name, &prop_len)) {
+ dev_err(&pdev->dev, "missing %s\n", prop_name);
+ return -EINVAL;
+ }
+
+ prop_len /= sizeof(u32);
+ if (prop_len % 2) {
+ dev_err(&pdev->dev, "bad length %d\n", prop_len);
+ return -EINVAL;
+ }
+
+ prop_len /= 2;
+ vdd->level_votes = devm_kzalloc(&pdev->dev, prop_len * sizeof(int),
+ GFP_KERNEL);
+ if (!vdd->level_votes)
+ return -ENOMEM;
+
+ vdd->vdd_uv = devm_kzalloc(&pdev->dev, prop_len * sizeof(int),
+ GFP_KERNEL);
+ if (!vdd->vdd_uv)
+ return -ENOMEM;
+
+ c->fmax = devm_kzalloc(&pdev->dev, prop_len * sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!c->fmax)
+ return -ENOMEM;
+
+ array = devm_kzalloc(&pdev->dev, prop_len * sizeof(u32), GFP_KERNEL);
+ if (!array)
+ return -ENOMEM;
+
+ of_property_read_u32_array(of, prop_name, array, prop_len * 2);
+ for (i = 0; i < prop_len; i++) {
+ c->fmax[i] = array[2 * i];
+ vdd->vdd_uv[i] = array[2 * i + 1];
+ }
+
+ devm_kfree(&pdev->dev, array);
+ vdd->num_levels = prop_len;
+ vdd->cur_level = prop_len;
+ c->num_fmax = prop_len;
+ return 0;
+}
+
+static void get_speed_bin(struct platform_device *pdev, int *bin, int *version)
+{
+ struct resource *res;
+ void __iomem *base;
+ u32 pte_efuse, redundant_sel, valid;
+
+ *bin = 0;
+ *version = 0;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse");
+ if (!res) {
+ dev_info(&pdev->dev,
+ "No speed/PVS binning available. Defaulting to 0!\n");
+ return;
+ }
+
+ base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!base) {
+ dev_warn(&pdev->dev,
+ "Unable to read efuse data. Defaulting to 0!\n");
+ return;
+ }
+
+ pte_efuse = readl_relaxed(base);
+ devm_iounmap(&pdev->dev, base);
+
+ redundant_sel = (pte_efuse >> 24) & 0x7;
+ *bin = pte_efuse & 0x7;
+ valid = (pte_efuse >> 3) & 0x1;
+ *version = (pte_efuse >> 4) & 0x3;
+
+ if (redundant_sel == 1)
+ *bin = (pte_efuse >> 27) & 0x7;
+
+ if (!valid) {
+ dev_info(&pdev->dev, "Speed bin not set. Defaulting to 0!\n");
+ *bin = 0;
+ } else {
+ dev_info(&pdev->dev, "Speed bin: %d\n", *bin);
+ }
+
+ dev_info(&pdev->dev, "PVS version: %d\n", *version);
+
+ return;
+}
+
+static int of_get_clk_src(struct platform_device *pdev, struct clk_src *parents)
+{
+ struct device_node *of = pdev->dev.of_node;
+ int num_parents, i, j, index;
+ struct clk *c;
+ char clk_name[] = "clk-x";
+
+ num_parents = of_property_count_strings(of, "clock-names");
+ if (num_parents <= 0 || num_parents > 8) {
+ dev_err(&pdev->dev, "missing clock-names\n");
+ return -EINVAL;
+ }
+
+ j = 0;
+ for (i = 0; i < 8; i++) {
+ snprintf(clk_name, ARRAY_SIZE(clk_name), "clk-%d", i);
+ index = of_property_match_string(of, "clock-names", clk_name);
+ if (IS_ERR_VALUE(index))
+ continue;
+
+ parents[j].sel = i;
+ parents[j].src = c = devm_clk_get(&pdev->dev, clk_name);
+ if (IS_ERR(c)) {
+ if (c != ERR_PTR(-EPROBE_DEFER))
+ dev_err(&pdev->dev, "clk_get: %s\n fail",
+ clk_name);
+ return PTR_ERR(c);
+ }
+ j++;
+ }
+
+ return num_parents;
+}
+
+static int clock_a7_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int speed_bin = 0, version = 0, rc;
+ unsigned long rate, aux_rate;
+ struct clk *aux_clk, *main_pll;
+ char prop_name[] = "qcom,speedX-bin-vX";
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg-base");
+ if (!res) {
+ dev_err(&pdev->dev, "missing rcg-base\n");
+ return -EINVAL;
+ }
+ a7ssmux.base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!a7ssmux.base) {
+ dev_err(&pdev->dev, "ioremap failed for rcg-base\n");
+ return -ENOMEM;
+ }
+
+ vdd_cpu.regulator[0] = devm_regulator_get(&pdev->dev, "cpu-vdd");
+ if (IS_ERR(vdd_cpu.regulator[0])) {
+ if (PTR_ERR(vdd_cpu.regulator[0]) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "unable to get regulator\n");
+ return PTR_ERR(vdd_cpu.regulator[0]);
+ }
+
+ a7ssmux.num_parents = of_get_clk_src(pdev, a7ssmux.parents);
+ if (IS_ERR_VALUE(a7ssmux.num_parents))
+ return a7ssmux.num_parents;
+
+ get_speed_bin(pdev, &speed_bin, &version);
+
+ snprintf(prop_name, ARRAY_SIZE(prop_name),
+ "qcom,speed%d-bin-v%d", speed_bin, version);
+ rc = of_get_fmax_vdd_class(pdev, &a7ssmux.c, prop_name);
+ if (rc) {
+ /* Fall back to most conservative PVS table */
+ dev_err(&pdev->dev, "Unable to load voltage plan %s!\n",
+ prop_name);
+ rc = of_get_fmax_vdd_class(pdev, &a7ssmux.c,
+ "qcom,speed0-bin-v0");
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Unable to load safe voltage plan\n");
+ return rc;
+ }
+ dev_info(&pdev->dev, "Safe voltage plan loaded.\n");
+ }
+
+ rc = msm_clock_register(clock_tbl_a7, ARRAY_SIZE(clock_tbl_a7));
+ if (rc) {
+ dev_err(&pdev->dev, "msm_clock_register failed\n");
+ return rc;
+ }
+
+ /* Force a PLL reconfiguration */
+ aux_clk = a7ssmux.parents[0].src;
+ main_pll = a7ssmux.parents[1].src;
+
+ aux_rate = clk_get_rate(aux_clk);
+ rate = clk_get_rate(&a7ssmux.c);
+ clk_set_rate(&a7ssmux.c, aux_rate);
+ clk_set_rate(main_pll, clk_round_rate(main_pll, 1));
+ clk_set_rate(&a7ssmux.c, rate);
+
+ /*
+ * We don't want the CPU clocks to be turned off at late init
+ * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
+ * refcount of these clocks. Any cpufreq/hotplug manager can assume
+ * that the clocks have already been prepared and enabled by the time
+ * they take over.
+ */
+ WARN(clk_prepare_enable(&a7ssmux.c),
+ "Unable to turn on CPU clock");
+ return 0;
+}
+
+static struct of_device_id clock_a7_match_table[] = {
+ {.compatible = "qcom,clock-a7-8226"},
+ {}
+};
+
+static struct platform_driver clock_a7_driver = {
+ .driver = {
+ .name = "clock-a7",
+ .of_match_table = clock_a7_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init clock_a7_init(void)
+{
+ return platform_driver_probe(&clock_a7_driver, clock_a7_probe);
+}
+device_initcall(clock_a7_init);
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 35917c3..c3b7229 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -23,6 +23,7 @@
#include <linux/clkdev.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>
+#include <linux/io.h>
#include <mach/clk-provider.h>
@@ -412,6 +413,56 @@
.write = clock_parent_write,
};
+void clk_debug_print_hw(struct clk *clk, struct seq_file *f)
+{
+ void __iomem *base;
+ struct clk_register_data *regs;
+ u32 i, j, size;
+
+ if (IS_ERR_OR_NULL(clk))
+ return;
+
+ clk_debug_print_hw(clk->parent, f);
+
+ clock_debug_output(f, false, "%s\n", clk->dbg_name);
+
+ if (!clk->ops->list_registers)
+ return;
+
+ j = 0;
+ base = clk->ops->list_registers(clk, j, ®s, &size);
+ while (!IS_ERR(base)) {
+ for (i = 0; i < size; i++) {
+ u32 val = readl_relaxed(base + regs[i].offset);
+ clock_debug_output(f, false, "%20s: 0x%.8x\n",
+ regs[i].name, val);
+ }
+ j++;
+ base = clk->ops->list_registers(clk, j, ®s, &size);
+ }
+}
+
+static int print_hw_show(struct seq_file *m, void *unused)
+{
+ struct clk *c = m->private;
+ clk_debug_print_hw(c, m);
+
+ return 0;
+}
+
+static int print_hw_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, print_hw_show, inode->i_private);
+}
+
+static const struct file_operations clock_print_hw_fops = {
+ .open = print_hw_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+
static int clock_debug_add(struct clk *clock)
{
char temp[50], *ptr;
@@ -463,6 +514,10 @@
&clock_parent_fops))
goto error;
+ if (!debugfs_create_file("print", S_IRUGO, clk_dir, clock,
+ &clock_print_hw_fops))
+ goto error;
+
return 0;
error:
debugfs_remove_recursive(clk_dir);
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index a251784..c08df46 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -304,6 +304,22 @@
return HANDOFF_ENABLED_CLK;
}
+static long local_pll_clk_round_rate(struct clk *c, unsigned long rate)
+{
+ struct pll_freq_tbl *nf;
+ struct pll_clk *pll = to_pll_clk(c);
+
+ if (!pll->freq_tbl)
+ return -EINVAL;
+
+ for (nf = pll->freq_tbl; nf->freq_hz != PLL_FREQ_END; nf++)
+ if (nf->freq_hz >= rate)
+ return nf->freq_hz;
+
+ nf--;
+ return nf->freq_hz;
+}
+
static int local_pll_clk_set_rate(struct clk *c, unsigned long rate)
{
struct pll_freq_tbl *nf;
@@ -426,6 +442,7 @@
.enable = sr2_pll_clk_enable,
.disable = local_pll_clk_disable,
.set_rate = local_pll_clk_set_rate,
+ .round_rate = local_pll_clk_round_rate,
.handoff = local_pll_clk_handoff,
};
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 027606e..4529a81 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -23,6 +23,7 @@
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
+#include <linux/seq_file.h>
#include <mach/clk.h>
/*
@@ -41,6 +42,21 @@
#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */
#define DELAY 5 /* No bit to check, just delay */
+struct clk_register_data {
+ char *name;
+ u32 offset;
+};
+#ifdef CONFIG_DEBUG_FS
+void clk_debug_print_hw(struct clk *clk, struct seq_file *f);
+#else
+static inline void clk_debug_print_hw(struct clk *clk, struct seq_file *f) {}
+#endif
+
+#define CLK_WARN(clk, cond, fmt, ...) do { \
+ clk_debug_print_hw(clk, NULL); \
+ WARN(cond, "%s: " fmt, (clk)->dbg_name, ##__VA_ARGS__); \
+} while (0)
+
/**
* struct clk_vdd_class - Voltage scaling class
* @class_name: name of the class
@@ -129,6 +145,8 @@
int (*set_parent)(struct clk *clk, struct clk *parent);
struct clk *(*get_parent)(struct clk *clk);
bool (*is_local)(struct clk *clk);
+ void __iomem *(*list_registers)(struct clk *clk, int n,
+ struct clk_register_data **regs, u32 *size);
};
/**
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index bdda546..5aa6c93 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -589,17 +589,24 @@
};
static const struct proto_ops msm_ipc_proto_ops = {
- .owner = THIS_MODULE,
.family = AF_MSM_IPC,
+ .owner = THIS_MODULE,
+ .release = msm_ipc_router_close,
.bind = msm_ipc_router_bind,
.connect = sock_no_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .getname = sock_no_getname,
+ .poll = msm_ipc_router_poll,
+ .ioctl = msm_ipc_router_ioctl,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
.sendmsg = msm_ipc_router_sendmsg,
.recvmsg = msm_ipc_router_recvmsg,
- .ioctl = msm_ipc_router_ioctl,
- .poll = msm_ipc_router_poll,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .release = msm_ipc_router_close,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
};
static struct proto msm_ipc_proto = {
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index f879d78..f5d8441 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/sensors.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -79,6 +80,21 @@
* The following table lists the maximum appropriate poll interval for each
* available output data rate.
*/
+
+static struct sensors_classdev sensors_cdev = {
+ .name = "kxtj9-accel",
+ .vendor = "Kionix",
+ .version = 1,
+ .handle = 0,
+ .type = 1,
+ .max_range = "19.6",
+ .resolution = "0.01",
+ .sensor_power = "0.2",
+ .min_delay = 2000,
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+};
+
static const struct {
unsigned int cutoff;
u8 mask;
@@ -415,19 +431,16 @@
}
}
- tj9->enable = true;
return 0;
fail:
kxtj9_device_power_off(tj9);
- tj9->enable = false;
return err;
}
static void kxtj9_disable(struct kxtj9_data *tj9)
{
kxtj9_device_power_off(tj9);
- tj9->enable = false;
}
@@ -496,18 +509,21 @@
if (error)
return error;
mutex_lock(&input_dev->mutex);
- disable_irq(client->irq);
- if (data == 0)
+ if (data == 0) {
+ disable_irq(client->irq);
kxtj9_disable(tj9);
- else if (data == 1)
- kxtj9_enable(tj9);
- else {
+ tj9->enable = false;
+ } else if (data == 1) {
+ if (!kxtj9_enable(tj9)) {
+ enable_irq(client->irq);
+ tj9->enable = true;
+ }
+ } else {
dev_err(&tj9->client->dev,
"Invalid value of input, input=%ld\n", data);
}
- enable_irq(client->irq);
mutex_unlock(&input_dev->mutex);
return count;
@@ -555,7 +571,8 @@
/* Lock the device to prevent races with open/close (and itself) */
mutex_lock(&input_dev->mutex);
- disable_irq(client->irq);
+ if (tj9->enable)
+ disable_irq(client->irq);
/*
* Set current interval to the greater of the minimum interval or
@@ -563,9 +580,10 @@
*/
tj9->last_poll_interval = max(interval, tj9->pdata.min_interval);
- kxtj9_update_odr(tj9, tj9->last_poll_interval);
-
- enable_irq(client->irq);
+ if (tj9->enable) {
+ kxtj9_update_odr(tj9, tj9->last_poll_interval);
+ enable_irq(client->irq);
+ }
mutex_unlock(&input_dev->mutex);
return count;
@@ -840,6 +858,12 @@
tj9->ctrl_reg1 = tj9->pdata.res_ctl | tj9->pdata.g_range;
tj9->last_poll_interval = tj9->pdata.init_interval;
+ err = sensors_classdev_register(&client->dev, &sensors_cdev);
+ if (err) {
+ dev_err(&client->dev, "class device create failed: %d\n", err);
+ goto err_power_off;
+ }
+
if (client->irq) {
/* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL;
@@ -857,6 +881,8 @@
goto err_destroy_input;
}
+ disable_irq(tj9->client->irq);
+
err = sysfs_create_group(&client->dev.kobj, &kxtj9_attribute_group);
if (err) {
dev_err(&client->dev, "sysfs create failed: %d\n", err);
@@ -923,7 +949,7 @@
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_dev->users && tj9->enable)
kxtj9_disable(tj9);
mutex_unlock(&input_dev->mutex);
@@ -939,7 +965,7 @@
mutex_lock(&input_dev->mutex);
- if (input_dev->users)
+ if (input_dev->users && tj9->enable)
kxtj9_enable(tj9);
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index d6fa2b0..8f080ce 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -28,6 +28,19 @@
#include "msm_jpeg_common.h"
#include "msm_jpeg_hw.h"
+int msm_jpeg_platform_set_clk_rate(struct msm_jpeg_device *pgmn_dev,
+ long clk_rate)
+{
+ struct msm_cam_clk_info jpeg_core_clk_info[] = {
+ {"core_clk", JPEG_CLK_RATE, 0}
+ };
+
+ jpeg_core_clk_info[0].clk_rate = clk_rate;
+
+ return msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_core_clk_info,
+ pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_core_clk_info), 1);
+}
+
void msm_jpeg_platform_p2v(struct msm_jpeg_device *pgmn_dev, struct file *file,
struct ion_handle **ionhandle, int domain_num)
{
@@ -135,8 +148,8 @@
{
.src = MSM_BUS_MASTER_JPEG,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = JPEG_CLK_RATE * 2.5,
- .ib = JPEG_CLK_RATE * 2.5,
+ .ab = JPEG_MAX_CLK_RATE * 2.5,
+ .ib = JPEG_MAX_CLK_RATE * 2.5,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
index a14b8ee..7be9e19 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
@@ -20,7 +20,10 @@
#include <mach/iommu.h>
#include "msm_jpeg_sync.h"
#define JPEG_CLK_RATE 266670000
+#define JPEG_MAX_CLK_RATE 320000000
+int msm_jpeg_platform_set_clk_rate(struct msm_jpeg_device *pgmn_dev,
+ long clk_rate);
void msm_jpeg_platform_p2v(struct msm_jpeg_device *pgmn_dev, struct file *file,
struct ion_handle **ionhandle, int domain_num);
uint32_t msm_jpeg_platform_v2p(struct msm_jpeg_device *pgmn_dev, int fd,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
index 80ff9e5..f7241dd 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
@@ -804,6 +804,36 @@
return 0;
}
+int msm_jpeg_ioctl_set_clk_rate(struct msm_jpeg_device *pgmn_dev,
+ unsigned long arg)
+{
+ long clk_rate;
+ int rc;
+
+ if ((pgmn_dev->state != MSM_JPEG_INIT) &&
+ (pgmn_dev->state != MSM_JPEG_RESET)) {
+ JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ if (get_user(clk_rate, (long __user *)arg)) {
+ JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ JPEG_DBG("%s:%d] Requested clk rate %ld\n", __func__, __LINE__,
+ clk_rate);
+ if (clk_rate < 0) {
+ JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ rc = msm_jpeg_platform_set_clk_rate(pgmn_dev, clk_rate);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
long __msm_jpeg_ioctl(struct msm_jpeg_device *pgmn_dev,
unsigned int cmd, unsigned long arg)
{
@@ -873,6 +903,9 @@
rc = msm_jpeg_ioctl_test_dump_region(pgmn_dev, arg);
break;
+ case MSM_JPEG_IOCTL_SET_CLK_RATE:
+ rc = msm_jpeg_ioctl_set_clk_rate(pgmn_dev, arg);
+ break;
default:
JPEG_PR_ERR(KERN_INFO "%s:%d] cmd = %d not supported\n",
__func__, __LINE__, _IOC_NR(cmd));
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 0083378..03145c8 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -1797,6 +1797,8 @@
(struct msm_sensor_ctrl_t *)data;
struct msm_camera_cci_client *cci_client = NULL;
uint32_t session_id;
+ unsigned long mount_pos;
+
s_ctrl->pdev = pdev;
s_ctrl->dev = &pdev->dev;
CDBG("%s called data %p\n", __func__, data);
@@ -1862,6 +1864,11 @@
s_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_SENSOR;
s_ctrl->msm_sd.sd.entity.name =
s_ctrl->msm_sd.sd.name;
+ mount_pos = s_ctrl->sensordata->sensor_init_params->position;
+ mount_pos = mount_pos << 8;
+ mount_pos = mount_pos |
+ (s_ctrl->sensordata->sensor_init_params->sensor_mount_angle / 90);
+ s_ctrl->msm_sd.sd.entity.flags = mount_pos;
rc = camera_init_v4l2(&s_ctrl->pdev->dev, &session_id);
CDBG("%s rc %d session_id %d\n", __func__, rc, session_id);
@@ -1880,6 +1887,8 @@
{
int rc = 0;
uint32_t session_id;
+ unsigned long mount_pos;
+
CDBG("%s %s_i2c_probe called\n", __func__, client->name);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
pr_err("%s %s i2c_check_functionality failed\n",
@@ -1976,6 +1985,12 @@
s_ctrl->msm_sd.sd.entity.name =
s_ctrl->msm_sd.sd.name;
+ mount_pos = s_ctrl->sensordata->sensor_init_params->position;
+ mount_pos = mount_pos << 8;
+ mount_pos = mount_pos |
+ (s_ctrl->sensordata->sensor_init_params->sensor_mount_angle / 90);
+ s_ctrl->msm_sd.sd.entity.flags = mount_pos;
+
rc = camera_init_v4l2(&s_ctrl->sensor_i2c_client->client->dev,
&session_id);
CDBG("%s rc %d session_id %d\n", __func__, rc, session_id);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index c63af6c..e127dc1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -765,6 +765,7 @@
mutex_lock(&core->lock);
core->state = VIDC_CORE_INVALID;
mutex_unlock(&core->lock);
+ mutex_lock(&core->sync_lock);
list_for_each_entry(inst, &core->instances,
list) {
mutex_lock(&inst->lock);
@@ -786,6 +787,7 @@
msm_vidc_queue_v4l2_event(inst,
V4L2_EVENT_MSM_VIDC_SYS_ERROR);
}
+ mutex_unlock(&core->sync_lock);
} else {
dprintk(VIDC_ERR,
"Got SYS_ERR but unable to identify core");
@@ -813,6 +815,7 @@
mutex_lock(&core->lock);
core->state = VIDC_CORE_INVALID;
mutex_unlock(&core->lock);
+ mutex_lock(&core->sync_lock);
list_for_each_entry(inst, &core->instances, list) {
if (inst) {
msm_vidc_queue_v4l2_event(inst,
@@ -834,6 +837,7 @@
mutex_unlock(&inst->lock);
}
}
+ mutex_unlock(&core->sync_lock);
}
static void handle_session_close(enum command_response cmd, void *data)
@@ -3161,10 +3165,12 @@
int num_mbs_per_sec = 0;
if (inst->state == MSM_VIDC_OPEN_DONE) {
+ mutex_lock(&inst->core->sync_lock);
num_mbs_per_sec = msm_comm_get_load(inst->core,
MSM_VIDC_DECODER);
num_mbs_per_sec += msm_comm_get_load(inst->core,
MSM_VIDC_ENCODER);
+ mutex_unlock(&inst->core->sync_lock);
if (num_mbs_per_sec > inst->core->resources.max_load) {
dprintk(VIDC_ERR,
"H/w is overloaded. needed: %d max: %d\n",
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index ce69e6d..071fffc 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -500,6 +500,11 @@
}
spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
flags);
+
+ if (ptr_svc == NULL) {
+ pr_err("Listener Svc %d does not exist\n", lstnr);
+ return -EINVAL;
+ }
if (ptr_svc->svc.listener_id != lstnr) {
pr_warning("Service requested for does on exist\n");
return -ERESTARTSYS;
@@ -861,14 +866,37 @@
struct qseecom_client_send_service_ireq *send_svc_ireq_ptr)
{
int ret = 0;
+ void *req_buf = NULL;
+
if ((req_ptr == NULL) || (send_svc_ireq_ptr == NULL)) {
pr_err("Error with pointer: req_ptr = %p, send_svc_ptr = %p\n",
req_ptr, send_svc_ireq_ptr);
return -EINVAL;
}
+
+ if (((uint32_t)req_ptr->cmd_req_buf <
+ data_ptr->client.user_virt_sb_base)
+ || ((uint32_t)req_ptr->cmd_req_buf >=
+ (data_ptr->client.user_virt_sb_base +
+ data_ptr->client.sb_length))) {
+ pr_err("cmd buffer address not within shared bufffer\n");
+ return -EINVAL;
+ }
+
+
+ if (((uint32_t)req_ptr->resp_buf < data_ptr->client.user_virt_sb_base)
+ || ((uint32_t)req_ptr->resp_buf >=
+ (data_ptr->client.user_virt_sb_base +
+ data_ptr->client.sb_length))){
+ pr_err("response buffer address not within shared bufffer\n");
+ return -EINVAL;
+ }
+
+ req_buf = data_ptr->client.sb_virt;
+
send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id;
send_svc_ireq_ptr->key_type =
- ((struct qseecom_rpmb_provision_key *)req_ptr->cmd_req_buf)->key_type;
+ ((struct qseecom_rpmb_provision_key *)req_buf)->key_type;
send_svc_ireq_ptr->req_len = req_ptr->cmd_req_len;
send_svc_ireq_ptr->rsp_ptr = (void *)(__qseecom_uvirt_to_kphys(data_ptr,
(uint32_t)req_ptr->resp_buf));
@@ -1069,8 +1097,6 @@
if (ret)
return ret;
- pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
- req.resp_len, req.resp_buf);
return ret;
}
@@ -1260,8 +1286,7 @@
ret = __qseecom_update_cmd_buf(&req, true, data, false);
if (ret)
return ret;
- pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
- req.resp_len, req.resp_buf);
+
return ret;
}
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index c6f6f03..e9bb553 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -37,6 +37,7 @@
#include <linux/regulator/consumer.h>
#define MAX_RAILS 5
+#define MAX_THRESHOLD 2
static struct msm_thermal_data msm_thermal_info;
static uint32_t limited_max_freq = UINT_MAX;
@@ -69,6 +70,7 @@
static bool psm_enabled;
static bool psm_nodes_called;
static bool psm_probed;
+static bool hotplug_enabled;
static int *tsens_id_map;
static DEFINE_MUTEX(vdd_rstr_mutex);
static DEFINE_MUTEX(psm_mutex);
@@ -77,8 +79,10 @@
uint32_t cpu;
bool offline;
bool user_offline;
+ bool thresh_cleared;
const char *sensor_type;
- struct sensor_threshold thresh[2];
+ uint32_t sensor_id;
+ struct sensor_threshold thresh[MAX_THRESHOLD];
};
struct rail {
@@ -624,6 +628,76 @@
return ret;
}
+static int set_and_activate_threshold(uint32_t sensor_id,
+ struct sensor_threshold *threshold)
+{
+ int ret = 0;
+
+ ret = sensor_set_trip(sensor_id, threshold);
+ if (ret != 0) {
+ pr_err("%s: Error in setting trip %d\n",
+ KBUILD_MODNAME, threshold->trip);
+ goto set_done;
+ }
+
+ ret = sensor_activate_trip(sensor_id, threshold, true);
+ if (ret != 0) {
+ pr_err("%s: Error in enabling trip %d\n",
+ KBUILD_MODNAME, threshold->trip);
+ goto set_done;
+ }
+
+set_done:
+ return ret;
+}
+
+static int set_threshold(uint32_t sensor_id,
+ struct sensor_threshold *threshold)
+{
+ struct tsens_device tsens_dev;
+ int i = 0, ret = 0;
+ long temp;
+
+ if ((!threshold) || check_sensor_id(sensor_id)) {
+ pr_err("%s: Invalid input\n", KBUILD_MODNAME);
+ ret = -EINVAL;
+ goto set_threshold_exit;
+ }
+
+ tsens_dev.sensor_num = sensor_id;
+ ret = tsens_get_temp(&tsens_dev, &temp);
+ if (ret) {
+ pr_err("%s: Unable to read TSENS sensor %d\n",
+ KBUILD_MODNAME, tsens_dev.sensor_num);
+ goto set_threshold_exit;
+ }
+ while (i < MAX_THRESHOLD) {
+ switch (threshold[i].trip) {
+ case THERMAL_TRIP_CONFIGURABLE_HI:
+ if (threshold[i].temp >= temp) {
+ ret = set_and_activate_threshold(sensor_id,
+ &threshold[i]);
+ if (ret)
+ goto set_threshold_exit;
+ }
+ break;
+ case THERMAL_TRIP_CONFIGURABLE_LOW:
+ if (threshold[i].temp <= temp) {
+ ret = set_and_activate_threshold(sensor_id,
+ &threshold[i]);
+ if (ret)
+ goto set_threshold_exit;
+ }
+ break;
+ default:
+ break;
+ }
+ i++;
+ }
+set_threshold_exit:
+ return ret;
+}
+
#ifdef CONFIG_SMP
static void __ref do_core_control(long temp)
{
@@ -677,7 +751,7 @@
/* Call with core_control_mutex locked */
static int __ref update_offline_cores(int val)
{
- int cpu = 0;
+ uint32_t cpu = 0;
int ret = 0;
if (!core_control_enabled)
@@ -701,8 +775,7 @@
static __ref int do_hotplug(void *data)
{
int ret = 0;
- int cpu = 0;
- uint32_t mask = 0;
+ uint32_t cpu = 0, mask = 0;
if (!core_control_enabled)
return -EINVAL;
@@ -714,6 +787,12 @@
mutex_lock(&core_control_mutex);
for_each_possible_cpu(cpu) {
+ if (hotplug_enabled &&
+ cpus[cpu].thresh_cleared) {
+ set_threshold(cpus[cpu].sensor_id,
+ cpus[cpu].thresh);
+ cpus[cpu].thresh_cleared = false;
+ }
if (cpus[cpu].offline || cpus[cpu].user_offline)
mask |= BIT(cpu);
}
@@ -984,10 +1063,12 @@
default:
break;
}
- if (hotplug_task)
+ if (hotplug_task) {
+ cpu_node->thresh_cleared = true;
complete(&hotplug_notify_complete);
- else
+ } else {
pr_err("%s: Hotplug task is not initialized\n", KBUILD_MODNAME);
+ }
return 0;
}
/* Adjust cpus offlined bit based on temperature reading. */
@@ -997,15 +1078,18 @@
long temp = 0;
int cpu = 0;
+ if (!hotplug_enabled)
+ return 0;
+
mutex_lock(&core_control_mutex);
for_each_possible_cpu(cpu) {
if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
continue;
- tsens_dev.sensor_num = sensor_get_id(\
- (char *)cpus[cpu].sensor_type);
+ tsens_dev.sensor_num = cpus[cpu].sensor_id;
if (tsens_get_temp(&tsens_dev, &temp)) {
pr_err("%s: Unable to read TSENS sensor %d\n",
KBUILD_MODNAME, tsens_dev.sensor_num);
+ mutex_unlock(&core_control_mutex);
return -EINVAL;
}
@@ -1034,26 +1118,29 @@
if (hotplug_task)
return;
+ if (!hotplug_enabled)
+ goto init_kthread;
+
for_each_possible_cpu(cpu) {
+ cpus[cpu].cpu = (uint32_t)cpu;
+ cpus[cpu].thresh_cleared = false;
+ cpus[cpu].sensor_id =
+ sensor_get_id((char *)cpus[cpu].sensor_type);
if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
continue;
- cpus[cpu].cpu = (uint32_t)cpu;
cpus[cpu].thresh[0].temp = msm_thermal_info.hotplug_temp_degC;
cpus[cpu].thresh[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
cpus[cpu].thresh[0].notify = hotplug_notify;
cpus[cpu].thresh[0].data = (void *)&cpus[cpu];
- sensor_set_trip(sensor_get_id((char *)cpus[cpu].sensor_type),
- &cpus[cpu].thresh[0]);
cpus[cpu].thresh[1].temp = msm_thermal_info.hotplug_temp_degC -
msm_thermal_info.hotplug_temp_hysteresis_degC;
cpus[cpu].thresh[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
cpus[cpu].thresh[1].notify = hotplug_notify;
cpus[cpu].thresh[1].data = (void *)&cpus[cpu];
- sensor_set_trip(sensor_get_id((char *)cpus[cpu].sensor_type),
- &cpus[cpu].thresh[1]);
-
+ set_threshold(cpus[cpu].sensor_id, cpus[cpu].thresh);
}
+init_kthread:
init_completion(&hotplug_notify_complete);
hotplug_task = kthread_run(do_hotplug, NULL, "msm_thermal:hotplug");
if (IS_ERR(hotplug_task)) {
@@ -1771,6 +1858,11 @@
int ret = 0;
int cpu = 0;
+ if (num_possible_cpus() > 1) {
+ core_control_enabled = 1;
+ hotplug_enabled = 1;
+ }
+
key = "qcom,core-limit-temp";
ret = of_property_read_u32(node, key, &data->core_limit_temp_degC);
if (ret)
@@ -1789,19 +1881,20 @@
key = "qcom,hotplug-temp";
ret = of_property_read_u32(node, key, &data->hotplug_temp_degC);
if (ret)
- goto read_node_fail;
+ goto hotplug_node_fail;
key = "qcom,hotplug-temp-hysteresis";
ret = of_property_read_u32(node, key,
&data->hotplug_temp_hysteresis_degC);
if (ret)
- goto read_node_fail;
+ goto hotplug_node_fail;
key = "qcom,cpu-sensors";
cpu_cnt = of_property_count_strings(node, key);
if (cpu_cnt != num_possible_cpus()) {
pr_err("%s: Wrong number of cpu\n", KBUILD_MODNAME);
- goto read_node_fail;
+ ret = -EINVAL;
+ goto hotplug_node_fail;
}
for_each_possible_cpu(cpu) {
@@ -1811,12 +1904,9 @@
ret = of_property_read_string_index(node, key, cpu,
&cpus[cpu].sensor_type);
if (ret)
- goto read_node_fail;
+ goto hotplug_node_fail;
}
- if (num_possible_cpus() > 1)
- core_control_enabled = 1;
-
read_node_fail:
if (ret) {
dev_info(&pdev->dev,
@@ -1826,6 +1916,16 @@
}
return ret;
+
+hotplug_node_fail:
+ if (ret) {
+ dev_info(&pdev->dev,
+ "%s:Failed reading node=%s, key=%s. KTM continues\n",
+ KBUILD_MODNAME, node->full_name, key);
+ hotplug_enabled = 0;
+ }
+
+ return ret;
}
static int __devinit msm_thermal_dev_probe(struct platform_device *pdev)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 8d9da6b..739696d 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -89,30 +89,21 @@
}
EXPORT_SYMBOL(sensor_get_id);
-static long get_min(struct sensor_info *sensor, long temp)
+static int __update_sensor_thresholds(struct sensor_info *sensor)
{
- long min = LONG_MIN;
- struct sensor_threshold *pos, *var;
-
- list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
- if (pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW)
- if (pos->temp < temp && pos->temp > min)
- min = pos->temp;
- }
-
- return min;
-}
-
-static void __update_sensor_thresholds(struct sensor_info *sensor)
-{
- long min = LONG_MIN;
- long max = LONG_MAX;
- long max_of_min = LONG_MIN;
- long min_of_max = LONG_MAX;
+ long max_of_low_thresh = LONG_MIN;
+ long min_of_high_thresh = LONG_MAX;
struct sensor_threshold *pos, *var;
enum thermal_trip_type type;
- int i;
- long curr_temp;
+ int i, ret = 0;
+
+ if (!sensor->tz->ops->set_trip_temp ||
+ !sensor->tz->ops->activate_trip_type ||
+ !sensor->tz->ops->get_trip_type ||
+ !sensor->tz->ops->get_trip_temp) {
+ ret = -ENODEV;
+ goto update_done;
+ }
for (i = 0; ((sensor->max_idx == -1) || (sensor->min_idx == -1)) &&
(sensor->tz->ops->get_trip_type) && (i < sensor->tz->trips);
@@ -128,60 +119,85 @@
THERMAL_TRIP_CONFIGURABLE_HI, &sensor->threshold_max);
}
- sensor->tz->ops->get_temp(sensor->tz, &curr_temp);
list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+ if (!pos->active)
+ continue;
if (pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW) {
- if (pos->temp > max_of_min)
- max_of_min = pos->temp;
- if (pos->temp < curr_temp && pos->temp > min)
- min = pos->temp;
+ if (pos->temp > max_of_low_thresh)
+ max_of_low_thresh = pos->temp;
}
if (pos->trip == THERMAL_TRIP_CONFIGURABLE_HI) {
- if (pos->temp < min_of_max)
- min_of_max = pos->temp;
- if (pos->temp > curr_temp && pos->temp < max)
- max = pos->temp;
+ if (pos->temp < min_of_high_thresh)
+ min_of_high_thresh = pos->temp;
}
}
- pr_debug("sensor %d: min of max: %ld max of min: %ld\n",
- sensor->sensor_id, max_of_min, min_of_max);
+ pr_debug("sensor %d: Thresholds: max of low: %ld min of high: %ld\n",
+ sensor->sensor_id, max_of_low_thresh,
+ min_of_high_thresh);
- /* If we haven't found a max and min bounding the curr_temp,
- * use the min of max and max of min instead.
- */
- if (max == LONG_MAX)
- max = min_of_max;
- if (min == LONG_MIN) {
- min = get_min(sensor, max);
- if (min == LONG_MIN)
- min = max_of_min;
+ if ((min_of_high_thresh != sensor->threshold_max) &&
+ (min_of_high_thresh != LONG_MAX)) {
+ ret = sensor->tz->ops->set_trip_temp(sensor->tz,
+ sensor->max_idx, min_of_high_thresh);
+ if (ret) {
+ pr_err("sensor %d: Unable to set high threshold %d",
+ sensor->sensor_id, ret);
+ goto update_done;
+ }
+ sensor->threshold_max = min_of_high_thresh;
+ }
+ ret = sensor->tz->ops->activate_trip_type(sensor->tz,
+ sensor->max_idx,
+ (min_of_high_thresh == LONG_MAX) ?
+ THERMAL_TRIP_ACTIVATION_DISABLED :
+ THERMAL_TRIP_ACTIVATION_ENABLED);
+ if (ret) {
+ pr_err("sensor %d: Unable to activate high threshold %d",
+ sensor->sensor_id, ret);
+ goto update_done;
}
- if (sensor->tz->ops->set_trip_temp) {
- if (max != sensor->threshold_max) {
- sensor->tz->ops->set_trip_temp(sensor->tz,
- sensor->max_idx, max);
- sensor->threshold_max = max;
+ if ((max_of_low_thresh != sensor->threshold_min) &&
+ (max_of_low_thresh != LONG_MIN)) {
+ ret = sensor->tz->ops->set_trip_temp(sensor->tz,
+ sensor->min_idx, max_of_low_thresh);
+ if (ret) {
+ pr_err("sensor %d: Unable to set low threshold %d",
+ sensor->sensor_id, ret);
+ goto update_done;
}
- if (min != sensor->threshold_min) {
- sensor->tz->ops->set_trip_temp(sensor->tz,
- sensor->min_idx, min);
- sensor->threshold_min = min;
- }
+ sensor->threshold_min = max_of_low_thresh;
+ }
+ ret = sensor->tz->ops->activate_trip_type(sensor->tz,
+ sensor->min_idx,
+ (max_of_low_thresh == LONG_MIN) ?
+ THERMAL_TRIP_ACTIVATION_DISABLED :
+ THERMAL_TRIP_ACTIVATION_ENABLED);
+ if (ret) {
+ pr_err("sensor %d: Unable to activate low threshold %d",
+ sensor->sensor_id, ret);
+ goto update_done;
}
- pr_debug("sensor %d: curr_temp: %ld min: %ld max: %ld\n",
- sensor->sensor_id, curr_temp,
+ pr_debug("sensor %d: low: %ld high: %ld\n",
+ sensor->sensor_id,
sensor->threshold_min, sensor->threshold_max);
+
+update_done:
+ return ret;
}
static void sensor_update_work(struct work_struct *work)
{
struct sensor_info *sensor = container_of(work, struct sensor_info,
work);
+ int ret = 0;
mutex_lock(&sensor->lock);
- __update_sensor_thresholds(sensor);
+ ret = __update_sensor_thresholds(sensor);
+ if (ret)
+ pr_err("sensor %d: Error %d setting threshold\n",
+ sensor->sensor_id, ret);
mutex_unlock(&sensor->lock);
}
@@ -202,7 +218,7 @@
return 0;
list_for_each_entry_safe(pos, var, &tz->sensor.threshold_list, list) {
- if (pos->trip != trip)
+ if ((pos->trip != trip) || (!pos->active))
continue;
if (((trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
(pos->temp <= tz->sensor.threshold_min) &&
@@ -210,6 +226,7 @@
((trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
(pos->temp >= tz->sensor.threshold_max) &&
(pos->temp <= temp))) {
+ pos->active = 0;
pos->notify(trip, temp, pos->data);
}
}
@@ -220,6 +237,29 @@
}
EXPORT_SYMBOL(thermal_sensor_trip);
+int sensor_activate_trip(uint32_t sensor_id,
+ struct sensor_threshold *threshold, bool enable)
+{
+ struct sensor_info *sensor = get_sensor(sensor_id);
+ int ret = 0;
+
+ if (!sensor || !threshold) {
+ pr_err("Sensor %d: uninitialized data\n",
+ sensor_id);
+ ret = -ENODEV;
+ goto activate_trip_exit;
+ }
+
+ mutex_lock(&sensor->lock);
+ threshold->active = (enable) ? 1 : 0;
+ ret = __update_sensor_thresholds(sensor);
+ mutex_unlock(&sensor->lock);
+
+activate_trip_exit:
+ return ret;
+}
+EXPORT_SYMBOL(sensor_activate_trip);
+
int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
{
struct sensor_threshold *pos, *var;
@@ -241,8 +281,7 @@
INIT_LIST_HEAD(&threshold->list);
list_add(&threshold->list, &sensor->threshold_list);
}
-
- __update_sensor_thresholds(sensor);
+ threshold->active = 0; /* Do not allow active threshold right away */
mutex_unlock(&sensor->lock);
return 0;
@@ -254,6 +293,7 @@
{
struct sensor_threshold *pos, *var;
struct sensor_info *sensor = get_sensor(sensor_id);
+ int ret = 0;
if (!sensor)
return -ENODEV;
@@ -261,15 +301,16 @@
mutex_lock(&sensor->lock);
list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
if (pos == threshold) {
+ pos->active = 0;
list_del(&pos->list);
break;
}
}
- __update_sensor_thresholds(sensor);
+ ret = __update_sensor_thresholds(sensor);
mutex_unlock(&sensor->lock);
- return 0;
+ return ret;
}
EXPORT_SYMBOL(sensor_cancel_trip);
@@ -283,36 +324,36 @@
return 0;
}
+static void get_trip_threshold(struct thermal_zone_device *tz, int trip,
+ struct sensor_threshold **threshold)
+{
+ enum thermal_trip_type type;
+
+ tz->ops->get_trip_type(tz, trip, &type);
+
+ if (type == THERMAL_TRIP_CONFIGURABLE_HI)
+ *threshold = &tz->tz_threshold[0];
+ else if (type == THERMAL_TRIP_CONFIGURABLE_LOW)
+ *threshold = &tz->tz_threshold[1];
+ else
+ *threshold = NULL;
+}
+
int sensor_set_trip_temp(struct thermal_zone_device *tz,
int trip, long temp)
{
int ret = 0;
- enum thermal_trip_type type;
+ struct sensor_threshold *threshold = NULL;
if (!tz->ops->get_trip_type)
return -EPERM;
- tz->ops->get_trip_type(tz, trip, &type);
- switch (type) {
- case THERMAL_TRIP_CONFIGURABLE_HI:
- tz->tz_threshold[0].temp = temp;
- tz->tz_threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
- tz->tz_threshold[0].notify = tz_notify_trip;
- tz->tz_threshold[0].data = tz;
- ret = sensor_set_trip(tz->sensor.sensor_id,
- &tz->tz_threshold[0]);
- break;
- case THERMAL_TRIP_CONFIGURABLE_LOW:
- tz->tz_threshold[1].temp = temp;
- tz->tz_threshold[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
- tz->tz_threshold[1].notify = tz_notify_trip;
- tz->tz_threshold[1].data = tz;
- ret = sensor_set_trip(tz->sensor.sensor_id,
- &tz->tz_threshold[1]);
- break;
- default:
+ get_trip_threshold(tz, trip, &threshold);
+ if (threshold) {
+ threshold->temp = temp;
+ ret = sensor_set_trip(tz->sensor.sensor_id, threshold);
+ } else {
ret = tz->ops->set_trip_temp(tz, trip, temp);
- break;
}
return ret;
@@ -333,10 +374,12 @@
INIT_LIST_HEAD(&sensor->threshold_list);
INIT_LIST_HEAD(&tz->tz_threshold[0].list);
INIT_LIST_HEAD(&tz->tz_threshold[1].list);
- tz->tz_threshold[0].notify = NULL;
- tz->tz_threshold[0].data = NULL;
- tz->tz_threshold[1].notify = NULL;
- tz->tz_threshold[1].data = NULL;
+ tz->tz_threshold[0].notify = tz_notify_trip;
+ tz->tz_threshold[0].data = tz;
+ tz->tz_threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
+ tz->tz_threshold[1].notify = tz_notify_trip;
+ tz->tz_threshold[1].data = tz;
+ tz->tz_threshold[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
list_add(&sensor->sensor_list, &sensor_info_list);
INIT_WORK(&sensor->work, sensor_update_work);
@@ -489,23 +532,40 @@
const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, result;
+ int trip, result = 0;
+ bool activate;
+ struct sensor_threshold *threshold = NULL;
- if (!tz->ops->activate_trip_type)
- return -EPERM;
+ if (!tz->ops->get_trip_type ||
+ !tz->ops->activate_trip_type) {
+ result = -EPERM;
+ goto trip_activate_exit;
+ }
- if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
- return -EINVAL;
-
- if (!strncmp(buf, "enabled", sizeof("enabled")))
- result = tz->ops->activate_trip_type(tz, trip,
- THERMAL_TRIP_ACTIVATION_ENABLED);
- else if (!strncmp(buf, "disabled", sizeof("disabled")))
- result = tz->ops->activate_trip_type(tz, trip,
- THERMAL_TRIP_ACTIVATION_DISABLED);
- else
+ if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) {
result = -EINVAL;
+ goto trip_activate_exit;
+ }
+ if (!strcmp(buf, "enabled")) {
+ activate = true;
+ } else if (!strcmp(buf, "disabled")) {
+ activate = false;
+ } else {
+ result = -EINVAL;
+ goto trip_activate_exit;
+ }
+
+ get_trip_threshold(tz, trip, &threshold);
+ if (threshold)
+ result = sensor_activate_trip(tz->sensor.sensor_id,
+ threshold, activate);
+ else
+ result = tz->ops->activate_trip_type(tz, trip,
+ activate ? THERMAL_TRIP_ACTIVATION_ENABLED :
+ THERMAL_TRIP_ACTIVATION_DISABLED);
+
+trip_activate_exit:
if (result)
return result;
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index 31e93a5..f26570d 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -203,11 +203,13 @@
fromoff = to->start - from->start;
else
tooff = from->start - to->start;
+ if ((to->len <= tooff) || (from->len <= fromoff))
+ return -EINVAL;
+
size = to->len - tooff;
+
if (size > (int) (from->len - fromoff))
size = from->len - fromoff;
- if (size <= 0)
- return -EINVAL;
size *= sizeof(u16);
if (from->red && to->red)
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index c4986ef..9ac17c9 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -38,7 +38,7 @@
#include <linux/major.h>
#include <linux/bootmem.h>
#include <linux/memblock.h>
-
+#include <linux/iopoll.h>
#include <mach/board.h>
#include <mach/clk.h>
#include <mach/hardware.h>
@@ -55,6 +55,10 @@
#include "mdp3_ppp.h"
#include "mdss_debug.h"
+#define MISR_POLL_SLEEP 2000
+#define MISR_POLL_TIMEOUT 32000
+#define MDP3_REG_CAPTURED_DSI_PCLK_MASK 1
+
#define MDP_CORE_HW_VERSION 0x03040310
struct mdp3_hw_resource *mdp3_res;
@@ -2001,6 +2005,105 @@
return rc;
}
+int mdp3_misr_get(struct mdp_misr *misr_resp)
+{
+ int result = 0, ret = -1;
+ int crc = 0;
+ pr_debug("%s CRC Capture on DSI\n", __func__);
+ switch (misr_resp->block_id) {
+ case DISPLAY_MISR_DSI0:
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_EN, 0);
+ /* Sleep for one vsync after DSI video engine is disabled */
+ msleep(20);
+ /* Enable DSI_VIDEO_0 MISR Block */
+ MDP3_REG_WRITE(MDP3_REG_MODE_DSI_PCLK, 0x20);
+ /* Reset MISR Block */
+ MDP3_REG_WRITE(MDP3_REG_MISR_RESET_DSI_PCLK, 1);
+ /* Clear MISR capture done bit */
+ MDP3_REG_WRITE(MDP3_REG_CAPTURED_DSI_PCLK, 0);
+ /* Enable MDP DSI interface */
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_EN, 1);
+ ret = readl_poll_timeout(mdp3_res->mdp_base +
+ MDP3_REG_CAPTURED_DSI_PCLK, result,
+ result & MDP3_REG_CAPTURED_DSI_PCLK_MASK,
+ MISR_POLL_SLEEP, MISR_POLL_TIMEOUT);
+ MDP3_REG_WRITE(MDP3_REG_MODE_DSI_PCLK, 0);
+ if (ret == 0) {
+ /* Disable DSI MISR interface */
+ MDP3_REG_WRITE(MDP3_REG_MODE_DSI_PCLK, 0x0);
+ crc = MDP3_REG_READ(MDP3_REG_MISR_CAPT_VAL_DSI_PCLK);
+ pr_debug("CRC Val %d\n", crc);
+ } else {
+ pr_err("CRC Read Timed Out\n");
+ }
+ break;
+
+ case DISPLAY_MISR_DSI_CMD:
+ /* Select DSI PCLK Domain */
+ MDP3_REG_WRITE(MDP3_REG_SEL_CLK_OR_HCLK_TEST_BUS, 0x004);
+ /* Select Block id DSI_CMD */
+ MDP3_REG_WRITE(MDP3_REG_MODE_DSI_PCLK, 0x10);
+ /* Reset MISR Block */
+ MDP3_REG_WRITE(MDP3_REG_MISR_RESET_DSI_PCLK, 1);
+ /* Drive Data on Test Bus */
+ MDP3_REG_WRITE(MDP3_REG_EXPORT_MISR_DSI_PCLK, 0);
+ /* Kikk off DMA_P */
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 0x11);
+ /* Wait for DMA_P Done */
+ ret = readl_poll_timeout(mdp3_res->mdp_base +
+ MDP3_REG_INTR_STATUS, result,
+ result & MDP3_INTR_DMA_P_DONE_BIT,
+ MISR_POLL_SLEEP, MISR_POLL_TIMEOUT);
+ if (ret == 0) {
+ crc = MDP3_REG_READ(MDP3_REG_MISR_CURR_VAL_DSI_PCLK);
+ pr_debug("CRC Val %d\n", crc);
+ } else {
+ pr_err("CRC Read Timed Out\n");
+ }
+ break;
+
+ default:
+ pr_err("%s CRC Capture not supported\n", __func__);
+ ret = -EINVAL;
+ break;
+ }
+
+ misr_resp->crc_value[0] = crc;
+ pr_debug("%s, CRC Capture on DSI Param Block = 0x%x, CRC 0x%x\n",
+ __func__, misr_resp->block_id, misr_resp->crc_value[0]);
+ return ret;
+}
+
+int mdp3_misr_set(struct mdp_misr *misr_req)
+{
+ int ret = 0;
+ pr_debug("%s Parameters Block = %d Cframe Count = %d CRC = %d\n",
+ __func__, misr_req->block_id, misr_req->frame_count,
+ misr_req->crc_value[0]);
+
+ switch (misr_req->block_id) {
+ case DISPLAY_MISR_DSI0:
+ pr_debug("In the case DISPLAY_MISR_DSI0\n");
+ MDP3_REG_WRITE(MDP3_REG_SEL_CLK_OR_HCLK_TEST_BUS, 1);
+ MDP3_REG_WRITE(MDP3_REG_MODE_DSI_PCLK, 0x20);
+ MDP3_REG_WRITE(MDP3_REG_MISR_RESET_DSI_PCLK, 0x1);
+ break;
+
+ case DISPLAY_MISR_DSI_CMD:
+ pr_debug("In the case DISPLAY_MISR_DSI_CMD\n");
+ MDP3_REG_WRITE(MDP3_REG_SEL_CLK_OR_HCLK_TEST_BUS, 1);
+ MDP3_REG_WRITE(MDP3_REG_MODE_DSI_PCLK, 0x10);
+ MDP3_REG_WRITE(MDP3_REG_MISR_RESET_DSI_PCLK, 0x1);
+ break;
+
+ default:
+ pr_err("%s CRC Capture not supported\n", __func__);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
static int mdp3_probe(struct platform_device *pdev)
{
int rc;
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index e0dd021..bc94fd6 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -194,6 +194,9 @@
int mdp3_get_mdp_dsi_clk(void);
int mdp3_put_mdp_dsi_clk(void);
+int mdp3_misr_set(struct mdp_misr *misr_req);
+int mdp3_misr_get(struct mdp_misr *misr_resp);
+
#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index de4e9a1..f36f088 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -951,6 +951,22 @@
mutex_unlock(&mdp3_session->lock);
}
+static int mdp3_set_metadata(struct msm_fb_data_type *mfd,
+ struct msmfb_metadata *metadata_ptr)
+{
+ int ret = 0;
+ switch (metadata_ptr->op) {
+ case metadata_op_crc:
+ ret = mdp3_misr_set(&metadata_ptr->data.misr_request);
+ break;
+ default:
+ pr_warn("Unsupported request to MDP SET META IOCTL.\n");
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
static int mdp3_get_metadata(struct msm_fb_data_type *mfd,
struct msmfb_metadata *metadata)
{
@@ -966,8 +982,11 @@
metadata->data.caps.vig_pipes = 0;
metadata->data.caps.dma_pipes = 1;
break;
+ case metadata_op_crc:
+ ret = mdp3_misr_get(&metadata->data.misr_request);
+ break;
default:
- pr_warn("Unsupported request to MDP META IOCTL.\n");
+ pr_warn("Unsupported request to MDP GET META IOCTL.\n");
ret = -EINVAL;
break;
}
@@ -1428,11 +1447,19 @@
break;
case MSMFB_METADATA_GET:
rc = copy_from_user(&metadata, argp, sizeof(metadata));
- if (rc)
- return rc;
- rc = mdp3_get_metadata(mfd, &metadata);
+ if (!rc)
+ rc = mdp3_get_metadata(mfd, &metadata);
if (!rc)
rc = copy_to_user(argp, &metadata, sizeof(metadata));
+ if (rc)
+ pr_err("mdp3_get_metadata failed (%d)\n", rc);
+ break;
+ case MSMFB_METADATA_SET:
+ rc = copy_from_user(&metadata, argp, sizeof(metadata));
+ if (!rc)
+ rc = mdp3_set_metadata(mfd, &metadata);
+ if (rc)
+ pr_err("mdp3_set_metadata failed (%d)\n", rc);
break;
case MSMFB_OVERLAY_GET:
rc = copy_from_user(req, argp, sizeof(*req));
diff --git a/drivers/video/msm/mdss/mdp3_hwio.h b/drivers/video/msm/mdss/mdp3_hwio.h
index 8846ec5..b457c10 100644
--- a/drivers/video/msm/mdss/mdp3_hwio.h
+++ b/drivers/video/msm/mdss/mdp3_hwio.h
@@ -55,6 +55,7 @@
#define MDP3_REG_HW_VERSION 0x0070
#define MDP3_REG_SW_RESET 0x0074
+#define MDP3_REG_SEL_CLK_OR_HCLK_TEST_BUS 0x007C
/*EBI*/
#define MDP3_REG_EBI2_LCD0 0x003c
@@ -117,6 +118,46 @@
#define MDP3_REG_DMA_S_IBUF_Y_STRIDE 0xA000C
#define MDP3_REG_DMA_S_OUT_XY 0xA0010
+/*MISR*/
+#define MDP3_REG_MODE_CLK 0x000D0000
+#define MDP3_REG_MISR_RESET_CLK 0x000D0004
+#define MDP3_REG_EXPORT_MISR_CLK 0x000D0008
+#define MDP3_REG_MISR_CURR_VAL_CLK 0x000D000C
+#define MDP3_REG_MODE_HCLK 0x000D0100
+#define MDP3_REG_MISR_RESET_HCLK 0x000D0104
+#define MDP3_REG_EXPORT_MISR_HCLK 0x000D0108
+#define MDP3_REG_MISR_CURR_VAL_HCLK 0x000D010C
+#define MDP3_REG_MODE_DCLK 0x000D0200
+#define MDP3_REG_MISR_RESET_DCLK 0x000D0204
+#define MDP3_REG_EXPORT_MISR_DCLK 0x000D0208
+#define MDP3_REG_MISR_CURR_VAL_DCLK 0x000D020C
+#define MDP3_REG_CAPTURED_DCLK 0x000D0210
+#define MDP3_REG_MISR_CAPT_VAL_DCLK 0x000D0214
+#define MDP3_REG_MODE_TVCLK 0x000D0300
+#define MDP3_REG_MISR_RESET_TVCLK 0x000D0304
+#define MDP3_REG_EXPORT_MISR_TVCLK 0x000D0308
+#define MDP3_REG_MISR_CURR_VAL_TVCLK 0x000D030C
+#define MDP3_REG_CAPTURED_TVCLK 0x000D0310
+#define MDP3_REG_MISR_CAPT_VAL_TVCLK 0x000D0314
+
+/* Select DSI operation type(CMD/VIDEO) */
+#define MDP3_REG_MODE_DSI_PCLK 0x000D0400
+#define MDP3_REG_MODE_DSI_PCLK_BLOCK_DSI_CMD 0x10
+#define MDP3_REG_MODE_DSI_PCLK_BLOCK_DSI_VIDEO1 0x20
+#define MDP3_REG_MODE_DSI_PCLK_BLOCK_DSI_VIDEO2 0x30
+/* RESET DSI MISR STATE */
+#define MDP3_REG_MISR_RESET_DSI_PCLK 0x000D0404
+
+/* For reading MISR State(1) and driving data on test bus(0) */
+#define MDP3_REG_EXPORT_MISR_DSI_PCLK 0x000D0408
+/* Read MISR signature */
+#define MDP3_REG_MISR_CURR_VAL_DSI_PCLK 0x000D040C
+
+/* MISR status Bit0 (1) Capture Done */
+#define MDP3_REG_CAPTURED_DSI_PCLK 0x000D0410
+#define MDP3_REG_MISR_CAPT_VAL_DSI_PCLK 0x000D0414
+#define MDP3_REG_MISR_TESTBUS_CAPT_VAL 0x000D0600
+
/*interface*/
#define MDP3_REG_LCDC_EN 0xE0000
#define MDP3_REG_LCDC_HSYNC_CTL 0xE0004
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index f933c8e..0d0240f 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -23,12 +23,13 @@
#include "mdss.h"
#include "mdss_mdp.h"
+#include "mdss_mdp_hwio.h"
#include "mdss_debug.h"
#define DEFAULT_BASE_REG_CNT 0x100
#define GROUP_BYTES 4
#define ROW_BYTES 16
-
+#define MAX_VSYNC_COUNT 0xFFFFFFF
struct mdss_debug_data {
struct dentry *root;
struct list_head base_list;
@@ -409,28 +410,63 @@
return 0;
}
+int vsync_count;
static struct mdss_mdp_misr_map {
u32 ctrl_reg;
u32 value_reg;
u32 crc_op_mode;
u32 crc_index;
- u32 crc_value[MISR_CRC_BATCH_SIZE];
+ bool use_ping;
+ bool is_ping_full;
+ bool is_pong_full;
+ struct mutex crc_lock;
+ u32 crc_ping[MISR_CRC_BATCH_SIZE];
+ u32 crc_pong[MISR_CRC_BATCH_SIZE];
} mdss_mdp_misr_table[DISPLAY_MISR_MAX] = {
[DISPLAY_MISR_DSI0] = {
.ctrl_reg = MDSS_MDP_LP_MISR_CTRL_DSI0,
.value_reg = MDSS_MDP_LP_MISR_SIGN_DSI0,
+ .crc_op_mode = 0,
+ .crc_index = 0,
+ .use_ping = true,
+ .is_ping_full = false,
+ .is_pong_full = false,
},
[DISPLAY_MISR_DSI1] = {
.ctrl_reg = MDSS_MDP_LP_MISR_CTRL_DSI1,
.value_reg = MDSS_MDP_LP_MISR_SIGN_DSI1,
+ .crc_op_mode = 0,
+ .crc_index = 0,
+ .use_ping = true,
+ .is_ping_full = false,
+ .is_pong_full = false,
},
[DISPLAY_MISR_EDP] = {
.ctrl_reg = MDSS_MDP_LP_MISR_CTRL_EDP,
.value_reg = MDSS_MDP_LP_MISR_SIGN_EDP,
+ .crc_op_mode = 0,
+ .crc_index = 0,
+ .use_ping = true,
+ .is_ping_full = false,
+ .is_pong_full = false,
},
[DISPLAY_MISR_HDMI] = {
.ctrl_reg = MDSS_MDP_LP_MISR_CTRL_HDMI,
.value_reg = MDSS_MDP_LP_MISR_SIGN_HDMI,
+ .crc_op_mode = 0,
+ .crc_index = 0,
+ .use_ping = true,
+ .is_ping_full = false,
+ .is_pong_full = false,
+ },
+ [DISPLAY_MISR_MDP] = {
+ .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_MDP,
+ .value_reg = MDSS_MDP_LP_MISR_SIGN_MDP,
+ .crc_op_mode = 0,
+ .crc_index = 0,
+ .use_ping = true,
+ .is_ping_full = false,
+ .is_pong_full = false,
},
};
@@ -438,7 +474,7 @@
{
struct mdss_mdp_misr_map *map;
- if (block_id > DISPLAY_MISR_LCDC) {
+ if (block_id > DISPLAY_MISR_MDP) {
pr_err("MISR Block id (%d) out of range\n", block_id);
return NULL;
}
@@ -452,23 +488,51 @@
return map;
}
-int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *req)
+int mdss_misr_set(struct mdss_data_type *mdata,
+ struct mdp_misr *req,
+ struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_misr_map *map;
- u32 config = 0;
-
+ struct mdss_mdp_mixer *mixer;
+ u32 config = 0, val = 0;
+ u32 mixer_num = 0;
+ bool is_valid_wb_mixer = true;
map = mdss_misr_get_map(req->block_id);
if (!map) {
pr_err("Invalid MISR Block=%d\n", req->block_id);
return -EINVAL;
}
-
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ if (req->block_id == DISPLAY_MISR_MDP) {
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
+ mixer_num = mixer->num;
+ pr_debug("SET MDP MISR BLK to MDSS_MDP_LP_MISR_SEL_LMIX%d_GC\n",
+ req->block_id);
+ switch (mixer_num) {
+ case MDSS_MDP_INTF_LAYERMIXER0:
+ pr_debug("Use Layer Mixer 0 for WB CRC\n");
+ val = MDSS_MDP_LP_MISR_SEL_LMIX0_GC;
+ break;
+ case MDSS_MDP_INTF_LAYERMIXER1:
+ pr_debug("Use Layer Mixer 1 for WB CRC\n");
+ val = MDSS_MDP_LP_MISR_SEL_LMIX1_GC;
+ break;
+ case MDSS_MDP_INTF_LAYERMIXER2:
+ pr_debug("Use Layer Mixer 2 for WB CRC\n");
+ val = MDSS_MDP_LP_MISR_SEL_LMIX2_GC;
+ break;
+ default:
+ pr_err("Invalid Layer Mixer %d selected for WB CRC\n",
+ mixer_num);
+ is_valid_wb_mixer = false;
+ break;
+ }
+ if (is_valid_wb_mixer)
+ writel_relaxed(val,
+ mdata->mdp_base + MDSS_MDP_LP_MISR_SEL);
+ }
+ vsync_count = 0;
map->crc_op_mode = req->crc_op_mode;
- memset(map->crc_value, 0, sizeof(map->crc_value));
-
- pr_debug("MISR Config (BlockId %d) (Frame Count = %d)\n",
- req->block_id, req->frame_count);
-
config = (MDSS_MDP_LP_MISR_CTRL_FRAME_COUNT_MASK & req->frame_count) |
(MDSS_MDP_LP_MISR_CTRL_ENABLE);
@@ -476,24 +540,32 @@
mdata->mdp_base + map->ctrl_reg);
/* ensure clear is done */
wmb();
- if (MISR_OP_BM == map->crc_op_mode) {
- writel_relaxed(MISR_CRC_BATCH_CFG,
- mdata->mdp_base + map->ctrl_reg);
- } else {
- writel_relaxed(config,
- mdata->mdp_base + map->ctrl_reg);
- config = readl_relaxed(mdata->mdp_base + map->ctrl_reg);
- pr_debug("MISR_CTRL = 0x%x", config);
+ memset(map->crc_ping, 0, sizeof(map->crc_ping));
+ memset(map->crc_pong, 0, sizeof(map->crc_pong));
+ map->crc_index = 0;
+ map->use_ping = true;
+ map->is_ping_full = false;
+ map->is_pong_full = false;
+
+ if (MISR_OP_BM != map->crc_op_mode) {
+
+ writel_relaxed(config,
+ mdata->mdp_base + map->ctrl_reg);
+ pr_debug("MISR_CTRL = 0x%x",
+ readl_relaxed(mdata->mdp_base + map->ctrl_reg));
}
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return 0;
}
-int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp)
+int mdss_misr_get(struct mdss_data_type *mdata,
+ struct mdp_misr *resp,
+ struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_misr_map *map;
u32 status;
- int ret = 0;
+ int ret = -1;
int i;
map = mdss_misr_get_map(resp->block_id);
@@ -501,35 +573,60 @@
pr_err("Invalid MISR Block=%d\n", resp->block_id);
return -EINVAL;
}
-
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
switch (map->crc_op_mode) {
case MISR_OP_SFM:
case MISR_OP_MFM:
ret = readl_poll_timeout(mdata->mdp_base + map->ctrl_reg,
status, status & MDSS_MDP_LP_MISR_CTRL_STATUS,
MISR_POLL_SLEEP, MISR_POLL_TIMEOUT);
-
- pr_debug("Status of Get MISR_CTRL = 0x%x", status);
if (ret == 0) {
- resp->crc_value[0] =
- readl_relaxed(mdata->mdp_base + map->value_reg);
+ resp->crc_value[0] = readl_relaxed(mdata->mdp_base +
+ map->value_reg);
pr_debug("CRC %d=0x%x\n", resp->block_id,
- resp->crc_value[0]);
+ resp->crc_value[0]);
+ writel_relaxed(0, mdata->mdp_base + map->ctrl_reg);
} else {
- pr_warn("MISR %d busy with status 0x%x\n",
- resp->block_id, status);
+ mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
+ ret = readl_poll_timeout(mdata->mdp_base +
+ map->ctrl_reg, status,
+ status & MDSS_MDP_LP_MISR_CTRL_STATUS,
+ MISR_POLL_SLEEP, MISR_POLL_TIMEOUT);
+ if (ret == 0) {
+ resp->crc_value[0] =
+ readl_relaxed(mdata->mdp_base +
+ map->value_reg);
+ }
+ writel_relaxed(0, mdata->mdp_base + map->ctrl_reg);
}
break;
case MISR_OP_BM:
- for (i = 0; i < MISR_CRC_BATCH_SIZE; i++)
- resp->crc_value[i] = map->crc_value[i];
- map->crc_index = 0;
+ if (map->is_ping_full) {
+ for (i = 0; i < MISR_CRC_BATCH_SIZE; i++)
+ resp->crc_value[i] = map->crc_ping[i];
+ memset(map->crc_ping, 0, sizeof(map->crc_ping));
+ map->is_ping_full = false;
+ ret = 0;
+ } else if (map->is_pong_full) {
+ for (i = 0; i < MISR_CRC_BATCH_SIZE; i++)
+ resp->crc_value[i] = map->crc_pong[i];
+ memset(map->crc_pong, 0, sizeof(map->crc_pong));
+ map->is_pong_full = false;
+ ret = 0;
+ } else {
+ pr_debug("mdss_mdp_misr_crc_get PING BUF %s\n",
+ map->is_ping_full ? "FULL" : "EMPTRY");
+ pr_debug("mdss_mdp_misr_crc_get PONG BUF %s\n",
+ map->is_pong_full ? "FULL" : "EMPTRY");
+ }
+ resp->crc_op_mode = map->crc_op_mode;
break;
default:
ret = -ENOSYS;
break;
}
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return ret;
}
@@ -537,22 +634,71 @@
void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id)
{
struct mdss_mdp_misr_map *map;
- u32 status, config;
+ u32 status = 0;
+ u32 crc = 0x0BAD0BAD;
+ bool crc_stored = false;
map = mdss_misr_get_map(block_id);
if (!map || (map->crc_op_mode != MISR_OP_BM))
return;
- config = MISR_CRC_BATCH_CFG;
-
status = readl_relaxed(mdata->mdp_base + map->ctrl_reg);
- if (status & MDSS_MDP_LP_MISR_CTRL_STATUS) {
- map->crc_value[map->crc_index] =
- readl_relaxed(mdata->mdp_base + map->value_reg);
- map->crc_index++;
- if (map->crc_index == MISR_CRC_BATCH_SIZE)
- map->crc_index = 0;
- config |= MDSS_MDP_LP_MISR_CTRL_STATUS_CLEAR;
+ if (MDSS_MDP_LP_MISR_CTRL_STATUS & status) {
+ crc = readl_relaxed(mdata->mdp_base + map->value_reg);
+ if (map->use_ping) {
+ if (map->is_ping_full) {
+ pr_err("PING Buffer FULL\n");
+ } else {
+ map->crc_ping[map->crc_index] = crc;
+ crc_stored = true;
+ }
+ } else {
+ if (map->is_pong_full) {
+ pr_err("PONG Buffer FULL\n");
+ } else {
+ map->crc_pong[map->crc_index] = crc;
+ crc_stored = true;
+ }
+ }
+
+ if (crc_stored) {
+ map->crc_index = (map->crc_index + 1);
+ if (map->crc_index == MISR_CRC_BATCH_SIZE) {
+ map->crc_index = 0;
+ if (true == map->use_ping) {
+ map->is_ping_full = true;
+ map->use_ping = false;
+ } else {
+ map->is_pong_full = true;
+ map->use_ping = true;
+ }
+ pr_debug("USE BUFF %s\n", map->use_ping ?
+ "PING" : "PONG");
+ pr_debug("mdss_misr_crc_collect PING BUF %s\n",
+ map->is_ping_full ? "FULL" : "EMPTRY");
+ pr_debug("mdss_misr_crc_collect PONG BUF %s\n",
+ map->is_pong_full ? "FULL" : "EMPTRY");
+ }
+ } else {
+ pr_err("CRC(%d) Not saved\n", crc);
+ }
+
+ writel_relaxed(MDSS_MDP_LP_MISR_CTRL_STATUS_CLEAR,
+ mdata->mdp_base + map->ctrl_reg);
+ writel_relaxed(MISR_CRC_BATCH_CFG,
+ mdata->mdp_base + map->ctrl_reg);
+ } else if (0 == status) {
+ writel_relaxed(MISR_CRC_BATCH_CFG,
+ mdata->mdp_base + map->ctrl_reg);
+ pr_debug("$$ Batch CRC Start $$\n");
}
- writel_relaxed(config, mdata->mdp_base + map->ctrl_reg);
+ pr_debug("$$ Vsync Count = %d, CRC=0x%x Indx = %d$$\n",
+ vsync_count, crc, map->crc_index);
+
+ if (MAX_VSYNC_COUNT == vsync_count) {
+ pr_err("RESET vsync_count(%d)\n", vsync_count);
+ vsync_count = 0;
+ } else {
+ vsync_count += 1;
+ }
}
diff --git a/drivers/video/msm/mdss/mdss_debug.h b/drivers/video/msm/mdss/mdss_debug.h
index 29eb16c..984caab 100644
--- a/drivers/video/msm/mdss/mdss_debug.h
+++ b/drivers/video/msm/mdss/mdss_debug.h
@@ -16,30 +16,35 @@
#include "mdss.h"
-#define MISR_POLL_SLEEP 2000
-#define MISR_POLL_TIMEOUT 32000
-#define MISR_CRC_BATCH_SIZE 32
-#define MISR_CRC_BATCH_CFG 0x101
+#define MISR_POLL_SLEEP 2000
+#define MISR_POLL_TIMEOUT 32000
+#define MISR_CRC_BATCH_CFG 0x101
#ifdef CONFIG_DEBUG_FS
int mdss_debugfs_init(struct mdss_data_type *mdata);
int mdss_debugfs_remove(struct mdss_data_type *mdata);
int mdss_debug_register_base(const char *name, void __iomem *base,
size_t max_offset);
-int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *req);
-int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp);
+int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req,
+ struct mdss_mdp_ctl *ctl);
+int mdss_misr_get(struct mdss_data_type *mdata, struct mdp_misr *resp,
+ struct mdss_mdp_ctl *ctl);
void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id);
#else
static inline int mdss_debugfs_init(struct mdss_data_type *mdata) { return 0; }
static inline int mdss_debugfs_remove(struct mdss_data_type *mdata)
{ return 0; }
static inline int mdss_debug_register_base(const char *name, void __iomem *base,
- size_t max_offset) { return 0; }
-static inline int mdss_misr_crc_set(struct mdss_data_type *mdata,
- struct mdp_misr *reg) { return 0; }
-static inline int mdss_misr_crc_get(struct mdss_data_type *mdata,
- struct mdp_misr *resp) { return 0; }
+ size_t max_offset) { return 0; }
+static inline int mdss_misr_set(struct mdss_data_type *mdata,
+ struct mdp_misr *req,
+ struct mdss_mdp_ctl *ctl)
+{ return 0; }
+static inline int mdss_misr_get(struct mdss_data_type *mdata,
+ struct mdp_misr *resp,
+ struct mdss_mdp_ctl *ctl)
+{ return 0; }
static inline void mdss_misr_crc_collect(struct mdss_data_type *mdata,
- int block_id) { }
+ int block_id) { }
#endif
#endif /* MDSS_DEBUG_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 7202c62..947923a 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -89,6 +89,17 @@
DSI_HS_MODE,
};
+enum dsi_lane_map_type {
+ DSI_LANE_MAP_0123,
+ DSI_LANE_MAP_3012,
+ DSI_LANE_MAP_2301,
+ DSI_LANE_MAP_1230,
+ DSI_LANE_MAP_0321,
+ DSI_LANE_MAP_1032,
+ DSI_LANE_MAP_2103,
+ DSI_LANE_MAP_3210,
+};
+
#define CTRL_STATE_UNKNOWN 0x00
#define CTRL_STATE_PANEL_INIT BIT(0)
#define CTRL_STATE_MDP_ACTIVE BIT(1)
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 8c04940..59e52b9 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -366,6 +366,49 @@
return 0;
}
+static void mdss_dsi_parse_lane_swap(struct device_node *np, char *dlane_swap)
+{
+ const char *data;
+
+ *dlane_swap = DSI_LANE_MAP_0123;
+ data = of_get_property(np, "qcom,mdss-dsi-lane-map", NULL);
+ if (data) {
+ if (!strcmp(data, "lane_map_3012"))
+ *dlane_swap = DSI_LANE_MAP_3012;
+ else if (!strcmp(data, "lane_map_2301"))
+ *dlane_swap = DSI_LANE_MAP_2301;
+ else if (!strcmp(data, "lane_map_1230"))
+ *dlane_swap = DSI_LANE_MAP_1230;
+ else if (!strcmp(data, "lane_map_0321"))
+ *dlane_swap = DSI_LANE_MAP_0321;
+ else if (!strcmp(data, "lane_map_1032"))
+ *dlane_swap = DSI_LANE_MAP_1032;
+ else if (!strcmp(data, "lane_map_2103"))
+ *dlane_swap = DSI_LANE_MAP_2103;
+ else if (!strcmp(data, "lane_map_3210"))
+ *dlane_swap = DSI_LANE_MAP_3210;
+ }
+}
+
+static void mdss_dsi_parse_trigger(struct device_node *np, char *trigger,
+ char *trigger_key)
+{
+ const char *data;
+
+ *trigger = DSI_CMD_TRIGGER_SW;
+ data = of_get_property(np, trigger_key, NULL);
+ if (data) {
+ if (!strcmp(data, "none"))
+ *trigger = DSI_CMD_TRIGGER_NONE;
+ else if (!strcmp(data, "trigger_te"))
+ *trigger = DSI_CMD_TRIGGER_TE;
+ else if (!strcmp(data, "trigger_sw_seof"))
+ *trigger = DSI_CMD_TRIGGER_SW_SEOF;
+ else if (!strcmp(data, "trigger_sw_te"))
+ *trigger = DSI_CMD_TRIGGER_SW_TE;
+ }
+}
+
static int mdss_dsi_parse_dcs_cmds(struct device_node *np,
struct dsi_panel_cmds *pcmds, char *cmd_key, char *link_key)
@@ -652,8 +695,10 @@
data = of_get_property(np, "qcom,mdss-dsi-panel-type", NULL);
if (data && !strncmp(data, "dsi_cmd_mode", 12))
pinfo->mipi.mode = DSI_CMD_MODE;
- rc = of_property_read_u32(np, "qcom,mdss-dsi-pixel-packing", &tmp);
- tmp = (!rc ? tmp : 0);
+ tmp = 0;
+ data = of_get_property(np, "qcom,mdss-dsi-pixel-packing", NULL);
+ if (data && !strcmp(data, "loose"))
+ tmp = 1;
rc = mdss_panel_dt_get_dst_fmt(pinfo->bpp,
pinfo->mipi.mode, tmp,
&(pinfo->mipi.dst_format));
@@ -761,10 +806,14 @@
"qcom,mdss-dsi-bllp-power-mode");
pinfo->mipi.eof_bllp_power_stop = of_property_read_bool(
np, "qcom,mdss-dsi-bllp-eof-power-mode");
- rc = of_property_read_u32(np,
- "qcom,mdss-dsi-traffic-mode", &tmp);
- pinfo->mipi.traffic_mode =
- (!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
+ pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+ data = of_get_property(np, "qcom,mdss-dsi-traffic-mode", NULL);
+ if (data) {
+ if (!strcmp(data, "non_burst_sync_event"))
+ pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
+ else if (!strcmp(data, "burst_mode"))
+ pinfo->mipi.traffic_mode = DSI_BURST_MODE;
+ }
rc = of_property_read_u32(np,
"qcom,mdss-dsi-te-dcs-command", &tmp);
pinfo->mipi.insert_dcs_cmd =
@@ -783,8 +832,20 @@
(!rc ? tmp : 1);
rc = of_property_read_u32(np, "qcom,mdss-dsi-virtual-channel-id", &tmp);
pinfo->mipi.vc = (!rc ? tmp : 0);
- rc = of_property_read_u32(np, "qcom,mdss-dsi-color-order", &tmp);
- pinfo->mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ data = of_get_property(np, "mdss-dsi-color-order", NULL);
+ if (data) {
+ if (!strcmp(data, "rgb_swap_rbg"))
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RBG;
+ else if (!strcmp(data, "rgb_swap_bgr"))
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_BGR;
+ else if (!strcmp(data, "rgb_swap_brg"))
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_BRG;
+ else if (!strcmp(data, "rgb_swap_grb"))
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_GRB;
+ else if (!strcmp(data, "rgb_swap_gbr"))
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_GBR;
+ }
pinfo->mipi.data_lane0 = of_property_read_bool(np,
"qcom,mdss-dsi-lane-0-state");
pinfo->mipi.data_lane1 = of_property_read_bool(np,
@@ -794,9 +855,6 @@
pinfo->mipi.data_lane3 = of_property_read_bool(np,
"qcom,mdss-dsi-lane-3-state");
- rc = of_property_read_u32(np, "qcom,mdss-dsi-lane-map", &tmp);
- pinfo->mipi.dlane_swap = (!rc ? tmp : 0);
-
rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-pre", &tmp);
pinfo->mipi.t_clk_pre = (!rc ? tmp : 0x24);
rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-post", &tmp);
@@ -805,26 +863,7 @@
rc = of_property_read_u32(np, "qcom,mdss-dsi-stream", &tmp);
pinfo->mipi.stream = (!rc ? tmp : 0);
- rc = of_property_read_u32(np, "qcom,mdss-dsi-mdp-trigger", &tmp);
- pinfo->mipi.mdp_trigger =
- (!rc ? tmp : DSI_CMD_TRIGGER_SW);
- if (pinfo->mipi.mdp_trigger > 6) {
- pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
- __func__, __LINE__);
- pinfo->mipi.mdp_trigger =
- DSI_CMD_TRIGGER_SW;
- }
-
- rc = of_property_read_u32(np, "qcom,mdss-dsi-dma-trigger", &tmp);
- pinfo->mipi.dma_trigger =
- (!rc ? tmp : DSI_CMD_TRIGGER_SW);
- if (pinfo->mipi.dma_trigger > 6) {
- pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
- __func__, __LINE__);
- pinfo->mipi.dma_trigger =
- DSI_CMD_TRIGGER_SW;
- }
- data = of_get_property(np, "qcom,mdss-dsi-panel-mode-gpio-state", &tmp);
+ data = of_get_property(np, "qcom,mdss-dsi-panel-mode-gpio-state", NULL);
if (data) {
if (!strcmp(data, "high"))
pinfo->mode_gpio_state = MODE_GPIO_HIGH;
@@ -854,6 +893,14 @@
mdss_dsi_parse_fbc_params(np, pinfo);
+ mdss_dsi_parse_trigger(np, &(pinfo->mipi.mdp_trigger),
+ "qcom,mdss-dsi-mdp-trigger");
+
+ mdss_dsi_parse_trigger(np, &(pinfo->mipi.dma_trigger),
+ "qcom,mdss-dsi-dma-trigger");
+
+ mdss_dsi_parse_lane_swap(np, &(pinfo->mipi.dlane_swap));
+
mdss_dsi_parse_reset_seq(np, pinfo->rst_seq, &(pinfo->rst_seq_len),
"qcom,mdss-dsi-reset-sequence");
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 81473db..5408bc3 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -92,7 +92,7 @@
unsigned long val, void *data);
static int __mdss_fb_display_thread(void *data);
-static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd);
+static int mdss_fb_pan_idle(struct msm_fb_data_type *mfd);
static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd,
int event, void *arg);
void mdss_fb_no_update_notify_timer_cb(unsigned long data)
@@ -297,6 +297,7 @@
{
struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+ mfd->shutdown_pending = true;
lock_fb_info(mfd->fbi);
mdss_fb_release_all(mfd->fbi, true);
unlock_fb_info(mfd->fbi);
@@ -779,13 +780,18 @@
u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ int ret = 0;
if (!start) {
pr_warn("No framebuffer memory is allocated.\n");
return -ENOMEM;
}
- mdss_fb_pan_idle(mfd);
+ ret = mdss_fb_pan_idle(mfd);
+ if (ret) {
+ pr_err("Shutdown pending. Aborting operation\n");
+ return ret;
+ }
/* Set VM flags. */
start &= PAGE_MASK;
@@ -1120,8 +1126,6 @@
mfd->index, fbi->var.xres, fbi->var.yres,
fbi->fix.smem_len);
- kthread_run(__mdss_fb_display_thread, mfd, "mdss_fb%d", mfd->index);
-
return 0;
}
@@ -1132,6 +1136,11 @@
int result;
int pid = current->tgid;
+ if (mfd->shutdown_pending) {
+ pr_err("Shutdown pending. Aborting operation\n");
+ return -EPERM;
+ }
+
list_for_each_entry(pinfo, &mfd->proc_list, list) {
if (pinfo->pid == pid)
break;
@@ -1151,23 +1160,47 @@
result = pm_runtime_get_sync(info->dev);
- if (result < 0)
+ if (result < 0) {
pr_err("pm_runtime: fail to wake up\n");
+ goto pm_error;
+ }
if (!mfd->ref_cnt) {
+ mfd->disp_thread = kthread_run(__mdss_fb_display_thread, mfd,
+ "mdss_fb%d", mfd->index);
+ if (IS_ERR(mfd->disp_thread)) {
+ pr_err("unable to start display thread %d\n",
+ mfd->index);
+ result = PTR_ERR(mfd->disp_thread);
+ goto thread_error;
+ }
+
result = mdss_fb_blank_sub(FB_BLANK_UNBLANK, info,
mfd->op_enable);
if (result) {
- pm_runtime_put(info->dev);
pr_err("can't turn on fb%d! rc=%d\n", mfd->index,
result);
- return result;
+ goto blank_error;
}
}
pinfo->ref_cnt++;
mfd->ref_cnt++;
+
return 0;
+
+blank_error:
+ kthread_stop(mfd->disp_thread);
+
+thread_error:
+ if (pinfo && !pinfo->ref_cnt) {
+ list_del(&pinfo->list);
+ kfree(pinfo);
+ }
+ pm_runtime_put(info->dev);
+
+pm_error:
+ return result;
}
static int mdss_fb_release_all(struct fb_info *info, bool release_all)
@@ -1176,9 +1209,12 @@
struct mdss_fb_proc_info *pinfo = NULL, *temp_pinfo = NULL;
int ret = 0;
int pid = current->tgid;
+ bool unknown_pid = true, release_needed = false;
+ struct task_struct *task = current->group_leader;
if (!mfd->ref_cnt) {
- pr_info("try to close unopened fb %d!\n", mfd->index);
+ pr_info("try to close unopened fb %d! from %s\n", mfd->index,
+ task->comm);
return -EINVAL;
}
@@ -1190,12 +1226,15 @@
if (!release_all && (pinfo->pid != pid))
continue;
- pr_debug("found process entry pid=%d ref=%d\n", pinfo->pid,
- pinfo->ref_cnt);
+ unknown_pid = false;
+
+ pr_debug("found process %s pid=%d mfd->ref=%d pinfo->ref=%d\n",
+ task->comm, mfd->ref_cnt, pinfo->pid, pinfo->ref_cnt);
do {
if (mfd->ref_cnt < pinfo->ref_cnt)
- pr_warn("WARN:mfd->ref_cnt < pinfo->ref_cnt\n");
+ pr_warn("WARN:mfd->ref=%d < pinfo->ref=%d\n",
+ mfd->ref_cnt, pinfo->ref_cnt);
else
mfd->ref_cnt--;
@@ -1203,24 +1242,52 @@
pm_runtime_put(info->dev);
} while (release_all && pinfo->ref_cnt);
+ if (release_all)
+ kthread_stop(mfd->disp_thread);
+
if (pinfo->ref_cnt == 0) {
- if (mfd->mdp.release_fnc) {
- ret = mfd->mdp.release_fnc(mfd);
- if (ret)
- pr_err("error releasing fb%d pid=%d\n",
- mfd->index, pinfo->pid);
- }
list_del(&pinfo->list);
kfree(pinfo);
+ release_needed = !release_all;
+ }
+
+ if (!release_all)
+ break;
+ }
+
+ if (release_needed) {
+ pr_debug("known process %s pid=%d mfd->ref=%d\n",
+ task->comm, pid, mfd->ref_cnt);
+
+ if (mfd->mdp.release_fnc) {
+ ret = mfd->mdp.release_fnc(mfd, false);
+ if (ret)
+ pr_err("error releasing fb%d pid=%d\n",
+ mfd->index, pid);
+ }
+ } else if (unknown_pid || release_all) {
+ pr_warn("unknown process %s pid=%d mfd->ref=%d\n",
+ task->comm, pid, mfd->ref_cnt);
+
+ if (mfd->ref_cnt)
+ mfd->ref_cnt--;
+
+ if (mfd->mdp.release_fnc) {
+ ret = mfd->mdp.release_fnc(mfd, true);
+ if (ret)
+ pr_err("error fb%d release process %s pid=%d\n",
+ mfd->index, task->comm, pid);
}
}
if (!mfd->ref_cnt) {
+ kthread_stop(mfd->disp_thread);
+
ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
mfd->op_enable);
if (ret) {
- pr_err("can't turn off fb%d! rc=%d\n",
- mfd->index, ret);
+ pr_err("can't turn off fb%d! rc=%d process %s pid=%d\n",
+ mfd->index, ret, task->comm, pid);
return ret;
}
}
@@ -1392,21 +1459,28 @@
* hardware configuration. After this function returns it is safe to perform
* software updates for next frame.
*/
-static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd)
+static int mdss_fb_pan_idle(struct msm_fb_data_type *mfd)
{
- int ret;
+ int ret = 0;
ret = wait_event_timeout(mfd->idle_wait_q,
- !atomic_read(&mfd->commits_pending),
+ (!atomic_read(&mfd->commits_pending) ||
+ mfd->shutdown_pending),
msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
if (!ret) {
pr_err("wait for idle timeout %d pending=%d\n",
ret, atomic_read(&mfd->commits_pending));
mdss_fb_signal_timeline(&mfd->mdp_sync_pt_data);
+ } else if (mfd->shutdown_pending) {
+ pr_debug("Shutdown signalled\n");
+ return -EPERM;
}
+
+ return 0;
}
+
static int mdss_fb_pan_display_ex(struct fb_info *info,
struct mdp_display_commit *disp_commit)
{
@@ -1424,7 +1498,11 @@
if (var->yoffset > (info->var.yres_virtual - info->var.yres))
return -EINVAL;
- mdss_fb_pan_idle(mfd);
+ ret = mdss_fb_pan_idle(mfd);
+ if (ret) {
+ pr_err("Shutdown pending. Aborting operation\n");
+ return ret;
+ }
mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
if (info->fix.xpanstep)
@@ -1556,14 +1634,20 @@
while (1) {
wait_event(mfd->commit_wait_q,
- atomic_read(&mfd->commits_pending));
+ (atomic_read(&mfd->commits_pending) ||
+ kthread_should_stop()));
+
+ if (kthread_should_stop())
+ break;
ret = __mdss_fb_perform_commit(mfd);
-
atomic_dec(&mfd->commits_pending);
wake_up_all(&mfd->idle_wait_q);
}
+ atomic_set(&mfd->commits_pending, 0);
+ wake_up_all(&mfd->idle_wait_q);
+
return ret;
}
@@ -1686,8 +1770,14 @@
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct fb_var_screeninfo *var = &info->var;
int old_imgType;
+ int ret = 0;
- mdss_fb_pan_idle(mfd);
+ ret = mdss_fb_pan_idle(mfd);
+ if (ret) {
+ pr_err("Shutdown pending. Aborting operation\n");
+ return ret;
+ }
+
old_imgType = mfd->fb_imgType;
switch (var->bits_per_pixel) {
case 16:
@@ -1734,7 +1824,7 @@
mfd->panel_reconfig = false;
}
- return 0;
+ return ret;
}
int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
@@ -1975,8 +2065,15 @@
mfd = (struct msm_fb_data_type *)info->par;
mdss_fb_power_setting_idle(mfd);
if ((cmd != MSMFB_VSYNC_CTRL) && (cmd != MSMFB_OVERLAY_VSYNC_CTRL) &&
- (cmd != MSMFB_ASYNC_BLIT) && (cmd != MSMFB_BLIT))
- mdss_fb_pan_idle(mfd);
+ (cmd != MSMFB_ASYNC_BLIT) && (cmd != MSMFB_BLIT) &&
+ (cmd != MSMFB_NOTIFY_UPDATE)) {
+ ret = mdss_fb_pan_idle(mfd);
+ if (ret) {
+ pr_debug("Shutdown pending. Aborting operation %x\n",
+ cmd);
+ return ret;
+ }
+ }
switch (cmd) {
case MSMFB_CURSOR:
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 8213dbe..e245dd3 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -106,7 +106,7 @@
int (*on_fnc)(struct msm_fb_data_type *mfd);
int (*off_fnc)(struct msm_fb_data_type *mfd);
/* called to release resources associated to the process */
- int (*release_fnc)(struct msm_fb_data_type *mfd);
+ int (*release_fnc)(struct msm_fb_data_type *mfd, bool release_all);
int (*kickoff_fnc)(struct msm_fb_data_type *mfd,
struct mdp_display_commit *data);
int (*ioctl_handler)(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
@@ -195,9 +195,11 @@
struct msm_sync_pt_data mdp_sync_pt_data;
/* for non-blocking */
+ struct task_struct *disp_thread;
atomic_t commits_pending;
wait_queue_head_t commit_wait_q;
wait_queue_head_t idle_wait_q;
+ bool shutdown_pending;
struct msm_fb_backup_type msm_fb_backup;
struct completion power_set_comp;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index bac01fc..0afa501 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1057,15 +1057,16 @@
#define SPRINT(fmt, ...) \
(cnt += scnprintf(buf + cnt, len - cnt, fmt, ##__VA_ARGS__))
- SPRINT("mdp_version=5 hw_rev=%d\n", mdata->mdp_rev);
+ SPRINT("mdp_version=5\n");
+ SPRINT("hw_rev=%d\n", mdata->mdp_rev);
SPRINT("rgb_pipes=%d\n", mdata->nrgb_pipes);
SPRINT("vig_pipes=%d\n", mdata->nvig_pipes);
SPRINT("dma_pipes=%d\n", mdata->ndma_pipes);
SPRINT("smp_count=%d\n", mdata->smp_mb_cnt);
SPRINT("smp_size=%d\n", mdata->smp_mb_size);
- SPRINT("max downscale ratio=%d\n", MAX_DOWNSCALE_RATIO);
- SPRINT("max upscale ratio=%d\n", MAX_UPSCALE_RATIO);
- SPRINT("features:");
+ SPRINT("max_downscale_ratio=%d\n", MAX_DOWNSCALE_RATIO);
+ SPRINT("max_upscale_ratio=%d\n", MAX_UPSCALE_RATIO);
+ SPRINT("features=");
if (mdata->has_bwc)
SPRINT(" bwc");
if (mdata->has_decimation)
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index d140ea0..6646c0b 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -354,6 +354,8 @@
u8 blend_op;
u8 overfetch_disable;
u32 transp;
+ u32 bg_color;
+ u8 has_buf;
struct msm_fb_data_type *mfd;
struct mdss_mdp_mixer *mixer;
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index aa7c4dd..19ed857 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1782,6 +1782,11 @@
{
int ret;
+ if (!ctl) {
+ pr_err("invalid ctl\n");
+ return -ENODEV;
+ }
+
ret = mutex_lock_interruptible(&ctl->lock);
if (ret)
return ret;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 0fb01ad..3fd4805 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -504,6 +504,7 @@
} else {
pipe->overfetch_disable = 0;
}
+ pipe->bg_color = req->bg_color;
req->id = pipe->ndx;
pipe->req_data = *req;
@@ -596,6 +597,7 @@
}
pipe->params_changed++;
+ pipe->has_buf = 0;
req->vert_deci = pipe->vert_deci;
@@ -1027,8 +1029,9 @@
} else if (pipe->front_buf.num_planes) {
buf = &pipe->front_buf;
} else {
- pr_warn("pipe queue w/o buffer\n");
- continue;
+ pr_debug("no buf detected pnum=%d use solid fill\n",
+ pipe->num);
+ buf = NULL;
}
ret = mdss_mdp_pipe_queue_data(pipe, buf);
@@ -1153,11 +1156,13 @@
/**
* mdss_mdp_overlay_release_all() - release any overlays associated with fb dev
* @mfd: Msm frame buffer structure associated with fb device
+ * @release_all: ignore pid and release all the pipes
*
* Release any resources allocated by calling process, this can be called
* on fb_release to release any overlays/rotator sessions left open.
*/
-static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd)
+static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd,
+ bool release_all)
{
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_rotator_session *rot, *tmp;
@@ -1171,7 +1176,7 @@
mutex_lock(&mdp5_data->ov_lock);
mutex_lock(&mfd->lock);
list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
- if (!mfd->ref_cnt || (pipe->pid == pid)) {
+ if (release_all || (pipe->pid == pid)) {
unset_ndx |= pipe->ndx;
cnt++;
}
@@ -1183,6 +1188,9 @@
cnt++;
}
+ pr_debug("release_all=%d mfd->ref_cnt=%d unset_ndx=0x%x cnt=%d\n",
+ release_all, mfd->ref_cnt, unset_ndx, cnt);
+
mutex_unlock(&mfd->lock);
if (unset_ndx) {
@@ -1251,6 +1259,7 @@
if (IS_ERR_VALUE(ret)) {
pr_err("src_data pmem error\n");
}
+ pipe->has_buf = 1;
mdss_mdp_pipe_unmap(pipe);
return ret;
@@ -1493,6 +1502,7 @@
buf->p[0].addr += offset;
buf->p[0].len = fbi->fix.smem_len - offset;
buf->num_planes = 1;
+ pipe->has_buf = 1;
mdss_mdp_pipe_unmap(pipe);
if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
@@ -1507,6 +1517,7 @@
goto pan_display_error;
}
pipe->back_buf = *buf;
+ pipe->has_buf = 1;
mdss_mdp_pipe_unmap(pipe);
}
mutex_unlock(&mdp5_data->ov_lock);
@@ -2092,7 +2103,10 @@
struct msmfb_metadata *metadata)
{
struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
int ret = 0;
+ if (!ctl)
+ return -EPERM;
switch (metadata->op) {
case metadata_op_vic:
if (mfd->panel_info)
@@ -2104,7 +2118,7 @@
case metadata_op_crc:
if (!mfd->panel_power_on)
return -EPERM;
- ret = mdss_misr_crc_set(mdata, &metadata->data.misr_request);
+ ret = mdss_misr_set(mdata, &metadata->data.misr_request, ctl);
break;
case metadata_op_wb_format:
ret = mdss_mdp_wb_set_format(mfd,
@@ -2140,7 +2154,10 @@
struct msmfb_metadata *metadata)
{
struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
int ret = 0;
+ if (!ctl)
+ return -EPERM;
switch (metadata->op) {
case metadata_op_frame_rate:
metadata->data.panel_frame_rate =
@@ -2152,7 +2169,7 @@
case metadata_op_crc:
if (!mfd->panel_power_on)
return -EPERM;
- ret = mdss_misr_crc_get(mdata, &metadata->data.misr_request);
+ ret = mdss_misr_get(mdata, &metadata->data.misr_request, ctl);
break;
case metadata_op_wb_format:
ret = mdss_mdp_wb_get_format(mfd, &metadata->data.mixer_cfg);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 25cb9dd..78e7d29 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -924,6 +924,8 @@
secure = (pipe->flags & MDP_SECURE_OVERLAY_SESSION ? 0xF : 0x0);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, format);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR,
+ pipe->bg_color);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_ADDR_SW_STATUS, secure);
return 0;
@@ -962,7 +964,8 @@
(pipe->mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
&& (ctl->mdata->mixer_switched)) ||
ctl->roi_changed;
- if (src_data == NULL) {
+ if (src_data == NULL || !pipe->has_buf) {
+ pipe->params_changed = 0;
mdss_mdp_pipe_solidfill_setup(pipe);
goto update_nobuf;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index b680823..c3e1916 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -200,14 +200,20 @@
mdss_misr_crc_collect(mdata, DISPLAY_MISR_HDMI);
}
- if (isr & MDSS_MDP_INTR_WB_0_DONE)
+ if (isr & MDSS_MDP_INTR_WB_0_DONE) {
mdss_mdp_intr_done(MDP_INTR_WB_0);
+ mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP);
+ }
- if (isr & MDSS_MDP_INTR_WB_1_DONE)
+ if (isr & MDSS_MDP_INTR_WB_1_DONE) {
mdss_mdp_intr_done(MDP_INTR_WB_1);
+ mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP);
+ }
- if (isr & MDSS_MDP_INTR_WB_2_DONE)
+ if (isr & MDSS_MDP_INTR_WB_2_DONE) {
mdss_mdp_intr_done(MDP_INTR_WB_2);
+ mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP);
+ }
mdp_isr_done:
hist_isr = MDSS_MDP_REG_READ(MDSS_MDP_REG_HIST_INTR_STATUS);
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 3425386..b9aa952 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -479,6 +479,50 @@
uint32_t roi_w[MAX_PLANES];
};
+/**
+ * struct mdp_overlay - overlay surface structure
+ * @src: Source image information (width, height, format).
+ * @src_rect: Source crop rectangle, portion of image that will be fetched.
+ * This should always be within boundaries of source image.
+ * @dst_rect: Destination rectangle, the position and size of image on screen.
+ * This should always be within panel boundaries.
+ * @z_order: Blending stage to occupy in display, if multiple layers are
+ * present, highest z_order usually means the top most visible
+ * layer. The range acceptable is from 0-3 to support blending
+ * up to 4 layers.
+ * @is_fg: This flag is used to disable blending of any layers with z_order
+ * less than this overlay. It means that any layers with z_order
+ * less than this layer will not be blended and will be replaced
+ * by the background border color.
+ * @alpha: Used to set plane opacity. The range can be from 0-255, where
+ * 0 means completely transparent and 255 means fully opaque.
+ * @transp_mask: Color used as color key for transparency. Any pixel in fetched
+ * image matching this color will be transparent when blending.
+ * The color should be in same format as the source image format.
+ * @flags: This is used to customize operation of overlay. See MDP flags
+ * for more information.
+ * @user_data: DEPRECATED* Used to store user application specific information.
+ * @bg_color: Solid color used to fill the overlay surface when no source
+ * buffer is provided.
+ * @horz_deci: Horizontal decimation value, this indicates the amount of pixels
+ * dropped for each pixel that is fetched from a line. The value
+ * given should be power of two of decimation amount.
+ * 0: no decimation
+ * 1: decimate by 2 (drop 1 pixel for each pixel fetched)
+ * 2: decimate by 4 (drop 3 pixels for each pixel fetched)
+ * 3: decimate by 8 (drop 7 pixels for each pixel fetched)
+ * 4: decimate by 16 (drop 15 pixels for each pixel fetched)
+ * @vert_deci: Vertical decimation value, this indicates the amount of lines
+ * dropped for each line that is fetched from overlay. The value
+ * given should be power of two of decimation amount.
+ * 0: no decimation
+ * 1: decimation by 2 (drop 1 line for each line fetched)
+ * 2: decimation by 4 (drop 3 lines for each line fetched)
+ * 3: decimation by 8 (drop 7 lines for each line fetched)
+ * 4: decimation by 16 (drop 15 lines for each line fetched)
+ * @overlay_pp_cfg: Overlay post processing configuration, for more information
+ * see struct mdp_overlay_pp_params.
+ */
struct mdp_overlay {
struct msmfb_img src;
struct mdp_rect src_rect;
@@ -490,7 +534,8 @@
uint32_t transp_mask;
uint32_t flags;
uint32_t id;
- uint32_t user_data[7];
+ uint32_t user_data[6];
+ uint32_t bg_color;
uint8_t horz_deci;
uint8_t vert_deci;
struct mdp_overlay_pp_params overlay_pp_cfg;
@@ -520,19 +565,21 @@
uint32_t *b;
};
+#define MISR_CRC_BATCH_SIZE 32
enum {
- DISPLAY_MISR_EDP,
+ DISPLAY_MISR_EDP = 0,
DISPLAY_MISR_DSI0,
DISPLAY_MISR_DSI1,
DISPLAY_MISR_HDMI,
DISPLAY_MISR_LCDC,
+ DISPLAY_MISR_MDP,
DISPLAY_MISR_ATV,
DISPLAY_MISR_DSI_CMD,
DISPLAY_MISR_MAX
};
enum {
- MISR_OP_NONE,
+ MISR_OP_NONE = 0,
MISR_OP_SFM,
MISR_OP_MFM,
MISR_OP_BM,
@@ -543,7 +590,7 @@
uint32_t block_id;
uint32_t frame_count;
uint32_t crc_op_mode;
- uint32_t crc_value[32];
+ uint32_t crc_value[MISR_CRC_BATCH_SIZE];
};
/*
diff --git a/include/linux/sensors.h b/include/linux/sensors.h
index d5b140c..3520034 100644
--- a/include/linux/sensors.h
+++ b/include/linux/sensors.h
@@ -17,6 +17,36 @@
#include <linux/spinlock.h>
#include <linux/rwsem.h>
+#define SENSORS_ACCELERATION_HANDLE 0
+#define SENSORS_MAGNETIC_FIELD_HANDLE 1
+#define SENSORS_ORIENTATION_HANDLE 2
+#define SENSORS_LIGHT_HANDLE 3
+#define SENSORS_PROXIMITY_HANDLE 4
+#define SENSORS_GYROSCOPE_HANDLE 5
+#define SENSORS_PRESSURE_HANDLE 6
+
+#define SENSOR_TYPE_ACCELEROMETER 1
+#define SENSOR_TYPE_GEOMAGNETIC_FIELD 2
+#define SENSOR_TYPE_MAGNETIC_FIELD SENSOR_TYPE_GEOMAGNETIC_FIELD
+#define SENSOR_TYPE_ORIENTATION 3
+#define SENSOR_TYPE_GYROSCOPE 4
+#define SENSOR_TYPE_LIGHT 5
+#define SENSOR_TYPE_PRESSURE 6
+#define SENSOR_TYPE_TEMPERATURE 7
+#define SENSOR_TYPE_PROXIMITY 8
+#define SENSOR_TYPE_GRAVITY 9
+#define SENSOR_TYPE_LINEAR_ACCELERATION 10
+#define SENSOR_TYPE_ROTATION_VECTOR 11
+#define SENSOR_TYPE_RELATIVE_HUMIDITY 12
+#define SENSOR_TYPE_AMBIENT_TEMPERATURE 13
+#define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED 14
+#define SENSOR_TYPE_GAME_ROTATION_VECTOR 15
+#define SENSOR_TYPE_GYROSCOPE_UNCALIBRATED 16
+#define SENSOR_TYPE_SIGNIFICANT_MOTION 17
+#define SENSOR_TYPE_STEP_DETECTOR 18
+#define SENSOR_TYPE_STEP_COUNTER 19
+#define SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR 20
+
struct sensors_classdev {
struct device *dev;
struct list_head node;
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index ed6d41b..faf98fe 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -102,6 +102,7 @@
enum thermal_trip_type trip;
int (*notify)(enum thermal_trip_type type, int temp, void *data);
void *data;
+ uint8_t active;
struct list_head list;
};
@@ -189,6 +190,8 @@
int sensor_get_id(char *name);
int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
+int sensor_activate_trip(uint32_t sensor_id, struct sensor_threshold *threshold,
+ bool enable);
int thermal_sensor_trip(struct thermal_zone_device *tz,
enum thermal_trip_type trip, long temp);
diff --git a/include/media/msm_jpeg.h b/include/media/msm_jpeg.h
index 56829f1..99f0de0 100644
--- a/include/media/msm_jpeg.h
+++ b/include/media/msm_jpeg.h
@@ -55,6 +55,9 @@
#define MSM_JPEG_IOCTL_TEST_DUMP_REGION \
_IOW(MSM_JPEG_IOCTL_MAGIC, 15, unsigned long)
+#define MSM_JPEG_IOCTL_SET_CLK_RATE \
+ _IOW(MSM_JPEG_IOCTL_MAGIC, 16, unsigned long)
+
#define MSM_JPEG_MODE_REALTIME_ENCODE 0
#define MSM_JPEG_MODE_OFFLINE_ENCODE 1
#define MSM_JPEG_MODE_REALTIME_ROTATION 2
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index b62a759..75fe3a2 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -6279,6 +6279,206 @@
#define VOICE_CMD_GET_PARAM 0x0001133E
#define VOICE_EVT_GET_PARAM_ACK 0x00011008
+
+/** ID of the Bass Boost module.
+ This module supports the following parameter IDs:
+ - #AUDPROC_PARAM_ID_BASS_BOOST_ENABLE
+ - #AUDPROC_PARAM_ID_BASS_BOOST_MODE
+ - #AUDPROC_PARAM_ID_BASS_BOOST_STRENGTH
+*/
+#define AUDPROC_MODULE_ID_BASS_BOOST 0x000108A1
+/** ID of the Bass Boost enable parameter used by
+ AUDPROC_MODULE_ID_BASS_BOOST.
+*/
+#define AUDPROC_PARAM_ID_BASS_BOOST_ENABLE 0x000108A2
+/** ID of the Bass Boost mode parameter used by
+ AUDPROC_MODULE_ID_BASS_BOOST.
+*/
+#define AUDPROC_PARAM_ID_BASS_BOOST_MODE 0x000108A3
+/** ID of the Bass Boost strength parameter used by
+ AUDPROC_MODULE_ID_BASS_BOOST.
+*/
+#define AUDPROC_PARAM_ID_BASS_BOOST_STRENGTH 0x000108A4
+
+/** ID of the Virtualizer module. This module supports the
+ following parameter IDs:
+ - #AUDPROC_PARAM_ID_VIRTUALIZER_ENABLE
+ - #AUDPROC_PARAM_ID_VIRTUALIZER_STRENGTH
+ - #AUDPROC_PARAM_ID_VIRTUALIZER_OUT_TYPE
+ - #AUDPROC_PARAM_ID_VIRTUALIZER_GAIN_ADJUST
+*/
+#define AUDPROC_MODULE_ID_VIRTUALIZER 0x000108A5
+/** ID of the Virtualizer enable parameter used by
+ AUDPROC_MODULE_ID_VIRTUALIZER.
+*/
+#define AUDPROC_PARAM_ID_VIRTUALIZER_ENABLE 0x000108A6
+/** ID of the Virtualizer strength parameter used by
+ AUDPROC_MODULE_ID_VIRTUALIZER.
+*/
+#define AUDPROC_PARAM_ID_VIRTUALIZER_STRENGTH 0x000108A7
+/** ID of the Virtualizer out type parameter used by
+ AUDPROC_MODULE_ID_VIRTUALIZER.
+*/
+#define AUDPROC_PARAM_ID_VIRTUALIZER_OUT_TYPE 0x000108A8
+/** ID of the Virtualizer out type parameter used by
+ AUDPROC_MODULE_ID_VIRTUALIZER.
+*/
+#define AUDPROC_PARAM_ID_VIRTUALIZER_GAIN_ADJUST 0x000108A9
+
+/** ID of the Reverb module. This module supports the following
+ parameter IDs:
+ - #AUDPROC_PARAM_ID_REVERB_ENABLE
+ - #AUDPROC_PARAM_ID_REVERB_MODE
+ - #AUDPROC_PARAM_ID_REVERB_PRESET
+ - #AUDPROC_PARAM_ID_REVERB_WET_MIX
+ - #AUDPROC_PARAM_ID_REVERB_GAIN_ADJUST
+ - #AUDPROC_PARAM_ID_REVERB_ROOM_LEVEL
+ - #AUDPROC_PARAM_ID_REVERB_ROOM_HF_LEVEL
+ - #AUDPROC_PARAM_ID_REVERB_DECAY_TIME
+ - #AUDPROC_PARAM_ID_REVERB_DECAY_HF_RATIO
+ - #AUDPROC_PARAM_ID_REVERB_REFLECTIONS_LEVEL
+ - #AUDPROC_PARAM_ID_REVERB_REFLECTIONS_DELAY
+ - #AUDPROC_PARAM_ID_REVERB_LEVEL
+ - #AUDPROC_PARAM_ID_REVERB_DELAY
+ - #AUDPROC_PARAM_ID_REVERB_DIFFUSION
+ - #AUDPROC_PARAM_ID_REVERB_DENSITY
+*/
+#define AUDPROC_MODULE_ID_REVERB 0x000108AA
+/** ID of the Reverb enable parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_ENABLE 0x000108AB
+/** ID of the Reverb mode parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_MODE 0x000108AC
+/** ID of the Reverb preset parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_PRESET 0x000108AD
+/** ID of the Reverb wet mix parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_WET_MIX 0x000108AE
+/** ID of the Reverb gain adjust parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_GAIN_ADJUST 0x000108AF
+/** ID of the Reverb room level parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_ROOM_LEVEL 0x000108B0
+/** ID of the Reverb room hf level parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_ROOM_HF_LEVEL 0x000108B1
+/** ID of the Reverb decay time parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_DECAY_TIME 0x000108B2
+/** ID of the Reverb decay hf ratio parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_DECAY_HF_RATIO 0x000108B3
+/** ID of the Reverb reflections level parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_REFLECTIONS_LEVEL 0x000108B4
+/** ID of the Reverb reflections delay parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_REFLECTIONS_DELAY 0x000108B5
+/** ID of the Reverb level parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_LEVEL 0x000108B6
+/** ID of the Reverb delay parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_DELAY 0x000108B7
+/** ID of the Reverb diffusion parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_DIFFUSION 0x000108B8
+/** ID of the Reverb density parameter used by
+ AUDPROC_MODULE_ID_REVERB.
+*/
+#define AUDPROC_PARAM_ID_REVERB_DENSITY 0x000108B9
+
+/** ID of the Popless Equalizer module. This module supports the
+ following parameter IDs:
+ - #AUDPROC_PARAM_ID_EQ_ENABLE
+ - #AUDPROC_PARAM_ID_EQ_CONFIG
+ - #AUDPROC_PARAM_ID_EQ_NUM_BANDS
+ - #AUDPROC_PARAM_ID_EQ_BAND_LEVELS
+ - #AUDPROC_PARAM_ID_EQ_BAND_LEVEL_RANGE
+ - #AUDPROC_PARAM_ID_EQ_BAND_FREQS
+ - #AUDPROC_PARAM_ID_EQ_SINGLE_BAND_FREQ_RANGE
+ - #AUDPROC_PARAM_ID_EQ_SINGLE_BAND_FREQ
+ - #AUDPROC_PARAM_ID_EQ_BAND_INDEX
+ - #AUDPROC_PARAM_ID_EQ_PRESET_ID
+ - #AUDPROC_PARAM_ID_EQ_NUM_PRESETS
+ - #AUDPROC_PARAM_ID_EQ_GET_PRESET_NAME
+*/
+#define AUDPROC_MODULE_ID_POPLESS_EQUALIZER 0x000108BA
+/** ID of the Popless Equalizer enable parameter used by
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER.
+*/
+#define AUDPROC_PARAM_ID_EQ_ENABLE 0x000108BB
+/** ID of the Popless Equalizer config parameter used by
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER.
+*/
+#define AUDPROC_PARAM_ID_EQ_CONFIG 0x000108BC
+/** ID of the Popless Equalizer number of bands parameter used
+ by AUDPROC_MODULE_ID_POPLESS_EQUALIZER. This param ID is
+ used for get param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_NUM_BANDS 0x000108BD
+/** ID of the Popless Equalizer band levels parameter used by
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER. This param ID is
+ used for get param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_BAND_LEVELS 0x000108BE
+/** ID of the Popless Equalizer band level range parameter used
+ by AUDPROC_MODULE_ID_POPLESS_EQUALIZER. This param ID is
+ used for get param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_BAND_LEVEL_RANGE 0x000108BF
+/** ID of the Popless Equalizer band frequencies parameter used
+ by AUDPROC_MODULE_ID_POPLESS_EQUALIZER. This param ID is
+ used for get param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_BAND_FREQS 0x000108C0
+/** ID of the Popless Equalizer single band frequency range
+ parameter used by AUDPROC_MODULE_ID_POPLESS_EQUALIZER.
+ This param ID is used for get param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_SINGLE_BAND_FREQ_RANGE 0x000108C1
+/** ID of the Popless Equalizer single band frequency parameter
+ used by AUDPROC_MODULE_ID_POPLESS_EQUALIZER. This param ID
+ is used for set param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_SINGLE_BAND_FREQ 0x000108C2
+/** ID of the Popless Equalizer band index parameter used by
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER.
+*/
+#define AUDPROC_PARAM_ID_EQ_BAND_INDEX 0x000108C3
+/** ID of the Popless Equalizer preset id parameter used by
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER. This param ID is used
+ for get param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_PRESET_ID 0x000108C4
+/** ID of the Popless Equalizer number of presets parameter used
+ by AUDPROC_MODULE_ID_POPLESS_EQUALIZER. This param ID is used
+ for get param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_NUM_PRESETS 0x000108C5
+/** ID of the Popless Equalizer preset name parameter used by
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER. This param ID is used
+ for get param only.
+*/
+#define AUDPROC_PARAM_ID_EQ_PRESET_NAME 0x000108C6
+
/* Set Q6 topologies */
#define ASM_CMD_ADD_TOPOLOGIES 0x00010DBE
#define ADM_CMD_ADD_TOPOLOGIES 0x00010335
diff --git a/include/sound/audio_effects.h b/include/sound/audio_effects.h
new file mode 100644
index 0000000..3444477
--- /dev/null
+++ b/include/sound/audio_effects.h
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+
+#ifndef _AUDIO_EFFECTS_H
+#define _AUDIO_EFFECTS_H
+
+/** AUDIO EFFECTS **/
+
+
+/* CONFIG GET/SET */
+#define CONFIG_CACHE 0
+#define CONFIG_SET 1
+#define CONFIG_GET 2
+
+/* CONFIG HEADER */
+/*
+
+ MODULE_ID,
+ DEVICE,
+ NUM_COMMANDS,
+ COMMAND_ID_1,
+ CONFIG_CACHE/SET/GET,
+ OFFSET_1,
+ LENGTH_1,
+ VALUES_1,
+ ...,
+ ...,
+ COMMAND_ID_2,
+ CONFIG_CACHE/SET/GET,
+ OFFSET_2,
+ LENGTH_2,
+ VALUES_2,
+ ...,
+ ...,
+ COMMAND_ID_3,
+ ...
+*/
+
+
+/* CONFIG PARAM IDs */
+#define VIRTUALIZER_MODULE 0x00001000
+#define VIRTUALIZER_ENABLE 0x00001001
+#define VIRTUALIZER_STRENGTH 0x00001002
+#define VIRTUALIZER_OUT_TYPE 0x00001003
+#define VIRTUALIZER_GAIN_ADJUST 0x00001004
+#define VIRTUALIZER_ENABLE_PARAM_LEN 1
+#define VIRTUALIZER_STRENGTH_PARAM_LEN 1
+#define VIRTUALIZER_OUT_TYPE_PARAM_LEN 1
+#define VIRTUALIZER_GAIN_ADJUST_PARAM_LEN 1
+
+#define REVERB_MODULE 0x00002000
+#define REVERB_ENABLE 0x00002001
+#define REVERB_MODE 0x00002002
+#define REVERB_PRESET 0x00002003
+#define REVERB_WET_MIX 0x00002004
+#define REVERB_GAIN_ADJUST 0x00002005
+#define REVERB_ROOM_LEVEL 0x00002006
+#define REVERB_ROOM_HF_LEVEL 0x00002007
+#define REVERB_DECAY_TIME 0x00002008
+#define REVERB_DECAY_HF_RATIO 0x00002009
+#define REVERB_REFLECTIONS_LEVEL 0x0000200a
+#define REVERB_REFLECTIONS_DELAY 0x0000200b
+#define REVERB_LEVEL 0x0000200c
+#define REVERB_DELAY 0x0000200d
+#define REVERB_DIFFUSION 0x0000200e
+#define REVERB_DENSITY 0x0000200f
+#define REVERB_ENABLE_PARAM_LEN 1
+#define REVERB_MODE_PARAM_LEN 1
+#define REVERB_PRESET_PARAM_LEN 1
+#define REVERB_WET_MIX_PARAM_LEN 1
+#define REVERB_GAIN_ADJUST_PARAM_LEN 1
+#define REVERB_ROOM_LEVEL_PARAM_LEN 1
+#define REVERB_ROOM_HF_LEVEL_PARAM_LEN 1
+#define REVERB_DECAY_TIME_PARAM_LEN 1
+#define REVERB_DECAY_HF_RATIO_PARAM_LEN 1
+#define REVERB_REFLECTIONS_LEVEL_PARAM_LEN 1
+#define REVERB_REFLECTIONS_DELAY_PARAM_LEN 1
+#define REVERB_LEVEL_PARAM_LEN 1
+#define REVERB_DELAY_PARAM_LEN 1
+#define REVERB_DIFFUSION_PARAM_LEN 1
+#define REVERB_DENSITY_PARAM_LEN 1
+
+#define BASS_BOOST_MODULE 0x00003000
+#define BASS_BOOST_ENABLE 0x00003001
+#define BASS_BOOST_MODE 0x00003002
+#define BASS_BOOST_STRENGTH 0x00003003
+#define BASS_BOOST_ENABLE_PARAM_LEN 1
+#define BASS_BOOST_MODE_PARAM_LEN 1
+#define BASS_BOOST_STRENGTH_PARAM_LEN 1
+
+#define EQ_MODULE 0x00004000
+#define EQ_ENABLE 0x00004001
+#define EQ_CONFIG 0x00004002
+#define EQ_NUM_BANDS 0x00004003
+#define EQ_BAND_LEVELS 0x00004004
+#define EQ_BAND_LEVEL_RANGE 0x00004005
+#define EQ_BAND_FREQS 0x00004006
+#define EQ_SINGLE_BAND_FREQ_RANGE 0x00004007
+#define EQ_SINGLE_BAND_FREQ 0x00004008
+#define EQ_BAND_INDEX 0x00004009
+#define EQ_PRESET_ID 0x0000400a
+#define EQ_NUM_PRESETS 0x0000400b
+#define EQ_PRESET_NAME 0x0000400c
+#define EQ_ENABLE_PARAM_LEN 1
+#define EQ_CONFIG_PARAM_LEN 3
+#define EQ_CONFIG_PER_BAND_PARAM_LEN 5
+#define EQ_NUM_BANDS_PARAM_LEN 1
+#define EQ_BAND_LEVELS_PARAM_LEN 13
+#define EQ_BAND_LEVEL_RANGE_PARAM_LEN 2
+#define EQ_BAND_FREQS_PARAM_LEN 13
+#define EQ_SINGLE_BAND_FREQ_RANGE_PARAM_LEN 2
+#define EQ_SINGLE_BAND_FREQ_PARAM_LEN 1
+#define EQ_BAND_INDEX_PARAM_LEN 1
+#define EQ_PRESET_ID_PARAM_LEN 1
+#define EQ_NUM_PRESETS_PARAM_LEN 1
+#define EQ_PRESET_NAME_PARAM_LEN 32
+
+#define EQ_TYPE_NONE 0
+#define EQ_BASS_BOOST 1
+#define EQ_BASS_CUT 2
+#define EQ_TREBLE_BOOST 3
+#define EQ_TREBLE_CUT 4
+#define EQ_BAND_BOOST 5
+#define EQ_BAND_CUT 6
+
+
+
+#define COMMAND_PAYLOAD_LEN 3
+#define COMMAND_PAYLOAD_SZ (COMMAND_PAYLOAD_LEN * sizeof(uint32_t))
+#define MAX_INBAND_PARAM_SZ 4096
+#define Q27_UNITY (1 << 27)
+#define Q8_UNITY (1 << 8)
+#define CUSTOM_OPENSL_PRESET 18
+
+#define VIRTUALIZER_ENABLE_PARAM_SZ \
+ (VIRTUALIZER_ENABLE_PARAM_LEN*sizeof(uint32_t))
+#define VIRTUALIZER_STRENGTH_PARAM_SZ \
+ (VIRTUALIZER_STRENGTH_PARAM_LEN*sizeof(uint32_t))
+#define VIRTUALIZER_OUT_TYPE_PARAM_SZ \
+ (VIRTUALIZER_OUT_TYPE_PARAM_LEN*sizeof(uint32_t))
+#define VIRTUALIZER_GAIN_ADJUST_PARAM_SZ \
+ (VIRTUALIZER_GAIN_ADJUST_PARAM_LEN*sizeof(uint32_t))
+struct virtualizer_params {
+ uint32_t device;
+ uint32_t enable_flag;
+ uint32_t strength;
+ uint32_t out_type;
+ int32_t gain_adjust;
+};
+
+#define NUM_OSL_REVERB_PRESETS_SUPPORTED 6
+#define REVERB_ENABLE_PARAM_SZ \
+ (REVERB_ENABLE_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_MODE_PARAM_SZ \
+ (REVERB_MODE_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_PRESET_PARAM_SZ \
+ (REVERB_PRESET_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_WET_MIX_PARAM_SZ \
+ (REVERB_WET_MIX_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_GAIN_ADJUST_PARAM_SZ \
+ (REVERB_GAIN_ADJUST_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_ROOM_LEVEL_PARAM_SZ \
+ (REVERB_ROOM_LEVEL_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_ROOM_HF_LEVEL_PARAM_SZ \
+ (REVERB_ROOM_HF_LEVEL_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_DECAY_TIME_PARAM_SZ \
+ (REVERB_DECAY_TIME_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_DECAY_HF_RATIO_PARAM_SZ \
+ (REVERB_DECAY_HF_RATIO_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_REFLECTIONS_LEVEL_PARAM_SZ \
+ (REVERB_REFLECTIONS_LEVEL_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_REFLECTIONS_DELAY_PARAM_SZ \
+ (REVERB_REFLECTIONS_DELAY_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_LEVEL_PARAM_SZ \
+ (REVERB_LEVEL_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_DELAY_PARAM_SZ \
+ (REVERB_DELAY_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_DIFFUSION_PARAM_SZ \
+ (REVERB_DIFFUSION_PARAM_LEN*sizeof(uint32_t))
+#define REVERB_DENSITY_PARAM_SZ \
+ (REVERB_DENSITY_PARAM_LEN*sizeof(uint32_t))
+struct reverb_params {
+ uint32_t device;
+ uint32_t enable_flag;
+ uint32_t mode;
+ uint32_t preset;
+ uint32_t wet_mix;
+ int32_t gain_adjust;
+ int32_t room_level;
+ int32_t room_hf_level;
+ uint32_t decay_time;
+ uint32_t decay_hf_ratio;
+ int32_t reflections_level;
+ uint32_t reflections_delay;
+ int32_t level;
+ uint32_t delay;
+ uint32_t diffusion;
+ uint32_t density;
+};
+
+#define BASS_BOOST_ENABLE_PARAM_SZ \
+ (BASS_BOOST_ENABLE_PARAM_LEN*sizeof(uint32_t))
+#define BASS_BOOST_MODE_PARAM_SZ \
+ (BASS_BOOST_MODE_PARAM_LEN*sizeof(uint32_t))
+#define BASS_BOOST_STRENGTH_PARAM_SZ \
+ (BASS_BOOST_STRENGTH_PARAM_LEN*sizeof(uint32_t))
+struct bass_boost_params {
+ uint32_t device;
+ uint32_t enable_flag;
+ uint32_t mode;
+ uint32_t strength;
+};
+
+
+#define MAX_EQ_BANDS 12
+#define MAX_OSL_EQ_BANDS 5
+#define EQ_ENABLE_PARAM_SZ \
+ (EQ_ENABLE_PARAM_LEN*sizeof(uint32_t))
+#define EQ_CONFIG_PARAM_SZ \
+ (EQ_CONFIG_PARAM_LEN*sizeof(uint32_t))
+#define EQ_CONFIG_PER_BAND_PARAM_SZ \
+ (EQ_CONFIG_PER_BAND_PARAM_LEN*sizeof(uint32_t))
+#define EQ_CONFIG_PARAM_MAX_LEN (EQ_CONFIG_PARAM_LEN+\
+ MAX_EQ_BANDS*EQ_CONFIG_PER_BAND_PARAM_LEN)
+#define EQ_CONFIG_PARAM_MAX_SZ \
+ (EQ_CONFIG_PARAM_MAX_LEN*sizeof(uint32_t))
+#define EQ_NUM_BANDS_PARAM_SZ \
+ (EQ_NUM_BANDS_PARAM_LEN*sizeof(uint32_t))
+#define EQ_BAND_LEVELS_PARAM_SZ \
+ (EQ_BAND_LEVELS_PARAM_LEN*sizeof(uint32_t))
+#define EQ_BAND_LEVEL_RANGE_PARAM_SZ \
+ (EQ_BAND_LEVEL_RANGE_PARAM_LEN*sizeof(uint32_t))
+#define EQ_BAND_FREQS_PARAM_SZ \
+ (EQ_BAND_FREQS_PARAM_LEN*sizeof(uint32_t))
+#define EQ_SINGLE_BAND_FREQ_RANGE_PARAM_SZ \
+ (EQ_SINGLE_BAND_FREQ_RANGE_PARAM_LEN*sizeof(uint32_t))
+#define EQ_SINGLE_BAND_FREQ_PARAM_SZ \
+ (EQ_SINGLE_BAND_FREQ_PARAM_LEN*sizeof(uint32_t))
+#define EQ_BAND_INDEX_PARAM_SZ \
+ (EQ_BAND_INDEX_PARAM_LEN*sizeof(uint32_t))
+#define EQ_PRESET_ID_PARAM_SZ \
+ (EQ_PRESET_ID_PARAM_LEN*sizeof(uint32_t))
+#define EQ_NUM_PRESETS_PARAM_SZ \
+ (EQ_NUM_PRESETS_PARAM_LEN*sizeof(uint8_t))
+struct eq_config_t {
+ int32_t eq_pregain;
+ int32_t preset_id;
+ uint32_t num_bands;
+};
+struct eq_per_band_config_t {
+ int32_t band_idx;
+ uint32_t filter_type;
+ uint32_t freq_millihertz;
+ int32_t gain_millibels;
+ uint32_t quality_factor;
+};
+struct eq_per_band_freq_range_t {
+ uint32_t band_index;
+ uint32_t min_freq_millihertz;
+ uint32_t max_freq_millihertz;
+};
+
+struct eq_params {
+ uint32_t device;
+ uint32_t enable_flag;
+ struct eq_config_t config;
+ struct eq_per_band_config_t per_band_cfg[MAX_EQ_BANDS];
+ struct eq_per_band_freq_range_t per_band_freq_range[MAX_EQ_BANDS];
+ uint32_t band_index;
+ uint32_t freq_millihertz;
+};
+
+#endif /*_MSM_AUDIO_EFFECTS_H*/
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index eb3b41a..9a459b8 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -377,6 +377,9 @@
int q6asm_get_session_time(struct audio_client *ac, uint64_t *tstamp);
+int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
+ uint32_t params_length);
+
/* Client can set the IO mode to either AIO/SIO mode */
int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode);
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 52af21c..55fec32 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -2582,6 +2582,8 @@
*/
{MSM8X10_WCD_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
{MSM8X10_WCD_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+ {MSM8X10_WCD_A_RX_HPH_L_TEST, 0x01, 0x01},
+ {MSM8X10_WCD_A_RX_HPH_R_TEST, 0x01, 0x01},
/* Initialize gain registers to use register gain */
{MSM8X10_WCD_A_RX_HPH_L_GAIN, 0x20, 0x20},
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index ec99c5f..db7a34c 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -90,7 +90,7 @@
#define WCD9XXX_HPHL_STATUS_READY_WAIT_US 1000
#define WCD9XXX_MUX_SWITCH_READY_WAIT_MS 50
-#define WCD9XXX_MEAS_DELTA_MAX_MV 50
+#define WCD9XXX_MEAS_DELTA_MAX_MV 120
#define WCD9XXX_MEAS_INVALD_RANGE_LOW_MV 20
#define WCD9XXX_MEAS_INVALD_RANGE_HIGH_MV 80
@@ -128,7 +128,7 @@
S_IRUGO | S_IWUSR | S_IWGRP);
MODULE_PARM_DESC(impedance_detect_en, "enable/disable impedance detect");
-static bool detect_use_vddio_switch = true;
+static bool detect_use_vddio_switch;
struct wcd9xxx_mbhc_detect {
u16 dce;
@@ -227,7 +227,7 @@
* setup internal micbias if codec uses internal micbias for
* headset detection
*/
- if (mbhc->mbhc_cfg->use_int_rbias && !mbhc->int_rbias_on) {
+ if (mbhc->mbhc_cfg->use_int_rbias) {
if (mbhc->mbhc_cb && mbhc->mbhc_cb->setup_int_rbias)
mbhc->mbhc_cb->setup_int_rbias(codec, true);
else
@@ -841,7 +841,8 @@
mbhc->zl = mbhc->zr = 0;
wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
0, WCD9XXX_JACK_MASK);
- mbhc->hph_status = 0;
+ mbhc->hph_status &= ~(SND_JACK_HEADSET |
+ SND_JACK_LINEOUT);
}
/* Report insertion */
mbhc->hph_status |= jack_type;
@@ -972,7 +973,9 @@
if (noreldetection)
wcd9xxx_turn_onoff_rel_detection(codec, false);
- snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x0);
+ if (mbhc->mbhc_cfg->do_recalibration)
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2,
+ 0x0);
/* Turn on the override */
if (!override_bypass)
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
@@ -982,8 +985,9 @@
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
0x0);
- snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2,
- 0x2);
+ if (mbhc->mbhc_cfg->do_recalibration)
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL,
+ 0x2, 0x2);
usleep_range(mbhc->mbhc_data.t_sta_dce,
mbhc->mbhc_data.t_sta_dce);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4);
@@ -995,8 +999,9 @@
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
0x0);
- snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2,
- 0x2);
+ if (mbhc->mbhc_cfg->do_recalibration)
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL,
+ 0x2, 0x2);
usleep_range(mbhc->mbhc_data.t_sta_dce,
mbhc->mbhc_data.t_sta_dce);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
@@ -1103,7 +1108,7 @@
* setup internal micbias if codec uses internal micbias for
* headset detection
*/
- if (mbhc->mbhc_cfg->use_int_rbias && !mbhc->int_rbias_on) {
+ if (mbhc->mbhc_cfg->use_int_rbias) {
if (mbhc->mbhc_cb && mbhc->mbhc_cb->setup_int_rbias)
mbhc->mbhc_cb->setup_int_rbias(codec, true);
else
@@ -1140,48 +1145,59 @@
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ if (!mbhc->mbhc_cfg->do_recalibration) {
+ if (!is_cs_enable)
+ wcd9xxx_calibrate_hs_polling(mbhc);
+ }
+
/* don't flip override */
bias_value = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
snd_soc_write(codec, mbhc->mbhc_bias_regs.cfilt_ctl, cfilt_mode);
snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
- /* recalibrate dce_z and sta_z */
- reg = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_CTL);
- change = snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x78,
- btn_det->mbhc_nsc << 3);
- wcd9xxx_get_z(mbhc, &dce_z, &sta_z);
- if (change)
- snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, reg);
- if (dce_z && sta_z) {
- pr_debug("%s: sta_z 0x%x -> 0x%x, dce_z 0x%x -> 0x%x\n",
- __func__,
- mbhc->mbhc_data.sta_z, sta_z & 0xffff,
- mbhc->mbhc_data.dce_z, dce_z & 0xffff);
- mbhc->mbhc_data.dce_z = dce_z;
- mbhc->mbhc_data.sta_z = sta_z;
- wcd9xxx_mbhc_calc_thres(mbhc);
- wcd9xxx_calibrate_hs_polling(mbhc);
- } else {
- pr_warn("%s: failed get new dce_z/sta_z 0x%x/0x%x\n", __func__,
- dce_z, sta_z);
- }
-
- if (is_cs_enable) {
- /* recalibrate dce_nsc_cs_z */
- reg = snd_soc_read(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL);
- snd_soc_update_bits(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
- 0x78, WCD9XXX_MBHC_NSC_CS << 3);
- wcd9xxx_get_z(mbhc, &dce_z, NULL);
- snd_soc_write(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL, reg);
- if (dce_z) {
- pr_debug("%s: dce_nsc_cs_z 0x%x -> 0x%x\n", __func__,
- mbhc->mbhc_data.dce_nsc_cs_z, dce_z & 0xffff);
- mbhc->mbhc_data.dce_nsc_cs_z = dce_z;
+ if (mbhc->mbhc_cfg->do_recalibration) {
+ /* recalibrate dce_z and sta_z */
+ reg = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_CTL);
+ change = snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
+ 0x78, btn_det->mbhc_nsc << 3);
+ wcd9xxx_get_z(mbhc, &dce_z, &sta_z);
+ if (change)
+ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, reg);
+ if (dce_z && sta_z) {
+ pr_debug("%s: sta_z 0x%x -> 0x%x, dce_z 0x%x -> 0x%x\n",
+ __func__,
+ mbhc->mbhc_data.sta_z, sta_z & 0xffff,
+ mbhc->mbhc_data.dce_z, dce_z & 0xffff);
+ mbhc->mbhc_data.dce_z = dce_z;
+ mbhc->mbhc_data.sta_z = sta_z;
+ wcd9xxx_mbhc_calc_thres(mbhc);
+ wcd9xxx_calibrate_hs_polling(mbhc);
} else {
- pr_debug("%s: failed get new dce_nsc_cs_z\n", __func__);
+ pr_warn("%s: failed get new dce_z/sta_z 0x%x/0x%x\n",
+ __func__, dce_z, sta_z);
+ }
+
+ if (is_cs_enable) {
+ /* recalibrate dce_nsc_cs_z */
+ reg = snd_soc_read(mbhc->codec,
+ WCD9XXX_A_CDC_MBHC_B1_CTL);
+ snd_soc_update_bits(mbhc->codec,
+ WCD9XXX_A_CDC_MBHC_B1_CTL,
+ 0x78, WCD9XXX_MBHC_NSC_CS << 3);
+ wcd9xxx_get_z(mbhc, &dce_z, NULL);
+ snd_soc_write(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
+ reg);
+ if (dce_z) {
+ pr_debug("%s: dce_nsc_cs_z 0x%x -> 0x%x\n",
+ __func__, mbhc->mbhc_data.dce_nsc_cs_z,
+ dce_z & 0xffff);
+ mbhc->mbhc_data.dce_nsc_cs_z = dce_z;
+ } else {
+ pr_debug("%s: failed get new dce_nsc_cs_z\n",
+ __func__);
+ }
}
}
-
return bias_value;
}
@@ -1751,6 +1767,7 @@
/* GND and MIC swap detection requires at least 2 rounds of DCE */
BUG_ON(NUM_DCE_PLUG_INS_DETECT < 2);
+ detect_use_vddio_switch = mbhc->mbhc_cfg->use_vddio_meas;
/*
* There are chances vddio switch is on and cfilt voltage is adjusted
@@ -3188,7 +3205,7 @@
* setup internal micbias if codec uses internal micbias for
* headset detection
*/
- if (mbhc->mbhc_cfg->use_int_rbias && !mbhc->int_rbias_on) {
+ if (mbhc->mbhc_cfg->use_int_rbias) {
if (mbhc->mbhc_cb && mbhc->mbhc_cb->setup_int_rbias)
mbhc->mbhc_cb->setup_int_rbias(codec, true);
else
@@ -4019,7 +4036,6 @@
if (mbhc->mbhc_cfg->use_int_rbias) {
if (mbhc->mbhc_cb && mbhc->mbhc_cb->setup_int_rbias) {
mbhc->mbhc_cb->setup_int_rbias(codec, true);
- mbhc->int_rbias_on = true;
} else {
pr_info("%s: internal bias requested but codec did not provide callback\n",
__func__);
@@ -4178,7 +4194,6 @@
case WCD9XXX_EVENT_PRE_MICBIAS_2_ON:
case WCD9XXX_EVENT_PRE_MICBIAS_3_ON:
case WCD9XXX_EVENT_PRE_MICBIAS_4_ON:
- mbhc->int_rbias_on = true;
if (mbhc->mbhc_cfg && mbhc->mbhc_cfg->micbias ==
wcd9xxx_event_to_micbias(event)) {
wcd9xxx_switch_micbias(mbhc, 0);
@@ -4206,7 +4221,6 @@
case WCD9XXX_EVENT_POST_MICBIAS_2_OFF:
case WCD9XXX_EVENT_POST_MICBIAS_3_OFF:
case WCD9XXX_EVENT_POST_MICBIAS_4_OFF:
- mbhc->int_rbias_on = false;
if (mbhc->mbhc_cfg && mbhc->mbhc_cfg->micbias ==
wcd9xxx_event_to_micbias(event)) {
if (mbhc->event_state &
@@ -4502,7 +4516,6 @@
mbhc->mbhc_cb = mbhc_cb;
mbhc->intr_ids = mbhc_cdc_intr_ids;
mbhc->impedance_detect = impedance_det_en;
- mbhc->int_rbias_on = false;
if (mbhc->intr_ids == NULL) {
pr_err("%s: Interrupt mapping not provided\n", __func__);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 7fe9538..29dd84a 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -228,6 +228,8 @@
bool (*swap_gnd_mic) (struct snd_soc_codec *);
unsigned long cs_enable_flags;
bool use_int_rbias;
+ bool do_recalibration;
+ bool use_vddio_meas;
};
struct wcd9xxx_cfilt_mode {
@@ -336,7 +338,6 @@
u32 rco_clk_rate;
bool update_z;
- bool int_rbias_on;
/* Holds codec specific interrupt mapping */
const struct wcd9xxx_mbhc_intr *intr_ids;
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.c b/sound/soc/codecs/wcd9xxx-resmgr.c
index 5d74469..6a22ff2 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr.c
@@ -561,8 +561,15 @@
if (--resmgr->clk_rco_users == 0 &&
resmgr->clk_type == WCD9XXX_CLK_RCO) {
wcd9xxx_disable_clock_block(resmgr);
- snd_soc_update_bits(resmgr->codec,
- WCD9XXX_A_RC_OSC_FREQ, 0x80, 0x00);
+ /* if RCO is enabled, switch from it */
+ if (snd_soc_read(resmgr->codec, WCD9XXX_A_RC_OSC_FREQ)
+ & 0x80) {
+ if (resmgr->codec_type !=
+ WCD9XXX_CDC_TYPE_HELICON)
+ snd_soc_write(resmgr->codec,
+ WCD9XXX_A_CLK_BUFF_EN2, 0x02);
+ wcd9xxx_resmgr_enable_config_mode(resmgr, 0);
+ }
resmgr->clk_type = WCD9XXX_CLK_OFF;
}
break;
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index c25a460..ceea3d2 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -94,6 +94,8 @@
.cs_enable_flags = (1 << MBHC_CS_ENABLE_POLLING |
1 << MBHC_CS_ENABLE_INSERTION |
1 << MBHC_CS_ENABLE_REMOVAL),
+ .do_recalibration = true,
+ .use_vddio_meas = true,
};
struct msm_auxpcm_gpio {
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index b34750a..c120e0c 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -129,6 +129,8 @@
.cs_enable_flags = (1 << MBHC_CS_ENABLE_POLLING |
1 << MBHC_CS_ENABLE_INSERTION |
1 << MBHC_CS_ENABLE_REMOVAL),
+ .do_recalibration = true,
+ .use_vddio_meas = true,
};
struct msm_auxpcm_gpio {
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index d9af6f3..408ec03 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -102,6 +102,8 @@
.cs_enable_flags = (1 << MBHC_CS_ENABLE_POLLING |
1 << MBHC_CS_ENABLE_INSERTION |
1 << MBHC_CS_ENABLE_REMOVAL),
+ .do_recalibration = false,
+ .use_vddio_meas = false,
};
/*
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 5aa84a0..ea16f47 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -3,7 +3,7 @@
msm-multi-ch-pcm-q6-v2.o msm-pcm-lpa-v2.o \
msm-pcm-afe-v2.o msm-pcm-voip-v2.o \
msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o \
- msm-lsm-client.o
+ msm-lsm-client.o msm-audio-effects-q6-v2.o
obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \
msm-dai-stub-v2.o
obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o
diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
new file mode 100644
index 0000000..5e4d9d3
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c
@@ -0,0 +1,721 @@
+/* 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.
+ */
+
+#include <linux/slab.h>
+#include <sound/apr_audio-v2.h>
+#include <sound/q6asm-v2.h>
+#include <sound/compress_params.h>
+#include "msm-audio-effects-q6-v2.h"
+
+int msm_audio_effects_virtualizer_handler(struct audio_client *ac,
+ struct virtualizer_params *virtualizer,
+ long *values)
+{
+ int devices = *values++;
+ int num_commands = *values++;
+ char *params;
+ int *updt_params, i, prev_enable_flag;
+ uint32_t params_length = (MAX_INBAND_PARAM_SZ);
+ int rc = 0;
+
+ pr_debug("%s\n", __func__);
+ if (!ac) {
+ pr_err("%s: cannot set audio effects\n", __func__);
+ return -EINVAL;
+ }
+ params = kzalloc(params_length, GFP_KERNEL);
+ if (!params) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ pr_debug("%s: device: %d\n", __func__, devices);
+ updt_params = (int *)params;
+ params_length = 0;
+ for (i = 0; i < num_commands; i++) {
+ uint32_t command_id = *values++;
+ uint32_t command_config_state = *values++;
+ uint32_t index_offset = *values++;
+ uint32_t length = *values++;
+ switch (command_id) {
+ case VIRTUALIZER_ENABLE:
+ pr_debug("%s: VIRTUALIZER_ENABLE\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ prev_enable_flag = virtualizer->enable_flag;
+ virtualizer->enable_flag = *values++;
+ if (prev_enable_flag != virtualizer->enable_flag) {
+ *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_VIRTUALIZER_ENABLE;
+ *updt_params++ = VIRTUALIZER_ENABLE_PARAM_SZ;
+ *updt_params++ = virtualizer->enable_flag;
+ params_length += COMMAND_PAYLOAD_SZ +
+ VIRTUALIZER_ENABLE_PARAM_SZ;
+ }
+ break;
+ case VIRTUALIZER_STRENGTH:
+ pr_debug("%s: VIRTUALIZER_STRENGTH\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ virtualizer->strength = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_VIRTUALIZER_STRENGTH;
+ *updt_params++ = VIRTUALIZER_STRENGTH_PARAM_SZ;
+ *updt_params++ = virtualizer->strength;
+ params_length += COMMAND_PAYLOAD_SZ +
+ VIRTUALIZER_STRENGTH_PARAM_SZ;
+ }
+ break;
+ case VIRTUALIZER_OUT_TYPE:
+ pr_debug("%s: VIRTUALIZER_OUT_TYPE\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ virtualizer->out_type = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_VIRTUALIZER_OUT_TYPE;
+ *updt_params++ = VIRTUALIZER_OUT_TYPE_PARAM_SZ;
+ *updt_params++ = virtualizer->out_type;
+ params_length += COMMAND_PAYLOAD_SZ +
+ VIRTUALIZER_OUT_TYPE_PARAM_SZ;
+ }
+ break;
+ case VIRTUALIZER_GAIN_ADJUST:
+ pr_debug("%s: VIRTUALIZER_GAIN_ADJUST\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ virtualizer->gain_adjust = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_VIRTUALIZER_GAIN_ADJUST;
+ *updt_params++ =
+ VIRTUALIZER_GAIN_ADJUST_PARAM_SZ;
+ *updt_params++ = virtualizer->gain_adjust;
+ params_length += COMMAND_PAYLOAD_SZ +
+ VIRTUALIZER_GAIN_ADJUST_PARAM_SZ;
+ }
+ break;
+ default:
+ pr_err("%s: Invalid command to set config\n", __func__);
+ break;
+ }
+ }
+ if (params_length)
+ q6asm_send_audio_effects_params(ac, params,
+ params_length);
+invalid_config:
+ kfree(params);
+ return rc;
+}
+
+int msm_audio_effects_reverb_handler(struct audio_client *ac,
+ struct reverb_params *reverb,
+ long *values)
+{
+ int devices = *values++;
+ int num_commands = *values++;
+ char *params;
+ int *updt_params, i, prev_enable_flag;
+ uint32_t params_length = (MAX_INBAND_PARAM_SZ);
+ int rc = 0;
+
+ pr_debug("%s\n", __func__);
+ if (!ac) {
+ pr_err("%s: cannot set audio effects\n", __func__);
+ return -EINVAL;
+ }
+ params = kzalloc(params_length, GFP_KERNEL);
+ if (!params) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ pr_debug("%s: device: %d\n", __func__, devices);
+ updt_params = (int *)params;
+ params_length = 0;
+ for (i = 0; i < num_commands; i++) {
+ uint32_t command_id = *values++;
+ uint32_t command_config_state = *values++;
+ uint32_t index_offset = *values++;
+ uint32_t length = *values++;
+ switch (command_id) {
+ case REVERB_ENABLE:
+ pr_debug("%s: REVERB_ENABLE\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ prev_enable_flag = reverb->enable_flag;
+ reverb->enable_flag = *values++;
+ if (prev_enable_flag != reverb->enable_flag) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ = AUDPROC_PARAM_ID_REVERB_ENABLE;
+ *updt_params++ = REVERB_ENABLE_PARAM_SZ;
+ *updt_params++ = reverb->enable_flag;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_ENABLE_PARAM_SZ;
+ }
+ break;
+ case REVERB_MODE:
+ pr_debug("%s: REVERB_MODE\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->mode = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ = AUDPROC_PARAM_ID_REVERB_MODE;
+ *updt_params++ = REVERB_MODE_PARAM_SZ;
+ *updt_params++ = reverb->mode;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_MODE_PARAM_SZ;
+ }
+ break;
+ case REVERB_PRESET:
+ pr_debug("%s: REVERB_PRESET\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->preset = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ = AUDPROC_PARAM_ID_REVERB_PRESET;
+ *updt_params++ = REVERB_PRESET_PARAM_SZ;
+ *updt_params++ = reverb->preset;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_PRESET_PARAM_SZ;
+ }
+ break;
+ case REVERB_WET_MIX:
+ pr_debug("%s: REVERB_WET_MIX\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->wet_mix = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_WET_MIX;
+ *updt_params++ = REVERB_WET_MIX_PARAM_SZ;
+ *updt_params++ = reverb->wet_mix;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_WET_MIX_PARAM_SZ;
+ }
+ break;
+ case REVERB_GAIN_ADJUST:
+ pr_debug("%s: REVERB_GAIN_ADJUST\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->gain_adjust = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_GAIN_ADJUST;
+ *updt_params++ = REVERB_GAIN_ADJUST_PARAM_SZ;
+ *updt_params++ = reverb->gain_adjust;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_GAIN_ADJUST_PARAM_SZ;
+ }
+ break;
+ case REVERB_ROOM_LEVEL:
+ pr_debug("%s: REVERB_ROOM_LEVEL\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->room_level = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_ROOM_LEVEL;
+ *updt_params++ = REVERB_ROOM_LEVEL_PARAM_SZ;
+ *updt_params++ = reverb->room_level;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_ROOM_LEVEL_PARAM_SZ;
+ }
+ break;
+ case REVERB_ROOM_HF_LEVEL:
+ pr_debug("%s: REVERB_ROOM_HF_LEVEL\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->room_hf_level = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_ROOM_HF_LEVEL;
+ *updt_params++ = REVERB_ROOM_HF_LEVEL_PARAM_SZ;
+ *updt_params++ = reverb->room_hf_level;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_ROOM_HF_LEVEL_PARAM_SZ;
+ }
+ break;
+ case REVERB_DECAY_TIME:
+ pr_debug("%s: REVERB_DECAY_TIME\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->decay_time = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_DECAY_TIME;
+ *updt_params++ = REVERB_DECAY_TIME_PARAM_SZ;
+ *updt_params++ = reverb->decay_time;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_DECAY_TIME_PARAM_SZ;
+ }
+ break;
+ case REVERB_DECAY_HF_RATIO:
+ pr_debug("%s: REVERB_DECAY_HF_RATIO\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->decay_hf_ratio = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_DECAY_HF_RATIO;
+ *updt_params++ = REVERB_DECAY_HF_RATIO_PARAM_SZ;
+ *updt_params++ = reverb->decay_hf_ratio;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_DECAY_HF_RATIO_PARAM_SZ;
+ }
+ break;
+ case REVERB_REFLECTIONS_LEVEL:
+ pr_debug("%s: REVERB_REFLECTIONS_LEVEL\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->reflections_level = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_REFLECTIONS_LEVEL;
+ *updt_params++ =
+ REVERB_REFLECTIONS_LEVEL_PARAM_SZ;
+ *updt_params++ = reverb->reflections_level;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_REFLECTIONS_LEVEL_PARAM_SZ;
+ }
+ break;
+ case REVERB_REFLECTIONS_DELAY:
+ pr_debug("%s: REVERB_REFLECTIONS_DELAY\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->reflections_delay = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_REFLECTIONS_DELAY;
+ *updt_params++ =
+ REVERB_REFLECTIONS_DELAY_PARAM_SZ;
+ *updt_params++ = reverb->reflections_delay;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_REFLECTIONS_DELAY_PARAM_SZ;
+ }
+ break;
+ case REVERB_LEVEL:
+ pr_debug("%s: REVERB_LEVEL\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->level = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ = AUDPROC_PARAM_ID_REVERB_LEVEL;
+ *updt_params++ = REVERB_LEVEL_PARAM_SZ;
+ *updt_params++ = reverb->level;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_LEVEL_PARAM_SZ;
+ }
+ break;
+ case REVERB_DELAY:
+ pr_debug("%s: REVERB_DELAY\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->delay = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ = AUDPROC_PARAM_ID_REVERB_DELAY;
+ *updt_params++ = REVERB_DELAY_PARAM_SZ;
+ *updt_params++ = reverb->delay;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_DELAY_PARAM_SZ;
+ }
+ break;
+ case REVERB_DIFFUSION:
+ pr_debug("%s: REVERB_DIFFUSION\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->diffusion = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_DIFFUSION;
+ *updt_params++ = REVERB_DIFFUSION_PARAM_SZ;
+ *updt_params++ = reverb->diffusion;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_DIFFUSION_PARAM_SZ;
+ }
+ break;
+ case REVERB_DENSITY:
+ pr_debug("%s: REVERB_DENSITY\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ reverb->density = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_REVERB;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_REVERB_DENSITY;
+ *updt_params++ = REVERB_DENSITY_PARAM_SZ;
+ *updt_params++ = reverb->density;
+ params_length += COMMAND_PAYLOAD_SZ +
+ REVERB_DENSITY_PARAM_SZ;
+ }
+ break;
+ default:
+ pr_err("%s: Invalid command to set config\n", __func__);
+ break;
+ }
+ }
+ if (params_length)
+ q6asm_send_audio_effects_params(ac, params,
+ params_length);
+invalid_config:
+ kfree(params);
+ return rc;
+}
+
+int msm_audio_effects_bass_boost_handler(struct audio_client *ac,
+ struct bass_boost_params *bass_boost,
+ long *values)
+{
+ int devices = *values++;
+ int num_commands = *values++;
+ char *params;
+ int *updt_params, i, prev_enable_flag;
+ uint32_t params_length = (MAX_INBAND_PARAM_SZ);
+ int rc = 0;
+
+ pr_debug("%s\n", __func__);
+ if (!ac) {
+ pr_err("%s: cannot set audio effects\n", __func__);
+ return -EINVAL;
+ }
+ params = kzalloc(params_length, GFP_KERNEL);
+ if (!params) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ pr_debug("%s: device: %d\n", __func__, devices);
+ updt_params = (int *)params;
+ params_length = 0;
+ for (i = 0; i < num_commands; i++) {
+ uint32_t command_id = *values++;
+ uint32_t command_config_state = *values++;
+ uint32_t index_offset = *values++;
+ uint32_t length = *values++;
+ switch (command_id) {
+ case BASS_BOOST_ENABLE:
+ pr_debug("%s: BASS_BOOST_ENABLE\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ prev_enable_flag = bass_boost->enable_flag;
+ bass_boost->enable_flag = *values++;
+ if (prev_enable_flag != bass_boost->enable_flag) {
+ *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_BASS_BOOST_ENABLE;
+ *updt_params++ = BASS_BOOST_ENABLE_PARAM_SZ;
+ *updt_params++ = bass_boost->enable_flag;
+ params_length += COMMAND_PAYLOAD_SZ +
+ BASS_BOOST_ENABLE_PARAM_SZ;
+ }
+ break;
+ case BASS_BOOST_MODE:
+ pr_debug("%s: BASS_BOOST_MODE\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ bass_boost->mode = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_BASS_BOOST_MODE;
+ *updt_params++ = BASS_BOOST_MODE_PARAM_SZ;
+ *updt_params++ = bass_boost->mode;
+ params_length += COMMAND_PAYLOAD_SZ +
+ BASS_BOOST_MODE_PARAM_SZ;
+ }
+ break;
+ case BASS_BOOST_STRENGTH:
+ pr_debug("%s: BASS_BOOST_STRENGTH\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ bass_boost->strength = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_BASS_BOOST_STRENGTH;
+ *updt_params++ = BASS_BOOST_STRENGTH_PARAM_SZ;
+ *updt_params++ = bass_boost->strength;
+ params_length += COMMAND_PAYLOAD_SZ +
+ BASS_BOOST_STRENGTH_PARAM_SZ;
+ }
+ break;
+ default:
+ pr_err("%s: Invalid command to set config\n", __func__);
+ break;
+ }
+ }
+ if (params_length)
+ q6asm_send_audio_effects_params(ac, params,
+ params_length);
+invalid_config:
+ kfree(params);
+ return rc;
+}
+
+int msm_audio_effects_popless_eq_handler(struct audio_client *ac,
+ struct eq_params *eq,
+ long *values)
+{
+ int devices = *values++;
+ int num_commands = *values++;
+ char *params;
+ int *updt_params, i, prev_enable_flag;
+ uint32_t params_length = (MAX_INBAND_PARAM_SZ);
+ int rc = 0;
+
+ pr_debug("%s\n", __func__);
+ if (!ac) {
+ pr_err("%s: cannot set audio effects\n", __func__);
+ return -EINVAL;
+ }
+ params = kzalloc(params_length, GFP_KERNEL);
+ if (!params) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ pr_debug("%s: device: %d\n", __func__, devices);
+ updt_params = (int *)params;
+ params_length = 0;
+ for (i = 0; i < num_commands; i++) {
+ uint32_t command_id = *values++;
+ uint32_t command_config_state = *values++;
+ uint32_t index_offset = *values++;
+ uint32_t length = *values++;
+ int idx, j;
+ switch (command_id) {
+ case EQ_ENABLE:
+ pr_debug("%s: EQ_ENABLE\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ prev_enable_flag = eq->enable_flag;
+ eq->enable_flag = *values++;
+ pr_debug("%s: prev_enable_flag : %d, eq.enable_flag : %d",
+ __func__, prev_enable_flag, eq->enable_flag);
+ if (prev_enable_flag != eq->enable_flag) {
+ *updt_params++ =
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER;
+ *updt_params++ = AUDPROC_PARAM_ID_EQ_ENABLE;
+ *updt_params++ = EQ_ENABLE_PARAM_SZ;
+ *updt_params++ = eq->enable_flag;
+ params_length += COMMAND_PAYLOAD_SZ +
+ EQ_ENABLE_PARAM_SZ;
+ }
+ break;
+ case EQ_CONFIG:
+ pr_debug("%s: EQ_CONFIG\n", __func__);
+ if (length < EQ_CONFIG_PARAM_LEN || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ for (idx = 0; idx < MAX_EQ_BANDS; idx++)
+ eq->per_band_cfg[idx].band_idx = -1;
+ eq->config.eq_pregain = *values++;
+ eq->config.preset_id = *values++;
+ eq->config.num_bands = *values++;
+ if (eq->config.num_bands > MAX_EQ_BANDS) {
+ pr_err("invalid num of bands\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ if (eq->config.num_bands &&
+ (((length - EQ_CONFIG_PARAM_LEN)/
+ EQ_CONFIG_PER_BAND_PARAM_LEN)
+ != eq->config.num_bands)) {
+ pr_err("invalid length to set config per band\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ for (j = 0; j < eq->config.num_bands; j++) {
+ idx = *values++;
+ eq->per_band_cfg[idx].band_idx = idx;
+ eq->per_band_cfg[idx].filter_type = *values++;
+ eq->per_band_cfg[idx].freq_millihertz =
+ *values++;
+ eq->per_band_cfg[idx].gain_millibels =
+ *values++;
+ eq->per_band_cfg[idx].quality_factor =
+ *values++;
+ }
+ if (command_config_state == CONFIG_SET) {
+ int config_param_length = EQ_CONFIG_PARAM_SZ +
+ (EQ_CONFIG_PER_BAND_PARAM_SZ*
+ eq->config.num_bands);
+ *updt_params++ =
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER;
+ *updt_params++ = AUDPROC_PARAM_ID_EQ_CONFIG;
+ *updt_params++ = config_param_length;
+ *updt_params++ = eq->config.eq_pregain;
+ *updt_params++ = eq->config.preset_id;
+ *updt_params++ = eq->config.num_bands;
+ for (idx = 0; idx < MAX_EQ_BANDS; idx++) {
+ if (eq->per_band_cfg[idx].band_idx < 0)
+ continue;
+ *updt_params++ =
+ eq->per_band_cfg[idx].filter_type;
+ *updt_params++ =
+ eq->per_band_cfg[idx].freq_millihertz;
+ *updt_params++ =
+ eq->per_band_cfg[idx].gain_millibels;
+ *updt_params++ =
+ eq->per_band_cfg[idx].quality_factor;
+ *updt_params++ =
+ eq->per_band_cfg[idx].band_idx;
+ }
+ params_length += COMMAND_PAYLOAD_SZ +
+ config_param_length;
+ }
+ break;
+ case EQ_BAND_INDEX:
+ pr_debug("%s: EQ_BAND_INDEX\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ idx = *values++;
+ if (idx > MAX_EQ_BANDS) {
+ pr_err("invalid band index\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ eq->band_index = idx;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ =
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_EQ_BAND_INDEX;
+ *updt_params++ = EQ_BAND_INDEX_PARAM_SZ;
+ *updt_params++ = eq->band_index;
+ params_length += COMMAND_PAYLOAD_SZ +
+ EQ_BAND_INDEX_PARAM_SZ;
+ }
+ break;
+ case EQ_SINGLE_BAND_FREQ:
+ pr_debug("%s: EQ_SINGLE_BAND_FREQ\n", __func__);
+ if (length != 1 || index_offset != 0) {
+ pr_err("no valid params\n");
+ rc = -EINVAL;
+ goto invalid_config;
+ }
+ if (eq->band_index > MAX_EQ_BANDS) {
+ pr_err("invalid band index to set frequency\n");
+ break;
+ }
+ eq->freq_millihertz = *values++;
+ if (command_config_state == CONFIG_SET) {
+ *updt_params++ =
+ AUDPROC_MODULE_ID_POPLESS_EQUALIZER;
+ *updt_params++ =
+ AUDPROC_PARAM_ID_EQ_SINGLE_BAND_FREQ;
+ *updt_params++ = EQ_SINGLE_BAND_FREQ_PARAM_SZ;
+ *updt_params++ = eq->freq_millihertz;
+ params_length += COMMAND_PAYLOAD_SZ +
+ EQ_SINGLE_BAND_FREQ_PARAM_SZ;
+ }
+ break;
+ default:
+ pr_err("%s: Invalid command to set config\n", __func__);
+ break;
+ }
+ }
+ if (params_length)
+ q6asm_send_audio_effects_params(ac, params,
+ params_length);
+invalid_config:
+ kfree(params);
+ return rc;
+}
diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.h
new file mode 100644
index 0000000..3d2e6d4
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef _MSM_AUDIO_EFFECTS_H
+#define _MSM_AUDIO_EFFECTS_H
+
+#include <sound/audio_effects.h>
+
+int msm_audio_effects_reverb_handler(struct audio_client *ac,
+ struct reverb_params *reverb,
+ long *values);
+
+int msm_audio_effects_bass_boost_handler(struct audio_client *ac,
+ struct bass_boost_params *bass_boost,
+ long *values);
+int msm_audio_effects_virtualizer_handler(struct audio_client *ac,
+ struct virtualizer_params *virtualizer,
+ long *values);
+
+int msm_audio_effects_popless_eq_handler(struct audio_client *ac,
+ struct eq_params *eq,
+ long *values);
+#endif /*_MSM_AUDIO_EFFECTS_H*/
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 55d50ed..7935100 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -43,6 +43,7 @@
#include "msm-pcm-routing-v2.h"
#include "audio_ocmem.h"
+#include "msm-audio-effects-q6-v2.h"
#define DSP_PP_BUFFERING_IN_MSEC 25
#define PARTIAL_DRAIN_ACK_EARLY_BY_MSEC 150
@@ -71,6 +72,7 @@
atomic_t audio_ocmem_req;
struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
uint32_t volume[MSM_FRONTEND_DAI_MAX][2]; /* For both L & R */
+ struct msm_compr_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX];
};
struct msm_compr_audio {
@@ -109,6 +111,7 @@
atomic_t xrun;
atomic_t close;
atomic_t wait_on_close;
+ atomic_t error;
wait_queue_head_t eos_wait;
wait_queue_head_t drain_wait;
@@ -118,6 +121,13 @@
spinlock_t lock;
};
+struct msm_compr_audio_effects {
+ struct bass_boost_params bass_boost;
+ struct virtualizer_params virtualizer;
+ struct reverb_params reverb;
+ struct eq_params equalizer;
+};
+
static int msm_compr_set_volume(struct snd_compr_stream *cstream,
uint32_t volume_l, uint32_t volume_r)
{
@@ -164,17 +174,11 @@
pr_debug("%s: bytes_received = %d copied_total = %d\n",
__func__, prtd->bytes_received, prtd->copied_total);
- /*
- * FIXME: Initial and trailing silence removal API call to DSP results
- * to a glitch during the stream transition for gapless playback.
- * Add this when the issue is fixed from DSP.
- */
-/*
if (prtd->first_buffer)
q6asm_send_meta_data(prtd->audio_client,
prtd->gapless_state.initial_samples_drop,
prtd->gapless_state.trailing_samples_drop);
-*/
+
buffer_length = prtd->codec_param.buffer.fragment_size;
bytes_available = prtd->bytes_received - prtd->copied_total;
if (bytes_available < prtd->codec_param.buffer.fragment_size)
@@ -354,6 +358,14 @@
case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3:
pr_debug("ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3\n");
break;
+ case RESET_EVENTS:
+ pr_err("Received reset events CB, move to error state");
+ spin_lock(&prtd->lock);
+ snd_compr_fragment_elapsed(cstream);
+ prtd->copied_total = prtd->bytes_received;
+ atomic_set(&prtd->error, 1);
+ spin_unlock(&prtd->lock);
+ break;
default:
pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
break;
@@ -514,10 +526,18 @@
prtd->cstream = cstream;
pdata->cstream[rtd->dai_link->be_id] = cstream;
+ pdata->audio_effects[rtd->dai_link->be_id] =
+ kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
+ if (!pdata->audio_effects[rtd->dai_link->be_id]) {
+ pr_err("%s: Could not allocate memory for effects\n", __func__);
+ kfree(prtd);
+ return -ENOMEM;
+ }
prtd->audio_client = q6asm_audio_client_alloc(
(app_cb)compr_event_handler, prtd);
if (!prtd->audio_client) {
- pr_err("%s: Could not allocate memory\n", __func__);
+ pr_err("%s: Could not allocate memory for client\n", __func__);
+ kfree(pdata->audio_effects[rtd->dai_link->be_id]);
kfree(prtd);
return -ENOMEM;
}
@@ -545,6 +565,7 @@
atomic_set(&prtd->xrun, 0);
atomic_set(&prtd->close, 0);
atomic_set(&prtd->wait_on_close, 0);
+ atomic_set(&prtd->error, 0);
init_waitqueue_head(&prtd->eos_wait);
init_waitqueue_head(&prtd->drain_wait);
@@ -629,6 +650,7 @@
q6asm_audio_client_free(ac);
+ kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]);
kfree(prtd);
return 0;
@@ -759,6 +781,14 @@
return -EINVAL;
}
+ spin_lock_irqsave(&prtd->lock, flags);
+ if (atomic_read(&prtd->error)) {
+ pr_err("%s Got RESET EVENTS notification, return immediately", __func__);
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&prtd->lock, flags);
+
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
@@ -1072,6 +1102,15 @@
tstamp.byte_offset = prtd->byte_offset;
tstamp.copied_total = prtd->copied_total;
first_buffer = prtd->first_buffer;
+
+ if (atomic_read(&prtd->error)) {
+ pr_err("%s Got RESET EVENTS notification, return error", __func__);
+ tstamp.pcm_io_frames = 0;
+ memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ return -EINVAL;
+ }
+
spin_unlock_irqrestore(&prtd->lock, flags);
/*
@@ -1160,6 +1199,14 @@
return 0;
}
+ spin_lock_irqsave(&prtd->lock, flags);
+ if (atomic_read(&prtd->error)) {
+ pr_err("%s Got RESET EVENTS notification", __func__);
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ return -EINVAL;
+ }
+ spin_unlock_irqrestore(&prtd->lock, flags);
+
dstn = prtd->buffer + prtd->app_pointer;
if (count < prtd->buffer_size - prtd->app_pointer) {
if (copy_from_user(dstn, buf, count))
@@ -1282,50 +1329,125 @@
}
static int msm_compr_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned long fe_id = kcontrol->private_value;
struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
snd_soc_platform_get_drvdata(platform);
- struct snd_compr_stream *cstream = pdata->cstream[mc->reg];
- uint32_t *volume = pdata->volume[mc->reg];
+ struct snd_compr_stream *cstream = NULL;
+ uint32_t *volume = NULL;
+
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds fe_id %lu\n",
+ __func__, fe_id);
+ return -EINVAL;
+ }
+
+ cstream = pdata->cstream[fe_id];
+ volume = pdata->volume[fe_id];
volume[0] = ucontrol->value.integer.value[0];
volume[1] = ucontrol->value.integer.value[1];
- pr_debug("%s: mc->reg %d left_vol %d right_vol %d\n",
- __func__, mc->reg, volume[0], volume[1]);
+ pr_debug("%s: fe_id %lu left_vol %d right_vol %d\n",
+ __func__, fe_id, volume[0], volume[1]);
if (cstream)
msm_compr_set_volume(cstream, volume[0], volume[1]);
return 0;
}
static int msm_compr_volume_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+ struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned long fe_id = kcontrol->private_value;
+
struct msm_compr_pdata *pdata =
snd_soc_platform_get_drvdata(platform);
- uint32_t *volume = pdata->volume[mc->reg];
- pr_debug("%s: mc->reg %d\n", __func__, mc->reg);
+ uint32_t *volume = NULL;
+
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
+ return -EINVAL;
+ }
+
+ volume = pdata->volume[fe_id];
+ pr_debug("%s: fe_id %lu\n", __func__, fe_id);
ucontrol->value.integer.value[0] = volume[0];
ucontrol->value.integer.value[1] = volume[1];
return 0;
}
-/* System Pin has no volume control */
-static const struct snd_kcontrol_new msm_compr_volume_controls[] = {
- SOC_DOUBLE_EXT_TLV("Compress Playback Volume",
- MSM_FRONTEND_DAI_MULTIMEDIA4,
- 0, 8, COMPRESSED_LR_VOL_MAX_STEPS, 0,
- msm_compr_volume_get,
- msm_compr_volume_put,
- msm_compr_vol_gain),
-};
+static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+ unsigned long fe_id = kcontrol->private_value;
+ struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+ snd_soc_platform_get_drvdata(platform);
+ struct msm_compr_audio_effects *audio_effects = NULL;
+ struct snd_compr_stream *cstream = NULL;
+ struct msm_compr_audio *prtd = NULL;
+ long *values = &(ucontrol->value.integer.value[0]);
+ int effects_module;
+
+ pr_debug("%s\n", __func__);
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds fe_id %lu\n",
+ __func__, fe_id);
+ return -EINVAL;
+ }
+ cstream = pdata->cstream[fe_id];
+ audio_effects = pdata->audio_effects[fe_id];
+ if (!cstream || !audio_effects) {
+ pr_err("%s: stream or effects inactive\n", __func__);
+ return -EINVAL;
+ }
+ prtd = cstream->runtime->private_data;
+ if (!prtd) {
+ pr_err("%s: cannot set audio effects\n", __func__);
+ return -EINVAL;
+ }
+ effects_module = *values++;
+ switch (effects_module) {
+ case VIRTUALIZER_MODULE:
+ pr_debug("%s: VIRTUALIZER_MODULE\n", __func__);
+ msm_audio_effects_virtualizer_handler(prtd->audio_client,
+ &(audio_effects->virtualizer),
+ values);
+ break;
+ case REVERB_MODULE:
+ pr_debug("%s: REVERB_MODULE\n", __func__);
+ msm_audio_effects_reverb_handler(prtd->audio_client,
+ &(audio_effects->reverb),
+ values);
+ break;
+ case BASS_BOOST_MODULE:
+ pr_debug("%s: BASS_BOOST_MODULE\n", __func__);
+ msm_audio_effects_bass_boost_handler(prtd->audio_client,
+ &(audio_effects->bass_boost),
+ values);
+ break;
+ case EQ_MODULE:
+ pr_debug("%s: EQ_MODULE\n", __func__);
+ msm_audio_effects_popless_eq_handler(prtd->audio_client,
+ &(audio_effects->equalizer),
+ values);
+ break;
+ default:
+ pr_err("%s Invalid effects config module\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ /* dummy function */
+ return 0;
+}
static int msm_compr_probe(struct snd_soc_platform *platform)
{
@@ -1345,12 +1467,141 @@
for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
pdata->volume[i][0] = COMPRESSED_LR_VOL_MAX_STEPS;
pdata->volume[i][1] = COMPRESSED_LR_VOL_MAX_STEPS;
+ pdata->audio_effects[i] = NULL;
pdata->cstream[i] = NULL;
}
return 0;
}
+static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = COMPRESSED_LR_VOL_MAX_STEPS;
+ return 0;
+}
+
+static int msm_compr_audio_effects_config_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 128;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xFFFFFFFF;
+ return 0;
+}
+
+static int msm_compr_add_volume_control(struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Compress Playback";
+ const char *deviceNo = "NN";
+ const char *suffix = "Volume";
+ char *mixer_str = NULL;
+ int ctl_len;
+ struct snd_kcontrol_new fe_volume_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_compr_volume_info,
+ .tlv.p = msm_compr_vol_gain,
+ .get = msm_compr_volume_get,
+ .put = msm_compr_volume_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\n", __func__);
+ return 0;
+ }
+ pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
+ __func__, rtd->dai_link->name, rtd->dai_link->be_id,
+ rtd->dai_link->cpu_dai_name, rtd->pcm->device);
+ ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
+ strlen(suffix) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+ if (!mixer_str) {
+ pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
+ return 0;
+ }
+ snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
+ rtd->pcm->device, suffix);
+ fe_volume_control[0].name = mixer_str;
+ fe_volume_control[0].private_value = rtd->dai_link->be_id;
+ pr_debug("Registering new mixer ctl %s", mixer_str);
+ snd_soc_add_platform_controls(rtd->platform, fe_volume_control,
+ ARRAY_SIZE(fe_volume_control));
+ kfree(mixer_str);
+ return 0;
+}
+
+static int msm_compr_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Audio Effects Config";
+ const char *deviceNo = "NN";
+ char *mixer_str = NULL;
+ int ctl_len;
+ struct snd_kcontrol_new fe_audio_effects_config_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_compr_audio_effects_config_info,
+ .get = msm_compr_audio_effects_config_get,
+ .put = msm_compr_audio_effects_config_put,
+ .private_value = 0,
+ }
+ };
+
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\n", __func__);
+ return 0;
+ }
+
+ pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
+ __func__, rtd->dai_link->name, rtd->dai_link->be_id,
+ rtd->dai_link->cpu_dai_name, rtd->pcm->device);
+
+ ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+
+ if (!mixer_str) {
+ pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
+ return 0;
+ }
+
+ snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
+
+ fe_audio_effects_config_control[0].name = mixer_str;
+ fe_audio_effects_config_control[0].private_value = rtd->dai_link->be_id;
+ pr_debug("Registering new mixer ctl %s", mixer_str);
+ snd_soc_add_platform_controls(rtd->platform,
+ fe_audio_effects_config_control,
+ ARRAY_SIZE(fe_audio_effects_config_control));
+ kfree(mixer_str);
+ return 0;
+}
+
+static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
+{
+ int rc;
+
+ rc = msm_compr_add_volume_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add Compr Volume Control\n", __func__);
+ rc = msm_compr_add_audio_effects_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add Compr Audio Effects Control\n",
+ __func__);
+ return 0;
+}
+
static struct snd_compr_ops msm_compr_ops = {
.open = msm_compr_open,
.free = msm_compr_free,
@@ -1367,8 +1618,7 @@
static struct snd_soc_platform_driver msm_soc_platform = {
.probe = msm_compr_probe,
.compr_ops = &msm_compr_ops,
- .controls = msm_compr_volume_controls,
- .num_controls = ARRAY_SIZE(msm_compr_volume_controls),
+ .pcm_new = msm_compr_new,
};
static __devinit int msm_compr_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 2804c6a..b45a218 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -62,10 +62,13 @@
uint32_t buf_addr_lsw;
uint32_t mmap_hdl;
};
-static int32_t q6asm_mmapcallback(struct apr_client_data *data, void *priv);
+static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv);
static int32_t q6asm_callback(struct apr_client_data *data, void *priv);
static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
uint32_t pkt_size, uint32_t cmd_flg);
+static void q6asm_add_hdr_custom_topology(struct audio_client *ac,
+ struct apr_hdr *hdr,
+ uint32_t pkt_size, uint32_t cmd_flg);
static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr,
uint32_t pkt_size, uint32_t cmd_flg);
static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
@@ -364,7 +367,6 @@
struct list_head *ptr, *next;
int result;
int size = 4096;
-
get_asm_custom_topology(&cal_block);
if (cal_block.cal_size == 0) {
pr_debug("%s: no cal to send addr= 0x%x\n",
@@ -422,8 +424,9 @@
}
}
- q6asm_add_hdr(ac, &asm_top.hdr, APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(asm_top)), TRUE);
+ q6asm_add_hdr_custom_topology(ac, &asm_top.hdr,
+ APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(asm_top)), TRUE);
asm_top.hdr.opcode = ASM_CMD_ADD_TOPOLOGIES;
asm_top.payload_addr_lsw = cal_block.cal_paddr;
@@ -445,7 +448,7 @@
result = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) == 0), 5*HZ);
if (!result) {
- pr_err("%s: Set topologies failed payload = 0x%x\n",
+ pr_err("%s: Set topologies failed after timedout payload = 0x%x\n",
__func__, cal_block.cal_paddr);
goto done;
}
@@ -775,7 +778,7 @@
if ((atomic_read(&this_mmap.ref_cnt) == 0) ||
(this_mmap.apr == NULL)) {
this_mmap.apr = apr_register("ADSP", "ASM", \
- (apr_fn)q6asm_mmapcallback,\
+ (apr_fn)q6asm_srvc_callback,\
0x0FFFFFFFF, &this_mmap);
if (this_mmap.apr == NULL) {
pr_debug("%s Unable to register APR ASM common port\n",
@@ -869,7 +872,6 @@
pr_err("%s: session not active: %d\n", __func__, session_id);
goto err;
}
-
return session[session_id];
err:
return NULL;
@@ -1042,7 +1044,7 @@
return -EINVAL;
}
-static int32_t q6asm_mmapcallback(struct apr_client_data *data, void *priv)
+static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
{
uint32_t sid = 0;
uint32_t dir = 0;
@@ -1089,6 +1091,7 @@
switch (payload[0]) {
case ASM_CMD_SHARED_MEM_MAP_REGIONS:
case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:
+ case ASM_CMD_ADD_TOPOLOGIES:
if (payload[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n",
__func__, payload[0], payload[1], sid);
@@ -1614,6 +1617,36 @@
return;
}
+static void q6asm_add_hdr_custom_topology(struct audio_client *ac,
+ struct apr_hdr *hdr,
+ uint32_t pkt_size, uint32_t cmd_flg)
+{
+ pr_debug("%s:pkt_size=%d cmd_flg=%d session=%d\n", __func__, pkt_size,
+ cmd_flg, ac->session);
+ if (ac->apr == NULL) {
+ pr_err("%s: ac->apr is NULL", __func__);
+ return;
+ }
+
+ mutex_lock(&ac->cmd_lock);
+ hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
+ APR_HDR_LEN(sizeof(struct apr_hdr)),\
+ APR_PKT_VER);
+ hdr->src_svc = ((struct apr_svc *)ac->apr)->id;
+ hdr->src_domain = APR_DOMAIN_APPS;
+ hdr->dest_svc = APR_SVC_ASM;
+ hdr->dest_domain = APR_DOMAIN_ADSP;
+ hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01;
+ hdr->dest_port = 0;
+ if (cmd_flg) {
+ hdr->token = ((ac->session << 8) | 0x0001) ;
+ atomic_set(&ac->cmd_state, 1);
+ }
+ hdr->pkt_size = pkt_size;
+ mutex_unlock(&ac->cmd_lock);
+ return;
+}
+
static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr,
u32 pkt_size, u32 cmd_flg, u32 token)
{
@@ -3930,6 +3963,58 @@
return -EINVAL;
}
+int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
+ uint32_t params_length)
+{
+ char *asm_params = NULL;
+ struct apr_hdr hdr;
+ struct asm_stream_cmd_set_pp_params_v2 payload_params;
+ int sz, rc;
+
+ pr_debug("%s\n", __func__);
+ if (!ac || ac->apr == NULL || params == NULL) {
+ pr_err("APR handle NULL or params NULL\n");
+ return -EINVAL;
+ }
+ sz = sizeof(struct apr_hdr) +
+ sizeof(struct asm_stream_cmd_set_pp_params_v2) +
+ params_length;
+ asm_params = kzalloc(sz, GFP_KERNEL);
+ if (!asm_params) {
+ pr_err("%s, adm params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+ q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
+ sizeof(struct asm_stream_cmd_set_pp_params_v2) +
+ params_length), TRUE);
+ hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
+ payload_params.data_payload_addr_lsw = 0;
+ payload_params.data_payload_addr_msw = 0;
+ payload_params.mem_map_handle = 0;
+ payload_params.data_payload_size = params_length;
+ memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr));
+ memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), &payload_params,
+ sizeof(struct asm_stream_cmd_set_pp_params_v2));
+ memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
+ sizeof(struct asm_stream_cmd_set_pp_params_v2)),
+ params, params_length);
+ rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
+ if (rc < 0) {
+ pr_err("%s: audio effects set-params send failed\n", __func__);
+ goto fail_send_param;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 1*HZ);
+ if (!rc) {
+ pr_err("%s: timeout, audio effects set-params\n", __func__);
+ goto fail_send_param;
+ }
+ rc = 0;
+fail_send_param:
+ kfree(asm_params);
+ return rc;
+}
+
static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id)
{
struct apr_hdr hdr;
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 58b8399..b9af9b6 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -756,6 +756,14 @@
rtd->compr = compr;
compr->private_data = rtd;
+ if (platform->driver->pcm_new) {
+ ret = platform->driver->pcm_new(rtd);
+ if (ret < 0) {
+ pr_err("asoc: compress pcm constructor failed\n");
+ goto compr_err;
+ }
+ }
+
printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
cpu_dai->name);
return ret;