diff options
82 files changed, 1643 insertions, 371 deletions
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi new file mode 100644 index 000000000000..7774a28ff495 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi @@ -0,0 +1,416 @@ +/* Copyright (c) 2017, 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. + */ + +&mdss_mdp { + dsi_dual_nt36850_truly_cmd: qcom,mdss_dsi_nt36850_truly_wqhd_cmd{ + qcom,mdss-dsi-panel-name = + "Dual nt36850 cmd mode dsi truly panel without DSC"; + qcom,mdss-dsi-panel-type = "dsi_cmd_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <720>; + qcom,mdss-dsi-panel-height = <2560>; + qcom,mdss-dsi-h-front-porch = <120>; + qcom,mdss-dsi-h-back-porch = <140>; + qcom,mdss-dsi-h-pulse-width = <20>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <20>; + qcom,mdss-dsi-v-front-porch = <8>; + qcom,mdss-dsi-v-pulse-width = <4>; + 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 = "rgb_swap_rgb"; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [ + 15 01 00 00 00 00 02 ff 24 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 19 + 15 01 00 00 00 00 02 01 03 + 15 01 00 00 00 00 02 02 04 + 15 01 00 00 00 00 02 03 1b + 15 01 00 00 00 00 02 04 1d + 15 01 00 00 00 00 02 05 01 + 15 01 00 00 00 00 02 06 0c + 15 01 00 00 00 00 02 07 0f + 15 01 00 00 00 00 02 08 1f + 15 01 00 00 00 00 02 09 00 + 15 01 00 00 00 00 02 0a 00 + 15 01 00 00 00 00 02 0b 13 + 15 01 00 00 00 00 02 0c 16 + 15 01 00 00 00 00 02 0d 14 + 15 01 00 00 00 00 02 0e 15 + 15 01 00 00 00 00 02 0f 00 + 15 01 00 00 00 00 02 10 19 + 15 01 00 00 00 00 02 11 03 + 15 01 00 00 00 00 02 12 04 + 15 01 00 00 00 00 02 13 1b + 15 01 00 00 00 00 02 14 1d + 15 01 00 00 00 00 02 15 01 + 15 01 00 00 00 00 02 16 0c + 15 01 00 00 00 00 02 17 0f + 15 01 00 00 00 00 02 18 1f + 15 01 00 00 00 00 02 19 00 + 15 01 00 00 00 00 02 1a 00 + 15 01 00 00 00 00 02 1b 13 + 15 01 00 00 00 00 02 1c 16 + 15 01 00 00 00 00 02 1d 14 + 15 01 00 00 00 00 02 1e 15 + 15 01 00 00 00 00 02 1f 00 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 10 + 15 01 00 00 00 00 02 23 28 + 15 01 00 00 00 00 02 24 28 + 15 01 00 00 00 00 02 25 5d + 15 01 00 00 00 00 02 26 28 + 15 01 00 00 00 00 02 27 28 + 15 01 00 00 00 00 02 29 d8 + 15 01 00 00 00 00 02 2a 15 + 15 01 00 00 00 00 02 2b 00 + 15 01 00 00 00 00 02 2d 00 + 15 01 00 00 00 00 02 2f 02 + 15 01 00 00 00 00 02 30 02 + 15 01 00 00 00 00 02 31 00 + 15 01 00 00 00 00 02 32 23 + 15 01 00 00 00 00 02 33 01 + 15 01 00 00 00 00 02 34 03 + 15 01 00 00 00 00 02 35 49 + 15 01 00 00 00 00 02 36 00 + 15 01 00 00 00 00 02 37 1d + 15 01 00 00 00 00 02 38 08 + 15 01 00 00 00 00 02 39 03 + 15 01 00 00 00 00 02 3a 49 + 15 01 00 00 00 00 02 42 01 + 15 01 00 00 00 00 02 43 8c + 15 01 00 00 00 00 02 44 a3 + 15 01 00 00 00 00 02 48 8c + 15 01 00 00 00 00 02 49 a3 + 15 01 00 00 00 00 02 5b 00 + 15 01 00 00 00 00 02 5f 4d + 15 01 00 00 00 00 02 63 00 + 15 01 00 00 00 00 02 67 04 + 15 01 00 00 00 00 02 6e 10 + 15 01 00 00 00 00 02 72 02 + 15 01 00 00 00 00 02 73 00 + 15 01 00 00 00 00 02 74 04 + 15 01 00 00 00 00 02 75 1b + 15 01 00 00 00 00 02 76 05 + 15 01 00 00 00 00 02 77 01 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 7a 00 + 15 01 00 00 00 00 02 7b 91 + 15 01 00 00 00 00 02 7c da + 15 01 00 00 00 00 02 7d 10 + 15 01 00 00 00 00 02 7e 04 + 15 01 00 00 00 00 02 7f 1b + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 81 05 + 15 01 00 00 00 00 02 82 01 + 15 01 00 00 00 00 02 83 00 + 15 01 00 00 00 00 02 84 05 + 15 01 00 00 00 00 02 85 05 + 15 01 00 00 00 00 02 86 1b + 15 01 00 00 00 00 02 87 1b + 15 01 00 00 00 00 02 88 1b + 15 01 00 00 00 00 02 89 1b + 15 01 00 00 00 00 02 8a 00 + 15 01 00 00 00 00 02 8b f0 + 15 01 00 00 00 00 02 8c 00 + 15 01 00 00 00 00 02 8f 63 + 15 01 00 00 00 00 02 90 51 + 15 01 00 00 00 00 02 91 40 + 15 01 00 00 00 00 02 92 51 + 15 01 00 00 00 00 02 93 08 + 15 01 00 00 00 00 02 94 08 + 15 01 00 00 00 00 02 95 51 + 15 01 00 00 00 00 02 96 51 + 15 01 00 00 00 00 02 97 00 + 15 01 00 00 00 00 02 98 00 + 15 01 00 00 00 00 02 99 33 + 15 01 00 00 00 00 02 9b ff + 15 01 00 00 00 00 02 9c 01 + 15 01 00 00 00 00 02 9d 30 + 15 01 00 00 00 00 02 a5 10 + 15 01 00 00 00 00 02 a6 01 + 15 01 00 00 00 00 02 a9 21 + 15 01 00 00 00 00 02 b3 2a + 15 01 00 00 00 00 02 b4 da + 15 01 00 00 00 00 02 ba 83 + 15 01 00 00 00 00 02 c4 24 + 15 01 00 00 00 00 02 c5 aa + 15 01 00 00 00 00 02 c6 09 + 15 01 00 00 00 00 02 c7 00 + 15 01 00 00 00 00 02 c9 c0 + 15 01 00 00 00 00 02 ca 04 + 15 01 00 00 00 00 02 d5 3f + 15 01 00 00 00 00 02 d6 10 + 15 01 00 00 00 00 02 d7 3f + 15 01 00 00 00 00 02 d8 10 + 15 01 00 00 00 00 02 d9 ee + 15 01 00 00 00 00 02 da 49 + 15 01 00 00 00 00 02 db 94 + 15 01 00 00 00 00 02 e9 33 + 15 01 00 00 00 00 02 eb 28 + 15 01 00 00 00 00 02 ec 00 + 15 01 00 00 00 00 02 ee 00 + 15 01 00 00 00 00 02 ef 06 + 15 01 00 00 00 00 02 f0 01 + 15 01 00 00 00 00 02 f1 01 + 15 01 00 00 00 00 02 f2 0d + 15 01 00 00 00 00 02 f3 48 + 15 01 00 00 00 00 02 f6 00 + 15 01 00 00 00 00 02 f7 00 + 15 01 00 00 00 00 02 f8 00 + 15 01 00 00 00 00 02 f9 00 + 15 01 00 00 00 00 02 ff 26 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 ab + 15 01 00 00 00 00 02 01 00 + 15 01 00 00 00 00 02 02 80 + 15 01 00 00 00 00 02 03 08 + 15 01 00 00 00 00 02 04 01 + 15 01 00 00 00 00 02 05 32 + 15 01 00 00 00 00 02 06 4c + 15 01 00 00 00 00 02 07 26 + 15 01 00 00 00 00 02 08 09 + 15 01 00 00 00 00 02 09 02 + 15 01 00 00 00 00 02 0a 32 + 15 01 00 00 00 00 02 0b 55 + 15 01 00 00 00 00 02 0c 14 + 15 01 00 00 00 00 02 0d 28 + 15 01 00 00 00 00 02 0e 00 + 15 01 00 00 00 00 02 0f 00 + 15 01 00 00 00 00 02 10 00 + 15 01 00 00 00 00 02 11 22 + 15 01 00 00 00 00 02 12 0a + 15 01 00 00 00 00 02 13 20 + 15 01 00 00 00 00 02 14 06 + 15 01 00 00 00 00 02 15 00 + 15 01 00 00 00 00 02 16 40 + 15 01 00 00 00 00 02 19 43 + 15 01 00 00 00 00 02 1a 03 + 15 01 00 00 00 00 02 1b 25 + 15 01 00 00 00 00 02 1c 11 + 15 01 00 00 00 00 02 1d 00 + 15 01 00 00 00 00 02 1e 80 + 15 01 00 00 00 00 02 1f 00 + 15 01 00 00 00 00 02 20 00 + 15 01 00 00 00 00 02 21 03 + 15 01 00 00 00 00 02 22 22 + 15 01 00 00 00 00 02 23 25 + 15 01 00 00 00 00 02 24 00 + 15 01 00 00 00 00 02 25 a7 + 15 01 00 00 00 00 02 26 00 + 15 01 00 00 00 00 02 27 a5 + 15 01 00 00 00 00 02 28 06 + 15 01 00 00 00 00 02 29 85 + 15 01 00 00 00 00 02 2a 3f + 15 01 00 00 00 00 02 2b 97 + 15 01 00 00 00 00 02 2f 25 + 15 01 00 00 00 00 02 30 26 + 15 01 00 00 00 00 02 31 41 + 15 01 00 00 00 00 02 32 04 + 15 01 00 00 00 00 02 33 04 + 15 01 00 00 00 00 02 34 2b + 15 01 00 00 00 00 02 35 00 + 15 01 00 00 00 00 02 36 00 + 15 01 00 00 00 00 02 37 c8 + 15 01 00 00 00 00 02 38 26 + 15 01 00 00 00 00 02 39 25 + 15 01 00 00 00 00 02 3a 26 + 15 01 00 00 00 00 02 3f eb + 15 01 00 00 00 00 02 41 21 + 15 01 00 00 00 00 02 42 03 + 15 01 00 00 00 00 02 43 00 + 15 01 00 00 00 00 02 44 11 + 15 01 00 00 00 00 02 45 00 + 15 01 00 00 00 00 02 46 00 + 15 01 00 00 00 00 02 47 00 + 15 01 00 00 00 00 02 48 00 + 15 01 00 00 00 00 02 49 03 + 15 01 00 00 00 00 02 4a 00 + 15 01 00 00 00 00 02 4b 00 + 15 01 00 00 00 00 02 4c 01 + 15 01 00 00 00 00 02 4d 4e + 15 01 00 00 00 00 02 4e 01 + 15 01 00 00 00 00 02 4f 4c + 15 01 00 00 00 00 02 50 0d + 15 01 00 00 00 00 02 51 0e + 15 01 00 00 00 00 02 52 23 + 15 01 00 00 00 00 02 53 97 + 15 01 00 00 00 00 02 54 4b + 15 01 00 00 00 00 02 55 4c + 15 01 00 00 00 00 02 56 20 + 15 01 00 00 00 00 02 58 04 + 15 01 00 00 00 00 02 59 04 + 15 01 00 00 00 00 02 5a 09 + 15 01 00 00 00 00 02 5b 00 + 15 01 00 00 00 00 02 5c 00 + 15 01 00 00 00 00 02 5d c8 + 15 01 00 00 00 00 02 5e 4c + 15 01 00 00 00 00 02 5f 4b + 15 01 00 00 00 00 02 60 00 + 15 01 00 00 00 00 02 80 2b + 15 01 00 00 00 00 02 81 43 + 15 01 00 00 00 00 02 82 03 + 15 01 00 00 00 00 02 83 25 + 15 01 00 00 00 00 02 84 11 + 15 01 00 00 00 00 02 85 00 + 15 01 00 00 00 00 02 86 80 + 15 01 00 00 00 00 02 87 00 + 15 01 00 00 00 00 02 88 00 + 15 01 00 00 00 00 02 89 03 + 15 01 00 00 00 00 02 8a 22 + 15 01 00 00 00 00 02 8b 25 + 15 01 00 00 00 00 02 8c 00 + 15 01 00 00 00 00 02 8d a4 + 15 01 00 00 00 00 02 8e 00 + 15 01 00 00 00 00 02 8f a2 + 15 01 00 00 00 00 02 90 06 + 15 01 00 00 00 00 02 91 63 + 15 01 00 00 00 00 02 92 30 + 15 01 00 00 00 00 02 93 97 + 15 01 00 00 00 00 02 94 25 + 15 01 00 00 00 00 02 95 26 + 15 01 00 00 00 00 02 96 41 + 15 01 00 00 00 00 02 97 04 + 15 01 00 00 00 00 02 98 04 + 15 01 00 00 00 00 02 99 f0 + 15 01 00 00 00 00 02 9a 00 + 15 01 00 00 00 00 02 9b 00 + 15 01 00 00 00 00 02 9c c8 + 15 01 00 00 00 00 02 9d 50 + 15 01 00 00 00 00 02 9e 26 + 15 01 00 00 00 00 02 9f 25 + 15 01 00 00 00 00 02 a0 26 + 15 01 00 00 00 00 02 a2 00 + 15 01 00 00 00 00 02 a3 33 + 15 01 00 00 00 00 02 a5 40 + 15 01 00 00 00 00 02 a6 40 + 15 01 00 00 00 00 02 ac 91 + 15 01 00 00 00 00 02 ad 66 + 15 01 00 00 00 00 02 ae 66 + 15 01 00 00 00 00 02 b1 40 + 15 01 00 00 00 00 02 b2 40 + 15 01 00 00 00 00 02 b4 40 + 15 01 00 00 00 00 02 b5 40 + 15 01 00 00 00 00 02 b7 40 + 15 01 00 00 00 00 02 b8 40 + 15 01 00 00 00 00 02 ba 22 + 15 01 00 00 00 00 02 bb 00 + 15 01 00 00 00 00 02 c2 01 + 15 01 00 00 00 00 02 c3 01 + 15 01 00 00 00 00 02 c4 01 + 15 01 00 00 00 00 02 c5 01 + 15 01 00 00 00 00 02 c6 01 + 15 01 00 00 00 00 02 c8 00 + 15 01 00 00 00 00 02 c9 00 + 15 01 00 00 00 00 02 ca 00 + 15 01 00 00 00 00 02 cd 00 + 15 01 00 00 00 00 02 ce 00 + 15 01 00 00 00 00 02 d6 04 + 15 01 00 00 00 00 02 d7 00 + 15 01 00 00 00 00 02 d8 0d + 15 01 00 00 00 00 02 d9 00 + 15 01 00 00 00 00 02 da 00 + 15 01 00 00 00 00 02 db 00 + 15 01 00 00 00 00 02 dc 00 + 15 01 00 00 00 00 02 dd 00 + 15 01 00 00 00 00 02 de 00 + 15 01 00 00 00 00 02 df 01 + 15 01 00 00 00 00 02 e0 00 + 15 01 00 00 00 00 02 e1 00 + 15 01 00 00 00 00 02 e2 19 + 15 01 00 00 00 00 02 e3 04 + 15 01 00 00 00 00 02 e4 00 + 15 01 00 00 00 00 02 e5 04 + 15 01 00 00 00 00 02 e6 00 + 15 01 00 00 00 00 02 e7 12 + 15 01 00 00 00 00 02 e8 00 + 15 01 00 00 00 00 02 e9 50 + 15 01 00 00 00 00 02 ea 10 + 15 01 00 00 00 00 02 eb 02 + 15 01 00 00 00 00 02 ff 27 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 ff 28 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 60 0a + 15 01 00 00 00 00 02 63 32 + 15 01 00 00 00 00 02 64 01 + 15 01 00 00 00 00 02 68 da + 15 01 00 00 00 00 02 69 00 + 15 01 00 00 00 00 02 ff 29 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 60 0a + 15 01 00 00 00 00 02 63 32 + 15 01 00 00 00 00 02 64 01 + 15 01 00 00 00 00 02 68 da + 15 01 00 00 00 00 02 69 00 + 15 01 00 00 00 00 02 ff e0 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 35 40 + 15 01 00 00 00 00 02 36 40 + 15 01 00 00 00 00 02 37 00 + 15 01 00 00 00 00 02 89 c6 + 15 01 00 00 00 00 02 ff f0 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 ea 40 + 15 01 00 00 00 00 02 ff 10 + 15 01 00 00 00 00 02 36 00 + 15 01 00 00 00 00 02 35 00 + 39 01 00 00 00 00 03 44 03 e8 + 15 01 00 00 00 00 02 51 ff + 15 01 00 00 00 00 02 53 2c + 15 01 00 00 00 00 02 55 01 + 05 01 00 00 0a 00 02 20 00 + 15 01 00 00 00 00 02 bb 10 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00]; + qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00 + 05 01 00 00 78 00 02 10 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 = <0>; + qcom,mdss-dsi-traffic-mode = "non_burst_sync_event"; + qcom,mdss-dsi-lane-map = "lane_map_0123"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-tx-eot-append; + qcom,cmd-sync-wait-broadcast; + 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-wr-mem-start = <0x2c>; + qcom,mdss-dsi-wr-mem-continue = <0x3c>; + qcom,mdss-dsi-te-pin-select = <1>; + qcom,mdss-dsi-te-dcs-command = <1>; + qcom,mdss-dsi-te-check-enable; + qcom,mdss-dsi-te-using-te-pin; + qcom,mdss-dsi-panel-timings = + [da 34 24 00 64 68 28 38 2a 03 04 00]; + qcom,mdss-dsi-t-clk-pre = <0x29>; + qcom,mdss-dsi-t-clk-post = <0x03>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-lp11-init; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi index 3674e2e5570b..e8e773a33622 100644 --- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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 @@ -585,8 +585,8 @@ pm660_haptics: qcom,haptic@c000 { compatible = "qcom,qpnp-haptic"; reg = <0xc000 0x100>; - interrupts = <0x1 0xc0 0x0>, - <0x1 0xc0 0x1>; + interrupts = <0x1 0xc0 0x0 IRQ_TYPE_NONE>, + <0x1 0xc0 0x1 IRQ_TYPE_NONE>; interrupt-names = "sc-irq", "play-irq"; qcom,actuator-type = "lra"; qcom,play-mode = "direct"; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi index 99f3f58cc20e..b1880c076e1c 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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 @@ -618,8 +618,8 @@ status = "disabled"; compatible = "qcom,qpnp-haptic"; reg = <0xc000 0x100>; - interrupts = <0x3 0xc0 0x0>, - <0x3 0xc0 0x1>; + interrupts = <0x3 0xc0 0x0 IRQ_TYPE_NONE>, + <0x3 0xc0 0x1 IRQ_TYPE_NONE>; interrupt-names = "sc-irq", "play-irq"; qcom,actuator-type = "lra"; qcom,play-mode = "direct"; diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi index 61fc31a17e52..2cb08e1709a5 100644 --- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi @@ -254,6 +254,7 @@ qcom,csid-sd-index = <1>; qcom,mount-angle = <90>; qcom,eeprom-src = <&eeprom1>; + qcom,actuator-src = <&actuator1>; cam_vdig-supply = <&pm8998_lvs1>; cam_vio-supply = <&pm8998_lvs1>; cam_vana-supply = <&pmi8998_bob>; diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi index 0bd9ab40e8f1..0a41383ba874 100644 --- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi @@ -254,6 +254,7 @@ qcom,csid-sd-index = <1>; qcom,mount-angle = <90>; qcom,eeprom-src = <&eeprom1>; + qcom,actuator-src = <&actuator1>; cam_vdig-supply = <&pm8998_lvs1>; cam_vio-supply = <&pm8998_lvs1>; cam_vana-supply = <&pmi8998_bob>; diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi index 6779d80d76cf..16d6c1bf9500 100644 --- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi @@ -20,5 +20,9 @@ pinctrl-0 = <&uart_console_active>; }; +&mem_client_3_size { + qcom,peripheral-size = <0x500000>; +}; + &soc { }; diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dts b/arch/arm/boot/dts/qcom/sdm660-qrd.dts index 29fc0d776fd0..a8fde35ba49c 100644 --- a/arch/arm/boot/dts/qcom/sdm660-qrd.dts +++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 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 @@ -23,3 +23,7 @@ qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>, <0x0001001b 0x0201011a 0x0 0x0>; }; + +&pm660l_wled { + qcom,led-strings-list = [00 01]; +}; diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi index 2b53a88f4bf5..d3d6bf6ca10e 100644 --- a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi @@ -103,3 +103,46 @@ &soc { }; + +&pm660l_gpios { + /* GPIO 7 for VOL_UP */ + gpio@c600 { + status = "ok"; + qcom,mode = <0>; + qcom,pull = <0>; + qcom,vin-sel = <0>; + qcom,src-sel = <0>; + qcom,out-strength = <1>; + }; +}; + +&soc { + gpio_keys { + compatible = "gpio-keys"; + input-name = "gpio-keys"; + status = "ok"; + + vol_up { + label = "volume_up"; + gpios = <&pm660l_gpios 7 0x1>; + linux,input-type = <1>; + linux,code = <115>; + gpio-key,wakeup; + debounce-interval = <15>; + }; + }; +}; + +/ { + qrd_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <15>; + + #include "fg-gen3-batterydata-qrd-skuk-4v4-3000mah.dtsi" + }; +}; + +&pm660_fg { + qcom,battery-data = <&qrd_batterydata>; + qcom,fg-jeita-thresholds = <0 5 55 55>; + qcom,fg-cutoff-voltage = <3700>; +}; diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index 563bd00120d6..54aa729352a3 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -1094,7 +1094,8 @@ reg-names = "osm", "pwrcl_pll", "perfcl_pll", "apcs_common", "perfcl_efuse"; - /* ToDo: Add power and perf supply rails */ + vdd-pwrcl-supply = <&apc0_pwrcl_vreg>; + vdd-perfcl-supply = <&apc1_perfcl_vreg>; interrupts = <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>; @@ -1160,19 +1161,6 @@ qcom,wfx-fsm-en; qcom,pc-fsm-en; - qcom,pwrcl-apcs-mem-acc-cfg = - <0x179d1360 0x179d1364 0x179d1364>; - qcom,perfcl-apcs-mem-acc-cfg = - <0x179d1368 0x179d136C 0x179d1370>; - qcom,pwrcl-apcs-mem-acc-val = - <0x00000000 0x80000000 0x80000000>, - <0x00000000 0x00000000 0x00000000>, - <0x00000000 0x00000001 0x00000001>; - qcom,perfcl-apcs-mem-acc-val = - <0x00000000 0x00000000 0x80000000>, - <0x00000000 0x00000000 0x00000000>, - <0x00000000 0x00000000 0x00000001>; - clock-names = "aux_clk", "xo_a"; clocks = <&clock_gcc HMSS_GPLL0_CLK_SRC>, <&clock_rpmcc RPM_XO_A_CLK_SRC>; diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index c5c7d924aab6..9cf5a15e80eb 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -254,7 +254,6 @@ CONFIG_PPPOPNS=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_CLD_LL_CORE=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -266,6 +265,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_SECURE_TOUCH=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_KEYCHORD=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig index 879b6ff88423..d555a1b179d8 100644 --- a/arch/arm/configs/sdm660-perf_defconfig +++ b/arch/arm/configs/sdm660-perf_defconfig @@ -280,7 +280,6 @@ CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_CLD_LL_CORE=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -292,6 +291,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_SECURE_TOUCH=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_KEYCHORD=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig index 10b8666a2d40..2c94274b0637 100644 --- a/arch/arm/configs/sdm660_defconfig +++ b/arch/arm/configs/sdm660_defconfig @@ -279,7 +279,6 @@ CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_CLD_LL_CORE=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -291,6 +290,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_SECURE_TOUCH=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_KEYCHORD=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 08dccf8e5022..07e413e31234 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -279,7 +279,6 @@ CONFIG_WIL6210=m CONFIG_CNSS=y CONFIG_CLD_LL_CORE=y CONFIG_BUS_AUTO_SUSPEND=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -293,6 +292,7 @@ CONFIG_SECURE_TOUCH=y CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_KEYCHORD=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index 4620e74de5bc..76d949319dfa 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -265,7 +265,6 @@ CONFIG_WIL6210=m CONFIG_CNSS=y CONFIG_CLD_LL_CORE=y CONFIG_BUS_AUTO_SUSPEND=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -280,6 +279,7 @@ CONFIG_SECURE_TOUCH=y CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y # CONFIG_SERIO_SERPORT is not set diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 71d067b27ddd..07d24ea6b707 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -275,7 +275,6 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m CONFIG_CLD_LL_CORE=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -286,6 +285,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_SECURE_TOUCH=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_UINPUT=y # CONFIG_SERIO_SERPORT is not set # CONFIG_VT is not set diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 02b9e08955f6..25b5c206e1ae 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -275,7 +275,6 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m CONFIG_CLD_LL_CORE=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -287,6 +286,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_SECURE_TOUCH=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_KEYCHORD=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig index f15fd895e65c..7d203e49d595 100644 --- a/arch/arm64/configs/sdm660-perf_defconfig +++ b/arch/arm64/configs/sdm660-perf_defconfig @@ -278,7 +278,6 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m CONFIG_CLD_LL_CORE=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -289,6 +288,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_SECURE_TOUCH=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_UINPUT=y # CONFIG_SERIO_SERPORT is not set # CONFIG_VT is not set @@ -397,9 +397,9 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y CONFIG_MSMB_JPEG=y CONFIG_MSM_FD=y CONFIG_MSM_JPEGDMA=y -CONFIG_MSM_VIDC_V4L2=m -CONFIG_MSM_VIDC_VMEM=m -CONFIG_MSM_VIDC_GOVERNORS=m +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y CONFIG_MSM_SDE_ROTATOR=y CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y CONFIG_QCOM_KGSL=y diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig index b52a672a5b5e..c295ba7e0d70 100644 --- a/arch/arm64/configs/sdm660_defconfig +++ b/arch/arm64/configs/sdm660_defconfig @@ -278,7 +278,6 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m CONFIG_CLD_LL_CORE=y -CONFIG_QPNP_POWER_ON=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y @@ -290,6 +289,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_SECURE_TOUCH=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_KEYCHORD=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y @@ -399,9 +399,9 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y CONFIG_MSMB_JPEG=y CONFIG_MSM_FD=y CONFIG_MSM_JPEGDMA=y -CONFIG_MSM_VIDC_V4L2=m -CONFIG_MSM_VIDC_VMEM=m -CONFIG_MSM_VIDC_GOVERNORS=m +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y CONFIG_MSM_SDE_ROTATOR=y CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y CONFIG_QCOM_KGSL=y diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 7326be306618..68cd3bb8eb89 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -39,6 +39,7 @@ #include <asm/pgtable.h> #include <asm/tlbflush.h> #include <asm/edac.h> +#include <soc/qcom/scm.h> #include <trace/events/exception.h> @@ -408,6 +409,23 @@ no_context: return 0; } +static int do_tlb_conf_fault(unsigned long addr, + unsigned int esr, + struct pt_regs *regs) +{ +#define SCM_TLB_CONFLICT_CMD 0x1B + struct scm_desc desc = { + .args[0] = addr, + .arginfo = SCM_ARGS(1), + }; + + if (scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_MP, SCM_TLB_CONFLICT_CMD), + &desc)) + return 1; + + return 0; +} + /* * First Level Translation Fault Handler * @@ -499,7 +517,7 @@ static struct fault_info { { do_bad, SIGBUS, 0, "unknown 45" }, { do_bad, SIGBUS, 0, "unknown 46" }, { do_bad, SIGBUS, 0, "unknown 47" }, - { do_bad, SIGBUS, 0, "TLB conflict abort" }, + { do_tlb_conf_fault, SIGBUS, 0, "TLB conflict abort" }, { do_bad, SIGBUS, 0, "unknown 49" }, { do_bad, SIGBUS, 0, "unknown 50" }, { do_bad, SIGBUS, 0, "unknown 51" }, diff --git a/drivers/clk/msm/clock-gcc-8998.c b/drivers/clk/msm/clock-gcc-8998.c index b1d767a4cb6f..87cf6cc5631e 100644 --- a/drivers/clk/msm/clock-gcc-8998.c +++ b/drivers/clk/msm/clock-gcc-8998.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 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 @@ -2799,6 +2799,9 @@ static int msm_gcc_8998_probe(struct platform_device *pdev) /* This clock is used for all MMSSCC register access */ clk_prepare_enable(&gcc_mmss_noc_cfg_ahb_clk.c); + /* Keep bimc gfx clock port on all the time */ + clk_prepare_enable(&gcc_bimc_gfx_clk.c); + /* This clock is used for all GPUCC register access */ clk_prepare_enable(&gcc_gpu_cfg_ahb_clk.c); diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c index 9e1036c19760..79e8a7d8eb00 100644 --- a/drivers/clk/msm/clock-osm.c +++ b/drivers/clk/msm/clock-osm.c @@ -231,6 +231,8 @@ enum clk_osm_trace_packet_id { #define MSM8998V2_PWRCL_BOOT_RATE 1555200000 #define MSM8998V2_PERFCL_BOOT_RATE 1728000000 +#define DEBUG_REG_NUM 3 + /* ACD registers */ #define ACD_HW_VERSION 0x0 #define ACDCR 0x4 @@ -340,6 +342,12 @@ struct osm_entry { long frequency; }; +const char *clk_panic_reg_names[] = {"WDOG_DOMAIN_PSTATE_STATUS", + "WDOG_PROGRAM_COUNTER", + "APM_STATUS"}; +const int clk_panic_reg_offsets[] = {WDOG_DOMAIN_PSTATE_STATUS, + WDOG_PROGRAM_COUNTER}; + static struct dentry *osm_debugfs_base; struct clk_osm { @@ -350,6 +358,7 @@ struct clk_osm { struct platform_device *vdd_dev; void *vbases[NUM_BASES]; unsigned long pbases[NUM_BASES]; + void __iomem *debug_regs[DEBUG_REG_NUM]; spinlock_t lock; u32 cpu_reg_mask; @@ -1371,6 +1380,64 @@ static int clk_osm_resources_init(struct platform_device *pdev) perfcl_clk.acd_init = false; } + pwrcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev, + pwrcl_clk.pbases[OSM_BASE] + + clk_panic_reg_offsets[0], + 0x4); + if (!pwrcl_clk.debug_regs[0]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[0]); + return -ENOMEM; + } + + pwrcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev, + pwrcl_clk.pbases[OSM_BASE] + + clk_panic_reg_offsets[1], + 0x4); + if (!pwrcl_clk.debug_regs[1]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[1]); + return -ENOMEM; + } + + pwrcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev, + pwrcl_clk.apm_ctrl_status, + 0x4); + if (!pwrcl_clk.debug_regs[2]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[2]); + return -ENOMEM; + } + + perfcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev, + perfcl_clk.pbases[OSM_BASE] + + clk_panic_reg_offsets[0], + 0x4); + if (!perfcl_clk.debug_regs[0]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[0]); + return -ENOMEM; + } + + perfcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev, + perfcl_clk.pbases[OSM_BASE] + + clk_panic_reg_offsets[1], + 0x4); + if (!perfcl_clk.debug_regs[1]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[1]); + return -ENOMEM; + } + + perfcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev, + perfcl_clk.apm_ctrl_status, + 0x4); + if (!perfcl_clk.debug_regs[2]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[2]); + return -ENOMEM; + } + vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl"); if (IS_ERR(vdd_pwrcl)) { rc = PTR_ERR(vdd_pwrcl); @@ -2976,36 +3043,16 @@ static int clk_osm_panic_callback(struct notifier_block *nfb, unsigned long event, void *data) { - void __iomem *virt_addr; - u32 value, reg; + int i; + u32 value; struct clk_osm *c = container_of(nfb, struct clk_osm, panic_notifier); - reg = c->pbases[OSM_BASE] + WDOG_DOMAIN_PSTATE_STATUS; - virt_addr = ioremap(reg, 0x4); - if (virt_addr != NULL) { - value = readl_relaxed(virt_addr); - pr_err("DOM%d_PSTATE_STATUS[0x%08x]=0x%08x\n", c->cluster_num, - reg, value); - iounmap(virt_addr); - } - - reg = c->pbases[OSM_BASE] + WDOG_PROGRAM_COUNTER; - virt_addr = ioremap(reg, 0x4); - if (virt_addr != NULL) { - value = readl_relaxed(virt_addr); - pr_err("DOM%d_PROGRAM_COUNTER[0x%08x]=0x%08x\n", c->cluster_num, - reg, value); - iounmap(virt_addr); - } - - virt_addr = ioremap(c->apm_ctrl_status, 0x4); - if (virt_addr != NULL) { - value = readl_relaxed(virt_addr); - pr_err("APM_CTLER_STATUS_%d[0x%08x]=0x%08x\n", c->cluster_num, - c->apm_ctrl_status, value); - iounmap(virt_addr); + for (i = 0; i < DEBUG_REG_NUM; i++) { + value = readl_relaxed(c->debug_regs[i]); + pr_err("%s_%d=0x%08x\n", clk_panic_reg_names[i], + c->cluster_num, value); } return NOTIFY_OK; @@ -3108,17 +3155,17 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev) msm8998_v2 = true; } - rc = clk_osm_resources_init(pdev); + rc = clk_osm_parse_dt_configs(pdev); if (rc) { - if (rc != -EPROBE_DEFER) - dev_err(&pdev->dev, "resources init failed, rc=%d\n", - rc); + dev_err(&pdev->dev, "Unable to parse device tree configurations\n"); return rc; } - rc = clk_osm_parse_dt_configs(pdev); + rc = clk_osm_resources_init(pdev); if (rc) { - dev_err(&pdev->dev, "Unable to parse device tree configurations\n"); + if (rc != -EPROBE_DEFER) + dev_err(&pdev->dev, "resources init failed, rc=%d\n", + rc); return rc; } diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c index ab6a1384ffbd..5ed0dba189f7 100644 --- a/drivers/clk/qcom/clk-cpu-osm.c +++ b/drivers/clk/qcom/clk-cpu-osm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 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 @@ -88,6 +88,7 @@ enum clk_osm_trace_packet_id { #define CORE_COUNT_VAL(val) ((val & GENMASK(18, 16)) >> 16) #define SINGLE_CORE 1 #define MAX_CORE_COUNT 4 +#define DEBUG_REG_NUM 3 #define ENABLE_REG 0x1004 #define INDEX_REG 0x1150 @@ -321,6 +322,13 @@ static struct dentry *osm_debugfs_base; static struct regulator *vdd_pwrcl; static struct regulator *vdd_perfcl; +const char *clk_panic_reg_names[] = {"WDOG_DOMAIN_PSTATE_STATUS", + "WDOG_PROGRAM_COUNTER", + "APM_STATUS"}; + +const int clk_panic_reg_offsets[] = {WDOG_DOMAIN_PSTATE_STATUS, + WDOG_PROGRAM_COUNTER}; + static const struct regmap_config osm_qcom_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -336,6 +344,7 @@ struct clk_osm { struct platform_device *vdd_dev; void *vbases[NUM_BASES]; unsigned long pbases[NUM_BASES]; + void __iomem *debug_regs[DEBUG_REG_NUM]; spinlock_t lock; u32 cpu_reg_mask; @@ -1366,6 +1375,64 @@ static int clk_osm_resources_init(struct platform_device *pdev) perfcl_clk.acd_init = false; } + pwrcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev, + pwrcl_clk.pbases[OSM_BASE] + + clk_panic_reg_offsets[0], + 0x4); + if (!pwrcl_clk.debug_regs[0]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[0]); + return -ENOMEM; + } + + pwrcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev, + pwrcl_clk.pbases[OSM_BASE] + + clk_panic_reg_offsets[1], + 0x4); + if (!pwrcl_clk.debug_regs[1]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[1]); + return -ENOMEM; + } + + pwrcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev, + pwrcl_clk.apm_ctrl_status, + 0x4); + if (!pwrcl_clk.debug_regs[2]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[2]); + return -ENOMEM; + }; + + perfcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev, + perfcl_clk.pbases[OSM_BASE] + + clk_panic_reg_offsets[0], + 0x4); + if (!perfcl_clk.debug_regs[0]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[0]); + return -ENOMEM; + } + + perfcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev, + perfcl_clk.pbases[OSM_BASE] + + clk_panic_reg_offsets[1], + 0x4); + if (!perfcl_clk.debug_regs[1]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[1]); + return -ENOMEM; + } + + perfcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev, + perfcl_clk.apm_ctrl_status, + 0x4); + if (!perfcl_clk.debug_regs[2]) { + dev_err(&pdev->dev, "Failed to map %s debug register\n", + clk_panic_reg_names[2]); + return -ENOMEM; + }; + vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl"); if (IS_ERR(vdd_pwrcl)) { rc = PTR_ERR(vdd_pwrcl); @@ -2859,36 +2926,16 @@ static int clk_osm_panic_callback(struct notifier_block *nfb, unsigned long event, void *data) { - void __iomem *virt_addr; - u32 value, reg; + int i; + u32 value; struct clk_osm *c = container_of(nfb, struct clk_osm, panic_notifier); - reg = c->pbases[OSM_BASE] + WDOG_DOMAIN_PSTATE_STATUS; - virt_addr = ioremap(reg, 0x4); - if (virt_addr != NULL) { - value = readl_relaxed(virt_addr); - pr_err("DOM%d_PSTATE_STATUS[0x%08x]=0x%08x\n", c->cluster_num, - reg, value); - iounmap(virt_addr); - } - - reg = c->pbases[OSM_BASE] + WDOG_PROGRAM_COUNTER; - virt_addr = ioremap(reg, 0x4); - if (virt_addr != NULL) { - value = readl_relaxed(virt_addr); - pr_err("DOM%d_PROGRAM_COUNTER[0x%08x]=0x%08x\n", c->cluster_num, - reg, value); - iounmap(virt_addr); - } - - virt_addr = ioremap(c->apm_ctrl_status, 0x4); - if (virt_addr != NULL) { - value = readl_relaxed(virt_addr); - pr_err("APM_CTLER_STATUS_%d[0x%08x]=0x%08x\n", c->cluster_num, - c->apm_ctrl_status, value); - iounmap(virt_addr); + for (i = 0; i < DEBUG_REG_NUM; i++) { + value = readl_relaxed(c->debug_regs[i]); + pr_err("%s_%d=0x%08x\n", clk_panic_reg_names[i], + c->cluster_num, value); } return NOTIFY_OK; @@ -3020,17 +3067,17 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev) clk_data->clk_num = num_clks; - rc = clk_osm_resources_init(pdev); + rc = clk_osm_parse_dt_configs(pdev); if (rc) { - if (rc != -EPROBE_DEFER) - dev_err(&pdev->dev, "resources init failed, rc=%d\n", - rc); + dev_err(&pdev->dev, "Unable to parse device tree configurations\n"); return rc; } - rc = clk_osm_parse_dt_configs(pdev); + rc = clk_osm_resources_init(pdev); if (rc) { - dev_err(&pdev->dev, "Unable to parse device tree configurations\n"); + if (rc != -EPROBE_DEFER) + dev_err(&pdev->dev, "resources init failed, rc=%d\n", + rc); return rc; } diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 81801605d6e7..823b7d988284 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -1061,8 +1061,9 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle, best_level = i; - if (predicted ? (pred_us <= pwr_params->max_residency) - : (sleep_us <= pwr_params->max_residency)) + if (from_idle && + (predicted ? (pred_us <= pwr_params->max_residency) + : (sleep_us <= pwr_params->max_residency))) break; } diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 84d3ec98e6b9..7f29f3644fb6 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -3,7 +3,7 @@ config DRM_MSM tristate "MSM DRM" depends on DRM depends on ARCH_QCOM || (ARM && COMPILE_TEST) - depends on OF && COMMON_CLK + depends on OF select REGULATOR select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index bc681057250d..d997cdd2cc7e 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, 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 @@ -134,7 +134,7 @@ static void kgsl_iommu_unmap_globals(struct kgsl_pagetable *pagetable) } } -static void kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable) +static int kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable) { unsigned int i; @@ -143,9 +143,11 @@ static void kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable) int ret = kgsl_mmu_map(pagetable, global_pt_entries[i].memdesc); - BUG_ON(ret); + if (ret) + return ret; } } + return 0; } static void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_pagetable @@ -158,16 +160,16 @@ static void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_pagetable } -static void kgsl_map_global_secure_pt_entry(struct kgsl_pagetable *pagetable) +static int kgsl_map_global_secure_pt_entry(struct kgsl_pagetable *pagetable) { - int ret; + int ret = 0; struct kgsl_memdesc *entry = kgsl_global_secure_pt_entry; if (entry != NULL) { entry->pagetable = pagetable; ret = kgsl_mmu_map(pagetable, entry); - BUG_ON(ret); } + return ret; } static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu, @@ -1171,7 +1173,7 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) goto done; } - kgsl_iommu_map_globals(pt); + ret = kgsl_iommu_map_globals(pt); done: if (ret) @@ -1227,7 +1229,7 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) ctx->regbase = iommu->regbase + KGSL_IOMMU_CB0_OFFSET + (cb_num << KGSL_IOMMU_CB_SHIFT); - kgsl_map_global_secure_pt_entry(pt); + ret = kgsl_map_global_secure_pt_entry(pt); done: if (ret) @@ -1288,7 +1290,7 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) goto done; } - kgsl_iommu_map_globals(pt); + ret = kgsl_iommu_map_globals(pt); done: if (ret) diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index a37b5ce9a6b2..287d839f98d0 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -2824,6 +2824,8 @@ err_late_init: unregister_hotcpu_notifier(&etm4_cpu_notifier); unregister_hotcpu_notifier(&etm4_cpu_dying_notifier); } + etmdrvdata[drvdata->cpu] = NULL; + dev_set_drvdata(dev, NULL); return ret; } diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 9b8bcdffdfba..2557dcda7621 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -25,14 +25,6 @@ config INPUT if INPUT -config QPNP_POWER_ON - tristate "QPNP PMIC POWER-ON Driver" - depends on SPMI && ARCH_QCOM - help - This driver supports the power-on functionality on Qualcomm - PNP PMIC. It currently supports reporting the change in status of - the KPDPWR_N line (connected to the power-key). - config INPUT_LEDS tristate "Export input device LEDs in sysfs" depends on LEDS_CLASS diff --git a/drivers/input/Makefile b/drivers/input/Makefile index fd35ebf6acd9..2a6d05ab9170 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_INPUT) += input-core.o input-core-y := input.o input-compat.o input-mt.o ff-core.o -obj-$(CONFIG_QPNP_POWER_ON) += qpnp-power-on.o obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 9c1380b65b77..5cfa1848e37c 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -161,6 +161,15 @@ config INPUT_PMIC8XXX_PWRKEY To compile this driver as a module, choose M here: the module will be called pmic8xxx-pwrkey. +config INPUT_QPNP_POWER_ON + tristate "QPNP PMIC Power-on support" + depends on SPMI + help + This option enables device driver support for the power-on + functionality of Qualcomm Technologies, Inc. PNP PMICs. It supports + reporting the change in status of the KPDPWR_N line (connected to the + power-key) as well as reset features. + config INPUT_SPARCSPKR tristate "SPARC Speaker support" depends on PCI && SPARC64 diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 4e806ac056ce..a5ab4b762d31 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o +obj-$(CONFIG_INPUT_QPNP_POWER_ON) += qpnp-power-on.o obj-$(CONFIG_INPUT_POWERMATE) += powermate.o obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o diff --git a/drivers/input/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index 967b23cae05c..e1c16aa5da43 100644 --- a/drivers/input/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -30,7 +30,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> -#include <linux/qpnp/power-on.h> +#include <linux/input/qpnp-power-on.h> #include <linux/power_supply.h> #define PMIC_VER_8941 0x01 @@ -223,7 +223,7 @@ struct qpnp_pon { static int pon_ship_mode_en; module_param_named( - ship_mode_en, pon_ship_mode_en, int, S_IRUSR | S_IWUSR + ship_mode_en, pon_ship_mode_en, int, 0600 ); static struct qpnp_pon *sys_reset_dev; diff --git a/drivers/media/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c index 0d44deed65bd..8ab60a4fec00 100644 --- a/drivers/media/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb-core/dvb_ringbuffer.c @@ -233,9 +233,11 @@ ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, */ smp_store_release(&rbuf->pwrite, 0); } - status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo); - if (status) - return len - todo; + + if (copy_from_user(rbuf->data + rbuf->pwrite, buf, todo)) { + smp_store_release(&rbuf->pwrite, oldpwrite); + return -EFAULT; + } /* smp_store_release() for write pointer update, see above */ smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size); diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c index 6c09f3820dfd..34fffa8dd7ce 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c +++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c @@ -686,6 +686,50 @@ error: } EXPORT_SYMBOL(msm_camera_regulator_enable); +/* set regulator mode */ +int msm_camera_regulator_set_mode(struct msm_cam_regulator *vdd_info, + int cnt, bool mode) +{ + int i; + int rc; + struct msm_cam_regulator *tmp = vdd_info; + + if (!tmp) { + pr_err("Invalid params"); + return -EINVAL; + } + CDBG("cnt : %d\n", cnt); + + for (i = 0; i < cnt; i++) { + if (tmp && !IS_ERR_OR_NULL(tmp->vdd)) { + CDBG("name : %s, enable : %d\n", tmp->name, mode); + if (mode) { + rc = regulator_set_mode(tmp->vdd, + REGULATOR_MODE_FAST); + if (rc < 0) { + pr_err("regulator enable failed %d\n", + i); + goto error; + } + } else { + rc = regulator_set_mode(tmp->vdd, + REGULATOR_MODE_NORMAL); + if (rc < 0) + pr_err("regulator disable failed %d\n", + i); + goto error; + } + } + tmp++; + } + + return 0; +error: + return rc; +} +EXPORT_SYMBOL(msm_camera_regulator_set_mode); + + /* Put regulators regulators */ void msm_camera_put_regulators(struct platform_device *pdev, struct msm_cam_regulator **vdd_info, int cnt) diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h index 0e9d26bebe30..55074490bd72 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h +++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h @@ -248,6 +248,23 @@ int msm_camera_regulator_enable(struct msm_cam_regulator *vdd_info, int cnt, int enable); /** + * @brief : set the regultors mode + * + * This function sets the regulators for a specific + * mode. say:REGULATOR_MODE_FAST/REGULATOR_MODE_NORMAL + * + * @param vdd_info: Pointer to list of regulators + * @param cnt: Number of regulators to enable/disable + * @param mode: Flags specifies either enable/disable + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ + +int msm_camera_regulator_set_mode(struct msm_cam_regulator *vdd_info, + int cnt, bool mode); + + +/** * @brief : Release the regulators * * This function releases the regulator resources. diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c index 35daf30bac63..840d84388a17 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c @@ -500,6 +500,10 @@ static int vfe_probe(struct platform_device *pdev) memset(&vfe_common_data, 0, sizeof(vfe_common_data)); mutex_init(&vfe_common_data.vfe_common_mutex); spin_lock_init(&vfe_common_data.common_dev_data_lock); + spin_lock_init(&vfe_common_data.vfe_irq_dump. + common_dev_irq_dump_lock); + spin_lock_init(&vfe_common_data.vfe_irq_dump. + common_dev_tasklet_dump_lock); for (i = 0; i < (VFE_AXI_SRC_MAX * MAX_VFE); i++) spin_lock_init(&(vfe_common_data.streams[i].lock)); for (i = 0; i < (MSM_ISP_STATS_MAX * MAX_VFE); i++) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index 9c7eba21fde1..4b881f4fd7b6 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -66,6 +66,8 @@ #define MAX_BUFFERS_IN_HW 2 #define MAX_VFE 2 +#define MAX_VFE_IRQ_DEBUG_DUMP_SIZE 10 +#define MAX_RECOVERY_THRESHOLD 5 struct vfe_device; struct msm_vfe_axi_stream; @@ -133,6 +135,8 @@ struct msm_isp_timestamp { }; struct msm_vfe_irq_ops { + void (*read_and_clear_irq_status)(struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t *irq_status1); void (*read_irq_status)(struct vfe_device *vfe_dev, uint32_t *irq_status0, uint32_t *irq_status1); void (*process_reg_update)(struct vfe_device *vfe_dev, @@ -525,6 +529,7 @@ struct msm_vfe_axi_shared_data { uint16_t stream_handle_cnt; uint32_t event_mask; uint8_t enable_frameid_recovery; + uint8_t recovery_count; }; struct msm_vfe_stats_hardware_info { @@ -691,6 +696,26 @@ struct master_slave_resource_info { enum msm_vfe_dual_cam_sync_mode dual_sync_mode; }; +struct msm_vfe_irq_debug_info { + uint32_t vfe_id; + struct msm_isp_timestamp ts; + uint32_t core_id; + uint32_t irq_status0[MAX_VFE]; + uint32_t irq_status1[MAX_VFE]; + uint32_t ping_pong_status[MAX_VFE]; +}; + +struct msm_vfe_irq_dump { + spinlock_t common_dev_irq_dump_lock; + spinlock_t common_dev_tasklet_dump_lock; + uint8_t current_irq_index; + uint8_t current_tasklet_index; + struct msm_vfe_irq_debug_info + irq_debug[MAX_VFE_IRQ_DEBUG_DUMP_SIZE]; + struct msm_vfe_irq_debug_info + tasklet_debug[MAX_VFE_IRQ_DEBUG_DUMP_SIZE]; +}; + struct msm_vfe_common_dev_data { spinlock_t common_dev_data_lock; struct dual_vfe_resource *dual_vfe_res; @@ -698,6 +723,8 @@ struct msm_vfe_common_dev_data { struct msm_vfe_axi_stream streams[VFE_AXI_SRC_MAX * MAX_VFE]; struct msm_vfe_stats_stream stats_streams[MSM_ISP_STATS_MAX * MAX_VFE]; struct mutex vfe_common_mutex; + /* Irq debug Info */ + struct msm_vfe_irq_dump vfe_irq_dump; }; struct msm_vfe_common_subdev { @@ -790,8 +817,9 @@ struct vfe_device { /* irq info */ uint32_t irq0_mask; uint32_t irq1_mask; - uint32_t bus_err_ign_mask; + uint32_t recovery_irq0_mask; + uint32_t recovery_irq1_mask; }; struct vfe_parent_device { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c index 43f562b18209..bf18fc59585c 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c @@ -576,7 +576,7 @@ static void msm_vfe32_process_error_status(struct vfe_device *vfe_dev) pr_err("%s: axi error\n", __func__); } -static void msm_vfe32_read_irq_status(struct vfe_device *vfe_dev, +static void msm_vfe32_read_and_clear_irq_status(struct vfe_device *vfe_dev, uint32_t *irq_status0, uint32_t *irq_status1) { *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C); @@ -594,6 +594,13 @@ static void msm_vfe32_read_irq_status(struct vfe_device *vfe_dev, msm_camera_io_r(vfe_dev->vfe_base + 0x7B4); } +static void msm_vfe32_read_irq_status(struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t irq_status1) +{ + *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C); + *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x30); +} + static void msm_vfe32_process_reg_update(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, struct msm_isp_timestamp *ts) @@ -1423,6 +1430,8 @@ struct msm_vfe_hardware_info vfe32_hw_info = { .vfe_clk_idx = VFE32_CLK_IDX, .vfe_ops = { .irq_ops = { + .read_and_clear_irq_status = + msm_vfe32_read_and_clear_irq_status, .read_irq_status = msm_vfe32_read_irq_status, .process_camif_irq = msm_vfe32_process_camif_irq, .process_reset_irq = msm_vfe32_process_reset_irq, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index ab01d37790d6..8e549c338bdd 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -566,7 +566,7 @@ static void msm_vfe40_process_error_status(struct vfe_device *vfe_dev) msm_isp_update_last_overflow_ab_ib(vfe_dev); } -static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev, +static void msm_vfe40_read_and_clear_irq_status(struct vfe_device *vfe_dev, uint32_t *irq_status0, uint32_t *irq_status1) { *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38); @@ -599,6 +599,13 @@ static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev, } +static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t *irq_status1) +{ + *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38); + *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x3C); +} + static void msm_vfe40_process_reg_update(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, struct msm_isp_timestamp *ts) @@ -1770,7 +1777,8 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev, static void msm_vfe40_axi_restart(struct vfe_device *vfe_dev, uint32_t blocking, uint32_t enable_camif) { - msm_vfe40_config_irq(vfe_dev, 0x800000E0, 0xFEFFFF7E, + msm_vfe40_config_irq(vfe_dev, vfe_dev->recovery_irq0_mask, + vfe_dev->recovery_irq1_mask, MSM_ISP_IRQ_ENABLE); msm_camera_io_w_mb(0x140000, vfe_dev->vfe_base + 0x318); @@ -2198,6 +2206,8 @@ struct msm_vfe_hardware_info vfe40_hw_info = { .min_ib = 12000000, .vfe_ops = { .irq_ops = { + .read_and_clear_irq_status = + msm_vfe40_read_and_clear_irq_status, .read_irq_status = msm_vfe40_read_irq_status, .process_camif_irq = msm_vfe40_process_input_irq, .process_reset_irq = msm_vfe40_process_reset_irq, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c index 0a72a041de28..957cbc292be3 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c @@ -401,7 +401,7 @@ static void msm_vfe44_process_error_status(struct vfe_device *vfe_dev) } } -static void msm_vfe44_read_irq_status(struct vfe_device *vfe_dev, +static void msm_vfe44_read_and_clear_irq_status(struct vfe_device *vfe_dev, uint32_t *irq_status0, uint32_t *irq_status1) { *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38); @@ -429,6 +429,13 @@ static void msm_vfe44_read_irq_status(struct vfe_device *vfe_dev, } +static void msm_vfe44_read_irq_status(struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t *irq_status1) +{ + *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38); + *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x3C); +} + static void msm_vfe44_process_reg_update(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, struct msm_isp_timestamp *ts) @@ -1341,8 +1348,8 @@ static int msm_vfe44_axi_halt(struct vfe_device *vfe_dev, static void msm_vfe44_axi_restart(struct vfe_device *vfe_dev, uint32_t blocking, uint32_t enable_camif) { - msm_vfe44_config_irq(vfe_dev, 0x800000E0, 0xFFFFFF7E, - MSM_ISP_IRQ_ENABLE); + msm_vfe44_config_irq(vfe_dev, vfe_dev->recovery_irq0_mask, + vfe_dev->recovery_irq1_mask, MSM_ISP_IRQ_ENABLE); msm_camera_io_w_mb(0x140000, vfe_dev->vfe_base + 0x318); /* Start AXI */ @@ -1806,6 +1813,8 @@ struct msm_vfe_hardware_info vfe44_hw_info = { .min_ib = 100000000, .vfe_ops = { .irq_ops = { + .read_and_clear_irq_status = + msm_vfe44_read_and_clear_irq_status, .read_irq_status = msm_vfe44_read_irq_status, .process_camif_irq = msm_vfe44_process_input_irq, .process_reset_irq = msm_vfe44_process_reset_irq, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c index f2d53c956fdc..cc768db875db 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c @@ -345,7 +345,7 @@ static void msm_vfe46_process_error_status(struct vfe_device *vfe_dev) pr_err("%s: status bf scale bus overflow\n", __func__); } -static void msm_vfe46_read_irq_status(struct vfe_device *vfe_dev, +static void msm_vfe46_read_and_clear_irq_status(struct vfe_device *vfe_dev, uint32_t *irq_status0, uint32_t *irq_status1) { *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x6C); @@ -369,6 +369,13 @@ static void msm_vfe46_read_irq_status(struct vfe_device *vfe_dev, } +static void msm_vfe46_read_irq_status(struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t *irq_status1) +{ + *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x6C); + *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x70); +} + static void msm_vfe46_process_reg_update(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, struct msm_isp_timestamp *ts) @@ -1406,7 +1413,8 @@ static int msm_vfe46_axi_halt(struct vfe_device *vfe_dev, static void msm_vfe46_axi_restart(struct vfe_device *vfe_dev, uint32_t blocking, uint32_t enable_camif) { - msm_vfe46_config_irq(vfe_dev, 0x810000E0, 0xFFFFFF7E, + msm_vfe46_config_irq(vfe_dev, vfe_dev->recovery_irq0_mask, + vfe_dev->recovery_irq1_mask, MSM_ISP_IRQ_ENABLE); msm_camera_io_w_mb(0x20000, vfe_dev->vfe_base + 0x3CC); @@ -1882,6 +1890,8 @@ struct msm_vfe_hardware_info vfe46_hw_info = { .min_ib = 100000000, .vfe_ops = { .irq_ops = { + .read_and_clear_irq_status = + msm_vfe46_read_and_clear_irq_status, .read_irq_status = msm_vfe46_read_irq_status, .process_camif_irq = msm_vfe46_process_input_irq, .process_reset_irq = msm_vfe46_process_reset_irq, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 71ee9211a434..9747cfd6dca3 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -556,7 +556,7 @@ void msm_vfe47_process_error_status(struct vfe_device *vfe_dev) pr_err("%s: status dsp error\n", __func__); } -void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev, +void msm_vfe47_read_and_clear_irq_status(struct vfe_device *vfe_dev, uint32_t *irq_status0, uint32_t *irq_status1) { *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x6C); @@ -582,6 +582,13 @@ void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev, } +void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t *irq_status1) +{ + *irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x6C); + *irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x70); +} + void msm_vfe47_process_reg_update(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, struct msm_isp_timestamp *ts) @@ -1931,7 +1938,9 @@ void msm_vfe47_axi_restart(struct vfe_device *vfe_dev, uint32_t blocking, uint32_t enable_camif) { vfe_dev->hw_info->vfe_ops.irq_ops.config_irq(vfe_dev, - 0x810000E0, 0xFFFFFF7E, MSM_ISP_IRQ_ENABLE); + vfe_dev->recovery_irq0_mask, + vfe_dev->recovery_irq1_mask, + MSM_ISP_IRQ_ENABLE); /* Start AXI */ msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x400); @@ -2783,7 +2792,8 @@ struct msm_vfe_hardware_info vfe47_hw_info = { .min_ab = 100000000, .vfe_ops = { .irq_ops = { - .read_irq_status = msm_vfe47_read_irq_status, + .read_and_clear_irq_status = + msm_vfe47_read_and_clear_irq_status, .process_camif_irq = msm_vfe47_process_input_irq, .process_reset_irq = msm_vfe47_process_reset_irq, .process_halt_irq = msm_vfe47_process_halt_irq, @@ -2793,6 +2803,7 @@ struct msm_vfe_hardware_info vfe47_hw_info = { .process_stats_irq = msm_isp_process_stats_irq, .process_epoch_irq = msm_vfe47_process_epoch_irq, .config_irq = msm_vfe47_config_irq, + .read_irq_status = msm_vfe47_read_irq_status, }, .axi_ops = { .reload_wm = msm_vfe47_axi_reload_wm, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h index 55cf6a17b18c..22a1a21bce9a 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h @@ -30,6 +30,8 @@ enum msm_vfe47_stats_comp_idx { extern struct msm_vfe_hardware_info vfe47_hw_info; +void msm_vfe47_read_and_clear_irq_status(struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t *irq_status1); void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev, uint32_t *irq_status0, uint32_t *irq_status1); void msm_vfe47_enable_camif_error(struct vfe_device *vfe_dev, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c index f346ceb6c9e5..1f2db9683cd0 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c @@ -26,6 +26,25 @@ #include "cam_soc_api.h" #define MSM_VFE48_BUS_CLIENT_INIT 0xABAB +#define VFE48_STATS_BURST_LEN 3 +#define VFE48_UB_SIZE_VFE 2048 /* 2048 * 256 bits = 64KB */ +#define VFE48_UB_STATS_SIZE 144 +#define MSM_ISP48_TOTAL_IMAGE_UB_VFE (VFE48_UB_SIZE_VFE - VFE48_UB_STATS_SIZE) + + +static uint32_t stats_base_addr[] = { + 0x1D4, /* HDR_BE */ + 0x254, /* BG(AWB_BG) */ + 0x214, /* BF */ + 0x1F4, /* HDR_BHIST */ + 0x294, /* RS */ + 0x2B4, /* CS */ + 0x2D4, /* IHIST */ + 0x274, /* BHIST (SKIN_BHIST) */ + 0x234, /* AEC_BG */ +}; + +#define VFE48_STATS_BASE(idx) (stats_base_addr[idx]) static struct msm_vfe_axi_hardware_info msm_vfe48_axi_hw_info = { .num_wm = 7, @@ -260,6 +279,40 @@ static void msm_vfe48_set_bus_err_ign_mask(struct vfe_device *vfe_dev, vfe_dev->bus_err_ign_mask &= ~(1 << wm); } +void msm_vfe48_stats_cfg_ub(struct vfe_device *vfe_dev) +{ + int i; + uint32_t ub_offset = 0, stats_burst_len; + uint32_t ub_size[VFE47_NUM_STATS_TYPE] = { + 16, /* MSM_ISP_STATS_HDR_BE */ + 16, /* MSM_ISP_STATS_BG */ + 16, /* MSM_ISP_STATS_BF */ + 16, /* MSM_ISP_STATS_HDR_BHIST */ + 16, /* MSM_ISP_STATS_RS */ + 16, /* MSM_ISP_STATS_CS */ + 16, /* MSM_ISP_STATS_IHIST */ + 16, /* MSM_ISP_STATS_BHIST */ + 16, /* MSM_ISP_STATS_AEC_BG */ + }; + + stats_burst_len = VFE48_STATS_BURST_LEN; + ub_offset = VFE48_UB_SIZE_VFE; + + for (i = 0; i < VFE47_NUM_STATS_TYPE; i++) { + ub_offset -= ub_size[i]; + msm_camera_io_w(stats_burst_len << 30 | + ub_offset << 16 | (ub_size[i] - 1), + vfe_dev->vfe_base + VFE48_STATS_BASE(i) + 0x14); + } +} + +uint32_t msm_vfe48_get_ub_size(struct vfe_device *vfe_dev) +{ + return MSM_ISP48_TOTAL_IMAGE_UB_VFE; +} + + + struct msm_vfe_hardware_info vfe48_hw_info = { .num_iommu_ctx = 1, .num_iommu_secure_ctx = 0, @@ -269,6 +322,8 @@ struct msm_vfe_hardware_info vfe48_hw_info = { .min_ab = 100000000, .vfe_ops = { .irq_ops = { + .read_and_clear_irq_status = + msm_vfe47_read_and_clear_irq_status, .read_irq_status = msm_vfe47_read_irq_status, .process_camif_irq = msm_vfe47_process_input_irq, .process_reset_irq = msm_vfe47_process_reset_irq, @@ -307,7 +362,7 @@ struct msm_vfe_hardware_info vfe48_hw_info = { .update_cgc_override = msm_vfe47_axi_update_cgc_override, .ub_reg_offset = msm_vfe47_ub_reg_offset, - .get_ub_size = msm_vfe47_get_ub_size, + .get_ub_size = msm_vfe48_get_ub_size, }, .core_ops = { .reg_update = msm_vfe47_reg_update, @@ -345,7 +400,7 @@ struct msm_vfe_hardware_info vfe48_hw_info = { .clear_wm_irq_mask = msm_vfe47_stats_clear_wm_irq_mask, .cfg_wm_reg = msm_vfe47_stats_cfg_wm_reg, .clear_wm_reg = msm_vfe47_stats_clear_wm_reg, - .cfg_ub = msm_vfe47_stats_cfg_ub, + .cfg_ub = msm_vfe48_stats_cfg_ub, .enable_module = msm_vfe47_stats_enable_module, .update_ping_pong_addr = msm_vfe47_stats_update_ping_pong_addr, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.h index ccca2010105f..3cf819fb1174 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.h @@ -32,4 +32,8 @@ static inline int msm_vfe_is_vfe48(struct vfe_device *vfe_dev) MSM_VFE48_HW_VERSION_MASK) == MSM_VFE48_HW_VERSION); } +void msm_vfe48_stats_cfg_ub(struct vfe_device *vfe_dev); +uint32_t msm_vfe48_get_ub_size(struct vfe_device *vfe_dev); + + #endif /* __MSM_ISP48_H__ */ diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 941119fad78e..60801ff6be0a 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -558,6 +558,7 @@ static int msm_isp_composite_irq(struct vfe_device *vfe_dev, { /* interrupt recv on same vfe w/o recv on other vfe */ if (stream_info->composite_irq[irq] & (1 << vfe_dev->pdev->id)) { + msm_isp_dump_ping_pong_mismatch(vfe_dev); pr_err("%s: irq %d out of sync for dual vfe on vfe %d\n", __func__, irq, vfe_dev->pdev->id); return -EINVAL; @@ -1604,7 +1605,23 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event) struct msm_isp_event_data error_event; struct msm_vfe_axi_halt_cmd halt_cmd; struct vfe_device *temp_dev = NULL; + uint32_t irq_status0 = 0, irq_status1 = 0; + if (atomic_read(&vfe_dev->error_info.overflow_state) != + NO_OVERFLOW) + /* Recovery is already in Progress */ + return; + + if (event == ISP_EVENT_PING_PONG_MISMATCH && + vfe_dev->axi_data.recovery_count < MAX_RECOVERY_THRESHOLD) { + pr_err("%s: ping pong mismatch on vfe%d recovery count %d\n", + __func__, vfe_dev->pdev->id, + vfe_dev->axi_data.recovery_count); + msm_isp_process_overflow_irq(vfe_dev, + &irq_status0, &irq_status1, 1); + vfe_dev->axi_data.recovery_count++; + return; + } memset(&halt_cmd, 0, sizeof(struct msm_vfe_axi_halt_cmd)); memset(&error_event, 0, sizeof(struct msm_isp_event_data)); halt_cmd.stop_camif = 1; @@ -3777,6 +3794,7 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, (~(pingpong_status >> stream_info->wm[vfe_idx][i]) & 0x1)) { spin_unlock_irqrestore(&stream_info->lock, flags); + msm_isp_dump_ping_pong_mismatch(vfe_dev); pr_err("%s: Write master ping pong mismatch. Status: 0x%x %x\n", __func__, pingpong_status, stream_info->stream_src); @@ -3798,7 +3816,7 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, spin_unlock_irqrestore(&stream_info->lock, flags); if (rc < 0) msm_isp_halt_send_error(vfe_dev, - ISP_EVENT_BUF_FATAL_ERROR); + ISP_EVENT_PING_PONG_MISMATCH); return; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c index 38ce78d941c9..72703c9590ed 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c @@ -195,7 +195,7 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev, spin_unlock_irqrestore(&stream_info->lock, flags); if (rc < 0) msm_isp_halt_send_error(vfe_dev, - ISP_EVENT_BUF_FATAL_ERROR); + ISP_EVENT_PING_PONG_MISMATCH); return rc; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 4abb6d1d91a8..e238f54a9100 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -21,6 +21,9 @@ #include "msm_camera_io_util.h" #include "cam_smmu_api.h" #include "msm_isp48.h" +#define CREATE_TRACE_POINTS +#include "trace/events/msm_cam.h" + #define MAX_ISP_V4l2_EVENTS 100 static DEFINE_MUTEX(bandwidth_mgr_mutex); @@ -1784,9 +1787,10 @@ static inline void msm_isp_update_error_info(struct vfe_device *vfe_dev, vfe_dev->error_info.error_count++; } -static int msm_isp_process_overflow_irq( +int msm_isp_process_overflow_irq( struct vfe_device *vfe_dev, - uint32_t *irq_status0, uint32_t *irq_status1) + uint32_t *irq_status0, uint32_t *irq_status1, + uint8_t force_overflow) { uint32_t overflow_mask; uint32_t bus_err = 0; @@ -1816,7 +1820,7 @@ static int msm_isp_process_overflow_irq( get_overflow_mask(&overflow_mask); overflow_mask &= *irq_status1; - if (overflow_mask) { + if (overflow_mask || force_overflow) { struct msm_isp_event_data error_event; int i; struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; @@ -1840,7 +1844,8 @@ static int msm_isp_process_overflow_irq( pr_err("%s: wm %d assigned to stream handle %x\n", __func__, i, axi_data->free_wm[i]); } - + vfe_dev->recovery_irq0_mask = vfe_dev->irq0_mask; + vfe_dev->recovery_irq1_mask = vfe_dev->irq1_mask; vfe_dev->hw_info->vfe_ops.core_ops. set_halt_restart_mask(vfe_dev); /* mask off other vfe if dual vfe is used */ @@ -1855,6 +1860,8 @@ static int msm_isp_process_overflow_irq( atomic_set(&temp_vfe->error_info.overflow_state, OVERFLOW_DETECTED); + temp_vfe->recovery_irq0_mask = temp_vfe->irq0_mask; + temp_vfe->recovery_irq1_mask = temp_vfe->irq1_mask; temp_vfe->hw_info->vfe_ops.core_ops. set_halt_restart_mask(temp_vfe); } @@ -1889,6 +1896,77 @@ void msm_isp_reset_burst_count_and_frame_drop( msm_isp_reset_framedrop(vfe_dev, stream_info); } +void msm_isp_prepare_irq_debug_info(struct vfe_device *vfe_dev, + uint32_t irq_status0, uint32_t irq_status1) +{ + + unsigned long flags; + struct msm_vfe_irq_debug_info *irq_debug; + uint8_t current_index; + + spin_lock_irqsave(&vfe_dev->common_data->vfe_irq_dump. + common_dev_irq_dump_lock, flags); + /* Fill current VFE debug info */ + current_index = vfe_dev->common_data->vfe_irq_dump. + current_irq_index % MAX_VFE_IRQ_DEBUG_DUMP_SIZE; + irq_debug = &vfe_dev->common_data->vfe_irq_dump. + irq_debug[current_index]; + irq_debug->vfe_id = vfe_dev->pdev->id; + irq_debug->core_id = smp_processor_id(); + msm_isp_get_timestamp(&irq_debug->ts, vfe_dev); + irq_debug->irq_status0[vfe_dev->pdev->id] = irq_status0; + irq_debug->irq_status1[vfe_dev->pdev->id] = irq_status1; + irq_debug->ping_pong_status[vfe_dev->pdev->id] = + vfe_dev->hw_info->vfe_ops.axi_ops. + get_pingpong_status(vfe_dev); + if (vfe_dev->is_split && + (vfe_dev->common_data-> + dual_vfe_res->vfe_dev[!vfe_dev->pdev->id]) + && (vfe_dev->common_data->dual_vfe_res-> + vfe_dev[!vfe_dev->pdev->id]->vfe_open_cnt)) { + /* Fill other VFE debug Info */ + vfe_dev->hw_info->vfe_ops.irq_ops.read_irq_status( + vfe_dev->common_data->dual_vfe_res-> + vfe_dev[!vfe_dev->pdev->id], + &irq_debug->irq_status0[!vfe_dev->pdev->id], + &irq_debug->irq_status1[!vfe_dev->pdev->id]); + irq_debug->ping_pong_status[!vfe_dev->pdev->id] = + vfe_dev->hw_info->vfe_ops.axi_ops. + get_pingpong_status(vfe_dev->common_data-> + dual_vfe_res->vfe_dev[!vfe_dev->pdev->id]); + } + vfe_dev->common_data->vfe_irq_dump.current_irq_index++; + spin_unlock_irqrestore(&vfe_dev->common_data->vfe_irq_dump. + common_dev_irq_dump_lock, flags); +} + +void msm_isp_prepare_tasklet_debug_info(struct vfe_device *vfe_dev, + uint32_t irq_status0, uint32_t irq_status1, + struct msm_isp_timestamp ts) +{ + struct msm_vfe_irq_debug_info *irq_debug; + uint8_t current_index; + unsigned long flags; + + spin_lock_irqsave(&vfe_dev->common_data->vfe_irq_dump. + common_dev_tasklet_dump_lock, flags); + current_index = vfe_dev->common_data->vfe_irq_dump. + current_tasklet_index % MAX_VFE_IRQ_DEBUG_DUMP_SIZE; + irq_debug = &vfe_dev->common_data->vfe_irq_dump. + tasklet_debug[current_index]; + irq_debug->vfe_id = vfe_dev->pdev->id; + irq_debug->core_id = smp_processor_id(); + irq_debug->ts = ts; + irq_debug->irq_status0[vfe_dev->pdev->id] = irq_status0; + irq_debug->irq_status1[vfe_dev->pdev->id] = irq_status1; + irq_debug->ping_pong_status[vfe_dev->pdev->id] = + vfe_dev->hw_info->vfe_ops.axi_ops. + get_pingpong_status(vfe_dev); + vfe_dev->common_data->vfe_irq_dump.current_tasklet_index++; + spin_unlock_irqrestore(&vfe_dev->common_data->vfe_irq_dump. + common_dev_tasklet_dump_lock, flags); +} + static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1) { @@ -1923,7 +2001,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data) uint32_t error_mask0, error_mask1; vfe_dev->hw_info->vfe_ops.irq_ops. - read_irq_status(vfe_dev, &irq_status0, &irq_status1); + read_and_clear_irq_status(vfe_dev, &irq_status0, &irq_status1); if ((irq_status0 == 0) && (irq_status1 == 0)) { ISP_DBG("%s:VFE%d irq_status0 & 1 are both 0\n", @@ -1932,7 +2010,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data) } if (msm_isp_process_overflow_irq(vfe_dev, - &irq_status0, &irq_status1)) { + &irq_status0, &irq_status1, 0)) { /* if overflow initiated no need to handle the interrupts */ pr_err("overflow processed\n"); return IRQ_HANDLED; @@ -1953,7 +2031,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data) ISP_DBG("%s: error_mask0/1 & error_count are set!\n", __func__); return IRQ_HANDLED; } - + msm_isp_prepare_irq_debug_info(vfe_dev, irq_status0, irq_status1); msm_isp_enqueue_tasklet_cmd(vfe_dev, irq_status0, irq_status1); return IRQ_HANDLED; @@ -1991,6 +2069,8 @@ void msm_isp_do_tasklet(unsigned long data) irq_status1 = queue_cmd->vfeInterruptStatus1; ts = queue_cmd->ts; spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); + msm_isp_prepare_tasklet_debug_info(vfe_dev, + irq_status0, irq_status1, ts); ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n", __func__, vfe_dev->pdev->id, irq_status0, irq_status1); irq_ops->process_reset_irq(vfe_dev, @@ -2242,3 +2322,53 @@ void msm_isp_flush_tasklet(struct vfe_device *vfe_dev) return; } +void msm_isp_irq_debug_dump(struct vfe_device *vfe_dev) +{ + + uint8_t i, dump_index; + unsigned long flags; + + spin_lock_irqsave(&vfe_dev->common_data->vfe_irq_dump. + common_dev_irq_dump_lock, flags); + dump_index = vfe_dev->common_data->vfe_irq_dump. + current_irq_index; + for (i = 0; i < MAX_VFE_IRQ_DEBUG_DUMP_SIZE; i++) { + trace_msm_cam_ping_pong_debug_dump( + vfe_dev->common_data->vfe_irq_dump. + irq_debug[dump_index % MAX_VFE_IRQ_DEBUG_DUMP_SIZE]); + dump_index++; + } + spin_unlock_irqrestore(&vfe_dev->common_data->vfe_irq_dump. + common_dev_irq_dump_lock, flags); +} + + +void msm_isp_tasklet_debug_dump(struct vfe_device *vfe_dev) +{ + + uint8_t i, dump_index; + unsigned long flags; + + spin_lock_irqsave(&vfe_dev->common_data->vfe_irq_dump. + common_dev_tasklet_dump_lock, flags); + dump_index = vfe_dev->common_data->vfe_irq_dump. + current_tasklet_index; + for (i = 0; i < MAX_VFE_IRQ_DEBUG_DUMP_SIZE; i++) { + trace_msm_cam_tasklet_debug_dump( + vfe_dev->common_data->vfe_irq_dump. + tasklet_debug[ + dump_index % MAX_VFE_IRQ_DEBUG_DUMP_SIZE]); + dump_index++; + } + spin_unlock_irqrestore(&vfe_dev->common_data->vfe_irq_dump. + common_dev_tasklet_dump_lock, flags); +} + +void msm_isp_dump_ping_pong_mismatch(struct vfe_device *vfe_dev) +{ + + trace_msm_cam_string(" ***** msm_isp_dump_irq_debug ****"); + msm_isp_irq_debug_dump(vfe_dev); + trace_msm_cam_string(" ***** msm_isp_dump_taskelet_debug ****"); + msm_isp_tasklet_debug_dump(vfe_dev); +} diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h index f4280581a730..d075bd1721ac 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h @@ -72,4 +72,9 @@ void msm_isp_print_fourcc_error(const char *origin, uint32_t fourcc_format); void msm_isp_flush_tasklet(struct vfe_device *vfe_dev); void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp, struct vfe_device *vfe_dev); +void msm_isp_dump_ping_pong_mismatch(struct vfe_device *vfe_dev); +int msm_isp_process_overflow_irq( + struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t *irq_status1, + uint8_t force_overflow); #endif /* __MSM_ISP_UTIL_H__ */ diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 4527d6699b88..1cf2c54aa8b8 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -1372,6 +1372,7 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) mutex_unlock(&cpp_dev->mutex); return rc; } + cpp_dev->state = CPP_STATE_IDLE; CPP_DBG("Invoking msm_ion_client_create()\n"); @@ -2479,7 +2480,7 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, struct msm_buf_mngr_info buff_mgr_info, dup_buff_mgr_info; int32_t in_fd; int32_t num_output_bufs = 1; - int32_t stripe_base = 0; + uint32_t stripe_base = 0; uint32_t stripe_size; uint8_t tnr_enabled; enum msm_camera_buf_mngr_buf_type buf_type = @@ -2514,6 +2515,13 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, return -EINVAL; } + if (stripe_base == UINT_MAX || new_frame->num_strips > + (UINT_MAX - 1 - stripe_base) / stripe_size) { + pr_err("Invalid frame message,num_strips %d is large\n", + new_frame->num_strips); + return -EINVAL; + } + if ((stripe_base + new_frame->num_strips * stripe_size + 1) != new_frame->msg_len) { pr_err("Invalid frame message,len=%d,expected=%d\n", @@ -4177,27 +4185,22 @@ static int msm_cpp_update_gdscr_status(struct cpp_device *cpp_dev, bool status) { int rc = 0; - int value = 0; - + uint32_t msm_cpp_reg_idx; if (!cpp_dev) { pr_err("%s: cpp device invalid\n", __func__); rc = -EINVAL; goto end; } - - if (cpp_dev->camss_cpp_base) { - value = msm_camera_io_r(cpp_dev->camss_cpp_base); - pr_debug("value from camss cpp %x, status %d\n", value, status); - if (status) { - value &= CPP_GDSCR_SW_COLLAPSE_ENABLE; - value |= CPP_GDSCR_HW_CONTROL_ENABLE; - } else { - value |= CPP_GDSCR_HW_CONTROL_DISABLE; - value &= CPP_GDSCR_SW_COLLAPSE_DISABLE; - } - pr_debug("value %x after camss cpp mask\n", value); - msm_camera_io_w(value, cpp_dev->camss_cpp_base); + msm_cpp_reg_idx = msm_cpp_get_regulator_index(cpp_dev, "vdd"); + if (msm_cpp_reg_idx < 0) { + pr_err(" Fail to regulator index\n"); + return -EINVAL; } + rc = msm_camera_regulator_set_mode(cpp_dev->cpp_vdd + + msm_cpp_reg_idx, 1, status); + if (rc < 0) + pr_err("update cpp gdscr status failed\n"); + end: return rc; } @@ -4306,14 +4309,6 @@ static int cpp_probe(struct platform_device *pdev) memset(&cpp_vbif, 0, sizeof(struct msm_cpp_vbif_data)); cpp_dev->vbif_data = &cpp_vbif; - cpp_dev->camss_cpp_base = - msm_camera_get_reg_base(pdev, "camss_cpp", true); - if (!cpp_dev->camss_cpp_base) { - rc = -ENOMEM; - pr_err("failed to get camss_cpp_base\n"); - goto camss_cpp_base_failed; - } - cpp_dev->base = msm_camera_get_reg_base(pdev, "cpp", true); if (!cpp_dev->base) { @@ -4485,7 +4480,7 @@ vbif_base_failed: cpp_base_failed: msm_camera_put_reg_base(pdev, cpp_dev->camss_cpp_base, "camss_cpp", true); -camss_cpp_base_failed: + kfree(cpp_dev); return rc; } diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h index 470c0cf1131b..e69b9d633a1f 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h @@ -289,6 +289,8 @@ struct cpp_device { int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev); int msm_update_freq_tbl(struct cpp_device *cpp_dev); int msm_cpp_get_clock_index(struct cpp_device *cpp_dev, const char *clk_name); +int msm_cpp_get_regulator_index(struct cpp_device *cpp_dev, + const char *regulator_name); long msm_cpp_set_core_clk(struct cpp_device *cpp_dev, long rate, int idx); void msm_cpp_fetch_dt_params(struct cpp_device *cpp_dev); int msm_cpp_read_payload_params_from_dt(struct cpp_device *cpp_dev); diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c index ddd32fc5c339..f016c348f144 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c @@ -71,6 +71,18 @@ int msm_cpp_get_clock_index(struct cpp_device *cpp_dev, const char *clk_name) return -EINVAL; } +int msm_cpp_get_regulator_index(struct cpp_device *cpp_dev, + const char *regulator_name) +{ + uint32_t i = 0; + + for (i = 0; i < cpp_dev->num_reg; i++) { + if (!strcmp(regulator_name, cpp_dev->cpp_vdd[i].name)) + return i; + } + return -EINVAL; +} + static int cpp_get_clk_freq_tbl_dt(struct cpp_device *cpp_dev) { uint32_t i, count, min_clk_rate; diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c index f2f1dca81f18..d7fb2449582c 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c +++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016 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 @@ -1054,10 +1054,16 @@ static int vpe_reset(struct vpe_device *vpe_dev) return rc; } -static void vpe_update_scale_coef(struct vpe_device *vpe_dev, uint32_t *p) +static int vpe_update_scale_coef(struct vpe_device *vpe_dev, uint32_t *p) { uint32_t i, offset; offset = *p; + + if (offset > VPE_SCALE_COEFF_MAX_N-VPE_SCALE_COEFF_NUM) { + pr_err("%s: invalid offset %d passed in", __func__, offset); + return -EINVAL; + } + for (i = offset; i < (VPE_SCALE_COEFF_NUM + offset); i++) { VPE_DBG("Setting scale table %d\n", i); msm_camera_io_w(*(++p), @@ -1065,6 +1071,8 @@ static void vpe_update_scale_coef(struct vpe_device *vpe_dev, uint32_t *p) msm_camera_io_w(*(++p), vpe_dev->base + VPE_SCALE_COEFF_MSBn(i)); } + + return 0; } static void vpe_input_plane_config(struct vpe_device *vpe_dev, uint32_t *p) @@ -1102,13 +1110,16 @@ static void vpe_operation_config(struct vpe_device *vpe_dev, uint32_t *p) */ static void msm_vpe_transaction_setup(struct vpe_device *vpe_dev, void *data) { - int i; + int i, rc = 0; void *iter = data; vpe_mem_dump("vpe_transaction", data, VPE_TRANSACTION_SETUP_CONFIG_LEN); for (i = 0; i < VPE_NUM_SCALER_TABLES; ++i) { - vpe_update_scale_coef(vpe_dev, (uint32_t *)iter); + rc = vpe_update_scale_coef(vpe_dev, (uint32_t *)iter); + if (rc != 0) + return; + iter += VPE_SCALER_CONFIG_LEN; } vpe_input_plane_config(vpe_dev, (uint32_t *)iter); diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h index f1869a2b9776..0c55ff70309e 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h +++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2014, 2016 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 @@ -70,6 +70,7 @@ #define VPE_SCALE_COEFF_LSBn(n) (0x50400 + 8 * (n)) #define VPE_SCALE_COEFF_MSBn(n) (0x50404 + 8 * (n)) #define VPE_SCALE_COEFF_NUM 32 +#define VPE_SCALE_COEFF_MAX_N 127 /*********** end of register offset ********************/ diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c index 5e763f74170e..9048d54bed38 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012, 2015-2017, 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 @@ -76,7 +76,10 @@ u32 sde_apply_comp_ratio_factor(u32 quota, #define RES_1080p (1088*1920) #define RES_UHD (3840*2160) +#define RES_WQXGA (2560*1600) #define XIN_HALT_TIMEOUT_US 0x4000 +#define MDSS_MDP_HW_REV_320 0x30020000 /* sdm660 */ +#define MDSS_MDP_HW_REV_330 0x30030000 /* sdm630 */ static int sde_mdp_wait_for_xin_halt(u32 xin_id) { @@ -174,15 +177,32 @@ u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd) SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%d rd:%d\n", width, height, fps, pixfmt, is_yuv, res, is_rd); - if (!is_yuv) - goto exit; + switch (mdata->mdss_version) { + case MDSS_MDP_HW_REV_320: + case MDSS_MDP_HW_REV_330: + if ((res <= RES_1080p) && (fps <= 30) && is_yuv) + ot_lim = 2; + else if ((res <= RES_1080p) && (fps <= 60) && is_yuv) + ot_lim = 4; + else if ((res <= RES_UHD) && (fps <= 30) && is_yuv) + ot_lim = 8; + else if ((res <= RES_WQXGA) && (fps <= 60) && is_yuv) + ot_lim = 4; + else if ((res <= RES_WQXGA) && (fps <= 60)) + ot_lim = 16; + break; + default: + if (is_yuv) { + if ((res <= RES_1080p) && (fps <= 30)) + ot_lim = 2; + else if ((res <= RES_1080p) && (fps <= 60)) + ot_lim = 4; + else if ((res <= RES_UHD) && (fps <= 30)) + ot_lim = 8; + } + break; + } - if ((res <= RES_1080p) && (fps <= 30)) - ot_lim = 2; - else if ((res <= RES_1080p) && (fps <= 60)) - ot_lim = 4; - else if ((res <= RES_UHD) && (fps <= 30)) - ot_lim = 8; exit: SDEROT_DBG("ot_lim=%d\n", ot_lim); diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 9970c4152ef9..30d1bae48e7d 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -4418,6 +4418,7 @@ static void __unload_fw(struct venus_hfi_device *device) if (device->state != VENUS_STATE_DEINIT) flush_workqueue(device->venus_pm_workq); + __vote_buses(device, NULL, 0); subsystem_put(device->resources.fw.cookie); __interface_queues_release(device); __venus_power_off(device, false); diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c index b6a476cd882d..2bc8bdff54f1 100644 --- a/drivers/mfd/wcd9xxx-irq.c +++ b/drivers/mfd/wcd9xxx-irq.c @@ -698,20 +698,27 @@ static int wcd9xxx_map_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq) static int wcd9xxx_irq_probe(struct platform_device *pdev) { - int irq; + int irq, dir_apps_irq = -EINVAL; struct wcd9xxx_irq_drv_data *data; struct device_node *node = pdev->dev.of_node; int ret = -EINVAL; irq = of_get_named_gpio(node, "qcom,gpio-connect", 0); - if (!gpio_is_valid(irq)) { + if (!gpio_is_valid(irq)) + dir_apps_irq = platform_get_irq_byname(pdev, "wcd_irq"); + + if (!gpio_is_valid(irq) && dir_apps_irq < 0) { dev_err(&pdev->dev, "TLMM connect gpio not found\n"); return -EPROBE_DEFER; } else { - irq = gpio_to_irq(irq); - if (irq < 0) { - dev_err(&pdev->dev, "Unable to configure irq\n"); - return irq; + if (dir_apps_irq > 0) { + irq = dir_apps_irq; + } else { + irq = gpio_to_irq(irq); + if (irq < 0) { + dev_err(&pdev->dev, "Unable to configure irq\n"); + return irq; + } } dev_dbg(&pdev->dev, "%s: virq = %d\n", __func__, irq); data = wcd9xxx_irq_add_domain(node, node->parent); diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 6b3d84a2c145..20949487f859 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -7660,11 +7660,11 @@ static void __qseecom_deinit_clk(enum qseecom_ce_hw_instance ce) } if (qclk->ce_core_clk != NULL) { clk_put(qclk->ce_core_clk); - qclk->ce_clk = NULL; + qclk->ce_core_clk = NULL; } if (qclk->ce_bus_clk != NULL) { clk_put(qclk->ce_bus_clk); - qclk->ce_clk = NULL; + qclk->ce_bus_clk = NULL; } if (qclk->ce_core_src_clk != NULL) { clk_put(qclk->ce_core_src_clk); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index a3f650f5ee9f..7aa01372412d 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1192,10 +1192,6 @@ static int mmc_select_hs400(struct mmc_card *card) if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) send_status = false; - /* Reduce frequency to HS frequency */ - max_dtr = card->ext_csd.hs_max_dtr; - mmc_set_clock(host, max_dtr); - /* Switch card to HS mode */ val = EXT_CSD_TIMING_HS; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, @@ -1211,6 +1207,10 @@ static int mmc_select_hs400(struct mmc_card *card) /* Set host controller to HS timing */ mmc_set_timing(card->host, MMC_TIMING_MMC_HS); + /* Reduce frequency to HS frequency */ + max_dtr = card->ext_csd.hs_max_dtr; + mmc_set_clock(host, max_dtr); + if (!send_status) { err = mmc_switch_status(card); if (err) diff --git a/drivers/power/qcom-charger/pmic-voter.c b/drivers/power/qcom-charger/pmic-voter.c index 8072b63f53fe..e1a92fb23912 100644 --- a/drivers/power/qcom-charger/pmic-voter.c +++ b/drivers/power/qcom-charger/pmic-voter.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,6 +21,7 @@ #include "pmic-voter.h" #define NUM_MAX_CLIENTS 8 +#define DEBUG_FORCE_CLIENT "DEBUG_FORCE_CLIENT" static DEFINE_SPINLOCK(votable_list_slock); static LIST_HEAD(votable_list); @@ -48,7 +49,12 @@ struct votable { const char *effective_client); char *client_strs[NUM_MAX_CLIENTS]; bool voted_on; - struct dentry *ent; + struct dentry *root; + struct dentry *status_ent; + u32 force_val; + struct dentry *force_val_ent; + bool force_active; + struct dentry *force_active_ent; }; /** @@ -236,6 +242,9 @@ int get_client_vote(struct votable *votable, const char *client_str) */ int get_effective_result_locked(struct votable *votable) { + if (votable->force_active) + return votable->force_val; + return votable->effective_result; } @@ -249,8 +258,29 @@ int get_effective_result(struct votable *votable) return value; } +/** + * get_effective_client() - + * get_effective_client_locked() - + * The unlocked and locked variants of getting the effective client + * amongst all the enabled voters. + * + * @votable: the votable object + * + * Returns: + * The effective client. + * For MIN and MAX votable, returns NULL when the votable + * object has been created but no clients have casted their votes or + * the last enabled client disables its vote. + * For SET_ANY votable it returns NULL too when no clients have casted + * their votes. But for SET_ANY since there is no concept of abstaining + * from election, the only client that casts a vote or the client that + * caused the result to change is returned. + */ const char *get_effective_client_locked(struct votable *votable) { + if (votable->force_active) + return DEBUG_FORCE_CLIENT; + return get_client_str(votable, votable->effective_client_id); } @@ -313,7 +343,7 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val) if ((votable->votes[client_id].enabled == enabled) && (votable->votes[client_id].value == val)) { - pr_debug("%s: %s,%d same vote %s of %d\n", + pr_debug("%s: %s,%d same vote %s of val=%d\n", votable->name, client_str, client_id, enabled ? "on" : "off", @@ -325,13 +355,13 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val) votable->votes[client_id].value = val; if (similar_vote && votable->voted_on) { - pr_debug("%s: %s,%d Similar vote %s of %d\n", + pr_debug("%s: %s,%d Ignoring similar vote %s of val=%d\n", votable->name, client_str, client_id, enabled ? "on" : "off", val); goto out; } - pr_debug("%s: %s,%d voting %s of %d\n", + pr_debug("%s: %s,%d voting %s of val=%d\n", votable->name, client_str, client_id, enabled ? "on" : "off", val); switch (votable->type) { @@ -361,7 +391,7 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val) votable->name, effective_result, get_client_str(votable, effective_id), effective_id); - if (votable->callback) + if (votable->callback && !votable->force_active) rc = votable->callback(votable, votable->data, effective_result, get_client_str(votable, effective_id)); @@ -412,6 +442,42 @@ out: return NULL; } +static int force_active_get(void *data, u64 *val) +{ + struct votable *votable = data; + + *val = votable->force_active; + + return 0; +} + +static int force_active_set(void *data, u64 val) +{ + struct votable *votable = data; + int rc = 0; + + lock_votable(votable); + votable->force_active = !!val; + + if (!votable->callback) + goto out; + + if (votable->force_active) { + rc = votable->callback(votable, votable->data, + votable->force_val, + DEBUG_FORCE_CLIENT); + } else { + rc = votable->callback(votable, votable->data, + votable->effective_result, + get_client_str(votable, votable->effective_client_id)); + } +out: + unlock_votable(votable); + return rc; +} +DEFINE_SIMPLE_ATTRIBUTE(votable_force_ops, force_active_get, force_active_set, + "%lld\n"); + static int show_votable_clients(struct seq_file *m, void *data) { struct votable *votable = m->private; @@ -421,8 +487,8 @@ static int show_votable_clients(struct seq_file *m, void *data) lock_votable(votable); - seq_printf(m, "%s:\n", votable->name); - seq_puts(m, "Clients:\n"); + seq_printf(m, "Votable %s:\n", votable->name); + seq_puts(m, "clients:\n"); for (i = 0; i < votable->num_clients; i++) { if (votable->client_strs[i]) { seq_printf(m, "%-15s:\t\ten=%d\t\tv=%d\n", @@ -444,7 +510,7 @@ static int show_votable_clients(struct seq_file *m, void *data) break; } - seq_printf(m, "Type: %s\n", type_str); + seq_printf(m, "type: %s\n", type_str); seq_puts(m, "Effective:\n"); effective_client_str = get_effective_client_locked(votable); seq_printf(m, "%-15s:\t\tv=%d\n", @@ -455,16 +521,16 @@ static int show_votable_clients(struct seq_file *m, void *data) return 0; } -static int votable_debugfs_open(struct inode *inode, struct file *file) +static int votable_status_open(struct inode *inode, struct file *file) { struct votable *votable = inode->i_private; return single_open(file, show_votable_clients, votable); } -static const struct file_operations votable_debugfs_ops = { +static const struct file_operations votable_status_ops = { .owner = THIS_MODULE, - .open = votable_debugfs_open, + .open = votable_status_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, @@ -527,11 +593,45 @@ struct votable *create_votable(const char *name, list_add(&votable->list, &votable_list); spin_unlock_irqrestore(&votable_list_slock, flags); - votable->ent = debugfs_create_file(name, S_IFREG | S_IRUGO, - debug_root, votable, - &votable_debugfs_ops); - if (!votable->ent) { - pr_err("Couldn't create %s debug file\n", name); + votable->root = debugfs_create_dir(name, debug_root); + if (!votable->root) { + pr_err("Couldn't create debug dir %s\n", name); + kfree(votable->name); + kfree(votable); + return ERR_PTR(-ENOMEM); + } + + votable->status_ent = debugfs_create_file("status", S_IFREG | S_IRUGO, + votable->root, votable, + &votable_status_ops); + if (!votable->status_ent) { + pr_err("Couldn't create status dbg file for %s\n", name); + debugfs_remove_recursive(votable->root); + kfree(votable->name); + kfree(votable); + return ERR_PTR(-EEXIST); + } + + votable->force_val_ent = debugfs_create_u32("force_val", + S_IFREG | S_IWUSR | S_IRUGO, + votable->root, + &(votable->force_val)); + + if (!votable->force_val_ent) { + pr_err("Couldn't create force_val dbg file for %s\n", name); + debugfs_remove_recursive(votable->root); + kfree(votable->name); + kfree(votable); + return ERR_PTR(-EEXIST); + } + + votable->force_active_ent = debugfs_create_file("force_active", + S_IFREG | S_IRUGO, + votable->root, votable, + &votable_force_ops); + if (!votable->force_active_ent) { + pr_err("Couldn't create force_active dbg file for %s\n", name); + debugfs_remove_recursive(votable->root); kfree(votable->name); kfree(votable); return ERR_PTR(-EEXIST); @@ -552,7 +652,8 @@ void destroy_votable(struct votable *votable) list_del(&votable->list); spin_unlock_irqrestore(&votable_list_slock, flags); - debugfs_remove(votable->ent); + debugfs_remove_recursive(votable->root); + for (i = 0; i < votable->num_clients && votable->client_strs[i]; i++) kfree(votable->client_strs[i]); diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index 02f5ea06e22d..8523efa1a4ab 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -2301,7 +2301,14 @@ static int fg_get_time_to_full(struct fg_chip *chip, int *val) return -ENODATA; } - if (chip->charge_status == POWER_SUPPLY_STATUS_FULL) { + rc = fg_get_prop_capacity(chip, &msoc); + if (rc < 0) { + pr_err("failed to get msoc rc=%d\n", rc); + return rc; + } + fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc); + + if (msoc >= 100) { *val = 0; return 0; } @@ -2364,13 +2371,6 @@ static int fg_get_time_to_full(struct fg_chip *chip, int *val) act_cap_uah *= MILLI_UNIT; fg_dbg(chip, FG_TTF, "actual_capacity_uah=%d\n", act_cap_uah); - rc = fg_get_prop_capacity(chip, &msoc); - if (rc < 0) { - pr_err("failed to get msoc rc=%d\n", rc); - return rc; - } - fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc); - rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc); if (rc < 0) { pr_err("failed to get full soc rc=%d\n", rc); @@ -2410,7 +2410,7 @@ skip_cc_estimate: fg_dbg(chip, FG_TTF, "t_predicted_cc=%lld\n", t_predicted_cc); /* CV estimate starts here */ - if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) + if (chip->charge_type >= POWER_SUPPLY_CHARGE_TYPE_TAPER) ln_val = ibatt_avg / abs(chip->dt.sys_term_curr_ma); else ln_val = i_cc2cv / abs(chip->dt.sys_term_curr_ma); diff --git a/drivers/power/qcom-charger/qpnp-qnovo.c b/drivers/power/qcom-charger/qpnp-qnovo.c index ac1c900f4771..7bc90fbf2929 100644 --- a/drivers/power/qcom-charger/qpnp-qnovo.c +++ b/drivers/power/qcom-charger/qpnp-qnovo.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017 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 @@ -99,8 +99,6 @@ #define VADC_LSB_NA 1220700 #define GAIN_LSB_FACTOR 976560 -#define MIN_EN_UA 1000000 - #define USER_VOTER "user_voter" #define OK_TO_QNOVO_VOTER "ok_to_qnovo_voter" @@ -119,9 +117,7 @@ enum { struct chg_props { bool charging; bool usb_online; - int usb_input_uA; bool dc_online; - int dc_input_uA; }; struct chg_status { @@ -1092,7 +1088,6 @@ static void get_chg_props(struct qnovo *chip, struct chg_props *cp) } cp->usb_online = false; - cp->usb_input_uA = 0; if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); if (chip->usb_psy) { @@ -1102,17 +1097,9 @@ static void get_chg_props(struct qnovo *chip, struct chg_props *cp) pr_err("Couldn't read usb online rc = %d\n", rc); else cp->usb_online = (bool)pval.intval; - - rc = power_supply_get_property(chip->usb_psy, - POWER_SUPPLY_PROP_CURRENT_MAX, &pval); - if (rc < 0) - pr_err("Couldn't read usb current max rc = %d\n", rc); - else - cp->usb_input_uA = pval.intval; } cp->dc_online = false; - cp->dc_input_uA = 0; if (!chip->dc_psy) chip->dc_psy = power_supply_get_by_name("dc"); if (chip->dc_psy) { @@ -1122,13 +1109,6 @@ static void get_chg_props(struct qnovo *chip, struct chg_props *cp) pr_err("Couldn't read dc online rc = %d\n", rc); else cp->dc_online = (bool)pval.intval; - - rc = power_supply_get_property(chip->dc_psy, - POWER_SUPPLY_PROP_CURRENT_MAX, &pval); - if (rc < 0) - pr_err("Couldn't read dc current max rc = %d\n", rc); - else - cp->dc_input_uA = pval.intval; } } @@ -1138,8 +1118,7 @@ static void get_chg_status(struct qnovo *chip, const struct chg_props *cp, cs->ok_to_qnovo = false; if (cp->charging && - ((cp->usb_online && cp->usb_input_uA >= MIN_EN_UA) - || (cp->dc_online && cp->dc_input_uA >= MIN_EN_UA))) + (cp->usb_online || cp->dc_online)) cs->ok_to_qnovo = true; } diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index 463cbb7cb8ba..a07325102631 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017 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 @@ -1144,13 +1144,6 @@ static int smb2_configure_typec(struct smb_charger *chg) return rc; } - rc = smblib_validate_initial_typec_legacy_status(chg); - if (rc < 0) { - dev_err(chg->dev, "Couldn't validate typec legacy status rc=%d\n", - rc); - return rc; - } - return rc; } @@ -1891,6 +1884,12 @@ static int smb2_probe(struct platform_device *pdev) goto cleanup; } + rc = smb2_init_hw(chip); + if (rc < 0) { + pr_err("Couldn't initialize hardware rc=%d\n", rc); + goto cleanup; + } + rc = smb2_init_dc_psy(chip); if (rc < 0) { pr_err("Couldn't initialize dc psy rc=%d\n", rc); @@ -1923,12 +1922,6 @@ static int smb2_probe(struct platform_device *pdev) goto cleanup; } - rc = smb2_init_hw(chip); - if (rc < 0) { - pr_err("Couldn't initialize hardware rc=%d\n", rc); - goto cleanup; - } - rc = smb2_determine_initial_status(chip); if (rc < 0) { pr_err("Couldn't determine initial status rc=%d\n", diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 86140386f0e3..6d010a11d034 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017 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 @@ -16,7 +16,7 @@ #include <linux/iio/consumer.h> #include <linux/power_supply.h> #include <linux/regulator/driver.h> -#include <linux/qpnp/power-on.h> +#include <linux/input/qpnp-power-on.h> #include <linux/irq.h> #include "smb-lib.h" #include "smb-reg.h" @@ -627,6 +627,21 @@ static void smblib_uusb_removal(struct smb_charger *chg) smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc); } +static bool smblib_sysok_reason_usbin(struct smb_charger *chg) +{ + int rc; + u8 stat; + + rc = smblib_read(chg, SYSOK_REASON_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't get SYSOK_REASON_STATUS rc=%d\n", rc); + /* assuming 'not usbin' in case of read failure */ + return false; + } + + return stat & SYSOK_REASON_USBIN_BIT; +} + /********************* * VOTABLE CALLBACKS * *********************/ @@ -2852,6 +2867,8 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) typec_source_removal(chg); typec_sink_removal(chg); + chg->usb_ever_removed = true; + smblib_update_usb_type(chg); } @@ -2860,6 +2877,7 @@ static void smblib_handle_typec_insertion(struct smb_charger *chg, { int rp; bool vbus_cc_short = false; + bool valid_legacy_cable; vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, false, 0); @@ -2871,10 +2889,12 @@ static void smblib_handle_typec_insertion(struct smb_charger *chg, typec_sink_removal(chg); } + valid_legacy_cable = legacy_cable && + (chg->usb_ever_removed || !smblib_sysok_reason_usbin(chg)); vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, - legacy_cable, 0); + valid_legacy_cable, 0); - if (legacy_cable) { + if (valid_legacy_cable) { rp = smblib_get_prop_ufp_mode(chg); if (rp == POWER_SUPPLY_TYPEC_SOURCE_HIGH || rp == POWER_SUPPLY_TYPEC_NON_COMPLIANT) { @@ -3476,40 +3496,3 @@ int smblib_deinit(struct smb_charger *chg) return 0; } - -int smblib_validate_initial_typec_legacy_status(struct smb_charger *chg) -{ - int rc; - u8 stat; - - - if (qpnp_pon_is_warm_reset()) - return 0; - - rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc); - return rc; - } - - if ((stat & TYPEC_LEGACY_CABLE_STATUS_BIT) == 0) - return 0; - - rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, - TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT); - if (rc < 0) { - smblib_err(chg, "Couldn't disable typec rc=%d\n", rc); - return rc; - } - - usleep_range(150000, 151000); - - rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, - TYPEC_DISABLE_CMD_BIT, 0); - if (rc < 0) { - smblib_err(chg, "Couldn't enable typec rc=%d\n", rc); - return rc; - } - - return 0; -} diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index f6335aae2637..b65c0211405a 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017 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 @@ -233,6 +233,7 @@ struct smb_charger { /* extcon for VBUS / ID notification to USB for uUSB */ struct extcon_dev *extcon; + bool usb_ever_removed; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); @@ -377,8 +378,6 @@ int smblib_get_prop_slave_current_now(struct smb_charger *chg, int smblib_set_prop_ship_mode(struct smb_charger *chg, const union power_supply_propval *val); -int smblib_validate_initial_typec_legacy_status(struct smb_charger *chg); - int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg); #endif /* __SMB2_CHARGER_H */ diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index a30efbe3651e..a9606ab1944b 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017 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 @@ -860,6 +860,10 @@ enum { #define WDOG_STATUS_1_BIT BIT(1) #define BARK_BITE_STATUS_BIT BIT(0) +#define SYSOK_REASON_STATUS_REG (MISC_BASE + 0x0D) +#define SYSOK_REASON_DCIN_BIT BIT(1) +#define SYSOK_REASON_USBIN_BIT BIT(0) + /* MISC Interrupt Bits */ #define SWITCHER_POWER_OK_RT_STS_BIT BIT(7) #define TEMPERATURE_CHANGE_RT_STS_BIT BIT(6) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 267df592ba8a..cd02ed5bd46a 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, 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 @@ -23,7 +23,7 @@ #include <linux/reboot.h> #include <linux/pm.h> #include <linux/delay.h> -#include <linux/qpnp/power-on.h> +#include <linux/input/qpnp-power-on.h> #include <linux/of_address.h> #include <asm/cacheflush.h> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 6e88e4b11273..2138e81bb9e9 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1344,7 +1344,8 @@ start: hba->clk_gating.state = REQ_CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); - schedule_work(&hba->clk_gating.ungate_work); + queue_work(hba->clk_gating.ungating_workq, + &hba->clk_gating.ungate_work); /* * fall through to check if we should wait for this * work to be done or not. @@ -1617,6 +1618,7 @@ static enum hrtimer_restart ufshcd_clkgate_hrtimer_handler( static void ufshcd_init_clk_gating(struct ufs_hba *hba) { struct ufs_clk_gating *gating = &hba->clk_gating; + char wq_name[sizeof("ufs_clk_ungating_00")]; hba->clk_gating.state = CLKS_ON; @@ -1645,6 +1647,10 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) hrtimer_init(&gating->gate_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); gating->gate_hrtimer.function = ufshcd_clkgate_hrtimer_handler; + snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_ungating_%d", + hba->host->host_no); + hba->clk_gating.ungating_workq = create_singlethread_workqueue(wq_name); + gating->is_enabled = true; gating->delay_ms_pwr_save = UFSHCD_CLK_GATING_DELAY_MS_PWR_SAVE; @@ -1707,6 +1713,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) device_remove_file(hba->dev, &hba->clk_gating.enable_attr); ufshcd_cancel_gate_work(hba); cancel_work_sync(&hba->clk_gating.ungate_work); + destroy_workqueue(hba->clk_gating.ungating_workq); } static void ufshcd_set_auto_hibern8_timer(struct ufs_hba *hba, u32 delay) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index b20afd85beab..c34a998aac17 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -431,6 +431,7 @@ struct ufs_clk_gating { struct device_attribute enable_attr; bool is_enabled; int active_reqs; + struct workqueue_struct *ungating_workq; }; /* Hibern8 state */ diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index e8ea99827403..9b71083e4f27 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, 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 @@ -274,6 +274,8 @@ static int spcom_open(struct spcom_channel *ch, unsigned int timeout_msec); static int spcom_close(struct spcom_channel *ch); static void spcom_notify_rx_abort(void *handle, const void *priv, const void *pkt_priv); +static struct spcom_channel *spcom_find_channel_by_name(const char *name); +static int spcom_unlock_ion_buf(struct spcom_channel *ch, int fd); /** * spcom_is_ready() - driver is initialized and ready. @@ -347,6 +349,9 @@ static int spcom_create_predefined_channels_chardev(void) static void spcom_link_state_notif_cb(struct glink_link_state_cb_info *cb_info, void *priv) { + struct spcom_channel *ch = NULL; + const char *ch_name = "sp_kernel"; + spcom_dev->link_state = cb_info->link_state; pr_debug("spcom_link_state_notif_cb called. transport = %s edge = %s\n", @@ -359,6 +364,17 @@ static void spcom_link_state_notif_cb(struct glink_link_state_cb_info *cb_info, break; case GLINK_LINK_STATE_DOWN: pr_err("GLINK_LINK_STATE_DOWN.\n"); + + /* + * Free all the SKP ION buffers that were locked + * for SPSS app swapping, when remote subsystem reset. + */ + pr_debug("Free all SKP ION buffers on SSR.\n"); + ch = spcom_find_channel_by_name(ch_name); + if (!ch) + pr_err("failed to find channel [%s].\n", ch_name); + else + spcom_unlock_ion_buf(ch, SPCOM_ION_FD_UNLOCK_ALL); break; default: pr_err("unknown link_state [%d].\n", cb_info->link_state); @@ -1643,24 +1659,18 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch, } /** - * spcom_handle_unlock_ion_buf_command() - Unlock an ION buffer. + * spcom_unlock_ion_buf() - Unlock an ION buffer. * * Unlock an ION buffer, let it be free, when it is no longer being used by * the remote subsystem. */ -static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch, - void *cmd_buf, int size) +static int spcom_unlock_ion_buf(struct spcom_channel *ch, int fd) { - struct spcom_user_command *cmd = cmd_buf; - int fd = cmd->arg; struct ion_client *ion_client = spcom_dev->ion_client; int i; + bool found = false; - if (size != sizeof(*cmd)) { - pr_err("cmd size [%d] , expected [%d].\n", - (int) size, (int) sizeof(*cmd)); - return -EINVAL; - } + pr_debug("Unlock ion buf ch [%s] fd [%d].\n", ch->name, fd); /* Check ION client */ if (ion_client == NULL) { @@ -1669,6 +1679,8 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch, } if (fd == (int) SPCOM_ION_FD_UNLOCK_ALL) { + pr_debug("unlocked ALL ion buf ch [%s].\n", ch->name); + found = true; /* unlock all ION buf */ for (i = 0 ; i < ARRAY_SIZE(ch->ion_handle_table) ; i++) { if (ch->ion_handle_table[i] != NULL) { @@ -1686,15 +1698,45 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch, ch->ion_handle_table[i] = NULL; ch->ion_fd_table[i] = -1; pr_debug("unlocked ion buf#[%d].\n", i); + found = true; break; } } } + if (!found) { + pr_err("ch [%s] fd [%d] was not found.\n", ch->name, fd); + return -ENODEV; + } + return 0; } /** + * spcom_handle_unlock_ion_buf_command() - Unlock an ION buffer. + * + * Unlock an ION buffer, let it be free, when it is no longer being used by + * the remote subsystem. + */ +static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch, + void *cmd_buf, int size) +{ + int ret; + struct spcom_user_command *cmd = cmd_buf; + int fd = cmd->arg; + + if (size != sizeof(*cmd)) { + pr_err("cmd size [%d] , expected [%d].\n", + (int) size, (int) sizeof(*cmd)); + return -EINVAL; + } + + ret = spcom_unlock_ion_buf(ch, fd); + + return ret; +} + +/** * spcom_handle_fake_ssr_command() - Handle fake ssr command from user space. */ static int spcom_handle_fake_ssr_command(struct spcom_channel *ch, int arg) diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c index 4585313772ff..b7733e90fc8b 100644 --- a/drivers/thermal/msm-tsens.c +++ b/drivers/thermal/msm-tsens.c @@ -170,10 +170,8 @@ #define TSENS_DEBUG_OFFSET_WORD3 0xc #define TSENS_DEBUG_OFFSET_ROW 0x10 #define TSENS_DEBUG_DECIDEGC -950 -#define TSENS_DEBUG_MIN_CYCLE 63000 -#define TSENS_DEBUG_MAX_CYCLE 64000 -#define TSENS_DEBUG_POLL_MIN 200000 -#define TSENS_DEBUG_POLL_MAX 210000 +#define TSENS_DEBUG_CYCLE_MS 64 +#define TSENS_DEBUG_POLL_MS 200 #define TSENS_DEBUG_BUS_ID2_MIN_CYCLE 50 #define TSENS_DEBUG_BUS_ID2_MAX_CYCLE 51 #define TSENS_DEBUG_ID_MASK_1_4 0xffffffe1 @@ -1412,8 +1410,7 @@ static void tsens_poll(struct work_struct *work) spin_unlock_irqrestore(&tmdev->tsens_crit_lock, flags); if (tmdev->tsens_critical_poll) { - usleep_range(TSENS_DEBUG_POLL_MIN, - TSENS_DEBUG_POLL_MAX); + msleep(TSENS_DEBUG_POLL_MS); sensor_status_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr); spin_lock_irqsave(&tmdev->tsens_crit_lock, flags); @@ -1567,8 +1564,7 @@ debug_start: offset += TSENS_DEBUG_OFFSET_ROW; } loop++; - usleep_range(TSENS_DEBUG_MIN_CYCLE, - TSENS_DEBUG_MAX_CYCLE); + msleep(TSENS_DEBUG_CYCLE_MS); } BUG(); } diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index 635ef68b4e94..22a424cc15b8 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, 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 @@ -1216,6 +1216,15 @@ void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, struct dsc_desc *dsc) { u32 data, offset; + if (!dsc) { + if (ctrl->panel_mode == DSI_VIDEO_MODE) + offset = MDSS_DSI_VIDEO_COMPRESSION_MODE_CTRL; + else + offset = MDSS_DSI_COMMAND_COMPRESSION_MODE_CTRL; + MIPI_OUTP((ctrl->ctrl_base) + offset, 0); + return; + } + if (dsc->pkt_per_line <= 0) { pr_err("%s: Error: pkt_per_line cannot be negative or 0\n", __func__); @@ -1404,8 +1413,7 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata) MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, stream_total); } - if (dsc) /* compressed */ - mdss_dsi_dsc_config(ctrl_pdata, dsc); + mdss_dsi_dsc_config(ctrl_pdata, dsc); } void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl) diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 29288f0bca74..c3ae4c1f8c17 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -1494,8 +1494,9 @@ static int mdss_dsi_parse_topology_config(struct device_node *np, goto end; } } - rc = of_property_read_string(cfg_np, "qcom,split-mode", &data); - if (!rc && !strcmp(data, "pingpong-split")) + + if (!of_property_read_string(cfg_np, "qcom,split-mode", + &data) && !strcmp(data, "pingpong-split")) pinfo->use_pingpong_split = true; if (((timing->lm_widths[0]) || (timing->lm_widths[1])) && diff --git a/include/linux/qpnp/power-on.h b/include/linux/input/qpnp-power-on.h index da8f5a8622dd..a2624ab57826 100644 --- a/include/linux/qpnp/power-on.h +++ b/include/linux/input/qpnp-power-on.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017, 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 @@ -60,7 +60,7 @@ enum pon_restart_reason { PON_RESTART_REASON_KEYS_CLEAR = 0x06, }; -#ifdef CONFIG_QPNP_POWER_ON +#ifdef CONFIG_INPUT_QPNP_POWER_ON int qpnp_pon_system_pwr_off(enum pon_power_off_type type); int qpnp_pon_is_warm_reset(void); int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable); diff --git a/include/trace/events/msm_cam.h b/include/trace/events/msm_cam.h new file mode 100644 index 000000000000..b52845407ef0 --- /dev/null +++ b/include/trace/events/msm_cam.h @@ -0,0 +1,136 @@ +/* Copyright (c) 2016, 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. + * + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM msm_cam + +#if !defined(_TRACE_MSM_VFE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MSM_VFE_H + +#include "msm_isp.h" +#include <linux/types.h> +#include <linux/tracepoint.h> + +#define STRING_LEN 80 + + +TRACE_EVENT(msm_cam_string, + TP_PROTO(const char *str), + TP_ARGS(str), + TP_STRUCT__entry( + __array(char, str, STRING_LEN) + ), + TP_fast_assign( + strlcpy(__entry->str, str, STRING_LEN); + ), + TP_printk("msm_cam: %s", __entry->str) +); + +TRACE_EVENT(msm_cam_tasklet_debug_dump, + TP_PROTO(struct msm_vfe_irq_debug_info tasklet_state), + TP_ARGS(tasklet_state), + TP_STRUCT__entry( + __field(unsigned int, vfe_id) + __field(unsigned int, core_id) + __field(unsigned int, irq_status0) + __field(unsigned int, irq_status1) + __field(unsigned int, ping_pong_status) + __field(long, tv_sec) + __field(long, tv_usec) + ), + TP_fast_assign( + __entry->vfe_id = tasklet_state.vfe_id; + __entry->irq_status0 = + tasklet_state.irq_status0[tasklet_state.vfe_id]; + __entry->irq_status1 = + tasklet_state.irq_status1[tasklet_state.vfe_id]; + __entry->core_id = tasklet_state.core_id; + __entry->ping_pong_status = + tasklet_state.ping_pong_status[tasklet_state.vfe_id]; + __entry->tv_sec = + tasklet_state.ts.buf_time.tv_sec; + __entry->tv_usec = + tasklet_state.ts.buf_time.tv_usec; + ), + TP_printk("vfe_id %d, core %d, irq_st0 0x%x, irq_st1 0x%x\n" + "pi_po_st 0x%x, time %ld:%ld", + __entry->vfe_id, + __entry->core_id, + __entry->irq_status0, + __entry->irq_status1, + __entry->ping_pong_status, + __entry->tv_sec, + __entry->tv_usec + ) +); + +TRACE_EVENT(msm_cam_ping_pong_debug_dump, + TP_PROTO(struct msm_vfe_irq_debug_info ping_pong_state), + TP_ARGS(ping_pong_state), + TP_STRUCT__entry( + __field(unsigned int, curr_vfe_id) + __field(unsigned int, curr_irq_status0) + __field(unsigned int, curr_irq_status1) + __field(unsigned int, curr_ping_pong_status) + __field(unsigned int, othr_vfe_id) + __field(unsigned int, othr_irq_status0) + __field(unsigned int, othr_irq_status1) + __field(unsigned int, othr_ping_pong_status) + __field(long, othr_tv_sec) + __field(long, othr_tv_usec) + __field(unsigned int, core_id) + ), + TP_fast_assign( + __entry->curr_vfe_id = + ping_pong_state.vfe_id; + __entry->curr_irq_status0 = + ping_pong_state.irq_status0[ping_pong_state.vfe_id]; + __entry->curr_irq_status1 = + ping_pong_state.irq_status1[ping_pong_state.vfe_id]; + __entry->curr_ping_pong_status = + ping_pong_state. + ping_pong_status[ping_pong_state.vfe_id]; + __entry->othr_vfe_id = + !ping_pong_state.vfe_id; + __entry->othr_irq_status0 = + ping_pong_state.irq_status0[!ping_pong_state.vfe_id]; + __entry->othr_irq_status1 = + ping_pong_state.irq_status1[!ping_pong_state.vfe_id]; + __entry->othr_ping_pong_status = + ping_pong_state. + ping_pong_status[!ping_pong_state.vfe_id]; + __entry->othr_tv_sec = + ping_pong_state.ts.buf_time.tv_sec; + __entry->othr_tv_usec = + ping_pong_state.ts.buf_time.tv_usec; + __entry->core_id = ping_pong_state.core_id; + ), + TP_printk("vfe_id %d, irq_st0 0x%x, irq_st1 0x%x, pi_po_st 0x%x\n" + "other vfe_id %d, irq_st0 0x%x, irq_st1 0x%x\n" + "pi_po_st 0x%x, time %ld:%ld core %d", + __entry->curr_vfe_id, + __entry->curr_irq_status0, + __entry->curr_irq_status1, + __entry->curr_ping_pong_status, + __entry->othr_vfe_id, + __entry->othr_irq_status0, + __entry->othr_irq_status1, + __entry->othr_ping_pong_status, + __entry->othr_tv_sec, + __entry->othr_tv_usec, + __entry->core_id + ) +); + +#endif /* _MSM_CAM_TRACE_H */ +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 271d83e30d19..bf7fc4989e5c 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1850,15 +1850,19 @@ schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta, * You can set the task state as follows - * * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to - * pass before the routine returns. + * pass before the routine returns unless the current task is explicitly + * woken up, (e.g. by wake_up_process()). * * %TASK_INTERRUPTIBLE - the routine may return early if a signal is - * delivered to the current task. + * delivered to the current task or the current task is explicitly woken + * up. * * The current task state is guaranteed to be TASK_RUNNING when this * routine returns. * - * Returns 0 when the timer has expired otherwise -EINTR + * Returns 0 when the timer has expired. If the task was woken before the + * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or + * by an explicit wakeup, it returns -EINTR. */ int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta, const enum hrtimer_mode mode) @@ -1880,15 +1884,19 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout_range); * You can set the task state as follows - * * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to - * pass before the routine returns. + * pass before the routine returns unless the current task is explicitly + * woken up, (e.g. by wake_up_process()). * * %TASK_INTERRUPTIBLE - the routine may return early if a signal is - * delivered to the current task. + * delivered to the current task or the current task is explicitly woken + * up. * * The current task state is guaranteed to be TASK_RUNNING when this * routine returns. * - * Returns 0 when the timer has expired otherwise -EINTR + * Returns 0 when the timer has expired. If the task was woken before the + * timer expired by a signal (only possible in state TASK_INTERRUPTIBLE) or + * by an explicit wakeup, it returns -EINTR. */ int __sched schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode) diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 5ebefc7cfa4f..2bde2c2b1cb3 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -811,8 +811,15 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer, __acquires(timer->base->lock) { for (;;) { - u32 tf = timer->flags; struct tvec_base *base; + u32 tf; + + /* + * We need to use READ_ONCE() here, otherwise the compiler + * might re-read @tf between the check for TIMER_MIGRATING + * and spin_lock(). + */ + tf = READ_ONCE(timer->flags); if (!(tf & TIMER_MIGRATING)) { base = get_timer_base(tf); @@ -1529,11 +1536,12 @@ static void process_timeout(unsigned long __data) * You can set the task state as follows - * * %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to - * pass before the routine returns. The routine will return 0 + * pass before the routine returns unless the current task is explicitly + * woken up, (e.g. by wake_up_process())". * * %TASK_INTERRUPTIBLE - the routine may return early if a signal is - * delivered to the current task. In this case the remaining time - * in jiffies will be returned, or 0 if the timer expired in time + * delivered to the current task or the current task is explicitly woken + * up. * * The current task state is guaranteed to be TASK_RUNNING when this * routine returns. @@ -1542,7 +1550,9 @@ static void process_timeout(unsigned long __data) * the CPU away without a bound on the timeout. In this case the return * value will be %MAX_SCHEDULE_TIMEOUT. * - * In all cases the return value is guaranteed to be non-negative. + * Returns 0 when the timer has expired otherwise the remaining time in + * jiffies will be returned. In all cases the return value is guaranteed + * to be non-negative. */ signed long __sched schedule_timeout(signed long timeout) { @@ -1777,16 +1787,6 @@ unsigned long msleep_interruptible(unsigned int msecs) EXPORT_SYMBOL(msleep_interruptible); -static void __sched do_usleep_range(unsigned long min, unsigned long max) -{ - ktime_t kmin; - u64 delta; - - kmin = ktime_set(0, min * NSEC_PER_USEC); - delta = (u64)(max - min) * NSEC_PER_USEC; - schedule_hrtimeout_range(&kmin, delta, HRTIMER_MODE_REL); -} - /** * usleep_range - Drop in replacement for udelay where wakeup is flexible * @min: Minimum time in usecs to sleep @@ -1794,7 +1794,14 @@ static void __sched do_usleep_range(unsigned long min, unsigned long max) */ void __sched usleep_range(unsigned long min, unsigned long max) { - __set_current_state(TASK_UNINTERRUPTIBLE); - do_usleep_range(min, max); + ktime_t exp = ktime_add_us(ktime_get(), min); + u64 delta = (u64)(max - min) * NSEC_PER_USEC; + + for (;;) { + __set_current_state(TASK_UNINTERRUPTIBLE); + /* Do not return before the requested sleep time has elapsed */ + if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS)) + break; + } } EXPORT_SYMBOL(usleep_range); diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index 9b45db43ffb2..f2850d5e5ed3 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -5204,6 +5204,14 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol, tavil_mad_input = ucontrol->value.integer.value[0]; + if (tavil_mad_input >= sizeof(tavil_conn_mad_text)/ + sizeof(tavil_conn_mad_text[0])) { + dev_err(codec->dev, + "%s: tavil_mad_input = %d out of bounds\n", + __func__, tavil_mad_input); + return -EINVAL; + } + if (strnstr(tavil_conn_mad_text[tavil_mad_input], "NOTUSED", sizeof("NOTUSED"))) { dev_dbg(codec->dev, diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig index 835022b76b78..6ecd300a18ac 100644 --- a/sound/soc/msm/Kconfig +++ b/sound/soc/msm/Kconfig @@ -124,7 +124,6 @@ config SND_SOC_INT_CODEC select SND_SOC_SDM660_CDC select QTI_PP select DTS_SRS_TM - select DOLBY_DAP select DOLBY_DS2 select SND_HWDEP select MSM_ULTRASOUND @@ -157,7 +156,6 @@ config SND_SOC_EXT_CODEC select MFD_CORE select QTI_PP select DTS_SRS_TM - select DOLBY_DAP select DOLBY_DS2 select SND_SOC_CPE select SND_SOC_WCD_CPE diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c index ef4c9b01d91e..5b90cc11548e 100644 --- a/sound/soc/msm/msm-cpe-lsm.c +++ b/sound/soc/msm/msm-cpe-lsm.c @@ -1878,6 +1878,13 @@ static int msm_cpe_lsm_reg_model(struct snd_pcm_substream *substream, lsm_ops->lsm_get_snd_model_offset(cpe->core_handle, session, &offset); + /* Check if 'p_info->param_size + offset' crosses U32_MAX. */ + if (p_info->param_size > U32_MAX - offset) { + dev_err(rtd->dev, + "%s: Invalid param_size %d\n", + __func__, p_info->param_size); + return -EINVAL; + } session->snd_model_size = p_info->param_size + offset; session->snd_model_data = vzalloc(session->snd_model_size); diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c index bb0f890d300f..5866e46cc6a2 100644 --- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2014, 2016, 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. @@ -18,6 +18,10 @@ #include "msm-dolby-dap-config.h" +#ifndef DOLBY_PARAM_VCNB_MAX_LENGTH +#define DOLBY_PARAM_VCNB_MAX_LENGTH 40 +#endif + /* dolby endp based parameters */ struct dolby_dap_endp_params_s { int device; @@ -896,6 +900,11 @@ int msm_dolby_dap_param_visualizer_control_get(struct snd_kcontrol *kcontrol, uint32_t param_payload_len = DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t); int port_id, copp_idx, idx; + if (length > DOLBY_PARAM_VCNB_MAX_LENGTH || length <= 0) { + pr_err("%s Incorrect VCNB length", __func__); + ucontrol->value.integer.value[0] = 0; + return -EINVAL; + } for (idx = 0; idx < AFE_MAX_PORTS; idx++) { port_id = dolby_dap_params_states.port_id[idx]; copp_idx = dolby_dap_params_states.copp_idx[idx]; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 2639bfd5b8fd..dc57ae804dfa 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -10982,6 +10982,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"TERT_MI2S_UL_HL", NULL, "TERT_MI2S_TX"}, {"SEC_I2S_RX", NULL, "SEC_I2S_DL_HL"}, {"PRI_MI2S_UL_HL", NULL, "PRI_MI2S_TX"}, + {"SEC_MI2S_UL_HL", NULL, "SEC_MI2S_TX"}, {"SEC_MI2S_RX", NULL, "SEC_MI2S_DL_HL"}, {"PRI_MI2S_RX", NULL, "PRI_MI2S_DL_HL"}, {"TERT_MI2S_RX", NULL, "TERT_MI2S_DL_HL"}, diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c index 9782fa26a2e9..5399a101ba62 100644 --- a/sound/soc/msm/qdsp6v2/q6core.c +++ b/sound/soc/msm/qdsp6v2/q6core.c @@ -221,7 +221,6 @@ struct cal_block_data *cal_utils_get_cal_block_by_key( int32_t core_set_license(uint32_t key, uint32_t module_id) { struct avcs_cmd_set_license *cmd_setl = NULL; - struct audio_cal_info_metainfo *metainfo = NULL; struct cal_block_data *cal_block = NULL; int rc = 0, packet_size = 0; @@ -278,9 +277,9 @@ int32_t core_set_license(uint32_t key, uint32_t module_id) memcpy((uint8_t *)cmd_setl + sizeof(struct avcs_cmd_set_license), cal_block->cal_data.kvaddr, cal_block->cal_data.size); - pr_info("%s: Set license opcode=0x%x ,key=0x%x, id =0x%x, size = %d\n", + pr_info("%s: Set license opcode=0x%x, id =0x%x, size = %d\n", __func__, cmd_setl->hdr.opcode, - metainfo->nKey, cmd_setl->id, cmd_setl->size); + cmd_setl->id, cmd_setl->size); rc = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *)cmd_setl); if (rc < 0) pr_err("%s: SET_LICENSE failed op[0x%x]rc[%d]\n", |
