summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-08-13 13:18:43 -0600
committerLinux Build Service Account <lnxbuild@localhost>2016-08-13 13:18:43 -0600
commit558d430357afca640b3f4634e5bc617825250733 (patch)
treeadca105427aa4a646032cc75aaf66b4c8ef69903
parent777125f27bfb2bd37e46c5ee17d595531ced4716 (diff)
parentd43110ab63411fa3ac53e92d4f646842149f185a (diff)
Promotion of kernel.lnx.4.4-160813.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 1048182 I2da2eba03ef30f3942ba3f8644efab98635002da defconfig: arm64: msmcortex: enable display xlog debug f 1034085 I810ad8c102124ce22de72d83b6df58c8fc991251 usb: dwc3-msm: Do dwc3_msm_gadget_vbus_draw() in sleepab 1049455 I2f8fba73a831d3bb711fe9310c5758221359819e usb: gadget: f_fs: Unlock mutex before unregistering gad 1042302 I792c043ca4d85e236c209605e80392a05d26b983 input: touchscreen: correct condition checks in ITE tech 1044467 I61d99454dab2fa90b4ed6577d1a58685088eb968 pinctrl: qcom: Update TLMM configuration for msmfalcon 1046961 I79abc586ad8c14a25afd56559c579a1415df9f0e input: ft5x06_ts: Add support for FB notifications 1042302 I30dd0cf0b15538e67f50725754d5059e2fe721d0 input: touchscreen: increase number of checks for touch 1048345 I41ad4af44504e3f192a989a763a4093cae03b76c soc: qcom: Fix error checks in service-notifier 1050785 I91f636b2c1cc1890b4ca28f52e5190561bc5d927 msm: mdss: dsi: fix lcd mode selection gpio config when 1040200 Ide4ed54970c62f6485809c3bd63960536b4ace4f msm: ipa: Add support for IPA unit-test framework 1046961 I48189abe60b4bd9d54a1bbc4657707213d8eb166 input: ft5x06: Add support for firmware upgrade 1050156 Ic23796c5a1388c41d533ca0f4fad04d01fe9e965 ARM: msmcortex_defconfig: Enable NCM function driver 1051878 If9ff41037d22d7be7f09c9468e8d4cc92280a28e USB: dwc3-msm: Add support for setting specific frequenc 1050517 I83651b3b3515e0923d7431cfe8b70e6059b51067 clk: msm: Add support for reset controller for GDSC 1049477 I7e442daf51c6ece39b8fe5cc8a38d3405163c9b5 usb: dwc3: Use clock API to control the memory power sta 1034085 I2c5ec90cc8c45019ad75056b6feb7e6319f85514 usb: dwc3-msm: Remove call to set POWER_SUPPLY_PROP_ONLI 1048282 I7716cff99b824b55e48aea57b9da91c16a8ecac1 usb: gadget: f_cdev: Fix memory leak upon composition sw 1051569 Ife9e165f6aa2112c1440819d659b97b5502a3f07 usb: dwc3: Remove tasklet bottom half handler 1051104 I642d5d4adc6978ddfa84f6d9dc4ae6428efc7894 soc: qcom: irq-helper: Fix spelling mistake 1049455 I1638001ff4a94f08224b188aa42425f3d732fa2b usb: f_fs: Prevent gadget unbind if it is already unboun 1040746 I365976021dcf02fbc3687091371d7d72cb711605 ARM: dts: msm: adjust mdp ot limits for msmcobalt 1046961 Ibcdd8c3579f401ac0632d670e1b7c674aa67ba8d input: ft5x06_ts: Add DT support 1050517 Ic9d00c0a03507a55ca6c96f977a6ddf55b4b5db7 clk: msm: Add reset controller support 1045208 Iafc3a9dda252417fcd06e3d9d24fb73b4d6f8e58 input: msg21xx_ts: release touch when finger leaves the 1044467 Ie0c46cbbcbc3edabd5e0f867b4393a27e55db9f5 ARM: dts: msm: Update TLMM base address for msmfalcon 1050763 Ie65f79051bfc452c63067c21efcfd9d98429bb15 drivers: soc: Set APR Glink transport to SMEM 1042302 982219 Ib609d6e76ea70cd3b49c4ea6f09c75bf52521aa8 input: touchscreen: remove global variable from ITE tech 1022917 I03e1a7f5ef3cf1b1907c03a3d38965ce3a611bc4 drivers: mfd: wcd9xxx: Add support to configure dmic clo 1046168 Ib0cd2ed579bd370cc8979cafcc14acb083a408b6 ASoC: msm8x16: Initial change for internal codec support 1052720 I5a98b6128f5d54163ab5d03c4c023a748e6a4e95 clock: qcom: Update the list of clocks supported on MSMF 1037107 Icbef00d61f8705429105f241161362ad9f1f9d30 usb: pd: Only request current amount for explicit contra 1049455 I15011d79fc2f054e64f8bbd1f8f5db8944b46ada usb: gadget: f_fs: Add support for ipc logging 1051104 I7a623463a142a4db1db7247cf7c5dfeb5b99283c defconfig: Enable irq-helper on msmcobalt 1051164 I36b60ba2283b0bbe36f492e1410603b8c2050cc4 ASoC: msm: qdsp6v2: set correct loopback mode 1042302 980427 I9f69eb541e31de6a04db7468ca12a04a837d2b40 input: touchscreen: identify ITE tech controller until r 1022917 I968e1fe6b099ebf5334eadb209219181293b207f ASoC: wcd9335: Configure DMIC clock rate for ECPP path 1026204 Ie9523558c23a8edc7a7ee058937658dd87ef5b16 msm: vidc: Add support for color space information 1046484 I94ae8c769ec2868a291e75a2f47c85bd8a449937 msm: gsi: fix memory corruption from debugfs 1044467 If39ad62cc591565793cd1d8a0f2a454e0b7d5c58 pinctrl: qcom: Update SDC pins for msmfalcon 1047798 If889cd278fea7e13f941635f72047dcb9141ec2e soc: qcom: core,gladiator hang: Change the sysfs print f 1048402 I315e191227e14e207187673b8efb5401143dec9d ASoC: msmcobalt: fix wrong platform device pointer assig 1048939 I667aef9208d14b2dff5944ad6ad9b053797c4ac9 usb: gadget: gsi: Use pm_runtime related API from state 1045916 Id5f204647205b2fde9e5cb422a3ddc8cc4f3a5a0 soc: qcom: glink: Receive remote rx_intent with a cookie 1036145 I725245178ab02c5ec39b89998f5c2ca3d494c8ee qcom-charger: smb138x-charger: add parallel enable statu 1050153 I1c1ef35ea7ef6c2552a22b85c5af260ade413777 soc: qcom: pil: Add flag to know if modem SSR happened. 1048939 I1bdfe16273186b594f83fd03936a461895701996 usb: gadget: gsi: Optimize TRB's buffer allocation funct 1051661 I5c61c970e17cba44c555e60418a9ece80c61488f lpm-levels: Use arm_cpuidle_suspend instead of cpu_suspe 1045208 Ic49a18de64ec210a0636405394ba7a8f52f336a9 input: msg21xx_ts: update mstar driver to enable msg2138 1045916 I97ca857c21d8873574a180d289e2fbca29c8a891 ARM: dts: msm: Add G-Link SPI Transport device for msmco 1051756 I4a3f415263b94d4eab16de05bbb9843b7bb04113 defconfig: Enable memory latency monitors and governor 1042302 982219 Iba07517fd32dbeb3079df9c0346ea0c044b88f63 input: touchscreen: correct return values in ITE tech dr 1030755 I55bc9cda07ef3c2d3ff5713f1ce83d8b344bed6a bluetooth: Add Split A2DP slimbus 1049984 I6dda3b5e8b314d392e51f492b23ce0342e47800a msm: wlan: Update db.txt for some countries 1048182 I67bc99d1939ec7176be2e73fdbe6960e677a5cad msm: mdss: add mdp debug bus for msmcobalt 1045916 I1936bb0542bcd531726bf987ef806969ce96d498 soc: qcom: glink_spi_xprt: Add support for GLink SPI Tra 1040746 I3559ed2b6984ac9cec8e219f59f634410aaf57c9 ARM: dts: msm: adjust mdp bw limits for msmcobalt v2 1049455 Iec93a9d4cb2a10b833cbba0d5256b64161147de2 usb: gadget: configfs: Synchronizing bind/unbind using m 1045045 Ib651dd59b30e4924f4e199cfd4fae64df6030d9d ASoC: msm: qdsp6v2: Fix crash during WFD playback and SS 1045904 I56581533ffff3b61f5b5ee128841ab61b62674d7 ASoC: msm: qdsp6v2: support for AFE encoder 1051416 Ic1b61b2bbb7ce74c9e9422b5e22ee9078251de21 cpuset: Add allow_attach hook for cpusets on android. 1051104 I4737975961b18f1095e3cd78d07a2bca22931291 soc: qcom: irq-helper: Add header file of irq-helper 1051756 Ic4838fd58d40d283ac301facc64b06813eb3bd7d PM / devfreq: memlat: Remove kfree() on probe fails 1036145 I79f95b145176b66d6b8cec5a21922ea16c2c8206 power_supply: add PIN_ENABLED property 1044351 I13161bd8b2a7777abbe2521178c5b1b1b6416eea mdss: display-port: add support to send HPD event to fra 997059 I44925240705608510266a51225cc02611637c571 ASoC: msm: set pointers to NULL after kfree 1050071 Ibeef761044deea375dc7684c0a160609b610b8f6 regulator: cpr3-mmss-regulator: add support for force hi 1050071 Ie9d4e825e5c6040036642cdaf22d1f67b6129685 ARM: dts: msm: increase VDD_GFX CPR ceiling voltages for 1031648 I754c85a2ed02d0b1e40fd1e27b10ff84c463ac83 ARM: dts: msm: Enable the GPU QDSS STM for msmcobalt 1051115 I1809fcef844d275175814e636591b87e91432609 usb: phy: qusb: Fix typo with emulation related property 1045916 I268d96f04b034edad2fadea8ef2c14fe8d8de251 defconfig: msmcortex: Enable G-Link SPI Transport driver 1052589 Id559d9ef9d1e0a25e3bbdc81503978f01c6ed85f Revert "genetlink: disallow subscribing to unknown mcast 1042302 I88e024700de43cc9f712fd7fa509fcb387f9cd21 input: touchscreen: don't allow ITE tech driver to do in 1045904 I22173ef9a7586cc7b9bc4b40afa1c02f5317c3a7 ASoC: msmcobalt: add BT audio support 1032820 I710c1f743d7502e93989e8cc487078366570e723 ASoC: msm: qdsp6v2: check param length for EAC3 format 1051371 If2a7eaf11ad05ced3c52ff87be934745b7dc713b msm: ipa3: update BCR Regsiter values for IPA v3.1 and v 1050517 I3e9f7f85bf1faf0e1bb501196ba9d7e197111a03 clk: msm: Add support for block reset clocks 1045208 Ib6046de5230c395b48818d01f26eb9394046808b input: msg21xx_ts: add support for firmware upgrade 1050071 Ifa54325a1364f10b6f1760c52ad029612114759c regulator: cpr3-mmss-regulator: update msmcobalt partial 1051878 Ia452476bd3bb7316a86efd08fed52c54f3efa34e ARM: dts: msm: Update USB core clock frequency to allow 1048727 I3a1ecc89f379a90d9fdacf0baa9b6c8498bb93fb msm: mdss: fix spurious wait4pingpong timeouts 1050670 Iba47db8936b49309360791c1c6b482dcfcffd4d7 msm: ipa: do not use skb clones for lan clients 1045904 I93ad53016a28efe0d8592ac0092d6c8896a66072 ASoC: msm: q6dspv2: add adm channel config support 1042302 982219 Ic8b66317f414fe3bfcd0f9c5b03369cc304edb55 input: touchscreen: correct function and variable names 1049499 I795d14fd4bc3b5f31897a70009546238117b0825 msm: vidc: Allow venus to power collapse in batch mode 1048706 I702b4ff11582047b00e3f0d5433d29c84f34e913 msm: ipa: Add parameters validation to handle static ana 1037191 I6d9d92f7291df2d92f9faf3c4e80b832422b3ddf ARM: dts: msm: Add SMMU implementation defined settings 1048941 I97763004454d082d3cc2d9d9dbef7da923608600 sched: Remove synchronize rcu/sched calls from _cpu_down Change-Id: I89d1085e144b7f28cd97520eb36af1fede881fcd CRs-Fixed: 1031648, 1046484, 1051756, 1051661, 1037107, 1050156, 1051104, 1049984, 1048182, 1050153, 1034085, 1049477, 1040200, 1045208, 1026204, 1046961, 1049455, 1051115, 982219, 1051878, 1022917, 1045916, 1049499, 1048282, 1050071, 1052720, 1050763, 1047798, 1030755, 1044351, 1050785, 980427, 1048941, 1036145, 1045045, 1051416, 1037191, 1044467, 1051569, 1042302, 1048727, 1050517, 1051371, 1048402, 1040746, 1048706, 1050670, 1048939, 1045904, 1032820, 1051164, 1052589, 997059, 1048345, 1046168
-rw-r--r--Documentation/devicetree/bindings/arm/msm/glink_spi_xprt.txt44
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt53
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt60
-rw-r--r--Documentation/devicetree/bindings/regulator/gdsc-regulator.txt6
-rwxr-xr-xDocumentation/devicetree/bindings/sound/qcom-audio-dev.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/wcd_codec.txt25
-rw-r--r--Documentation/devicetree/bindings/usb/msm-ssusb.txt1
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi564
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi31
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi10
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig6
-rw-r--r--arch/arm64/configs/msmcortex_defconfig6
-rw-r--r--drivers/bluetooth/btfm_slim.c3
-rw-r--r--drivers/bluetooth/btfm_slim.h2
-rw-r--r--drivers/bluetooth/btfm_slim_codec.c22
-rw-r--r--drivers/bluetooth/btfm_slim_wcn3990.c2
-rw-r--r--drivers/clk/msm/Makefile1
-rw-r--r--drivers/clk/msm/clock-gcc-8996.c27
-rw-r--r--drivers/clk/msm/clock-mmss-8996.c17
-rw-r--r--drivers/clk/msm/gdsc.c46
-rw-r--r--drivers/clk/msm/reset.c94
-rw-r--r--drivers/clk/msm/reset.h39
-rw-r--r--drivers/cpuidle/lpm-levels.c4
-rw-r--r--drivers/devfreq/arm-memlat-mon.c12
-rw-r--r--drivers/input/touchscreen/Kconfig11
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ft5x06_ts.c777
-rw-r--r--drivers/input/touchscreen/it7258_ts_i2c.c1234
-rw-r--r--drivers/input/touchscreen/msg21xx_ts.c3272
-rw-r--r--drivers/media/platform/msm/vidc/hfi_packetization.c26
-rw-r--r--drivers/media/platform/msm/vidc/msm_vdec.c7
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c103
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c28
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_debug.c2
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c12
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi.h1
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_api.h10
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_helper.h12
-rw-r--r--drivers/mfd/wcd9xxx-utils.c10
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msmfalcon.c932
-rw-r--r--drivers/platform/msm/Kconfig11
-rw-r--r--drivers/platform/msm/gsi/gsi_dbg.c6
-rw-r--r--drivers/platform/msm/ipa/Makefile1
-rw-r--r--drivers/platform/msm/ipa/ipa_api.c44
-rw-r--r--drivers/platform/msm/ipa/ipa_common_i.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_dp.c22
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c6
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c10
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c16
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c5
-rw-r--r--drivers/platform/msm/ipa/test/Makefile2
-rw-r--r--drivers/platform/msm/ipa/test/ipa_test_example.c99
-rw-r--r--drivers/platform/msm/ipa/test/ipa_ut_framework.c969
-rw-r--r--drivers/platform/msm/ipa/test/ipa_ut_framework.h222
-rw-r--r--drivers/platform/msm/ipa/test/ipa_ut_i.h86
-rw-r--r--drivers/platform/msm/ipa/test/ipa_ut_suite_list.h35
-rw-r--r--drivers/power/power_supply_sysfs.c2
-rw-r--r--drivers/power/qcom-charger/smb138x-charger.c15
-rw-r--r--drivers/regulator/cpr3-mmss-regulator.c64
-rw-r--r--drivers/soc/qcom/Kconfig10
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/core_hang_detect.c11
-rw-r--r--drivers/soc/qcom/gladiator_hang_detect.c8
-rw-r--r--drivers/soc/qcom/glink.c60
-rw-r--r--drivers/soc/qcom/glink_core_if.h7
-rw-r--r--drivers/soc/qcom/glink_spi_xprt.c2192
-rw-r--r--drivers/soc/qcom/glink_xprt_if.h5
-rw-r--r--drivers/soc/qcom/irq-helper.c3
-rw-r--r--drivers/soc/qcom/peripheral-loader.c20
-rw-r--r--drivers/soc/qcom/peripheral-loader.h2
-rw-r--r--drivers/soc/qcom/pil-q6v5-mss.c1
-rw-r--r--drivers/soc/qcom/qdsp6v2/apr_tal_glink.c13
-rw-r--r--drivers/soc/qcom/service-locator.c18
-rw-r--r--drivers/soc/qcom/service-notifier.c56
-rw-r--r--drivers/usb/dwc3/core.h1
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c79
-rw-r--r--drivers/usb/dwc3/gadget.c21
-rw-r--r--drivers/usb/gadget/configfs.c3
-rw-r--r--drivers/usb/gadget/function/f_cdev.c5
-rw-r--r--drivers/usb/gadget/function/f_fs.c385
-rw-r--r--drivers/usb/gadget/function/f_gsi.c199
-rw-r--r--drivers/usb/pd/policy_engine.c11
-rw-r--r--drivers/usb/phy/phy-msm-qusb-v2.c2
-rw-r--r--drivers/usb/phy/phy-msm-qusb.c2
-rw-r--r--drivers/video/fbdev/msm/mdss.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_debug.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_debug_xlog.c9
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c106
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_panel.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_panel.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_debug.c791
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_hwio.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c24
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h6
-rw-r--r--include/dt-bindings/clock/msm-clocks-8996.h29
-rw-r--r--include/dt-bindings/clock/qcom,gcc-msmfalcon.h445
-rw-r--r--include/dt-bindings/clock/qcom,gpu-msmfalcon.h40
-rw-r--r--include/dt-bindings/clock/qcom,mmcc-msmfalcon.h367
-rw-r--r--include/linux/input/ft5x06_ts.h24
-rwxr-xr-xinclude/linux/mfd/wcd9xxx/pdata.h1
-rw-r--r--include/linux/power_supply.h2
-rw-r--r--include/soc/qcom/irq-helper.h20
-rw-r--r--include/sound/apr_audio-v2.h331
-rw-r--r--include/sound/q6afe-v2.h3
-rw-r--r--include/uapi/linux/v4l2-controls.h23
-rw-r--r--include/uapi/media/msm_vidc.h120
-rw-r--r--kernel/cpu.c15
-rw-r--r--kernel/cpuset.c18
-rw-r--r--net/netlink/genetlink.c2
-rw-r--r--net/wireless/db.txt62
-rwxr-xr-xsound/soc/codecs/Kconfig6
-rw-r--r--sound/soc/codecs/Makefile3
-rw-r--r--sound/soc/codecs/msm8x16/Kconfig3
-rw-r--r--sound/soc/codecs/msm8x16/Makefile3
-rw-r--r--sound/soc/codecs/msm8x16/msm8916-wcd-irq.c (renamed from sound/soc/codecs/msm8916-wcd-irq.c)56
-rw-r--r--sound/soc/codecs/msm8x16/msm8916-wcd-irq.h (renamed from sound/soc/codecs/msm8916-wcd-irq.h)0
-rw-r--r--sound/soc/codecs/msm8x16/msm89xx-regmap.c417
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16-wcd-tables.c263
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16-wcd.c6037
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16-wcd.h341
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16_wcd_registers.h585
-rw-r--r--sound/soc/codecs/wcd9335.c23
-rw-r--r--sound/soc/msm/msm-cpe-lsm.c9
-rw-r--r--sound/soc/msm/msmcobalt.c46
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c1
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c183
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-slim.c4
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c347
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h1
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c173
-rw-r--r--sound/soc/msm/qdsp6v2/q6lsm.c3
144 files changed, 19860 insertions, 3412 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/glink_spi_xprt.txt b/Documentation/devicetree/bindings/arm/msm/glink_spi_xprt.txt
new file mode 100644
index 000000000000..0a78eb6b91fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/glink_spi_xprt.txt
@@ -0,0 +1,44 @@
+Qualcomm Technologies, Inc. G-link SPI Transport
+
+Required properties:
+-compatible : should be "qcom,glink-spi-xprt".
+-label : the name of the subsystem this link connects to.
+
+Optional properties:
+-qcom,remote-fifo-config: Reference to the FIFO configuratio in the remote
+ processor.
+-qcom,qos-config: Reference to the qos configuration elements.It depends on
+ ramp-time.
+-qcom,ramp-time: Worst case time in microseconds to transition to this power
+ state. Power states are numbered by array index position.
+
+Example:
+
+ glink_spi_xprt_wdsp: qcom,glink-spi-xprt-wdsp {
+ compatible = "qcom,glink-spi-xprt";
+ label = "wdsp";
+ qcom,remote-fifo-config = <&glink_fifo_wdsp>;
+ qcom,qos-config = <&glink_qos_wdsp>;
+ qcom,ramp-time = <0x10>,
+ <0x20>,
+ <0x30>,
+ <0x40>;
+ };
+
+ glink_fifo_wdsp: qcom,glink-fifo-config-wdsp {
+ compatible = "qcom,glink-fifo-config";
+ qcom,out-read-idx-reg = <0x12000>;
+ qcom,out-write-idx-reg = <0x12004>;
+ qcom,in-read-idx-reg = <0x1200C>;
+ qcom,in-write-idx-reg = <0x12010>;
+ };
+
+ glink_qos_wdsp: qcom,glink-qos-config-wdsp {
+ compatible = "qcom,glink-qos-config";
+ qcom,flow-info = <0x80 0x0>,
+ <0x70 0x1>,
+ <0x60 0x2>,
+ <0x50 0x3>;
+ qcom,mtu-size = <0x800>;
+ qcom,tput-stats-cycle = <0xa>;
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
new file mode 100644
index 000000000000..1c7c2c5ea99f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
@@ -0,0 +1,53 @@
+FocalTech touch controller
+
+The focaltech controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible : should be "focaltech,5x06".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : touch sample interrupt to indicate presense or release
+ of fingers on the panel.
+ - vdd-supply : Power supply needed to power up the device.
+ - vcc_i2c-supply : Power source required to power up i2c bus.
+ - focaltech,family-id : family identification of the controller.
+ - focaltech,irq-gpio : irq gpio which is to provide interrupts to host,
+ same as "interrupts" node. It will also
+ contain active low or active high information.
+ - focaltech,reset-gpio : reset gpio to control the reset of chip.
+ - focaltech,display-coords : display coordinates in pixels. It is a four
+ tuple consisting of min x, min y, max x and
+ max y values.
+
+Optional properties:
+
+ - focaltech,panel-coords : panel coordinates for the chip in pixels.
+ It is a four tuple consisting of min x,
+ min y, max x and max y values.
+ - focaltech,i2c-pull-up : to specify pull up is required.
+ - focaltech,no-force-update : to specify force update is allowed.
+ - focaltech,button-map : button map of key codes. The number
+ of key codes depend on panel.
+
+Example:
+ i2c@f9924000 {
+ ft5x06_ts@38 {
+ compatible = "focaltech,5x06";
+ reg = <0x38>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <61 0x2>;
+ vdd-supply = <&pm8941_l22>;
+ vcc_i2c-supply = <&pm8941_s3>;
+ focaltech,reset-gpio = <&msmgpio 60 0x00>;
+ focaltech,irq-gpio = <&msmgpio 61 0x00>;
+ focaltech,panel-coords = <0 0 480 800>;
+ focaltech,display-coords = <0 0 480 800>;
+ focaltech,button-map= <158 102 139 217>;
+ focaltech,family-id = <0x0a>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
new file mode 100644
index 000000000000..26f01ca8577f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
@@ -0,0 +1,60 @@
+Mstar touch controller
+
+The mstar controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible : should be "mstar,msg21xx".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : touch sample interrupt to indicate presense or release
+ of fingers on the panel.
+ - vdd-supply : Power supply needed to power up the device.
+ - vcc_i2c-supply : Power source required to power up i2c bus.
+ - mstar,irq-gpio : irq gpio which is to provide interrupts to host,
+ same as "interrupts" node. It will also
+ contain active low or active high information.
+ - mstar,reset-gpio : reset gpio to control the reset of chip.
+ - mstar,display-coords : display coords in pixels. It is a four
+ tuple consisting of min x, min y, max x and
+ max y values.
+ - pinctrl-names : This should be defined if a target uses pinctrl framework.
+ See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
+ Specify the names of the configs that pinctrl can install in driver.
+ Following are the pinctrl configs that can be installed:
+ "pmx_ts_active" : Active configuration of pins, this should specify active
+ config defined in pin groups of interrupt and reset gpio.
+ "pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep
+ config defined in pin groups of interrupt and reset gpio.
+ "pmx_ts_release" : Release configuration of pins, this should specify
+ release config defined in pin groups of interrupt and reset gpio.
+
+Optional properties:
+
+ - mstar,button-map : button map of key codes. It is a three tuple consisting of key codes.
+ - mstar,panel-coords : panel coords for the chip in pixels.
+ It is a four tuple consisting of min x,
+ min y, max x and max y values.
+
+Example:
+ i2c@78b9000 { /* BLSP1 QUP5 */
+ mstar@26 {
+ compatible = "mstar,msg21xx";
+ reg = <0x26>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <13 0x2008>;
+ mstar,irq-gpio = <&msm_gpio 13 0x00000001>;
+ mstar,reset-gpio = <&msm_gpio 12 0x0>;
+ vdd-supply = <&pm8916_l17>;
+ vcc_i2c-supply = <&pm8916_l6>;
+ mstar,display-coords = <0 0 480 854>;
+ pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
+ pinctrl-0 = <&ts_int_active &ts_reset_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ mstar,button-map= <172 139 158>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 526c51836402..20e5c5be37ce 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -50,6 +50,12 @@ Optional properties:
to enable.
- qcom,reset-aon-logic: If present, the GPU DEMET cells need to be reset while
enabling the GX GDSC.
+ - resets: reset specifier pair consisting of phandle for the reset controller
+ and reset lines used by this controller. These can be
+ supplied only if we support qcom,skip-logic-collapse.
+ - reset-names: reset signal name strings sorted in the same order as the resets
+ property. These can be supplied only if we support
+ qcom,skip-logic-collapse.
Example:
gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 7fa51e394f5c..c8f8d38c2a5e 100755
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -725,6 +725,11 @@ Optional Properties:
Example:
+ msm_dig_codec: qcom,msm-int-codec {
+ compatible = "qcom,msm_int_core_codec";
+ qcom,dig-cdc-base-addr = <0xc0f0000>;
+ };
+
sound {
compatible = "qcom,msm8x16-audio-codec";
qcom,model = "msm8x16-snd-card";
diff --git a/Documentation/devicetree/bindings/sound/wcd_codec.txt b/Documentation/devicetree/bindings/sound/wcd_codec.txt
index d585595f21c6..c0a7a240b922 100644
--- a/Documentation/devicetree/bindings/sound/wcd_codec.txt
+++ b/Documentation/devicetree/bindings/sound/wcd_codec.txt
@@ -92,6 +92,14 @@ Optional properties:
involving DMIC will use the rate defined by
cdc-dmic-sample-rate.
+ - qcom,cdc-ecpp-dmic-rate: Specifies the sample rate of digital mic in HZ to be
+ used by ECPP (Echo Cancellation Ping Pong) block
+ on the codec. The valid set of values are same
+ as that of cdc-dmic-sample-rate, but this rate will
+ only be used by ECPP and all other audio use cases
+ involving DMIC will use the rate defined by
+ cdc-dmic-sample-rate.
+
- qcom,cdc-dmic-clk-drv-strength: Specifies the drive strength for digital microphone
clock in the codec. Accepted values are 2,4,8 and 16.
The clock drive strentgh is in uA. Codec driver will
@@ -375,7 +383,9 @@ i2c@f9925000 {
Tombak audio CODEC in SPMI mode
- - compatible = "qcom,msm8x16_wcd_codec";
+ - compatible = "qcom,msm-codec-core",
+ - compatible = "qcom,pmic-codec-digital"
+ - compatible = "qcom,pmic-codec-analog"
- reg: represents the slave base address provided to the peripheral.
- interrupt-parent : The parent interrupt controller.
- interrupts: List of interrupts in given SPMI peripheral.
@@ -427,8 +437,19 @@ Optional properties:
core register writes.
Example:
+
+msm_dig_codec: qcom,msm-int-codec {
+ compatible = "qcom,msm_int_core_codec";
+ qcom,dig-cdc-base-addr = <0xc0f0000>;
+};
+
+msm8x16_wcd_codec@f100 {
+ compatible = "qcom,msm_int_pmic_analog_codec";
+ reg = <0xf100 0x100>;
+};
+
msm8x16_wcd_codec@f000{
- compatible = "qcom,msm8x16_wcd_codec";
+ compatible = "qcom,msm_int_pmic_digital_codec";
reg = <0xf000 0x100>;
interrupt-parent = <&spmi_bus>;
interrupts = <0x1 0xf0 0x0>,
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 2b2bfe428c79..c5e5f1851fc2 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -50,6 +50,7 @@ Optional properties :
- qcom,disable-dev-mode-pm: If present, it disables PM runtime functionality for device mode.
- qcom,disable-host-mode-pm: If present, it disables XHCI PM runtime functionality when USB
host mode is used.
+- qcom,core-clk-rate: If present, indicates clock frequency to be set for USB master clock.
- extcon: phandles to external connector devices. First phandle should point to
external connector, which provide "USB" cable events, the second
should point to external connector device, which provide "USB-HOST"
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 4097b7cd6454..aca2dd3e4ccb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -146,6 +146,7 @@ mosaixtech Mosaix Technologies, Inc.
moxa Moxa
mpl MPL AG
msi Micro-Star International Co. Ltd.
+mstar MStar Semiconductor, Inc.
mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
mundoreader Mundo Reader S.L.
murata Murata Manufacturing Co., Ltd.
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi
new file mode 100644
index 000000000000..feb74b5480f1
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi
@@ -0,0 +1,564 @@
+/* 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.
+ */
+
+
+&kgsl_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6470 0x110011>,
+ <0x6478 0x0>,
+ <0x647c 0x1000100>,
+ <0x6480 0x81108110>,
+ <0x6484 0x81108110>,
+ <0x6488 0x3e003e0>,
+ <0x648c 0x3e003e0>,
+ <0x6490 0x80008010>,
+ <0x6494 0x8020>,
+ <0x649c 0x6>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x604>,
+ <0x6928 0x11000>,
+ <0x6930 0x800>,
+ <0x6b64 0x1a5551>,
+ <0x6b68 0x2aaa2f82>;
+};
+
+&lpass_q6_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0xe0>,
+ <0x6074 0xe0>,
+ <0x6078 0xe0>,
+ <0x607c 0xe0>,
+ <0x60f0 0xc0>,
+ <0x60f4 0xc8>,
+ <0x60f8 0xd0>,
+ <0x60fc 0xd8>,
+ <0x6170 0x0>,
+ <0x6174 0x30>,
+ <0x6178 0x60>,
+ <0x617c 0x90>,
+ <0x6270 0x0>,
+ <0x6274 0x2>,
+ <0x6278 0x4>,
+ <0x627c 0x6>,
+ <0x62f0 0x8>,
+ <0x62f4 0xe>,
+ <0x62f8 0x14>,
+ <0x62fc 0x1a>,
+ <0x6370 0x20>,
+ <0x6374 0x40>,
+ <0x6378 0x60>,
+ <0x637c 0x80>,
+ <0x67a0 0x0>,
+ <0x67a4 0x0>,
+ <0x67a8 0x20>,
+ <0x67b0 0x0>,
+ <0x67b4 0x8>,
+ <0x67b8 0xc8>,
+ <0x67d0 0x4>,
+ <0x67dc 0x8>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x202>,
+ <0x6928 0x10a00>,
+ <0x6930 0x500>,
+ <0x6b64 0x121151>,
+ <0x6b68 0x8a840080>,
+ <0x6c00 0x0>,
+ <0x6c04 0x0>,
+ <0x6c08 0x0>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x1>,
+ <0x6c14 0x1>,
+ <0x6c18 0x1>,
+ <0x6c1c 0x1>,
+ <0x6c20 0x2>,
+ <0x6c24 0x2>,
+ <0x6c28 0x2>,
+ <0x6c2c 0x2>,
+ <0x6c30 0x3>,
+ <0x6c34 0x3>,
+ <0x6c38 0x3>,
+ <0x6c3c 0x3>;
+};
+
+&mmss_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x204>,
+ <0x6928 0x11002>,
+ <0x6930 0x800>,
+ <0x6960 0xffffffff>,
+ <0x6964 0xffffffff>,
+ <0x6968 0xffffffff>,
+ <0x696c 0xffffffff>,
+ <0x6b48 0x330330>,
+ <0x6b4c 0x81>,
+ <0x6b50 0x3333>,
+ <0x6b54 0x3333>,
+ <0x6b64 0x1a5555>,
+ <0x6b68 0x9aaa892a>,
+ <0x6b70 0x10100002>,
+ <0x6b74 0x10100002>,
+ <0x6b78 0x10100002>,
+ <0x6b80 0x20042004>,
+ <0x6b84 0x20042004>;
+};
+
+&anoc1_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0x19>,
+ <0x6074 0x39>,
+ <0x6078 0x41>,
+ <0x607c 0x59>,
+ <0x6080 0x95>,
+ <0x6084 0x98>,
+ <0x6088 0xc0>,
+ <0x608c 0xc0>,
+ <0x60f0 0x0>,
+ <0x60f4 0x2>,
+ <0x60f8 0x5>,
+ <0x60fc 0x8>,
+ <0x6100 0x16>,
+ <0x6104 0x17>,
+ <0x6108 0x19>,
+ <0x610c 0x19>,
+ <0x6170 0x0>,
+ <0x6174 0x0>,
+ <0x6178 0x0>,
+ <0x617c 0x0>,
+ <0x6180 0x0>,
+ <0x6184 0x0>,
+ <0x6188 0x0>,
+ <0x618c 0x0>,
+ <0x6270 0x0>,
+ <0x6274 0xd>,
+ <0x6278 0xe>,
+ <0x627c 0x12>,
+ <0x6280 0x16>,
+ <0x6284 0x16>,
+ <0x6288 0x18>,
+ <0x628c 0x18>,
+ <0x62f0 0x18>,
+ <0x62f4 0x1b>,
+ <0x62f8 0x1c>,
+ <0x62fc 0x24>,
+ <0x6300 0x28>,
+ <0x6304 0x2b>,
+ <0x6308 0x31>,
+ <0x630c 0x31>,
+ <0x6370 0x31>,
+ <0x6374 0x34>,
+ <0x6378 0x35>,
+ <0x637c 0x47>,
+ <0x6380 0x4f>,
+ <0x6384 0x54>,
+ <0x6388 0x60>,
+ <0x638c 0x60>,
+ <0x67a0 0x0>,
+ <0x67a4 0xa7>,
+ <0x67a8 0xc0>,
+ <0x67b0 0x0>,
+ <0x67b4 0x18>,
+ <0x67b8 0x7c>,
+ <0x67d0 0x0>,
+ <0x67dc 0x4>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6b64 0x121151>,
+ <0x6b68 0xbb804080>,
+ <0x6c00 0x0>,
+ <0x6c04 0x0>,
+ <0x6c08 0x0>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x0>,
+ <0x6c14 0x0>,
+ <0x6c18 0x0>,
+ <0x6c1c 0x0>,
+ <0x6c20 0x0>,
+ <0x6c24 0x0>,
+ <0x6c28 0x0>,
+ <0x6c2c 0x0>,
+ <0x6c30 0x0>,
+ <0x6c34 0x0>,
+ <0x6c38 0x0>,
+ <0x6c3c 0x0>,
+ <0x6c40 0x0>,
+ <0x6c44 0x0>,
+ <0x6c48 0x0>,
+ <0x6c4c 0x0>,
+ <0x6c50 0x0>,
+ <0x6c54 0x0>,
+ <0x6c58 0x0>,
+ <0x6c5c 0x0>,
+ <0x6c60 0x0>,
+ <0x6c64 0x0>,
+ <0x6c68 0x0>,
+ <0x6c6c 0x0>,
+ <0x6c70 0x0>,
+ <0x6c74 0x0>,
+ <0x6c78 0x0>,
+ <0x6c7c 0x0>,
+ <0x6c80 0x0>,
+ <0x6c84 0x1>,
+ <0x6c88 0x0>,
+ <0x6c8c 0x0>,
+ <0x6c90 0x4>,
+ <0x6c94 0x3>,
+ <0x6c98 0x2>,
+ <0x6c9c 0x0>,
+ <0x6ca0 0x5>,
+ <0x6ca4 0x5>,
+ <0x6ca8 0x0>,
+ <0x6cac 0x0>,
+ <0x6cb0 0x0>,
+ <0x6cb4 0x0>,
+ <0x6cb8 0x0>,
+ <0x6cbc 0x0>,
+ <0x6cc0 0x0>,
+ <0x6cc4 0x0>,
+ <0x6cc8 0x0>,
+ <0x6ccc 0x0>,
+ <0x6cd0 0x0>,
+ <0x6cd4 0x0>,
+ <0x6cd8 0x0>,
+ <0x6cdc 0x0>,
+ <0x6ce0 0x0>,
+ <0x6ce4 0x0>,
+ <0x6ce8 0x0>,
+ <0x6cec 0x0>,
+ <0x6cf0 0x0>,
+ <0x6cf4 0x0>,
+ <0x6cf8 0x0>,
+ <0x6cfc 0x0>,
+ <0x6d00 0x0>,
+ <0x6d04 0x0>,
+ <0x6d08 0x0>,
+ <0x6d0c 0x0>,
+ <0x6d10 0x0>,
+ <0x6d14 0x0>,
+ <0x6d18 0x0>,
+ <0x6d1c 0x0>,
+ <0x6d20 0x0>,
+ <0x6d24 0x0>,
+ <0x6d28 0x0>,
+ <0x6d2c 0x0>,
+ <0x6d30 0x0>,
+ <0x6d34 0x0>,
+ <0x6d38 0x0>,
+ <0x6d3c 0x0>,
+ <0x6d40 0x0>,
+ <0x6d44 0x0>,
+ <0x6d48 0x0>,
+ <0x6d4c 0x0>,
+ <0x6d50 0x0>,
+ <0x6d54 0x0>,
+ <0x6d58 0x0>,
+ <0x6d5c 0x0>,
+ <0x6d60 0x0>,
+ <0x6d64 0x0>,
+ <0x6d68 0x0>,
+ <0x6d6c 0x0>,
+ <0x6d70 0x0>,
+ <0x6d74 0x0>,
+ <0x6d78 0x0>,
+ <0x6d7c 0x0>,
+ <0x6d80 0x0>,
+ <0x6d84 0x0>,
+ <0x6d88 0x0>,
+ <0x6d8c 0x0>,
+ <0x6d90 0x0>,
+ <0x6d94 0x0>,
+ <0x6d98 0x0>,
+ <0x6d9c 0x0>,
+ <0x6da0 0x0>,
+ <0x6da4 0x0>,
+ <0x6da8 0x0>,
+ <0x6dac 0x0>,
+ <0x6db0 0x0>,
+ <0x6db4 0x0>,
+ <0x6db8 0x0>,
+ <0x6dbc 0x0>,
+ <0x6dc0 0x0>,
+ <0x6dc4 0x0>,
+ <0x6dc8 0x0>,
+ <0x6dcc 0x0>,
+ <0x6dd0 0x0>,
+ <0x6dd4 0x0>,
+ <0x6dd8 0x0>,
+ <0x6ddc 0x0>,
+ <0x6de0 0x0>,
+ <0x6de4 0x0>,
+ <0x6de8 0x0>,
+ <0x6dec 0x0>,
+ <0x6df0 0x0>,
+ <0x6df4 0x0>,
+ <0x6df8 0x0>,
+ <0x6dfc 0x0>;
+};
+
+&anoc2_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0x12>,
+ <0x6074 0x26>,
+ <0x6078 0x3a>,
+ <0x607c 0x3c>,
+ <0x6080 0x3f>,
+ <0x6084 0x67>,
+ <0x6088 0x6c>,
+ <0x608c 0x74>,
+ <0x6090 0x7c>,
+ <0x6094 0x80>,
+ <0x6098 0xa0>,
+ <0x609c 0xa0>,
+ <0x60a0 0xa0>,
+ <0x60a4 0xa0>,
+ <0x60a8 0xa0>,
+ <0x60ac 0xa0>,
+ <0x60f0 0x0>,
+ <0x60f4 0x1>,
+ <0x60f8 0x3>,
+ <0x60fc 0x4>,
+ <0x6100 0x5>,
+ <0x6104 0x7>,
+ <0x6108 0x8>,
+ <0x610c 0x10>,
+ <0x6110 0x10>,
+ <0x6114 0x10>,
+ <0x6118 0x12>,
+ <0x611c 0x12>,
+ <0x6120 0x12>,
+ <0x6124 0x12>,
+ <0x6128 0x12>,
+ <0x612c 0x12>,
+ <0x6170 0x0>,
+ <0x6174 0x0>,
+ <0x6178 0x0>,
+ <0x617c 0x0>,
+ <0x6180 0x0>,
+ <0x6184 0x0>,
+ <0x6188 0x0>,
+ <0x618c 0x0>,
+ <0x6190 0x0>,
+ <0x6194 0x0>,
+ <0x6198 0x0>,
+ <0x619c 0x0>,
+ <0x61a0 0x0>,
+ <0x61a4 0x0>,
+ <0x61a8 0x0>,
+ <0x61ac 0x0>,
+ <0x6270 0x0>,
+ <0x6274 0x1>,
+ <0x6278 0x2>,
+ <0x627c 0x4>,
+ <0x6280 0x4>,
+ <0x6284 0x6>,
+ <0x6288 0x6>,
+ <0x628c 0x18>,
+ <0x6290 0x1a>,
+ <0x6294 0x1a>,
+ <0x6298 0x1e>,
+ <0x629c 0x1e>,
+ <0x62a0 0x1e>,
+ <0x62a4 0x1e>,
+ <0x62a8 0x1e>,
+ <0x62ac 0x1e>,
+ <0x62f0 0x1e>,
+ <0x62f4 0x24>,
+ <0x62f8 0x2a>,
+ <0x62fc 0x2c>,
+ <0x6300 0x2d>,
+ <0x6304 0x33>,
+ <0x6308 0x34>,
+ <0x630c 0x3a>,
+ <0x6310 0x3c>,
+ <0x6314 0x44>,
+ <0x6318 0x48>,
+ <0x631c 0x48>,
+ <0x6320 0x48>,
+ <0x6324 0x48>,
+ <0x6328 0x48>,
+ <0x632c 0x48>,
+ <0x6370 0x48>,
+ <0x6374 0x4d>,
+ <0x6378 0x52>,
+ <0x637c 0x56>,
+ <0x6380 0x59>,
+ <0x6384 0x63>,
+ <0x6388 0x68>,
+ <0x638c 0x70>,
+ <0x6390 0x78>,
+ <0x6394 0x88>,
+ <0x6398 0x90>,
+ <0x639c 0x90>,
+ <0x63a0 0x90>,
+ <0x63a4 0x90>,
+ <0x63a8 0x90>,
+ <0x63ac 0x90>,
+ <0x67a0 0x0>,
+ <0x67a4 0x8e>,
+ <0x67a8 0xa0>,
+ <0x67b0 0x0>,
+ <0x67b4 0x1e>,
+ <0x67b8 0xc6>,
+ <0x67d0 0x0>,
+ <0x67dc 0x4>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6b48 0x330331>,
+ <0x6b4c 0x81>,
+ <0x6b50 0x1313>,
+ <0x6b64 0x121155>,
+ <0x6b68 0xea880920>,
+ <0x6b70 0x10100101>,
+ <0x6b74 0xc0c0000>,
+ <0x6b78 0xc0c0000>,
+ <0x6b80 0x20012001>,
+ <0x6b84 0x20012001>,
+ <0x6c00 0x5>,
+ <0x6c04 0x0>,
+ <0x6c08 0x5>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x5>,
+ <0x6c14 0x0>,
+ <0x6c18 0x5>,
+ <0x6c1c 0x0>,
+ <0x6c20 0x5>,
+ <0x6c24 0x0>,
+ <0x6c28 0x0>,
+ <0x6c2c 0x0>,
+ <0x6c30 0x0>,
+ <0x6c34 0x0>,
+ <0x6c38 0x0>,
+ <0x6c3c 0x0>,
+ <0x6c40 0x0>,
+ <0x6c44 0x0>,
+ <0x6c48 0x0>,
+ <0x6c4c 0x0>,
+ <0x6c50 0x0>,
+ <0x6c54 0x0>,
+ <0x6c58 0x0>,
+ <0x6c5c 0x0>,
+ <0x6c60 0x0>,
+ <0x6c64 0x0>,
+ <0x6c68 0x0>,
+ <0x6c6c 0x0>,
+ <0x6c70 0x0>,
+ <0x6c74 0x0>,
+ <0x6c78 0x0>,
+ <0x6c7c 0x0>,
+ <0x6c80 0x0>,
+ <0x6c84 0x0>,
+ <0x6c88 0x0>,
+ <0x6c8c 0x0>,
+ <0x6c90 0x0>,
+ <0x6c94 0x0>,
+ <0x6c98 0x0>,
+ <0x6c9c 0x0>,
+ <0x6ca0 0x0>,
+ <0x6ca4 0x0>,
+ <0x6ca8 0x0>,
+ <0x6cac 0x0>,
+ <0x6cb0 0x0>,
+ <0x6cb4 0x0>,
+ <0x6cb8 0x0>,
+ <0x6cbc 0x0>,
+ <0x6cc0 0x0>,
+ <0x6cc4 0x0>,
+ <0x6cc8 0x0>,
+ <0x6ccc 0x0>,
+ <0x6cd0 0x0>,
+ <0x6cd4 0x0>,
+ <0x6cd8 0x0>,
+ <0x6cdc 0x0>,
+ <0x6ce0 0x0>,
+ <0x6ce4 0x0>,
+ <0x6ce8 0x0>,
+ <0x6cec 0x0>,
+ <0x6cf0 0x0>,
+ <0x6cf4 0x0>,
+ <0x6cf8 0x0>,
+ <0x6cfc 0x0>,
+ <0x6d00 0x8>,
+ <0x6d04 0x0>,
+ <0x6d08 0x8>,
+ <0x6d0c 0x0>,
+ <0x6d10 0x7>,
+ <0x6d14 0x0>,
+ <0x6d18 0x3>,
+ <0x6d1c 0x2>,
+ <0x6d20 0x4>,
+ <0x6d24 0x0>,
+ <0x6d28 0x4>,
+ <0x6d2c 0x0>,
+ <0x6d30 0x6>,
+ <0x6d34 0x0>,
+ <0x6d38 0x9>,
+ <0x6d3c 0x0>,
+ <0x6d40 0x0>,
+ <0x6d44 0x1>,
+ <0x6d48 0x4>,
+ <0x6d4c 0x0>,
+ <0x6d50 0x4>,
+ <0x6d54 0x0>,
+ <0x6d58 0x0>,
+ <0x6d5c 0x0>,
+ <0x6d60 0x0>,
+ <0x6d64 0x0>,
+ <0x6d68 0x0>,
+ <0x6d6c 0x0>,
+ <0x6d70 0x0>,
+ <0x6d74 0x0>,
+ <0x6d78 0x0>,
+ <0x6d7c 0x0>,
+ <0x6d80 0x0>,
+ <0x6d84 0x0>,
+ <0x6d88 0x0>,
+ <0x6d8c 0x0>,
+ <0x6d90 0x0>,
+ <0x6d94 0x0>,
+ <0x6d98 0x0>,
+ <0x6d9c 0x0>,
+ <0x6da0 0x0>,
+ <0x6da4 0x0>,
+ <0x6da8 0x0>,
+ <0x6dac 0x0>,
+ <0x6db0 0x0>,
+ <0x6db4 0x0>,
+ <0x6db8 0x0>,
+ <0x6dbc 0x0>,
+ <0x6dc0 0x0>,
+ <0x6dc4 0x0>,
+ <0x6dc8 0x0>,
+ <0x6dcc 0x0>,
+ <0x6dd0 0x0>,
+ <0x6dd4 0x0>,
+ <0x6dd8 0x0>,
+ <0x6ddc 0x0>,
+ <0x6de0 0x0>,
+ <0x6de4 0x0>,
+ <0x6de8 0x0>,
+ <0x6dec 0x0>,
+ <0x6df0 0x0>,
+ <0x6df4 0x0>,
+ <0x6df8 0x0>,
+ <0x6dfc 0x0>;
+};
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index 596a713a9ad0..deccd14d5d85 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -781,6 +781,7 @@
reg-names = "cc_base";
vdd_dig-supply = <&pm8994_s1_corner>;
#clock-cells = <1>;
+ #reset-cells = <1>;
};
clock_mmss: qcom,mmsscc@8c0000 {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
index 6ab19b298aa7..d273d757dba5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
@@ -79,6 +79,8 @@
qcom,snapshot-size = <1048576>; //bytes
+ qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size
+
clocks = <&clock_gfx clk_gpucc_gfx3d_clk>,
<&clock_gcc clk_gcc_gpu_cfg_ahb_clk>,
<&clock_gpu clk_gpucc_rbbmtimer_clk>,
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi
index a99ce727c195..7f1f2c10f6c4 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi
@@ -44,7 +44,8 @@
/* VBIF QoS remapper settings*/
qcom,mdss-vbif-qos-rt-setting = <1 2 2 2>;
- qcom,vbif-settings = <0x00ac 0x00000040>;
+ qcom,vbif-settings = <0x00ac 0x00000040>,
+ <0x00d0 0x00001010>; /* v1 only */
qcom,mdss-has-panic-ctrl;
qcom,mdss-per-pipe-panic-luts = <0x000f>,
@@ -57,9 +58,8 @@
qcom,max-bandwidth-high-kbps = <6700000>;
qcom,max-bandwidth-per-pipe-kbps = <2400000>;
qcom,max-clk-rate = <412500000>;
- /* OT settings and bw for v1, revisit for v2 */
- qcom,mdss-default-ot-rd-limit = <16>;
- qcom,mdss-default-ot-wr-limit = <16>;
+ qcom,mdss-default-ot-rd-limit = <32>;
+ qcom,mdss-default-ot-wr-limit = <32>;
qcom,mdss-dram-channels = <2>;
qcom,mdss-pipe-vig-off = <0x00005000 0x00007000
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
index 5833b30d1fd1..9f8ecea15568 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
@@ -944,20 +944,20 @@
qcom,cpr-voltage-ceiling =
<896000 896000 896000 896000 896000
1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>,
- <632000 696000 768000 828000 896000
- 1032000>;
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>,
+ <672000 740000 800000 868000 976000
+ 1100000>;
qcom,cpr-voltage-floor =
<896000 896000 896000 896000 896000
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
index 3bb5943634f2..b484b94692b5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
@@ -58,3 +58,10 @@
< 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >,
< 710000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
};
+
+&mdss_mdp {
+ qcom,vbif-settings = <0x00d0 0x00002020>;
+ qcom,max-bandwidth-low-kbps = <9400000>;
+ qcom,max-bandwidth-high-kbps = <9400000>;
+ qcom,max-bandwidth-per-pipe-kbps = <4700000>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index c9a2abf0d5b5..83ad8861103b 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -1309,6 +1309,35 @@
qcom,rx-ring-size = <0x800>;
};
+ glink_spi_xprt_wdsp: qcom,glink-spi-xprt-wdsp {
+ compatible = "qcom,glink-spi-xprt";
+ label = "wdsp";
+ qcom,remote-fifo-config = <&glink_fifo_wdsp>;
+ qcom,qos-config = <&glink_qos_wdsp>;
+ qcom,ramp-time = <0x10>,
+ <0x20>,
+ <0x30>,
+ <0x40>;
+ };
+
+ glink_fifo_wdsp: qcom,glink-fifo-config-wdsp {
+ compatible = "qcom,glink-fifo-config";
+ qcom,out-read-idx-reg = <0x12000>;
+ qcom,out-write-idx-reg = <0x12004>;
+ qcom,in-read-idx-reg = <0x1200C>;
+ qcom,in-write-idx-reg = <0x12010>;
+ };
+
+ glink_qos_wdsp: qcom,glink-qos-config-wdsp {
+ compatible = "qcom,glink-qos-config";
+ qcom,flow-info = <0x80 0x0>,
+ <0x70 0x1>,
+ <0x60 0x2>,
+ <0x50 0x3>;
+ qcom,mtu-size = <0x800>;
+ qcom,tput-stats-cycle = <0xa>;
+ };
+
qcom,glink_pkt {
compatible = "qcom,glinkpkt";
@@ -1737,6 +1766,7 @@
clock-names = "core_clk", "iface_clk", "bus_aggr_clk",
"utmi_clk", "sleep_clk", "xo";
+ qcom,core-clk-rate = <120000000>;
dwc3@a800000 {
compatible = "snps,dwc3";
reg = <0x0a800000 0xcd00>;
@@ -2918,6 +2948,7 @@
#include "msmcobalt-pm.dtsi"
#include "msm-arm-smmu-cobalt.dtsi"
+#include "msm-arm-smmu-impl-defs-cobalt.dtsi"
#include "msmcobalt-ion.dtsi"
#include "msmcobalt-camera.dtsi"
#include "msmcobalt-vidc.dtsi"
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
index a397310d4a61..6a000e4d4fd0 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
@@ -11,9 +11,9 @@
*/
&soc {
- tlmm: pinctrl@03400000 {
+ tlmm: pinctrl@03000000 {
compatible = "qcom,msmfalcon-pinctrl";
- reg = <0x03400000 0xc00000>;
+ reg = <0x03000000 0xc00000>;
interrupts = <0 208 0>;
gpio-controller;
#gpio-cells = <2>;
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 9ccf55322de1..4b3ebd3d1636 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -314,6 +314,16 @@
#clock-cells = <1>;
};
+ clock_mmss: qcom,dummycc {
+ compatible = "qcom,dummycc";
+ #clock-cells = <1>;
+ };
+
+ clock_gfx: qcom,dummycc {
+ compatible = "qcom,dummycc";
+ #clock-cells = <1>;
+ };
+
qcom,ipc-spinlock@1f40000 {
compatible = "qcom,ipc-spinlock-sfpb";
reg = <0x1f40000 0x8000>;
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index f9d9a882db1f..a09e952927f7 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -383,6 +383,7 @@ CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
CONFIG_FB_MSM_MDSS_DP_PANEL=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
@@ -419,6 +420,7 @@ CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_MTP=y
@@ -481,6 +483,7 @@ CONFIG_MSM_GLINK=y
CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
CONFIG_MSM_GLINK_SMD_XPRT=y
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_MSM_SPCOM=y
CONFIG_MSM_SMEM_LOGGING=y
CONFIG_MSM_SMP2P=y
@@ -495,6 +498,7 @@ CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SPM=y
CONFIG_QCOM_SCM=y
CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_IRQ_HELPER=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_ICNSS=y
CONFIG_MSM_RUN_QUEUE_STATS=y
@@ -517,7 +521,9 @@ CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_QSEE_IPC_IRQ_BRIDGE=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_ARM_MEMLAT_MON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_GOV_MEMLAT=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index bdfcbb4d1621..cfc2c30ca91f 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -386,6 +386,7 @@ CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
CONFIG_FB_MSM_MDSS_DP_PANEL=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
@@ -421,6 +422,7 @@ CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_MTP=y
@@ -494,6 +496,7 @@ CONFIG_MSM_GLINK=y
CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
CONFIG_MSM_GLINK_SMD_XPRT=y
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_MSM_SPCOM=y
CONFIG_MSM_SMEM_LOGGING=y
CONFIG_MSM_SMP2P=y
@@ -510,6 +513,7 @@ CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SPM=y
CONFIG_QCOM_SCM=y
CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_IRQ_HELPER=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_ICNSS=y
CONFIG_MSM_GLADIATOR_ERP_V2=y
@@ -538,7 +542,9 @@ CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_QSEE_IPC_IRQ_BRIDGE=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_ARM_MEMLAT_MON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_GOV_MEMLAT=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c
index 3b3d1b2e37b1..a88ae0f59e63 100644
--- a/drivers/bluetooth/btfm_slim.c
+++ b/drivers/bluetooth/btfm_slim.c
@@ -132,7 +132,8 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
/* Define the channel with below parameters */
prop.prot = SLIM_AUTO_ISO;
prop.baser = SLIM_RATE_4000HZ;
- prop.dataf = SLIM_CH_DATAF_LPCM_AUDIO;
+ prop.dataf = (rates == 48000) ? SLIM_CH_DATAF_NOT_DEFINED
+ : SLIM_CH_DATAF_LPCM_AUDIO;
prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
prop.ratem = (rates/4000);
prop.sampleszbits = 16;
diff --git a/drivers/bluetooth/btfm_slim.h b/drivers/bluetooth/btfm_slim.h
index 1161708d6a90..dbb4c563d802 100644
--- a/drivers/bluetooth/btfm_slim.h
+++ b/drivers/bluetooth/btfm_slim.h
@@ -39,7 +39,7 @@
enum {
BTFM_FM_SLIM_TX = 0,
BTFM_BT_SCO_SLIM_TX,
- BTFM_BT_SCO_SLIM_RX,
+ BTFM_BT_SCO_A2DP_SLIM_RX,
BTFM_BT_SPLIT_A2DP_SLIM_RX,
BTFM_SLIM_NUM_CODEC_DAIS
};
diff --git a/drivers/bluetooth/btfm_slim_codec.c b/drivers/bluetooth/btfm_slim_codec.c
index 2194b8cc6f6f..d7d24ff07801 100644
--- a/drivers/bluetooth/btfm_slim_codec.c
+++ b/drivers/bluetooth/btfm_slim_codec.c
@@ -102,7 +102,7 @@ int btfm_slim_dai_prepare(struct snd_pcm_substream *substream,
ch = btfmslim->tx_chs;
rxport = 0;
break;
- case BTFM_BT_SCO_SLIM_RX:
+ case BTFM_BT_SCO_A2DP_SLIM_RX:
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
ch = btfmslim->rx_chs;
rxport = 1;
@@ -150,7 +150,7 @@ int btfm_slim_dai_hw_free(struct snd_pcm_substream *substream,
ch = btfmslim->tx_chs;
rxport = 0;
break;
- case BTFM_BT_SCO_SLIM_RX:
+ case BTFM_BT_SCO_A2DP_SLIM_RX:
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
ch = btfmslim->rx_chs;
rxport = 1;
@@ -267,7 +267,7 @@ static int btfm_slim_dai_get_channel_map(struct snd_soc_dai *dai,
*tx_num = num;
*rx_num = 0;
break;
- case BTFM_BT_SCO_SLIM_RX:
+ case BTFM_BT_SCO_A2DP_SLIM_RX:
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
if (!rx_slot || !rx_num) {
BTFMSLIM_ERR("Invalid rx_slot %p or rx_num %p",
@@ -335,7 +335,7 @@ static struct snd_soc_dai_driver btfmslim_dai[] = {
},
.ops = &btfmslim_dai_ops,
},
- { /* Bluetooth SCO NBS voice uplink: bt -> modem */
+ { /* Bluetooth SCO voice uplink: bt -> modem */
.name = "btfm_bt_sco_slim_tx",
.id = BTFM_BT_SCO_SLIM_TX,
.capture = {
@@ -350,15 +350,15 @@ static struct snd_soc_dai_driver btfmslim_dai[] = {
},
.ops = &btfmslim_dai_ops,
},
- { /* Bluetooth SCO NBS voice downlink: modem -> bt */
- .name = "btfm_bt_sco_slim_rx",
- .id = BTFM_BT_SCO_SLIM_RX,
+ { /* Bluetooth SCO voice downlink: modem -> bt or A2DP Playback */
+ .name = "btfm_bt_sco_a2dp_slim_rx",
+ .id = BTFM_BT_SCO_A2DP_SLIM_RX,
.playback = {
- .stream_name = "SCO RX Playback",
- /* 8 KHz or 16 KHz */
- .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .stream_name = "SCO A2DP RX Playback",
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000
+ | SNDRV_PCM_RATE_48000, /* 8 or 16 or 48 Khz*/
.formats = SNDRV_PCM_FMTBIT_S16_LE, /* 16 bits */
- .rate_max = 16000,
+ .rate_max = 48000,
.rate_min = 8000,
.channels_min = 1,
.channels_max = 1,
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index 3300085be9a7..7d7bd2441c6e 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -15,7 +15,7 @@
/* WCN3990 Port assignment */
struct btfmslim_ch wcn3990_rxport[] = {
- {.id = BTFM_BT_SCO_SLIM_RX, .name = "SCO_Rx",
+ {.id = BTFM_BT_SCO_A2DP_SLIM_RX, .name = "SCO_A2P_Rx",
.port = CHRK_SB_PGD_PORT_RX_SCO},
{.id = BTFM_BT_SPLIT_A2DP_SLIM_RX, .name = "A2P_Rx",
.port = CHRK_SB_PGD_PORT_RX_A2P},
diff --git a/drivers/clk/msm/Makefile b/drivers/clk/msm/Makefile
index ecf0b09bb49a..baf22bf1df9a 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK_MSM) += clock-pll.o
obj-$(CONFIG_COMMON_CLK_MSM) += clock-alpha-pll.o
obj-$(CONFIG_COMMON_CLK_MSM) += clock-rpm.o
obj-$(CONFIG_COMMON_CLK_MSM) += clock-voter.o
+obj-$(CONFIG_COMMON_CLK_MSM) += reset.o
obj-$(CONFIG_MSM_CLK_CONTROLLER_V2) += msm-clock-controller.o
diff --git a/drivers/clk/msm/clock-gcc-8996.c b/drivers/clk/msm/clock-gcc-8996.c
index edd78e29957d..a9e0b53c3b22 100644
--- a/drivers/clk/msm/clock-gcc-8996.c
+++ b/drivers/clk/msm/clock-gcc-8996.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -31,6 +31,7 @@
#include <dt-bindings/clock/msm-clocks-8996.h>
#include <dt-bindings/clock/msm-clocks-hwio-8996.h>
+#include "reset.h"
#include "vdd-level-8996.h"
static void __iomem *virt_base;
@@ -3142,6 +3143,26 @@ static struct branch_clk gcc_aggre0_noc_mpu_cfg_ahb_clk = {
},
};
+static const struct msm_reset_map gcc_msm8996_resets[] = {
+ [QUSB2PHY_PRIM_BCR] = { 0x12038 },
+ [QUSB2PHY_SEC_BCR] = { 0x1203c },
+ [BLSP1_BCR] = { 0x17000 },
+ [BLSP2_BCR] = { 0x25000 },
+ [BOOT_ROM_BCR] = { 0x38000 },
+ [PRNG_BCR] = { 0x34000 },
+ [UFS_BCR] = { 0x75000 },
+ [USB_20_BCR] = { 0x12000 },
+ [USB_30_BCR] = { 0x0f000 },
+ [USB3_PHY_BCR] = { 0x50020 },
+ [USB3PHY_PHY_BCR] = { 0x50024 },
+ [PCIE_0_PHY_BCR] = { 0x6c01c },
+ [PCIE_1_PHY_BCR] = { 0x6d038 },
+ [PCIE_2_PHY_BCR] = { 0x6e038 },
+ [PCIE_PHY_BCR] = { 0x6f000 },
+ [PCIE_PHY_NOCSR_COM_PHY_BCR] = { 0x6f00C },
+ [PCIE_PHY_COM_BCR] = { 0x6f014 },
+};
+
static struct mux_clk gcc_debug_mux;
static struct mux_clk gcc_debug_mux_v2;
static struct clk_ops clk_ops_debug_mux;
@@ -3711,6 +3732,10 @@ static int msm_gcc_8996_probe(struct platform_device *pdev)
*/
clk_set_flags(&gcc_mmss_bimc_gfx_clk.c, CLKFLAG_RETAIN_MEM);
+ /* Register block resets */
+ msm_reset_controller_register(pdev, gcc_msm8996_resets,
+ ARRAY_SIZE(gcc_msm8996_resets), virt_base);
+
dev_info(&pdev->dev, "Registered GCC clocks.\n");
return 0;
}
diff --git a/drivers/clk/msm/clock-mmss-8996.c b/drivers/clk/msm/clock-mmss-8996.c
index ba81731ce1cb..91c871cae225 100644
--- a/drivers/clk/msm/clock-mmss-8996.c
+++ b/drivers/clk/msm/clock-mmss-8996.c
@@ -32,6 +32,7 @@
#include "vdd-level-8996.h"
#include "clock.h"
+#include "reset.h"
static void __iomem *virt_base;
static void __iomem *virt_base_gpu;
@@ -3032,6 +3033,17 @@ static struct branch_clk vmem_maxi_clk = {
},
};
+static const struct msm_reset_map mmss_msm8996_resets[] = {
+ [VIDEO_BCR] = { 0x1020 },
+ [MDSS_BCR] = { 0x2300 },
+ [CAMSS_MICRO_BCR] = { 0x3490 },
+ [CAMSS_JPEG_BCR] = { 0x35a0 },
+ [CAMSS_VFE0_BCR] = { 0x3660 },
+ [CAMSS_VFE1_BCR] = { 0x3670 },
+ [FD_BCR] = { 0x3b60 },
+ [GPU_GX_BCR] = { 0x4020 },
+};
+
static struct mux_clk mmss_gcc_dbg_clk = {
.ops = &mux_reg_ops,
.en_mask = BIT(16),
@@ -3778,6 +3790,11 @@ int msm_mmsscc_8996_probe(struct platform_device *pdev)
if (rc)
return rc;
}
+
+ /* Register block resets */
+ msm_reset_controller_register(pdev, mmss_msm8996_resets,
+ ARRAY_SIZE(mmss_msm8996_resets), virt_base);
+
dev_info(&pdev->dev, "Registered MMSS clocks.\n");
return platform_driver_register(&msm_clock_gpu_driver);
diff --git a/drivers/clk/msm/gdsc.c b/drivers/clk/msm/gdsc.c
index 5ea2a9ccd1bb..cdaba72532d4 100644
--- a/drivers/clk/msm/gdsc.c
+++ b/drivers/clk/msm/gdsc.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/reset.h>
#include <linux/regulator/of_regulator.h>
#include <linux/slab.h>
#include <linux/clk.h>
@@ -48,7 +49,9 @@ struct gdsc {
struct regulator_desc rdesc;
void __iomem *gdscr;
struct clk **clocks;
+ struct reset_control **reset_clocks;
int clock_count;
+ int reset_count;
bool toggle_mem;
bool toggle_periph;
bool toggle_logic;
@@ -247,9 +250,8 @@ static int gdsc_enable(struct regulator_dev *rdev)
}
}
} else {
- for (i = 0; i < sc->clock_count; i++)
- if (likely(i != sc->root_clk_idx))
- clk_reset(sc->clocks[i], CLK_RESET_DEASSERT);
+ for (i = 0; i < sc->reset_count; i++)
+ reset_control_deassert(sc->reset_clocks[i]);
sc->resets_asserted = false;
}
@@ -342,9 +344,8 @@ static int gdsc_disable(struct regulator_dev *rdev)
wmb();
}
} else {
- for (i = sc->clock_count-1; i >= 0; i--)
- if (likely(i != sc->root_clk_idx))
- clk_reset(sc->clocks[i], CLK_RESET_ASSERT);
+ for (i = sc->reset_count-1; i >= 0; i--)
+ reset_control_assert(sc->reset_clocks[i]);
sc->resets_asserted = true;
}
@@ -605,6 +606,39 @@ static int gdsc_probe(struct platform_device *pdev)
}
if (!sc->toggle_logic) {
+ sc->reset_count = of_property_count_strings(pdev->dev.of_node,
+ "reset-names");
+ if (sc->reset_count == -EINVAL) {
+ sc->reset_count = 0;
+ } else if (IS_ERR_VALUE(sc->reset_count)) {
+ dev_err(&pdev->dev, "Failed to get reset reset names\n");
+ return -EINVAL;
+ }
+
+ sc->reset_clocks = devm_kzalloc(&pdev->dev,
+ sizeof(struct reset_control *) *
+ sc->reset_count,
+ GFP_KERNEL);
+ if (!sc->reset_clocks)
+ return -ENOMEM;
+
+ for (i = 0; i < sc->reset_count; i++) {
+ const char *reset_name;
+
+ of_property_read_string_index(pdev->dev.of_node,
+ "reset-names", i, &reset_name);
+ sc->reset_clocks[i] = devm_reset_control_get(&pdev->dev,
+ reset_name);
+ if (IS_ERR(sc->reset_clocks[i])) {
+ int rc = PTR_ERR(sc->reset_clocks[i]);
+
+ if (rc != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get %s\n",
+ reset_name);
+ return rc;
+ }
+ }
+
regval &= ~SW_COLLAPSE_MASK;
writel_relaxed(regval, sc->gdscr);
diff --git a/drivers/clk/msm/reset.c b/drivers/clk/msm/reset.c
new file mode 100644
index 000000000000..41e0357aea3e
--- /dev/null
+++ b/drivers/clk/msm/reset.c
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/reset-controller.h>
+
+#include "reset.h"
+
+static int msm_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ rcdev->ops->assert(rcdev, id);
+ udelay(1);
+ rcdev->ops->deassert(rcdev, id);
+ return 0;
+}
+
+static int
+msm_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ struct msm_reset_controller *rst;
+ const struct msm_reset_map *map;
+ u32 regval;
+
+ rst = to_msm_reset_controller(rcdev);
+ map = &rst->reset_map[id];
+
+ regval = readl_relaxed(rst->base + map->reg);
+ regval |= BIT(map->bit);
+ writel_relaxed(regval, rst->base + map->reg);
+
+ return 0;
+}
+
+static int
+msm_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ struct msm_reset_controller *rst;
+ const struct msm_reset_map *map;
+ u32 regval;
+
+ rst = to_msm_reset_controller(rcdev);
+ map = &rst->reset_map[id];
+
+ regval = readl_relaxed(rst->base + map->reg);
+ regval &= ~BIT(map->bit);
+ writel_relaxed(regval, rst->base + map->reg);
+
+ return 0;
+}
+
+struct reset_control_ops msm_reset_ops = {
+ .reset = msm_reset,
+ .assert = msm_reset_assert,
+ .deassert = msm_reset_deassert,
+};
+EXPORT_SYMBOL_GPL(msm_reset_ops);
+
+int msm_reset_controller_register(struct platform_device *pdev,
+ const struct msm_reset_map *map, unsigned int num_resets,
+ void __iomem *virt_base)
+{
+ struct msm_reset_controller *reset;
+ int ret = 0;
+
+ reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
+ if (!reset)
+ return -ENOMEM;
+
+ reset->rcdev.of_node = pdev->dev.of_node;
+ reset->rcdev.ops = &msm_reset_ops;
+ reset->rcdev.owner = pdev->dev.driver->owner;
+ reset->rcdev.nr_resets = num_resets;
+ reset->reset_map = map;
+ reset->base = virt_base;
+
+ ret = reset_controller_register(&reset->rcdev);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to register with reset controller\n");
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(msm_reset_controller_register);
diff --git a/drivers/clk/msm/reset.h b/drivers/clk/msm/reset.h
new file mode 100644
index 000000000000..538a432fed60
--- /dev/null
+++ b/drivers/clk/msm/reset.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#ifndef __DRIVERS_CLK_RESET_H
+#define __DRIVERS_CLK_RESET_H
+
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+struct msm_reset_map {
+ unsigned int reg;
+ u8 bit;
+};
+
+struct msm_reset_controller {
+ const struct msm_reset_map *reset_map;
+ struct reset_controller_dev rcdev;
+ void __iomem *base;
+};
+
+#define to_msm_reset_controller(r) \
+ container_of(r, struct msm_reset_controller, rcdev)
+
+extern struct reset_control_ops msm_reset_ops;
+
+int msm_reset_controller_register(struct platform_device *pdev,
+ const struct msm_reset_map *map, unsigned int nr_resets,
+ void __iomem *virt_base);
+#endif
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 3f8a3927ff92..2b0df3f0e04e 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -44,6 +44,7 @@
#include <asm/arch_timer.h>
#include <asm/cacheflush.h>
#include <asm/suspend.h>
+#include <asm/cpuidle.h>
#include "lpm-levels.h"
#include "lpm-workarounds.h"
#include <trace/events/power.h>
@@ -914,7 +915,6 @@ unlock_and_return:
}
#if !defined(CONFIG_CPU_V7)
-#include <asm/cpuidle.h>
asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64);
bool psci_enter_sleep(struct lpm_cluster *cluster, int idx, bool from_idle)
{
@@ -976,7 +976,7 @@ bool psci_enter_sleep(struct lpm_cluster *cluster, int idx, bool from_idle)
update_debug_pc_event(CPU_ENTER, state_id,
0xdeaffeed, 0xdeaffeed, true);
stop_critical_timings();
- success = !cpu_suspend(state_id);
+ success = !arm_cpuidle_suspend(state_id);
start_critical_timings();
update_debug_pc_event(CPU_EXIT, state_id,
success, 0xdeaffeed, true);
diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c
index 370d7d95042b..4fb0a5ffda50 100644
--- a/drivers/devfreq/arm-memlat-mon.c
+++ b/drivers/devfreq/arm-memlat-mon.c
@@ -311,19 +311,19 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
hw->of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0);
if (!hw->of_node) {
dev_err(dev, "Couldn't find a target device\n");
- goto err_out;
+ return -ENODEV;
}
if (get_mask_from_dev_handle(pdev, &cpu_grp->cpus)) {
dev_err(dev, "CPU list is empty\n");
- goto err_out;
+ return -ENODEV;
}
hw->num_cores = cpumask_weight(&cpu_grp->cpus);
hw->core_stats = devm_kzalloc(dev, hw->num_cores *
sizeof(*(hw->core_stats)), GFP_KERNEL);
if (!hw->core_stats)
- goto err_out;
+ return -ENOMEM;
for_each_cpu(cpu, &cpu_grp->cpus)
hw->core_stats[cpu - cpumask_first(&cpu_grp->cpus)].id = cpu;
@@ -335,14 +335,10 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
ret = register_memlat(dev, hw);
if (ret) {
pr_err("Mem Latency Gov registration failed\n");
- goto err_out;
+ return ret;
}
return 0;
-
-err_out:
- kfree(cpu_grp);
- return -EINVAL;
}
static struct of_device_id match_table[] = {
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 529edb16565a..69028bd45fdd 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1110,6 +1110,17 @@ config TOUCHSCREEN_COLIBRI_VF50
To compile this driver as a module, choose M here: the
module will be called colibri_vf50_ts.
+config TOUCHSCREEN_MSTAR21XX
+ tristate "Mstar touchscreens"
+ depends on I2C
+ help
+ Say Y here if you have a mstar touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called msg21xx_ts.
+
config TOUCHSCREEN_ROHM_BU21023
tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index e04e787cea6e..e1777f11d77b 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -97,3 +97,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
+obj-$(CONFIG_TOUCHSCREEN_MSTAR21XX) += msg21xx_ts.o
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index d619c1d06e9e..45ce036b1693 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -3,7 +3,7 @@
* FocalTech ft5x06 TouchScreen driver.
*
* Copyright (c) 2010 Focal tech Ltd.
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -24,13 +24,19 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
#include <linux/input/ft5x06_ts.h>
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
/* Early-suspend level */
-#define FT5X06_SUSPEND_LEVEL 1
+#define FT_SUSPEND_LEVEL 1
#endif
#define CFG_MAX_TOUCH_POINTS 5
@@ -50,33 +56,136 @@
#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
-/*register address*/
-#define FT5X06_REG_PMODE 0xA5
-#define FT5X06_REG_FW_VER 0xA6
-#define FT5X06_REG_POINT_RATE 0x88
-#define FT5X06_REG_THGROUP 0x80
-
-/* power register bits*/
-#define FT5X06_PMODE_ACTIVE 0x00
-#define FT5X06_PMODE_MONITOR 0x01
-#define FT5X06_PMODE_STANDBY 0x02
-#define FT5X06_PMODE_HIBERNATE 0x03
-
-#define FT5X06_VTG_MIN_UV 2600000
-#define FT5X06_VTG_MAX_UV 3300000
-#define FT5X06_I2C_VTG_MIN_UV 1800000
-#define FT5X06_I2C_VTG_MAX_UV 1800000
+/* register address*/
+#define FT_REG_DEV_MODE 0x00
+#define FT_DEV_MODE_REG_CAL 0x02
+#define FT_REG_ID 0xA3
+#define FT_REG_PMODE 0xA5
+#define FT_REG_FW_VER 0xA6
+#define FT_REG_POINT_RATE 0x88
+#define FT_REG_THGROUP 0x80
+#define FT_REG_ECC 0xCC
+#define FT_REG_RESET_FW 0x07
+
+/* power register bits */
+#define FT_PMODE_ACTIVE 0x00
+#define FT_PMODE_MONITOR 0x01
+#define FT_PMODE_STANDBY 0x02
+#define FT_PMODE_HIBERNATE 0x03
+#define FT_FACTORYMODE_VALUE 0x40
+#define FT_WORKMODE_VALUE 0x00
+#define FT_RST_CMD_REG 0xFC
+#define FT_READ_ID_REG 0x90
+#define FT_ERASE_APP_REG 0x61
+#define FT_ERASE_PANEL_REG 0x63
+#define FT_FW_START_REG 0xBF
+
+
+#define FT_VTG_MIN_UV 2600000
+#define FT_VTG_MAX_UV 3300000
+#define FT_I2C_VTG_MIN_UV 1800000
+#define FT_I2C_VTG_MAX_UV 1800000
+
+#define FT_COORDS_ARR_SIZE 4
+#define MAX_BUTTONS 4
+
+#define FT_8BIT_SHIFT 8
+#define FT_4BIT_SHIFT 4
+#define FT_FW_NAME_MAX_LEN 50
+
+#define FT5316_ID 0x0A
+#define FT5306I_ID 0x55
+
+#define FT_UPGRADE_AA 0xAA
+#define FT_UPGRADE_55 0x55
+
+/* upgrade config of FT5606 */
+#define FT5606_UPGRADE_AA_DELAY 50
+#define FT5606_UPGRADE_55_DELAY 10
+#define FT5606_UPGRADE_ID_1 0x79
+#define FT5606_UPGRADE_ID_2 0x06
+#define FT5606_UPGRADE_READID_DELAY 100
+#define FT5606_UPGRADE_EARSE_DELAY 2000
+
+/* upgrade config of FT5316 */
+#define FT5316_UPGRADE_AA_DELAY 50
+#define FT5316_UPGRADE_55_DELAY 30
+#define FT5316_UPGRADE_ID_1 0x79
+#define FT5316_UPGRADE_ID_2 0x07
+#define FT5316_UPGRADE_READID_DELAY 1
+#define FT5316_UPGRADE_EARSE_DELAY 1500
+
+/* upgrade config of FT5x06(x=2,3,4) */
+#define FT5X06_UPGRADE_AA_DELAY 50
+#define FT5X06_UPGRADE_55_DELAY 30
+#define FT5X06_UPGRADE_ID_1 0x79
+#define FT5X06_UPGRADE_ID_2 0x03
+#define FT5X06_UPGRADE_READID_DELAY 1
+#define FT5X06_UPGRADE_EARSE_DELAY 2000
+
+/* upgrade config of FT6208 */
+#define FT6208_UPGRADE_AA_DELAY 60
+#define FT6208_UPGRADE_55_DELAY 10
+#define FT6208_UPGRADE_ID_1 0x79
+#define FT6208_UPGRADE_ID_2 0x05
+#define FT6208_UPGRADE_READID_DELAY 10
+#define FT6208_UPGRADE_EARSE_DELAY 2000
+
+#define FT_UPGRADE_INFO(x, y) do { \
+ x->delay_55 = y##_UPGRADE_55_DELAY; \
+ x->delay_aa = y##_UPGRADE_AA_DELAY; \
+ x->upgrade_id_1 = y##_UPGRADE_ID_1; \
+ x->upgrade_id_2 = y##_UPGRADE_ID_2; \
+ x->delay_readid = y##_UPGRADE_READID_DELAY; \
+ x->delay_earse_flash = y##_UPGRADE_EARSE_DELAY; \
+ } while (0)
+
+#define FT_FW_MIN_SIZE 8
+#define FT_FW_MAX_SIZE 32768
+#define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2])
+#define FT_FW_CHECK(x) \
+ (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \
+ && (((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \
+ && (((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF)))
+
+#define FT_MAX_TRIES 5
+#define FT_RETRY_DLY 20
+
+#define FT_MAX_WR_BUF 10
+#define FT_MAX_RD_BUF 2
+#define FT_FW_PKT_LEN 128
+#define FT_FW_PKT_META_LEN 6
+#define FT_FW_PKT_DLY_MS 20
+#define FT_FW_LAST_PKT 0x6ffa
+#define FT_EARSE_DLY_MS 100
+
+#define FT_UPGRADE_LOOP 3
+#define FT_CAL_START 0x04
+#define FT_CAL_FIN 0x00
+#define FT_CAL_STORE 0x05
+#define FT_CAL_RETRY 100
+#define FT_REG_CAL 0x00
+#define FT_CAL_MASK 0x70
struct ts_event {
- u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
- u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
+ u16 x[CFG_MAX_TOUCH_POINTS]; /* x coordinate */
+ u16 y[CFG_MAX_TOUCH_POINTS]; /* y coordinate */
/* touch event: 0 -- down; 1-- contact; 2 -- contact */
u8 touch_event[CFG_MAX_TOUCH_POINTS];
- u8 finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
+ u8 finger_id[CFG_MAX_TOUCH_POINTS]; /* touch ID */
u16 pressure;
u8 touch_point;
};
+struct upgrade_info {
+ u16 delay_aa; /* delay of write FT_UPGRADE_AA */
+ u16 delay_55; /* delay of write FT_UPGRADE_55 */
+ u8 upgrade_id_1; /* upgrade id 1 */
+ u8 upgrade_id_2; /* upgrade id 2 */
+ u16 delay_readid; /* delay of read id */
+ u16 delay_earse_flash; /* delay of earse flash */
+};
+
struct ft5x06_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
@@ -84,7 +193,12 @@ struct ft5x06_ts_data {
const struct ft5x06_ts_platform_data *pdata;
struct regulator *vdd;
struct regulator *vcc_i2c;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ char fw_name[FT_FW_NAME_MAX_LEN];
+ bool loading_fw;
+ u8 family_id;
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
};
@@ -149,6 +263,21 @@ static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
return ret;
}
+static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val)
+{
+ u8 buf[2] = {0};
+
+ buf[0] = addr;
+ buf[1] = val;
+
+ return ft5x06_i2c_write(client, buf, sizeof(buf));
+}
+
+static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
+{
+ return ft5x06_i2c_read(client, &addr, 1, val, 1);
+}
+
static void ft5x06_report_value(struct ft5x06_ts_data *data)
{
struct ts_event *event = &data->event;
@@ -289,8 +418,8 @@ static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
}
if (regulator_count_voltages(data->vdd) > 0) {
- rc = regulator_set_voltage(data->vdd, FT5X06_VTG_MIN_UV,
- FT5X06_VTG_MAX_UV);
+ rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
+ FT_VTG_MAX_UV);
if (rc) {
dev_err(&data->client->dev,
"Regulator set_vtg failed vdd rc=%d\n", rc);
@@ -307,8 +436,8 @@ static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
}
if (regulator_count_voltages(data->vcc_i2c) > 0) {
- rc = regulator_set_voltage(data->vcc_i2c, FT5X06_I2C_VTG_MIN_UV,
- FT5X06_I2C_VTG_MAX_UV);
+ rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
+ FT_I2C_VTG_MAX_UV);
if (rc) {
dev_err(&data->client->dev,
"Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
@@ -322,19 +451,19 @@ reg_vcc_i2c_put:
regulator_put(data->vcc_i2c);
reg_vdd_set_vtg:
if (regulator_count_voltages(data->vdd) > 0)
- regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
+ regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
reg_vdd_put:
regulator_put(data->vdd);
return rc;
pwr_deinit:
if (regulator_count_voltages(data->vdd) > 0)
- regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
+ regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
regulator_put(data->vdd);
if (regulator_count_voltages(data->vcc_i2c) > 0)
- regulator_set_voltage(data->vcc_i2c, 0, FT5X06_I2C_VTG_MAX_UV);
+ regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
regulator_put(data->vcc_i2c);
return 0;
@@ -349,8 +478,8 @@ static int ft5x06_ts_suspend(struct device *dev)
disable_irq(data->client->irq);
if (gpio_is_valid(data->pdata->reset_gpio)) {
- txbuf[0] = FT5X06_REG_PMODE;
- txbuf[1] = FT5X06_PMODE_HIBERNATE;
+ txbuf[0] = FT_REG_PMODE;
+ txbuf[1] = FT_PMODE_HIBERNATE;
ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
}
@@ -371,7 +500,27 @@ static int ft5x06_ts_resume(struct device *dev)
return 0;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct ft5x06_ts_data *ft5x06_data =
+ container_of(self, struct ft5x06_ts_data, fb_notif);
+
+ if (evdata && evdata->data && event == FB_EVENT_BLANK &&
+ ft5x06_data && ft5x06_data->client) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ ft5x06_ts_resume(&ft5x06_data->client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ ft5x06_ts_suspend(&ft5x06_data->client->dev);
+ }
+
+ return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
static void ft5x06_ts_early_suspend(struct early_suspend *handler)
{
struct ft5x06_ts_data *data = container_of(handler,
@@ -392,23 +541,478 @@ static void ft5x06_ts_late_resume(struct early_suspend *handler)
#endif
static const struct dev_pm_ops ft5x06_ts_pm_ops = {
-#ifndef CONFIG_HAS_EARLYSUSPEND
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
.suspend = ft5x06_ts_suspend,
.resume = ft5x06_ts_resume,
#endif
};
#endif
+static int ft5x06_auto_cal(struct i2c_client *client)
+{
+ u8 temp = 0, i;
+
+ /* set to factory mode */
+ msleep(2 * FT_STARTUP_DLY);
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+ msleep(FT_STARTUP_DLY);
+
+ /* start calibration */
+ ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
+ msleep(2 * FT_STARTUP_DLY);
+ for (i = 0; i < FT_CAL_RETRY; i++) {
+ ft5x0x_read_reg(client, FT_REG_CAL, &temp);
+ /* return to normal mode, calibration finish */
+ if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
+ break;
+ }
+
+ /* calibration OK */
+ msleep(2 * FT_STARTUP_DLY);
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+ msleep(FT_STARTUP_DLY);
+
+ /* store calibration data */
+ ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
+ msleep(2 * FT_STARTUP_DLY);
+
+ /* set to normal mode */
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
+ msleep(2 * FT_STARTUP_DLY);
+
+ return 0;
+}
+
+static int ft5x06_get_upgrade_info(u8 family_id, struct upgrade_info *info)
+{
+ switch (family_id) {
+ case FT5306I_ID:
+ FT_UPGRADE_INFO(info, FT5X06);
+ break;
+ case FT5316_ID:
+ FT_UPGRADE_INFO(info, FT5316);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ft5x06_fw_upgrade_start(struct i2c_client *client,
+ const u8 *data, u32 data_len)
+{
+ struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
+ struct upgrade_info info;
+ u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
+ u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
+ int rc, i, j, temp;
+ u32 pkt_num, pkt_len;
+ u8 fw_ecc;
+
+ rc = ft5x06_get_upgrade_info(ts_data->family_id, &info);
+ if (rc < 0) {
+ dev_err(&client->dev, "Cannot get upgrade information!\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < FT_UPGRADE_LOOP; i++) {
+ /* reset - write 0xaa and 0x55 to register 0xfc */
+ ft5x0x_write_reg(client, FT_RST_CMD_REG, FT_UPGRADE_AA);
+ msleep(info.delay_aa);
+
+ ft5x0x_write_reg(client, FT_RST_CMD_REG, FT_UPGRADE_55);
+ msleep(info.delay_55);
+
+ /* Enter upgrade mode */
+ w_buf[0] = FT_UPGRADE_55;
+ w_buf[1] = FT_UPGRADE_AA;
+ do {
+ i++;
+ rc = ft5x06_i2c_write(client, w_buf, 2);
+ msleep(FT_RETRY_DLY);
+ } while (rc <= 0 && i < FT_MAX_TRIES);
+
+ /* check READ_ID */
+ msleep(info.delay_readid);
+ w_buf[0] = FT_READ_ID_REG;
+ w_buf[1] = 0x00;
+ w_buf[2] = 0x00;
+ w_buf[3] = 0x00;
+
+ ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
+
+ if (r_buf[0] != info.upgrade_id_1
+ || r_buf[1] != info.upgrade_id_2) {
+ dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
+ } else
+ break;
+ }
+
+ if (i >= FT_UPGRADE_LOOP) {
+ dev_err(&client->dev, "Abort upgrade\n");
+ return -EIO;
+ }
+
+ /* erase app and panel paramenter area */
+ w_buf[0] = FT_ERASE_APP_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(info.delay_earse_flash);
+
+ w_buf[0] = FT_ERASE_PANEL_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(FT_EARSE_DLY_MS);
+
+ /* program firmware */
+ data_len = data_len - 8;
+ pkt_num = (data_len) / FT_FW_PKT_LEN;
+ pkt_len = FT_FW_PKT_LEN;
+ pkt_buf[0] = FT_FW_START_REG;
+ pkt_buf[1] = 0x00;
+ fw_ecc = 0;
+
+ for (i = 0; i < pkt_num; i++) {
+ temp = i * FT_FW_PKT_LEN;
+ pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[3] = (u8) temp;
+ pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
+ pkt_buf[5] = (u8) pkt_len;
+
+ for (j = 0; j < FT_FW_PKT_LEN; j++) {
+ pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
+ fw_ecc ^= pkt_buf[6 + j];
+ }
+
+ ft5x06_i2c_write(client, pkt_buf,
+ FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* send remaining bytes */
+ if ((data_len) % FT_FW_PKT_LEN > 0) {
+ temp = pkt_num * FT_FW_PKT_LEN;
+ pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[3] = (u8) temp;
+ temp = (data_len) % FT_FW_PKT_LEN;
+ pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[5] = (u8) temp;
+
+ for (i = 0; i < temp; i++) {
+ pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
+ fw_ecc ^= pkt_buf[6 + i];
+ }
+
+ ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* send the finishing packet */
+ for (i = 0; i < 6; i++) {
+ temp = FT_FW_LAST_PKT + i;
+ pkt_buf[2] = (u8) (temp >> 8);
+ pkt_buf[3] = (u8) temp;
+ temp = 1;
+ pkt_buf[4] = (u8) (temp >> 8);
+ pkt_buf[5] = (u8) temp;
+ pkt_buf[6] = data[data_len + i];
+ fw_ecc ^= pkt_buf[6];
+ ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* verify checksum */
+ w_buf[0] = FT_REG_ECC;
+ ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
+ if (r_buf[0] != fw_ecc) {
+ dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
+ r_buf[0], fw_ecc);
+ return -EIO;
+ }
+
+ /* reset */
+ w_buf[0] = FT_REG_RESET_FW;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(FT_STARTUP_DLY);
+
+ return 0;
+}
+
+static int ft5x06_fw_upgrade(struct device *dev, bool force)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ const struct firmware *fw = NULL;
+ int rc;
+ u8 val = 0;
+
+ rc = request_firmware(&fw, data->fw_name, dev);
+ if (rc < 0) {
+ dev_err(dev, "Request firmware failed - %s (%d)\n",
+ data->fw_name, rc);
+ return rc;
+ }
+
+ if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
+ dev_err(dev, "Invalid firmware size (%d)\n", fw->size);
+ rc = -EIO;
+ goto rel_fw;
+ }
+
+ /* check firmware version */
+ rc = ft5x0x_read_reg(data->client, FT_REG_FW_VER, &val);
+ if (rc < 0) {
+ dev_err(dev, "Get firmware version failed\n");
+ goto rel_fw;
+ }
+
+ if (val == FT_FW_FILE_VER(fw) && !force) {
+ dev_err(dev, "No need to update (0x%x)\n", val);
+ rc = -EFAULT;
+ goto rel_fw;
+ }
+
+ dev_info(dev, "upgrade to fw ver 0x%x from 0x%x\n",
+ FT_FW_FILE_VER(fw), val);
+
+ /* start firmware upgrade */
+ if (FT_FW_CHECK(fw)) {
+ rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
+ if (rc < 0)
+ dev_err(dev, "update failed (%d)\n", rc);
+ else
+ ft5x06_auto_cal(data->client);
+ } else {
+ dev_err(dev, "FW format error\n");
+ rc = -EIO;
+ }
+
+rel_fw:
+ release_firmware(fw);
+ return rc;
+}
+
+static ssize_t ft5x06_update_fw_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, 2, "%d\n", data->loading_fw);
+}
+
+static ssize_t ft5x06_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = kstrtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&data->input_dev->mutex);
+ if (!data->loading_fw && val) {
+ data->loading_fw = true;
+ ft5x06_fw_upgrade(dev, false);
+ data->loading_fw = false;
+ }
+ mutex_unlock(&data->input_dev->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
+ ft5x06_update_fw_store);
+
+static ssize_t ft5x06_force_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = kstrtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&data->input_dev->mutex);
+ if (!data->loading_fw && val) {
+ data->loading_fw = true;
+ ft5x06_fw_upgrade(dev, true);
+ data->loading_fw = false;
+ }
+ mutex_unlock(&data->input_dev->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
+ ft5x06_force_update_fw_store);
+
+static ssize_t ft5x06_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
+}
+
+static ssize_t ft5x06_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ if (size > FT_FW_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(data->fw_name, buf, size);
+ if (data->fw_name[size-1] == '\n')
+ data->fw_name[size-1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
+
+#ifdef CONFIG_OF
+static int ft5x06_get_dt_coords(struct device *dev, char *name,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ u32 coords[FT_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FT_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "focaltech,panel-coords")) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (!strcmp(name, "focaltech,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ft5x06_parse_dt(struct device *dev,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val, num_buttons;
+ u32 button_map[MAX_BUTTONS];
+
+ rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
+ if (rc)
+ return rc;
+
+ pdata->i2c_pull_up = of_property_read_bool(np,
+ "focaltech,i2c-pull-up");
+
+ pdata->no_force_update = of_property_read_bool(np,
+ "focaltech,no-force-update");
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
+ 0, &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ return pdata->reset_gpio;
+
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
+ 0, &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ return pdata->irq_gpio;
+
+ rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
+ if (!rc)
+ pdata->family_id = temp_val;
+ else
+ return rc;
+
+ prop = of_find_property(np, "focaltech,button-map", NULL);
+ if (prop) {
+ num_buttons = prop->length / sizeof(temp_val);
+ if (num_buttons > MAX_BUTTONS)
+ return -EINVAL;
+
+ rc = of_property_read_u32_array(np,
+ "focaltech,button-map", button_map,
+ num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+#else
+static int ft5x06_parse_dt(struct device *dev,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ return -ENODEV;
+}
+#endif
+
static int ft5x06_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct ft5x06_ts_platform_data *pdata = client->dev.platform_data;
+ struct ft5x06_ts_platform_data *pdata;
struct ft5x06_ts_data *data;
struct input_dev *input_dev;
u8 reg_value;
u8 reg_addr;
int err;
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ err = ft5x06_parse_dt(&client->dev, pdata);
+ if (err)
+ return err;
+ } else
+ pdata = client->dev.platform_data;
+
if (!pdata) {
dev_err(&client->dev, "Invalid pdata\n");
return -EINVAL;
@@ -446,9 +1050,9 @@ static int ft5x06_ts_probe(struct i2c_client *client,
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
pdata->x_max, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
CFG_MAX_TOUCH_POINTS, 0, 0);
@@ -523,25 +1127,44 @@ static int ft5x06_ts_probe(struct i2c_client *client,
/* make sure CTP already finish startup process */
msleep(FT_STARTUP_DLY);
- /*get some register information */
- reg_addr = FT5X06_REG_FW_VER;
+ /* check the controller id */
+ reg_addr = FT_REG_ID;
err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0) {
dev_err(&client->dev, "version read failed");
+ return err;
+ }
+
+ dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
- dev_info(&client->dev, "[FTS] Firmware version = 0x%x\n", reg_value);
+ if (pdata->family_id != reg_value) {
+ dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
+ goto free_reset_gpio;
+ }
+
+ data->family_id = reg_value;
+
+ /* get some register information */
+ reg_addr = FT_REG_FW_VER;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "version read failed");
- reg_addr = FT5X06_REG_POINT_RATE;
+ dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
+
+ reg_addr = FT_REG_POINT_RATE;
ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0)
dev_err(&client->dev, "report rate read failed");
- dev_info(&client->dev, "[FTS] report rate is %dHz.\n", reg_value * 10);
- reg_addr = FT5X06_REG_THGROUP;
+ dev_dbg(&client->dev, "report rate = %dHz\n", reg_value * 10);
+
+ reg_addr = FT_REG_THGROUP;
err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0)
dev_err(&client->dev, "threshold read failed");
- dev_dbg(&client->dev, "[FTS] touch threshold is %d.\n", reg_value * 4);
+
+ dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
err = request_threaded_irq(client->irq, NULL,
ft5x06_ts_interrupt, pdata->irqflags,
@@ -551,9 +1174,36 @@ static int ft5x06_ts_probe(struct i2c_client *client,
goto free_reset_gpio;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ err = device_create_file(&client->dev, &dev_attr_fw_name);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto irq_free;
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_update_fw);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_fw_name_sys;
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_force_update_fw);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_update_fw_sys;
+ }
+
+
+#if defined(CONFIG_FB)
+ data->fb_notif.notifier_call = fb_notifier_callback;
+
+ err = fb_register_client(&data->fb_notif);
+
+ if (err)
+ dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
+ err);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
- FT5X06_SUSPEND_LEVEL;
+ FT_SUSPEND_LEVEL;
data->early_suspend.suspend = ft5x06_ts_early_suspend;
data->early_suspend.resume = ft5x06_ts_late_resume;
register_early_suspend(&data->early_suspend);
@@ -561,12 +1211,18 @@ static int ft5x06_ts_probe(struct i2c_client *client,
return 0;
+free_update_fw_sys:
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+free_fw_name_sys:
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+irq_free:
+ free_irq(client->irq, data);
free_reset_gpio:
if (gpio_is_valid(pdata->reset_gpio))
gpio_free(pdata->reset_gpio);
free_irq_gpio:
if (gpio_is_valid(pdata->irq_gpio))
- gpio_free(pdata->reset_gpio);
+ gpio_free(pdata->irq_gpio);
pwr_off:
if (pdata->power_on)
pdata->power_on(false);
@@ -591,7 +1247,14 @@ static int ft5x06_ts_remove(struct i2c_client *client)
{
struct ft5x06_ts_data *data = i2c_get_clientdata(client);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ device_remove_file(&client->dev, &dev_attr_force_update_fw);
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&data->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
unregister_early_suspend(&data->early_suspend);
#endif
free_irq(client->irq, data);
@@ -600,7 +1263,7 @@ static int ft5x06_ts_remove(struct i2c_client *client)
gpio_free(data->pdata->reset_gpio);
if (gpio_is_valid(data->pdata->irq_gpio))
- gpio_free(data->pdata->reset_gpio);
+ gpio_free(data->pdata->irq_gpio);
if (data->pdata->power_on)
data->pdata->power_on(false);
@@ -625,12 +1288,22 @@ static const struct i2c_device_id ft5x06_ts_id[] = {
MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
+#ifdef CONFIG_OF
+static const struct of_device_id ft5x06_match_table[] = {
+ { .compatible = "focaltech,5x06",},
+ { },
+};
+#else
+#define ft5x06_match_table NULL
+#endif
+
static struct i2c_driver ft5x06_ts_driver = {
.probe = ft5x06_ts_probe,
.remove = __devexit_p(ft5x06_ts_remove),
.driver = {
.name = "ft5x06_ts",
.owner = THIS_MODULE,
+ .of_match_table = ft5x06_match_table,
#ifdef CONFIG_PM
.pm = &ft5x06_ts_pm_ops,
#endif
diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c
index c60a2b5a94b0..9080a13069a8 100644
--- a/drivers/input/touchscreen/it7258_ts_i2c.c
+++ b/drivers/input/touchscreen/it7258_ts_i2c.c
@@ -1,7 +1,7 @@
/* drivers/input/touchscreen/it7258_ts_i2c.c
*
* Copyright (C) 2014 ITE Tech. Inc.
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -30,7 +30,7 @@
#include <linux/string.h>
#define MAX_BUFFER_SIZE 144
-#define DEVICE_NAME "IT7260"
+#define DEVICE_NAME "it7260"
#define SCREEN_X_RESOLUTION 320
#define SCREEN_Y_RESOLUTION 320
#define DEBUGFS_DIR_NAME "ts_debug"
@@ -99,18 +99,20 @@
#define FW_WRITE_CHUNK_SIZE 128
#define FW_WRITE_RETRY_COUNT 4
#define CHIP_FLASH_SIZE 0x8000
-#define DEVICE_READY_MAX_WAIT 10
+#define DEVICE_READY_COUNT_MAX 500
+#define DEVICE_READY_COUNT_20 20
+#define IT_I2C_WAIT_10MS 10
+#define IT_I2C_READ_RET 2
+#define IT_I2C_WRITE_RET 1
/* result of reading with BUF_QUERY bits */
#define CMD_STATUS_BITS 0x07
#define CMD_STATUS_DONE 0x00
#define CMD_STATUS_BUSY 0x01
#define CMD_STATUS_ERROR 0x02
+#define CMD_STATUS_NO_CONN 0x07
#define PT_INFO_BITS 0xF8
-#define BT_INFO_NONE 0x00
#define PT_INFO_YES 0x80
-/* no new data but finder(s) still down */
-#define BT_INFO_NONE_BUT_DOWN 0x08
#define PD_FLAGS_DATA_TYPE_BITS 0xF0
/* other types (like chip-detected gestures) exist but we do not care */
@@ -133,22 +135,21 @@
#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
#define PINCTRL_STATE_RELEASE "pmx_ts_release"
-#define IT_I2C_WAIT 1000
-struct FingerData {
+struct finger_data {
uint8_t xLo;
uint8_t hi;
uint8_t yLo;
uint8_t pressure;
} __packed;
-struct PointData {
+struct point_data {
uint8_t flags;
uint8_t palm;
- struct FingerData fd[3];
+ struct finger_data fd[3];
} __packed;
-struct IT7260_ts_platform_data {
+struct it7260_ts_platform_data {
u32 irq_gpio;
u32 irq_gpio_flags;
u32 reset_gpio;
@@ -172,10 +173,10 @@ struct IT7260_ts_platform_data {
bool low_reset;
};
-struct IT7260_ts_data {
+struct it7260_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
- const struct IT7260_ts_platform_data *pdata;
+ const struct it7260_ts_platform_data *pdata;
struct regulator *vdd;
struct regulator *avdd;
bool device_needs_wakeup;
@@ -204,44 +205,49 @@ struct IT7260_ts_data {
/* Function declarations */
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data);
-static int IT7260_ts_resume(struct device *dev);
-static int IT7260_ts_suspend(struct device *dev);
+static int it7260_ts_resume(struct device *dev);
+static int it7260_ts_suspend(struct device *dev);
-static struct IT7260_ts_data *gl_ts;
-
-static int IT7260_debug_suspend_set(void *_data, u64 val)
+static int it7260_debug_suspend_set(void *_data, u64 val)
{
+ struct it7260_ts_data *ts_data = _data;
+
if (val)
- IT7260_ts_suspend(&gl_ts->client->dev);
+ it7260_ts_suspend(&ts_data->client->dev);
else
- IT7260_ts_resume(&gl_ts->client->dev);
+ it7260_ts_resume(&ts_data->client->dev);
return 0;
}
-static int IT7260_debug_suspend_get(void *_data, u64 *val)
+static int it7260_debug_suspend_get(void *_data, u64 *val)
{
- *val = gl_ts->suspended;
+ struct it7260_ts_data *ts_data = _data;
+
+ mutex_lock(&ts_data->input_dev->mutex);
+ *val = ts_data->suspended;
+ mutex_lock(&ts_data->input_dev->mutex);
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, IT7260_debug_suspend_get,
- IT7260_debug_suspend_set, "%lld\n");
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, it7260_debug_suspend_get,
+ it7260_debug_suspend_set, "%lld\n");
/* internal use func - does not make sure chip is ready before read */
-static bool IT7260_i2cReadNoReadyCheck(uint8_t buf_index, uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_read_no_ready_check(struct it7260_ts_data *ts_data,
+ uint8_t buf_index, uint8_t *buffer, uint16_t buf_len)
{
+ int ret;
struct i2c_msg msgs[2] = {
{
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = I2C_M_NOSTART,
.len = 1,
.buf = &buf_index
},
{
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = I2C_M_RD,
.len = buf_len,
.buf = buffer
@@ -250,15 +256,20 @@ static bool IT7260_i2cReadNoReadyCheck(uint8_t buf_index, uint8_t *buffer,
memset(buffer, 0xFF, buf_len);
- return i2c_transfer(gl_ts->client->adapter, msgs, 2);
+ ret = i2c_transfer(ts_data->client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev, "i2c read failed %d\n", ret);
+
+ return ret;
}
-static bool IT7260_i2cWriteNoReadyCheck(uint8_t buf_index,
- const uint8_t *buffer, uint16_t buf_len)
+static int it7260_i2c_write_no_ready_check(struct it7260_ts_data *ts_data,
+ uint8_t buf_index, const uint8_t *buffer, uint16_t buf_len)
{
uint8_t txbuf[257];
+ int ret;
struct i2c_msg msg = {
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = 0,
.len = buf_len + 1,
.buf = txbuf
@@ -266,110 +277,178 @@ static bool IT7260_i2cWriteNoReadyCheck(uint8_t buf_index,
/* just to be careful */
if (buf_len > sizeof(txbuf) - 1) {
- dev_err(&gl_ts->client->dev, "buf length is out of limit\n");
+ dev_err(&ts_data->client->dev, "buf length is out of limit\n");
return false;
}
txbuf[0] = buf_index;
memcpy(txbuf + 1, buffer, buf_len);
- return i2c_transfer(gl_ts->client->adapter, &msg, 1);
+ ret = i2c_transfer(ts_data->client->adapter, &msg, 1);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev, "i2c write failed %d\n", ret);
+
+ return ret;
}
/*
- * Device is apparently always ready for i2c but not for actual
- * register reads/writes. This function ascertains it is ready
- * for that too. the results of this call often were ignored.
+ * Device is apparently always ready for I2C communication but not for
+ * actual register reads/writes. This function checks if it is ready
+ * for that too. The results of this call often were ignored.
+ * If forever is set to TRUE, then check the device's status until it
+ * becomes ready with 500 retries at max. Otherwise retry 25 times only.
+ * If slowly is set to TRUE, then add sleep of 50 ms in each retry,
+ * otherwise don't sleep.
*/
-static bool IT7260_waitDeviceReady(bool forever, bool slowly)
+static int it7260_wait_device_ready(struct it7260_ts_data *ts_data,
+ bool forever, bool slowly)
{
uint8_t query;
- uint32_t count = DEVICE_READY_MAX_WAIT;
+ uint32_t count = DEVICE_READY_COUNT_20;
+ int ret;
+
+ if (ts_data->fw_cfg_uploading || forever)
+ count = DEVICE_READY_COUNT_MAX;
do {
- if (!IT7260_i2cReadNoReadyCheck(BUF_QUERY, &query,
- sizeof(query)))
- query = CMD_STATUS_BUSY;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &query,
+ sizeof(query));
+ if (ret < 0 && ((query & CMD_STATUS_BITS)
+ == CMD_STATUS_NO_CONN))
+ continue;
- if (slowly)
- msleep(IT_I2C_WAIT);
- if (!forever)
- count--;
+ if ((query & CMD_STATUS_BITS) == CMD_STATUS_DONE)
+ break;
- } while ((query & CMD_STATUS_BUSY) && count);
+ query = CMD_STATUS_BUSY;
+ if (slowly)
+ msleep(IT_I2C_WAIT_10MS);
+ } while (--count);
- return !query;
+ return ((!(query & CMD_STATUS_BITS)) ? 0 : -ENODEV);
}
-static bool IT7260_i2cRead(uint8_t buf_index, uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_read(struct it7260_ts_data *ts_data, uint8_t buf_index,
+ uint8_t *buffer, uint16_t buf_len)
{
- IT7260_waitDeviceReady(false, false);
- return IT7260_i2cReadNoReadyCheck(buf_index, buffer, buf_len);
+ int ret;
+
+ ret = it7260_wait_device_ready(ts_data, false, false);
+ if (ret < 0)
+ return ret;
+
+ return it7260_i2c_read_no_ready_check(ts_data, buf_index,
+ buffer, buf_len);
}
-static bool IT7260_i2cWrite(uint8_t buf_index, const uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_write(struct it7260_ts_data *ts_data, uint8_t buf_index,
+ const uint8_t *buffer, uint16_t buf_len)
{
- IT7260_waitDeviceReady(false, false);
- return IT7260_i2cWriteNoReadyCheck(buf_index, buffer, buf_len);
+ int ret;
+
+ ret = it7260_wait_device_ready(ts_data, false, false);
+ if (ret < 0)
+ return ret;
+
+ return it7260_i2c_write_no_ready_check(ts_data, buf_index,
+ buffer, buf_len);
}
-static bool IT7260_firmware_reinitialize(u8 command)
+static int it7260_firmware_reinitialize(struct it7260_ts_data *ts_data,
+ u8 command)
{
uint8_t cmd[] = {command};
uint8_t rsp[2];
+ int ret;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd)))
- return false;
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, sizeof(cmd));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write fw reinit command %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cRead(BUF_RESPONSE, rsp, sizeof(rsp)))
- return false;
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, rsp, sizeof(rsp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !rsp[0] && !rsp[1];
+ if (rsp[0] == 0 && rsp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
-static bool IT7260_enter_exit_fw_ugrade_mode(bool enter)
+static int it7260_enter_exit_fw_ugrade_mode(struct it7260_ts_data *ts_data,
+ bool enter)
{
uint8_t cmd[] = {CMD_FIRMWARE_UPGRADE, 0, 'I', 'T', '7', '2',
'6', '0', 0x55, 0xAA};
uint8_t resp[2];
+ int ret;
cmd[1] = enter ? SUB_CMD_ENTER_FW_UPGRADE_MODE :
SUB_CMD_EXIT_FW_UPGRADE_MODE;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd)))
- return false;
- if (!IT7260_i2cRead(BUF_RESPONSE, resp, sizeof(resp)))
- return false;
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, sizeof(cmd));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_FIRMWARE_UPGRADE %d\n", ret);
+ return ret;
+ }
+
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, resp, sizeof(resp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !resp[0] && !resp[1];
+ if (resp[0] == 0 && resp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
-static bool IT7260_chipSetStartOffset(uint16_t offset)
+static int it7260_set_start_offset(struct it7260_ts_data *ts_data,
+ uint16_t offset)
{
uint8_t cmd[] = {CMD_SET_START_OFFSET, 0, ((uint8_t)(offset)),
((uint8_t)((offset) >> 8))};
uint8_t resp[2];
+ int ret;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, 4))
- return false;
-
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, 4);
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_SET_START_OFFSET %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cRead(BUF_RESPONSE, resp, sizeof(resp)))
- return false;
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, resp, sizeof(resp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !resp[0] && !resp[1];
+ if (resp[0] == 0 && resp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
/* write fw_length bytes from fw_data at chip offset wr_start_offset */
-static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
- const uint8_t *fw_data, uint16_t wr_start_offset)
+static int it7260_fw_flash_write_verify(struct it7260_ts_data *ts_data,
+ unsigned int fw_length, const uint8_t *fw_data,
+ uint16_t wr_start_offset)
{
uint32_t cur_data_off;
@@ -399,17 +478,18 @@ static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
retries++) {
/* set write offset and write the data */
- IT7260_chipSetStartOffset(
+ it7260_set_start_offset(ts_data,
wr_start_offset + cur_data_off);
- IT7260_i2cWrite(BUF_COMMAND, cmd_write,
+ it7260_i2c_write(ts_data, BUF_COMMAND, cmd_write,
cur_wr_size + 2);
/* set offset and read the data back */
- IT7260_chipSetStartOffset(
+ it7260_set_start_offset(ts_data,
wr_start_offset + cur_data_off);
- IT7260_i2cWrite(BUF_COMMAND, cmd_read,
+ it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read,
sizeof(cmd_read));
- IT7260_i2cRead(BUF_RESPONSE, buf_read, cur_wr_size);
+ it7260_i2c_read(ts_data, BUF_RESPONSE, buf_read,
+ cur_wr_size);
/* verify. If success break out of retry loop */
i = 0;
@@ -421,68 +501,96 @@ static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
}
/* if we've failed after all the retries, tell the caller */
if (retries == FW_WRITE_RETRY_COUNT) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"write of data offset %u failed on try %u at byte %u/%u\n",
cur_data_off, retries, i, cur_wr_size);
- return false;
+ return -EIO;
}
}
- return true;
+ return 0;
}
/*
* this code to get versions from the chip via i2c transactions, and save
* them in driver data structure.
*/
-static void IT7260_get_chip_versions(struct device *dev)
+static void it7260_get_chip_versions(struct it7260_ts_data *ts_data)
{
static const u8 cmd_read_fw_ver[] = {CMD_READ_VERSIONS,
SUB_CMD_READ_FIRMWARE_VERSION};
static const u8 cmd_read_cfg_ver[] = {CMD_READ_VERSIONS,
SUB_CMD_READ_CONFIG_VERSION};
u8 ver_fw[VERSION_LENGTH], ver_cfg[VERSION_LENGTH];
- bool ret = true;
+ int ret;
- ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_fw_ver,
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read_fw_ver,
sizeof(cmd_read_fw_ver));
- if (ret) {
- ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH);
- if (ret)
- memcpy(gl_ts->fw_ver, ver_fw + (5 * sizeof(u8)),
+ if (ret == IT_I2C_WRITE_RET) {
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE,
+ ver_fw, VERSION_LENGTH);
+ if (ret == IT_I2C_READ_RET)
+ memcpy(ts_data->fw_ver, ver_fw + (5 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
+ else
+ dev_err(&ts_data->client->dev,
+ "failed to read fw-ver from chip %d\n", ret);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "failed to write fw-read command %d\n", ret);
}
- if (!ret)
- dev_err(dev, "failed to read fw version from chip\n");
- ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver,
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read_cfg_ver,
sizeof(cmd_read_cfg_ver));
- if (ret) {
- ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH)
- && ret;
- if (ret)
- memcpy(gl_ts->cfg_ver, ver_cfg + (1 * sizeof(u8)),
+ if (ret == IT_I2C_WRITE_RET) {
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE,
+ ver_cfg, VERSION_LENGTH);
+ if (ret == IT_I2C_READ_RET)
+ memcpy(ts_data->cfg_ver, ver_cfg + (1 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
+ else
+ dev_err(&ts_data->client->dev,
+ "failed to read cfg-ver from chip %d\n", ret);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "failed to write cfg-read command %d\n", ret);
}
- if (!ret)
- dev_err(dev, "failed to read cfg version from chip\n");
- dev_info(dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2],
- gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ dev_info(&ts_data->client->dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1], ts_data->fw_ver[2],
+ ts_data->fw_ver[3], ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
-static int IT7260_cfg_upload(struct device *dev, bool force)
+static int it7260_cfg_upload(struct it7260_ts_data *ts_data, bool force)
{
const struct firmware *cfg = NULL;
int ret;
- bool success, cfg_upgrade = false;
+ bool cfg_upgrade = false;
+ struct device *dev = &ts_data->client->dev;
- ret = request_firmware(&cfg, gl_ts->cfg_name, dev);
+ ret = request_firmware(&cfg, ts_data->cfg_name, dev);
if (ret) {
dev_err(dev, "failed to get config data %s for it7260 %d\n",
- gl_ts->cfg_name, ret);
+ ts_data->cfg_name, ret);
return ret;
}
@@ -493,43 +601,59 @@ static int IT7260_cfg_upload(struct device *dev, bool force)
*/
if (force)
cfg_upgrade = true;
- else if (IT_CFG_CHECK(gl_ts->cfg_ver, cfg))
+ else if (IT_CFG_CHECK(ts_data->cfg_ver, cfg))
cfg_upgrade = true;
if (!cfg_upgrade) {
- dev_err(dev, "CFG upgrade no required ...\n");
+ dev_err(dev, "CFG upgrade not required ...\n");
+ dev_info(dev,
+ "Chip CFG : %X.%X.%X.%X Binary CFG : %X.%X.%X.%X\n",
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3],
+ cfg->data[cfg->size - 8], cfg->data[cfg->size - 7],
+ cfg->data[cfg->size - 6], cfg->data[cfg->size - 5]);
ret = -EFAULT;
goto out;
} else {
dev_info(dev, "Config upgrading...\n");
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
/* enter cfg upload mode */
- success = IT7260_enter_exit_fw_ugrade_mode(true);
- if (!success) {
- dev_err(dev, "Can't enter cfg upgrade mode\n");
- ret = -EIO;
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, true);
+ if (ret < 0) {
+ dev_err(dev, "Can't enter cfg upgrade mode %d\n", ret);
+ enable_irq(ts_data->client->irq);
goto out;
}
/* flash config data if requested */
- success = IT7260_fw_flash_write_verify(cfg->size, cfg->data,
- CHIP_FLASH_SIZE - cfg->size);
- if (!success) {
- dev_err(dev, "failed to upgrade touch cfg data\n");
- IT7260_enter_exit_fw_ugrade_mode(false);
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F);
+ ret = it7260_fw_flash_write_verify(ts_data, cfg->size,
+ cfg->data, CHIP_FLASH_SIZE - cfg->size);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to upgrade touch cfg data %d\n", ret);
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, false);
+ if (ret < 0)
+ dev_err(dev,
+ "Can't exit cfg upgrade mode%d\n", ret);
+
+ ret = it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F);
+ if (ret < 0)
+ dev_err(dev, "Can't reinit cfg %d\n", ret);
+
ret = -EIO;
+ enable_irq(ts_data->client->irq);
goto out;
} else {
- memcpy(gl_ts->cfg_ver, cfg->data +
+ memcpy(ts_data->cfg_ver, cfg->data +
(cfg->size - 8 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
dev_info(dev, "CFG upgrade is success. New cfg ver: %X.%X.%X.%X\n",
- gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
- enable_irq(gl_ts->client->irq);
+ enable_irq(ts_data->client->irq);
}
out:
@@ -538,16 +662,17 @@ out:
return ret;
}
-static int IT7260_fw_upload(struct device *dev, bool force)
+static int it7260_fw_upload(struct it7260_ts_data *ts_data, bool force)
{
const struct firmware *fw = NULL;
int ret;
- bool success, fw_upgrade = false;
+ bool fw_upgrade = false;
+ struct device *dev = &ts_data->client->dev;
- ret = request_firmware(&fw, gl_ts->fw_name, dev);
+ ret = request_firmware(&fw, ts_data->fw_name, dev);
if (ret) {
dev_err(dev, "failed to get firmware %s for it7260 %d\n",
- gl_ts->fw_name, ret);
+ ts_data->fw_name, ret);
return ret;
}
@@ -558,40 +683,55 @@ static int IT7260_fw_upload(struct device *dev, bool force)
*/
if (force)
fw_upgrade = true;
- else if (IT_FW_CHECK(gl_ts->fw_ver, fw))
+ else if (IT_FW_CHECK(ts_data->fw_ver, fw))
fw_upgrade = true;
if (!fw_upgrade) {
dev_err(dev, "FW upgrade not required ...\n");
+ dev_info(dev, "Chip FW : %X.%X.%X.%X Binary FW : %X.%X.%X.%X\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3],
+ fw->data[8], fw->data[9], fw->data[10], fw->data[11]);
ret = -EFAULT;
goto out;
} else {
dev_info(dev, "Firmware upgrading...\n");
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
/* enter fw upload mode */
- success = IT7260_enter_exit_fw_ugrade_mode(true);
- if (!success) {
- dev_err(dev, "Can't enter fw upgrade mode\n");
- ret = -EIO;
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, true);
+ if (ret < 0) {
+ dev_err(dev, "Can't enter fw upgrade mode %d\n", ret);
+ enable_irq(ts_data->client->irq);
goto out;
}
/* flash the firmware if requested */
- success = IT7260_fw_flash_write_verify(fw->size, fw->data, 0);
- if (!success) {
- dev_err(dev, "failed to upgrade touch firmware\n");
- IT7260_enter_exit_fw_ugrade_mode(false);
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F);
+ ret = it7260_fw_flash_write_verify(ts_data, fw->size,
+ fw->data, 0);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to upgrade touch firmware %d\n", ret);
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, false);
+ if (ret < 0)
+ dev_err(dev,
+ "Can't exit fw upgrade mode %d\n", ret);
+
+ ret = it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F);
+ if (ret < 0)
+ dev_err(dev, "Can't reinit firmware %d\n", ret);
+
ret = -EIO;
+ enable_irq(ts_data->client->irq);
goto out;
} else {
- memcpy(gl_ts->fw_ver, fw->data + (8 * sizeof(u8)),
+ memcpy(ts_data->fw_ver, fw->data + (8 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
dev_info(dev, "FW upgrade is success. New fw ver: %X.%X.%X.%X\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1],
- gl_ts->fw_ver[2], gl_ts->fw_ver[3]);
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3]);
}
- enable_irq(gl_ts->client->irq);
+ enable_irq(ts_data->client->irq);
}
out:
@@ -600,16 +740,18 @@ out:
return ret;
}
-static int IT7260_ts_chipLowPowerMode(const u8 sleep_type)
+static int it7260_ts_chip_low_power_mode(struct it7260_ts_data *ts_data,
+ const u8 sleep_type)
{
const uint8_t cmd_sleep[] = {CMD_PWR_CTL, 0x00, sleep_type};
uint8_t dummy;
if (sleep_type)
- IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_sleep,
+ it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_sleep,
sizeof(cmd_sleep));
else
- IT7260_i2cReadNoReadyCheck(BUF_QUERY, &dummy, sizeof(dummy));
+ it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &dummy,
+ sizeof(dummy));
msleep(WAIT_CHANGE_MODE);
return 0;
@@ -618,32 +760,33 @@ static int IT7260_ts_chipLowPowerMode(const u8 sleep_type)
static ssize_t sysfs_fw_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash fw!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_fw_upload(dev, false);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_fw_upload(ts_data, false);
if (ret) {
dev_err(dev, "Failed to flash fw: %d", ret);
- gl_ts->fw_upgrade_result = false;
+ ts_data->fw_upgrade_result = false;
} else {
- gl_ts->fw_upgrade_result = true;
+ ts_data->fw_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -651,32 +794,33 @@ static ssize_t sysfs_fw_upgrade_store(struct device *dev,
static ssize_t sysfs_cfg_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash cfg!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_cfg_upload(dev, false);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_cfg_upload(ts_data, false);
if (ret) {
dev_err(dev, "Failed to flash cfg: %d", ret);
- gl_ts->cfg_upgrade_result = false;
+ ts_data->cfg_upgrade_result = false;
} else {
- gl_ts->cfg_upgrade_result = true;
+ ts_data->cfg_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -684,46 +828,51 @@ static ssize_t sysfs_cfg_upgrade_store(struct device *dev,
static ssize_t sysfs_fw_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->fw_upgrade_result);
+ ts_data->fw_upgrade_result);
}
static ssize_t sysfs_cfg_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->cfg_upgrade_result);
+ ts_data->cfg_upgrade_result);
}
static ssize_t sysfs_force_fw_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash fw!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_fw_upload(dev, true);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_fw_upload(ts_data, true);
if (ret) {
dev_err(dev, "Failed to force flash fw: %d", ret);
- gl_ts->fw_upgrade_result = false;
+ ts_data->fw_upgrade_result = false;
} else {
- gl_ts->fw_upgrade_result = true;
+ ts_data->fw_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -731,32 +880,33 @@ static ssize_t sysfs_force_fw_upgrade_store(struct device *dev,
static ssize_t sysfs_force_cfg_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash cfg!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_cfg_upload(dev, true);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_cfg_upload(ts_data, true);
if (ret) {
dev_err(dev, "Failed to force flash cfg: %d", ret);
- gl_ts->cfg_upgrade_result = false;
+ ts_data->cfg_upgrade_result = false;
} else {
- gl_ts->cfg_upgrade_result = true;
+ ts_data->cfg_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -764,51 +914,65 @@ static ssize_t sysfs_force_cfg_upgrade_store(struct device *dev,
static ssize_t sysfs_force_fw_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->fw_upgrade_result);
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MAX_BUFFER_SIZE, "%d", ts_data->fw_upgrade_result);
}
static ssize_t sysfs_force_cfg_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->cfg_upgrade_result);
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MAX_BUFFER_SIZE, "%d",
+ ts_data->cfg_upgrade_result);
}
static ssize_t sysfs_calibration_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->calibration_success);
+ ts_data->calibration_success);
}
-static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on)
+static int it7260_ts_send_calibration_cmd(struct it7260_ts_data *ts_data,
+ bool auto_tune_on)
{
uint8_t cmd_calibrate[] = {CMD_CALIBRATE, 0,
auto_tune_on ? 1 : 0, 0, 0};
- return IT7260_i2cWrite(BUF_COMMAND, cmd_calibrate,
+
+ return it7260_i2c_write(ts_data, BUF_COMMAND, cmd_calibrate,
sizeof(cmd_calibrate));
}
static ssize_t sysfs_calibration_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
uint8_t resp;
+ int ret;
- if (!IT7260_chipSendCalibrationCmd(false)) {
+ ret = it7260_ts_send_calibration_cmd(ts_data, false);
+ if (ret < 0) {
dev_err(dev, "failed to send calibration command\n");
} else {
- gl_ts->calibration_success =
- IT7260_i2cRead(BUF_RESPONSE, &resp, sizeof(resp));
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, &resp,
+ sizeof(resp));
+ if (ret == IT_I2C_READ_RET)
+ ts_data->calibration_success = true;
/*
* previous logic that was here never called
- * IT7260_firmware_reinitialize() due to checking a
+ * it7260_firmware_reinitialize() due to checking a
* guaranteed-not-null value against null. We now
* call it. Hopefully this is OK
*/
if (!resp)
- dev_dbg(dev, "IT7260_firmware_reinitialize-> %s\n",
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F)
- ? "success" : "fail");
+ dev_dbg(dev, "it7260_firmware_reinitialize-> %s\n",
+ it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F) ? "success" : "fail");
}
return count;
@@ -817,21 +981,22 @@ static ssize_t sysfs_calibration_store(struct device *dev,
static ssize_t sysfs_point_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- uint8_t point_data[sizeof(struct PointData)];
- bool readSuccess;
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ uint8_t pt_data[sizeof(struct point_data)];
+ int readSuccess;
ssize_t ret;
- readSuccess = IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, point_data,
- sizeof(point_data));
+ readSuccess = it7260_i2c_read_no_ready_check(ts_data, BUF_POINT_INFO,
+ pt_data, sizeof(pt_data));
- if (readSuccess) {
+ if (readSuccess == IT_I2C_READ_RET) {
ret = scnprintf(buf, MAX_BUFFER_SIZE,
"point_show read ret[%d]--point[%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]\n",
- readSuccess, point_data[0], point_data[1],
- point_data[2], point_data[3], point_data[4],
- point_data[5], point_data[6], point_data[7],
- point_data[8], point_data[9], point_data[10],
- point_data[11], point_data[12], point_data[13]);
+ readSuccess, pt_data[0], pt_data[1],
+ pt_data[2], pt_data[3], pt_data[4],
+ pt_data[5], pt_data[6], pt_data[7],
+ pt_data[8], pt_data[9], pt_data[10],
+ pt_data[11], pt_data[12], pt_data[13]);
} else {
ret = scnprintf(buf, MAX_BUFFER_SIZE,
"failed to read point data\n");
@@ -844,51 +1009,57 @@ static ssize_t sysfs_point_show(struct device *dev,
static ssize_t sysfs_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE,
"fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2],
- gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3],
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
static ssize_t sysfs_sleep_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
/*
* The usefulness of this was questionable at best - we were at least
* leaking a byte of kernel data (by claiming to return a byte but not
* writing to buf. To fix this now we actually return the sleep status
*/
- *buf = gl_ts->suspended ? '1' : '0';
+ *buf = ts_data->suspended ? '1' : '0';
+
return 1;
}
static ssize_t sysfs_sleep_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int go_to_sleep, ret;
ret = kstrtoint(buf, 10, &go_to_sleep);
- /* (gl_ts->suspended == true && goToSleepVal > 0) means
+ /* (ts_data->suspended == true && goToSleepVal > 0) means
* device is already suspended and you want it to be in sleep,
- * (gl_ts->suspended == false && goToSleepVal == 0) means
+ * (ts_data->suspended == false && goToSleepVal == 0) means
* device is already active and you also want it to be active.
*/
- if ((gl_ts->suspended && go_to_sleep > 0) ||
- (!gl_ts->suspended && go_to_sleep == 0))
+ if ((ts_data->suspended && go_to_sleep > 0) ||
+ (!ts_data->suspended && go_to_sleep == 0))
dev_err(dev, "duplicate request to %s chip\n",
go_to_sleep ? "sleep" : "wake");
else if (go_to_sleep) {
- disable_irq(gl_ts->client->irq);
- IT7260_ts_chipLowPowerMode(PWR_CTL_SLEEP_MODE);
+ disable_irq(ts_data->client->irq);
+ it7260_ts_chip_low_power_mode(ts_data, PWR_CTL_SLEEP_MODE);
dev_dbg(dev, "touch is going to sleep...\n");
} else {
- IT7260_ts_chipLowPowerMode(PWR_CTL_ACTIVE_MODE);
- enable_irq(gl_ts->client->irq);
+ it7260_ts_chip_low_power_mode(ts_data, PWR_CTL_ACTIVE_MODE);
+ enable_irq(ts_data->client->irq);
dev_dbg(dev, "touch is going to wake!\n");
}
- gl_ts->suspended = go_to_sleep;
+ ts_data->suspended = go_to_sleep;
return count;
}
@@ -896,6 +1067,7 @@ static ssize_t sysfs_sleep_store(struct device *dev,
static ssize_t sysfs_cfg_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
char *strptr;
if (count >= MAX_BUFFER_SIZE) {
@@ -909,7 +1081,7 @@ static ssize_t sysfs_cfg_name_store(struct device *dev,
return -EINVAL;
}
- strlcpy(gl_ts->cfg_name, buf, count);
+ strlcpy(ts_data->cfg_name, buf, count);
return count;
}
@@ -917,9 +1089,11 @@ static ssize_t sysfs_cfg_name_store(struct device *dev,
static ssize_t sysfs_cfg_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (strnlen(gl_ts->cfg_name, MAX_BUFFER_SIZE) > 0)
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ if (strnlen(ts_data->cfg_name, MAX_BUFFER_SIZE) > 0)
return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n",
- gl_ts->cfg_name);
+ ts_data->cfg_name);
else
return scnprintf(buf, MAX_BUFFER_SIZE,
"No config file name given\n");
@@ -928,6 +1102,7 @@ static ssize_t sysfs_cfg_name_show(struct device *dev,
static ssize_t sysfs_fw_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
char *strptr;
if (count >= MAX_BUFFER_SIZE) {
@@ -941,16 +1116,18 @@ static ssize_t sysfs_fw_name_store(struct device *dev,
return -EINVAL;
}
- strlcpy(gl_ts->fw_name, buf, count);
+ strlcpy(ts_data->fw_name, buf, count);
return count;
}
static ssize_t sysfs_fw_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (strnlen(gl_ts->fw_name, MAX_BUFFER_SIZE) > 0)
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ if (strnlen(ts_data->fw_name, MAX_BUFFER_SIZE) > 0)
return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n",
- gl_ts->fw_name);
+ ts_data->fw_name);
else
return scnprintf(buf, MAX_BUFFER_SIZE,
"No firmware file name given\n");
@@ -997,59 +1174,47 @@ static const struct attribute_group it7260_attr_group = {
.attrs = it7260_attributes,
};
-static void IT7260_chipExternalCalibration(bool autoTuneEnabled)
-{
- uint8_t resp[2];
-
- dev_dbg(&gl_ts->client->dev, "sent calibration command -> %d\n",
- IT7260_chipSendCalibrationCmd(autoTuneEnabled));
- IT7260_waitDeviceReady(true, true);
- IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, resp, sizeof(resp));
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_C);
-}
-
-void IT7260_sendCalibrationCmd(void)
-{
- IT7260_chipExternalCalibration(false);
-}
-EXPORT_SYMBOL(IT7260_sendCalibrationCmd);
-
-static void IT7260_ts_release_all(void)
+static void it7260_ts_release_all(struct it7260_ts_data *ts_data)
{
int finger;
- for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) {
- input_mt_slot(gl_ts->input_dev, finger);
- input_mt_report_slot_state(gl_ts->input_dev,
+ for (finger = 0; finger < ts_data->pdata->num_of_fingers; finger++) {
+ input_mt_slot(ts_data->input_dev, finger);
+ input_mt_report_slot_state(ts_data->input_dev,
MT_TOOL_FINGER, 0);
}
- input_report_key(gl_ts->input_dev, BTN_TOUCH, 0);
- input_sync(gl_ts->input_dev);
+ input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
+ input_sync(ts_data->input_dev);
}
-static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
+static irqreturn_t it7260_ts_threaded_handler(int irq, void *devid)
{
- struct PointData point_data;
- struct input_dev *input_dev = gl_ts->input_dev;
+ struct point_data pt_data;
+ struct it7260_ts_data *ts_data = devid;
+ struct input_dev *input_dev = ts_data->input_dev;
u8 dev_status, finger, touch_count = 0, finger_status;
u8 pressure = FD_PRESSURE_NONE;
u16 x, y;
bool palm_detected;
+ int ret;
/* verify there is point data to read & it is readable and valid */
- IT7260_i2cReadNoReadyCheck(BUF_QUERY, &dev_status, sizeof(dev_status));
- if (!((dev_status & PT_INFO_BITS) & PT_INFO_YES))
- return IRQ_HANDLED;
- if (!IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, (void *)&point_data,
- sizeof(point_data))) {
- dev_err(&gl_ts->client->dev,
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &dev_status,
+ sizeof(dev_status));
+ if (ret == IT_I2C_READ_RET)
+ if (!((dev_status & PT_INFO_BITS) & PT_INFO_YES))
+ return IRQ_HANDLED;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_POINT_INFO,
+ (void *)&pt_data, sizeof(pt_data));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
"failed to read point data buffer\n");
return IRQ_HANDLED;
}
/* Check if controller moves from idle to active state */
- if ((point_data.flags & PD_FLAGS_DATA_TYPE_BITS) !=
+ if ((pt_data.flags & PD_FLAGS_DATA_TYPE_BITS) !=
PD_FLAGS_DATA_TYPE_TOUCH) {
/*
* This code adds the touch-to-wake functionality to the ITE
@@ -1061,40 +1226,40 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
* schedule a work that tells the pm core to relax once the CPU
* cores are up.
*/
- if (gl_ts->device_needs_wakeup) {
- pm_stay_awake(&gl_ts->client->dev);
+ if (ts_data->device_needs_wakeup) {
+ pm_stay_awake(&ts_data->client->dev);
input_report_key(input_dev, KEY_WAKEUP, 1);
input_sync(input_dev);
input_report_key(input_dev, KEY_WAKEUP, 0);
input_sync(input_dev);
- schedule_work(&gl_ts->work_pm_relax);
+ schedule_work(&ts_data->work_pm_relax);
return IRQ_HANDLED;
}
}
- palm_detected = point_data.palm & PD_PALM_FLAG_BIT;
- if (palm_detected && gl_ts->pdata->palm_detect_en) {
+ palm_detected = pt_data.palm & PD_PALM_FLAG_BIT;
+ if (palm_detected && ts_data->pdata->palm_detect_en) {
input_report_key(input_dev,
- gl_ts->pdata->palm_detect_keycode, 1);
+ ts_data->pdata->palm_detect_keycode, 1);
input_sync(input_dev);
input_report_key(input_dev,
- gl_ts->pdata->palm_detect_keycode, 0);
+ ts_data->pdata->palm_detect_keycode, 0);
input_sync(input_dev);
}
- for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) {
- finger_status = point_data.flags & (0x01 << finger);
+ for (finger = 0; finger < ts_data->pdata->num_of_fingers; finger++) {
+ finger_status = pt_data.flags & (0x01 << finger);
input_mt_slot(input_dev, finger);
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
finger_status != 0);
- x = point_data.fd[finger].xLo +
- (((u16)(point_data.fd[finger].hi & 0x0F)) << 8);
- y = point_data.fd[finger].yLo +
- (((u16)(point_data.fd[finger].hi & 0xF0)) << 4);
+ x = pt_data.fd[finger].xLo +
+ (((u16)(pt_data.fd[finger].hi & 0x0F)) << 8);
+ y = pt_data.fd[finger].yLo +
+ (((u16)(pt_data.fd[finger].hi & 0xF0)) << 4);
- pressure = point_data.fd[finger].pressure & FD_PRESSURE_BITS;
+ pressure = pt_data.fd[finger].pressure & FD_PRESSURE_BITS;
if (finger_status) {
if (pressure >= FD_PRESSURE_LIGHT) {
@@ -1114,35 +1279,66 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
return IRQ_HANDLED;
}
-static void IT7260_ts_work_func(struct work_struct *work)
+static void it7260_ts_work_func(struct work_struct *work)
{
- pm_relax(&gl_ts->client->dev);
+ struct it7260_ts_data *ts_data = container_of(work,
+ struct it7260_ts_data, work_pm_relax);
+
+ pm_relax(&ts_data->client->dev);
}
-static int IT7260_chipIdentify(void)
+static int it7260_ts_chip_identify(struct it7260_ts_data *ts_data)
{
static const uint8_t cmd_ident[] = {CMD_IDENT_CHIP};
static const uint8_t expected_id[] = {0x0A, 'I', 'T', 'E', '7',
'2', '6', '0'};
uint8_t chip_id[10] = {0,};
+ int ret;
- IT7260_waitDeviceReady(false, false);
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ * FALSE means to retry 20 times at max to read the chip status.
+ * TRUE means to add delay in each retry.
+ */
+ ret = it7260_wait_device_ready(ts_data, false, true);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_ident,
- sizeof(cmd_ident))) {
- dev_err(&gl_ts->client->dev, "failed to write CMD_IDENT_CHIP\n");
- return -ENODEV;
+ ret = it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_ident,
+ sizeof(cmd_ident));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_IDENT_CHIP %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ * TRUE means to retry 500 times at max to read the chip status.
+ * FALSE means to avoid unnecessary delays in each retry.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+ return ret;
}
- IT7260_waitDeviceReady(false, false);
- if (!IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, chip_id,
- sizeof(chip_id))) {
- dev_err(&gl_ts->client->dev, "failed to read chip-id\n");
- return -ENODEV;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE, chip_id,
+ sizeof(chip_id));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip-id %d\n", ret);
+ return ret;
}
- dev_info(&gl_ts->client->dev,
- "IT7260_chipIdentify read id: %02X %c%c%c%c%c%c%c %c%c\n",
+ dev_info(&ts_data->client->dev,
+ "it7260_ts_chip_identify read id: %02X %c%c%c%c%c%c%c %c%c\n",
chip_id[0], chip_id[1], chip_id[2], chip_id[3], chip_id[4],
chip_id[5], chip_id[6], chip_id[7], chip_id[8], chip_id[9]);
@@ -1150,11 +1346,11 @@ static int IT7260_chipIdentify(void)
return -EINVAL;
if (chip_id[8] == '5' && chip_id[9] == '6')
- dev_info(&gl_ts->client->dev, "rev BX3 found\n");
+ dev_info(&ts_data->client->dev, "rev BX3 found\n");
else if (chip_id[8] == '6' && chip_id[9] == '6')
- dev_info(&gl_ts->client->dev, "rev BX4 found\n");
+ dev_info(&ts_data->client->dev, "rev BX4 found\n");
else
- dev_info(&gl_ts->client->dev, "unknown revision (0x%02X 0x%02X) found\n",
+ dev_info(&ts_data->client->dev, "unknown revision (0x%02X 0x%02X) found\n",
chip_id[8], chip_id[9]);
return 0;
@@ -1166,44 +1362,44 @@ static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
regulator_set_optimum_mode(reg, load_uA) : 0;
}
-static int IT7260_regulator_configure(bool on)
+static int it7260_regulator_configure(struct it7260_ts_data *ts_data, bool on)
{
int retval;
if (on == false)
goto hw_shutdown;
- gl_ts->vdd = devm_regulator_get(&gl_ts->client->dev, "vdd");
- if (IS_ERR(gl_ts->vdd)) {
- dev_err(&gl_ts->client->dev,
+ ts_data->vdd = devm_regulator_get(&ts_data->client->dev, "vdd");
+ if (IS_ERR(ts_data->vdd)) {
+ dev_err(&ts_data->client->dev,
"%s: Failed to get vdd regulator\n", __func__);
- return PTR_ERR(gl_ts->vdd);
+ return PTR_ERR(ts_data->vdd);
}
- if (regulator_count_voltages(gl_ts->vdd) > 0) {
- retval = regulator_set_voltage(gl_ts->vdd,
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
+ retval = regulator_set_voltage(ts_data->vdd,
IT_VTG_MIN_UV, IT_VTG_MAX_UV);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"regulator set_vtg failed retval =%d\n",
retval);
goto err_set_vtg_vdd;
}
}
- gl_ts->avdd = devm_regulator_get(&gl_ts->client->dev, "avdd");
- if (IS_ERR(gl_ts->avdd)) {
- dev_err(&gl_ts->client->dev,
+ ts_data->avdd = devm_regulator_get(&ts_data->client->dev, "avdd");
+ if (IS_ERR(ts_data->avdd)) {
+ dev_err(&ts_data->client->dev,
"%s: Failed to get i2c regulator\n", __func__);
- retval = PTR_ERR(gl_ts->avdd);
+ retval = PTR_ERR(ts_data->avdd);
goto err_get_vtg_i2c;
}
- if (regulator_count_voltages(gl_ts->avdd) > 0) {
- retval = regulator_set_voltage(gl_ts->avdd,
+ if (regulator_count_voltages(ts_data->avdd) > 0) {
+ retval = regulator_set_voltage(ts_data->avdd,
IT_I2C_VTG_MIN_UV, IT_I2C_VTG_MAX_UV);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"reg set i2c vtg failed retval =%d\n",
retval);
goto err_set_vtg_i2c;
@@ -1214,55 +1410,55 @@ static int IT7260_regulator_configure(bool on)
err_set_vtg_i2c:
err_get_vtg_i2c:
- if (regulator_count_voltages(gl_ts->vdd) > 0)
- regulator_set_voltage(gl_ts->vdd, 0, IT_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, IT_VTG_MAX_UV);
err_set_vtg_vdd:
return retval;
hw_shutdown:
- if (regulator_count_voltages(gl_ts->vdd) > 0)
- regulator_set_voltage(gl_ts->vdd, 0, IT_VTG_MAX_UV);
- if (regulator_count_voltages(gl_ts->avdd) > 0)
- regulator_set_voltage(gl_ts->avdd, 0, IT_I2C_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, IT_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->avdd) > 0)
+ regulator_set_voltage(ts_data->avdd, 0, IT_I2C_VTG_MAX_UV);
return 0;
};
-static int IT7260_power_on(bool on)
+static int it7260_power_on(struct it7260_ts_data *ts_data, bool on)
{
int retval;
if (on == false)
goto power_off;
- retval = reg_set_optimum_mode_check(gl_ts->vdd,
+ retval = reg_set_optimum_mode_check(ts_data->vdd,
IT_ACTIVE_LOAD_UA);
if (retval < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vdd set_opt failed rc=%d\n",
retval);
return retval;
}
- retval = regulator_enable(gl_ts->vdd);
+ retval = regulator_enable(ts_data->vdd);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vdd enable failed rc=%d\n",
retval);
goto error_reg_en_vdd;
}
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
+ retval = reg_set_optimum_mode_check(ts_data->avdd,
IT_I2C_ACTIVE_LOAD_UA);
if (retval < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator avdd set_opt failed rc=%d\n",
retval);
goto error_reg_opt_i2c;
}
- retval = regulator_enable(gl_ts->avdd);
+ retval = regulator_enable(ts_data->avdd);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator avdd enable failed rc=%d\n",
retval);
goto error_reg_en_avdd;
@@ -1271,118 +1467,119 @@ static int IT7260_power_on(bool on)
return 0;
error_reg_en_avdd:
- reg_set_optimum_mode_check(gl_ts->avdd, 0);
+ reg_set_optimum_mode_check(ts_data->avdd, 0);
error_reg_opt_i2c:
- regulator_disable(gl_ts->vdd);
+ regulator_disable(ts_data->vdd);
error_reg_en_vdd:
- reg_set_optimum_mode_check(gl_ts->vdd, 0);
+ reg_set_optimum_mode_check(ts_data->vdd, 0);
return retval;
power_off:
- reg_set_optimum_mode_check(gl_ts->vdd, 0);
- regulator_disable(gl_ts->vdd);
- reg_set_optimum_mode_check(gl_ts->avdd, 0);
- regulator_disable(gl_ts->avdd);
+ reg_set_optimum_mode_check(ts_data->vdd, 0);
+ regulator_disable(ts_data->vdd);
+ reg_set_optimum_mode_check(ts_data->avdd, 0);
+ regulator_disable(ts_data->avdd);
return 0;
}
-static int IT7260_gpio_configure(bool on)
+static int it7260_gpio_configure(struct it7260_ts_data *ts_data, bool on)
{
int retval = 0;
if (on) {
- if (gpio_is_valid(gl_ts->pdata->irq_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->irq_gpio)) {
/* configure touchscreen irq gpio */
- retval = gpio_request(gl_ts->pdata->irq_gpio,
+ retval = gpio_request(ts_data->pdata->irq_gpio,
"ite_irq_gpio");
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to request irq gpio [%d]\n",
retval);
goto err_irq_gpio_req;
}
- retval = gpio_direction_input(gl_ts->pdata->irq_gpio);
+ retval = gpio_direction_input(ts_data->pdata->irq_gpio);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for irq gpio [%d]\n",
retval);
goto err_irq_gpio_dir;
}
} else {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"irq gpio not provided\n");
goto err_irq_gpio_req;
}
- if (gpio_is_valid(gl_ts->pdata->reset_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
/* configure touchscreen reset out gpio */
- retval = gpio_request(gl_ts->pdata->reset_gpio,
+ retval = gpio_request(ts_data->pdata->reset_gpio,
"ite_reset_gpio");
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to request reset gpio [%d]\n",
retval);
goto err_reset_gpio_req;
}
retval = gpio_direction_output(
- gl_ts->pdata->reset_gpio, 1);
+ ts_data->pdata->reset_gpio, 1);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for reset gpio [%d]\n",
retval);
goto err_reset_gpio_dir;
}
- if (gl_ts->pdata->low_reset)
- gpio_set_value(gl_ts->pdata->reset_gpio, 0);
+ if (ts_data->pdata->low_reset)
+ gpio_set_value(ts_data->pdata->reset_gpio, 0);
else
- gpio_set_value(gl_ts->pdata->reset_gpio, 1);
+ gpio_set_value(ts_data->pdata->reset_gpio, 1);
- msleep(gl_ts->pdata->reset_delay);
+ msleep(ts_data->pdata->reset_delay);
} else {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"reset gpio not provided\n");
goto err_reset_gpio_req;
}
} else {
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
- if (gpio_is_valid(gl_ts->pdata->reset_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
/*
* This is intended to save leakage current
* only. Even if the call(gpio_direction_input)
* fails, only leakage current will be more but
* functionality will not be affected.
*/
- retval = gpio_direction_input(gl_ts->pdata->reset_gpio);
+ retval = gpio_direction_input(
+ ts_data->pdata->reset_gpio);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for gpio reset [%d]\n",
retval);
}
- gpio_free(gl_ts->pdata->reset_gpio);
+ gpio_free(ts_data->pdata->reset_gpio);
}
}
return 0;
err_reset_gpio_dir:
- if (gpio_is_valid(gl_ts->pdata->reset_gpio))
- gpio_free(gl_ts->pdata->reset_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->reset_gpio);
err_reset_gpio_req:
err_irq_gpio_dir:
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
err_irq_gpio_req:
return retval;
}
#if CONFIG_OF
-static int IT7260_get_dt_coords(struct device *dev, char *name,
- struct IT7260_ts_platform_data *pdata)
+static int it7260_get_dt_coords(struct device *dev, char *name,
+ struct it7260_ts_platform_data *pdata)
{
u32 coords[IT7260_COORDS_ARR_SIZE];
struct property *prop;
@@ -1435,9 +1632,10 @@ static int IT7260_get_dt_coords(struct device *dev, char *name,
return 0;
}
-static int IT7260_parse_dt(struct device *dev,
- struct IT7260_ts_platform_data *pdata)
+static int it7260_parse_dt(struct device *dev,
+ struct it7260_ts_platform_data *pdata)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
struct device_node *np = dev->of_node;
u32 temp_val;
int rc;
@@ -1481,9 +1679,9 @@ static int IT7260_parse_dt(struct device *dev,
return rc;
}
- snprintf(gl_ts->fw_name, MAX_BUFFER_SIZE, "%s",
+ snprintf(ts_data->fw_name, MAX_BUFFER_SIZE, "%s",
(pdata->fw_name != NULL) ? pdata->fw_name : FW_NAME);
- snprintf(gl_ts->cfg_name, MAX_BUFFER_SIZE, "%s",
+ snprintf(ts_data->cfg_name, MAX_BUFFER_SIZE, "%s",
(pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME);
rc = of_property_read_u32(np, "ite,reset-delay", &temp_val);
@@ -1504,25 +1702,25 @@ static int IT7260_parse_dt(struct device *dev,
pdata->low_reset = of_property_read_bool(np, "ite,low-reset");
- rc = IT7260_get_dt_coords(dev, "ite,display-coords", pdata);
+ rc = it7260_get_dt_coords(dev, "ite,display-coords", pdata);
if (rc && (rc != -EINVAL))
return rc;
- rc = IT7260_get_dt_coords(dev, "ite,panel-coords", pdata);
+ rc = it7260_get_dt_coords(dev, "ite,panel-coords", pdata);
if (rc && (rc != -EINVAL))
return rc;
return 0;
}
#else
-static inline int IT7260_ts_parse_dt(struct device *dev,
- struct IT7260_ts_platform_data *pdata)
+static inline int it7260_ts_parse_dt(struct device *dev,
+ struct it7260_ts_platform_data *pdata)
{
return 0;
}
#endif
-static int IT7260_ts_pinctrl_init(struct IT7260_ts_data *ts_data)
+static int it7260_ts_pinctrl_init(struct it7260_ts_data *ts_data)
{
int retval;
@@ -1576,11 +1774,12 @@ err_pinctrl_get:
return retval;
}
-static int IT7260_ts_probe(struct i2c_client *client,
+static int it7260_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
static const uint8_t cmd_start[] = {CMD_UNKNOWN_7};
- struct IT7260_ts_platform_data *pdata;
+ struct it7260_ts_data *ts_data;
+ struct it7260_ts_platform_data *pdata;
uint8_t rsp[2];
int ret = -1, err;
struct dentry *temp;
@@ -1590,40 +1789,39 @@ static int IT7260_ts_probe(struct i2c_client *client,
return -ENODEV;
}
- gl_ts = devm_kzalloc(&client->dev, sizeof(*gl_ts), GFP_KERNEL);
- if (!gl_ts)
+ ts_data = devm_kzalloc(&client->dev, sizeof(*ts_data), GFP_KERNEL);
+ if (!ts_data)
return -ENOMEM;
- gl_ts->client = client;
- i2c_set_clientdata(client, gl_ts);
-
- if (client->dev.platform_data == NULL)
- return -ENODEV;
+ ts_data->client = client;
+ i2c_set_clientdata(client, ts_data);
if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- ret = IT7260_parse_dt(&client->dev, pdata);
+ ret = it7260_parse_dt(&client->dev, pdata);
if (ret)
return ret;
} else {
pdata = client->dev.platform_data;
}
- if (!pdata)
+ if (!pdata) {
+ dev_err(&client->dev, "No platform data found\n");
return -ENOMEM;
+ }
- gl_ts->pdata = pdata;
+ ts_data->pdata = pdata;
- ret = IT7260_regulator_configure(true);
+ ret = it7260_regulator_configure(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to configure regulators\n");
goto err_reg_configure;
}
- ret = IT7260_power_on(true);
+ ret = it7260_power_on(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to power on\n");
goto err_power_device;
@@ -1635,81 +1833,82 @@ static int IT7260_ts_probe(struct i2c_client *client,
*/
msleep(DELAY_VTG_REG_EN);
- ret = IT7260_ts_pinctrl_init(gl_ts);
- if (!ret && gl_ts->ts_pinctrl) {
+ ret = it7260_ts_pinctrl_init(ts_data);
+ if (!ret && ts_data->ts_pinctrl) {
/*
* Pinctrl handle is optional. If pinctrl handle is found
* let pins to be configured in active state. If not
* found continue further without error.
*/
- ret = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_active);
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
if (ret < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select pin to active state %d",
ret);
}
} else {
- ret = IT7260_gpio_configure(true);
+ ret = it7260_gpio_configure(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to configure gpios\n");
goto err_gpio_config;
}
}
- ret = IT7260_chipIdentify();
+ ret = it7260_ts_chip_identify(ts_data);
if (ret) {
dev_err(&client->dev, "Failed to identify chip %d!!!", ret);
goto err_identification_fail;
}
- IT7260_get_chip_versions(&client->dev);
+ it7260_get_chip_versions(ts_data);
- gl_ts->input_dev = input_allocate_device();
- if (!gl_ts->input_dev) {
+ ts_data->input_dev = input_allocate_device();
+ if (!ts_data->input_dev) {
dev_err(&client->dev, "failed to allocate input device\n");
ret = -ENOMEM;
goto err_input_alloc;
}
/* Initialize mutex for fw and cfg upgrade */
- mutex_init(&gl_ts->fw_cfg_mutex);
-
- gl_ts->input_dev->name = DEVICE_NAME;
- gl_ts->input_dev->phys = "I2C";
- gl_ts->input_dev->id.bustype = BUS_I2C;
- gl_ts->input_dev->id.vendor = 0x0001;
- gl_ts->input_dev->id.product = 0x7260;
- set_bit(EV_SYN, gl_ts->input_dev->evbit);
- set_bit(EV_KEY, gl_ts->input_dev->evbit);
- set_bit(EV_ABS, gl_ts->input_dev->evbit);
- set_bit(INPUT_PROP_DIRECT, gl_ts->input_dev->propbit);
- set_bit(BTN_TOUCH, gl_ts->input_dev->keybit);
- input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_X,
- gl_ts->pdata->disp_minx, gl_ts->pdata->disp_maxx, 0, 0);
- input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_Y,
- gl_ts->pdata->disp_miny, gl_ts->pdata->disp_maxy, 0, 0);
- input_mt_init_slots(gl_ts->input_dev, gl_ts->pdata->num_of_fingers, 0);
-
- input_set_drvdata(gl_ts->input_dev, gl_ts);
+ mutex_init(&ts_data->fw_cfg_mutex);
+
+ ts_data->input_dev->name = DEVICE_NAME;
+ ts_data->input_dev->phys = "I2C";
+ ts_data->input_dev->id.bustype = BUS_I2C;
+ ts_data->input_dev->id.vendor = 0x0001;
+ ts_data->input_dev->id.product = 0x7260;
+ set_bit(EV_SYN, ts_data->input_dev->evbit);
+ set_bit(EV_KEY, ts_data->input_dev->evbit);
+ set_bit(EV_ABS, ts_data->input_dev->evbit);
+ set_bit(INPUT_PROP_DIRECT, ts_data->input_dev->propbit);
+ set_bit(BTN_TOUCH, ts_data->input_dev->keybit);
+ input_set_abs_params(ts_data->input_dev, ABS_MT_POSITION_X,
+ ts_data->pdata->disp_minx, ts_data->pdata->disp_maxx, 0, 0);
+ input_set_abs_params(ts_data->input_dev, ABS_MT_POSITION_Y,
+ ts_data->pdata->disp_miny, ts_data->pdata->disp_maxy, 0, 0);
+ input_mt_init_slots(ts_data->input_dev,
+ ts_data->pdata->num_of_fingers, 0);
+
+ input_set_drvdata(ts_data->input_dev, ts_data);
if (pdata->wakeup) {
- set_bit(KEY_WAKEUP, gl_ts->input_dev->keybit);
- INIT_WORK(&gl_ts->work_pm_relax, IT7260_ts_work_func);
+ set_bit(KEY_WAKEUP, ts_data->input_dev->keybit);
+ INIT_WORK(&ts_data->work_pm_relax, it7260_ts_work_func);
device_init_wakeup(&client->dev, pdata->wakeup);
}
if (pdata->palm_detect_en)
- set_bit(gl_ts->pdata->palm_detect_keycode,
- gl_ts->input_dev->keybit);
+ set_bit(ts_data->pdata->palm_detect_keycode,
+ ts_data->input_dev->keybit);
- if (input_register_device(gl_ts->input_dev)) {
+ if (input_register_device(ts_data->input_dev)) {
dev_err(&client->dev, "failed to register input device\n");
goto err_input_register;
}
- if (request_threaded_irq(client->irq, NULL, IT7260_ts_threaded_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, gl_ts)) {
+ if (request_threaded_irq(client->irq, NULL, it7260_ts_threaded_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts_data)) {
dev_err(&client->dev, "request_irq failed\n");
goto err_irq_reg;
}
@@ -1720,30 +1919,31 @@ static int IT7260_ts_probe(struct i2c_client *client,
}
#if defined(CONFIG_FB)
- gl_ts->fb_notif.notifier_call = fb_notifier_callback;
+ ts_data->fb_notif.notifier_call = fb_notifier_callback;
- ret = fb_register_client(&gl_ts->fb_notif);
+ ret = fb_register_client(&ts_data->fb_notif);
if (ret)
dev_err(&client->dev, "Unable to register fb_notifier %d\n",
ret);
#endif
- IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_start, sizeof(cmd_start));
+ it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_start,
+ sizeof(cmd_start));
msleep(pdata->reset_delay);
- IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, rsp, sizeof(rsp));
+ it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE, rsp, sizeof(rsp));
msleep(pdata->reset_delay);
- gl_ts->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
- if (gl_ts->dir == NULL || IS_ERR(gl_ts->dir)) {
+ ts_data->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
+ if (ts_data->dir == NULL || IS_ERR(ts_data->dir)) {
dev_err(&client->dev,
"%s: Failed to create debugfs directory, ret = %ld\n",
- __func__, PTR_ERR(gl_ts->dir));
- ret = PTR_ERR(gl_ts->dir);
+ __func__, PTR_ERR(ts_data->dir));
+ ret = PTR_ERR(ts_data->dir);
goto err_create_debugfs_dir;
}
- temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, gl_ts->dir,
- gl_ts, &debug_suspend_fops);
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, ts_data->dir,
+ ts_data, &debug_suspend_fops);
if (temp == NULL || IS_ERR(temp)) {
dev_err(&client->dev,
"%s: Failed to create suspend debugfs file, ret = %ld\n",
@@ -1755,40 +1955,40 @@ static int IT7260_ts_probe(struct i2c_client *client,
return 0;
err_create_debugfs_file:
- debugfs_remove_recursive(gl_ts->dir);
+ debugfs_remove_recursive(ts_data->dir);
err_create_debugfs_dir:
#if defined(CONFIG_FB)
- if (fb_unregister_client(&gl_ts->fb_notif))
+ if (fb_unregister_client(&ts_data->fb_notif))
dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
#endif
sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
err_sysfs_grp_create:
- free_irq(client->irq, gl_ts);
+ free_irq(client->irq, ts_data);
err_irq_reg:
- input_unregister_device(gl_ts->input_dev);
+ input_unregister_device(ts_data->input_dev);
err_input_register:
if (pdata->wakeup) {
- cancel_work_sync(&gl_ts->work_pm_relax);
+ cancel_work_sync(&ts_data->work_pm_relax);
device_init_wakeup(&client->dev, false);
}
- if (gl_ts->input_dev)
- input_free_device(gl_ts->input_dev);
- gl_ts->input_dev = NULL;
+ if (ts_data->input_dev)
+ input_free_device(ts_data->input_dev);
+ ts_data->input_dev = NULL;
err_input_alloc:
err_identification_fail:
- if (gl_ts->ts_pinctrl) {
- if (IS_ERR_OR_NULL(gl_ts->pinctrl_state_release)) {
- devm_pinctrl_put(gl_ts->ts_pinctrl);
- gl_ts->ts_pinctrl = NULL;
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
} else {
- err = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_release);
+ err = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
if (err)
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select relase pinctrl state %d\n",
err);
}
@@ -1800,54 +2000,55 @@ err_identification_fail:
}
err_gpio_config:
- IT7260_power_on(false);
+ it7260_power_on(ts_data, false);
err_power_device:
- IT7260_regulator_configure(false);
+ it7260_regulator_configure(ts_data, false);
err_reg_configure:
return ret;
}
-static int IT7260_ts_remove(struct i2c_client *client)
+static int it7260_ts_remove(struct i2c_client *client)
{
+ struct it7260_ts_data *ts_data = i2c_get_clientdata(client);
int ret;
- debugfs_remove_recursive(gl_ts->dir);
+ debugfs_remove_recursive(ts_data->dir);
#if defined(CONFIG_FB)
- if (fb_unregister_client(&gl_ts->fb_notif))
+ if (fb_unregister_client(&ts_data->fb_notif))
dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
#endif
sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
- free_irq(client->irq, gl_ts);
- input_unregister_device(gl_ts->input_dev);
- if (gl_ts->input_dev)
- input_free_device(gl_ts->input_dev);
- gl_ts->input_dev = NULL;
- if (gl_ts->pdata->wakeup) {
- cancel_work_sync(&gl_ts->work_pm_relax);
+ free_irq(client->irq, ts_data);
+ input_unregister_device(ts_data->input_dev);
+ if (ts_data->input_dev)
+ input_free_device(ts_data->input_dev);
+ ts_data->input_dev = NULL;
+ if (ts_data->pdata->wakeup) {
+ cancel_work_sync(&ts_data->work_pm_relax);
device_init_wakeup(&client->dev, false);
}
- if (gl_ts->ts_pinctrl) {
- if (IS_ERR_OR_NULL(gl_ts->pinctrl_state_release)) {
- devm_pinctrl_put(gl_ts->ts_pinctrl);
- gl_ts->ts_pinctrl = NULL;
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
} else {
- ret = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_release);
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
if (ret)
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select relase pinctrl state %d\n",
ret);
}
} else {
- if (gpio_is_valid(gl_ts->pdata->reset_gpio))
- gpio_free(gl_ts->pdata->reset_gpio);
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->reset_gpio);
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
}
- IT7260_power_on(false);
- IT7260_regulator_configure(false);
+ it7260_power_on(ts_data, false);
+ it7260_regulator_configure(ts_data, false);
return 0;
}
@@ -1856,17 +2057,19 @@ static int IT7260_ts_remove(struct i2c_client *client)
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
+ struct it7260_ts_data *ts_data = container_of(self,
+ struct it7260_ts_data, fb_notif);
struct fb_event *evdata = data;
int *blank;
- if (evdata && evdata->data && gl_ts && gl_ts->client) {
+ if (evdata && evdata->data && ts_data && ts_data->client) {
if (event == FB_EVENT_BLANK) {
blank = evdata->data;
if (*blank == FB_BLANK_UNBLANK)
- IT7260_ts_resume(&(gl_ts->client->dev));
+ it7260_ts_resume(&(ts_data->client->dev));
else if (*blank == FB_BLANK_POWERDOWN ||
*blank == FB_BLANK_VSYNC_SUSPEND)
- IT7260_ts_suspend(&(gl_ts->client->dev));
+ it7260_ts_suspend(&(ts_data->client->dev));
}
}
@@ -1875,30 +2078,32 @@ static int fb_notifier_callback(struct notifier_block *self,
#endif
#ifdef CONFIG_PM
-static int IT7260_ts_resume(struct device *dev)
+static int it7260_ts_resume(struct device *dev)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int retval;
if (device_may_wakeup(dev)) {
- if (gl_ts->device_needs_wakeup) {
+ if (ts_data->device_needs_wakeup) {
/* Set active current for the avdd regulator */
- if (gl_ts->pdata->avdd_lpm_cur) {
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
+ if (ts_data->pdata->avdd_lpm_cur) {
+ retval = reg_set_optimum_mode_check(
+ ts_data->avdd,
IT_I2C_ACTIVE_LOAD_UA);
if (retval < 0)
dev_err(dev, "Regulator avdd set_opt failed at resume rc=%d\n",
retval);
}
- gl_ts->device_needs_wakeup = false;
- disable_irq_wake(gl_ts->client->irq);
+ ts_data->device_needs_wakeup = false;
+ disable_irq_wake(ts_data->client->irq);
}
return 0;
}
- if (gl_ts->ts_pinctrl) {
- retval = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_active);
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
if (retval < 0) {
dev_err(dev, "Cannot get default pinctrl state %d\n",
retval);
@@ -1906,50 +2111,53 @@ static int IT7260_ts_resume(struct device *dev)
}
}
- enable_irq(gl_ts->client->irq);
- gl_ts->suspended = false;
+ enable_irq(ts_data->client->irq);
+ ts_data->suspended = false;
return 0;
err_pinctrl_select_suspend:
return retval;
}
-static int IT7260_ts_suspend(struct device *dev)
+static int it7260_ts_suspend(struct device *dev)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int retval;
- if (gl_ts->fw_cfg_uploading) {
+ if (ts_data->fw_cfg_uploading) {
dev_dbg(dev, "Fw/cfg uploading. Can't go to suspend.\n");
return -EBUSY;
}
if (device_may_wakeup(dev)) {
- if (!gl_ts->device_needs_wakeup) {
+ if (!ts_data->device_needs_wakeup) {
/* put the device in low power idle mode */
- IT7260_ts_chipLowPowerMode(PWR_CTL_LOW_POWER_MODE);
+ it7260_ts_chip_low_power_mode(ts_data,
+ PWR_CTL_LOW_POWER_MODE);
/* Set lpm current for avdd regulator */
- if (gl_ts->pdata->avdd_lpm_cur) {
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
- gl_ts->pdata->avdd_lpm_cur);
+ if (ts_data->pdata->avdd_lpm_cur) {
+ retval = reg_set_optimum_mode_check(
+ ts_data->avdd,
+ ts_data->pdata->avdd_lpm_cur);
if (retval < 0)
dev_err(dev, "Regulator avdd set_opt failed at suspend rc=%d\n",
retval);
}
- gl_ts->device_needs_wakeup = true;
- enable_irq_wake(gl_ts->client->irq);
+ ts_data->device_needs_wakeup = true;
+ enable_irq_wake(ts_data->client->irq);
}
return 0;
}
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
- IT7260_ts_release_all();
+ it7260_ts_release_all(ts_data);
- if (gl_ts->ts_pinctrl) {
- retval = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_suspend);
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_suspend);
if (retval < 0) {
dev_err(dev, "Cannot get idle pinctrl state %d\n",
retval);
@@ -1957,7 +2165,7 @@ static int IT7260_ts_suspend(struct device *dev)
}
}
- gl_ts->suspended = true;
+ ts_data->suspended = true;
return 0;
@@ -1965,49 +2173,49 @@ err_pinctrl_select_suspend:
return retval;
}
-static const struct dev_pm_ops IT7260_ts_dev_pm_ops = {
- .suspend = IT7260_ts_suspend,
- .resume = IT7260_ts_resume,
+static const struct dev_pm_ops it7260_ts_dev_pm_ops = {
+ .suspend = it7260_ts_suspend,
+ .resume = it7260_ts_resume,
};
#else
-static int IT7260_ts_resume(struct device *dev)
+static int it7260_ts_resume(struct device *dev)
{
return 0;
}
-static int IT7260_ts_suspend(struct device *dev)
+static int it7260_ts_suspend(struct device *dev)
{
return 0;
}
#endif
-static const struct i2c_device_id IT7260_ts_id[] = {
+static const struct i2c_device_id it7260_ts_id[] = {
{ DEVICE_NAME, 0},
{}
};
-MODULE_DEVICE_TABLE(i2c, IT7260_ts_id);
+MODULE_DEVICE_TABLE(i2c, it7260_ts_id);
-static const struct of_device_id IT7260_match_table[] = {
+static const struct of_device_id it7260_match_table[] = {
{ .compatible = "ite,it7260_ts",},
{},
};
-static struct i2c_driver IT7260_ts_driver = {
+static struct i2c_driver it7260_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DEVICE_NAME,
- .of_match_table = IT7260_match_table,
+ .of_match_table = it7260_match_table,
#ifdef CONFIG_PM
- .pm = &IT7260_ts_dev_pm_ops,
+ .pm = &it7260_ts_dev_pm_ops,
#endif
},
- .probe = IT7260_ts_probe,
- .remove = IT7260_ts_remove,
- .id_table = IT7260_ts_id,
+ .probe = it7260_ts_probe,
+ .remove = it7260_ts_remove,
+ .id_table = it7260_ts_id,
};
-module_i2c_driver(IT7260_ts_driver);
+module_i2c_driver(it7260_ts_driver);
-MODULE_DESCRIPTION("IT7260 Touchscreen Driver");
+MODULE_DESCRIPTION("it7260 Touchscreen Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c
index 4eb7fd4b1cc9..8f2c4da578fc 100644
--- a/drivers/input/touchscreen/msg21xx_ts.c
+++ b/drivers/input/touchscreen/msg21xx_ts.c
@@ -5,6 +5,8 @@
*
* Copyright (C) 2012 Bruce Ding <bruce.ding@mstarsemi.com>
*
+ * Copyright (c) 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 as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -17,72 +19,55 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/timer.h>
#include <linux/gpio.h>
-
+#include <linux/of_gpio.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/mutex.h>
-#include <mach/gpio.h>
-#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/slab.h>
-
-#include <linux/syscalls.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/fcntl.h>
+#include <linux/firmware.h>
#include <linux/string.h>
-#include <asm/unistd.h>
-#include <linux/cdev.h>
-#include <asm/uaccess.h>
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#endif
-#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/regulator/consumer.h>
+
#if defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#endif
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
#include <linux/input/vir_ps.h>
#endif
-/*=============================================================*/
-// Macro Definition
-/*=============================================================*/
+/* Macro Definition */
#define TOUCH_DRIVER_DEBUG 0
#if (TOUCH_DRIVER_DEBUG == 1)
-#define DBG(fmt, arg...) pr_err(fmt, ##arg) //pr_info(fmt, ##arg)
+#define DBG(fmt, arg...) pr_info(fmt, ##arg)
#else
#define DBG(fmt, arg...)
#endif
-/*=============================================================*/
-// Constant Value & Variable Definition
-/*=============================================================*/
+/* Constant Value & Variable Definition */
-#define U8 unsigned char
-#define U16 unsigned short
-#define U32 unsigned int
-#define S8 signed char
-#define S16 signed short
-#define S32 signed int
+#define MSTAR_VTG_MIN_UV 2800000
+#define MSTAR_VTG_MAX_UV 3300000
+#define MSTAR_I2C_VTG_MIN_UV 1800000
+#define MSTAR_I2C_VTG_MAX_UV 1800000
+
+#define MAX_BUTTONS 4
+#define FT_COORDS_ARR_SIZE 4
+#define MSTAR_FW_NAME_MAX_LEN 50
+
+#define MSTAR_CHIPTOP_REGISTER_BANK 0x1E
+#define MSTAR_CHIPTOP_REGISTER_ICTYPE 0xCC
+#define MSTAR_INIT_SW_ID 0x7FF
-#define TOUCH_SCREEN_X_MIN (0)
-#define TOUCH_SCREEN_Y_MIN (0)
-/*
- * Note.
- * Please change the below touch screen resolution according to the touch panel that you are using.
- */
-#define TOUCH_SCREEN_X_MAX (480)
-#define TOUCH_SCREEN_Y_MAX (800)
/*
* Note.
* Please do not change the below setting.
@@ -90,62 +75,29 @@
#define TPD_WIDTH (2048)
#define TPD_HEIGHT (2048)
-/*
- * Note.
- * Please change the below GPIO pin setting to follow the platform that you are using
- */
-static int int_gpio = 1;
-static int reset_gpio = 0;
-#define MS_TS_MSG21XX_GPIO_RST reset_gpio
-#define MS_TS_MSG21XX_GPIO_INT int_gpio
-//---------------------------------------------------------------------//
-
-//#define SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST
-
-#ifdef SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST
-#define SYSFS_AUTHORITY (0644)
-#else
-#define SYSFS_AUTHORITY (0777)
-#endif
-
-#define FIRMWARE_AUTOUPDATE
#ifdef FIRMWARE_AUTOUPDATE
-typedef enum {
- SWID_START = 1,
- SWID_TRULY = SWID_START,
- SWID_NULL,
-} SWID_ENUM;
+enum {
+ SWID_START = 1,
+ SWID_TRULY = SWID_START,
+ SWID_NULL,
+};
-unsigned char MSG_FIRMWARE[1][33*1024] =
-{
- {
- #include "msg21xx_truly_update_bin.h"
- }
+static unsigned char MSG_FIRMWARE[1][33*1024] = { {
+ #include "msg21xx_truly_update_bin.h"
+ }
};
#endif
#define CONFIG_TP_HAVE_KEY
-/*
- * Note.
- * If the below virtual key value definition are not consistent with those that defined in key layout file of platform,
- * please change the below virtual key value to follow the platform that you are using.
- */
-#ifdef CONFIG_TP_HAVE_KEY
-#define TOUCH_KEY_MENU (139) //229
-#define TOUCH_KEY_HOME (172) //102
-#define TOUCH_KEY_BACK (158)
-#define TOUCH_KEY_SEARCH (217)
-
-const U16 tp_key_array[] = {TOUCH_KEY_MENU, TOUCH_KEY_HOME, TOUCH_KEY_BACK, TOUCH_KEY_SEARCH};
-#define MAX_KEY_NUM (sizeof(tp_key_array)/sizeof(tp_key_array[0]))
-#endif
+#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_ts_release"
-#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
-#define SLAVE_I2C_ID_DWI2C (0x4C>>1)
+#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
-#define DEMO_MODE_PACKET_LENGTH (8)
-#define MAX_TOUCH_NUM (2) //5
+#define DEMO_MODE_PACKET_LENGTH (8)
+#define MAX_TOUCH_NUM (2)
#define TP_PRINT
#ifdef TP_PRINT
@@ -153,1605 +105,2089 @@ static int tp_print_proc_read(void);
static void tp_print_create_entry(void);
#endif
-static char *fw_version = NULL; // customer firmware version
-static U16 fw_version_major = 0;
-static U16 fw_version_minor = 0;
-static U8 temp[94][1024];
-static U32 crc32_table[256];
-static int FwDataCnt = 0;
-static U8 bFwUpdating = 0;
-static struct class *firmware_class = NULL;
-static struct device *firmware_cmd_dev = NULL;
+static char *fw_version; /* customer firmware version */
+static unsigned short fw_version_major;
+static unsigned short fw_version_minor;
+static unsigned char temp[94][1024];
+static unsigned int crc32_table[256];
+static int FwDataCnt;
+static unsigned char bFwUpdating;
+static struct class *firmware_class;
+static struct device *firmware_cmd_dev;
+
+static struct i2c_client *i2c_client;
+
+static u32 button_map[MAX_BUTTONS];
+static u32 num_buttons;
+
+static unsigned short update_bin_major, update_bin_minor;
+static unsigned short main_sw_id = MSTAR_INIT_SW_ID;
+static unsigned short info_sw_id = MSTAR_INIT_SW_ID;
+static unsigned int bin_conf_crc32;
+
+struct msg21xx_ts_platform_data {
+ const char *name;
+ char fw_name[MSTAR_FW_NAME_MAX_LEN];
+ char *fw_version;
+ unsigned short fw_version_major;
+ unsigned short fw_version_minor;
+ u32 irqflags;
+ u32 irq_gpio;
+ u32 irq_gpio_flags;
+ u32 reset_gpio;
+ u32 reset_gpio_flags;
+ u32 family_id;
+ u32 x_max;
+ u32 y_max;
+ u32 x_min;
+ u32 y_min;
+ u32 panel_minx;
+ u32 panel_miny;
+ u32 panel_maxx;
+ u32 panel_maxy;
+ u32 num_max_touches;
+ bool no_force_update;
+ bool i2c_pull_up;
+ bool ignore_id_check;
+ int (*power_init)(bool);
+ int (*power_on)(bool);
+ int (*power_init)(bool);
+ int (*power_on)(bool);
+};
-static struct i2c_client *i2c_client = NULL;
+static struct msg21xx_ts_platform_data *pdata;
+
+struct msg21xx_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ const struct msg21xx_ts_platform_data *pdata;
+ struct regulator *vdd;
+ struct regulator *vcc_i2c;
+ bool loading_fw;
+ u8 family_id;
+ struct dentry *dir;
+ u16 addr;
+ bool suspended;
+ char *ts_info;
+ u8 *tch_data;
+ u32 tch_data_len;
+ u8 fw_ver[3];
+ u8 fw_vendor_id;
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#endif
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspend;
+ struct pinctrl_state *pinctrl_state_release;
+ struct mutex ts_mutex;
+};
+
+static struct msg21xx_ts_data *ts_data;
#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
-static struct notifier_block msg21xx_fb_notif;
-#elif defined (CONFIG_HAS_EARLYSUSPEND)
-static struct early_suspend mstar_ts_early_suspend;
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
#endif
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-static U8 bEnableTpProximity = 0;
-static U8 bFaceClosingTp = 0;
+static unsigned char bEnableTpProximity;
+static unsigned char bFaceClosingTp;
#endif
-static U8 bTpInSuspend = 0;
-static int irq_msg21xx = -1;
-static struct work_struct msg21xx_wk;
static struct mutex msg21xx_mutex;
-static struct input_dev *input_dev = NULL;
+static struct input_dev *input_dev;
-/*=============================================================*/
-// Data Type Definition
-/*=============================================================*/
-typedef struct
-{
- U16 x;
- U16 y;
-} touchPoint_t;
+/* Data Type Definition */
-/// max 80+1+1 = 82 bytes
-typedef struct
-{
- touchPoint_t point[MAX_TOUCH_NUM];
- U8 count;
- U8 keycode;
-} touchInfo_t;
+struct touchPoint_t {
+ unsigned short x;
+ unsigned short y;
+};
-enum i2c_speed
-{
- I2C_SLOW = 0,
- I2C_NORMAL = 1, /* Enable erasing/writing for 10 msec. */
- I2C_FAST = 2, /* Disable EWENB before 10 msec timeout. */
+struct touchInfo_t {
+ struct touchPoint_t point[MAX_TOUCH_NUM];
+ unsigned char count;
+ unsigned char keycode;
};
-typedef enum
-{
- EMEM_ALL = 0,
- EMEM_MAIN,
- EMEM_INFO,
-} EMEM_TYPE_t;
-/*=============================================================*/
-// Function Definition
-/*=============================================================*/
+enum EMEM_TYPE_t {
+ EMEM_ALL = 0,
+ EMEM_MAIN,
+ EMEM_INFO,
+};
+
+/* Function Definition */
-/// CRC
-static U32 _CRC_doReflect(U32 ref, S8 ch)
+static unsigned int _CRC_doReflect(unsigned int ref, signed char ch)
{
- U32 value = 0;
- U32 i = 0;
-
- for (i = 1; i < (ch + 1); i ++)
- {
- if (ref & 1)
- {
- value |= 1 << (ch - i);
- }
- ref >>= 1;
- }
-
- return value;
+ unsigned int value = 0;
+ unsigned int i = 0;
+
+ for (i = 1; i < (ch + 1); i++) {
+ if (ref & 1)
+ value |= 1 << (ch - i);
+ ref >>= 1;
+ }
+
+ return value;
}
-U32 _CRC_getValue(U32 text, U32 prevCRC)
+static unsigned int _CRC_getValue(unsigned int text, unsigned int prevCRC)
{
- U32 ulCRC = prevCRC;
+ unsigned int ulCRC = prevCRC;
- ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
+ ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
- return ulCRC;
+ return ulCRC;
}
static void _CRC_initTable(void)
{
- U32 magic_number = 0x04c11db7;
- U32 i, j;
-
- for (i = 0; i <= 0xFF; i ++)
- {
- crc32_table[i] = _CRC_doReflect (i, 8) << 24;
- for (j = 0; j < 8; j ++)
- {
- crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (0x80000000L) ? magic_number : 0);
- }
- crc32_table[i] = _CRC_doReflect(crc32_table[i], 32);
- }
+ unsigned int magic_number = 0x04c11db7;
+ unsigned int i, j;
+
+ for (i = 0; i <= 0xFF; i++) {
+ crc32_table[i] = _CRC_doReflect(i, 8) << 24;
+ for (j = 0; j < 8; j++)
+ crc32_table[i] = (crc32_table[i] << 1) ^
+ (crc32_table[i] & (0x80000000L) ?
+ magic_number : 0);
+ crc32_table[i] = _CRC_doReflect(crc32_table[i], 32);
+ }
}
static void reset_hw(void)
{
- DBG("reset_hw()\n");
-
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(100); /* Note that the RST must be in LOW 10ms at least */
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(100); /* Enable the interrupt service thread/routine for INT after 50ms */
+ DBG("reset_hw()\n");
+
+ gpio_direction_output(pdata->reset_gpio, 1);
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ msleep(100); /* Note that the RST must be in LOW 10ms at least */
+ gpio_set_value_cansleep(pdata->reset_gpio, 1);
+ /* Enable the interrupt service thread/routine for INT after 50ms */
+ msleep(100);
}
-static int read_i2c_seq(U8 addr, U8* buf, U16 size)
+static int read_i2c_seq(unsigned char addr, unsigned char *buf,
+ unsigned short size)
{
- int rc = 0;
- struct i2c_msg msgs[] =
- {
- {
- .addr = addr,
- .flags = I2C_M_RD, // read flag
- .len = size,
- .buf = buf,
- },
- };
-
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- if (i2c_client != NULL)
- {
- rc = i2c_transfer(i2c_client->adapter, msgs, 1);
- if (rc < 0)
- {
- DBG("read_i2c_seq() error %d\n", rc);
- }
- }
- else
- {
- DBG("i2c_client is NULL\n");
- }
-
- return rc;
+ int rc = 0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = addr,
+ .flags = I2C_M_RD, /* read flag*/
+ .len = size,
+ .buf = buf,
+ },
+ };
+
+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ * transmitted, else error code.
+ */
+ if (i2c_client != NULL) {
+ rc = i2c_transfer(i2c_client->adapter, msgs, 1);
+ if (rc < 0)
+ DBG("read_i2c_seq() error %d\n", rc);
+ } else {
+ DBG("i2c_client is NULL\n");
+ }
+
+ return rc;
}
-static int write_i2c_seq(U8 addr, U8* buf, U16 size)
+static int write_i2c_seq(unsigned char addr, unsigned char *buf,
+ unsigned short size)
{
- int rc = 0;
- struct i2c_msg msgs[] =
- {
- {
- .addr = addr,
- .flags = 0, // if read flag is undefined, then it means write flag.
- .len = size,
- .buf = buf,
- },
- };
-
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- if (i2c_client != NULL)
- {
- rc = i2c_transfer(i2c_client->adapter, msgs, 1);
- if ( rc < 0 )
- {
- DBG("write_i2c_seq() error %d\n", rc);
- }
- }
- else
- {
- DBG("i2c_client is NULL\n");
- }
-
- return rc;
+ int rc = 0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = addr,
+ /* if read flag is undefined,
+ * then it means write flag.
+ */
+ .flags = 0,
+ .len = size,
+ .buf = buf,
+ },
+ };
+
+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ * transmitted, else error code.
+ */
+ if (i2c_client != NULL) {
+ rc = i2c_transfer(i2c_client->adapter, msgs, 1);
+ if (rc < 0)
+ DBG("write_i2c_seq() error %d\n", rc);
+ } else {
+ DBG("i2c_client is NULL\n");
+ }
+
+ return rc;
}
-static U16 read_reg(U8 bank, U8 addr)
+static unsigned short read_reg(unsigned char bank, unsigned char addr)
{
- U8 tx_data[3] = {0x10, bank, addr};
- U8 rx_data[2] = {0};
+ unsigned char tx_data[3] = {0x10, bank, addr};
+ unsigned char rx_data[2] = {0};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3);
+ read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2);
- return (rx_data[1] << 8 | rx_data[0]);
+ return rx_data[1] << 8 | rx_data[0];
}
-static void write_reg(U8 bank, U8 addr, U16 data)
+static void write_reg(unsigned char bank, unsigned char addr,
+ unsigned short data)
{
- U8 tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
-}
+ unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
-static void write_reg_8bit(U8 bank, U8 addr, U8 data)
-{
- U8 tx_data[4] = {0x10, bank, addr, data};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
}
-void dbbusDWIICEnterSerialDebugMode(void)
+static void write_reg_8bit(unsigned char bank, unsigned char addr,
+ unsigned char data)
{
- U8 data[5];
-
- // Enter the Serial Debug Mode
- data[0] = 0x53;
- data[1] = 0x45;
- data[2] = 0x52;
- data[3] = 0x44;
- data[4] = 0x42;
+ unsigned char tx_data[4] = {0x10, bank, addr, data};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
}
-void dbbusDWIICStopMCU(void)
+static void dbbusDWIICEnterSerialDebugMode(void)
{
- U8 data[1];
+ unsigned char data[5];
- // Stop the MCU
- data[0] = 0x37;
+ /* Enter the Serial Debug Mode */
+ data[0] = 0x53;
+ data[1] = 0x45;
+ data[2] = 0x52;
+ data[3] = 0x44;
+ data[4] = 0x42;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5);
}
-void dbbusDWIICIICUseBus(void)
+static void dbbusDWIICStopMCU(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Use Bus
- data[0] = 0x35;
+ /* Stop the MCU */
+ data[0] = 0x37;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICIICReshape(void)
+static void dbbusDWIICIICUseBus(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Re-shape
- data[0] = 0x71;
+ /* IIC Use Bus */
+ data[0] = 0x35;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICIICNotUseBus(void)
+static void dbbusDWIICIICReshape(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Not Use Bus
- data[0] = 0x34;
+ /* IIC Re-shape */
+ data[0] = 0x71;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICNotStopMCU(void)
+static unsigned char get_ic_type(void)
{
- U8 data[1];
-
- // Not Stop the MCU
- data[0] = 0x36;
+ unsigned char ic_type = 0;
+ unsigned char bank;
+ unsigned char addr;
+
+ reset_hw();
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* stop mcu */
+ write_reg_8bit(0x0F, 0xE6, 0x01);
+ /* disable watch dog */
+ write_reg(0x3C, 0x60, 0xAA55);
+ /* get ic type */
+ bank = MSTAR_CHIPTOP_REGISTER_BANK;
+ addr = MSTAR_CHIPTOP_REGISTER_ICTYPE;
+ ic_type = (0xff)&(read_reg(bank, addr));
+
+ if (ic_type != 1 /* msg2133 */
+ && ic_type != 2 /* msg21xxA */
+ && ic_type != 3) /* msg26xxM */ {
+ ic_type = 0;
+ }
+
+ reset_hw();
+
+ return ic_type;
+}
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+static int msg21xx_read_firmware_id(void)
+{
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char dbbus_rx_data[4] = {0};
+ int ret = 0;
+
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = 0x00;
+ dbbus_tx_data[2] = 0x2A;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+ pdata->fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
+ pdata->fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+
+ dev_dbg(&i2c_client->dev, "major num = %d, minor num = %d\n",
+ pdata->fw_version_major, pdata->fw_version_minor);
+
+ if (pdata->fw_version == NULL)
+ pdata->fw_version = kzalloc(sizeof(char), GFP_KERNEL);
+
+ snprintf(pdata->fw_version, sizeof(char) * 7, "%03d%03d",
+ pdata->fw_version_major,
+ pdata->fw_version_minor);
+
+ return ret;
}
-void dbbusDWIICExitSerialDebugMode(void)
+static int firmware_erase_c33(enum EMEM_TYPE_t emem_type)
{
- U8 data[1];
+ /* stop mcu */
+ write_reg(0x0F, 0xE6, 0x0001);
- // Exit the Serial Debug Mode
- data[0] = 0x45;
+ /* disable watch dog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ /* set PROGRAM password */
+ write_reg_8bit(0x16, 0x1A, 0xBA);
+ write_reg_8bit(0x16, 0x1B, 0xAB);
- // Delay some interval to guard the next transaction
- //udelay ( 200 ); // delay about 0.2ms
-}
+ write_reg_8bit(0x16, 0x18, 0x80);
-//---------------------------------------------------------------------//
+ if (emem_type == EMEM_ALL)
+ write_reg_8bit(0x16, 0x08, 0x10);
-static U8 get_ic_type(void)
-{
- U8 ic_type = 0;
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- // stop mcu
- write_reg_8bit ( 0x0F, 0xE6, 0x01 );
- // disable watch dog
- write_reg ( 0x3C, 0x60, 0xAA55 );
- // get ic type
- ic_type = (0xff)&(read_reg(0x1E, 0xCC));
-
- if (ic_type != 1 //msg2133
- && ic_type != 2 //msg21xxA
- && ic_type != 3) //msg26xxM
- {
- ic_type = 0;
- }
-
- reset_hw();
-
- return ic_type;
-}
+ write_reg_8bit(0x16, 0x18, 0x40);
+ msleep(20);
-static int get_customer_firmware_version(void)
-{
- U8 dbbus_tx_data[3] = {0};
- U8 dbbus_rx_data[4] = {0};
- int ret = 0;
+ /* clear pce */
+ write_reg_8bit(0x16, 0x18, 0x80);
- DBG("get_customer_firmware_version()\n");
+ /* erase trigger */
+ if (emem_type == EMEM_MAIN)
+ write_reg_8bit(0x16, 0x0E, 0x04); /* erase main */
+ else
+ write_reg_8bit(0x16, 0x0E, 0x08); /* erase all block */
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = 0x00;
- dbbus_tx_data[2] = 0x2A;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
- fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+ return 1;
+}
- DBG("*** major = %d ***\n", fw_version_major);
- DBG("*** minor = %d ***\n", fw_version_minor);
+static void _ReadBinConfig(void);
+static unsigned int _CalMainCRC32(void);
- if (fw_version == NULL)
- {
- fw_version = kzalloc(sizeof(char), GFP_KERNEL);
- }
+static int check_fw_update(void)
+{
+ int ret = 0;
+
+ msg21xx_read_firmware_id();
+ _ReadBinConfig();
+ if (main_sw_id == info_sw_id) {
+ if (_CalMainCRC32() == bin_conf_crc32) {
+ /*check upgrading*/
+ if ((update_bin_major == pdata->fw_version_major) &&
+ (update_bin_minor > pdata->fw_version_minor)) {
+ ret = 1;
+ }
+ }
+ }
+ return ret;
- sprintf(fw_version, "%03d%03d", fw_version_major, fw_version_minor);
+}
- return ret;
+static ssize_t firmware_update_c33(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size,
+ enum EMEM_TYPE_t emem_type,
+ bool isForce) {
+ unsigned int i, j;
+ unsigned int crc_main, crc_main_tp;
+ unsigned int crc_info, crc_info_tp;
+ unsigned short reg_data = 0;
+ int update_pass = 1;
+
+ crc_main = 0xffffffff;
+ crc_info = 0xffffffff;
+
+ reset_hw();
+
+ if (!check_fw_update() && !isForce) {
+ DBG("****no need to update\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return size;
+ }
+ reset_hw();
+ msleep(300);
+
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* erase main */
+ firmware_erase_c33(EMEM_MAIN);
+ msleep(1000);
+
+ reset_hw();
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* polling 0x3CE4 is 0x1C70 */
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x1C70);
+ }
+
+ switch (emem_type) {
+ case EMEM_ALL:
+ write_reg(0x3C, 0xE4, 0xE38F); /* for all-blocks */
+ break;
+ case EMEM_MAIN:
+ write_reg(0x3C, 0xE4, 0x7731); /* for main block */
+ break;
+ case EMEM_INFO:
+ write_reg(0x3C, 0xE4, 0x7731); /* for info block */
+
+ write_reg_8bit(0x0F, 0xE6, 0x01);
+
+ write_reg_8bit(0x3C, 0xE4, 0xC5);
+ write_reg_8bit(0x3C, 0xE5, 0x78);
+
+ write_reg_8bit(MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x9F);
+ write_reg_8bit(MSTAR_CHIPTOP_REGISTER_BANK, 0x05, 0x82);
+
+ write_reg_8bit(0x0F, 0xE6, 0x00);
+ msleep(100);
+ break;
+ }
+
+ /* polling 0x3CE4 is 0x2F43 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x2F43);
+
+ /* calculate CRC 32 */
+ _CRC_initTable();
+
+ /* total 32 KB : 2 byte per R/W */
+ for (i = 0; i < 32; i++) {
+ if (i == 31) {
+ fw_bin_data[i][1014] = 0x5A;
+ fw_bin_data[i][1015] = 0xA5;
+
+ for (j = 0; j < 1016; j++)
+ crc_main = _CRC_getValue(fw_bin_data[i][j],
+ crc_main);
+ } else {
+ for (j = 0; j < 1024; j++)
+ crc_main = _CRC_getValue(fw_bin_data[i][j],
+ crc_main);
+ }
+
+ for (j = 0; j < 8; j++)
+ write_i2c_seq(ts_data->client->addr,
+ &fw_bin_data[i][j * 128], 128);
+ msleep(100);
+
+ /* polling 0x3CE4 is 0xD0BC */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0xD0BC);
+
+ write_reg(0x3C, 0xE4, 0x2F43);
+ }
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* write file done and check crc */
+ write_reg(0x3C, 0xE4, 0x1380);
+ }
+ msleep(20);
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* polling 0x3CE4 is 0x9432 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x9432);
+ }
+
+ crc_main = crc_main ^ 0xffffffff;
+ crc_info = crc_info ^ 0xffffffff;
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* CRC Main from TP */
+ crc_main_tp = read_reg(0x3C, 0x80);
+ crc_main_tp = (crc_main_tp << 16) | read_reg(0x3C, 0x82);
+
+ /* CRC Info from TP */
+ crc_info_tp = read_reg(0x3C, 0xA0);
+ crc_info_tp = (crc_info_tp << 16) | read_reg(0x3C, 0xA2);
+ }
+
+ update_pass = 1;
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ if (crc_main_tp != crc_main)
+ update_pass = 0;
+ }
+
+ if (!update_pass) {
+ DBG("update_C33 failed\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return 0;
+ }
+
+ DBG("update_C33 OK\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return size;
}
-static int firmware_erase_c33 ( EMEM_TYPE_t emem_type )
+static unsigned int _CalMainCRC32(void)
{
- // stop mcu
- write_reg ( 0x0F, 0xE6, 0x0001 );
+ unsigned int ret = 0;
+ unsigned short reg_data = 0;
+
+ reset_hw();
- //disable watch dog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(100);
- // set PROGRAM password
- write_reg_8bit ( 0x16, 0x1A, 0xBA );
- write_reg_8bit ( 0x16, 0x1B, 0xAB );
+ /* Stop MCU */
+ write_reg(0x0F, 0xE6, 0x0001);
- write_reg_8bit ( 0x16, 0x18, 0x80 );
+ /* Stop Watchdog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
- if ( emem_type == EMEM_ALL )
- {
- write_reg_8bit ( 0x16, 0x08, 0x10 ); //mark
- }
+ /* cmd */
+ write_reg(0x3C, 0xE4, 0xDF4C);
+ write_reg(0x1E, 0x04, 0x7d60);
+ /* TP SW reset */
+ write_reg(0x1E, 0x04, 0x829F);
- write_reg_8bit ( 0x16, 0x18, 0x40 );
- mdelay ( 10 );
+ /* MCU run */
+ write_reg(0x0F, 0xE6, 0x0000);
- // clear pce
- write_reg_8bit ( 0x16, 0x18, 0x80 );
+ /* polling 0x3CE4 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x9432);
- // erase trigger
- if ( emem_type == EMEM_MAIN )
- {
- write_reg_8bit ( 0x16, 0x0E, 0x04 ); //erase main
- }
- else
- {
- write_reg_8bit ( 0x16, 0x0E, 0x08 ); //erase all block
- }
+ /* Cal CRC Main from TP */
+ ret = read_reg(0x3C, 0x80);
+ ret = (ret << 16) | read_reg(0x3C, 0x82);
- return ( 1 );
+ DBG("[21xxA]:Current main crc32=0x%x\n", ret);
+ return ret;
}
-static ssize_t firmware_update_c33 ( struct device *dev, struct device_attribute *attr,
- const char *buf, size_t size, EMEM_TYPE_t emem_type )
+static void _ReadBinConfig(void)
{
- U32 i, j;
- U32 crc_main, crc_main_tp;
- U32 crc_info, crc_info_tp;
- U16 reg_data = 0;
- int update_pass = 1;
-
- crc_main = 0xffffffff;
- crc_info = 0xffffffff;
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- //erase main
- firmware_erase_c33 ( EMEM_MAIN );
- mdelay ( 1000 );
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- /////////////////////////
- // Program
- /////////////////////////
-
- //polling 0x3CE4 is 0x1C70
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x1C70 );
- }
-
- switch ( emem_type )
- {
- case EMEM_ALL:
- write_reg ( 0x3C, 0xE4, 0xE38F ); // for all-blocks
- break;
- case EMEM_MAIN:
- write_reg ( 0x3C, 0xE4, 0x7731 ); // for main block
- break;
- case EMEM_INFO:
- write_reg ( 0x3C, 0xE4, 0x7731 ); // for info block
-
- write_reg_8bit ( 0x0F, 0xE6, 0x01 );
-
- write_reg_8bit ( 0x3C, 0xE4, 0xC5 );
- write_reg_8bit ( 0x3C, 0xE5, 0x78 );
-
- write_reg_8bit ( 0x1E, 0x04, 0x9F );
- write_reg_8bit ( 0x1E, 0x05, 0x82 );
-
- write_reg_8bit ( 0x0F, 0xE6, 0x00 );
- mdelay ( 100 );
- break;
- }
-
- // polling 0x3CE4 is 0x2F43
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x2F43 );
-
- // calculate CRC 32
- _CRC_initTable ();
-
- for ( i = 0; i < 32; i++ ) // total 32 KB : 2 byte per R/W
- {
- if ( i == 31 )
- {
- temp[i][1014] = 0x5A;
- temp[i][1015] = 0xA5;
-
- for ( j = 0; j < 1016; j++ )
- {
- crc_main = _CRC_getValue ( temp[i][j], crc_main);
- }
- }
- else
- {
- for ( j = 0; j < 1024; j++ )
- {
- crc_main = _CRC_getValue ( temp[i][j], crc_main);
- }
- }
-
- //write_i2c_seq(SLAVE_I2C_ID_DWI2C, temp[i], 1024);
- for (j = 0; j < 8; j++)
- {
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &temp[i][j*128], 128 );
- }
- msleep (100);
-
- // polling 0x3CE4 is 0xD0BC
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0xD0BC );
-
- write_reg ( 0x3C, 0xE4, 0x2F43 );
- }
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // write file done and check crc
- write_reg ( 0x3C, 0xE4, 0x1380 );
- }
- mdelay ( 10 );
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // polling 0x3CE4 is 0x9432
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }while ( reg_data != 0x9432 );
- }
-
- crc_main = crc_main ^ 0xffffffff;
- crc_info = crc_info ^ 0xffffffff;
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // CRC Main from TP
- crc_main_tp = read_reg ( 0x3C, 0x80 );
- crc_main_tp = ( crc_main_tp << 16 ) | read_reg ( 0x3C, 0x82 );
-
- // CRC Info from TP
- crc_info_tp = read_reg ( 0x3C, 0xA0 );
- crc_info_tp = ( crc_info_tp << 16 ) | read_reg ( 0x3C, 0xA2 );
- }
-
- update_pass = 1;
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- if ( crc_main_tp != crc_main )
- update_pass = 0;
-
- /*
- if ( crc_info_tp != crc_info )
- update_pass = 0;
- */
- }
-
- if ( !update_pass )
- {
- DBG( "update_C33 failed\n" );
- reset_hw();
- FwDataCnt = 0;
- return 0;
- }
-
- DBG( "update_C33 OK\n" );
- reset_hw();
- FwDataCnt = 0;
- return size;
+ unsigned char dbbus_tx_data[5] = {0};
+ unsigned char dbbus_rx_data[4] = {0};
+ unsigned short reg_data = 0;
+
+ reset_hw();
+
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(100);
+
+ /* Stop MCU */
+ write_reg(0x0F, 0xE6, 0x0001);
+
+ /* Stop Watchdog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
+
+ /* cmd */
+ write_reg(0x3C, 0xE4, 0xA4AB);
+ write_reg(MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
+ /* TP SW reset */
+ write_reg(0x1E, 0x04, 0x829F);
+ /* TP SW reset*/
+
+ /* MCU run */
+ write_reg(0x0F, 0xE6, 0x0000);
+
+ /* polling 0x3CE4 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x5B58);
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x7F;
+ dbbus_tx_data[2] = 0x55;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39)
+ && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39)
+ && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) {
+ main_sw_id = (dbbus_rx_data[0] - 0x30) * 100 +
+ (dbbus_rx_data[1] - 0x30) * 10 +
+ (dbbus_rx_data[2] - 0x30);
+ }
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x7F;
+ dbbus_tx_data[2] = 0xFC;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ bin_conf_crc32 = dbbus_rx_data[0];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3];
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x83;
+ dbbus_tx_data[2] = 0x00;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39)
+ && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39)
+ && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) {
+ info_sw_id = (dbbus_rx_data[0] - 0x30) * 100 +
+ (dbbus_rx_data[1] - 0x30) * 10 +
+ (dbbus_rx_data[2] - 0x30);
+ }
+
+ DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n",
+ main_sw_id, info_sw_id, bin_conf_crc32);
}
-#ifdef FIRMWARE_AUTOUPDATE
-unsigned short main_sw_id = 0x7FF, info_sw_id = 0x7FF;
-U32 bin_conf_crc32 = 0;
-
-static U32 _CalMainCRC32(void)
+static ssize_t firmware_update_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- U32 ret=0;
- U16 reg_data=0;
-
- reset_hw();
-
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- msleep ( 100 );
+ DBG("*** firmware_update_show() pdata->fw_version = %s ***\n",
+ pdata->fw_version);
- //Stop MCU
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- // Stop Watchdog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- //cmd
- write_reg ( 0x3C, 0xE4, 0xDF4C );
- write_reg ( 0x1E, 0x04, 0x7d60 );
- // TP SW reset
- write_reg ( 0x1E, 0x04, 0x829F );
+ return snprintf(buf, sizeof(char) - 1, "%s\n", pdata->fw_version);
+}
- //MCU run
- write_reg ( 0x0F, 0xE6, 0x0000 );
+static ssize_t firmware_update_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
- //polling 0x3CE4
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }while ( reg_data != 0x9432 );
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
- // Cal CRC Main from TP
- ret = read_reg ( 0x3C, 0x80 );
- ret = ( ret << 16 ) | read_reg ( 0x3C, 0x82 );
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
- DBG("[21xxA]:Current main crc32=0x%x\n",ret);
- return (ret);
+ return size;
}
-static void _ReadBinConfig ( void )
-{
- U8 dbbus_tx_data[5]={0};
- U8 dbbus_rx_data[4]={0};
- U16 reg_data=0;
-
- reset_hw();
-
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- msleep ( 100 );
-
- //Stop MCU
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- // Stop Watchdog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- //cmd
- write_reg ( 0x3C, 0xE4, 0xA4AB );
- write_reg ( 0x1E, 0x04, 0x7d60 );
-
- // TP SW reset
- write_reg ( 0x1E, 0x04, 0x829F );
-
- //MCU run
- write_reg ( 0x0F, 0xE6, 0x0000 );
-
- //polling 0x3CE4
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x5B58 );
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x7F;
- dbbus_tx_data[2] = 0x55;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39)
- &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39)
- &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39))
- {
- main_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30);
- }
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x7F;
- dbbus_tx_data[2] = 0xFC;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- bin_conf_crc32 = dbbus_rx_data[0];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3];
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x83;
- dbbus_tx_data[2] = 0x00;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39)
- &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39)
- &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39))
- {
- info_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30);
- }
-
- DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n", main_sw_id, info_sw_id, bin_conf_crc32);
-}
+static DEVICE_ATTR(update, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_update_store);
-static int fwAutoUpdate(void *unused)
+static int prepare_fw_data(struct device *dev)
{
- int time = 0;
- ssize_t ret = 0;
-
- for (time = 0; time < 5; time++)
- {
- DBG("fwAutoUpdate time = %d\n",time);
- ret = firmware_update_c33(NULL, NULL, NULL, 1, EMEM_MAIN);
- if (ret == 1)
- {
- DBG("AUTO_UPDATE OK!!!");
- break;
- }
- }
- if (time == 5)
- {
- DBG("AUTO_UPDATE failed!!!");
- }
- enable_irq(irq_msg21xx);
- return 0;
+ int count;
+ int i;
+ int ret;
+ const struct firmware *fw = NULL;
+
+ ret = request_firmware(&fw, pdata->fw_name, dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed - %s (%d)\n",
+ pdata->fw_name, ret);
+ return ret;
+ }
+ DBG("*** prepare_fw_data() ret = %d, size = %d***\n", ret, fw->size);
+
+ count = fw->size / 1024;
+
+ for (i = 0; i < count; i++) {
+ memcpy(fw_bin_data[FwDataCnt], fw->data + (i * 1024), 1024);
+ FwDataCnt++;
+ }
+ update_bin_major = (fw->data[0x7f4f] << 8) + fw->data[0x7f4e];
+ update_bin_minor = (fw->data[0x7f51] << 8) + fw->data[0x7f50];
+ DBG("*** prepare_fw_data bin major = %d ***\n", update_bin_major);
+ DBG("*** prepare_fw_data bin minor = %d ***\n", update_bin_minor);
+
+ DBG("***FwDataCnt = %d ***\n", FwDataCnt);
+
+ return fw->size;
}
-#endif
-//------------------------------------------------------------------------------//
-static ssize_t firmware_update_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t firmware_update_smart_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- DBG("*** firmware_update_show() fw_version = %s ***\n", fw_version);
+ int ret;
- return sprintf(buf, "%s\n", fw_version);
+ ret = prepare_fw_data(dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed -(%d)\n", ret);
+ return ret;
+ }
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
+
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
+ if (ret == 0)
+ DBG("*** firmware_update_c33 ret = %d ***\n", ret);
+
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
+
+ return ret;
}
-static ssize_t firmware_update_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+static ssize_t firmware_force_update_smart_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- bFwUpdating = 1;
- disable_irq(irq_msg21xx);
+ int ret;
- DBG("*** update fw size = %d ***\n", FwDataCnt);
- size = firmware_update_c33 (dev, attr, buf, size, EMEM_MAIN);
+ ret = prepare_fw_data(dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed -(%d)\n", ret);
+ return ret;
+ }
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
- enable_irq(irq_msg21xx);
- bFwUpdating = 0;
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, true);
+ if (ret == 0)
+ DBG("*** firmware_update_c33 et = %d ***\n", ret);
- return size;
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
+
+ return ret;
}
-static DEVICE_ATTR(update, SYSFS_AUTHORITY, firmware_update_show, firmware_update_store);
+static DEVICE_ATTR(update_fw, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_update_smart_store);
+
+static DEVICE_ATTR(force_update_fw, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_force_update_smart_store);
static ssize_t firmware_version_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- DBG("*** firmware_version_show() fw_version = %s ***\n", fw_version);
-
- return sprintf(buf, "%s\n", fw_version);
+ msg21xx_read_firmware_id();
+ return snprintf(buf, 8, "%s\n", pdata->fw_version);
}
static ssize_t firmware_version_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- get_customer_firmware_version();
+ msg21xx_read_firmware_id();
+ DBG("*** firmware_version_store() pdata->fw_version = %s ***\n",
+ pdata->fw_version);
+
+ return size;
+}
- DBG("*** firmware_version_store() fw_version = %s ***\n", fw_version);
+static DEVICE_ATTR(version, (S_IRUGO | S_IWUSR),
+ firmware_version_show,
+ firmware_version_store);
- return size;
+
+static ssize_t msg21xx_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1, "%s\n", pdata->fw_name);
}
-static DEVICE_ATTR(version, SYSFS_AUTHORITY, firmware_version_show, firmware_version_store);
+static ssize_t msg21xx_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+
+ if (size > MSTAR_FW_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(pdata->fw_name, buf, size);
+ if (pdata->fw_name[size - 1] == '\n')
+ pdata->fw_name[size - 1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR),
+ msg21xx_fw_name_show, msg21xx_fw_name_store);
static ssize_t firmware_data_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt);
+ DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt);
- return FwDataCnt;
+ return FwDataCnt;
}
static ssize_t firmware_data_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- int count = size / 1024;
- int i;
+ int count = size / 1024;
+ int i;
- for (i = 0; i < count; i ++)
- {
- memcpy(temp[FwDataCnt], buf+(i*1024), 1024);
+ for (i = 0; i < count; i++) {
+ memcpy(fw_bin_data[FwDataCnt], buf + (i * 1024), 1024);
- FwDataCnt ++;
- }
+ FwDataCnt++;
+ }
- DBG("***FwDataCnt = %d ***\n", FwDataCnt);
+ DBG("***FwDataCnt = %d ***\n", FwDataCnt);
- if (buf != NULL)
- {
- DBG("*** buf[0] = %c ***\n", buf[0]);
- }
+ if (buf != NULL)
+ DBG("*** buf[0] = %c ***\n", buf[0]);
- return size;
+ return size;
}
-static DEVICE_ATTR(data, SYSFS_AUTHORITY, firmware_data_show, firmware_data_store);
+static DEVICE_ATTR(data, (S_IRUGO | S_IWUSR),
+ firmware_data_show, firmware_data_store);
#ifdef TP_PRINT
static ssize_t tp_print_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- tp_print_proc_read();
+ tp_print_proc_read();
- return sprintf(buf, "%d\n", bTpInSuspend);
+ return snprintf(buf, sizeof(char) - 1, "%d\n", ts_data->suspended);
}
static ssize_t tp_print_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- DBG("*** tp_print_store() ***\n");
+ DBG("*** tp_print_store() ***\n");
- return size;
+ return size;
}
-static DEVICE_ATTR(tpp, SYSFS_AUTHORITY, tp_print_show, tp_print_store);
+static DEVICE_ATTR(tpp, (S_IRUGO | S_IWUSR),
+ tp_print_show, tp_print_store);
#endif
-//------------------------------------------------------------------------------//
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
static void _msg_enable_proximity(void)
{
- U8 tx_data[4] = {0};
-
- DBG("_msg_enable_proximity!");
- tx_data[0] = 0x52;
- tx_data[1] = 0x00;
- tx_data[2] = 0x47;
- tx_data[3] = 0xa0;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
-
- bEnableTpProximity = 1;
+ unsigned char tx_data[4] = {0};
+
+ DBG("_msg_enable_proximity!");
+ tx_data[0] = 0x52;
+ tx_data[1] = 0x00;
+ tx_data[2] = 0x47;
+ tx_data[3] = 0xa0;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &tx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+
+ bEnableTpProximity = 1;
}
static void _msg_disable_proximity(void)
{
- U8 tx_data[4] = {0};
-
- DBG("_msg_disable_proximity!");
- tx_data[0] = 0x52;
- tx_data[1] = 0x00;
- tx_data[2] = 0x47;
- tx_data[3] = 0xa1;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
-
- bEnableTpProximity = 0;
- bFaceClosingTp = 0;
+ unsigned char tx_data[4] = {0};
+
+ DBG("_msg_disable_proximity!");
+ tx_data[0] = 0x52;
+ tx_data[1] = 0x00;
+ tx_data[2] = 0x47;
+ tx_data[3] = 0xa1;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &tx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+
+ bEnableTpProximity = 0;
+ bFaceClosingTp = 0;
}
-void tsps_msg21xx_enable(int en)
+static void tsps_msg21xx_enable(int en)
{
- if (en)
- {
- _msg_enable_proximity();
- }
- else
- {
- _msg_disable_proximity();
- }
+ if (en)
+ _msg_enable_proximity();
+ else
+ _msg_disable_proximity();
}
-int tsps_msg21xx_data(void)
+static int tsps_msg21xx_data(void)
{
- return bFaceClosingTp;
+ return bFaceClosingTp;
}
#endif
-static U8 calculate_checksum(U8 *msg, S32 length)
+static int msg21xx_pinctrl_init(void)
{
- S32 Checksum = 0;
- S32 i;
+ int retval;
+
+ /* Get pinctrl if target uses pinctrl */
+ ts_data->ts_pinctrl = devm_pinctrl_get(&(i2c_client->dev));
+ if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) {
+ retval = PTR_ERR(ts_data->ts_pinctrl);
+ dev_dbg(&i2c_client->dev,
+ "Target does not use pinctrl %d\n", retval);
+ goto err_pinctrl_get;
+ }
+
+ ts_data->pinctrl_state_active = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_ACTIVE);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_active)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_active);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts_data->pinctrl_state_suspend = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_SUSPEND);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_suspend)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_suspend);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts_data->pinctrl_state_release = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_RELEASE);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_release);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
+ }
+
+ return 0;
+
+err_pinctrl_lookup:
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+err_pinctrl_get:
+ ts_data->ts_pinctrl = NULL;
+ return retval;
+}
- for (i = 0; i < length; i ++)
- {
- Checksum += msg[i];
- }
+static unsigned char calculate_checksum(unsigned char *msg, int length)
+{
+ int checksum = 0, i;
- return (U8)((-Checksum) & 0xFF);
+ for (i = 0; i < length; i++)
+ checksum += msg[i];
+
+ return (unsigned char)((-checksum) & 0xFF);
}
-static S32 parse_info(touchInfo_t *info)
+static int parse_info(struct touchInfo_t *info)
{
- U8 data[DEMO_MODE_PACKET_LENGTH] = {0};
- U8 checksum = 0;
- U32 x = 0, y = 0;
- U32 x2 = 0, y2 = 0;
- U32 delta_x = 0, delta_y = 0;
-
- mutex_lock(&msg21xx_mutex);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &data[0], DEMO_MODE_PACKET_LENGTH);
- mutex_unlock(&msg21xx_mutex);
- checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
- DBG("check sum: [%x] == [%x]? \n", data[DEMO_MODE_PACKET_LENGTH-1], checksum);
-
- if(data[DEMO_MODE_PACKET_LENGTH-1] != checksum)
- {
- DBG("WRONG CHECKSUM\n");
- return -1;
- }
-
- if(data[0] != 0x52)
- {
- DBG("WRONG HEADER\n");
- return -1;
- }
-
- info->keycode = 0xFF;
- if ((data[1] == 0xFF) && (data[2] == 0xFF) && (data[3] == 0xFF) && (data[4] == 0xFF) && (data[6] == 0xFF))
- {
- if ((data[5] == 0xFF) || (data[5] == 0))
- {
- info->keycode = 0xFF;
- }
- else if ((data[5] == 1) || (data[5] == 2) || (data[5] == 4) || (data[5] == 8))
- {
- if (data[5] == 1)
- {
- info->keycode = 0;
- }
- else if (data[5] == 2)
- {
- info->keycode = 1;
- }
- else if (data[5] == 4)
- {
- info->keycode = 2;
- }
- else if (data[5] == 8)
- {
- info->keycode = 3;
- }
- }
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- else if (bEnableTpProximity &&((data[5] == 0x80) || (data[5] == 0x40)))
- {
- if (data[5] == 0x80)
- {
- bFaceClosingTp = 1;
- }
- else if (data[5] == 0x40)
- {
- bFaceClosingTp = 0;
- }
- DBG("bEnableTpProximity=%d; bFaceClosingTp=%d; data[5]=%x;\n", bEnableTpProximity, bFaceClosingTp, data[5]);
- return -1;
- }
- #endif
- else
- {
- DBG("WRONG KEY\n");
- return -1;
- }
- }
- else
- {
- x = (((data[1] & 0xF0 ) << 4) | data[2]);
- y = ((( data[1] & 0x0F) << 8) | data[3]);
- delta_x = (((data[4] & 0xF0) << 4 ) | data[5]);
- delta_y = (((data[4] & 0x0F) << 8 ) | data[6]);
-
- if ((delta_x == 0) && (delta_y == 0))
- {
- info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->count = 1;
- }
- else
- {
- if (delta_x > 2048)
- {
- delta_x -= 4096;
- }
- if (delta_y > 2048)
- {
- delta_y -= 4096;
- }
- x2 = (U32)((S16)x + (S16)delta_x);
- y2 = (U32)((S16)y + (S16)delta_y);
- info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->point[1].x = x2 * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[1].y = y2 * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->count = 2;
- }
- }
-
- return 0;
+ unsigned char data[DEMO_MODE_PACKET_LENGTH] = {0};
+ unsigned char checksum = 0;
+ unsigned int x = 0, y = 0;
+ unsigned int x2 = 0, y2 = 0;
+ unsigned int delta_x = 0, delta_y = 0;
+
+ mutex_lock(&msg21xx_mutex);
+ read_i2c_seq(ts_data->client->addr, &data[0], DEMO_MODE_PACKET_LENGTH);
+ mutex_unlock(&msg21xx_mutex);
+ checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
+ DBG("check sum: [%x] == [%x]?\n",
+ data[DEMO_MODE_PACKET_LENGTH-1], checksum);
+
+ if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) {
+ DBG("WRONG CHECKSUM\n");
+ return -EINVAL;
+ }
+
+ if (data[0] != 0x52) {
+ DBG("WRONG HEADER\n");
+ return -EINVAL;
+ }
+
+ info->keycode = 0xFF;
+ if ((data[1] == 0xFF) && (data[2] == 0xFF) &&
+ (data[3] == 0xFF) && (data[4] == 0xFF) &&
+ (data[6] == 0xFF)) {
+ if ((data[5] == 0xFF) || (data[5] == 0)) {
+ info->keycode = 0xFF;
+ } else if ((data[5] == 1) || (data[5] == 2) ||
+ (data[5] == 4) || (data[5] == 8)) {
+ info->keycode = data[5] >> 1;
+
+ DBG("info->keycode index %d\n", info->keycode);
+ }
+ #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+ else if (bEnableTpProximity && ((data[5] == 0x80) ||
+ (data[5] == 0x40))) {
+ if (data[5] == 0x80)
+ bFaceClosingTp = 1;
+ else if (data[5] == 0x40)
+ bFaceClosingTp = 0;
+
+ return -EINVAL;
+ }
+ #endif
+ else {
+ DBG("WRONG KEY\n");
+ return -EINVAL;
+ }
+ } else {
+ x = (((data[1] & 0xF0) << 4) | data[2]);
+ y = (((data[1] & 0x0F) << 8) | data[3]);
+ delta_x = (((data[4] & 0xF0) << 4) | data[5]);
+ delta_y = (((data[4] & 0x0F) << 8) | data[6]);
+
+ if ((delta_x == 0) && (delta_y == 0)) {
+ info->point[0].x = x * pdata->x_max / TPD_WIDTH;
+ info->point[0].y = y * pdata->y_max / TPD_HEIGHT;
+ info->count = 1;
+ } else {
+ if (delta_x > 2048)
+ delta_x -= 4096;
+
+ if (delta_y > 2048)
+ delta_y -= 4096;
+
+ x2 = (unsigned int)((signed short)x +
+ (signed short)delta_x);
+ y2 = (unsigned int)((signed short)y +
+ (signed short)delta_y);
+ info->point[0].x = x * pdata->x_max / TPD_WIDTH;
+ info->point[0].y = y * pdata->y_max / TPD_HEIGHT;
+ info->point[1].x = x2 * pdata->x_max / TPD_WIDTH;
+ info->point[1].y = y2 * pdata->y_max / TPD_HEIGHT;
+ info->count = 2;
+ }
+ }
+
+ return 0;
}
-static void touch_driver_touch_pressed(int x, int y)
+static void touch_driver_touch_released(void)
{
- DBG("point touch pressed");
+ int i;
+
+ DBG("point touch released\n");
+
+ for (i = 0; i < MAX_TOUCH_NUM; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
+ }
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
- input_mt_sync(input_dev);
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ input_report_key(input_dev, BTN_TOOL_FINGER, 0);
+ input_sync(input_dev);
}
-static void touch_driver_touch_released(void)
+/* read data through I2C then report data to input
+ *sub-system when interrupt occurred
+ */
+static irqreturn_t msg21xx_ts_interrupt(int irq, void *dev_id)
{
- DBG("point touch released");
+ struct touchInfo_t info;
+ int i = 0;
+ static int last_keycode = 0xFF;
+ static int last_count;
+
+ DBG("touch_driver_do_work()\n");
+
+ memset(&info, 0x0, sizeof(info));
+ if (parse_info(&info) == 0) {
+ #ifdef CONFIG_TP_HAVE_KEY
+ if (info.keycode != 0xFF) { /* key touch pressed */
+ if (info.keycode < num_buttons) {
+ if (info.keycode != last_keycode) {
+ DBG("key touch pressed");
+
+ input_report_key(input_dev,
+ BTN_TOUCH, 1);
+ input_report_key(input_dev,
+ button_map[info.keycode], 1);
+
+ last_keycode = info.keycode;
+ } else {
+ /* pass duplicate key-pressing */
+ DBG("REPEATED KEY\n");
+ }
+ } else {
+ DBG("WRONG KEY\n");
+ }
+ } else { /* key touch released */
+ if (last_keycode != 0xFF) {
+ DBG("key touch released");
+
+ input_report_key(input_dev,
+ BTN_TOUCH, 0);
+ input_report_key(input_dev,
+ button_map[last_keycode],
+ 0);
+
+ last_keycode = 0xFF;
+ }
+ }
+ #endif /* CONFIG_TP_HAVE_KEY */
+
+ if (info.count > 0) { /* point touch pressed */
+ for (i = 0; i < info.count; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, 1);
+ input_report_abs(input_dev,
+ ABS_MT_TOUCH_MAJOR, 1);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_X,
+ info.point[i].x);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_Y,
+ info.point[i].y);
+ }
+ }
+
+ if (last_count > info.count) {
+ for (i = info.count; i < MAX_TOUCH_NUM; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, 0);
+ }
+ }
+ last_count = info.count;
+
+ input_report_key(input_dev, BTN_TOUCH, info.count > 0);
+ input_report_key(input_dev, BTN_TOOL_FINGER, info.count > 0);
+
+ input_sync(input_dev);
+ }
+
+ return IRQ_HANDLED;
+}
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_mt_sync(input_dev);
+
+static int msg21xx_ts_power_init(void)
+{
+ int rc;
+
+ ts_data->vdd = regulator_get(&i2c_client->dev, "vdd");
+ if (IS_ERR(ts_data->vdd)) {
+ rc = PTR_ERR(ts_data->vdd);
+ dev_err(&i2c_client->dev,
+ "Regulator get failed vdd rc=%d\n", rc);
+ return rc;
+ }
+
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
+ rc = regulator_set_voltage(ts_data->vdd, MSTAR_VTG_MIN_UV,
+ MSTAR_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator set_vtg failed vdd rc=%d\n", rc);
+ goto reg_vdd_put;
+ }
+ }
+
+ ts_data->vcc_i2c = regulator_get(&i2c_client->dev, "vcc_i2c");
+ if (IS_ERR(ts_data->vcc_i2c)) {
+ rc = PTR_ERR(ts_data->vcc_i2c);
+ dev_err(&i2c_client->dev,
+ "Regulator get failed vcc_i2c rc=%d\n", rc);
+ goto reg_vdd_set_vtg;
+ }
+
+ if (regulator_count_voltages(ts_data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(ts_data->vcc_i2c,
+ MSTAR_I2C_VTG_MIN_UV,
+ MSTAR_I2C_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
+ goto reg_vcc_i2c_put;
+ }
+ }
+
+ return 0;
+
+reg_vcc_i2c_put:
+ regulator_put(ts_data->vcc_i2c);
+reg_vdd_set_vtg:
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV);
+reg_vdd_put:
+ regulator_put(ts_data->vdd);
+ return rc;
}
-/* read data through I2C then report data to input sub-system when interrupt occurred */
-void touch_driver_do_work(struct work_struct *work)
+
+static int msg21xx_ts_power_deinit(void)
{
- touchInfo_t info;
- int i = 0;
- static int last_keycode = 0xFF;
- static int last_count = 0;
-
- DBG("touch_driver_do_work()\n");
-
- memset(&info, 0x0, sizeof(info));
- if (0 == parse_info(&info))
- {
- #ifdef CONFIG_TP_HAVE_KEY
- if (info.keycode != 0xFF) //key touch pressed
- {
- DBG("touch_driver_do_work() info.keycode=%x, last_keycode=%x, tp_key_array[%d]=%d\n", info.keycode, last_keycode, info.keycode, tp_key_array[info.keycode]);
- if (info.keycode < MAX_KEY_NUM)
- {
- if (info.keycode != last_keycode)
- {
- DBG("key touch pressed");
-
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_report_key(input_dev, tp_key_array[info.keycode], 1);
-
- last_keycode = info.keycode;
- }
- else
- {
- /// pass duplicate key-pressing
- DBG("REPEATED KEY\n");
- }
- }
- else
- {
- DBG("WRONG KEY\n");
- }
- }
- else //key touch released
- {
- if (last_keycode != 0xFF)
- {
- DBG("key touch released");
-
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_report_key(input_dev, tp_key_array[last_keycode], 0);
-
- last_keycode = 0xFF;
- }
- }
- #endif //CONFIG_TP_HAVE_KEY
-
- if (info.count > 0) //point touch pressed
- {
- for (i = 0; i < info.count; i ++)
- {
- touch_driver_touch_pressed(info.point[i].x, info.point[i].y);
- }
- last_count = info.count;
- }
- else if (last_count > 0) //point touch released
- {
- touch_driver_touch_released();
- last_count = 0;
- }
-
- input_sync(input_dev);
- }
-
- enable_irq(irq_msg21xx);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV);
+
+ regulator_put(ts_data->vdd);
+
+ if (regulator_count_voltages(ts_data->vcc_i2c) > 0)
+ regulator_set_voltage(ts_data->vcc_i2c, 0,
+ MSTAR_I2C_VTG_MAX_UV);
+
+ regulator_put(ts_data->vcc_i2c);
+ return 0;
}
-/* The interrupt service routine will be triggered when interrupt occurred */
-irqreturn_t touch_driver_isr(int irq, void *dev_id)
+static int msg21xx_ts_power_on(void)
{
- DBG("touch_driver_isr()\n");
+ int rc;
+
+ rc = regulator_enable(ts_data->vdd);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vdd enable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_enable(ts_data->vcc_i2c);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vcc_i2c enable failed rc=%d\n", rc);
+ regulator_disable(ts_data->vdd);
+ }
+
+ return rc;
+}
- disable_irq_nosync(irq_msg21xx);
- schedule_work(&msg21xx_wk);
+static int msg21xx_ts_power_off(void)
+{
+ int rc;
+
+ DBG("*** %s ***\n", __func__);
+ rc = regulator_disable(vdd);
+ rc = regulator_disable(ts_data->vdd);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vdd disable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_disable(ts_data->vcc_i2c);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vcc_i2c disable failed rc=%d\n", rc);
+ rc = regulator_enable(ts_data->vdd);
+ }
+
+ return rc;
+}
- return IRQ_HANDLED;
+static int msg21xx_ts_gpio_configure(bool on)
+{
+ int ret = 0;
+
+ if (on) {
+ if (gpio_is_valid(pdata->irq_gpio)) {
+ ret = gpio_request(pdata->irq_gpio, "msg21xx_irq_gpio");
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to request GPIO[%d], %d\n",
+ pdata->irq_gpio, ret);
+ goto err_irq_gpio_req;
+ }
+ ret = gpio_direction_input(pdata->irq_gpio);
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to set direction for gpio[%d], %d\n",
+ pdata->irq_gpio, ret);
+ goto err_irq_gpio_dir;
+ }
+ gpio_set_value_cansleep(pdata->irq_gpio, 1);
+ } else {
+ dev_err(&i2c_client->dev, "irq gpio not provided\n");
+ goto err_irq_gpio_req;
+ }
+
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ ret = gpio_request(pdata->reset_gpio,
+ "msg21xx_reset_gpio");
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to request GPIO[%d], %d\n",
+ pdata->reset_gpio, ret);
+ goto err_reset_gpio_req;
+ }
+
+ /* power on TP */
+ ret = gpio_direction_output(pdata->reset_gpio, 1);
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to set direction for GPIO[%d], %d\n",
+ pdata->reset_gpio, ret);
+ goto err_reset_gpio_dir;
+ }
+ msleep(100);
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ msleep(20);
+ gpio_set_value_cansleep(pdata->reset_gpio, 1);
+ msleep(200);
+ } else {
+ dev_err(&i2c_client->dev, "reset gpio not provided\n");
+ goto err_reset_gpio_req;
+ }
+
+ } else {
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ ret = gpio_direction_input(pdata->reset_gpio);
+ if (ret)
+ dev_err(&i2c_client->dev,
+ "Unable to set direction for gpio [%d]\n",
+ pdata->reset_gpio);
+ gpio_free(pdata->reset_gpio);
+ }
+ }
+ return 0;
+err_reset_gpio_dir:
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->irq_gpio);
+err_reset_gpio_req:
+err_irq_gpio_dir:
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+err_irq_gpio_req:
+ return ret;
}
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
+#ifdef CONFIG_PM
+static int msg21xx_ts_resume(struct device *dev)
{
- struct fb_event *evdata = data;
- int *blank;
-
- if (evdata && evdata->data && event == FB_EVENT_BLANK )
- {
- blank = evdata->data;
- if (*blank == FB_BLANK_UNBLANK)
- {
- if (bTpInSuspend)
- {
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
-
- touch_driver_touch_released();
- input_sync(input_dev);
-
- enable_irq(irq_msg21xx);
- }
- bTpInSuspend = 0;
- }
- else if (*blank == FB_BLANK_POWERDOWN)
- {
- if (bFwUpdating)
- {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
- return 0;
- }
-
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity)
- {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
- return 0;
- }
- #endif
-
- if (bTpInSuspend == 0)
- {
- disable_irq(irq_msg21xx);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- }
- bTpInSuspend = 1;
- }
- }
-
- return 0;
+ int retval;
+
+ mutex_lock(&ts_data->ts_mutex);
+ if (ts_data->suspended) {
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
+ if (retval < 0) {
+ dev_err(dev, "Cannot get active pinctrl state\n");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+ }
+
+ retval = msg21xx_ts_gpio_configure(true);
+ if (retval) {
+ dev_err(dev, "Failed to put gpios in active state %d",
+ retval);
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ enable_irq(ts_data->client->irq);
+
+ retval = msg21xx_ts_power_on();
+ if (retval) {
+ dev_err(dev, "msg21xx_ts power on failed");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ ts_data->suspended = 0;
+ } else {
+ dev_info(dev, "msg21xx_ts already in resume\n");
+ }
+ mutex_unlock(&ts_data->ts_mutex);
+
+ return 0;
}
-#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
-void touch_driver_early_suspend(struct early_suspend *p)
+static int msg21xx_ts_suspend(struct device *dev)
{
- DBG("touch_driver_early_suspend()\n");
+ int retval;
- if (bFwUpdating)
- {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
- return;
- }
+ if (bFwUpdating) {
+ DBG("suspend bFwUpdating=%d\n", bFwUpdating);
+ return 0;
+ }
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity)
- {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
- return;
- }
+ if (bEnableTpProximity) {
+ DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
+ return 0;
+ }
#endif
- if (bTpInSuspend == 0)
- {
- disable_irq(irq_msg21xx);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- }
- bTpInSuspend = 1;
+ mutex_lock(&ts_data->ts_mutex);
+ if (ts_data->suspended == 0) {
+ disable_irq(ts_data->client->irq);
+
+ touch_driver_touch_released();
+
+ retval = msg21xx_ts_power_off();
+ if (retval) {
+ dev_err(dev, "msg21xx_ts power off failed");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_suspend);
+ if (retval < 0) {
+ dev_err(&i2c_client->dev, "Cannot get idle pinctrl state\n");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+ }
+
+ retval = msg21xx_ts_gpio_configure(false);
+ if (retval) {
+ dev_err(dev, "Failed to put gpios in idle state %d",
+ retval);
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ ts_data->suspended = 1;
+ } else {
+ dev_err(dev, "msg21xx_ts already in suspend\n");
+ }
+ mutex_unlock(&ts_data->ts_mutex);
+
+
+ return 0;
}
-
-void touch_driver_early_resume(struct early_suspend *p)
+#else
+static int msg21xx_ts_resume(struct device *dev)
+{
+ return 0;
+}
+static int msg21xx_ts_suspend(struct device *dev)
{
- DBG("touch_driver_early_resume() bTpInSuspend=%d\n", bTpInSuspend);
-
- if (bTpInSuspend)
- {
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
-
- touch_driver_touch_released();
- input_sync(input_dev);
-
- enable_irq(irq_msg21xx);
- }
- bTpInSuspend = 0;
+ return 0;
}
#endif
-/* probe function is used for matching and initializing input device */
-static int touch_driver_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
{
-#ifdef FIRMWARE_AUTOUPDATE
- unsigned short update_bin_major = 0, update_bin_minor = 0;
- int i, update_flag = 0;
+ struct fb_event *evdata = data;
+ int *blank;
+
+ if (evdata && evdata->data && event == FB_EVENT_BLANK) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ msg21xx_ts_resume(&i2c_client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ msg21xx_ts_suspend(&i2c_client->dev);
+ }
+
+ return 0;
+}
#endif
- int ret = 0;
-
- if (input_dev != NULL)
- {
- DBG("input device has found\n");
- return -1;
- }
-
- DBG("*** %s ***\n", __FUNCTION__);
-
- i2c_client = client;
-
- ret = gpio_request(MS_TS_MSG21XX_GPIO_RST, "reset");
- if (ret < 0)
- {
- pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_RST, ret);
- goto err0;
- }
-
- // power on TP
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(100);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
- if (0 == get_ic_type())
- {
- pr_err("the currnet ic is not Mstar\n");
- ret = -1;
- goto err0;
- }
-
- mutex_init(&msg21xx_mutex);
-
- /* allocate an input device */
- input_dev = input_allocate_device();
- if (!input_dev)
- {
- ret = -ENOMEM;
- pr_err("*** input device allocation failed ***\n");
- goto err1;
- }
-
- input_dev->name = client->name;
- input_dev->phys = "I2C";
- input_dev->dev.parent = &client->dev;
- input_dev->id.bustype = BUS_I2C;
-
- /* set the supported event type for input device */
- set_bit(EV_ABS, input_dev->evbit);
- set_bit(EV_SYN, input_dev->evbit);
- set_bit(EV_KEY, input_dev->evbit);
- set_bit(BTN_TOUCH, input_dev->keybit);
- set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+static int msg21xx_get_dt_coords(struct device *dev, char *name,
+ struct msg21xx_ts_platform_data *pdata)
+{
+ u32 coords[FT_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FT_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "mstar,panel-coords")) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (!strcmp(name, "mstar,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int msg21xx_parse_dt(struct device *dev,
+ struct msg21xx_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val;
+
+ rc = msg21xx_get_dt_coords(dev, "mstar,panel-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = msg21xx_get_dt_coords(dev, "mstar,display-coords", pdata);
+ if (rc)
+ return rc;
+
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np, "mstar,reset-gpio",
+ 0, &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ return pdata->reset_gpio;
+
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "mstar,irq-gpio",
+ 0, &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ return pdata->irq_gpio;
+
+
+ prop = of_find_property(np, "mstar,button-map", NULL);
+ if (prop) {
+ num_buttons = prop->length / sizeof(temp_val);
+ if (num_buttons > MAX_BUTTONS)
+ return -EINVAL;
+
+ rc = of_property_read_u32_array(np,
+ "mstar,button-map", button_map,
+ num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/* probe function is used for matching and initializing input device */
+static int msg21xx_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id) {
+
+ int ret = 0;
+
+ if (input_dev != NULL) {
+ DBG("input device has found\n");
+ return -EINVAL;
+ }
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct msg21xx_ts_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ ret = msg21xx_parse_dt(&client->dev, pdata);
+ if (ret) {
+ dev_err(&client->dev, "DT parsing failed\n");
+ return ret;
+ }
+ } else
+ pdata = client->dev.platform_data;
+
+ ts_data = devm_kzalloc(&client->dev,
+ sizeof(struct msg21xx_ts_data), GFP_KERNEL);
+ if (!ts_data)
+ return -ENOMEM;
+
+ DBG("*** %s ***\n", __func__);
+
+ i2c_client = client;
+
+ ret = msg21xx_ts_power_init();
+ if (ret)
+ dev_err(&client->dev, "Mstar power init failed\n");
+
+ ret = msg21xx_ts_power_on();
+ if (ret) {
+ dev_err(&client->dev, "Mstar power on failed\n");
+ goto exit_deinit_power;
+ }
+
+ ret = msg21xx_pinctrl_init();
+ if (!ret && ts_data->ts_pinctrl) {
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
+ if (ret < 0)
+ goto exit_pinctrl_select;
+ } else {
+ goto exit_pinctrl_init;
+ }
+
+ ret = msg21xx_ts_gpio_configure(true);
+ if (ret) {
+ dev_err(&client->dev, "Failed to configure gpio %d\n", ret);
+ goto exit_gpio_config;
+ }
+
+ if (get_ic_type() == 0) {
+ pr_err("the currnet ic is not Mstar\n");
+ ret = -1;
+ goto err_wrong_ic_type;
+ }
+
+ mutex_init(&msg21xx_mutex);
+ mutex_init(&ts_data->ts_mutex);
+
+ /* allocate an input device */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ ret = -ENOMEM;
+ pr_err("*** input device allocation failed ***\n");
+ goto err_input_allocate_dev;
+ }
+
+ input_dev->name = client->name;
+ input_dev->phys = "I2C";
+ input_dev->dev.parent = &client->dev;
+ input_dev->id.bustype = BUS_I2C;
+
+ /* set the supported event type for input device */
+ set_bit(EV_ABS, input_dev->evbit);
+ set_bit(EV_SYN, input_dev->evbit);
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+ set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ ts_data->input_dev = input_dev;
+ ts_data->client = client;
+ ts_data->pdata = pdata;
+
+ input_set_drvdata(input_dev, ts_data);
+ i2c_set_clientdata(client, ts_data);
#ifdef CONFIG_TP_HAVE_KEY
- {
- int i;
- for (i = 0; i < MAX_KEY_NUM; i ++)
- {
- input_set_capability(input_dev, EV_KEY, tp_key_array[i]);
- }
- }
+ {
+ int i;
+
+ for (i = 0; i < num_buttons; i++)
+ input_set_capability(input_dev, EV_KEY, button_map[i]);
+ }
#endif
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, TOUCH_SCREEN_X_MIN, TOUCH_SCREEN_X_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, TOUCH_SCREEN_Y_MIN, TOUCH_SCREEN_Y_MAX, 0, 0);
-
- /* register the input device to input sub-system */
- ret = input_register_device(input_dev);
- if (ret < 0)
- {
- pr_err("*** Unable to register ms-touchscreen input device ***\n");
- goto err1;
- }
-
- /* set sysfs for firmware */
- firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg20xx"); //client->name
- if (IS_ERR(firmware_class))
- pr_err("Failed to create class(firmware)!\n");
-
- firmware_cmd_dev = device_create(firmware_class, NULL, 0, NULL, "device");
- if (IS_ERR(firmware_cmd_dev))
- pr_err("Failed to create device(firmware_cmd_dev)!\n");
-
- // version
- if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_version.attr.name);
- // update
- if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_update.attr.name);
- // data
- if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_data.attr.name);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, 2, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, pdata->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, pdata->y_max, 0, 0);
+ ret = input_mt_init_slots(input_dev, MAX_TOUCH_NUM, 0);
+ if (ret) {
+ pr_err("Error %d initialising slots\n", ret);
+ goto err_free_mem;
+ }
+
+ /* register the input device to input sub-system */
+ ret = input_register_device(input_dev);
+ if (ret < 0) {
+ pr_err("*** Unable to register ms-touchscreen input device ***\n");
+ goto err_input_reg_dev;
+ }
+
+ /* set sysfs for firmware */
+ firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg21xx");
+ if (IS_ERR(firmware_class))
+ pr_err("Failed to create class(firmware)!\n");
+
+ firmware_cmd_dev = device_create(firmware_class, NULL, 0,
+ NULL, "device");
+ if (IS_ERR(firmware_cmd_dev))
+ pr_err("Failed to create device(firmware_cmd_dev)!\n");
+
+ /* version */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_version.attr.name);
+ /* update */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_update.attr.name);
+ /* data */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_data.attr.name);
+ /* fw name*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_fw_name) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_fw_name.attr.name);
+ /* smart fw update*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_update_fw) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_update_fw.attr.name);
+ /* smart fw force update*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_force_update_fw) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_force_update_fw.attr.name);
#ifdef TP_PRINT
- tp_print_create_entry();
+ tp_print_create_entry();
#endif
- dev_set_drvdata(firmware_cmd_dev, NULL);
-
- /* initialize the work queue */
- INIT_WORK(&msg21xx_wk, touch_driver_do_work);
-
- ret = gpio_request(MS_TS_MSG21XX_GPIO_INT, "interrupt");
- if (ret < 0)
- {
- pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret);
- goto err2;
- }
- gpio_direction_input(MS_TS_MSG21XX_GPIO_INT);
- gpio_set_value(MS_TS_MSG21XX_GPIO_INT, 1);
+ dev_set_drvdata(firmware_cmd_dev, NULL);
- irq_msg21xx = gpio_to_irq(MS_TS_MSG21XX_GPIO_INT);
+ ret = request_threaded_irq(client->irq, NULL,
+ msg21xx_ts_interrupt,
+ pdata->irq_gpio_flags | IRQF_ONESHOT,
+ "msg21xx", ts_data);
+ if (ret)
+ goto err_req_irq;
- /* request an irq and register the isr */
- ret = request_irq(irq_msg21xx, touch_driver_isr, IRQF_TRIGGER_RISING, "msg21xx", NULL);
- if (ret != 0)
- {
- pr_err("*** Unable to claim irq %d; error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret);
- goto err3;
- }
-
- disable_irq(irq_msg21xx);
+ disable_irq(ts_data->client->irq);
#if defined(CONFIG_FB)
- msg21xx_fb_notif.notifier_call = fb_notifier_callback;
- ret = fb_register_client(&msg21xx_fb_notif);
-#elif defined (CONFIG_HAS_EARLYSUSPEND)
- mstar_ts_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
- mstar_ts_early_suspend.suspend = touch_driver_early_suspend;
- mstar_ts_early_suspend.resume = touch_driver_early_resume;
- register_early_suspend(&mstar_ts_early_suspend);
+ ts_data->fb_notif.notifier_call = fb_notifier_callback;
+ ret = fb_register_client(&ts_data->fb_notif);
#endif
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable, &tsps_msg21xx_data);
+#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+ tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable,
+ &tsps_msg21xx_data);
#endif
#ifdef FIRMWARE_AUTOUPDATE
- get_customer_firmware_version();
- _ReadBinConfig();
-
- if (main_sw_id == info_sw_id)
- {
- if (_CalMainCRC32() == bin_conf_crc32)
- {
- if ((main_sw_id >= SWID_START) && (main_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f50];
-
- //check upgrading
- if ((update_bin_major == fw_version_major) && (update_bin_minor > fw_version_minor))
- {
- update_flag = 1;
- }
- }
- DBG("MAIN sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",main_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
- else
- {
- if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50];
- update_flag = 1;
- }
- DBG("INFO1 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
- }
- else
- {
- if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50];
- update_flag = 1;
- }
- DBG("INFO2 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
-
- if (update_flag == 1)
- {
- DBG("MSG21XX_fw_auto_update begin....\n");
- //transfer data
- for (i = 0; i < 33; i++)
- {
- firmware_data_store(NULL, NULL, &(MSG_FIRMWARE[info_sw_id-SWID_START][i*1024]), 1024);
- }
-
- kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update");
- DBG("*** mstar touch screen registered ***\n");
- return 0;
- }
-
- reset_hw();
+ get_customer_firmware_version();
+ _ReadBinConfig();
+
+ if (main_sw_id == info_sw_id) {
+ if (_CalMainCRC32() == bin_conf_crc32) {
+ if ((main_sw_id >= SWID_START) &&
+ (main_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [main_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE[main_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [main_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE[main_sw_id - SWID_START][0x7f50];
+
+ /* check upgrading */
+ if ((update_bin_major == fw_version_major) &&
+ (update_bin_minor > fw_version_minor)) {
+ update_flag = 1;
+ }
+ }
+ } else {
+ if ((info_sw_id >= SWID_START) &&
+ (info_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f50];
+ update_flag = 1;
+ }
+ }
+ } else {
+ if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f50];
+ update_flag = 1;
+ }
+ }
+
+ if (update_flag == 1) {
+ DBG("MSG21XX_fw_auto_update begin....\n");
+ /* transfer data */
+ for (i = 0; i < 33; i++) {
+ firmware_data_store(NULL, NULL,
+ &(MSG_FIRMWARE[info_sw_id - SWID_START][i * 1024]),
+ 1024);
+ }
+
+ kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update");
+ DBG("*** mstar touch screen registered ***\n");
+ return 0;
+ }
+
+ reset_hw();
#endif
- DBG("*** mstar touch screen registered ***\n");
- enable_irq(irq_msg21xx);
- return 0;
-
-err3:
- free_irq(irq_msg21xx, input_dev);
-
-err2:
- gpio_free(MS_TS_MSG21XX_GPIO_INT);
-
-err1:
- mutex_destroy(&msg21xx_mutex);
- input_unregister_device(input_dev);
- input_free_device(input_dev);
- input_dev = NULL;
-
-err0:
- gpio_free(MS_TS_MSG21XX_GPIO_RST);
-
- return ret;
+ DBG("*** mstar touch screen registered ***\n");
+ enable_irq(ts_data->client->irq);
+ return 0;
+
+err_req_irq:
+ free_irq(ts_data->client->irq, ts_data);
+
+err_input_reg_dev:
+err_input_allocate_dev:
+ mutex_destroy(&msg21xx_mutex);
+ mutex_destroy(&ts_data->ts_mutex);
+ input_unregister_device(input_dev);
+ input_free_device(input_dev);
+ input_dev = NULL;
+
+err_wrong_ic_type:
+ msg21xx_ts_gpio_configure(false);
+exit_gpio_config:
+exit_pinctrl_select:
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
+ } else {
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
+ if (ret < 0)
+ pr_err("Cannot get release pinctrl state\n");
+ }
+ }
+exit_pinctrl_init:
+ msg21xx_ts_power_off();
+exit_deinit_power:
+ msg21xx_ts_power_deinit();
+err_free_mem:
+ input_free_device(input_dev);
+
+ return ret;
}
-/* remove function is triggered when the input device is removed from input sub-system */
+/* remove function is triggered when the input device is removed
+ *from input sub-system
+ */
static int touch_driver_remove(struct i2c_client *client)
{
- DBG("touch_driver_remove()\n");
-
- free_irq(irq_msg21xx, input_dev);
- gpio_free(MS_TS_MSG21XX_GPIO_INT);
- gpio_free(MS_TS_MSG21XX_GPIO_RST);
- input_unregister_device(input_dev);
- mutex_destroy(&msg21xx_mutex);
-
- return 0;
+ int retval = 0;
+
+ DBG("touch_driver_remove()\n");
+
+ free_irq(ts_data->client->irq, ts_data);
+ gpio_free(pdata->irq_gpio);
+ gpio_free(pdata->reset_gpio);
+
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
+ } else {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
+ if (retval < 0)
+ pr_err("Cannot get release pinctrl state\n");
+ }
+ }
+
+ input_unregister_device(input_dev);
+ mutex_destroy(&msg21xx_mutex);
+ mutex_destroy(&ts_data->ts_mutex);
+
+ return retval;
}
-/* The I2C device list is used for matching I2C device and I2C device driver. */
-static const struct i2c_device_id touch_device_id[] =
-{
- {"msg21xx", 0},
- {}, /* should not omitted */
+/* The I2C device list is used for matching I2C device
+ *and I2C device driver.
+ */
+static const struct i2c_device_id touch_device_id[] = {
+ {"msg21xx", 0},
+ {}, /* should not omitted */
};
-MODULE_DEVICE_TABLE(i2c, touch_device_id);
-
-static struct i2c_driver touch_device_driver =
-{
- .driver = {
- .name = "msg21xx",
- .owner = THIS_MODULE,
- },
- .probe = touch_driver_probe,
- .remove = touch_driver_remove,
- .id_table = touch_device_id,
+static const struct of_device_id msg21xx_match_table[] = {
+ { .compatible = "mstar,msg21xx", },
+ { },
};
-static int __init touch_driver_init(void)
-{
- int ret;
-
- /* register driver */
- ret = i2c_add_driver(&touch_device_driver);
- if (ret < 0)
- {
- DBG("add touch_device_driver i2c driver failed.\n");
- return -ENODEV;
- }
- DBG("add touch_device_driver i2c driver.\n");
-
- return ret;
-}
+MODULE_DEVICE_TABLE(i2c, touch_device_id);
-static void __exit touch_driver_exit(void)
-{
- DBG("remove touch_device_driver i2c driver.\n");
+static struct i2c_driver touch_device_driver = {
+ .driver = {
+ .name = "ms-msg21xx",
+ .owner = THIS_MODULE,
+ .of_match_table = msg21xx_match_table,
+ },
+ .probe = msg21xx_ts_probe,
+ .remove = touch_driver_remove,
+ .id_table = touch_device_id,
+};
- i2c_del_driver(&touch_device_driver);
-}
+module_i2c_driver(touch_device_driver);
#ifdef TP_PRINT
#include <linux/proc_fs.h>
-static U16 InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
-static U8 row, units, cnt;
+static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
+static unsigned char row, units, cnt;
static int tp_print_proc_read(void)
{
- U16 i, j;
- U16 left, offset = 0;
- U8 dbbus_tx_data[3] = {0};
- U8 u8Data;
- S16 s16Data;
- S32 s32Data;
- char *buf = NULL;
-
- left = cnt*row*units;
- if ((bTpInSuspend == 0) && (InfoAddr != 0x0F) && (PoolAddr != 0x10) && (left > 0))
- {
- buf = kmalloc(left, GFP_KERNEL);
- if (buf != NULL)
- {
- printk("tpp: \n");
-
- while (left > 0)
- {
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = ((PoolAddr + offset) >> 8) & 0xFF;
- dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &buf[offset], left > TransLen ? TransLen : left);
- mutex_unlock(&msg21xx_mutex);
-
- if (left > TransLen)
- {
- left -= TransLen;
- offset += TransLen;
- }
- else
- {
- left = 0;
- }
- }
-
- for (i = 0; i < cnt; i++)
- {
- printk("tpp: ");
- for (j = 0; j < row; j++)
- {
- if (units == 1)
- {
- u8Data = buf[i*row*units + j*units];
- printk("%d\t", u8Data);
- }
- else if (units == 2)
- {
- s16Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8);
- printk("%d\t", s16Data);
- }
- else if (units == 4)
- {
- s32Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8) + (buf[i*row*units + j*units + 2] << 16) + (buf[i*row*units + j*units + 3] << 24);
- printk("%d\t", s32Data);
- }
- }
- printk("\n");
- }
-
- kfree(buf);
- }
- }
-
- return 0;
+ unsigned short i, j;
+ unsigned short left, offset = 0;
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char u8Data;
+ signed short s16Data;
+ int s32Data;
+ char *buf = NULL;
+
+ left = cnt*row*units;
+ if ((ts_data->suspended == 0) &&
+ (InfoAddr != 0x0F) &&
+ (PoolAddr != 0x10) &&
+ (left > 0)) {
+ buf = kmalloc(left, GFP_KERNEL);
+ if (buf != NULL) {
+
+ while (left > 0) {
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = ((PoolAddr + offset) >> 8)
+ & 0xFF;
+ dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr,
+ &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr,
+ &buf[offset],
+ left > TransLen ? TransLen : left);
+ mutex_unlock(&msg21xx_mutex);
+
+ if (left > TransLen) {
+ left -= TransLen;
+ offset += TransLen;
+ } else {
+ left = 0;
+ }
+ }
+
+ for (i = 0; i < cnt; i++) {
+ for (j = 0; j < row; j++) {
+ if (units == 1) {
+ u8Data = buf[i * row * units +
+ j * units];
+ } else if (units == 2) {
+ s16Data = buf[i * row * units +
+ j * units] +
+ (buf[i * row * units +
+ j * units + 1] << 8);
+ } else if (units == 4) {
+ s32Data = buf[i * row * units +
+ j * units] +
+ (buf[i * row * units +
+ j * units + 1] << 8) +
+ (buf[i * row * units +
+ j * units + 2] << 16) +
+ (buf[i * row * units +
+ j * units + 3] << 24);
+ }
+ }
+ }
+
+ kfree(buf);
+ }
+ }
+
+ return 0;
}
static void tp_print_create_entry(void)
{
- U8 dbbus_tx_data[3] = {0};
- U8 dbbus_rx_data[8] = {0};
-
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = 0x00;
- dbbus_tx_data[2] = 0x58;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
- InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
- printk("InfoAddr=0x%X\n", InfoAddr);
- printk("PoolAddr=0x%X\n", PoolAddr);
-
- if ((InfoAddr != 0x0F) && (PoolAddr != 0x10))
- {
- msleep(10);
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF;
- dbbus_tx_data[2] = InfoAddr & 0xFF;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 8);
- mutex_unlock(&msg21xx_mutex);
-
- units = dbbus_rx_data[0];
- row = dbbus_rx_data[1];
- cnt = dbbus_rx_data[2];
- TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6];
- printk("tpp: row=%d, units=%d\n", row, units);
- printk("tpp: cnt=%d, TransLen=%d\n", cnt, TransLen);
-
- // tpp
- if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0)
- {
- pr_err("Failed to create device file(%s)!\n", dev_attr_tpp.attr.name);
- }
- }
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char dbbus_rx_data[8] = {0};
+
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = 0x00;
+ dbbus_tx_data[2] = 0x58;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+ InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
+ PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+
+ if ((InfoAddr != 0x0F) && (PoolAddr != 0x10)) {
+ msleep(20);
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF;
+ dbbus_tx_data[2] = InfoAddr & 0xFF;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 8);
+ mutex_unlock(&msg21xx_mutex);
+
+ units = dbbus_rx_data[0];
+ row = dbbus_rx_data[1];
+ cnt = dbbus_rx_data[2];
+ TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6];
+
+ if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_tpp.attr.name);
+ }
+ }
}
#endif
-module_init(touch_driver_init);
-module_exit(touch_driver_exit);
MODULE_AUTHOR("MStar Semiconductor, Inc.");
MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index cbe77022404b..9b9b74436d88 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -675,6 +675,12 @@ static int get_hfi_extradata_index(enum hal_extradata_id index)
case HAL_EXTRADATA_PQ_INFO:
ret = HFI_PROPERTY_PARAM_VENC_OVERRIDE_QP_EXTRADATA;
break;
+ case HAL_EXTRADATA_VUI_DISPLAY_INFO:
+ ret = HFI_PROPERTY_PARAM_VUI_DISPLAY_INFO_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_VPX_COLORSPACE:
+ ret = HFI_PROPERTY_PARAM_VDEC_VPX_COLORSPACE_EXTRADATA;
+ break;
default:
dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
break;
@@ -2127,6 +2133,26 @@ int create_pkt_cmd_session_set_property(
pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
break;
}
+ case HAL_PARAM_VENC_VIDEO_SIGNAL_INFO:
+ {
+ struct hal_video_signal_info *hal = pdata;
+ struct hfi_video_signal_metadata *signal_info =
+ (struct hfi_video_signal_metadata *)
+ &pkt->rg_property_data[1];
+
+ signal_info->enable = true;
+ signal_info->video_format = MSM_VIDC_NTSC;
+ signal_info->video_full_range = hal->full_range;
+ signal_info->color_description = MSM_VIDC_COLOR_DESC_PRESENT;
+ signal_info->color_primaries = hal->color_space;
+ signal_info->transfer_characteristics = hal->transfer_chars;
+ signal_info->matrix_coeffs = hal->matrix_coeffs;
+
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pkt->size += sizeof(u32) + sizeof(*signal_info);
+ break;
+ }
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 0c26cc7debaf..96fefea39241 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -247,7 +247,7 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
.name = "Extradata Type",
.type = V4L2_CTRL_TYPE_MENU,
.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
- .maximum = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI,
+ .maximum = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE,
.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
.menu_skip_mask = ~(
(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -273,7 +273,10 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
(1 << V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI) |
(1 << V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP) |
(1 << V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI) |
- (1 << V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI)
+ (1 <<
+ V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE)
),
.qmenu = mpeg_video_vidc_extradata,
},
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 55e54f7eb008..c08084a54e86 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1242,6 +1242,46 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.default_value = V4L2_MPEG_VIDC_VIDEO_H264_TRANSFORM_8x8_ENABLE,
.step = 1,
},
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE,
+ .name = "Set Color space",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = MSM_VIDC_BT709_5,
+ .maximum = MSM_VIDC_BT2020,
+ .default_value = MSM_VIDC_BT601_6_625,
+ .step = 1,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE,
+ .name = "Set Color space range",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .minimum = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_DISABLE,
+ .maximum = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_ENABLE,
+ .default_value = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_DISABLE,
+ .step = 1,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS,
+ .name = "Set Color space transfer characterstics",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = MSM_VIDC_TRANSFER_BT709_5,
+ .maximum = MSM_VIDC_TRANSFER_BT_2020_12,
+ .default_value = MSM_VIDC_TRANSFER_601_6_625,
+ .step = 1,
+ .qmenu = NULL,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS,
+ .name = "Set Color space matrix coefficients",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = MSM_VIDC_MATRIX_BT_709_5,
+ .maximum = MSM_VIDC_MATRIX_BT_2020_CONST,
+ .default_value = MSM_VIDC_MATRIX_601_6_625,
+ .step = 1,
+ .qmenu = NULL,
+ },
+
};
#define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
@@ -2105,6 +2145,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
int baselayerid = 0;
int frameqp = 0;
int pic_order_cnt = 0;
+ struct hal_video_signal_info signal_info = {0};
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
@@ -3093,6 +3134,64 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
pdata = &pic_order_cnt;
break;
}
+ case V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE:
+ {
+ signal_info.color_space = ctrl->val;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE);
+ signal_info.full_range = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS);
+ signal_info.transfer_chars = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS);
+ signal_info.matrix_coeffs = temp_ctrl ? temp_ctrl->val : 0;
+ property_id = HAL_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pdata = &signal_info;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE:
+ {
+ signal_info.full_range = ctrl->val;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
+ signal_info.color_space = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS);
+ signal_info.transfer_chars = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS);
+ signal_info.matrix_coeffs = temp_ctrl ? temp_ctrl->val : 0;
+ property_id = HAL_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pdata = &signal_info;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS:
+ {
+ signal_info.transfer_chars = ctrl->val;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE);
+ signal_info.full_range = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
+ signal_info.color_space = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS);
+ signal_info.matrix_coeffs = temp_ctrl ? temp_ctrl->val : 0;
+ property_id = HAL_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pdata = &signal_info;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS:
+ {
+ signal_info.matrix_coeffs = ctrl->val;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE);
+ signal_info.full_range = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS);
+ signal_info.transfer_chars = temp_ctrl ? temp_ctrl->val : 0;
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
+ signal_info.color_space = temp_ctrl ? temp_ctrl->val : 0;
+ property_id = HAL_PARAM_VENC_VIDEO_SIGNAL_INFO;
+ pdata = &signal_info;
+ break;
+ }
case V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC:
if (ctrl->val == V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_ENABLE) {
rc = msm_venc_set_csc(inst);
@@ -3516,10 +3615,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
}
hdev = inst->core->device;
- if (msm_vidc_vpe_csc_601_to_709) {
- msm_venc_set_csc(inst);
- }
-
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
fmt = msm_comm_get_pixel_fmt_fourcc(venc_formats,
ARRAY_SIZE(venc_formats), f->fmt.pix_mp.pixelformat,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 8541e06d997a..1f071ba36ec1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -77,6 +77,8 @@ const char *const mpeg_video_vidc_extradata[] = {
"Extradata display colour SEI",
"Extradata light level SEI",
"Extradata PQ Info",
+ "Extradata display VUI",
+ "Extradata vpx color space",
};
struct getprop_buf {
@@ -210,7 +212,8 @@ int msm_comm_ctrl_init(struct msm_vidc_inst *inst,
}
if (!ctrl) {
- dprintk(VIDC_ERR, "%s - invalid ctrl\n", __func__);
+ dprintk(VIDC_ERR, "%s - invalid ctrl %s\n", __func__,
+ drv_ctrls[idx].name);
return -EINVAL;
}
@@ -1719,6 +1722,19 @@ static struct vb2_buffer *get_vb_from_device_addr(struct buf_queue *bufq,
return vb;
}
+static void msm_vidc_try_suspend(struct msm_vidc_inst *inst)
+{
+ bool batch_mode;
+
+ batch_mode = msm_comm_g_ctrl_for_id(inst, V4L2_CID_VIDC_QBUF_MODE)
+ == V4L2_VIDC_QBUF_BATCHED;
+ if (batch_mode) {
+ dprintk(VIDC_DBG,
+ "Trying to suspend Venus after finishing Batch\n");
+ msm_comm_suspend(inst->core->id);
+ }
+}
+
static void handle_ebd(enum hal_command_response cmd, void *data)
{
struct msm_vidc_cb_data_done *response = data;
@@ -1790,6 +1806,8 @@ static void handle_ebd(enum hal_command_response cmd, void *data)
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD);
}
+ msm_vidc_try_suspend(inst);
+
put_inst(inst);
}
@@ -2089,6 +2107,7 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD);
}
+ msm_vidc_try_suspend(inst);
err_handle_fbd:
put_inst(inst);
}
@@ -4692,6 +4711,13 @@ enum hal_extradata_id msm_comm_get_hal_extradata_index(
case V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO:
ret = HAL_EXTRADATA_PQ_INFO;
break;
+
+ case V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY:
+ ret = HAL_EXTRADATA_VUI_DISPLAY_INFO;
+ break;
+ case V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE:
+ ret = HAL_EXTRADATA_VPX_COLORSPACE;
+ break;
default:
dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
break;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index fb79661dd2d7..7976d6e8a603 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -171,8 +171,6 @@ struct dentry *msm_vidc_debugfs_init_drv(void)
&msm_vidc_fw_low_power_mode) &&
__debugfs_create(u32, "debug_output", &msm_vidc_debug_out) &&
__debugfs_create(u32, "hw_rsp_timeout", &msm_vidc_hw_rsp_timeout) &&
- __debugfs_create(bool, "enable_vpe_csc_601_709",
- &msm_vidc_vpe_csc_601_to_709) &&
__debugfs_create(bool, "sys_idle_indicator",
&msm_vidc_sys_idle_indicator) &&
__debugfs_create(u32, "firmware_unload_delay",
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 20e217cc0445..50c0eb351d4f 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1297,17 +1297,9 @@ static int venus_hfi_suspend(void *dev)
return -ENOTSUPP;
}
- mutex_lock(&device->lock);
+ dprintk(VIDC_DBG, "Suspending Venus\n");
+ rc = flush_delayed_work(&venus_hfi_pm_work);
- if (device->power_enabled) {
- dprintk(VIDC_DBG, "Venus is busy\n");
- rc = -EBUSY;
- } else {
- dprintk(VIDC_DBG, "Venus is power suspended\n");
- rc = 0;
- }
-
- mutex_unlock(&device->lock);
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 330710631211..4cbb59d12f92 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -85,6 +85,7 @@
#define HFI_EXTRADATA_STREAM_USERDATA 0x0000000E
#define HFI_EXTRADATA_FRAME_QP 0x0000000F
#define HFI_EXTRADATA_FRAME_BITS_INFO 0x00000010
+#define HFI_EXTRADATA_VPX_COLORSPACE 0x00000014
#define HFI_EXTRADATA_MULTISLICE_INFO 0x7F100000
#define HFI_EXTRADATA_NUM_CONCEALED_MB 0x7F100001
#define HFI_EXTRADATA_INDEX 0x7F100002
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 36df3a1d45a1..34ab36a4647b 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -125,6 +125,8 @@ enum hal_extradata_id {
HAL_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI,
HAL_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI,
HAL_EXTRADATA_PQ_INFO,
+ HAL_EXTRADATA_VUI_DISPLAY_INFO,
+ HAL_EXTRADATA_VPX_COLORSPACE,
};
enum hal_property {
@@ -239,6 +241,7 @@ enum hal_property {
HAL_CONFIG_VENC_BLUR_RESOLUTION,
HAL_PARAM_VENC_SESSION_QP_RANGE_PACKED,
HAL_PARAM_VENC_H264_TRANSFORM_8x8,
+ HAL_PARAM_VENC_VIDEO_SIGNAL_INFO,
};
enum hal_domain {
@@ -992,6 +995,13 @@ struct hal_vpe_color_space_conversion {
u32 csc_limit[HAL_MAX_LIMIT_COEFFS];
};
+struct hal_video_signal_info {
+ u32 color_space;
+ u32 transfer_chars;
+ u32 matrix_coeffs;
+ bool full_range;
+};
+
enum vidc_resource_id {
VIDC_RESOURCE_NONE,
VIDC_RESOURCE_OCMEM,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index ff043e9a819b..23240746baf1 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -350,7 +350,7 @@ struct hfi_buffer_info {
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01B)
#define HFI_PROPERTY_PARAM_VENC_LTRMODE \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01C)
-#define HFI_PROPERTY_PARAM_VENC_VIDEO_FULL_RANGE \
+#define HFI_PROPERTY_PARAM_VENC_VIDEO_SIGNAL_INFO \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01D)
#define HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01E)
@@ -671,6 +671,16 @@ struct hfi_frame_size {
u32 height;
};
+struct hfi_video_signal_metadata {
+ u32 enable;
+ u32 video_format;
+ u32 video_full_range;
+ u32 color_description;
+ u32 color_primaries;
+ u32 transfer_characteristics;
+ u32 matrix_coeffs;
+};
+
struct hfi_h264_vui_timing_info {
u32 enable;
u32 fixed_frame_rate;
diff --git a/drivers/mfd/wcd9xxx-utils.c b/drivers/mfd/wcd9xxx-utils.c
index 22d61d96a11d..38286831a02c 100644
--- a/drivers/mfd/wcd9xxx-utils.c
+++ b/drivers/mfd/wcd9xxx-utils.c
@@ -298,6 +298,7 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev)
struct wcd9xxx_pdata *pdata;
u32 dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
u32 mad_dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
+ u32 ecpp_dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
u32 dmic_clk_drive = WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED;
u32 prop_val;
@@ -358,6 +359,15 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev)
pdata->mclk_rate,
"mad_dmic_rate");
+ if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-ecpp-dmic-rate",
+ &prop_val)))
+ ecpp_dmic_sample_rate = prop_val;
+
+ pdata->ecpp_dmic_sample_rate = wcd9xxx_validate_dmic_sample_rate(dev,
+ ecpp_dmic_sample_rate,
+ pdata->mclk_rate,
+ "ecpp_dmic_rate");
+
if (!(of_property_read_u32(dev->of_node,
"qcom,cdc-dmic-clk-drv-strength",
&prop_val)))
diff --git a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
index 14abb75fffe0..45db409eb7c1 100644
--- a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
+++ b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
@@ -25,9 +25,9 @@
.ngroups = ARRAY_SIZE(fname##_groups), \
}
-#define SOUTH 0x00500000
-#define WEST 0x00100000
-#define EAST 0x00900000
+#define NORTH 0x00900000
+#define CENTER 0x00500000
+#define SOUTH 0x00100000
#define REG_SIZE 0x1000
#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
{ \
@@ -204,9 +204,16 @@ static const struct pinctrl_pin_desc msmfalcon_pins[] = {
PINCTRL_PIN(108, "GPIO_108"),
PINCTRL_PIN(109, "GPIO_109"),
PINCTRL_PIN(110, "GPIO_110"),
- PINCTRL_PIN(111, "SDC2_CLK"),
- PINCTRL_PIN(112, "SDC2_CMD"),
- PINCTRL_PIN(113, "SDC2_DATA"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "SDC1_CLK"),
+ PINCTRL_PIN(115, "SDC1_CMD"),
+ PINCTRL_PIN(116, "SDC1_DATA"),
+ PINCTRL_PIN(117, "SDC2_CLK"),
+ PINCTRL_PIN(118, "SDC2_CMD"),
+ PINCTRL_PIN(119, "SDC2_DATA"),
+ PINCTRL_PIN(120, "SDC1_RCLK"),
};
#define DECLARE_MSM_GPIO_PINS(pin) \
@@ -322,88 +329,101 @@ DECLARE_MSM_GPIO_PINS(107);
DECLARE_MSM_GPIO_PINS(108);
DECLARE_MSM_GPIO_PINS(109);
DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
-static const unsigned int sdc2_clk_pins[] = { 111 };
-static const unsigned int sdc2_cmd_pins[] = { 112 };
-static const unsigned int sdc2_data_pins[] = { 113 };
+static const unsigned int sdc1_clk_pins[] = { 114 };
+static const unsigned int sdc1_cmd_pins[] = { 115 };
+static const unsigned int sdc1_data_pins[] = { 116 };
+static const unsigned int sdc2_clk_pins[] = { 117 };
+static const unsigned int sdc2_cmd_pins[] = { 118 };
+static const unsigned int sdc2_data_pins[] = { 119 };
+static const unsigned int sdc1_rclk_pins[] = { 120 };
enum msmfalcon_functions {
msm_mux_blsp_spi1,
msm_mux_gpio,
+ msm_mux_blsp_uim1,
msm_mux_tgu_ch0,
- msm_mux_tgu_ch1,
+ msm_mux_qdss_gpio4,
+ msm_mux_atest_gpsadc1,
msm_mux_blsp_uart1,
+ msm_mux_SMB_STAT,
+ msm_mux_phase_flag14,
+ msm_mux_blsp_i2c2,
+ msm_mux_phase_flag31,
msm_mux_blsp_spi3,
msm_mux_wlan1_adc1,
msm_mux_atest_usb13,
- msm_mux_bimc_dte1,
- msm_mux_wlan1_adc0,
- msm_mux_atest_usb12,
- msm_mux_bimc_dte0,
+ msm_mux_tgu_ch1,
+ msm_mux_qdss_gpio5,
+ msm_mux_atest_gpsadc0,
msm_mux_blsp_i2c1,
- msm_mux_blsp_uim1,
msm_mux_ddr_bist,
msm_mux_atest_tsens2,
msm_mux_atest_usb1,
msm_mux_blsp_spi2,
- msm_mux_phase_flag3,
- msm_mux_phase_flag14,
- msm_mux_blsp_i2c2,
msm_mux_blsp_uim2,
- msm_mux_phase_flag31,
+ msm_mux_phase_flag3,
+ msm_mux_bimc_dte1,
+ msm_mux_wlan1_adc0,
+ msm_mux_atest_usb12,
+ msm_mux_bimc_dte0,
msm_mux_blsp_i2c3,
- msm_mux_atest_gpsadc1,
msm_mux_wlan2_adc1,
msm_mux_atest_usb11,
msm_mux_dbg_out,
- msm_mux_atest_gpsadc0,
msm_mux_wlan2_adc0,
msm_mux_atest_usb10,
+ msm_mux_RCM_MARKER,
msm_mux_blsp_spi4,
msm_mux_pri_mi2s,
msm_mux_phase_flag26,
- msm_mux_qdss_gpio4,
+ msm_mux_qdss_cti,
+ msm_mux_DP_HOT,
msm_mux_pri_mi2s_ws,
msm_mux_phase_flag27,
- msm_mux_qdss_gpio5,
msm_mux_blsp_i2c4,
msm_mux_phase_flag28,
msm_mux_blsp_uart5,
msm_mux_blsp_spi5,
+ msm_mux_blsp_uim5,
msm_mux_phase_flag5,
msm_mux_blsp_i2c5,
- msm_mux_blsp_uim5,
msm_mux_blsp_spi6,
msm_mux_blsp_uart2,
- msm_mux_qdss_cti,
- msm_mux_sec_mi2s,
- msm_mux_sndwire_clk,
- msm_mux_phase_flag17,
- msm_mux_vsense_clkout,
- msm_mux_sndwire_data,
- msm_mux_phase_flag18,
- msm_mux_blsp_i2c7,
- msm_mux_wsa_en1,
- msm_mux_phase_flag19,
+ msm_mux_blsp_uim6,
msm_mux_phase_flag11,
msm_mux_vsense_data0,
msm_mux_blsp_i2c6,
- msm_mux_blsp_uim6,
msm_mux_phase_flag12,
msm_mux_vsense_data1,
msm_mux_phase_flag13,
msm_mux_vsense_mode,
msm_mux_blsp_spi7,
msm_mux_BLSP_UART,
+ msm_mux_sec_mi2s,
+ msm_mux_sndwire_clk,
+ msm_mux_phase_flag17,
+ msm_mux_vsense_clkout,
+ msm_mux_sndwire_data,
+ msm_mux_phase_flag18,
+ msm_mux_WSA_SPKR,
+ msm_mux_blsp_i2c7,
+ msm_mux_phase_flag19,
msm_mux_vfr_1,
- msm_mux_wsa_en2,
msm_mux_phase_flag20,
+ msm_mux_NFC_INT,
msm_mux_blsp_spi,
msm_mux_m_voc,
msm_mux_phase_flag21,
+ msm_mux_NFC_EN,
msm_mux_phase_flag22,
+ msm_mux_NFC_DWL,
msm_mux_BLSP_I2C,
msm_mux_phase_flag23,
+ msm_mux_NFC_ESE,
msm_mux_pwr_modem,
msm_mux_phase_flag24,
msm_mux_qdss_gpio,
@@ -419,88 +439,92 @@ enum msmfalcon_functions {
msm_mux_qspi_data2,
msm_mux_jitter_bist,
msm_mux_qdss_gpio3,
+ msm_mux_qdss_gpio7,
+ msm_mux_FL_R3LED,
+ msm_mux_CCI_TIMER0,
+ msm_mux_FL_STROBE,
+ msm_mux_CCI_TIMER1,
+ msm_mux_CAM_LDO1,
+ msm_mux_mdss_vsync0,
+ msm_mux_mdss_vsync1,
+ msm_mux_mdss_vsync2,
+ msm_mux_mdss_vsync3,
+ msm_mux_qdss_gpio9,
+ msm_mux_CAM_IRQ,
+ msm_mux_atest_usb2,
msm_mux_cci_i2c,
msm_mux_pll_bypassnl,
msm_mux_atest_tsens,
+ msm_mux_atest_usb21,
msm_mux_pll_reset,
- msm_mux_qdss_gpio9,
- msm_mux_CAM_IRQ,
+ msm_mux_atest_usb23,
+ msm_mux_qdss_gpio6,
msm_mux_CCI_TIMER3,
msm_mux_CCI_ASYNC,
msm_mux_qspi_cs,
msm_mux_qdss_gpio10,
- msm_mux_CAM4_STANDBY,
+ msm_mux_CAM3_STANDBY,
msm_mux_CCI_TIMER4,
msm_mux_qdss_gpio11,
- msm_mux_bt_reset,
+ msm_mux_CAM_LDO2,
msm_mux_cci_async,
msm_mux_qdss_gpio12,
- msm_mux_CAM1_RST,
- msm_mux_qdss_gpio6,
- msm_mux_qdss_gpio7,
- msm_mux_FL_FRONT,
- msm_mux_CCI_TIMER0,
- msm_mux_qdss_gpio8,
- msm_mux_FL_STROBE,
- msm_mux_CCI_TIMER1,
- msm_mux_LASER_CE,
- msm_mux_mdss_vsync0,
- msm_mux_mdss_vsync1,
- msm_mux_mdss_vsync2,
- msm_mux_mdss_vsync3,
+ msm_mux_CAM0_RST,
msm_mux_qdss_gpio13,
- msm_mux_CAM2_RST,
+ msm_mux_CAM1_RST,
msm_mux_qspi_clk,
msm_mux_phase_flag30,
msm_mux_qdss_gpio14,
- msm_mux_CAM3_RST,
msm_mux_qspi_resetn,
msm_mux_phase_flag1,
msm_mux_qdss_gpio15,
- msm_mux_CAM1_STANDBY,
+ msm_mux_CAM0_STANDBY,
msm_mux_phase_flag2,
- msm_mux_CAM2_STANDBY,
+ msm_mux_CAM1_STANDBY,
msm_mux_phase_flag9,
- msm_mux_CAM3_STANDBY,
+ msm_mux_CAM2_STANDBY,
msm_mux_qspi_data3,
msm_mux_phase_flag15,
- msm_mux_CAM4_RST,
+ msm_mux_qdss_gpio8,
+ msm_mux_CAM3_RST,
msm_mux_CCI_TIMER2,
msm_mux_phase_flag16,
+ msm_mux_LCD0_RESET,
msm_mux_phase_flag6,
- msm_mux_RCM_MARKER2,
+ msm_mux_SD_CARD,
msm_mux_phase_flag29,
- msm_mux_SS_SWITCH,
+ msm_mux_DP_EN,
msm_mux_phase_flag25,
+ msm_mux_USBC_ORIENTATION,
msm_mux_phase_flag10,
+ msm_mux_atest_usb20,
msm_mux_gcc_gp1,
msm_mux_phase_flag4,
- msm_mux_USB_DIR,
+ msm_mux_atest_usb22,
msm_mux_USB_PHY,
msm_mux_gcc_gp2,
msm_mux_atest_char,
msm_mux_mdp_vsync,
msm_mux_gcc_gp3,
msm_mux_atest_char3,
- msm_mux_Lcd_mode,
- msm_mux_EDP_HOT,
+ msm_mux_FORCE_TOUCH,
msm_mux_cri_trng0,
msm_mux_atest_char2,
msm_mux_cri_trng1,
msm_mux_atest_char1,
+ msm_mux_AUDIO_USBC,
msm_mux_audio_ref,
msm_mux_MDP_VSYNC,
msm_mux_cri_trng,
msm_mux_atest_char0,
msm_mux_US_EURO,
- msm_mux_KEY_FOCUS,
- msm_mux_NAV_PPS,
+ msm_mux_LCD_BACKLIGHT,
msm_mux_blsp_spi8,
msm_mux_sp_cmu,
- msm_mux_SLT_PWR,
+ msm_mux_NAV_PPS,
+ msm_mux_GPS_TX,
msm_mux_adsp_ext,
msm_mux_TS_RESET,
- msm_mux_TS_INT,
msm_mux_ssc_irq,
msm_mux_isense_dbg,
msm_mux_phase_flag0,
@@ -508,8 +532,10 @@ enum msmfalcon_functions {
msm_mux_phase_flag8,
msm_mux_tsense_pwm1,
msm_mux_tsense_pwm2,
+ msm_mux_SENSOR_RST,
+ msm_mux_WMSS_RESETN,
msm_mux_HAPTICS_PWM,
- msm_mux_wmss_reset,
+ msm_mux_GPS_eLNA,
msm_mux_mss_lte,
msm_mux_uim2_data,
msm_mux_uim2_clk,
@@ -521,12 +547,12 @@ enum msmfalcon_functions {
msm_mux_uim1_present,
msm_mux_uim_batt,
msm_mux_pa_indicator,
- msm_mux_ssbi_gnss,
msm_mux_ldo_en,
msm_mux_ldo_update,
msm_mux_qlink_request,
msm_mux_qlink_enable,
msm_mux_prng_rosc,
+ msm_mux_LCD_PWR,
msm_mux_NA,
};
@@ -534,27 +560,44 @@ static const char * const blsp_spi1_groups[] = {
"gpio0", "gpio1", "gpio2", "gpio3", "gpio46",
};
static const char * const gpio_groups[] = {
- "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
- "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
- "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
- "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
- "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
- "gpio36", "gpio37", "gpio38", "gpio39", "gpio53", "gpio57", "gpio59",
- "gpio61", "gpio62", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
- "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
- "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
- "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
- "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio6", "gpio7", "gpio8",
+ "gpio9", "gpio10", "gpio11", "gpio14", "gpio15", "gpio16", "gpio17",
+ "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23", "gpio24",
+ "gpio25", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", "gpio37",
+ "gpio38", "gpio39", "gpio57", "gpio58", "gpio59", "gpio61", "gpio65",
+ "gpio81", "gpio82", "gpio83", "gpio84", "gpio85", "gpio86", "gpio87",
+ "gpio88", "gpio89", "gpio90", "gpio91", "gpio92", "gpio93", "gpio94",
+ "gpio95", "gpio96", "gpio97", "gpio98", "gpio99", "gpio100", "gpio101",
+ "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107",
+ "gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113",
+};
+static const char * const blsp_uim1_groups[] = {
+ "gpio0", "gpio1",
};
static const char * const tgu_ch0_groups[] = {
"gpio0",
};
-static const char * const tgu_ch1_groups[] = {
- "gpio1",
+static const char * const qdss_gpio4_groups[] = {
+ "gpio0", "gpio36",
+};
+static const char * const atest_gpsadc1_groups[] = {
+ "gpio0",
};
static const char * const blsp_uart1_groups[] = {
"gpio0", "gpio1", "gpio2", "gpio3",
};
+static const char * const SMB_STAT_groups[] = {
+ "gpio5",
+};
+static const char * const phase_flag14_groups[] = {
+ "gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio6", "gpio7",
+};
+static const char * const phase_flag31_groups[] = {
+ "gpio6",
+};
static const char * const blsp_spi3_groups[] = {
"gpio8", "gpio9", "gpio10", "gpio11", "gpio30", "gpio65",
};
@@ -564,24 +607,18 @@ static const char * const wlan1_adc1_groups[] = {
static const char * const atest_usb13_groups[] = {
"gpio8",
};
-static const char * const bimc_dte1_groups[] = {
- "gpio8", "gpio10",
-};
-static const char * const wlan1_adc0_groups[] = {
- "gpio9",
+static const char * const tgu_ch1_groups[] = {
+ "gpio1",
};
-static const char * const atest_usb12_groups[] = {
- "gpio9",
+static const char * const qdss_gpio5_groups[] = {
+ "gpio1", "gpio37",
};
-static const char * const bimc_dte0_groups[] = {
- "gpio9", "gpio11",
+static const char * const atest_gpsadc0_groups[] = {
+ "gpio1",
};
static const char * const blsp_i2c1_groups[] = {
"gpio2", "gpio3",
};
-static const char * const blsp_uim1_groups[] = {
- "gpio2", "gpio3",
-};
static const char * const ddr_bist_groups[] = {
"gpio3", "gpio8", "gpio9", "gpio10",
};
@@ -594,27 +631,27 @@ static const char * const atest_usb1_groups[] = {
static const char * const blsp_spi2_groups[] = {
"gpio4", "gpio5", "gpio6", "gpio7",
};
+static const char * const blsp_uim2_groups[] = {
+ "gpio4", "gpio5",
+};
static const char * const phase_flag3_groups[] = {
"gpio4",
};
-static const char * const phase_flag14_groups[] = {
- "gpio5",
+static const char * const bimc_dte1_groups[] = {
+ "gpio8", "gpio10",
};
-static const char * const blsp_i2c2_groups[] = {
- "gpio6", "gpio7",
+static const char * const wlan1_adc0_groups[] = {
+ "gpio9",
};
-static const char * const blsp_uim2_groups[] = {
- "gpio6", "gpio7",
+static const char * const atest_usb12_groups[] = {
+ "gpio9",
};
-static const char * const phase_flag31_groups[] = {
- "gpio6",
+static const char * const bimc_dte0_groups[] = {
+ "gpio9", "gpio11",
};
static const char * const blsp_i2c3_groups[] = {
"gpio10", "gpio11",
};
-static const char * const atest_gpsadc1_groups[] = {
- "gpio10",
-};
static const char * const wlan2_adc1_groups[] = {
"gpio10",
};
@@ -624,15 +661,15 @@ static const char * const atest_usb11_groups[] = {
static const char * const dbg_out_groups[] = {
"gpio11",
};
-static const char * const atest_gpsadc0_groups[] = {
- "gpio11",
-};
static const char * const wlan2_adc0_groups[] = {
"gpio11",
};
static const char * const atest_usb10_groups[] = {
"gpio11",
};
+static const char * const RCM_MARKER_groups[] = {
+ "gpio12", "gpio13",
+};
static const char * const blsp_spi4_groups[] = {
"gpio12", "gpio13", "gpio14", "gpio15",
};
@@ -642,8 +679,12 @@ static const char * const pri_mi2s_groups[] = {
static const char * const phase_flag26_groups[] = {
"gpio12",
};
-static const char * const qdss_gpio4_groups[] = {
- "gpio12", "gpio36",
+static const char * const qdss_cti_groups[] = {
+ "gpio12", "gpio13", "gpio21", "gpio49", "gpio50", "gpio53", "gpio55",
+ "gpio66",
+};
+static const char * const DP_HOT_groups[] = {
+ "gpio13",
};
static const char * const pri_mi2s_ws_groups[] = {
"gpio13",
@@ -651,9 +692,6 @@ static const char * const pri_mi2s_ws_groups[] = {
static const char * const phase_flag27_groups[] = {
"gpio13",
};
-static const char * const qdss_gpio5_groups[] = {
- "gpio13", "gpio37",
-};
static const char * const blsp_i2c4_groups[] = {
"gpio14", "gpio15",
};
@@ -666,51 +704,23 @@ static const char * const blsp_uart5_groups[] = {
static const char * const blsp_spi5_groups[] = {
"gpio16", "gpio17", "gpio18", "gpio19",
};
+static const char * const blsp_uim5_groups[] = {
+ "gpio16", "gpio17",
+};
static const char * const phase_flag5_groups[] = {
"gpio17",
};
static const char * const blsp_i2c5_groups[] = {
"gpio18", "gpio19",
};
-static const char * const blsp_uim5_groups[] = {
- "gpio18", "gpio19",
-};
static const char * const blsp_spi6_groups[] = {
"gpio20", "gpio21", "gpio22", "gpio23",
};
static const char * const blsp_uart2_groups[] = {
"gpio20", "gpio21", "gpio22", "gpio23",
};
-static const char * const qdss_cti_groups[] = {
- "gpio20", "gpio21", "gpio24", "gpio25", "gpio26", "gpio49", "gpio50",
- "gpio61",
-};
-static const char * const sec_mi2s_groups[] = {
- "gpio24", "gpio25", "gpio26", "gpio27", "gpio62",
-};
-static const char * const sndwire_clk_groups[] = {
- "gpio24",
-};
-static const char * const phase_flag17_groups[] = {
- "gpio24",
-};
-static const char * const vsense_clkout_groups[] = {
- "gpio24",
-};
-static const char * const sndwire_data_groups[] = {
- "gpio25",
-};
-static const char * const phase_flag18_groups[] = {
- "gpio25",
-};
-static const char * const blsp_i2c7_groups[] = {
- "gpio26", "gpio27",
-};
-static const char * const wsa_en1_groups[] = {
- "gpio26",
-};
-static const char * const phase_flag19_groups[] = {
- "gpio26",
+static const char * const blsp_uim6_groups[] = {
+ "gpio20", "gpio21",
};
static const char * const phase_flag11_groups[] = {
"gpio21",
@@ -721,9 +731,6 @@ static const char * const vsense_data0_groups[] = {
static const char * const blsp_i2c6_groups[] = {
"gpio22", "gpio23",
};
-static const char * const blsp_uim6_groups[] = {
- "gpio22", "gpio23",
-};
static const char * const phase_flag12_groups[] = {
"gpio22",
};
@@ -743,15 +750,42 @@ static const char * const BLSP_UART_groups[] = {
"gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30",
"gpio31",
};
-static const char * const vfr_1_groups[] = {
- "gpio27",
+static const char * const sec_mi2s_groups[] = {
+ "gpio24", "gpio25", "gpio26", "gpio27", "gpio62",
+};
+static const char * const sndwire_clk_groups[] = {
+ "gpio24",
+};
+static const char * const phase_flag17_groups[] = {
+ "gpio24",
+};
+static const char * const vsense_clkout_groups[] = {
+ "gpio24",
+};
+static const char * const sndwire_data_groups[] = {
+ "gpio25",
+};
+static const char * const phase_flag18_groups[] = {
+ "gpio25",
+};
+static const char * const WSA_SPKR_groups[] = {
+ "gpio26", "gpio27",
};
-static const char * const wsa_en2_groups[] = {
+static const char * const blsp_i2c7_groups[] = {
+ "gpio26", "gpio27",
+};
+static const char * const phase_flag19_groups[] = {
+ "gpio26",
+};
+static const char * const vfr_1_groups[] = {
"gpio27",
};
static const char * const phase_flag20_groups[] = {
"gpio27",
};
+static const char * const NFC_INT_groups[] = {
+ "gpio28",
+};
static const char * const blsp_spi_groups[] = {
"gpio28", "gpio29", "gpio30", "gpio31", "gpio40", "gpio41", "gpio44",
"gpio52",
@@ -762,15 +796,24 @@ static const char * const m_voc_groups[] = {
static const char * const phase_flag21_groups[] = {
"gpio28",
};
+static const char * const NFC_EN_groups[] = {
+ "gpio29",
+};
static const char * const phase_flag22_groups[] = {
"gpio29",
};
+static const char * const NFC_DWL_groups[] = {
+ "gpio30",
+};
static const char * const BLSP_I2C_groups[] = {
"gpio30", "gpio31", "gpio44", "gpio52",
};
static const char * const phase_flag23_groups[] = {
"gpio30",
};
+static const char * const NFC_ESE_groups[] = {
+ "gpio31",
+};
static const char * const pwr_modem_groups[] = {
"gpio31",
};
@@ -778,7 +821,7 @@ static const char * const phase_flag24_groups[] = {
"gpio31",
};
static const char * const qdss_gpio_groups[] = {
- "gpio31", "gpio41", "gpio68", "gpio69",
+ "gpio31", "gpio52", "gpio68", "gpio69",
};
static const char * const cam_mclk_groups[] = {
"gpio32", "gpio33", "gpio34", "gpio35",
@@ -787,7 +830,7 @@ static const char * const pwr_nav_groups[] = {
"gpio32",
};
static const char * const qdss_gpio0_groups[] = {
- "gpio32", "gpio62",
+ "gpio32", "gpio67",
};
static const char * const qspi_data0_groups[] = {
"gpio33",
@@ -814,7 +857,46 @@ static const char * const jitter_bist_groups[] = {
"gpio35",
};
static const char * const qdss_gpio3_groups[] = {
- "gpio35", "gpio65",
+ "gpio35", "gpio56",
+};
+static const char * const qdss_gpio7_groups[] = {
+ "gpio39", "gpio71",
+};
+static const char * const FL_R3LED_groups[] = {
+ "gpio40",
+};
+static const char * const CCI_TIMER0_groups[] = {
+ "gpio40",
+};
+static const char * const FL_STROBE_groups[] = {
+ "gpio41",
+};
+static const char * const CCI_TIMER1_groups[] = {
+ "gpio41",
+};
+static const char * const CAM_LDO1_groups[] = {
+ "gpio42",
+};
+static const char * const mdss_vsync0_groups[] = {
+ "gpio42",
+};
+static const char * const mdss_vsync1_groups[] = {
+ "gpio42",
+};
+static const char * const mdss_vsync2_groups[] = {
+ "gpio42",
+};
+static const char * const mdss_vsync3_groups[] = {
+ "gpio42",
+};
+static const char * const qdss_gpio9_groups[] = {
+ "gpio42", "gpio76",
+};
+static const char * const CAM_IRQ_groups[] = {
+ "gpio43",
+};
+static const char * const atest_usb2_groups[] = {
+ "gpio35",
};
static const char * const cci_i2c_groups[] = {
"gpio36", "gpio37", "gpio38", "gpio39",
@@ -825,14 +907,17 @@ static const char * const pll_bypassnl_groups[] = {
static const char * const atest_tsens_groups[] = {
"gpio36",
};
+static const char * const atest_usb21_groups[] = {
+ "gpio36",
+};
static const char * const pll_reset_groups[] = {
"gpio37",
};
-static const char * const qdss_gpio9_groups[] = {
- "gpio42", "gpio76",
+static const char * const atest_usb23_groups[] = {
+ "gpio37",
};
-static const char * const CAM_IRQ_groups[] = {
- "gpio43",
+static const char * const qdss_gpio6_groups[] = {
+ "gpio38", "gpio70",
};
static const char * const CCI_TIMER3_groups[] = {
"gpio43",
@@ -846,7 +931,7 @@ static const char * const qspi_cs_groups[] = {
static const char * const qdss_gpio10_groups[] = {
"gpio43", "gpio77",
};
-static const char * const CAM4_STANDBY_groups[] = {
+static const char * const CAM3_STANDBY_groups[] = {
"gpio44",
};
static const char * const CCI_TIMER4_groups[] = {
@@ -855,7 +940,7 @@ static const char * const CCI_TIMER4_groups[] = {
static const char * const qdss_gpio11_groups[] = {
"gpio44", "gpio79",
};
-static const char * const bt_reset_groups[] = {
+static const char * const CAM_LDO2_groups[] = {
"gpio45",
};
static const char * const cci_async_groups[] = {
@@ -864,49 +949,13 @@ static const char * const cci_async_groups[] = {
static const char * const qdss_gpio12_groups[] = {
"gpio45", "gpio80",
};
-static const char * const CAM1_RST_groups[] = {
+static const char * const CAM0_RST_groups[] = {
"gpio46",
};
-static const char * const qdss_gpio6_groups[] = {
- "gpio38", "gpio70",
-};
-static const char * const qdss_gpio7_groups[] = {
- "gpio39", "gpio71",
-};
-static const char * const FL_FRONT_groups[] = {
- "gpio40",
-};
-static const char * const CCI_TIMER0_groups[] = {
- "gpio40",
-};
-static const char * const qdss_gpio8_groups[] = {
- "gpio40", "gpio75",
-};
-static const char * const FL_STROBE_groups[] = {
- "gpio41",
-};
-static const char * const CCI_TIMER1_groups[] = {
- "gpio41",
-};
-static const char * const LASER_CE_groups[] = {
- "gpio42",
-};
-static const char * const mdss_vsync0_groups[] = {
- "gpio42",
-};
-static const char * const mdss_vsync1_groups[] = {
- "gpio42",
-};
-static const char * const mdss_vsync2_groups[] = {
- "gpio42",
-};
-static const char * const mdss_vsync3_groups[] = {
- "gpio42",
-};
static const char * const qdss_gpio13_groups[] = {
"gpio46", "gpio78",
};
-static const char * const CAM2_RST_groups[] = {
+static const char * const CAM1_RST_groups[] = {
"gpio47",
};
static const char * const qspi_clk_groups[] = {
@@ -918,9 +967,6 @@ static const char * const phase_flag30_groups[] = {
static const char * const qdss_gpio14_groups[] = {
"gpio47", "gpio72",
};
-static const char * const CAM3_RST_groups[] = {
- "gpio48",
-};
static const char * const qspi_resetn_groups[] = {
"gpio48",
};
@@ -930,19 +976,19 @@ static const char * const phase_flag1_groups[] = {
static const char * const qdss_gpio15_groups[] = {
"gpio48", "gpio73",
};
-static const char * const CAM1_STANDBY_groups[] = {
+static const char * const CAM0_STANDBY_groups[] = {
"gpio49",
};
static const char * const phase_flag2_groups[] = {
"gpio49",
};
-static const char * const CAM2_STANDBY_groups[] = {
+static const char * const CAM1_STANDBY_groups[] = {
"gpio50",
};
static const char * const phase_flag9_groups[] = {
"gpio50",
};
-static const char * const CAM3_STANDBY_groups[] = {
+static const char * const CAM2_STANDBY_groups[] = {
"gpio51",
};
static const char * const qspi_data3_groups[] = {
@@ -951,7 +997,10 @@ static const char * const qspi_data3_groups[] = {
static const char * const phase_flag15_groups[] = {
"gpio51",
};
-static const char * const CAM4_RST_groups[] = {
+static const char * const qdss_gpio8_groups[] = {
+ "gpio51", "gpio75",
+};
+static const char * const CAM3_RST_groups[] = {
"gpio52",
};
static const char * const CCI_TIMER2_groups[] = {
@@ -960,32 +1009,41 @@ static const char * const CCI_TIMER2_groups[] = {
static const char * const phase_flag16_groups[] = {
"gpio52",
};
+static const char * const LCD0_RESET_groups[] = {
+ "gpio53",
+};
static const char * const phase_flag6_groups[] = {
"gpio53",
};
-static const char * const RCM_MARKER2_groups[] = {
+static const char * const SD_CARD_groups[] = {
"gpio54",
};
static const char * const phase_flag29_groups[] = {
"gpio54",
};
-static const char * const SS_SWITCH_groups[] = {
- "gpio55", "gpio56",
+static const char * const DP_EN_groups[] = {
+ "gpio55",
};
static const char * const phase_flag25_groups[] = {
"gpio55",
};
+static const char * const USBC_ORIENTATION_groups[] = {
+ "gpio56",
+};
static const char * const phase_flag10_groups[] = {
"gpio56",
};
+static const char * const atest_usb20_groups[] = {
+ "gpio56",
+};
static const char * const gcc_gp1_groups[] = {
"gpio57", "gpio78",
};
static const char * const phase_flag4_groups[] = {
"gpio57",
};
-static const char * const USB_DIR_groups[] = {
- "gpio58",
+static const char * const atest_usb22_groups[] = {
+ "gpio57",
};
static const char * const USB_PHY_groups[] = {
"gpio58",
@@ -1005,11 +1063,8 @@ static const char * const gcc_gp3_groups[] = {
static const char * const atest_char3_groups[] = {
"gpio59",
};
-static const char * const Lcd_mode_groups[] = {
- "gpio60",
-};
-static const char * const EDP_HOT_groups[] = {
- "gpio60",
+static const char * const FORCE_TOUCH_groups[] = {
+ "gpio60", "gpio73",
};
static const char * const cri_trng0_groups[] = {
"gpio60",
@@ -1023,6 +1078,9 @@ static const char * const cri_trng1_groups[] = {
static const char * const atest_char1_groups[] = {
"gpio61",
};
+static const char * const AUDIO_USBC_groups[] = {
+ "gpio62",
+};
static const char * const audio_ref_groups[] = {
"gpio62",
};
@@ -1038,20 +1096,20 @@ static const char * const atest_char0_groups[] = {
static const char * const US_EURO_groups[] = {
"gpio63",
};
-static const char * const KEY_FOCUS_groups[] = {
+static const char * const LCD_BACKLIGHT_groups[] = {
"gpio64",
};
-static const char * const NAV_PPS_groups[] = {
- "gpio64", "gpio65", "gpio98", "gpio98",
-};
static const char * const blsp_spi8_groups[] = {
"gpio64", "gpio76",
};
static const char * const sp_cmu_groups[] = {
"gpio64",
};
-static const char * const SLT_PWR_groups[] = {
- "gpio65",
+static const char * const NAV_PPS_groups[] = {
+ "gpio65", "gpio65", "gpio80", "gpio80", "gpio98", "gpio98",
+};
+static const char * const GPS_TX_groups[] = {
+ "gpio65", "gpio80", "gpio98",
};
static const char * const adsp_ext_groups[] = {
"gpio65",
@@ -1059,12 +1117,9 @@ static const char * const adsp_ext_groups[] = {
static const char * const TS_RESET_groups[] = {
"gpio66",
};
-static const char * const TS_INT_groups[] = {
- "gpio67",
-};
static const char * const ssc_irq_groups[] = {
- "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio73", "gpio74",
- "gpio75", "gpio76", "gpio77",
+ "gpio67", "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio74",
+ "gpio75", "gpio76",
};
static const char * const isense_dbg_groups[] = {
"gpio68",
@@ -1084,12 +1139,18 @@ static const char * const tsense_pwm1_groups[] = {
static const char * const tsense_pwm2_groups[] = {
"gpio71",
};
-static const char * const HAPTICS_PWM_groups[] = {
+static const char * const SENSOR_RST_groups[] = {
+ "gpio77",
+};
+static const char * const WMSS_RESETN_groups[] = {
"gpio78",
};
-static const char * const wmss_reset_groups[] = {
+static const char * const HAPTICS_PWM_groups[] = {
"gpio79",
};
+static const char * const GPS_eLNA_groups[] = {
+ "gpio80",
+};
static const char * const mss_lte_groups[] = {
"gpio81", "gpio82",
};
@@ -1123,9 +1184,6 @@ static const char * const uim_batt_groups[] = {
static const char * const pa_indicator_groups[] = {
"gpio92",
};
-static const char * const ssbi_gnss_groups[] = {
- "gpio94",
-};
static const char * const ldo_en_groups[] = {
"gpio97",
};
@@ -1141,84 +1199,93 @@ static const char * const qlink_enable_groups[] = {
static const char * const prng_rosc_groups[] = {
"gpio102",
};
+static const char * const LCD_PWR_groups[] = {
+ "gpio113",
+};
static const struct msm_function msmfalcon_functions[] = {
FUNCTION(blsp_spi1),
FUNCTION(gpio),
+ FUNCTION(blsp_uim1),
FUNCTION(tgu_ch0),
- FUNCTION(tgu_ch1),
+ FUNCTION(qdss_gpio4),
+ FUNCTION(atest_gpsadc1),
FUNCTION(blsp_uart1),
+ FUNCTION(SMB_STAT),
+ FUNCTION(phase_flag14),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(phase_flag31),
FUNCTION(blsp_spi3),
FUNCTION(wlan1_adc1),
FUNCTION(atest_usb13),
- FUNCTION(bimc_dte1),
- FUNCTION(wlan1_adc0),
- FUNCTION(atest_usb12),
- FUNCTION(bimc_dte0),
+ FUNCTION(tgu_ch1),
+ FUNCTION(qdss_gpio5),
+ FUNCTION(atest_gpsadc0),
FUNCTION(blsp_i2c1),
- FUNCTION(blsp_uim1),
FUNCTION(ddr_bist),
FUNCTION(atest_tsens2),
FUNCTION(atest_usb1),
FUNCTION(blsp_spi2),
- FUNCTION(phase_flag3),
- FUNCTION(phase_flag14),
- FUNCTION(blsp_i2c2),
FUNCTION(blsp_uim2),
- FUNCTION(phase_flag31),
+ FUNCTION(phase_flag3),
+ FUNCTION(bimc_dte1),
+ FUNCTION(wlan1_adc0),
+ FUNCTION(atest_usb12),
+ FUNCTION(bimc_dte0),
FUNCTION(blsp_i2c3),
- FUNCTION(atest_gpsadc1),
FUNCTION(wlan2_adc1),
FUNCTION(atest_usb11),
FUNCTION(dbg_out),
- FUNCTION(atest_gpsadc0),
FUNCTION(wlan2_adc0),
FUNCTION(atest_usb10),
+ FUNCTION(RCM_MARKER),
FUNCTION(blsp_spi4),
FUNCTION(pri_mi2s),
FUNCTION(phase_flag26),
- FUNCTION(qdss_gpio4),
+ FUNCTION(qdss_cti),
+ FUNCTION(DP_HOT),
FUNCTION(pri_mi2s_ws),
FUNCTION(phase_flag27),
- FUNCTION(qdss_gpio5),
FUNCTION(blsp_i2c4),
FUNCTION(phase_flag28),
FUNCTION(blsp_uart5),
FUNCTION(blsp_spi5),
+ FUNCTION(blsp_uim5),
FUNCTION(phase_flag5),
FUNCTION(blsp_i2c5),
- FUNCTION(blsp_uim5),
FUNCTION(blsp_spi6),
FUNCTION(blsp_uart2),
- FUNCTION(qdss_cti),
- FUNCTION(sec_mi2s),
- FUNCTION(sndwire_clk),
- FUNCTION(phase_flag17),
- FUNCTION(vsense_clkout),
- FUNCTION(sndwire_data),
- FUNCTION(phase_flag18),
- FUNCTION(blsp_i2c7),
- FUNCTION(wsa_en1),
- FUNCTION(phase_flag19),
+ FUNCTION(blsp_uim6),
FUNCTION(phase_flag11),
FUNCTION(vsense_data0),
FUNCTION(blsp_i2c6),
- FUNCTION(blsp_uim6),
FUNCTION(phase_flag12),
FUNCTION(vsense_data1),
FUNCTION(phase_flag13),
FUNCTION(vsense_mode),
FUNCTION(blsp_spi7),
FUNCTION(BLSP_UART),
+ FUNCTION(sec_mi2s),
+ FUNCTION(sndwire_clk),
+ FUNCTION(phase_flag17),
+ FUNCTION(vsense_clkout),
+ FUNCTION(sndwire_data),
+ FUNCTION(phase_flag18),
+ FUNCTION(WSA_SPKR),
+ FUNCTION(blsp_i2c7),
+ FUNCTION(phase_flag19),
FUNCTION(vfr_1),
- FUNCTION(wsa_en2),
FUNCTION(phase_flag20),
+ FUNCTION(NFC_INT),
FUNCTION(blsp_spi),
FUNCTION(m_voc),
FUNCTION(phase_flag21),
+ FUNCTION(NFC_EN),
FUNCTION(phase_flag22),
+ FUNCTION(NFC_DWL),
FUNCTION(BLSP_I2C),
FUNCTION(phase_flag23),
+ FUNCTION(NFC_ESE),
FUNCTION(pwr_modem),
FUNCTION(phase_flag24),
FUNCTION(qdss_gpio),
@@ -1234,88 +1301,92 @@ static const struct msm_function msmfalcon_functions[] = {
FUNCTION(qspi_data2),
FUNCTION(jitter_bist),
FUNCTION(qdss_gpio3),
+ FUNCTION(qdss_gpio7),
+ FUNCTION(FL_R3LED),
+ FUNCTION(CCI_TIMER0),
+ FUNCTION(FL_STROBE),
+ FUNCTION(CCI_TIMER1),
+ FUNCTION(CAM_LDO1),
+ FUNCTION(mdss_vsync0),
+ FUNCTION(mdss_vsync1),
+ FUNCTION(mdss_vsync2),
+ FUNCTION(mdss_vsync3),
+ FUNCTION(qdss_gpio9),
+ FUNCTION(CAM_IRQ),
+ FUNCTION(atest_usb2),
FUNCTION(cci_i2c),
FUNCTION(pll_bypassnl),
FUNCTION(atest_tsens),
+ FUNCTION(atest_usb21),
FUNCTION(pll_reset),
- FUNCTION(qdss_gpio9),
- FUNCTION(CAM_IRQ),
+ FUNCTION(atest_usb23),
+ FUNCTION(qdss_gpio6),
FUNCTION(CCI_TIMER3),
FUNCTION(CCI_ASYNC),
FUNCTION(qspi_cs),
FUNCTION(qdss_gpio10),
- FUNCTION(CAM4_STANDBY),
+ FUNCTION(CAM3_STANDBY),
FUNCTION(CCI_TIMER4),
FUNCTION(qdss_gpio11),
- FUNCTION(bt_reset),
+ FUNCTION(CAM_LDO2),
FUNCTION(cci_async),
FUNCTION(qdss_gpio12),
- FUNCTION(CAM1_RST),
- FUNCTION(qdss_gpio6),
- FUNCTION(qdss_gpio7),
- FUNCTION(FL_FRONT),
- FUNCTION(CCI_TIMER0),
- FUNCTION(qdss_gpio8),
- FUNCTION(FL_STROBE),
- FUNCTION(CCI_TIMER1),
- FUNCTION(LASER_CE),
- FUNCTION(mdss_vsync0),
- FUNCTION(mdss_vsync1),
- FUNCTION(mdss_vsync2),
- FUNCTION(mdss_vsync3),
+ FUNCTION(CAM0_RST),
FUNCTION(qdss_gpio13),
- FUNCTION(CAM2_RST),
+ FUNCTION(CAM1_RST),
FUNCTION(qspi_clk),
FUNCTION(phase_flag30),
FUNCTION(qdss_gpio14),
- FUNCTION(CAM3_RST),
FUNCTION(qspi_resetn),
FUNCTION(phase_flag1),
FUNCTION(qdss_gpio15),
- FUNCTION(CAM1_STANDBY),
+ FUNCTION(CAM0_STANDBY),
FUNCTION(phase_flag2),
- FUNCTION(CAM2_STANDBY),
+ FUNCTION(CAM1_STANDBY),
FUNCTION(phase_flag9),
- FUNCTION(CAM3_STANDBY),
+ FUNCTION(CAM2_STANDBY),
FUNCTION(qspi_data3),
FUNCTION(phase_flag15),
- FUNCTION(CAM4_RST),
+ FUNCTION(qdss_gpio8),
+ FUNCTION(CAM3_RST),
FUNCTION(CCI_TIMER2),
FUNCTION(phase_flag16),
+ FUNCTION(LCD0_RESET),
FUNCTION(phase_flag6),
- FUNCTION(RCM_MARKER2),
+ FUNCTION(SD_CARD),
FUNCTION(phase_flag29),
- FUNCTION(SS_SWITCH),
+ FUNCTION(DP_EN),
FUNCTION(phase_flag25),
+ FUNCTION(USBC_ORIENTATION),
FUNCTION(phase_flag10),
+ FUNCTION(atest_usb20),
FUNCTION(gcc_gp1),
FUNCTION(phase_flag4),
- FUNCTION(USB_DIR),
+ FUNCTION(atest_usb22),
FUNCTION(USB_PHY),
FUNCTION(gcc_gp2),
FUNCTION(atest_char),
FUNCTION(mdp_vsync),
FUNCTION(gcc_gp3),
FUNCTION(atest_char3),
- FUNCTION(Lcd_mode),
- FUNCTION(EDP_HOT),
+ FUNCTION(FORCE_TOUCH),
FUNCTION(cri_trng0),
FUNCTION(atest_char2),
FUNCTION(cri_trng1),
FUNCTION(atest_char1),
+ FUNCTION(AUDIO_USBC),
FUNCTION(audio_ref),
FUNCTION(MDP_VSYNC),
FUNCTION(cri_trng),
FUNCTION(atest_char0),
FUNCTION(US_EURO),
- FUNCTION(KEY_FOCUS),
- FUNCTION(NAV_PPS),
+ FUNCTION(LCD_BACKLIGHT),
FUNCTION(blsp_spi8),
FUNCTION(sp_cmu),
- FUNCTION(SLT_PWR),
+ FUNCTION(NAV_PPS),
+ FUNCTION(GPS_TX),
FUNCTION(adsp_ext),
FUNCTION(TS_RESET),
- FUNCTION(TS_INT),
FUNCTION(ssc_irq),
FUNCTION(isense_dbg),
FUNCTION(phase_flag0),
@@ -1323,8 +1394,10 @@ static const struct msm_function msmfalcon_functions[] = {
FUNCTION(phase_flag8),
FUNCTION(tsense_pwm1),
FUNCTION(tsense_pwm2),
+ FUNCTION(SENSOR_RST),
+ FUNCTION(WMSS_RESETN),
FUNCTION(HAPTICS_PWM),
- FUNCTION(wmss_reset),
+ FUNCTION(GPS_eLNA),
FUNCTION(mss_lte),
FUNCTION(uim2_data),
FUNCTION(uim2_clk),
@@ -1336,153 +1409,155 @@ static const struct msm_function msmfalcon_functions[] = {
FUNCTION(uim1_present),
FUNCTION(uim_batt),
FUNCTION(pa_indicator),
- FUNCTION(ssbi_gnss),
FUNCTION(ldo_en),
FUNCTION(ldo_update),
FUNCTION(qlink_request),
FUNCTION(qlink_enable),
FUNCTION(prng_rosc),
+ FUNCTION(LCD_PWR),
};
static const struct msm_pingroup msmfalcon_groups[] = {
- PINGROUP(0, SOUTH, blsp_spi1, blsp_uart1, tgu_ch0, NA, NA, NA, NA, NA,
- NA),
- PINGROUP(1, SOUTH, blsp_spi1, blsp_uart1, tgu_ch1, NA, NA, NA, NA, NA,
- NA),
- PINGROUP(2, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, blsp_uim1, NA, NA,
- NA, NA, NA),
- PINGROUP(3, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, blsp_uim1,
- ddr_bist, NA, atest_tsens2, atest_usb1, NA),
- PINGROUP(4, WEST, blsp_spi2, phase_flag3, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(5, WEST, blsp_spi2, phase_flag14, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(6, WEST, blsp_spi2, blsp_i2c2, blsp_uim2, phase_flag31, NA,
- NA, NA, NA, NA),
- PINGROUP(7, WEST, blsp_spi2, blsp_i2c2, blsp_uim2, NA, NA, NA, NA, NA,
- NA),
- PINGROUP(8, WEST, blsp_spi3, ddr_bist, NA, NA, wlan1_adc1, atest_usb13,
- bimc_dte1, NA, NA),
- PINGROUP(9, WEST, blsp_spi3, ddr_bist, NA, NA, wlan1_adc0, atest_usb12,
- bimc_dte0, NA, NA),
- PINGROUP(10, WEST, blsp_spi3, blsp_i2c3, ddr_bist, NA, atest_gpsadc1,
- wlan2_adc1, atest_usb11, bimc_dte1, NA),
- PINGROUP(11, WEST, blsp_spi3, blsp_i2c3, dbg_out, atest_gpsadc0,
- wlan2_adc0, atest_usb10, bimc_dte0, NA, NA),
- PINGROUP(12, SOUTH, blsp_spi4, pri_mi2s, phase_flag26, qdss_gpio4, NA,
+ PINGROUP(0, SOUTH, blsp_spi1, blsp_uart1, blsp_uim1, tgu_ch0, NA, NA,
+ qdss_gpio4, atest_gpsadc1, NA),
+ PINGROUP(1, SOUTH, blsp_spi1, blsp_uart1, blsp_uim1, tgu_ch1, NA, NA,
+ qdss_gpio5, atest_gpsadc0, NA),
+ PINGROUP(2, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(3, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, ddr_bist, NA, NA,
+ atest_tsens2, atest_usb1, NA),
+ PINGROUP(4, NORTH, blsp_spi2, blsp_uim2, NA, phase_flag3, NA, NA, NA,
+ NA, NA),
+ PINGROUP(5, SOUTH, blsp_spi2, blsp_uim2, NA, phase_flag14, NA, NA, NA,
+ NA, NA),
+ PINGROUP(6, SOUTH, blsp_spi2, blsp_i2c2, NA, phase_flag31, NA, NA, NA,
+ NA, NA),
+ PINGROUP(7, SOUTH, blsp_spi2, blsp_i2c2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(8, NORTH, blsp_spi3, ddr_bist, NA, NA, NA, wlan1_adc1,
+ atest_usb13, bimc_dte1, NA),
+ PINGROUP(9, NORTH, blsp_spi3, ddr_bist, NA, NA, NA, wlan1_adc0,
+ atest_usb12, bimc_dte0, NA),
+ PINGROUP(10, NORTH, blsp_spi3, blsp_i2c3, ddr_bist, NA, NA, wlan2_adc1,
+ atest_usb11, bimc_dte1, NA),
+ PINGROUP(11, NORTH, blsp_spi3, blsp_i2c3, NA, dbg_out, wlan2_adc0,
+ atest_usb10, bimc_dte0, NA, NA),
+ PINGROUP(12, NORTH, blsp_spi4, pri_mi2s, NA, phase_flag26, qdss_cti,
NA, NA, NA, NA),
- PINGROUP(13, SOUTH, blsp_spi4, pri_mi2s_ws, NA, phase_flag27,
- qdss_gpio5, NA, NA, NA, NA),
- PINGROUP(14, SOUTH, blsp_spi4, blsp_i2c4, pri_mi2s, phase_flag28, NA,
+ PINGROUP(13, NORTH, blsp_spi4, DP_HOT, pri_mi2s_ws, NA, NA,
+ phase_flag27, qdss_cti, NA, NA),
+ PINGROUP(14, NORTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, phase_flag28,
NA, NA, NA, NA),
- PINGROUP(15, SOUTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, NA, NA, NA, NA,
+ PINGROUP(15, NORTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, NA, NA, NA, NA,
NA),
- PINGROUP(16, WEST, blsp_uart5, blsp_spi5, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(17, WEST, blsp_uart5, blsp_spi5, phase_flag5, NA, NA, NA, NA,
+ PINGROUP(16, CENTER, blsp_uart5, blsp_spi5, blsp_uim5, NA, NA, NA, NA,
NA, NA),
- PINGROUP(18, WEST, blsp_uart5, blsp_spi5, blsp_i2c5, blsp_uim5, NA, NA,
- NA, NA, NA),
- PINGROUP(19, WEST, blsp_uart5, blsp_spi5, blsp_i2c5, blsp_uim5, NA, NA,
- NA, NA, NA),
- PINGROUP(20, WEST, blsp_spi6, blsp_uart2, NA, qdss_cti, NA, NA, NA, NA,
- NA),
- PINGROUP(21, WEST, blsp_spi6, blsp_uart2, phase_flag11, qdss_cti,
- vsense_data0, NA, NA, NA, NA),
- PINGROUP(22, WEST, blsp_spi6, blsp_uart2, blsp_i2c6, blsp_uim6,
+ PINGROUP(17, CENTER, blsp_uart5, blsp_spi5, blsp_uim5, NA, phase_flag5,
+ NA, NA, NA, NA),
+ PINGROUP(18, CENTER, blsp_uart5, blsp_spi5, blsp_i2c5, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(19, CENTER, blsp_uart5, blsp_spi5, blsp_i2c5, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(20, SOUTH, blsp_spi6, blsp_uart2, blsp_uim6, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(21, SOUTH, blsp_spi6, blsp_uart2, blsp_uim6, NA, phase_flag11,
+ qdss_cti, vsense_data0, NA, NA),
+ PINGROUP(22, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA,
phase_flag12, vsense_data1, NA, NA, NA),
- PINGROUP(23, WEST, blsp_spi6, blsp_uart2, blsp_i2c6, blsp_uim6,
+ PINGROUP(23, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA,
phase_flag13, vsense_mode, NA, NA, NA),
- PINGROUP(24, WEST, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_clk, NA,
- phase_flag17, qdss_cti, vsense_clkout, NA),
- PINGROUP(25, WEST, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_data, NA,
- phase_flag18, qdss_cti, NA, NA),
- PINGROUP(26, WEST, blsp_spi7, BLSP_UART, blsp_i2c7, sec_mi2s, wsa_en1,
- phase_flag19, qdss_cti, NA, NA),
- PINGROUP(27, WEST, blsp_spi7, BLSP_UART, blsp_i2c7, vfr_1, sec_mi2s,
- wsa_en2, phase_flag20, NA, NA),
- PINGROUP(28, SOUTH, blsp_spi, BLSP_UART, m_voc, phase_flag21, NA, NA,
+ PINGROUP(24, NORTH, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_clk, NA,
+ NA, phase_flag17, vsense_clkout, NA),
+ PINGROUP(25, NORTH, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_data, NA,
+ NA, phase_flag18, NA, NA),
+ PINGROUP(26, NORTH, blsp_spi7, BLSP_UART, blsp_i2c7, sec_mi2s, NA,
+ phase_flag19, NA, NA, NA),
+ PINGROUP(27, NORTH, blsp_spi7, BLSP_UART, blsp_i2c7, vfr_1, sec_mi2s,
+ NA, phase_flag20, NA, NA),
+ PINGROUP(28, CENTER, blsp_spi, BLSP_UART, m_voc, NA, phase_flag21, NA,
NA, NA, NA),
- PINGROUP(29, SOUTH, blsp_spi, BLSP_UART, NA, phase_flag22, NA, NA, NA,
+ PINGROUP(29, CENTER, blsp_spi, BLSP_UART, NA, NA, phase_flag22, NA, NA,
NA, NA),
- PINGROUP(30, SOUTH, blsp_spi, BLSP_UART, BLSP_I2C, blsp_spi3,
- phase_flag23, NA, NA, NA, NA),
- PINGROUP(31, SOUTH, blsp_spi, BLSP_UART, BLSP_I2C, pwr_modem,
- phase_flag24, qdss_gpio, NA, NA, NA),
- PINGROUP(32, SOUTH, cam_mclk, pwr_nav, NA, qdss_gpio0, NA, NA, NA, NA,
+ PINGROUP(30, CENTER, blsp_spi, BLSP_UART, BLSP_I2C, blsp_spi3, NA,
+ phase_flag23, NA, NA, NA),
+ PINGROUP(31, CENTER, blsp_spi, BLSP_UART, BLSP_I2C, pwr_modem, NA,
+ phase_flag24, qdss_gpio, NA, NA),
+ PINGROUP(32, SOUTH, cam_mclk, pwr_nav, NA, NA, qdss_gpio0, NA, NA, NA,
NA),
- PINGROUP(33, SOUTH, cam_mclk, qspi_data0, pwr_crypto, NA, qdss_gpio1,
- NA, NA, NA, NA),
- PINGROUP(34, SOUTH, cam_mclk, qspi_data1, agera_pll, NA, qdss_gpio2,
- NA, NA, NA, NA),
- PINGROUP(35, SOUTH, cam_mclk, qspi_data2, jitter_bist, NA, qdss_gpio3,
- NA, NA, NA, NA),
- PINGROUP(36, SOUTH, cci_i2c, pll_bypassnl, agera_pll, NA, qdss_gpio4,
- atest_tsens, NA, NA, NA),
- PINGROUP(37, SOUTH, cci_i2c, pll_reset, NA, qdss_gpio5, NA, NA, NA, NA,
- NA),
- PINGROUP(38, SOUTH, cci_i2c, NA, qdss_gpio6, NA, NA, NA, NA, NA, NA),
- PINGROUP(39, SOUTH, cci_i2c, NA, qdss_gpio7, NA, NA, NA, NA, NA, NA),
- PINGROUP(40, SOUTH, CCI_TIMER0, NA, blsp_spi, NA, qdss_gpio8, NA, NA,
- NA, NA),
- PINGROUP(41, SOUTH, CCI_TIMER1, NA, blsp_spi, NA, qdss_gpio, NA, NA,
- NA, NA),
+ PINGROUP(33, SOUTH, cam_mclk, qspi_data0, pwr_crypto, NA, NA,
+ qdss_gpio1, NA, NA, NA),
+ PINGROUP(34, SOUTH, cam_mclk, qspi_data1, agera_pll, NA, NA,
+ qdss_gpio2, NA, NA, NA),
+ PINGROUP(35, SOUTH, cam_mclk, qspi_data2, jitter_bist, NA, NA,
+ qdss_gpio3, NA, atest_usb2, NA),
+ PINGROUP(36, SOUTH, cci_i2c, pll_bypassnl, agera_pll, NA, NA,
+ qdss_gpio4, atest_tsens, atest_usb21, NA),
+ PINGROUP(37, SOUTH, cci_i2c, pll_reset, NA, NA, qdss_gpio5,
+ atest_usb23, NA, NA, NA),
+ PINGROUP(38, SOUTH, cci_i2c, NA, NA, qdss_gpio6, NA, NA, NA, NA, NA),
+ PINGROUP(39, SOUTH, cci_i2c, NA, NA, qdss_gpio7, NA, NA, NA, NA, NA),
+ PINGROUP(40, SOUTH, CCI_TIMER0, NA, blsp_spi, NA, NA, NA, NA, NA, NA),
+ PINGROUP(41, SOUTH, CCI_TIMER1, NA, blsp_spi, NA, NA, NA, NA, NA, NA),
PINGROUP(42, SOUTH, mdss_vsync0, mdss_vsync1, mdss_vsync2, mdss_vsync3,
- NA, qdss_gpio9, NA, NA, NA),
- PINGROUP(43, SOUTH, CCI_TIMER3, CCI_ASYNC, qspi_cs, NA, qdss_gpio10,
- NA, NA, NA, NA),
- PINGROUP(44, SOUTH, CCI_TIMER4, CCI_ASYNC, blsp_spi, BLSP_I2C, NA,
- qdss_gpio11, NA, NA, NA),
- PINGROUP(45, SOUTH, cci_async, NA, qdss_gpio12, NA, NA, NA, NA, NA, NA),
- PINGROUP(46, SOUTH, blsp_spi1, NA, qdss_gpio13, NA, NA, NA, NA, NA, NA),
- PINGROUP(47, SOUTH, qspi_clk, phase_flag30, qdss_gpio14, NA, NA, NA,
- NA, NA, NA),
- PINGROUP(48, SOUTH, qspi_resetn, phase_flag1, qdss_gpio15, NA, NA, NA,
+ NA, NA, qdss_gpio9, NA, NA),
+ PINGROUP(43, SOUTH, CCI_TIMER3, CCI_ASYNC, qspi_cs, NA, NA,
+ qdss_gpio10, NA, NA, NA),
+ PINGROUP(44, SOUTH, CCI_TIMER4, CCI_ASYNC, blsp_spi, BLSP_I2C, NA, NA,
+ qdss_gpio11, NA, NA),
+ PINGROUP(45, SOUTH, cci_async, NA, NA, qdss_gpio12, NA, NA, NA, NA, NA),
+ PINGROUP(46, SOUTH, blsp_spi1, NA, NA, qdss_gpio13, NA, NA, NA, NA, NA),
+ PINGROUP(47, SOUTH, qspi_clk, NA, phase_flag30, qdss_gpio14, NA, NA,
NA, NA, NA),
- PINGROUP(49, SOUTH, phase_flag2, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(50, SOUTH, qspi_cs, phase_flag9, qdss_cti, NA, NA, NA, NA, NA,
+ PINGROUP(48, SOUTH, NA, phase_flag1, qdss_gpio15, NA, NA, NA, NA, NA,
NA),
- PINGROUP(51, SOUTH, qspi_data3, phase_flag15, NA, NA, NA, NA, NA, NA,
- NA),
- PINGROUP(52, EAST, CCI_TIMER2, blsp_spi, BLSP_I2C, phase_flag16, NA,
- NA, NA, NA, NA),
- PINGROUP(53, EAST, phase_flag6, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(54, EAST, NA, phase_flag29, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(55, WEST, phase_flag25, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(56, WEST, phase_flag10, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(57, SOUTH, gcc_gp1, phase_flag4, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(58, SOUTH, USB_PHY, gcc_gp2, NA, atest_char, NA, NA, NA, NA,
+ PINGROUP(49, SOUTH, NA, phase_flag2, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(50, SOUTH, qspi_cs, NA, phase_flag9, qdss_cti, NA, NA, NA, NA,
NA),
- PINGROUP(59, EAST, mdp_vsync, gcc_gp3, NA, atest_char3, NA, NA, NA, NA,
- NA),
- PINGROUP(60, EAST, EDP_HOT, cri_trng0, NA, atest_char2, NA, NA, NA, NA,
- NA),
- PINGROUP(61, EAST, pri_mi2s, cri_trng1, NA, qdss_cti, atest_char1, NA,
+ PINGROUP(51, SOUTH, qspi_data3, NA, phase_flag15, qdss_gpio8, NA, NA,
+ NA, NA, NA),
+ PINGROUP(52, SOUTH, CCI_TIMER2, blsp_spi, BLSP_I2C, NA, phase_flag16,
+ qdss_gpio, NA, NA, NA),
+ PINGROUP(53, NORTH, NA, phase_flag6, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(54, NORTH, NA, NA, phase_flag29, NA, NA, NA, NA, NA, NA),
+ PINGROUP(55, SOUTH, NA, phase_flag25, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(56, SOUTH, NA, phase_flag10, qdss_gpio3, NA, atest_usb20, NA,
NA, NA, NA),
- PINGROUP(62, SOUTH, sec_mi2s, audio_ref, MDP_VSYNC, cri_trng, NA,
- qdss_gpio0, atest_char0, NA, NA),
- PINGROUP(63, SOUTH, NA, NA, qdss_gpio1, NA, NA, NA, NA, NA, NA),
- PINGROUP(64, SOUTH, NAV_PPS, blsp_spi8, sp_cmu, NA, qdss_gpio2, NA, NA,
+ PINGROUP(57, SOUTH, gcc_gp1, NA, phase_flag4, atest_usb22, NA, NA, NA,
NA, NA),
- PINGROUP(65, SOUTH, NAV_PPS, blsp_spi3, NA, adsp_ext, NA, qdss_gpio3,
+ PINGROUP(58, SOUTH, USB_PHY, gcc_gp2, NA, NA, atest_char, NA, NA, NA,
+ NA),
+ PINGROUP(59, NORTH, mdp_vsync, gcc_gp3, NA, NA, atest_char3, NA, NA,
+ NA, NA),
+ PINGROUP(60, NORTH, cri_trng0, NA, NA, atest_char2, NA, NA, NA, NA, NA),
+ PINGROUP(61, NORTH, pri_mi2s, cri_trng1, NA, NA, atest_char1, NA, NA,
+ NA, NA),
+ PINGROUP(62, NORTH, sec_mi2s, audio_ref, MDP_VSYNC, cri_trng, NA, NA,
+ atest_char0, NA, NA),
+ PINGROUP(63, NORTH, NA, NA, NA, qdss_gpio1, NA, NA, NA, NA, NA),
+ PINGROUP(64, SOUTH, blsp_spi8, sp_cmu, NA, NA, qdss_gpio2, NA, NA, NA,
+ NA),
+ PINGROUP(65, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, blsp_spi3, adsp_ext,
NA, NA, NA),
- PINGROUP(66, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(67, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(68, SOUTH, isense_dbg, phase_flag0, qdss_gpio, NA, NA, NA, NA,
+ PINGROUP(66, NORTH, NA, NA, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(67, NORTH, NA, NA, qdss_gpio0, NA, NA, NA, NA, NA, NA),
+ PINGROUP(68, NORTH, isense_dbg, NA, phase_flag0, qdss_gpio, NA, NA, NA,
NA, NA),
- PINGROUP(69, SOUTH, phase_flag7, qdss_gpio, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(70, SOUTH, phase_flag8, qdss_gpio6, NA, NA, NA, NA, NA, NA,
+ PINGROUP(69, NORTH, NA, phase_flag7, qdss_gpio, NA, NA, NA, NA, NA, NA),
+ PINGROUP(70, NORTH, NA, phase_flag8, qdss_gpio6, NA, NA, NA, NA, NA,
NA),
- PINGROUP(71, SOUTH, NA, qdss_gpio7, tsense_pwm1, tsense_pwm2, NA, NA,
+ PINGROUP(71, NORTH, NA, NA, qdss_gpio7, tsense_pwm1, tsense_pwm2, NA,
NA, NA, NA),
- PINGROUP(72, SOUTH, qdss_gpio14, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(73, SOUTH, NA, qdss_gpio15, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(74, SOUTH, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(75, WEST, NA, qdss_gpio8, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(76, WEST, blsp_spi8, NA, NA, qdss_gpio9, NA, NA, NA, NA, NA),
- PINGROUP(77, SOUTH, NA, qdss_gpio10, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(78, SOUTH, gcc_gp1, qdss_gpio13, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(79, SOUTH, NA, qdss_gpio11, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(80, SOUTH, NA, qdss_gpio12, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(81, SOUTH, mss_lte, gcc_gp2, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(82, SOUTH, mss_lte, NA, gcc_gp3, NA, NA, NA, NA, NA, NA),
+ PINGROUP(72, NORTH, NA, qdss_gpio14, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(73, NORTH, NA, NA, qdss_gpio15, NA, NA, NA, NA, NA, NA),
+ PINGROUP(74, NORTH, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(75, NORTH, NA, NA, qdss_gpio8, NA, NA, NA, NA, NA, NA),
+ PINGROUP(76, NORTH, blsp_spi8, NA, NA, NA, qdss_gpio9, NA, NA, NA, NA),
+ PINGROUP(77, NORTH, NA, NA, qdss_gpio10, NA, NA, NA, NA, NA, NA),
+ PINGROUP(78, NORTH, gcc_gp1, NA, qdss_gpio13, NA, NA, NA, NA, NA, NA),
+ PINGROUP(79, SOUTH, NA, NA, qdss_gpio11, NA, NA, NA, NA, NA, NA),
+ PINGROUP(80, SOUTH, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, qdss_gpio12, NA,
+ NA, NA),
+ PINGROUP(81, CENTER, mss_lte, gcc_gp2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(82, CENTER, mss_lte, gcc_gp3, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(83, SOUTH, uim2_data, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(84, SOUTH, uim2_clk, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(85, SOUTH, uim2_reset, NA, NA, NA, NA, NA, NA, NA, NA),
@@ -1494,12 +1569,12 @@ static const struct msm_pingroup msmfalcon_groups[] = {
PINGROUP(91, SOUTH, uim_batt, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(92, SOUTH, NA, NA, pa_indicator, NA, NA, NA, NA, NA, NA),
PINGROUP(93, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(94, SOUTH, NA, ssbi_gnss, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(94, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(95, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(96, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(97, SOUTH, NA, NA, ldo_en, NA, NA, NA, NA, NA, NA),
- PINGROUP(98, SOUTH, NA, NAV_PPS, NAV_PPS, ldo_update, NA, NA, NA, NA,
- NA),
+ PINGROUP(97, SOUTH, NA, ldo_en, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(98, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, ldo_update, NA, NA,
+ NA, NA),
PINGROUP(99, SOUTH, qlink_request, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(100, SOUTH, qlink_enable, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(101, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
@@ -1508,13 +1583,20 @@ static const struct msm_pingroup msmfalcon_groups[] = {
PINGROUP(104, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(105, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(106, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(107, EAST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(108, EAST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(109, EAST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- PINGROUP(110, EAST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
- SDC_QDSD_PINGROUP(sdc2_clk, 0x999000, 14, 6),
- SDC_QDSD_PINGROUP(sdc2_cmd, 0x999000, 11, 3),
- SDC_QDSD_PINGROUP(sdc2_data, 0x999000, 9, 0),
+ PINGROUP(107, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(108, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(109, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(110, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(111, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(112, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(113, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ SDC_QDSD_PINGROUP(sdc1_clk, 0x99a000, 13, 6),
+ SDC_QDSD_PINGROUP(sdc1_cmd, 0x99a000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc1_data, 0x99a000, 9, 0),
+ SDC_QDSD_PINGROUP(sdc2_clk, 0x99b000, 14, 6),
+ SDC_QDSD_PINGROUP(sdc2_cmd, 0x99b000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc2_data, 0x99b000, 9, 0),
+ SDC_QDSD_PINGROUP(sdc1_rclk, 0x99a000, 15, 0),
};
static const struct msm_pinctrl_soc_data msmfalcon_pinctrl = {
@@ -1524,7 +1606,7 @@ static const struct msm_pinctrl_soc_data msmfalcon_pinctrl = {
.nfunctions = ARRAY_SIZE(msmfalcon_functions),
.groups = msmfalcon_groups,
.ngroups = ARRAY_SIZE(msmfalcon_groups),
- .ngpios = 111,
+ .ngpios = 114,
};
static int msmfalcon_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 18ae7fa5454b..9c2697dde76d 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -114,7 +114,6 @@ config IPA3
Kernel and user-space processes can call the IPA driver
to configure IPA core.
-
config RMNET_IPA3
tristate "IPA3 RMNET WWAN Network Device"
depends on IPA3 && MSM_QMI_INTERFACE
@@ -124,6 +123,16 @@ config RMNET_IPA3
for RmNet Data Driver and also exchange of QMI messages between
A7 and Q6 IPA-driver.
+config IPA_UT
+ tristate "IPA Unit-Test Framework and Test Suites"
+ depends on IPA3 && DEBUG_FS
+ help
+ This Module implements IPA in-kernel test framework.
+ The framework supports defining and running tests, grouped
+ into suites according to the sub-unit of the IPA being tested.
+ The user interface to run and control the tests is debugfs file
+ system.
+
config SSM
tristate "QTI Secure Service Module"
depends on QSEECOM
diff --git a/drivers/platform/msm/gsi/gsi_dbg.c b/drivers/platform/msm/gsi/gsi_dbg.c
index bd8cdf3f9770..2ab8b79acc6d 100644
--- a/drivers/platform/msm/gsi/gsi_dbg.c
+++ b/drivers/platform/msm/gsi/gsi_dbg.c
@@ -653,11 +653,11 @@ static ssize_t gsi_rst_stats(struct file *file,
} else if (ch_id < 0 || ch_id >= GSI_MAX_CHAN ||
!gsi_ctx->chan[ch_id].allocated) {
goto error;
+ } else {
+ min = ch_id;
+ max = ch_id + 1;
}
- min = ch_id;
- max = ch_id + 1;
-
for (ch_id = min; ch_id < max; ch_id++)
memset(&gsi_ctx->chan[ch_id].stats, 0,
sizeof(gsi_ctx->chan[ch_id].stats));
diff --git a/drivers/platform/msm/ipa/Makefile b/drivers/platform/msm/ipa/Makefile
index 704dd0abfefa..15ed471f383c 100644
--- a/drivers/platform/msm/ipa/Makefile
+++ b/drivers/platform/msm/ipa/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_IPA) += ipa_v2/ ipa_clients/ ipa_common
obj-$(CONFIG_IPA3) += ipa_v3/ ipa_clients/ ipa_common
+obj-$(CONFIG_IPA_UT) += test/
ipa_common += ipa_api.o ipa_rm.o ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 09d1166e29a6..a08d157e2b0f 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -2533,6 +2533,50 @@ int ipa_stop_gsi_channel(u32 clnt_hdl)
}
EXPORT_SYMBOL(ipa_stop_gsi_channel);
+/**
+ * ipa_get_version_string() - Get string representation of IPA version
+ * @ver: IPA version
+ *
+ * Return: Constant string representation
+ */
+const char *ipa_get_version_string(enum ipa_hw_type ver)
+{
+ const char *str;
+
+ switch (ver) {
+ case IPA_HW_v1_0:
+ str = "1.0";
+ break;
+ case IPA_HW_v1_1:
+ str = "1.1";
+ break;
+ case IPA_HW_v2_0:
+ str = "2.0";
+ break;
+ case IPA_HW_v2_1:
+ str = "2.1";
+ break;
+ case IPA_HW_v2_5:
+ str = "2.5/2.6";
+ break;
+ case IPA_HW_v2_6L:
+ str = "2.6L";
+ break;
+ case IPA_HW_v3_0:
+ str = "3.0";
+ break;
+ case IPA_HW_v3_1:
+ str = "3.1";
+ break;
+ default:
+ str = "Invalid version";
+ break;
+ }
+
+ return str;
+}
+EXPORT_SYMBOL(ipa_get_version_string);
+
static struct of_device_id ipa_plat_drv_match[] = {
{ .compatible = "qcom,ipa", },
{ .compatible = "qcom,ipa-smmu-ap-cb", },
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 115348251d17..c5f75046cd2c 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -355,5 +355,6 @@ u8 *ipa_write_16(u16 hw, u8 *dest);
u8 *ipa_write_8(u8 b, u8 *dest);
u8 *ipa_pad_to_64(u8 *dest);
u8 *ipa_pad_to_32(u8 *dest);
+const char *ipa_get_version_string(enum ipa_hw_type ver);
#endif /* _IPA_COMMON_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 0bb863037772..005508fdcdc1 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -40,6 +40,8 @@
IPA_GENERIC_RX_BUFF_BASE_SZ) -\
IPA_GENERIC_RX_BUFF_BASE_SZ)
+#define IPA_RX_BUFF_CLIENT_HEADROOM 256
+
/* less 1 nominal MTU (1500 bytes) rounded to units of KB */
#define IPA_ADJUST_AGGR_BYTE_LIMIT(X) (((X) - IPA_MTU)/1000)
@@ -2288,6 +2290,21 @@ static void ipa_cleanup_rx(struct ipa_sys_context *sys)
}
}
+static struct sk_buff *ipa_skb_copy_for_client(struct sk_buff *skb, int len)
+{
+ struct sk_buff *skb2 = NULL;
+
+ skb2 = __dev_alloc_skb(len + IPA_RX_BUFF_CLIENT_HEADROOM, GFP_KERNEL);
+ if (likely(skb2)) {
+ /* Set the data pointer */
+ skb_reserve(skb2, IPA_RX_BUFF_CLIENT_HEADROOM);
+ memcpy(skb2->data, skb->data, len);
+ skb2->len = len;
+ skb_set_tail_pointer(skb2, len);
+ }
+
+ return skb2;
+}
static int ipa_lan_rx_pyld_hdlr(struct sk_buff *skb,
struct ipa_sys_context *sys)
@@ -2484,7 +2501,8 @@ begin:
sys->drop_packet = true;
}
- skb2 = skb_clone(skb, GFP_KERNEL);
+ skb2 = ipa_skb_copy_for_client(skb,
+ status->pkt_len + IPA_PKT_STATUS_SIZE);
if (likely(skb2)) {
if (skb->len < len + IPA_PKT_STATUS_SIZE) {
IPADBG("SPL skb len %d len %d\n",
@@ -2527,7 +2545,7 @@ begin:
IPA_PKT_STATUS_SIZE);
}
} else {
- IPAERR("fail to clone\n");
+ IPAERR("fail to alloc skb\n");
if (skb->len < len) {
sys->prev_skb = NULL;
sys->len_rem = len - skb->len +
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index c3c5ae38ec14..95ef9afbbd3e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -2131,6 +2131,12 @@ void ipa3_debugfs_remove(void)
debugfs_remove_recursive(dent);
}
+struct dentry *ipa_debugfs_get_root(void)
+{
+ return dent;
+}
+EXPORT_SYMBOL(ipa_debugfs_get_root);
+
#else /* !CONFIG_DEBUG_FS */
void ipa3_debugfs_init(void) {}
void ipa3_debugfs_remove(void) {}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 806510ea8867..a7587b2b9675 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -2012,4 +2012,5 @@ int ipa3_smmu_map_peer_buff(u64 iova, phys_addr_t phys_addr,
u32 size, bool map);
int ipa3_ntn_init(void);
int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats);
+struct dentry *ipa_debugfs_get_root(void);
#endif /* _IPA3_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index b89dcfe18925..395cf62c9728 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -41,8 +41,7 @@
#define IPA_TAG_SLEEP_MAX_USEC (2000)
#define IPA_FORCE_CLOSE_TAG_PROCESS_TIMEOUT (10 * HZ)
#define IPA_BCR_REG_VAL_v3_0 (0x00000001)
-#define IPA_BCR_REG_VAL_v3_1 (0x00000003)
-#define IPA_BCR_REG_VAL_v3_5_1 (0x0000003B)
+#define IPA_BCR_REG_VAL_v3_5 (0x0000003B)
#define IPA_AGGR_GRAN_MIN (1)
#define IPA_AGGR_GRAN_MAX (32)
#define IPA_EOT_COAL_GRAN_MIN (1)
@@ -859,13 +858,12 @@ int ipa3_init_hw(void)
switch (ipa3_ctx->ipa_hw_type) {
case IPA_HW_v3_0:
- val = IPA_BCR_REG_VAL_v3_0;
- break;
case IPA_HW_v3_1:
- val = IPA_BCR_REG_VAL_v3_1;
+ val = IPA_BCR_REG_VAL_v3_0;
break;
+ case IPA_HW_v3_5:
case IPA_HW_v3_5_1:
- val = IPA_BCR_REG_VAL_v3_5_1;
+ val = IPA_BCR_REG_VAL_v3_5;
break;
default:
IPAERR("unknown HW type in dts\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index 6c4d14b093c3..bcd2cb3bfd7a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -535,6 +535,11 @@ static int ipahal_imm_cmd_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
for (j = 0; j < IPA_IMM_CMD_MAX ; j++) {
@@ -901,6 +906,11 @@ static int ipahal_pkt_status_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
/*
* Since structure alignment is implementation dependent,
* add test to avoid different and incompatible data layouts.
@@ -1269,6 +1279,12 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base,
goto bail_free_ctx;
}
+ if (ipa_hw_type >= IPA_HW_MAX) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ result = -EINVAL;
+ goto bail_free_ctx;
+ }
+
if (!base) {
IPAHAL_ERR("invalid memory io mapping addr\n");
result = -EINVAL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index c47d353d9658..a3345d7ac305 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -1066,6 +1066,11 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
for (j = 0; j < IPA_REG_MAX ; j++) {
diff --git a/drivers/platform/msm/ipa/test/Makefile b/drivers/platform/msm/ipa/test/Makefile
new file mode 100644
index 000000000000..62bb9a783c89
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IPA_UT) += ipa_ut_mod.o
+ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o
diff --git a/drivers/platform/msm/ipa/test/ipa_test_example.c b/drivers/platform/msm/ipa/test/ipa_test_example.c
new file mode 100644
index 000000000000..0313375ec3d3
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_test_example.c
@@ -0,0 +1,99 @@
+/* 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.
+ */
+
+#include "ipa_ut_framework.h"
+
+/**
+ * Example IPA Unit-test suite
+ * To be a reference for writing new suites and tests.
+ * This suite is also used as unit-test for the testing framework itself.
+ * Structure:
+ * 1- Define the setup and teardown functions
+ * Not Mandatory. Null may be used as well
+ * 2- For each test, define its Run() function
+ * 3- Use IPA_UT_DEFINE_SUITE_START() to start defining the suite
+ * 4- use IPA_UT_ADD_TEST() for adding tests within
+ * the suite definition block
+ * 5- IPA_UT_DEFINE_SUITE_END() close the suite definition
+ */
+
+static int ipa_test_example_dummy;
+
+static int ipa_test_example_suite_setup(void **ppriv)
+{
+ IPA_UT_DBG("Start Setup - set 0x1234F\n");
+
+ ipa_test_example_dummy = 0x1234F;
+ *ppriv = (void *)&ipa_test_example_dummy;
+
+ return 0;
+}
+
+static int ipa_test_example_teardown(void *priv)
+{
+ IPA_UT_DBG("Start Teardown\n");
+ IPA_UT_DBG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+
+ return 0;
+}
+
+static int ipa_test_example_test1(void *priv)
+{
+ IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+ ipa_test_example_dummy++;
+
+ return 0;
+}
+
+static int ipa_test_example_test2(void *priv)
+{
+ IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+ ipa_test_example_dummy++;
+
+ return 0;
+}
+
+static int ipa_test_example_test3(void *priv)
+{
+ IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+ ipa_test_example_dummy++;
+
+ return 0;
+}
+
+static int ipa_test_example_test4(void *priv)
+{
+ IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+ ipa_test_example_dummy++;
+
+ IPA_UT_TEST_FAIL_REPORT("failed on test");
+
+ return -EFAULT;
+}
+
+/* Suite definition block */
+IPA_UT_DEFINE_SUITE_START(example, "Example suite",
+ ipa_test_example_suite_setup, ipa_test_example_teardown)
+{
+ IPA_UT_ADD_TEST(test1, "This is test number 1",
+ ipa_test_example_test1, false, IPA_HW_v1_0, IPA_HW_MAX),
+
+ IPA_UT_ADD_TEST(test2, "This is test number 2",
+ ipa_test_example_test2, false, IPA_HW_v1_0, IPA_HW_MAX),
+
+ IPA_UT_ADD_TEST(test3, "This is test number 3",
+ ipa_test_example_test3, false, IPA_HW_v1_1, IPA_HW_v2_6),
+
+ IPA_UT_ADD_TEST(test4, "This is test number 4",
+ ipa_test_example_test4, false, IPA_HW_v1_1, IPA_HW_MAX),
+
+} IPA_UT_DEFINE_SUITE_END(example);
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_framework.c b/drivers/platform/msm/ipa/test/ipa_ut_framework.c
new file mode 100644
index 000000000000..8816fc37c2e2
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_ut_framework.c
@@ -0,0 +1,969 @@
+/* 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.
+ */
+
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/ipa.h>
+#include "../ipa_v3/ipa_i.h"
+#include "ipa_ut_framework.h"
+#include "ipa_ut_suite_list.h"
+#include "ipa_ut_i.h"
+
+
+#define IPA_UT_DEBUG_WRITE_BUF_SIZE 256
+#define IPA_UT_DEBUG_READ_BUF_SIZE 1024
+
+#define IPA_UT_READ_WRITE_DBG_FILE_MODE \
+ (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP)
+
+/**
+ * struct ipa_ut_context - I/S context
+ * @inited: Will wait till IPA is ready. Will create the enable file
+ * @enabled: All tests and suite debugfs files are created
+ * @lock: Lock for mutual exclustion
+ * @ipa_dbgfs_root: IPA root debugfs folder
+ * @test_dbgfs_root: UT root debugfs folder. Sub-folder of IPA root
+ * @test_dbgfs_suites: Suites root debugfs folder. Sub-folder of UT root
+ */
+struct ipa_ut_context {
+ bool inited;
+ bool enabled;
+ struct mutex lock;
+ struct dentry *ipa_dbgfs_root;
+ struct dentry *test_dbgfs_root;
+ struct dentry *test_dbgfs_suites;
+};
+
+static ssize_t ipa_ut_dbgfs_enable_read(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos);
+static ssize_t ipa_ut_dbgfs_enable_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos);
+static ssize_t ipa_ut_dbgfs_test_read(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos);
+static ssize_t ipa_ut_dbgfs_test_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos);
+static int ipa_ut_dbgfs_all_test_open(struct inode *inode,
+ struct file *filp);
+static int ipa_ut_dbgfs_regression_test_open(struct inode *inode,
+ struct file *filp);
+static ssize_t ipa_ut_dbgfs_meta_test_read(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos);
+static ssize_t ipa_ut_dbgfs_meta_test_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos);
+
+
+static const struct file_operations ipa_ut_dbgfs_enable_fops = {
+ .read = ipa_ut_dbgfs_enable_read,
+ .write = ipa_ut_dbgfs_enable_write,
+};
+static const struct file_operations ipa_ut_dbgfs_test_fops = {
+ .read = ipa_ut_dbgfs_test_read,
+ .write = ipa_ut_dbgfs_test_write,
+};
+static const struct file_operations ipa_ut_dbgfs_all_test_fops = {
+ .open = ipa_ut_dbgfs_all_test_open,
+ .read = ipa_ut_dbgfs_meta_test_read,
+ .write = ipa_ut_dbgfs_meta_test_write,
+};
+static const struct file_operations ipa_ut_dbgfs_regression_test_fops = {
+ .open = ipa_ut_dbgfs_regression_test_open,
+ .read = ipa_ut_dbgfs_meta_test_read,
+ .write = ipa_ut_dbgfs_meta_test_write,
+};
+
+static struct ipa_ut_context *ipa_ut_ctx;
+char *_IPA_UT_TEST_LOG_BUF_NAME;
+struct ipa_ut_tst_fail_report _IPA_UT_TEST_FAIL_REPORT_DATA;
+
+
+/**
+ * ipa_ut_show_suite_exec_summary() - Show tests run summary
+ * @suite: suite to print its running summary
+ *
+ * Print list of succeeded tests, failed tests and skipped tests
+ *
+ * Note: Assumes lock acquired
+ */
+static void ipa_ut_show_suite_exec_summary(const struct ipa_ut_suite *suite)
+{
+ int i;
+
+ IPA_UT_DBG("Entry\n");
+
+ ipa_assert_on(!suite);
+
+ pr_info("\n\n");
+ pr_info("\t Suite '%s' summary\n", suite->meta_data->name);
+ pr_info("===========================\n");
+ pr_info("Successful tests\n");
+ pr_info("----------------\n");
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (suite->tests[i].res != IPA_UT_TEST_RES_SUCCESS)
+ continue;
+ pr_info("\t%s\n", suite->tests[i].name);
+ }
+ pr_info("\nFailed tests\n");
+ pr_info("------------\n");
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (suite->tests[i].res != IPA_UT_TEST_RES_FAIL)
+ continue;
+ pr_info("\t%s\n", suite->tests[i].name);
+ }
+ pr_info("\nSkipped tests\n");
+ pr_info("-------------\n");
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (suite->tests[i].res != IPA_UT_TEST_RES_SKIP)
+ continue;
+ pr_info("\t%s\n", suite->tests[i].name);
+ }
+ pr_info("\n");
+}
+
+/**
+ * ipa_ut_dbgfs_meta_test_write() - Debugfs write func for a for a meta test
+ * @params: write fops
+ *
+ * Used to run all/regression tests in a suite
+ * Create log buffer that the test can use to store ongoing logs
+ * IPA clocks need to be voted.
+ * Run setup() once before running the tests and teardown() once after
+ * If no such call-backs then ignore it; if failed then fail the suite
+ * Print tests progress during running
+ * Test log and fail report will be showed only if the test failed.
+ * Finally show Summary of the suite tests running
+ *
+ * Note: If test supported IPA H/W version mismatch, skip it
+ * If a test lack run function, skip it
+ * If test doesn't belong to regression and it is regression run, skip it
+ * Note: Running mode: Do not stop running on failure
+ *
+ * Return: Negative in failure, given characters amount in success
+ */
+static ssize_t ipa_ut_dbgfs_meta_test_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct ipa_ut_suite *suite;
+ int i;
+ enum ipa_hw_type ipa_ver;
+ int rc = 0;
+ long meta_type;
+ bool tst_fail = false;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ suite = file->f_inode->i_private;
+ ipa_assert_on(!suite);
+ meta_type = (long)(file->private_data);
+ IPA_UT_DBG("Meta test type %ld\n", meta_type);
+
+ _IPA_UT_TEST_LOG_BUF_NAME = kzalloc(_IPA_UT_TEST_LOG_BUF_SIZE,
+ GFP_KERNEL);
+ if (!_IPA_UT_TEST_LOG_BUF_NAME) {
+ IPA_UT_ERR("failed to allocate %d bytes\n",
+ _IPA_UT_TEST_LOG_BUF_SIZE);
+ rc = -ENOMEM;
+ goto unlock_mutex;
+ }
+
+ if (!suite->tests_cnt || !suite->tests) {
+ pr_info("No tests for suite '%s'\n", suite->meta_data->name);
+ goto free_mem;
+ }
+
+ ipa_ver = ipa_get_hw_type();
+
+ IPA_ACTIVE_CLIENTS_INC_SPECIAL("IPA_UT");
+
+ if (suite->meta_data->setup) {
+ pr_info("*** Suite '%s': Run setup ***\n",
+ suite->meta_data->name);
+ rc = suite->meta_data->setup(&suite->meta_data->priv);
+ if (rc) {
+ IPA_UT_ERR("Setup failed for suite %s\n",
+ suite->meta_data->name);
+ rc = -EFAULT;
+ goto release_clock;
+ }
+ } else {
+ pr_info("*** Suite '%s': No Setup ***\n",
+ suite->meta_data->name);
+ }
+
+ pr_info("*** Suite '%s': Run %s tests ***\n\n",
+ suite->meta_data->name,
+ meta_type == IPA_UT_META_TEST_REGRESSION ? "regression" : "all"
+ );
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (meta_type == IPA_UT_META_TEST_REGRESSION &&
+ !suite->tests[i].run_in_regression) {
+ pr_info(
+ "*** Test '%s': Skip - Not in regression ***\n\n"
+ , suite->tests[i].name);
+ suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
+ continue;
+ }
+ if (suite->tests[i].min_ipa_hw_ver > ipa_ver ||
+ suite->tests[i].max_ipa_hw_ver < ipa_ver) {
+ pr_info(
+ "*** Test '%s': Skip - IPA VER mismatch ***\n\n"
+ , suite->tests[i].name);
+ suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
+ continue;
+ }
+ if (!suite->tests[i].run) {
+ pr_info(
+ "*** Test '%s': Skip - No Run function ***\n\n"
+ , suite->tests[i].name);
+ suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
+ continue;
+ }
+
+ _IPA_UT_TEST_LOG_BUF_NAME[0] = '\0';
+ _IPA_UT_TEST_FAIL_REPORT_DATA.valid = false;
+ pr_info("*** Test '%s': Running... ***\n",
+ suite->tests[i].name);
+ rc = suite->tests[i].run(suite->meta_data->priv);
+ if (rc) {
+ tst_fail = true;
+ suite->tests[i].res = IPA_UT_TEST_RES_FAIL;
+ pr_info("%s", _IPA_UT_TEST_LOG_BUF_NAME);
+ } else {
+ suite->tests[i].res = IPA_UT_TEST_RES_SUCCESS;
+ }
+
+ pr_info(">>>>>>**** TEST '%s': %s ****<<<<<<\n",
+ suite->tests[i].name, tst_fail ? "FAIL" : "SUCCESS");
+
+ if (tst_fail && _IPA_UT_TEST_FAIL_REPORT_DATA.valid) {
+ pr_info("*** FAIL INFO:\n");
+ pr_info("\tFILE = %s\n\tFUNC = %s()\n\tLINE = %d\n",
+ _IPA_UT_TEST_FAIL_REPORT_DATA.file,
+ _IPA_UT_TEST_FAIL_REPORT_DATA.func,
+ _IPA_UT_TEST_FAIL_REPORT_DATA.line);
+ pr_info("\t%s\n", _IPA_UT_TEST_FAIL_REPORT_DATA.info);
+ }
+
+ pr_info("\n");
+ }
+
+ if (suite->meta_data->teardown) {
+ pr_info("*** Suite '%s': Run Teardown ***\n",
+ suite->meta_data->name);
+ rc = suite->meta_data->teardown(suite->meta_data->priv);
+ if (rc) {
+ IPA_UT_ERR("Teardown failed for suite %s\n",
+ suite->meta_data->name);
+ rc = -EFAULT;
+ goto release_clock;
+ }
+ } else {
+ pr_info("*** Suite '%s': No Teardown ***\n",
+ suite->meta_data->name);
+ }
+
+ ipa_ut_show_suite_exec_summary(suite);
+
+release_clock:
+ IPA_ACTIVE_CLIENTS_DEC_SPECIAL("IPA_UT");
+free_mem:
+ kfree(_IPA_UT_TEST_LOG_BUF_NAME);
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ((!rc && !tst_fail) ? count : -EFAULT);
+}
+
+/**
+ * ipa_ut_dbgfs_meta_test_read() - Debugfs read func for a meta test
+ * @params: read fops
+ *
+ * Meta test, is a test that describes other test or bunch of tests.
+ * for example, the 'all' test. Running this test will run all
+ * the tests in the suite.
+ *
+ * Show information regard the suite. E.g. name and description
+ * If regression - List the regression tests names
+ *
+ * Return: Amount of characters written to user space buffer
+ */
+static ssize_t ipa_ut_dbgfs_meta_test_read(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos)
+{
+ char *buf;
+ struct ipa_ut_suite *suite;
+ int nbytes;
+ ssize_t cnt;
+ long meta_type;
+ int i;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ suite = file->f_inode->i_private;
+ ipa_assert_on(!suite);
+ meta_type = (long)(file->private_data);
+ IPA_UT_DBG("Meta test type %ld\n", meta_type);
+
+ buf = kmalloc(IPA_UT_DEBUG_READ_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ IPA_UT_ERR("failed to allocate %d bytes\n",
+ IPA_UT_DEBUG_READ_BUF_SIZE);
+ cnt = 0;
+ goto unlock_mutex;
+ }
+
+ if (meta_type == IPA_UT_META_TEST_ALL) {
+ nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
+ "\tMeta-test running all the tests in the suite:\n"
+ "\tSuite Name: %s\n"
+ "\tDescription: %s\n"
+ "\tNumber of test in suite: %zu\n",
+ suite->meta_data->name,
+ suite->meta_data->desc ?: "",
+ suite->tests_cnt);
+ } else {
+ nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
+ "\tMeta-test running regression tests in the suite:\n"
+ "\tSuite Name: %s\n"
+ "\tDescription: %s\n"
+ "\tRegression tests:\n",
+ suite->meta_data->name,
+ suite->meta_data->desc ?: "");
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (!suite->tests[i].run_in_regression)
+ continue;
+ nbytes += scnprintf(buf + nbytes,
+ IPA_UT_DEBUG_READ_BUF_SIZE - nbytes,
+ "\t\t%s\n", suite->tests[i].name);
+ }
+ }
+
+ cnt = simple_read_from_buffer(ubuf, count, ppos, buf, nbytes);
+ kfree(buf);
+
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return cnt;
+}
+
+/**
+ * ipa_ut_dbgfs_regression_test_open() - Debugfs open function for
+ * 'regression' tests
+ * @params: open fops
+ *
+ * Mark "Regression tests" for meta-tests later operations.
+ *
+ * Return: Zero (always success).
+ */
+static int ipa_ut_dbgfs_regression_test_open(struct inode *inode,
+ struct file *filp)
+{
+ IPA_UT_DBG("Entry\n");
+
+ filp->private_data = (void *)(IPA_UT_META_TEST_REGRESSION);
+
+ return 0;
+}
+
+/**
+ * ipa_ut_dbgfs_all_test_open() - Debugfs open function for 'all' tests
+ * @params: open fops
+ *
+ * Mark "All tests" for meta-tests later operations.
+ *
+ * Return: Zero (always success).
+ */
+static int ipa_ut_dbgfs_all_test_open(struct inode *inode,
+ struct file *filp)
+{
+ IPA_UT_DBG("Entry\n");
+
+ filp->private_data = (void *)(IPA_UT_META_TEST_ALL);
+
+ return 0;
+}
+
+/**
+ * ipa_ut_dbgfs_test_write() - Debugfs write function for a test
+ * @params: write fops
+ *
+ * Used to run a test.
+ * Create log buffer that the test can use to store ongoing logs
+ * IPA clocks need to be voted.
+ * Run setup() before the test and teardown() after the tests.
+ * If no such call-backs then ignore it; if failed then fail the test
+ * If all succeeds, no printing to user
+ * If failed, test logs and failure report will be printed to user
+ *
+ * Note: Test must has run function and it's supported IPA H/W version
+ * must be matching. Otherwise test will fail.
+ *
+ * Return: Negative in failure, given characters amount in success
+ */
+static ssize_t ipa_ut_dbgfs_test_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct ipa_ut_test *test;
+ struct ipa_ut_suite *suite;
+ bool tst_fail = false;
+ int rc = 0;
+ enum ipa_hw_type ipa_ver;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ test = file->f_inode->i_private;
+ ipa_assert_on(!test);
+
+ _IPA_UT_TEST_LOG_BUF_NAME = kzalloc(_IPA_UT_TEST_LOG_BUF_SIZE,
+ GFP_KERNEL);
+ if (!_IPA_UT_TEST_LOG_BUF_NAME) {
+ IPA_UT_ERR("failed to allocate %d bytes\n",
+ _IPA_UT_TEST_LOG_BUF_SIZE);
+ rc = -ENOMEM;
+ goto unlock_mutex;
+ }
+
+ if (!test->run) {
+ IPA_UT_ERR("*** Test %s - No run func ***\n",
+ test->name);
+ rc = -EFAULT;
+ goto free_mem;
+ }
+
+ ipa_ver = ipa_get_hw_type();
+ if (test->min_ipa_hw_ver > ipa_ver ||
+ test->max_ipa_hw_ver < ipa_ver) {
+ IPA_UT_ERR("Cannot run test %s on IPA HW Ver %s\n",
+ test->name, ipa_get_version_string(ipa_ver));
+ rc = -EFAULT;
+ goto free_mem;
+ }
+
+ IPA_ACTIVE_CLIENTS_INC_SPECIAL("IPA_UT");
+
+ suite = test->suite;
+ if (suite && suite->meta_data->setup) {
+ IPA_UT_DBG("*** Suite '%s': Run setup ***\n",
+ suite->meta_data->name);
+ rc = suite->meta_data->setup(&suite->meta_data->priv);
+ if (rc) {
+ IPA_UT_ERR("Setup failed for suite %s\n",
+ suite->meta_data->name);
+ rc = -EFAULT;
+ goto release_clock;
+ }
+ } else {
+ IPA_UT_DBG("*** Suite '%s': No Setup ***\n",
+ suite->meta_data->name);
+ }
+
+ IPA_UT_DBG("*** Test '%s': Running... ***\n", test->name);
+ _IPA_UT_TEST_FAIL_REPORT_DATA.valid = false;
+ rc = test->run(suite->meta_data->priv);
+ if (rc)
+ tst_fail = true;
+ IPA_UT_DBG("*** Test %s - ***\n", tst_fail ? "FAIL" : "SUCCESS");
+ if (tst_fail) {
+ pr_info("=================>>>>>>>>>>>\n");
+ pr_info("%s\n", _IPA_UT_TEST_LOG_BUF_NAME);
+ pr_info("**** TEST %s FAILED ****\n", test->name);
+ if (_IPA_UT_TEST_FAIL_REPORT_DATA.valid) {
+ pr_info("*** FAIL INFO:\n");
+ pr_info("\tFILE = %s\n\tFUNC = %s()\n\tLINE = %d\n",
+ _IPA_UT_TEST_FAIL_REPORT_DATA.file,
+ _IPA_UT_TEST_FAIL_REPORT_DATA.func,
+ _IPA_UT_TEST_FAIL_REPORT_DATA.line);
+ pr_info("\t%s\n", _IPA_UT_TEST_FAIL_REPORT_DATA.info);
+ }
+ pr_info("<<<<<<<<<<<=================\n");
+ }
+
+ if (suite && suite->meta_data->teardown) {
+ IPA_UT_DBG("*** Suite '%s': Run Teardown ***\n",
+ suite->meta_data->name);
+ rc = suite->meta_data->teardown(suite->meta_data->priv);
+ if (rc) {
+ IPA_UT_ERR("Teardown failed for suite %s\n",
+ suite->meta_data->name);
+ rc = -EFAULT;
+ goto release_clock;
+ }
+ } else {
+ IPA_UT_DBG("*** Suite '%s': No Teardown ***\n",
+ suite->meta_data->name);
+ }
+
+release_clock:
+ IPA_ACTIVE_CLIENTS_DEC_SPECIAL("IPA_UT");
+free_mem:
+ kfree(_IPA_UT_TEST_LOG_BUF_NAME);
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ((!rc && !tst_fail) ? count : -EFAULT);
+}
+
+/**
+ * ipa_ut_dbgfs_test_read() - Debugfs read function for a test
+ * @params: read fops
+ *
+ * print information regard the test. E.g. name and description
+ *
+ * Return: Amount of characters written to user space buffer
+ */
+static ssize_t ipa_ut_dbgfs_test_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ struct ipa_ut_test *test;
+ int nbytes;
+ ssize_t cnt;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ test = file->f_inode->i_private;
+ ipa_assert_on(!test);
+
+ buf = kmalloc(IPA_UT_DEBUG_READ_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ IPA_UT_ERR("failed to allocate %d bytes\n",
+ IPA_UT_DEBUG_READ_BUF_SIZE);
+ cnt = 0;
+ goto unlock_mutex;
+ }
+
+ nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
+ "\t Test Name: %s\n"
+ "\t Description: %s\n"
+ "\t Suite Name: %s\n"
+ "\t Run In Regression: %s\n"
+ "\t Supported IPA versions: [%s -> %s]\n",
+ test->name, test->desc ?: "", test->suite->meta_data->name,
+ test->run_in_regression ? "Yes" : "No",
+ ipa_get_version_string(test->min_ipa_hw_ver),
+ test->max_ipa_hw_ver == IPA_HW_MAX ? "MAX" :
+ ipa_get_version_string(test->max_ipa_hw_ver));
+
+ if (nbytes > count)
+ IPA_UT_ERR("User buf too small - return partial info\n");
+
+ cnt = simple_read_from_buffer(ubuf, count, ppos, buf, nbytes);
+ kfree(buf);
+
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return cnt;
+}
+
+/**
+ * ipa_ut_framework_load_suites() - Load tests and expose them to user space
+ *
+ * Creates debugfs folder for each suite and then file for each test in it.
+ * Create debugfs "all" file for each suite for meta-test to run all tests.
+ *
+ * Note: Assumes lock acquired
+ *
+ * Return: Zero in success, otherwise in failure
+ */
+int ipa_ut_framework_load_suites(void)
+{
+ int suite_idx;
+ int tst_idx;
+ struct ipa_ut_suite *suite;
+ struct dentry *s_dent;
+ struct dentry *f_dent;
+
+ IPA_UT_DBG("Entry\n");
+
+ for (suite_idx = IPA_UT_SUITE_FIRST_INDEX;
+ suite_idx < IPA_UT_SUITES_COUNT; suite_idx++) {
+ suite = IPA_UT_GET_SUITE(suite_idx);
+
+ if (!suite->meta_data->name) {
+ IPA_UT_ERR("No suite name\n");
+ return -EFAULT;
+ }
+
+ s_dent = debugfs_create_dir(suite->meta_data->name,
+ ipa_ut_ctx->test_dbgfs_suites);
+
+ if (!s_dent || IS_ERR(s_dent)) {
+ IPA_UT_ERR("fail create dbg entry - suite %s\n",
+ suite->meta_data->name);
+ return -EFAULT;
+ }
+
+ for (tst_idx = 0; tst_idx < suite->tests_cnt ; tst_idx++) {
+ if (!suite->tests[tst_idx].name) {
+ IPA_UT_ERR("No test name on suite %s\n",
+ suite->meta_data->name);
+ return -EFAULT;
+ }
+ f_dent = debugfs_create_file(
+ suite->tests[tst_idx].name,
+ IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
+ &suite->tests[tst_idx],
+ &ipa_ut_dbgfs_test_fops);
+ if (!f_dent || IS_ERR(f_dent)) {
+ IPA_UT_ERR("fail create dbg entry - tst %s\n",
+ suite->tests[tst_idx].name);
+ return -EFAULT;
+ }
+ }
+
+ /* entry for meta-test all to run all tests in suites */
+ f_dent = debugfs_create_file(_IPA_UT_RUN_ALL_TEST_NAME,
+ IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
+ suite, &ipa_ut_dbgfs_all_test_fops);
+ if (!f_dent || IS_ERR(f_dent)) {
+ IPA_UT_ERR("fail to create dbg entry - %s\n",
+ _IPA_UT_RUN_ALL_TEST_NAME);
+ return -EFAULT;
+ }
+
+ /*
+ * entry for meta-test regression to run all regression
+ * tests in suites
+ */
+ f_dent = debugfs_create_file(_IPA_UT_RUN_REGRESSION_TEST_NAME,
+ IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
+ suite, &ipa_ut_dbgfs_regression_test_fops);
+ if (!f_dent || IS_ERR(f_dent)) {
+ IPA_UT_ERR("fail to create dbg entry - %s\n",
+ _IPA_UT_RUN_ALL_TEST_NAME);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ipa_ut_framework_enable() - Enable the framework
+ *
+ * Creates the tests and suites debugfs entries and load them.
+ * This will expose the tests to user space.
+ *
+ * Return: Zero in success, otherwise in failure
+ */
+static int ipa_ut_framework_enable(void)
+{
+ int ret = 0;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+
+ if (ipa_ut_ctx->enabled) {
+ IPA_UT_ERR("Already enabled\n");
+ goto unlock_mutex;
+ }
+
+ ipa_ut_ctx->test_dbgfs_suites = debugfs_create_dir("suites",
+ ipa_ut_ctx->test_dbgfs_root);
+ if (!ipa_ut_ctx->test_dbgfs_suites ||
+ IS_ERR(ipa_ut_ctx->test_dbgfs_suites)) {
+ IPA_UT_ERR("failed to create suites debugfs dir\n");
+ ret = -EFAULT;
+ goto unlock_mutex;
+ }
+
+ if (ipa_ut_framework_load_suites()) {
+ IPA_UT_ERR("failed to load the suites into debugfs\n");
+ ret = -EFAULT;
+ goto fail_clean_suites_dbgfs;
+ }
+
+ ipa_ut_ctx->enabled = true;
+ goto unlock_mutex;
+
+fail_clean_suites_dbgfs:
+ debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_suites);
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ret;
+}
+
+/**
+ * ipa_ut_framework_disable() - Disable the framework
+ *
+ * Remove the tests and suites debugfs exposure.
+ *
+ * Return: Zero in success, otherwise in failure
+ */
+static int ipa_ut_framework_disable(void)
+{
+ int ret = 0;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+
+ if (!ipa_ut_ctx->enabled) {
+ IPA_UT_ERR("Already disabled\n");
+ goto unlock_mutex;
+ }
+
+ debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_suites);
+
+ ipa_ut_ctx->enabled = false;
+
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ret;
+}
+
+/**
+ * ipa_ut_dbgfs_enable_write() - Debugfs enable file write fops
+ * @params: write fops
+ *
+ * Input should be number. If 0, then disable. Otherwise enable.
+ *
+ * Return: if failed then negative value, if succeeds, amount of given chars
+ */
+static ssize_t ipa_ut_dbgfs_enable_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ char lcl_buf[IPA_UT_DEBUG_WRITE_BUF_SIZE];
+ s8 option = 0;
+ int ret;
+
+ IPA_UT_DBG("Entry\n");
+
+ if (sizeof(lcl_buf) < count + 1) {
+ IPA_UT_ERR("No enough space\n");
+ return -E2BIG;
+ }
+
+ if (copy_from_user(lcl_buf, buf, count)) {
+ IPA_UT_ERR("fail to copy buf from user space\n");
+ return -EFAULT;
+ }
+
+ lcl_buf[count] = '\0';
+ if (kstrtos8(lcl_buf, 0, &option)) {
+ IPA_UT_ERR("fail convert str to s8\n");
+ return -EINVAL;
+ }
+
+ if (option == 0)
+ ret = ipa_ut_framework_disable();
+ else
+ ret = ipa_ut_framework_enable();
+
+ return ret ?: count;
+}
+
+/**
+ * ipa_ut_dbgfs_enable_read() - Debugfs enable file read fops
+ * @params: read fops
+ *
+ * To show to user space if the I/S is enabled or disabled.
+ *
+ * Return: amount of characters returned to user space
+ */
+static ssize_t ipa_ut_dbgfs_enable_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ const char *status;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ status = ipa_ut_ctx->enabled ?
+ "Enabled - Write 0 to disable\n" :
+ "Disabled - Write 1 to enable\n";
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return simple_read_from_buffer(ubuf, count, ppos,
+ status, strlen(status));
+}
+
+/**
+ * ipa_ut_framework_init() - Unit-tests framework initialization
+ *
+ * Complete tests initialization: Each tests needs to point to it's
+ * corresponing suite.
+ * Creates the framework debugfs root directory under IPA directory.
+ * Create enable debugfs file - to enable/disable the framework.
+ *
+ * Return: Zero in success, otherwise in failure
+ */
+static int ipa_ut_framework_init(void)
+{
+ struct dentry *dfile_enable;
+ int ret;
+ int suite_idx;
+ int test_idx;
+ struct ipa_ut_suite *suite;
+
+ IPA_UT_DBG("Entry\n");
+
+ ipa_assert_on(!ipa_ut_ctx);
+
+ ipa_ut_ctx->ipa_dbgfs_root = ipa_debugfs_get_root();
+ if (!ipa_ut_ctx->ipa_dbgfs_root) {
+ IPA_UT_ERR("No IPA debugfs root entry\n");
+ return -EFAULT;
+ }
+
+ mutex_lock(&ipa_ut_ctx->lock);
+
+ /* tests needs to point to their corresponding suites structures */
+ for (suite_idx = IPA_UT_SUITE_FIRST_INDEX;
+ suite_idx < IPA_UT_SUITES_COUNT; suite_idx++) {
+ suite = IPA_UT_GET_SUITE(suite_idx);
+ ipa_assert_on(!suite);
+ if (!suite->tests) {
+ IPA_UT_DBG("No tests for suite %s\n",
+ suite->meta_data->name);
+ continue;
+ }
+ for (test_idx = 0; test_idx < suite->tests_cnt; test_idx++) {
+ suite->tests[test_idx].suite = suite;
+ IPA_UT_DBG("Updating test %s info for suite %s\n",
+ suite->tests[test_idx].name,
+ suite->meta_data->name);
+ }
+ }
+
+ ipa_ut_ctx->test_dbgfs_root = debugfs_create_dir("test",
+ ipa_ut_ctx->ipa_dbgfs_root);
+ if (!ipa_ut_ctx->test_dbgfs_root ||
+ IS_ERR(ipa_ut_ctx->test_dbgfs_root)) {
+ IPA_UT_ERR("failed to create test debugfs dir\n");
+ ret = -EFAULT;
+ goto unlock_mutex;
+ }
+
+ dfile_enable = debugfs_create_file("enable",
+ IPA_UT_READ_WRITE_DBG_FILE_MODE,
+ ipa_ut_ctx->test_dbgfs_root, 0, &ipa_ut_dbgfs_enable_fops);
+ if (!dfile_enable || IS_ERR(dfile_enable)) {
+ IPA_UT_ERR("failed to create enable debugfs file\n");
+ ret = -EFAULT;
+ goto fail_clean_dbgfs;
+ }
+
+ ipa_ut_ctx->inited = true;
+ IPA_UT_DBG("Done\n");
+ ret = 0;
+ goto unlock_mutex;
+
+fail_clean_dbgfs:
+ debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_root);
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ret;
+}
+
+/**
+ * ipa_ut_framework_destroy() - Destroy the UT framework info
+ *
+ * Disable it if enabled.
+ * Remove the debugfs entries using the root entry
+ */
+static void ipa_ut_framework_destroy(void)
+{
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ if (ipa_ut_ctx->enabled)
+ ipa_ut_framework_disable();
+ if (ipa_ut_ctx->inited)
+ debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_root);
+ mutex_unlock(&ipa_ut_ctx->lock);
+}
+
+/**
+ * ipa_ut_ipa_ready_cb() - IPA ready CB
+ *
+ * Once IPA is ready starting initializing the unit-test framework
+ */
+static void ipa_ut_ipa_ready_cb(void *user_data)
+{
+ IPA_UT_DBG("Entry\n");
+ (void)ipa_ut_framework_init();
+}
+
+/**
+ * ipa_ut_module_init() - Module init
+ *
+ * Create the framework context, wait for IPA driver readiness
+ * and Initialize it.
+ * If IPA driver already ready, continue initialization immediately.
+ * if not, wait for IPA ready notification by IPA driver context
+ */
+static int __init ipa_ut_module_init(void)
+{
+ int ret;
+
+ IPA_UT_INFO("Loading IPA test module...\n");
+
+ ipa_ut_ctx = kzalloc(sizeof(struct ipa_ut_context), GFP_KERNEL);
+ if (!ipa_ut_ctx) {
+ IPA_UT_ERR("Failed to allocate ctx\n");
+ return -ENOMEM;
+ }
+ mutex_init(&ipa_ut_ctx->lock);
+
+ if (!ipa_is_ready()) {
+ IPA_UT_DBG("IPA driver not ready, registering callback\n");
+ ret = ipa_register_ipa_ready_cb(ipa_ut_ipa_ready_cb, NULL);
+
+ /*
+ * If we received -EEXIST, IPA has initialized. So we need
+ * to continue the initing process.
+ */
+ if (ret != -EEXIST) {
+ if (ret) {
+ IPA_UT_ERR("IPA CB reg failed - %d\n", ret);
+ kfree(ipa_ut_ctx);
+ ipa_ut_ctx = NULL;
+ }
+ return ret;
+ }
+ }
+
+ ret = ipa_ut_framework_init();
+ if (ret) {
+ IPA_UT_ERR("framework init failed\n");
+ kfree(ipa_ut_ctx);
+ ipa_ut_ctx = NULL;
+ }
+ return ret;
+}
+
+/**
+ * ipa_ut_module_exit() - Module exit function
+ *
+ * Destroys the Framework and removes its context
+ */
+static void ipa_ut_module_exit(void)
+{
+ IPA_UT_DBG("Entry\n");
+
+ if (!ipa_ut_ctx)
+ return;
+
+ ipa_ut_framework_destroy();
+ kfree(ipa_ut_ctx);
+ ipa_ut_ctx = NULL;
+}
+
+module_init(ipa_ut_module_init);
+module_exit(ipa_ut_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("IPA Unit Test module");
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_framework.h b/drivers/platform/msm/ipa/test/ipa_ut_framework.h
new file mode 100644
index 000000000000..177be51bfe7d
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_ut_framework.h
@@ -0,0 +1,222 @@
+/* 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.
+ */
+
+#ifndef _IPA_UT_FRAMEWORK_H_
+#define _IPA_UT_FRAMEWORK_H_
+
+#include <linux/kernel.h>
+#include "../ipa_common_i.h"
+#include "ipa_ut_i.h"
+
+#define IPA_UT_DRV_NAME "ipa_ut"
+
+#define IPA_UT_DBG(fmt, args...) \
+ do { \
+ pr_debug(IPA_UT_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPA_UT_DBG_LOW(fmt, args...) \
+ do { \
+ pr_debug(IPA_UT_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPA_UT_ERR(fmt, args...) \
+ do { \
+ pr_err(IPA_UT_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPA_UT_INFO(fmt, args...) \
+ do { \
+ pr_info(IPA_UT_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+/**
+ * struct ipa_ut_tst_fail_report - Information on test failure
+ * @valid: When a test posts a report, valid will be marked true
+ * @file: File name containing the failed test.
+ * @line: Number of line in the file where the test failed.
+ * @func: Function where the test failed in.
+ * @info: Information about the failure.
+ */
+struct ipa_ut_tst_fail_report {
+ bool valid;
+ const char *file;
+ int line;
+ const char *func;
+ const char *info;
+};
+
+/**
+ * Report on test failure
+ * To be used by tests.
+ */
+#define IPA_UT_TEST_FAIL_REPORT(__info) \
+ do { \
+ extern struct ipa_ut_tst_fail_report \
+ _IPA_UT_TEST_FAIL_REPORT_DATA; \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.valid = true; \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.file = __FILENAME__; \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.line = __LINE__; \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.func = __func__; \
+ if (__info) \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.info = __info; \
+ else \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.info = ""; \
+ } while (0)
+
+/**
+ * To be used by tests to log progress and ongoing information
+ * Logs are not printed to user, but saved to a buffer.
+ * I/S shall print the buffer at different occasions - e.g. in test failure
+ */
+#define IPA_UT_LOG(fmt, args...) \
+ do { \
+ extern char *_IPA_UT_TEST_LOG_BUF_NAME; \
+ char __buf[512]; \
+ IPA_UT_DBG(fmt, args); \
+ scnprintf(__buf, sizeof(__buf), \
+ fmt, args); \
+ strlcat(_IPA_UT_TEST_LOG_BUF_NAME, __buf, sizeof(__buf)); \
+ } while (0)
+
+/**
+ * struct ipa_ut_suite_meta - Suite meta-data
+ * @name: Suite unique name
+ * @desc: Suite description
+ * @setup: Setup Call-back of the suite
+ * @teardown: Teardown Call-back of the suite
+ * @priv: Private pointer of the suite
+ *
+ * Setup/Teardown will be called once for the suite when running a tests of it.
+ * priv field is shared between the Setup/Teardown and the tests
+ */
+struct ipa_ut_suite_meta {
+ char *name;
+ char *desc;
+ int (*setup)(void **ppriv);
+ int (*teardown)(void *priv);
+ void *priv;
+};
+
+/* Test suite data structure declaration */
+struct ipa_ut_suite;
+
+/**
+ * struct ipa_ut_test - Test information
+ * @name: Test name
+ * @desc: Test description
+ * @run: Test execution call-back
+ * @run_in_regression: To run this test as part of regression?
+ * @min_ipa_hw_ver: Minimum IPA H/W version where the test is supported?
+ * @max_ipa_hw_ver: Maximum IPA H/W version where the test is supported?
+ * @suite: Pointer to suite containing this test
+ * @res: Test execution result. Will be updated after running a test as part
+ * of suite tests run
+ */
+struct ipa_ut_test {
+ char *name;
+ char *desc;
+ int (*run)(void *priv);
+ bool run_in_regression;
+ int min_ipa_hw_ver;
+ int max_ipa_hw_ver;
+ struct ipa_ut_suite *suite;
+ enum ipa_ut_test_result res;
+};
+
+/**
+ * struct ipa_ut_suite - Suite information
+ * @meta_data: Pointer to meta-data structure of the suite
+ * @tests: Pointer to array of tests belongs to the suite
+ * @tests_cnt: Number of tests
+ */
+struct ipa_ut_suite {
+ struct ipa_ut_suite_meta *meta_data;
+ struct ipa_ut_test *tests;
+ size_t tests_cnt;
+};
+
+
+/**
+ * Add a test to a suite.
+ * Will add entry to tests array and update its info with
+ * the given info, thus adding new test.
+ */
+#define IPA_UT_ADD_TEST(__name, __desc, __run, __run_in_regression, \
+ __min_ipa_hw_ver, __max_ipa__hw_ver) \
+ { \
+ .name = #__name, \
+ .desc = __desc, \
+ .run = __run, \
+ .run_in_regression = __run_in_regression, \
+ .min_ipa_hw_ver = __min_ipa_hw_ver, \
+ .max_ipa_hw_ver = __max_ipa__hw_ver, \
+ .suite = NULL, \
+ }
+
+/**
+ * Declare a suite
+ * Every suite need to be declared before it is registered.
+ */
+#define IPA_UT_DECLARE_SUITE(__name) \
+ extern struct ipa_ut_suite _IPA_UT_SUITE_DATA(__name)
+
+/**
+ * Register a suite
+ * Registering a suite is mandatory so it will be considered.
+ */
+#define IPA_UT_REGISTER_SUITE(__name) \
+ (&_IPA_UT_SUITE_DATA(__name))
+
+/**
+ * Start/End suite definition
+ * Will create the suite global structures and adds adding tests to it.
+ * Use IPA_UT_ADD_TEST() with these macros to add tests when defining
+ * a suite
+ */
+#define IPA_UT_DEFINE_SUITE_START(__name, __desc, __setup, __teardown) \
+ static struct ipa_ut_suite_meta _IPA_UT_SUITE_META_DATA(__name) = \
+ { \
+ .name = #__name, \
+ .desc = __desc, \
+ .setup = __setup, \
+ .teardown = __teardown, \
+ }; \
+ static struct ipa_ut_test _IPA_UT_SUITE_TESTS(__name)[] =
+#define IPA_UT_DEFINE_SUITE_END(__name) \
+ ; \
+ struct ipa_ut_suite _IPA_UT_SUITE_DATA(__name) = \
+ { \
+ .meta_data = &_IPA_UT_SUITE_META_DATA(__name), \
+ .tests = _IPA_UT_SUITE_TESTS(__name), \
+ .tests_cnt = ARRAY_SIZE(_IPA_UT_SUITE_TESTS(__name)), \
+ }
+
+#endif /* _IPA_UT_FRAMEWORK_H_ */
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_i.h b/drivers/platform/msm/ipa/test/ipa_ut_i.h
new file mode 100644
index 000000000000..7cf5e53d0af1
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_ut_i.h
@@ -0,0 +1,86 @@
+/* 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.
+ */
+
+#ifndef _IPA_UT_I_H_
+#define _IPA_UT_I_H_
+
+/* Suite data global structure name */
+#define _IPA_UT_SUITE_DATA(__name) ipa_ut_ ##__name ##_data
+
+/* Suite meta-data global structure name */
+#define _IPA_UT_SUITE_META_DATA(__name) ipa_ut_ ##__name ##_meta_data
+
+/* Suite global array of tests */
+#define _IPA_UT_SUITE_TESTS(__name) ipa_ut_ ##__name ##_tests
+
+/* Global array of all suites */
+#define _IPA_UT_ALL_SUITES ipa_ut_all_suites_data
+
+/* Meta-test "all" name - test to run all tests in given suite */
+#define _IPA_UT_RUN_ALL_TEST_NAME "all"
+
+/**
+ * Meta-test "regression" name -
+ * test to run all regression tests in given suite
+ */
+#define _IPA_UT_RUN_REGRESSION_TEST_NAME "regression"
+
+
+/* Test Log buffer name and size */
+#define _IPA_UT_TEST_LOG_BUF_NAME ipa_ut_tst_log_buf
+#define _IPA_UT_TEST_LOG_BUF_SIZE 2048
+
+/* Global structure for test fail execution result information */
+#define _IPA_UT_TEST_FAIL_REPORT_DATA ipa_ut_tst_fail_report_data
+
+/* Start/End definitions of the array of suites */
+#define IPA_UT_DEFINE_ALL_SUITES_START \
+ static struct ipa_ut_suite *_IPA_UT_ALL_SUITES[] =
+#define IPA_UT_DEFINE_ALL_SUITES_END
+
+/**
+ * Suites iterator - Array-like container
+ * First index, number of elements and element fetcher
+ */
+#define IPA_UT_SUITE_FIRST_INDEX 0
+#define IPA_UT_SUITES_COUNT \
+ ARRAY_SIZE(_IPA_UT_ALL_SUITES)
+#define IPA_UT_GET_SUITE(__index) \
+ _IPA_UT_ALL_SUITES[__index]
+
+/**
+ * enum ipa_ut_test_result - Test execution result
+ * @IPA_UT_TEST_RES_FAIL: Test executed and failed
+ * @IPA_UT_TEST_RES_SUCCESS: Test executed and succeeded
+ * @IPA_UT_TEST_RES_SKIP: Test was not executed.
+ *
+ * When running all tests in a suite, a specific test could
+ * be skipped and not executed. For example due to mismatch of
+ * IPA H/W version.
+ */
+enum ipa_ut_test_result {
+ IPA_UT_TEST_RES_FAIL,
+ IPA_UT_TEST_RES_SUCCESS,
+ IPA_UT_TEST_RES_SKIP,
+};
+
+/**
+ * enum ipa_ut_meta_test_type - Type of suite meta-test
+ * @IPA_UT_META_TEST_ALL: Represents all tests in suite
+ * @IPA_UT_META_TEST_REGRESSION: Represents all regression tests in suite
+ */
+enum ipa_ut_meta_test_type {
+ IPA_UT_META_TEST_ALL,
+ IPA_UT_META_TEST_REGRESSION,
+};
+
+#endif /* _IPA_UT_I_H_ */
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
new file mode 100644
index 000000000000..615ba671ebaa
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
@@ -0,0 +1,35 @@
+/* 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.
+ */
+
+#ifndef _IPA_UT_SUITE_LIST_H_
+#define _IPA_UT_SUITE_LIST_H_
+
+#include "ipa_ut_framework.h"
+#include "ipa_ut_i.h"
+
+/**
+ * Declare every suite here so that it will be found later below
+ * No importance for order.
+ */
+IPA_UT_DECLARE_SUITE(example);
+
+
+/**
+ * Register every suite inside the below block.
+ * Unregistered suites will be ignored
+ */
+IPA_UT_DEFINE_ALL_SUITES_START
+{
+ IPA_UT_REGISTER_SUITE(example),
+} IPA_UT_DEFINE_ALL_SUITES_END;
+
+#endif /* _IPA_UT_SUITE_LIST_H_ */
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index a45a5d103040..b1c3441b285a 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -225,9 +225,9 @@ static struct device_attribute power_supply_attrs[] = {
/* Local extensions */
POWER_SUPPLY_ATTR(usb_hc),
POWER_SUPPLY_ATTR(usb_otg),
- POWER_SUPPLY_ATTR(charge_enabled),
POWER_SUPPLY_ATTR(battery_charging_enabled),
POWER_SUPPLY_ATTR(charging_enabled),
+ POWER_SUPPLY_ATTR(pin_enabled),
POWER_SUPPLY_ATTR(input_suspend),
POWER_SUPPLY_ATTR(input_voltage_regulation),
POWER_SUPPLY_ATTR(input_current_max),
diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c
index 11d936762e3c..e9006cfc0b9e 100644
--- a/drivers/power/qcom-charger/smb138x-charger.c
+++ b/drivers/power/qcom-charger/smb138x-charger.c
@@ -357,6 +357,8 @@ static int smb138x_init_batt_psy(struct smb138x *chip)
*****************************/
static enum power_supply_property smb138x_parallel_props[] = {
+ POWER_SUPPLY_PROP_CHARGING_ENABLED,
+ POWER_SUPPLY_PROP_PIN_ENABLED,
POWER_SUPPLY_PROP_INPUT_SUSPEND,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
@@ -368,8 +370,21 @@ static int smb138x_parallel_get_prop(struct power_supply *psy,
{
struct smb_charger *chg = power_supply_get_drvdata(psy);
int rc = 0;
+ u8 temp;
switch (prop) {
+ case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+ rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
+ &temp);
+ if (rc >= 0)
+ val->intval = (bool)(temp & CHARGING_ENABLE_BIT);
+ break;
+ case POWER_SUPPLY_PROP_PIN_ENABLED:
+ rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
+ &temp);
+ if (rc >= 0)
+ val->intval = !(temp & DISABLE_CHARGING_BIT);
+ break;
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
rc = smblib_get_usb_suspend(chg, &val->intval);
break;
diff --git a/drivers/regulator/cpr3-mmss-regulator.c b/drivers/regulator/cpr3-mmss-regulator.c
index e5055708a871..232bcf8fcf31 100644
--- a/drivers/regulator/cpr3-mmss-regulator.c
+++ b/drivers/regulator/cpr3-mmss-regulator.c
@@ -50,6 +50,9 @@
* @limitation: CPR limitation select fuse parameter value
* @aging_init_quot_diff: Initial quotient difference between CPR aging
* min and max sensors measured at time of manufacturing
+ * @force_highest_corner: Flag indicating that all corners must operate
+ * at the voltage of the highest corner. This is
+ * applicable to MSMCOBALT only.
*
* This struct holds the values for all of the fuses read from memory.
*/
@@ -60,6 +63,7 @@ struct cpr3_msm8996_mmss_fuses {
u64 cpr_fusing_rev;
u64 limitation;
u64 aging_init_quot_diff;
+ u64 force_highest_corner;
};
/* Fuse combos 0 - 7 map to CPR fusing revision 0 - 7 */
@@ -158,6 +162,12 @@ msmcobalt_mmss_offset_voltage_param[MSM8996_MMSS_FUSE_CORNERS][2] = {
{{65, 44, 47}, {} },
};
+static const struct cpr3_fuse_param
+msmcobalt_cpr_force_highest_corner_param[] = {
+ {100, 45, 45},
+ {},
+};
+
#define MSM8996PRO_SOC_ID 4
#define MSMCOBALT_SOC_ID 5
@@ -243,6 +253,12 @@ enum msmcobalt_cpr_partial_binning {
MSMCOBALT_CPR_PARTIAL_BINNING_SAFE_CORNER = 0xE,
};
+/*
+ * The partial binning open-loop voltage fuse values only apply to the lowest
+ * two fuse corners (0 and 1, i.e. MinSVS and SVS).
+ */
+#define MSMCOBALT_CPR_PARTIAL_BINNING_MAX_FUSE_CORNER 1
+
/**
* cpr3_msm8996_mmss_read_fuse_data() - load MMSS specific fuse parameter values
* @vreg: Pointer to the CPR3 regulator
@@ -338,6 +354,19 @@ static int cpr3_msm8996_mmss_read_fuse_data(struct cpr3_regulator *vreg)
}
if (vreg->thread->ctrl->soc_revision == MSMCOBALT_SOC_ID) {
+ rc = cpr3_read_fuse_param(base,
+ msmcobalt_cpr_force_highest_corner_param,
+ &fuse->force_highest_corner);
+ if (rc) {
+ cpr3_err(vreg, "Unable to read CPR force highest corner fuse, rc=%d\n",
+ rc);
+ return rc;
+ }
+ if (fuse->force_highest_corner)
+ cpr3_info(vreg, "Fusing requires all operation at the highest corner\n");
+ }
+
+ if (vreg->thread->ctrl->soc_revision == MSMCOBALT_SOC_ID) {
combo_max = CPR3_MSMCOBALT_MMSS_FUSE_COMBO_COUNT;
vreg->fuse_combo = fuse->cpr_fusing_rev;
} else if (vreg->thread->ctrl->soc_revision == MSM8996PRO_SOC_ID) {
@@ -738,7 +767,8 @@ static int cpr3_msm8996_mmss_calculate_open_loop_voltages(
*/
if (is_msmcobalt &&
(volt_init == MSMCOBALT_CPR_PARTIAL_BINNING_NEXT_CORNER ||
- volt_init == MSMCOBALT_CPR_PARTIAL_BINNING_SAFE_CORNER))
+ volt_init == MSMCOBALT_CPR_PARTIAL_BINNING_SAFE_CORNER) &&
+ i <= MSMCOBALT_CPR_PARTIAL_BINNING_MAX_FUSE_CORNER)
volt_init = MSM8996_MMSS_MIN_VOLTAGE_FUSE_VAL;
fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse(ref_volt[i],
@@ -849,19 +879,43 @@ static int cpr3_msmcobalt_partial_binning_override(struct cpr3_regulator *vreg)
u32 proc_freq;
struct cpr3_corner *corner;
struct cpr3_corner *safe_corner;
- int i, j, low, high, safe_fuse_corner;
+ int i, j, low, high, safe_fuse_corner, max_fuse_corner;
if (vreg->thread->ctrl->soc_revision != MSMCOBALT_SOC_ID)
return 0;
- /* Loop over all fuse corners except for the highest one. */
- for (i = 0; i < vreg->fuse_corner_count - 1; i++) {
+ /* Handle the force highest corner fuse. */
+ if (fuse->force_highest_corner) {
+ cpr3_info(vreg, "overriding CPR parameters for corners 0 to %d with quotients and voltages of corner %d\n",
+ vreg->corner_count - 2, vreg->corner_count - 1);
+ corner = &vreg->corner[vreg->corner_count - 1];
+ for (i = 0; i < vreg->corner_count - 1; i++) {
+ proc_freq = vreg->corner[i].proc_freq;
+ vreg->corner[i] = *corner;
+ vreg->corner[i].proc_freq = proc_freq;
+ }
+
+ /*
+ * Return since the potential partial binning fuse values are
+ * superceded by the force highest corner fuse value.
+ */
+ return 0;
+ }
+
+ /*
+ * Allow up to the max corner which can be fused with partial
+ * binning values.
+ */
+ max_fuse_corner = min(MSMCOBALT_CPR_PARTIAL_BINNING_MAX_FUSE_CORNER,
+ vreg->fuse_corner_count - 2);
+
+ for (i = 0; i <= max_fuse_corner; i++) {
/* Determine which higher corners to override with (if any). */
if (fuse->init_voltage[i] != next
&& fuse->init_voltage[i] != safe)
continue;
- for (j = i + 1; j < vreg->fuse_corner_count - 1; j++)
+ for (j = i + 1; j <= max_fuse_corner; j++)
if (fuse->init_voltage[j] != next
&& fuse->init_voltage[j] != safe)
break;
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 3f8aa534c220..c45cbfa8a786 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -104,6 +104,16 @@ config MSM_GLINK_SMEM_NATIVE_XPRT
transport to only connecting with entities internal to the
System-on-Chip.
+config MSM_GLINK_SPI_XPRT
+ depends on MSM_GLINK
+ tristate "Generic Link (G-Link) SPI Transport"
+ help
+ G-Link SPI Transport is a Transport plug-in developed over SPI
+ bus. This transport plug-in performs marshaling of G-Link
+ commands & data to the appropriate SPI bus wire format and
+ allows for G-Link communication with remote subsystems that are
+ external to the System-on-Chip.
+
config MSM_SPCOM
depends on MSM_GLINK
bool "Secure Processor Communication over GLINK"
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index f8450a4868ad..269b72c68b68 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_MSM_GLINK) += glink.o glink_debugfs.o glink_ssr.o
obj-$(CONFIG_MSM_GLINK_LOOPBACK_SERVER) += glink_loopback_server.o
obj-$(CONFIG_MSM_GLINK_SMD_XPRT) += glink_smd_xprt.o
obj-$(CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT)+= glink_smem_native_xprt.o
+obj-$(CONFIG_MSM_GLINK_SPI_XPRT) += glink_spi_xprt.o
obj-$(CONFIG_MSM_SMEM_LOGGING) += smem_log.o
obj-$(CONFIG_MSM_SYSMON_GLINK_COMM) += sysmon-glink.o sysmon-qmi.o
obj-$(CONFIG_ARCH_MSM8996) += kryo-l2-accessors.o
diff --git a/drivers/soc/qcom/core_hang_detect.c b/drivers/soc/qcom/core_hang_detect.c
index 42f31e320b61..e9b7f612dccc 100644
--- a/drivers/soc/qcom/core_hang_detect.c
+++ b/drivers/soc/qcom/core_hang_detect.c
@@ -33,6 +33,7 @@
#define _WRITE(x, y, z) (((~(_VAL(z))) & y) | _VALUE(x, z))
#define MODULE_NAME "msm_hang_detect"
+#define MAX_SYSFS_LEN 12
struct hang_detect {
phys_addr_t threshold[NR_CPUS];
@@ -108,8 +109,7 @@ static ssize_t show_threshold(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(device->threshold_val),
- "%u\n", device->threshold_val);
+ return snprintf(buf, MAX_SYSFS_LEN, "0x%x\n", device->threshold_val);
}
static size_t store_threshold(struct kobject *kobj, struct attribute *attr,
@@ -147,8 +147,8 @@ static ssize_t show_pmu_event_sel(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *hang_device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(hang_device->pmu_event_sel),
- "%u\n", hang_device->pmu_event_sel);
+ return snprintf(buf, MAX_SYSFS_LEN, "0x%x\n",
+ hang_device->pmu_event_sel);
}
static size_t store_pmu_event_sel(struct kobject *kobj, struct attribute *attr,
@@ -188,8 +188,7 @@ static ssize_t show_enable(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *hang_device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(hang_device->enabled),
- "%u\n", hang_device->enabled);
+ return snprintf(buf, MAX_SYSFS_LEN, "%u\n", hang_device->enabled);
}
static size_t store_enable(struct kobject *kobj, struct attribute *attr,
diff --git a/drivers/soc/qcom/gladiator_hang_detect.c b/drivers/soc/qcom/gladiator_hang_detect.c
index fd8062ca523a..e2bbe26decc8 100644
--- a/drivers/soc/qcom/gladiator_hang_detect.c
+++ b/drivers/soc/qcom/gladiator_hang_detect.c
@@ -34,6 +34,7 @@
#define NR_GLA_REG 6
#define MODULE_NAME "gladiator_hang_detect"
#define MAX_THRES 0xFFFFFFFF
+#define MAX_LEN_SYSFS 12
struct hang_detect {
phys_addr_t threshold[NR_GLA_REG];
@@ -199,8 +200,7 @@ static inline ssize_t generic_enable_show(struct kobject *kobj,
uint32_t reg_value;
get_enable(offset, hang_dev, &reg_value);
- return snprintf(buf, sizeof(hang_dev->ACE_enable),
- "%d\n", reg_value);
+ return snprintf(buf, MAX_LEN_SYSFS, "%u\n", reg_value);
}
static inline ssize_t generic_threshold_show(struct kobject *kobj,
@@ -210,9 +210,7 @@ static inline ssize_t generic_threshold_show(struct kobject *kobj,
uint32_t reg_value;
get_threshold(offset, hang_dev, &reg_value);
- return snprintf(buf, sizeof(hang_dev->ACE_threshold),
- "%u\n", reg_value);
-
+ return snprintf(buf, MAX_LEN_SYSFS, "0x%x\n", reg_value);
}
static inline size_t generic_threshold_store(struct kobject *kobj,
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index 464fe17158cf..57e58a57fab7 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -372,10 +372,10 @@ static struct channel_ctx *ch_name_to_ch_ctx_create(
const char *name);
static void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
- uint32_t riid);
+ uint32_t riid, void *cookie);
static int ch_pop_remote_rx_intent(struct channel_ctx *ctx, size_t size,
- uint32_t *riid_ptr, size_t *intent_size);
+ uint32_t *riid_ptr, size_t *intent_size, void **cookie);
static struct glink_core_rx_intent *ch_push_local_rx_intent(
struct channel_ctx *ctx, const void *pkt_priv, size_t size);
@@ -1139,11 +1139,12 @@ bool ch_check_duplicate_riid(struct channel_ctx *ctx, int riid)
* @ctx: Local channel context
* @size: Size of Intent
* @riid_ptr: Pointer to return value of remote intent ID
+ * @cookie: Transport-specific cookie to return
*
* This functions searches for an RX intent that is >= to the requested size.
*/
int ch_pop_remote_rx_intent(struct channel_ctx *ctx, size_t size,
- uint32_t *riid_ptr, size_t *intent_size)
+ uint32_t *riid_ptr, size_t *intent_size, void **cookie)
{
struct glink_core_rx_intent *intent;
struct glink_core_rx_intent *intent_tmp;
@@ -1177,6 +1178,7 @@ int ch_pop_remote_rx_intent(struct channel_ctx *ctx, size_t size,
intent->intent_size);
*riid_ptr = intent->id;
*intent_size = intent->intent_size;
+ *cookie = intent->cookie;
kfree(intent);
spin_unlock_irqrestore(
&ctx->rmt_rx_intent_lst_lock_lhc2, flags);
@@ -1192,11 +1194,12 @@ int ch_pop_remote_rx_intent(struct channel_ctx *ctx, size_t size,
* @ctx: Local channel context
* @size: Size of Intent
* @riid: Remote intent ID
+ * @cookie: Transport-specific cookie to cache
*
* This functions adds a remote RX intent to the remote RX intent list.
*/
void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
- uint32_t riid)
+ uint32_t riid, void *cookie)
{
struct glink_core_rx_intent *intent;
unsigned long flags;
@@ -1225,6 +1228,7 @@ void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
}
intent->id = riid;
intent->intent_size = size;
+ intent->cookie = cookie;
spin_lock_irqsave(&ctx->rmt_rx_intent_lst_lock_lhc2, flags);
list_add_tail(&intent->list, &ctx->rmt_rx_intent_list);
@@ -2794,6 +2798,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
bool is_atomic =
tx_flags & (GLINK_TX_SINGLE_THREADED | GLINK_TX_ATOMIC);
unsigned long flags;
+ void *cookie = NULL;
if (!size)
return -EINVAL;
@@ -2826,7 +2831,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
}
/* find matching rx intent (first-fit algorithm for now) */
- if (ch_pop_remote_rx_intent(ctx, size, &riid, &intent_size)) {
+ if (ch_pop_remote_rx_intent(ctx, size, &riid, &intent_size, &cookie)) {
if (!(tx_flags & GLINK_TX_REQ_INTENT)) {
/* no rx intent available */
GLINK_ERR_CH(ctx,
@@ -2856,7 +2861,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
}
while (ch_pop_remote_rx_intent(ctx, size, &riid,
- &intent_size)) {
+ &intent_size, &cookie)) {
rwref_get(&ctx->ch_state_lhb2);
rwref_read_put(&ctx->ch_state_lhb2);
if (is_atomic) {
@@ -2928,7 +2933,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
is_atomic ? GFP_ATOMIC : GFP_KERNEL);
if (!tx_info) {
GLINK_ERR_CH(ctx, "%s: No memory for allocation\n", __func__);
- ch_push_remote_rx_intent(ctx, intent_size, riid);
+ ch_push_remote_rx_intent(ctx, intent_size, riid, cookie);
rwref_read_put(&ctx->ch_state_lhb2);
return -ENOMEM;
}
@@ -2946,6 +2951,7 @@ static int glink_tx_common(void *handle, void *pkt_priv,
tx_info->vprovider = vbuf_provider;
tx_info->pprovider = pbuf_provider;
tx_info->intent_size = intent_size;
+ tx_info->cookie = cookie;
/* schedule packet for transmit */
if ((tx_flags & GLINK_TX_SINGLE_THREADED) &&
@@ -3577,6 +3583,10 @@ int glink_xprt_name_to_id(const char *name, uint16_t *id)
*id = SMEM_XPRT_ID;
return 0;
}
+ if (!strcmp(name, "spi")) {
+ *id = SPIV2_XPRT_ID;
+ return 0;
+ }
if (!strcmp(name, "smd_trans")) {
*id = SMD_TRANS_XPRT_ID;
return 0;
@@ -4844,7 +4854,35 @@ static void glink_core_remote_rx_intent_put(struct glink_transport_if *if_ptr,
return;
}
- ch_push_remote_rx_intent(ctx, size, riid);
+ ch_push_remote_rx_intent(ctx, size, riid, NULL);
+ rwref_put(&ctx->ch_state_lhb2);
+}
+
+/**
+ * glink_core_remote_rx_intent_put_cookie() - Receive remove intent
+ *
+ * @if_ptr: Pointer to transport instance
+ * @rcid: Remote Channel ID
+ * @riid: Remote Intent ID
+ * @size: Size of the remote intent ID
+ * @cookie: Transport-specific cookie to cache
+ */
+static void glink_core_remote_rx_intent_put_cookie(
+ struct glink_transport_if *if_ptr,
+ uint32_t rcid, uint32_t riid, size_t size, void *cookie)
+{
+ struct channel_ctx *ctx;
+
+ ctx = xprt_rcid_to_ch_ctx_get(if_ptr->glink_core_priv, rcid);
+ if (!ctx) {
+ /* unknown rcid received - this shouldn't happen */
+ GLINK_ERR_XPRT(if_ptr->glink_core_priv,
+ "%s: invalid rcid received %u\n", __func__,
+ (unsigned)rcid);
+ return;
+ }
+
+ ch_push_remote_rx_intent(ctx, size, riid, cookie);
rwref_put(&ctx->ch_state_lhb2);
}
@@ -5050,6 +5088,7 @@ void glink_core_rx_cmd_tx_done(struct glink_transport_if *if_ptr,
struct glink_core_tx_pkt *tx_pkt;
unsigned long flags;
size_t intent_size;
+ void *cookie;
ctx = xprt_rcid_to_ch_ctx_get(if_ptr->glink_core_priv, rcid);
if (!ctx) {
@@ -5082,11 +5121,12 @@ void glink_core_rx_cmd_tx_done(struct glink_transport_if *if_ptr,
ctx->notify_tx_done(ctx, ctx->user_priv, tx_pkt->pkt_priv,
tx_pkt->data ? tx_pkt->data : tx_pkt->iovec);
intent_size = tx_pkt->intent_size;
+ cookie = tx_pkt->cookie;
ch_remove_tx_pending_remote_done(ctx, tx_pkt);
spin_unlock_irqrestore(&ctx->tx_lists_lock_lhc3, flags);
if (reuse)
- ch_push_remote_rx_intent(ctx, intent_size, riid);
+ ch_push_remote_rx_intent(ctx, intent_size, riid, cookie);
rwref_put(&ctx->ch_state_lhb2);
}
@@ -5525,6 +5565,8 @@ static struct glink_core_if core_impl = {
.rx_get_pkt_ctx = glink_core_rx_get_pkt_ctx,
.rx_put_pkt_ctx = glink_core_rx_put_pkt_ctx,
.rx_cmd_remote_rx_intent_put = glink_core_remote_rx_intent_put,
+ .rx_cmd_remote_rx_intent_put_cookie =
+ glink_core_remote_rx_intent_put_cookie,
.rx_cmd_remote_rx_intent_req = glink_core_rx_cmd_remote_rx_intent_req,
.rx_cmd_rx_intent_req_ack = glink_core_rx_cmd_rx_intent_req_ack,
.rx_cmd_tx_done = glink_core_rx_cmd_tx_done,
diff --git a/drivers/soc/qcom/glink_core_if.h b/drivers/soc/qcom/glink_core_if.h
index 93c59d9c4aa1..14113305a50e 100644
--- a/drivers/soc/qcom/glink_core_if.h
+++ b/drivers/soc/qcom/glink_core_if.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -64,6 +64,7 @@ struct glink_core_version {
* iovec: Pointer to vector buffer if the transport passes a vector buffer
* vprovider: Virtual address-space buffer provider for a vector buffer
* pprovider: Physical address-space buffer provider for a vector buffer
+ * cookie: Private transport specific cookie
* pkt_priv: G-Link core owned packet-private data
* list: G-Link core owned list node
* bounce_buf: Pointer to the temporary/internal bounce buffer
@@ -78,6 +79,7 @@ struct glink_core_rx_intent {
void *iovec;
void * (*vprovider)(void *iovec, size_t offset, size_t *size);
void * (*pprovider)(void *iovec, size_t offset, size_t *size);
+ void *cookie;
/* G-Link-Core-owned elements - please ignore */
struct list_head list;
@@ -151,6 +153,9 @@ struct glink_core_if {
struct glink_core_rx_intent *intent_ptr, bool complete);
void (*rx_cmd_remote_rx_intent_put)(struct glink_transport_if *if_ptr,
uint32_t rcid, uint32_t riid, size_t size);
+ void (*rx_cmd_remote_rx_intent_put_cookie)(
+ struct glink_transport_if *if_ptr, uint32_t rcid,
+ uint32_t riid, size_t size, void *cookie);
void (*rx_cmd_tx_done)(struct glink_transport_if *if_ptr, uint32_t rcid,
uint32_t riid, bool reuse);
void (*rx_cmd_remote_rx_intent_req)(struct glink_transport_if *if_ptr,
diff --git a/drivers/soc/qcom/glink_spi_xprt.c b/drivers/soc/qcom/glink_spi_xprt.c
new file mode 100644
index 000000000000..6c91ac54821d
--- /dev/null
+++ b/drivers/soc/qcom/glink_spi_xprt.c
@@ -0,0 +1,2192 @@
+/* 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spinlock.h>
+#include <linux/srcu.h>
+#include <linux/wait.h>
+#include <linux/component.h>
+#include <soc/qcom/tracer_pkt.h>
+#include <sound/wcd-dsp-mgr.h>
+#include <sound/wcd-spi.h>
+#include "glink_core_if.h"
+#include "glink_private.h"
+#include "glink_xprt_if.h"
+
+#define XPRT_NAME "spi"
+#define FIFO_ALIGNMENT 16
+#define FIFO_FULL_RESERVE 8
+#define TX_BLOCKED_CMD_RESERVE 16
+#define TRACER_PKT_FEATURE BIT(2)
+#define DEFAULT_FIFO_SIZE 1024
+#define SHORT_PKT_SIZE 16
+#define XPRT_ALIGNMENT 4
+
+#define MAX_INACTIVE_CYCLES 50
+#define POLL_INTERVAL_US 500
+
+#define ACTIVE_TX BIT(0)
+#define ACTIVE_RX BIT(1)
+
+#define ID_MASK 0xFFFFFF
+/**
+ * enum command_types - definition of the types of commands sent/received
+ * @VERSION_CMD: Version and feature set supported
+ * @VERSION_ACK_CMD: Response for @VERSION_CMD
+ * @OPEN_CMD: Open a channel
+ * @CLOSE_CMD: Close a channel
+ * @OPEN_ACK_CMD: Response to @OPEN_CMD
+ * @CLOSE_ACK_CMD: Response for @CLOSE_CMD
+ * @RX_INTENT_CMD: RX intent for a channel is queued
+ * @RX_DONE_CMD: Use of RX intent for a channel is complete
+ * @RX_DONE_W_REUSE_CMD: Same as @RX_DONE but also reuse the used intent
+ * @RX_INTENT_REQ_CMD: Request to have RX intent queued
+ * @RX_INTENT_REQ_ACK_CMD: Response for @RX_INTENT_REQ_CMD
+ * @TX_DATA_CMD: Start of a data transfer
+ * @TX_DATA_CONT_CMD: Continuation or end of a data transfer
+ * @READ_NOTIF_CMD: Request for a notification when this cmd is read
+ * @SIGNALS_CMD: Sideband signals
+ * @TRACER_PKT_CMD: Start of a Tracer Packet Command
+ * @TRACER_PKT_CONT_CMD: Continuation or end of a Tracer Packet Command
+ * @TX_SHORT_DATA_CMD: Transmit short packets
+ */
+enum command_types {
+ VERSION_CMD,
+ VERSION_ACK_CMD,
+ OPEN_CMD,
+ CLOSE_CMD,
+ OPEN_ACK_CMD,
+ CLOSE_ACK_CMD,
+ RX_INTENT_CMD,
+ RX_DONE_CMD,
+ RX_DONE_W_REUSE_CMD,
+ RX_INTENT_REQ_CMD,
+ RX_INTENT_REQ_ACK_CMD,
+ TX_DATA_CMD,
+ TX_DATA_CONT_CMD,
+ READ_NOTIF_CMD,
+ SIGNALS_CMD,
+ TRACER_PKT_CMD,
+ TRACER_PKT_CONT_CMD,
+ TX_SHORT_DATA_CMD,
+};
+
+/**
+ * struct glink_cmpnt - Component to cache WDSP component and its operations
+ * @master_dev: Device structure corresponding to WDSP device.
+ * @master_ops: Operations supported by the WDSP device.
+ */
+struct glink_cmpnt {
+ struct device *master_dev;
+ struct wdsp_mgr_ops *master_ops;
+};
+
+/**
+ * struct edge_info - local information for managing a single complete edge
+ * @xprt_if: The transport interface registered with the
+ * glink core associated with this edge.
+ * @xprt_cfg: The transport configuration for the glink core
+ * assocaited with this edge.
+ * @subsys_name: Name of the remote subsystem in the edge.
+ * @spi_dev: Pointer to the connectingSPI Device.
+ * @fifo_size: Size of the FIFO at the remote end.
+ * @tx_fifo_start: Base Address of the TX FIFO.
+ * @tx_fifo_end: End Address of the TX FIFO.
+ * @rx_fifo_start: Base Address of the RX FIFO.
+ * @rx_fifo_end: End Address of the RX FIFO.
+ * @tx_fifo_read_reg_addr: Address of the TX FIFO Read Index Register.
+ * @tx_fifo_write_reg_addr: Address of the TX FIFO Write Index Register.
+ * @rx_fifo_read_reg_addr: Address of the RX FIFO Read Index Register.
+ * @rx_fifo_write_reg_addr: Address of the RX FIFO Write Index Register.
+ * @kwork: Work to be executed when receiving data.
+ * @kworker: Handle to the entity processing @kwork.
+ * @task: Handle to the task context that runs @kworker.
+ * @use_ref: Active users of this transport grab a
+ * reference. Used for SSR synchronization.
+ * @in_ssr: Signals if this transport is in ssr.
+ * @write_lock: Lock to serialize write/tx operation.
+ * @tx_blocked_queue: Queue of entities waiting for the remote side to
+ * signal the resumption of TX.
+ * @tx_resume_needed: A tx resume signal needs to be sent to the glink
+ * core.
+ * @tx_blocked_signal_sent: Flag to indicate the flush signal has already
+ * been sent, and a response is pending from the
+ * remote side. Protected by @write_lock.
+ * @num_pw_states: Size of @ramp_time_us.
+ * @ramp_time_us: Array of ramp times in microseconds where array
+ * index position represents a power state.
+ * @activity_flag: Flag indicating active TX and RX.
+ * @activity_lock: Lock to synchronize access to activity flag.
+ * @cmpnt: Component to interface with the remote device.
+ */
+struct edge_info {
+ struct list_head list;
+ struct glink_transport_if xprt_if;
+ struct glink_core_transport_cfg xprt_cfg;
+ char subsys_name[GLINK_NAME_SIZE];
+ struct spi_device *spi_dev;
+
+ uint32_t fifo_size;
+ uint32_t tx_fifo_start;
+ uint32_t tx_fifo_end;
+ uint32_t rx_fifo_start;
+ uint32_t rx_fifo_end;
+ unsigned int tx_fifo_read_reg_addr;
+ unsigned int tx_fifo_write_reg_addr;
+ unsigned int rx_fifo_read_reg_addr;
+ unsigned int rx_fifo_write_reg_addr;
+
+ struct kthread_work kwork;
+ struct kthread_worker kworker;
+ struct task_struct *task;
+ struct srcu_struct use_ref;
+ bool in_ssr;
+ struct mutex write_lock;
+ wait_queue_head_t tx_blocked_queue;
+ bool tx_resume_needed;
+ bool tx_blocked_signal_sent;
+
+ uint32_t num_pw_states;
+ unsigned long *ramp_time_us;
+
+ uint32_t activity_flag;
+ spinlock_t activity_lock;
+
+ struct glink_cmpnt cmpnt;
+};
+
+static uint32_t negotiate_features_v1(struct glink_transport_if *if_ptr,
+ const struct glink_core_version *version,
+ uint32_t features);
+static DEFINE_SPINLOCK(edge_infos_lock);
+static LIST_HEAD(edge_infos);
+static struct glink_core_version versions[] = {
+ {1, TRACER_PKT_FEATURE, negotiate_features_v1},
+};
+
+/**
+ * negotiate_features_v1() - determine what features of a version can be used
+ * @if_ptr: The transport for which features are negotiated for.
+ * @version: The version negotiated.
+ * @features: The set of requested features.
+ *
+ * Return: What set of the requested features can be supported.
+ */
+static uint32_t negotiate_features_v1(struct glink_transport_if *if_ptr,
+ const struct glink_core_version *version,
+ uint32_t features)
+{
+ return features & version->features;
+}
+
+/**
+ * wdsp_suspend() - Vote for the WDSP device suspend
+ * @cmpnt: Component to identify the WDSP device.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int wdsp_suspend(struct glink_cmpnt *cmpnt)
+{
+ if (cmpnt && cmpnt->master_dev &&
+ cmpnt->master_ops && cmpnt->master_ops->suspend)
+ return cmpnt->master_ops->suspend(cmpnt->master_dev);
+ else
+ return -EINVAL;
+}
+
+/**
+ * wdsp_resume() - Vote for the WDSP device resume
+ * @cmpnt: Component to identify the WDSP device.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int wdsp_resume(struct glink_cmpnt *cmpnt)
+{
+ if (cmpnt && cmpnt->master_dev &&
+ cmpnt->master_ops && cmpnt->master_ops->resume)
+ return cmpnt->master_ops->resume(cmpnt->master_dev);
+ else
+ return -EINVAL;
+}
+
+/**
+ * glink_spi_xprt_set_poll_mode() - Set the transport to polling mode
+ * @einfo: Edge information corresponding to the transport.
+ *
+ * This helper function indicates the start of RX polling. This will
+ * prevent the system from suspending and keeps polling for RX for a
+ * pre-defined duration.
+ */
+static void glink_spi_xprt_set_poll_mode(struct edge_info *einfo)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ einfo->activity_flag |= ACTIVE_RX;
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+ if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
+ wdsp_resume(&einfo->cmpnt);
+}
+
+/**
+ * glink_spi_xprt_set_irq_mode() - Set the transport to IRQ mode
+ * @einfo: Edge information corresponding to the transport.
+ *
+ * This helper indicates the end of RX polling. This will allow the
+ * system to suspend and new RX data can be handled only through an IRQ.
+ */
+static void glink_spi_xprt_set_irq_mode(struct edge_info *einfo)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ einfo->activity_flag &= ~ACTIVE_RX;
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+}
+
+/**
+ * glink_spi_xprt_rx_data() - Receive data over SPI bus
+ * @einfo: Edge from which the data has to be received.
+ * @src: Source Address of the RX data.
+ * @dst: Address of the destination RX buffer.
+ * @size: Size of the RX data.
+ *
+ * This function is used to receive data or command as a byte stream from
+ * the remote subsystem over the SPI bus.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int glink_spi_xprt_rx_data(struct edge_info *einfo, void *src,
+ void *dst, uint32_t size)
+{
+ struct wcd_spi_msg spi_msg;
+
+ memset(&spi_msg, 0, sizeof(spi_msg));
+ spi_msg.data = dst;
+ spi_msg.remote_addr = (uint32_t)(size_t)src;
+ spi_msg.len = (size_t)size;
+ return wcd_spi_data_read(einfo->spi_dev, &spi_msg);
+}
+
+/**
+ * glink_spi_xprt_tx_data() - Transmit data over SPI bus
+ * @einfo: Edge from which the data has to be received.
+ * @src: Address of the TX buffer.
+ * @dst: Destination Address of the TX Date.
+ * @size: Size of the TX data.
+ *
+ * This function is used to transmit data or command as a byte stream to
+ * the remote subsystem over the SPI bus.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int glink_spi_xprt_tx_data(struct edge_info *einfo, void *src,
+ void *dst, uint32_t size)
+{
+ struct wcd_spi_msg spi_msg;
+
+ memset(&spi_msg, 0, sizeof(spi_msg));
+ spi_msg.data = src;
+ spi_msg.remote_addr = (uint32_t)(size_t)dst;
+ spi_msg.len = (size_t)size;
+ return wcd_spi_data_write(einfo->spi_dev, &spi_msg);
+}
+
+/**
+ * glink_spi_xprt_reg_read() - Read the TX/RX FIFO Read/Write Index registers
+ * @einfo: Edge from which the registers have to be read.
+ * @reg_addr: Address of the register to be read.
+ * @data: Buffer into which the register data has to be read.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int glink_spi_xprt_reg_read(struct edge_info *einfo, u32 reg_addr,
+ uint32_t *data)
+{
+ int rc;
+
+ rc = glink_spi_xprt_rx_data(einfo, (void *)(unsigned long)reg_addr,
+ data, sizeof(*data));
+ if (!rc)
+ *data = *data & ID_MASK;
+ return rc;
+}
+
+/**
+ * glink_spi_xprt_reg_write() - Write the TX/RX FIFO Read/Write Index registers
+ * @einfo: Edge to which the registers have to be written.
+ * @reg_addr: Address of the registers to be written.
+ * @data: Data to be written to the registers.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+static int glink_spi_xprt_reg_write(struct edge_info *einfo, u32 reg_addr,
+ uint32_t data)
+{
+ return glink_spi_xprt_tx_data(einfo, &data,
+ (void *)(unsigned long)reg_addr, sizeof(data));
+}
+
+/**
+ * glink_spi_xprt_write_avail() - Available Write Space in the remote side
+ * @einfo: Edge information corresponding to the remote side.
+ *
+ * This function reads the TX FIFO Read & Write Index registers from the
+ * remote subsystem and calculate the available write space.
+ *
+ * Return: 0 on error, available write space on success.
+ */
+static int glink_spi_xprt_write_avail(struct edge_info *einfo)
+{
+ uint32_t read_id;
+ uint32_t write_id;
+ int write_avail;
+ int ret;
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->tx_fifo_read_reg_addr,
+ &read_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s tx_fifo_read_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->tx_fifo_read_reg_addr);
+ return 0;
+ }
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->tx_fifo_write_reg_addr,
+ &write_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s tx_fifo_write_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->tx_fifo_write_reg_addr);
+ return 0;
+ }
+
+ if (!read_id || !write_id)
+ return 0;
+
+ if (unlikely(!einfo->tx_fifo_start))
+ einfo->tx_fifo_start = write_id;
+
+ if (read_id > write_id)
+ write_avail = read_id - write_id;
+ else
+ write_avail = einfo->fifo_size - (write_id - read_id);
+
+ if (write_avail < FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE)
+ write_avail = 0;
+ else
+ write_avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE;
+
+ return write_avail;
+}
+
+/**
+ * glink_spi_xprt_read_avail() - Available Read Data from the remote side
+ * @einfo: Edge information corresponding to the remote side.
+ *
+ * This function reads the RX FIFO Read & Write Index registers from the
+ * remote subsystem and calculate the available read data size.
+ *
+ * Return: 0 on error, available read data on success.
+ */
+static int glink_spi_xprt_read_avail(struct edge_info *einfo)
+{
+ uint32_t read_id;
+ uint32_t write_id;
+ int read_avail;
+ int ret;
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->rx_fifo_read_reg_addr,
+ &read_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s rx_fifo_read_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->rx_fifo_read_reg_addr);
+ return 0;
+ }
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->rx_fifo_write_reg_addr,
+ &write_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s rx_fifo_write_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->rx_fifo_write_reg_addr);
+ return 0;
+ }
+
+ if (!read_id || !write_id)
+ return 0;
+
+ if (unlikely(!einfo->rx_fifo_start))
+ einfo->rx_fifo_start = read_id;
+
+ if (read_id <= write_id)
+ read_avail = write_id - read_id;
+ else
+ read_avail = einfo->fifo_size - (read_id - write_id);
+ return read_avail;
+}
+
+/**
+ * glink_spi_xprt_rx_cmd() - Receive G-Link commands
+ * @einfo: Edge information corresponding to the remote side.
+ * @dst: Destination buffer where the commands have to be read into.
+ * @size: Size of the data to be read.
+ *
+ * This function is used to receive the commands from the RX FIFO. This
+ * function updates the RX FIFO Read Index after reading the data.
+ *
+ * Return: 0 on success, standard Linux error codes on error.
+ */
+static int glink_spi_xprt_rx_cmd(struct edge_info *einfo, void *dst,
+ uint32_t size)
+{
+ uint32_t read_id;
+ uint32_t size_to_read = size;
+ uint32_t offset = 0;
+ int ret;
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->rx_fifo_read_reg_addr,
+ &read_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s rx_fifo_read_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->rx_fifo_read_reg_addr);
+ return ret;
+ }
+
+ do {
+ if ((read_id + size_to_read) >=
+ (einfo->rx_fifo_start + einfo->fifo_size))
+ size_to_read = einfo->rx_fifo_start + einfo->fifo_size
+ - read_id;
+ ret = glink_spi_xprt_rx_data(einfo, (void *)(size_t)read_id,
+ dst + offset, size_to_read);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading data\n", __func__, ret);
+ return ret;
+ }
+ read_id += size_to_read;
+ offset += size_to_read;
+ if (read_id >= (einfo->rx_fifo_start + einfo->fifo_size))
+ read_id = einfo->rx_fifo_start;
+ size_to_read = size - offset;
+ } while (size_to_read);
+
+ ret = glink_spi_xprt_reg_write(einfo, einfo->rx_fifo_read_reg_addr,
+ read_id);
+ if (ret < 0)
+ pr_err("%s: Error %d writing %s rx_fifo_read_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->rx_fifo_read_reg_addr);
+ return ret;
+}
+
+/**
+ * glink_spi_xprt_tx_cmd_safe() - Transmit G-Link commands
+ * @einfo: Edge information corresponding to the remote subsystem.
+ * @src: Source buffer containing the G-Link command.
+ * @size: Size of the command to transmit.
+ *
+ * This function is used to transmit the G-Link commands. This function
+ * must be called with einfo->write_lock locked.
+ *
+ * Return: 0 on success, standard Linux error codes on error.
+ */
+static int glink_spi_xprt_tx_cmd_safe(struct edge_info *einfo, void *src,
+ uint32_t size)
+{
+ uint32_t write_id;
+ uint32_t size_to_write = size;
+ uint32_t offset = 0;
+ int ret;
+
+ ret = glink_spi_xprt_reg_read(einfo, einfo->tx_fifo_write_reg_addr,
+ &write_id);
+ if (ret < 0) {
+ pr_err("%s: Error %d reading %s tx_fifo_write_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->tx_fifo_write_reg_addr);
+ return ret;
+ }
+
+ do {
+ if ((write_id + size_to_write) >=
+ (einfo->tx_fifo_start + einfo->fifo_size))
+ size_to_write = einfo->tx_fifo_start + einfo->fifo_size
+ - write_id;
+ ret = glink_spi_xprt_tx_data(einfo, src + offset,
+ (void *)(size_t)write_id, size_to_write);
+ if (ret < 0) {
+ pr_err("%s: Error %d writing data\n", __func__, ret);
+ return ret;
+ }
+ write_id += size_to_write;
+ offset += size_to_write;
+ if (write_id >= (einfo->tx_fifo_start + einfo->fifo_size))
+ write_id = einfo->tx_fifo_start;
+ size_to_write = size - offset;
+ } while (size_to_write);
+
+ ret = glink_spi_xprt_reg_write(einfo, einfo->tx_fifo_write_reg_addr,
+ write_id);
+ if (ret < 0)
+ pr_err("%s: Error %d writing %s tx_fifo_write_reg_addr %d\n",
+ __func__, ret, einfo->xprt_cfg.edge,
+ einfo->tx_fifo_write_reg_addr);
+ return ret;
+}
+
+/**
+ * send_tx_blocked_signal() - Send flow control request message
+ * @einfo: Edge information corresponding to the remote subsystem.
+ *
+ * This function is used to send a message to the remote subsystem indicating
+ * that the local subsystem is waiting for the write space. The remote
+ * subsystem on receiving this message will send a resume tx message.
+ */
+static void send_tx_blocked_signal(struct edge_info *einfo)
+{
+ struct read_notif_request {
+ uint16_t cmd;
+ uint16_t reserved;
+ uint32_t reserved2;
+ uint64_t reserved3;
+ };
+ struct read_notif_request read_notif_req = {0};
+
+ read_notif_req.cmd = READ_NOTIF_CMD;
+
+ if (!einfo->tx_blocked_signal_sent) {
+ einfo->tx_blocked_signal_sent = true;
+ glink_spi_xprt_tx_cmd_safe(einfo, &read_notif_req,
+ sizeof(read_notif_req));
+ }
+}
+
+/**
+ * glink_spi_xprt_tx_cmd() - Transmit G-Link commands
+ * @einfo: Edge information corresponding to the remote subsystem.
+ * @src: Source buffer containing the G-Link command.
+ * @size: Size of the command to transmit.
+ *
+ * This function is used to transmit the G-Link commands. This function
+ * might sleep if the space is not available to transmit the command.
+ *
+ * Return: 0 on success, standard Linux error codes on error.
+ */
+static int glink_spi_xprt_tx_cmd(struct edge_info *einfo, void *src,
+ uint32_t size)
+{
+ int ret;
+ DEFINE_WAIT(wait);
+
+ mutex_lock(&einfo->write_lock);
+ while (glink_spi_xprt_write_avail(einfo) < size) {
+ send_tx_blocked_signal(einfo);
+ prepare_to_wait(&einfo->tx_blocked_queue, &wait,
+ TASK_UNINTERRUPTIBLE);
+ if (glink_spi_xprt_write_avail(einfo) < size &&
+ !einfo->in_ssr) {
+ mutex_unlock(&einfo->write_lock);
+ schedule();
+ mutex_lock(&einfo->write_lock);
+ }
+ finish_wait(&einfo->tx_blocked_queue, &wait);
+ if (einfo->in_ssr) {
+ mutex_unlock(&einfo->write_lock);
+ return -EFAULT;
+ }
+ }
+ ret = glink_spi_xprt_tx_cmd_safe(einfo, src, size);
+ mutex_unlock(&einfo->write_lock);
+ return ret;
+}
+
+/**
+ * process_rx_data() - process received data from an edge
+ * @einfo: The edge the data is received on.
+ * @cmd_id: ID to specify the type of data.
+ * @rcid: The remote channel id associated with the data.
+ * @intend_id: The intent the data should be put in.
+ * @src: Address of the source buffer from which the data
+ * is read.
+ * @frag_size: Size of the data fragment to read.
+ * @size_remaining: Size of data left to be read in this packet.
+ */
+static void process_rx_data(struct edge_info *einfo, uint16_t cmd_id,
+ uint32_t rcid, uint32_t intent_id, void *src,
+ uint32_t frag_size, uint32_t size_remaining)
+{
+ struct glink_core_rx_intent *intent;
+ int rc = 0;
+
+ intent = einfo->xprt_if.glink_core_if_ptr->rx_get_pkt_ctx(
+ &einfo->xprt_if, rcid, intent_id);
+ if (intent == NULL) {
+ GLINK_ERR("%s: no intent for ch %d liid %d\n", __func__, rcid,
+ intent_id);
+ return;
+ } else if (intent->data == NULL) {
+ GLINK_ERR("%s: intent for ch %d liid %d has no data buff\n",
+ __func__, rcid, intent_id);
+ return;
+ } else if (intent->intent_size - intent->write_offset < frag_size ||
+ intent->write_offset + size_remaining > intent->intent_size) {
+ GLINK_ERR("%s: rx data size:%d and remaining:%d %s %d %s:%d\n",
+ __func__, frag_size, size_remaining,
+ "will overflow ch", rcid, "intent", intent_id);
+ return;
+ }
+
+ if (cmd_id == TX_SHORT_DATA_CMD)
+ memcpy(intent->data + intent->write_offset, src, frag_size);
+ else
+ rc = glink_spi_xprt_rx_data(einfo, src,
+ intent->data + intent->write_offset, frag_size);
+ if (rc < 0) {
+ GLINK_ERR("%s: Error %d receiving data %d:%d:%d:%d\n",
+ __func__, rc, rcid, intent_id, frag_size,
+ size_remaining);
+ size_remaining += frag_size;
+ } else {
+ intent->write_offset += frag_size;
+ intent->pkt_size += frag_size;
+
+ if (unlikely((cmd_id == TRACER_PKT_CMD ||
+ cmd_id == TRACER_PKT_CONT_CMD) && !size_remaining)) {
+ tracer_pkt_log_event(intent->data, GLINK_XPRT_RX);
+ intent->tracer_pkt = true;
+ }
+ }
+ einfo->xprt_if.glink_core_if_ptr->rx_put_pkt_ctx(&einfo->xprt_if,
+ rcid, intent, size_remaining ? false : true);
+}
+
+/**
+ * process_rx_cmd() - Process incoming G-Link commands
+ * @einfo: Edge information corresponding to the remote subsystem.
+ * @rx_data: Buffer which contains the G-Link commands to be processed.
+ * @rx_size: Size of the buffer containing the series of G-Link commands.
+ *
+ * This function is used to parse and process a series of G-Link commands
+ * received in a buffer.
+ */
+static void process_rx_cmd(struct edge_info *einfo,
+ void *rx_data, int rx_size)
+{
+ struct command {
+ uint16_t id;
+ uint16_t param1;
+ uint32_t param2;
+ uint32_t param3;
+ uint32_t param4;
+ };
+ struct intent_desc {
+ uint32_t size;
+ uint32_t id;
+ uint64_t addr;
+ };
+ struct rx_desc {
+ uint32_t size;
+ uint32_t size_left;
+ uint64_t addr;
+ };
+ struct rx_short_data_desc {
+ unsigned char data[SHORT_PKT_SIZE];
+ };
+ struct command *cmd;
+ struct intent_desc *intents;
+ struct rx_desc *rx_descp;
+ struct rx_short_data_desc *rx_sd_descp;
+ int offset = 0;
+ int rcu_id;
+ uint16_t rcid;
+ uint16_t name_len;
+ uint16_t prio;
+ char *name;
+ bool granted;
+ int i;
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ while (offset < rx_size) {
+ cmd = (struct command *)(rx_data + offset);
+ offset += sizeof(*cmd);
+ switch (cmd->id) {
+ case VERSION_CMD:
+ if (cmd->param3)
+ einfo->fifo_size = cmd->param3;
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_version(
+ &einfo->xprt_if, cmd->param1, cmd->param2);
+ break;
+
+ case VERSION_ACK_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_version_ack(
+ &einfo->xprt_if, cmd->param1, cmd->param2);
+ break;
+
+ case OPEN_CMD:
+ rcid = cmd->param1;
+ name_len = (uint16_t)(cmd->param2 & 0xFFFF);
+ prio = (uint16_t)((cmd->param2 & 0xFFFF0000) >> 16);
+ name = (char *)(rx_data + offset);
+ offset += ALIGN(name_len, FIFO_ALIGNMENT);
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
+ &einfo->xprt_if, rcid, name, prio);
+ break;
+
+ case CLOSE_CMD:
+ einfo->xprt_if.glink_core_if_ptr->
+ rx_cmd_ch_remote_close(
+ &einfo->xprt_if, cmd->param1);
+ break;
+
+ case OPEN_ACK_CMD:
+ prio = (uint16_t)(cmd->param2 & 0xFFFF);
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_open_ack(
+ &einfo->xprt_if, cmd->param1, prio);
+ break;
+
+ case CLOSE_ACK_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
+ &einfo->xprt_if, cmd->param1);
+ break;
+
+ case RX_INTENT_CMD:
+ for (i = 0; i < cmd->param2; i++) {
+ intents = (struct intent_desc *)
+ (rx_data + offset);
+ offset += sizeof(*intents);
+ einfo->xprt_if.glink_core_if_ptr->
+ rx_cmd_remote_rx_intent_put_cookie(
+ &einfo->xprt_if, cmd->param1,
+ intents->id, intents->size,
+ (void *)(intents->addr));
+ }
+ break;
+
+ case RX_DONE_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_tx_done(
+ &einfo->xprt_if, cmd->param1, cmd->param2,
+ false);
+ break;
+
+ case RX_INTENT_REQ_CMD:
+ einfo->xprt_if.glink_core_if_ptr->
+ rx_cmd_remote_rx_intent_req(
+ &einfo->xprt_if, cmd->param1,
+ cmd->param2);
+ break;
+
+ case RX_INTENT_REQ_ACK_CMD:
+ granted = cmd->param2 == 1 ? true : false;
+ einfo->xprt_if.glink_core_if_ptr->
+ rx_cmd_rx_intent_req_ack(&einfo->xprt_if,
+ cmd->param1, granted);
+ break;
+
+ case TX_DATA_CMD:
+ case TX_DATA_CONT_CMD:
+ case TRACER_PKT_CMD:
+ case TRACER_PKT_CONT_CMD:
+ rx_descp = (struct rx_desc *)(rx_data + offset);
+ offset += sizeof(*rx_descp);
+ process_rx_data(einfo, cmd->id, cmd->param1,
+ cmd->param2, (void *)rx_descp->addr,
+ rx_descp->size, rx_descp->size_left);
+ break;
+
+ case TX_SHORT_DATA_CMD:
+ rx_sd_descp = (struct rx_short_data_desc *)
+ (rx_data + offset);
+ offset += sizeof(*rx_sd_descp);
+ process_rx_data(einfo, cmd->id, cmd->param1,
+ cmd->param2, (void *)rx_sd_descp->data,
+ cmd->param3, cmd->param4);
+ break;
+
+ case READ_NOTIF_CMD:
+ break;
+
+ case SIGNALS_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_remote_sigs(
+ &einfo->xprt_if, cmd->param1, cmd->param2);
+ break;
+
+ case RX_DONE_W_REUSE_CMD:
+ einfo->xprt_if.glink_core_if_ptr->rx_cmd_tx_done(
+ &einfo->xprt_if, cmd->param1,
+ cmd->param2, true);
+ break;
+
+ default:
+ pr_err("Unrecognized command: %d\n", cmd->id);
+ break;
+ }
+ }
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * __rx_worker() - Receive commands on a specific edge
+ * @einfo: Edge to process commands on.
+ *
+ * This function checks the size of data to be received, allocates the
+ * buffer for that data and reads the data from the remote subsytem
+ * into that buffer. This function then calls the process_rx_cmd() to
+ * parse the received G-Link command sequence. This function will also
+ * poll for the data for a predefined duration for performance reasons.
+ */
+static void __rx_worker(struct edge_info *einfo)
+{
+ uint32_t inactive_cycles = 0;
+ int rx_avail, rc;
+ void *rx_data;
+ int rcu_id;
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (unlikely(!einfo->rx_fifo_start)) {
+ rx_avail = glink_spi_xprt_read_avail(einfo);
+ if (!rx_avail) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+ einfo->in_ssr = false;
+ einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
+ }
+
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ glink_spi_xprt_set_poll_mode(einfo);
+ while (inactive_cycles < MAX_INACTIVE_CYCLES) {
+ if (einfo->tx_resume_needed &&
+ glink_spi_xprt_write_avail(einfo)) {
+ einfo->tx_resume_needed = false;
+ einfo->xprt_if.glink_core_if_ptr->tx_resume(
+ &einfo->xprt_if);
+ }
+ mutex_lock(&einfo->write_lock);
+ if (einfo->tx_blocked_signal_sent) {
+ wake_up_all(&einfo->tx_blocked_queue);
+ einfo->tx_blocked_signal_sent = false;
+ }
+ mutex_unlock(&einfo->write_lock);
+
+ rx_avail = glink_spi_xprt_read_avail(einfo);
+ if (!rx_avail) {
+ usleep_range(POLL_INTERVAL_US, POLL_INTERVAL_US + 50);
+ inactive_cycles++;
+ continue;
+ }
+ inactive_cycles = 0;
+
+ rx_data = kzalloc(rx_avail, GFP_KERNEL);
+ if (!rx_data)
+ break;
+
+ rc = glink_spi_xprt_rx_cmd(einfo, rx_data, rx_avail);
+ if (rc < 0) {
+ GLINK_ERR("%s: Error %d receiving data\n",
+ __func__, rc);
+ kfree(rx_data);
+ break;
+ }
+ process_rx_cmd(einfo, rx_data, rx_avail);
+ kfree(rx_data);
+ }
+ glink_spi_xprt_set_irq_mode(einfo);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * rx_worker() - Worker function to process received commands
+ * @work: kwork associated with the edge to process commands on.
+ */
+static void rx_worker(struct kthread_work *work)
+{
+ struct edge_info *einfo;
+
+ einfo = container_of(work, struct edge_info, kwork);
+ __rx_worker(einfo);
+};
+
+/**
+ * tx_cmd_version() - Convert a version cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @version: The version number to encode.
+ * @features: The features information to encode.
+ */
+static void tx_cmd_version(struct glink_transport_if *if_ptr, uint32_t version,
+ uint32_t features)
+{
+ struct command {
+ uint16_t id;
+ uint16_t version;
+ uint32_t features;
+ uint32_t fifo_size;
+ uint32_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = VERSION_CMD;
+ cmd.version = version;
+ cmd.features = features;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_version_ack() - Convert a version ack cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @version: The version number to encode.
+ * @features: The features information to encode.
+ */
+static void tx_cmd_version_ack(struct glink_transport_if *if_ptr,
+ uint32_t version,
+ uint32_t features)
+{
+ struct command {
+ uint16_t id;
+ uint16_t version;
+ uint32_t features;
+ uint32_t fifo_size;
+ uint32_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = VERSION_ACK_CMD;
+ cmd.version = version;
+ cmd.features = features;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * set_version() - Activate a negotiated version and feature set
+ * @if_ptr: The transport to configure.
+ * @version: The version to use.
+ * @features: The features to use.
+ *
+ * Return: The supported capabilities of the transport.
+ */
+static uint32_t set_version(struct glink_transport_if *if_ptr, uint32_t version,
+ uint32_t features)
+{
+ struct edge_info *einfo;
+ uint32_t ret;
+ int rcu_id;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+ }
+
+ ret = GCAP_SIGNALS;
+ if (features & TRACER_PKT_FEATURE)
+ ret |= GCAP_TRACER_PKT;
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return ret;
+}
+
+/**
+ * tx_cmd_ch_open() - Convert a channel open cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @name: The channel name to encode.
+ * @req_xprt: The transport the core would like to migrate this channel to.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_ch_open(struct glink_transport_if *if_ptr, uint32_t lcid,
+ const char *name, uint16_t req_xprt)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint16_t length;
+ uint16_t req_xprt;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ uint32_t buf_size;
+ void *buf;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = OPEN_CMD;
+ cmd.lcid = lcid;
+ cmd.length = (uint16_t)(strlen(name) + 1);
+ cmd.req_xprt = req_xprt;
+
+ buf_size = ALIGN(sizeof(cmd) + cmd.length, FIFO_ALIGNMENT);
+
+ buf = kzalloc(buf_size, GFP_KERNEL);
+ if (!buf) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -ENOMEM;
+ }
+
+ memcpy(buf, &cmd, sizeof(cmd));
+ memcpy(buf + sizeof(cmd), name, cmd.length);
+
+ glink_spi_xprt_tx_cmd(einfo, buf, buf_size);
+
+ kfree(buf);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_ch_close() - Convert a channel close cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_ch_close(struct glink_transport_if *if_ptr, uint32_t lcid)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t reserved1;
+ uint64_t reserved2;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = CLOSE_CMD;
+ cmd.lcid = lcid;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_ch_remote_open_ack() - Convert a channel open ack cmd to wire format
+ * and transmit
+ * @if_ptr: The transport to transmit on.
+ * @rcid: The remote channel id to encode.
+ * @xprt_resp: The response to a transport migration request.
+ */
+static void tx_cmd_ch_remote_open_ack(struct glink_transport_if *if_ptr,
+ uint32_t rcid, uint16_t xprt_resp)
+{
+ struct command {
+ uint16_t id;
+ uint16_t rcid;
+ uint16_t reserved1;
+ uint16_t xprt_resp;
+ uint64_t reserved2;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = OPEN_ACK_CMD;
+ cmd.rcid = rcid;
+ cmd.xprt_resp = xprt_resp;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_ch_remote_close_ack() - Convert a channel close ack cmd to wire format
+ * and transmit
+ * @if_ptr: The transport to transmit on.
+ * @rcid: The remote channel id to encode.
+ */
+static void tx_cmd_ch_remote_close_ack(struct glink_transport_if *if_ptr,
+ uint32_t rcid)
+{
+ struct command {
+ uint16_t id;
+ uint16_t rcid;
+ uint32_t reserved1;
+ uint64_t reserved2;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = CLOSE_ACK_CMD;
+ cmd.rcid = rcid;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * ssr() - Process a subsystem restart notification of a transport
+ * @if_ptr: The transport to restart
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int ssr(struct glink_transport_if *if_ptr)
+{
+ struct edge_info *einfo;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ einfo->in_ssr = true;
+ wake_up_all(&einfo->tx_blocked_queue);
+
+ synchronize_srcu(&einfo->use_ref);
+ einfo->tx_resume_needed = false;
+ einfo->tx_blocked_signal_sent = false;
+ einfo->tx_fifo_start = 0;
+ einfo->rx_fifo_start = 0;
+ einfo->fifo_size = DEFAULT_FIFO_SIZE;
+ einfo->xprt_if.glink_core_if_ptr->link_down(&einfo->xprt_if);
+
+ return 0;
+}
+
+/**
+ * allocate_rx_intent() - Allocate/reserve space for RX Intent
+ * @if_ptr: The transport the intent is associated with.
+ * @size: size of intent.
+ * @intent: Pointer to the intent structure.
+ *
+ * Assign "data" with the buffer created, since the transport creates
+ * a linear buffer and "iovec" with the "intent" itself, so that
+ * the data can be passed to a client that receives only vector buffer.
+ * Note that returning NULL for the pointer is valid (it means that space has
+ * been reserved, but the actual pointer will be provided later).
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int allocate_rx_intent(struct glink_transport_if *if_ptr, size_t size,
+ struct glink_core_rx_intent *intent)
+{
+ void *t;
+
+ t = kzalloc(size, GFP_KERNEL);
+ if (!t)
+ return -ENOMEM;
+
+ intent->data = t;
+ intent->iovec = (void *)intent;
+ intent->vprovider = rx_linear_vbuf_provider;
+ intent->pprovider = NULL;
+ return 0;
+}
+
+/**
+ * deallocate_rx_intent() - Deallocate space created for RX Intent
+ * @if_ptr: The transport the intent is associated with.
+ * @intent: Pointer to the intent structure.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int deallocate_rx_intent(struct glink_transport_if *if_ptr,
+ struct glink_core_rx_intent *intent)
+{
+ if (!intent || !intent->data)
+ return -EINVAL;
+
+ kfree(intent->data);
+ intent->data = NULL;
+ intent->iovec = NULL;
+ intent->vprovider = NULL;
+ return 0;
+}
+
+/**
+ * tx_cmd_local_rx_intent() - Convert an rx intent cmd to wire format and
+ * transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @size: The intent size to encode.
+ * @liid: The local intent id to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_local_rx_intent(struct glink_transport_if *if_ptr,
+ uint32_t lcid, size_t size, uint32_t liid)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t count;
+ uint64_t reserved;
+ uint32_t size;
+ uint32_t liid;
+ uint64_t addr;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ if (size > UINT_MAX) {
+ pr_err("%s: size %zu is too large to encode\n", __func__, size);
+ return -EMSGSIZE;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = RX_INTENT_CMD;
+ cmd.lcid = lcid;
+ cmd.count = 1;
+ cmd.size = size;
+ cmd.liid = liid;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_local_rx_done() - Convert an rx done cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @liid: The local intent id to encode.
+ * @reuse: Reuse the consumed intent.
+ */
+static void tx_cmd_local_rx_done(struct glink_transport_if *if_ptr,
+ uint32_t lcid, uint32_t liid, bool reuse)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t liid;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+ }
+
+ cmd.id = reuse ? RX_DONE_W_REUSE_CMD : RX_DONE_CMD;
+ cmd.lcid = lcid;
+ cmd.liid = liid;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_rx_intent_req() - Convert an rx intent request cmd to wire format and
+ * transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @size: The requested intent size to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_rx_intent_req(struct glink_transport_if *if_ptr,
+ uint32_t lcid, size_t size)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t size;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ if (size > UINT_MAX) {
+ pr_err("%s: size %zu is too large to encode\n", __func__, size);
+ return -EMSGSIZE;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = RX_INTENT_REQ_CMD,
+ cmd.lcid = lcid;
+ cmd.size = size;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_rx_intent_req_ack() - Convert an rx intent request ack cmd to wire
+ * format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @granted: The request response to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_remote_rx_intent_req_ack(struct glink_transport_if *if_ptr,
+ uint32_t lcid, bool granted)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t response;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = RX_INTENT_REQ_ACK_CMD,
+ cmd.lcid = lcid;
+ if (granted)
+ cmd.response = 1;
+ else
+ cmd.response = 0;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_cmd_set_sigs() - Convert a signals ack cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @sigs: The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_set_sigs(struct glink_transport_if *if_ptr, uint32_t lcid,
+ uint32_t sigs)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t sigs;
+ uint64_t reserved;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ int rcu_id;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = SIGNALS_CMD,
+ cmd.lcid = lcid;
+ cmd.sigs = sigs;
+
+ glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return 0;
+}
+
+/**
+ * tx_data() - convert a data/tracer_pkt to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @cmd_id: The command ID to transmit.
+ * @lcid: The local channel id to encode.
+ * @pctx: The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx_data(struct glink_transport_if *if_ptr, uint16_t cmd_id,
+ uint32_t lcid, struct glink_core_tx_pkt *pctx)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t riid;
+ uint64_t reserved;
+ uint32_t size;
+ uint32_t size_left;
+ uint64_t addr;
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ uint32_t size;
+ void *data_start, *dst = NULL;
+ size_t tx_size = 0;
+ int rcu_id;
+
+ if (pctx->size < pctx->size_remaining) {
+ GLINK_ERR("%s: size remaining exceeds size. Resetting.\n",
+ __func__);
+ pctx->size_remaining = pctx->size;
+ }
+ if (!pctx->size_remaining)
+ return 0;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ if (cmd_id == TX_DATA_CMD) {
+ if (pctx->size_remaining == pctx->size)
+ cmd.id = TX_DATA_CMD;
+ else
+ cmd.id = TX_DATA_CONT_CMD;
+ } else {
+ if (pctx->size_remaining == pctx->size)
+ cmd.id = TRACER_PKT_CMD;
+ else
+ cmd.id = TRACER_PKT_CONT_CMD;
+ }
+ cmd.lcid = lcid;
+ cmd.riid = pctx->riid;
+ data_start = get_tx_vaddr(pctx, pctx->size - pctx->size_remaining,
+ &tx_size);
+ if (unlikely(!data_start)) {
+ GLINK_ERR("%s: invalid data_start\n", __func__);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EINVAL;
+ }
+ if (tx_size & (XPRT_ALIGNMENT - 1))
+ tx_size = ALIGN(tx_size - SHORT_PKT_SIZE, XPRT_ALIGNMENT);
+ if (likely(pctx->cookie))
+ dst = pctx->cookie + (pctx->size - pctx->size_remaining);
+
+ mutex_lock(&einfo->write_lock);
+ size = glink_spi_xprt_write_avail(einfo);
+ /* Need enough space to write the command */
+ if (size <= sizeof(cmd)) {
+ einfo->tx_resume_needed = true;
+ mutex_unlock(&einfo->write_lock);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EAGAIN;
+ }
+ cmd.addr = 0;
+ cmd.size = tx_size;
+ pctx->size_remaining -= tx_size;
+ cmd.size_left = pctx->size_remaining;
+ if (cmd.id == TRACER_PKT_CMD)
+ tracer_pkt_log_event((void *)(pctx->data), GLINK_XPRT_TX);
+
+ if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
+ wdsp_resume(&einfo->cmpnt);
+ glink_spi_xprt_tx_data(einfo, data_start, dst, tx_size);
+ glink_spi_xprt_tx_cmd_safe(einfo, &cmd, sizeof(cmd));
+ GLINK_DBG("%s %s: lcid[%u] riid[%u] cmd[%d], size[%d], size_left[%d]\n",
+ "<SPI>", __func__, cmd.lcid, cmd.riid, cmd.id, cmd.size,
+ cmd.size_left);
+ mutex_unlock(&einfo->write_lock);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return cmd.size;
+}
+
+/**
+ * tx_short_data() - Tansmit a short packet in band along with command
+ * @if_ptr: The transport to transmit on.
+ * @cmd_id: The command ID to transmit.
+ * @lcid: The local channel id to encode.
+ * @pctx: The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx_short_data(struct glink_transport_if *if_ptr,
+ uint32_t lcid, struct glink_core_tx_pkt *pctx)
+{
+ struct command {
+ uint16_t id;
+ uint16_t lcid;
+ uint32_t riid;
+ uint32_t size;
+ uint32_t size_left;
+ unsigned char data[SHORT_PKT_SIZE];
+ };
+ struct command cmd;
+ struct edge_info *einfo;
+ uint32_t size;
+ void *data_start;
+ size_t tx_size = 0;
+ int rcu_id;
+
+ if (pctx->size < pctx->size_remaining) {
+ GLINK_ERR("%s: size remaining exceeds size. Resetting.\n",
+ __func__);
+ pctx->size_remaining = pctx->size;
+ }
+ if (!pctx->size_remaining)
+ return 0;
+
+ memset(&cmd, 0, sizeof(cmd));
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+ rcu_id = srcu_read_lock(&einfo->use_ref);
+ if (einfo->in_ssr) {
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EFAULT;
+ }
+
+ cmd.id = TX_SHORT_DATA_CMD;
+ cmd.lcid = lcid;
+ cmd.riid = pctx->riid;
+ data_start = get_tx_vaddr(pctx, pctx->size - pctx->size_remaining,
+ &tx_size);
+ if (unlikely(!data_start || tx_size > SHORT_PKT_SIZE)) {
+ GLINK_ERR("%s: invalid data_start %p or tx_size %zu\n",
+ __func__, data_start, tx_size);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&einfo->write_lock);
+ size = glink_spi_xprt_write_avail(einfo);
+ /* Need enough space to write the command */
+ if (size <= sizeof(cmd)) {
+ einfo->tx_resume_needed = true;
+ mutex_unlock(&einfo->write_lock);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return -EAGAIN;
+ }
+ cmd.size = tx_size;
+ pctx->size_remaining -= tx_size;
+ cmd.size_left = pctx->size_remaining;
+ memcpy(cmd.data, data_start, tx_size);
+ if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
+ wdsp_resume(&einfo->cmpnt);
+ glink_spi_xprt_tx_cmd_safe(einfo, &cmd, sizeof(cmd));
+ GLINK_DBG("%s %s: lcid[%u] riid[%u] cmd[%d], size[%d], size_left[%d]\n",
+ "<SPI>", __func__, cmd.lcid, cmd.riid, cmd.id, cmd.size,
+ cmd.size_left);
+ mutex_unlock(&einfo->write_lock);
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return cmd.size;
+}
+
+/**
+ * tx() - convert a data transmit cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @pctx: The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx(struct glink_transport_if *if_ptr, uint32_t lcid,
+ struct glink_core_tx_pkt *pctx)
+{
+ if (pctx->size_remaining <= SHORT_PKT_SIZE)
+ return tx_short_data(if_ptr, lcid, pctx);
+ return tx_data(if_ptr, TX_DATA_CMD, lcid, pctx);
+}
+
+/**
+ * tx_cmd_tracer_pkt() - convert a tracer packet cmd to wire format and transmit
+ * @if_ptr: The transport to transmit on.
+ * @lcid: The local channel id to encode.
+ * @pctx: The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx_cmd_tracer_pkt(struct glink_transport_if *if_ptr, uint32_t lcid,
+ struct glink_core_tx_pkt *pctx)
+{
+ return tx_data(if_ptr, TRACER_PKT_CMD, lcid, pctx);
+}
+
+/**
+ * int wait_link_down() - Check status of read/write indices
+ * @if_ptr: The transport to check
+ *
+ * Return: 1 if indices are all zero, 0 otherwise
+ */
+static int wait_link_down(struct glink_transport_if *if_ptr)
+{
+ return 0;
+}
+
+/**
+ * get_power_vote_ramp_time() - Get the ramp time required for the power
+ * votes to be applied
+ * @if_ptr: The transport interface on which power voting is requested.
+ * @state: The power state for which ramp time is required.
+ *
+ * Return: The ramp time specific to the power state, standard error otherwise.
+ */
+static unsigned long get_power_vote_ramp_time(
+ struct glink_transport_if *if_ptr, uint32_t state)
+{
+ return 0;
+}
+
+/**
+ * power_vote() - Update the power votes to meet qos requirement
+ * @if_ptr: The transport interface on which power voting is requested.
+ * @state: The power state for which the voting should be done.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int power_vote(struct glink_transport_if *if_ptr, uint32_t state)
+{
+ unsigned long flags;
+ struct edge_info *einfo;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ einfo->activity_flag |= ACTIVE_TX;
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+ return 0;
+}
+
+/**
+ * power_unvote() - Remove the all the power votes
+ * @if_ptr: The transport interface on which power voting is requested.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int power_unvote(struct glink_transport_if *if_ptr)
+{
+ unsigned long flags;
+ struct edge_info *einfo;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ einfo->activity_flag &= ~ACTIVE_TX;
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+ return 0;
+}
+
+static int glink_wdsp_cmpnt_init(struct device *dev, void *priv_data)
+{
+ return 0;
+}
+
+static int glink_wdsp_cmpnt_deinit(struct device *dev, void *priv_data)
+{
+ return 0;
+}
+
+static int glink_wdsp_cmpnt_event_handler(struct device *dev,
+ void *priv_data, enum wdsp_event_type event, void *data)
+{
+ struct edge_info *einfo = dev_get_drvdata(dev);
+ struct glink_cmpnt *cmpnt = &einfo->cmpnt;
+ struct device *sdev;
+ struct spi_device *spi_dev;
+
+ switch (event) {
+ case WDSP_EVENT_PRE_BOOTUP:
+ if (cmpnt && cmpnt->master_dev &&
+ cmpnt->master_ops &&
+ cmpnt->master_ops->get_dev_for_cmpnt)
+ sdev = cmpnt->master_ops->get_dev_for_cmpnt(
+ cmpnt->master_dev, WDSP_CMPNT_TRANSPORT);
+ else
+ sdev = NULL;
+
+ if (!sdev) {
+ dev_err(dev, "%s: Failed to get transport device\n",
+ __func__);
+ break;
+ }
+
+ spi_dev = to_spi_device(sdev);
+ einfo->spi_dev = spi_dev;
+ break;
+ case WDSP_EVENT_IPC1_INTR:
+ queue_kthread_work(&einfo->kworker, &einfo->kwork);
+ break;
+ default:
+ pr_debug("%s: unhandled event %d", __func__, event);
+ break;
+ }
+
+ return 0;
+}
+
+/* glink_wdsp_cmpnt_ops - Callback operations registered wtih WDSP framework */
+static struct wdsp_cmpnt_ops glink_wdsp_cmpnt_ops = {
+ .init = glink_wdsp_cmpnt_init,
+ .deinit = glink_wdsp_cmpnt_deinit,
+ .event_handler = glink_wdsp_cmpnt_event_handler,
+};
+
+static int glink_component_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct edge_info *einfo = dev_get_drvdata(dev);
+ struct glink_cmpnt *cmpnt = &einfo->cmpnt;
+ int ret = 0;
+
+ cmpnt->master_dev = master;
+ cmpnt->master_ops = data;
+
+ if (cmpnt->master_ops && cmpnt->master_ops->register_cmpnt_ops)
+ ret = cmpnt->master_ops->register_cmpnt_ops(master, dev, einfo,
+ &glink_wdsp_cmpnt_ops);
+ else
+ ret = -EINVAL;
+
+ if (ret)
+ dev_err(dev, "%s: register_cmpnt_ops failed, err = %d\n",
+ __func__, ret);
+ return ret;
+}
+
+static void glink_component_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct edge_info *einfo = dev_get_drvdata(dev);
+ struct glink_cmpnt *cmpnt = &einfo->cmpnt;
+
+ cmpnt->master_dev = NULL;
+ cmpnt->master_ops = NULL;
+}
+
+static const struct component_ops glink_component_ops = {
+ .bind = glink_component_bind,
+ .unbind = glink_component_unbind,
+};
+
+/**
+ * init_xprt_if() - Initialize the xprt_if for an edge
+ * @einfo: The edge to initialize.
+ */
+static void init_xprt_if(struct edge_info *einfo)
+{
+ einfo->xprt_if.tx_cmd_version = tx_cmd_version;
+ einfo->xprt_if.tx_cmd_version_ack = tx_cmd_version_ack;
+ einfo->xprt_if.set_version = set_version;
+ einfo->xprt_if.tx_cmd_ch_open = tx_cmd_ch_open;
+ einfo->xprt_if.tx_cmd_ch_close = tx_cmd_ch_close;
+ einfo->xprt_if.tx_cmd_ch_remote_open_ack = tx_cmd_ch_remote_open_ack;
+ einfo->xprt_if.tx_cmd_ch_remote_close_ack = tx_cmd_ch_remote_close_ack;
+ einfo->xprt_if.ssr = ssr;
+ einfo->xprt_if.allocate_rx_intent = allocate_rx_intent;
+ einfo->xprt_if.deallocate_rx_intent = deallocate_rx_intent;
+ einfo->xprt_if.tx_cmd_local_rx_intent = tx_cmd_local_rx_intent;
+ einfo->xprt_if.tx_cmd_local_rx_done = tx_cmd_local_rx_done;
+ einfo->xprt_if.tx = tx;
+ einfo->xprt_if.tx_cmd_rx_intent_req = tx_cmd_rx_intent_req;
+ einfo->xprt_if.tx_cmd_remote_rx_intent_req_ack =
+ tx_cmd_remote_rx_intent_req_ack;
+ einfo->xprt_if.tx_cmd_set_sigs = tx_cmd_set_sigs;
+ einfo->xprt_if.wait_link_down = wait_link_down;
+ einfo->xprt_if.tx_cmd_tracer_pkt = tx_cmd_tracer_pkt;
+ einfo->xprt_if.get_power_vote_ramp_time = get_power_vote_ramp_time;
+ einfo->xprt_if.power_vote = power_vote;
+ einfo->xprt_if.power_unvote = power_unvote;
+}
+
+/**
+ * init_xprt_cfg() - Initialize the xprt_cfg for an edge
+ * @einfo: The edge to initialize.
+ * @name: The name of the remote side this edge communicates to.
+ */
+static void init_xprt_cfg(struct edge_info *einfo, const char *name)
+{
+ einfo->xprt_cfg.name = XPRT_NAME;
+ einfo->xprt_cfg.edge = name;
+ einfo->xprt_cfg.versions = versions;
+ einfo->xprt_cfg.versions_entries = ARRAY_SIZE(versions);
+ einfo->xprt_cfg.max_cid = SZ_64K;
+ einfo->xprt_cfg.max_iid = SZ_2G;
+}
+
+/**
+ * parse_qos_dt_params() - Parse the power states from DT
+ * @dev: Reference to the platform device for a specific edge.
+ * @einfo: Edge information for the edge probe function is called.
+ *
+ * Return: 0 on success, standard error code otherwise.
+ */
+static int parse_qos_dt_params(struct device_node *node,
+ struct edge_info *einfo)
+{
+ int rc;
+ int i;
+ char *key;
+ uint32_t *arr32;
+ uint32_t num_states;
+
+ key = "qcom,ramp-time";
+ if (!of_find_property(node, key, &num_states))
+ return -ENODEV;
+
+ num_states /= sizeof(uint32_t);
+
+ einfo->num_pw_states = num_states;
+
+ arr32 = kmalloc_array(num_states, sizeof(uint32_t), GFP_KERNEL);
+ if (!arr32)
+ return -ENOMEM;
+
+ einfo->ramp_time_us = kmalloc_array(num_states, sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!einfo->ramp_time_us) {
+ rc = -ENOMEM;
+ goto mem_alloc_fail;
+ }
+
+ rc = of_property_read_u32_array(node, key, arr32, num_states);
+ if (rc) {
+ rc = -ENODEV;
+ goto invalid_key;
+ }
+ for (i = 0; i < num_states; i++)
+ einfo->ramp_time_us[i] = arr32[i];
+
+ kfree(arr32);
+ return 0;
+
+invalid_key:
+ kfree(einfo->ramp_time_us);
+mem_alloc_fail:
+ kfree(arr32);
+ return rc;
+}
+
+/**
+ * parse_qos_dt_params() - Parse any remote FIFO configuration
+ * @node: Reference to the platform device for a specific edge.
+ * @einfo: Edge information for the edge probe function is called.
+ *
+ * Return: 0 on success, standard error code otherwise.
+ */
+static int parse_remote_fifo_cfg(struct device_node *node,
+ struct edge_info *einfo)
+{
+ int rc;
+ char *key;
+
+ key = "qcom,out-read-idx-reg";
+ rc = of_property_read_u32(node, key, &einfo->tx_fifo_read_reg_addr);
+ if (rc)
+ goto key_error;
+
+ key = "qcom,out-write-idx-reg";
+ rc = of_property_read_u32(node, key, &einfo->tx_fifo_write_reg_addr);
+ if (rc)
+ goto key_error;
+
+ key = "qcom,in-read-idx-reg";
+ rc = of_property_read_u32(node, key, &einfo->rx_fifo_read_reg_addr);
+ if (rc)
+ goto key_error;
+
+ key = "qcom,in-write-idx-reg";
+ rc = of_property_read_u32(node, key, &einfo->rx_fifo_write_reg_addr);
+ if (rc)
+ goto key_error;
+ return 0;
+
+key_error:
+ pr_err("%s: Error %d parsing key %s\n", __func__, rc, key);
+ return rc;
+}
+
+static int glink_spi_probe(struct platform_device *pdev)
+{
+ struct device_node *node;
+ struct device_node *phandle_node;
+ struct edge_info *einfo;
+ int rc;
+ char *key;
+ const char *subsys_name;
+ unsigned long flags;
+
+ node = pdev->dev.of_node;
+
+ einfo = kzalloc(sizeof(*einfo), GFP_KERNEL);
+ if (!einfo) {
+ rc = -ENOMEM;
+ goto edge_info_alloc_fail;
+ }
+
+ key = "label";
+ subsys_name = of_get_property(node, key, NULL);
+ if (!subsys_name) {
+ pr_err("%s: missing key %s\n", __func__, key);
+ rc = -ENODEV;
+ goto missing_key;
+ }
+ strlcpy(einfo->subsys_name, subsys_name, sizeof(einfo->subsys_name));
+
+ init_xprt_cfg(einfo, subsys_name);
+ init_xprt_if(einfo);
+
+ einfo->in_ssr = true;
+ einfo->fifo_size = DEFAULT_FIFO_SIZE;
+ init_kthread_work(&einfo->kwork, rx_worker);
+ init_kthread_worker(&einfo->kworker);
+ init_srcu_struct(&einfo->use_ref);
+ mutex_init(&einfo->write_lock);
+ init_waitqueue_head(&einfo->tx_blocked_queue);
+ spin_lock_init(&einfo->activity_lock);
+
+ spin_lock_irqsave(&edge_infos_lock, flags);
+ list_add_tail(&einfo->list, &edge_infos);
+ spin_unlock_irqrestore(&edge_infos_lock, flags);
+
+ einfo->task = kthread_run(kthread_worker_fn, &einfo->kworker,
+ "spi_%s", subsys_name);
+ if (IS_ERR(einfo->task)) {
+ rc = PTR_ERR(einfo->task);
+ pr_err("%s: kthread run failed %d\n", __func__, rc);
+ goto kthread_fail;
+ }
+
+ key = "qcom,remote-fifo-config";
+ phandle_node = of_parse_phandle(node, key, 0);
+ if (phandle_node)
+ parse_remote_fifo_cfg(phandle_node, einfo);
+
+ key = "qcom,qos-config";
+ phandle_node = of_parse_phandle(node, key, 0);
+ if (phandle_node && !(of_get_glink_core_qos_cfg(phandle_node,
+ &einfo->xprt_cfg)))
+ parse_qos_dt_params(node, einfo);
+
+ rc = glink_core_register_transport(&einfo->xprt_if, &einfo->xprt_cfg);
+ if (rc == -EPROBE_DEFER)
+ goto reg_xprt_fail;
+ if (rc) {
+ pr_err("%s: glink core register transport failed: %d\n",
+ __func__, rc);
+ goto reg_xprt_fail;
+ }
+
+ dev_set_drvdata(&pdev->dev, einfo);
+ if (!strcmp(einfo->xprt_cfg.edge, "wdsp")) {
+ rc = component_add(&pdev->dev, &glink_component_ops);
+ if (rc) {
+ pr_err("%s: component_add failed, err = %d\n",
+ __func__, rc);
+ rc = -ENODEV;
+ goto reg_cmpnt_fail;
+ }
+ }
+ return 0;
+
+reg_cmpnt_fail:
+ dev_set_drvdata(&pdev->dev, NULL);
+ glink_core_unregister_transport(&einfo->xprt_if);
+reg_xprt_fail:
+ flush_kthread_worker(&einfo->kworker);
+ kthread_stop(einfo->task);
+ einfo->task = NULL;
+kthread_fail:
+ spin_lock_irqsave(&edge_infos_lock, flags);
+ list_del(&einfo->list);
+ spin_unlock_irqrestore(&edge_infos_lock, flags);
+missing_key:
+ kfree(einfo);
+edge_info_alloc_fail:
+ return rc;
+}
+
+static int glink_spi_remove(struct platform_device *pdev)
+{
+ struct edge_info *einfo;
+ unsigned long flags;
+
+ einfo = (struct edge_info *)dev_get_drvdata(&pdev->dev);
+ glink_core_unregister_transport(&einfo->xprt_if);
+ flush_kthread_worker(&einfo->kworker);
+ kthread_stop(einfo->task);
+ einfo->task = NULL;
+ spin_lock_irqsave(&edge_infos_lock, flags);
+ list_del(&einfo->list);
+ spin_unlock_irqrestore(&edge_infos_lock, flags);
+ kfree(einfo);
+ return 0;
+}
+
+static int glink_spi_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int glink_spi_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ unsigned long flags;
+ struct edge_info *einfo;
+ bool suspend;
+ int rc = -EBUSY;
+
+ einfo = (struct edge_info *)dev_get_drvdata(&pdev->dev);
+ if (strcmp(einfo->xprt_cfg.edge, "wdsp"))
+ return 0;
+
+ spin_lock_irqsave(&einfo->activity_lock, flags);
+ suspend = !(einfo->activity_flag);
+ spin_unlock_irqrestore(&einfo->activity_lock, flags);
+ if (suspend)
+ rc = wdsp_suspend(&einfo->cmpnt);
+ if (rc < 0)
+ pr_err("%s: Could not suspend activity_flag %d, rc %d\n",
+ __func__, einfo->activity_flag, rc);
+ return rc;
+}
+
+static const struct of_device_id spi_match_table[] = {
+ { .compatible = "qcom,glink-spi-xprt" },
+ {},
+};
+
+static struct platform_driver glink_spi_driver = {
+ .probe = glink_spi_probe,
+ .remove = glink_spi_remove,
+ .resume = glink_spi_resume,
+ .suspend = glink_spi_suspend,
+ .driver = {
+ .name = "msm_glink_spi_xprt",
+ .owner = THIS_MODULE,
+ .of_match_table = spi_match_table,
+ },
+};
+
+static int __init glink_spi_xprt_init(void)
+{
+ int rc;
+
+ rc = platform_driver_register(&glink_spi_driver);
+ if (rc)
+ pr_err("%s: glink_spi register failed %d\n", __func__, rc);
+
+ return rc;
+}
+module_init(glink_spi_xprt_init);
+
+static void __exit glink_spi_xprt_exit(void)
+{
+ platform_driver_unregister(&glink_spi_driver);
+}
+module_exit(glink_spi_xprt_exit);
+
+MODULE_DESCRIPTION("MSM G-Link SPI Transport");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/glink_xprt_if.h b/drivers/soc/qcom/glink_xprt_if.h
index 6242e867fe72..f4d5a3b303db 100644
--- a/drivers/soc/qcom/glink_xprt_if.h
+++ b/drivers/soc/qcom/glink_xprt_if.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -28,6 +28,7 @@ enum buf_type {
enum xprt_ids {
SMEM_XPRT_ID = 100,
+ SPIV2_XPRT_ID = SMEM_XPRT_ID,
SMD_TRANS_XPRT_ID = 200,
LLOOP_XPRT_ID = 300,
MOCK_XPRT_HIGH_ID = 390,
@@ -56,6 +57,7 @@ enum xprt_ids {
* @iovec: Pointer to the vector buffer packet.
* @vprovider: Packet-specific virtual buffer provider function.
* @pprovider: Packet-specific physical buffer provider function.
+ * @cookie: Transport-specific cookie
* @pkt_ref: Active references to the packet.
*/
struct glink_core_tx_pkt {
@@ -73,6 +75,7 @@ struct glink_core_tx_pkt {
void *iovec;
void * (*vprovider)(void *iovec, size_t offset, size_t *size);
void * (*pprovider)(void *iovec, size_t offset, size_t *size);
+ void *cookie;
struct rwref_lock pkt_ref;
};
diff --git a/drivers/soc/qcom/irq-helper.c b/drivers/soc/qcom/irq-helper.c
index 270a1ba9ba19..2bb71464d165 100644
--- a/drivers/soc/qcom/irq-helper.c
+++ b/drivers/soc/qcom/irq-helper.c
@@ -18,6 +18,7 @@
#include <linux/kobject.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
+#include <soc/qcom/irq-helper.h>
struct irq_helper {
bool enable;
@@ -161,7 +162,7 @@ static int __init irq_helper_init(void)
irq_h->enable = true;
return 0;
out_put_kobj:
- koject_put(&irq_h->kobj);
+ kobject_put(&irq_h->kobj);
out_free_irq:
kfree(irq_h);
return ret;
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index b055234326b6..eaeb8d4776fe 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -813,15 +813,19 @@ int pil_boot(struct pil_desc *desc)
}
if (desc->subsys_vmid > 0) {
- /* Make sure the memory is actually assigned to Linux. In the
- * case where the shutdown sequence is not able to immediately
- * assign the memory back to Linux, we need to do this here. */
- ret = pil_assign_mem_to_linux(desc, priv->region_start,
+ /**
+ * In case of modem ssr, we need to assign memory back to linux.
+ * This is not true after cold boot since linux already owns it.
+ * Also for secure boot devices, modem memory has to be released
+ * after MBA is booted
+ */
+ if (desc->modem_ssr) {
+ ret = pil_assign_mem_to_linux(desc, priv->region_start,
(priv->region_end - priv->region_start));
- if (ret)
- pil_err(desc, "Failed to assign to linux, ret - %d\n",
+ if (ret)
+ pil_err(desc, "Failed to assign to linux, ret- %d\n",
ret);
-
+ }
ret = pil_assign_mem_to_subsys_and_linux(desc,
priv->region_start,
(priv->region_end - priv->region_start));
@@ -857,6 +861,7 @@ int pil_boot(struct pil_desc *desc)
goto err_auth_and_reset;
}
pil_info(desc, "Brought out of reset\n");
+ desc->modem_ssr = false;
err_auth_and_reset:
if (ret && desc->subsys_vmid > 0) {
pil_assign_mem_to_linux(desc, priv->region_start,
@@ -917,6 +922,7 @@ void pil_shutdown(struct pil_desc *desc)
pil_proxy_unvote(desc, 1);
else
flush_delayed_work(&priv->proxy);
+ desc->modem_ssr = true;
}
EXPORT_SYMBOL(pil_shutdown);
diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h
index c3689faf0034..802abe26a960 100644
--- a/drivers/soc/qcom/peripheral-loader.h
+++ b/drivers/soc/qcom/peripheral-loader.h
@@ -36,6 +36,7 @@ struct pil_priv;
* @unmap_fw_mem: Custom function used to undo mapping by map_fw_mem.
* This defaults to iounmap if not specified.
* @shutdown_fail: Set if PIL op for shutting down subsystem fails.
+ * @modem_ssr: true if modem is restarting, false if booting for first time.
* @subsys_vmid: memprot id for the subsystem.
*/
struct pil_desc {
@@ -54,6 +55,7 @@ struct pil_desc {
void (*unmap_fw_mem)(void *virt, size_t size, void *data);
void *map_data;
bool shutdown_fail;
+ bool modem_ssr;
u32 subsys_vmid;
};
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c
index af9cd189cf6d..31a5ae89174e 100644
--- a/drivers/soc/qcom/pil-q6v5-mss.c
+++ b/drivers/soc/qcom/pil-q6v5-mss.c
@@ -214,6 +214,7 @@ static int pil_subsys_init(struct modem_data *drv,
drv->subsys_desc.stop_ack_handler = modem_stop_ack_intr_handler;
drv->subsys_desc.wdog_bite_handler = modem_wdog_bite_intr_handler;
+ drv->q6->desc.modem_ssr = false;
drv->subsys = subsys_register(&drv->subsys_desc);
if (IS_ERR(drv->subsys)) {
ret = PTR_ERR(drv->subsys);
diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
index 7e5f1661932f..dfd6b448a65f 100644
--- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
+++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
@@ -316,14 +316,7 @@ struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, uint32_t dl,
open_cfg.notify_rx_intent_req = apr_tal_notify_rx_intent_req;
open_cfg.notify_remote_rx_intent = apr_tal_notify_remote_rx_intent;
open_cfg.priv = apr_ch;
- /*
- * The transport name "smd_trans" is required if far end is using SMD.
- * In that case Glink will fall back to SMD and the client (APR in this
- * case) will still work as if Glink is the communication channel.
- * If far end is already using Glink, this property will be ignored in
- * Glink layer and communication will be through Glink.
- */
- open_cfg.transport = "smd_trans";
+ open_cfg.transport = "smem";
apr_ch->channel_state = GLINK_REMOTE_DISCONNECTED;
apr_ch->handle = glink_open(&open_cfg);
@@ -420,13 +413,13 @@ static void apr_tal_link_state_cb(struct glink_link_state_cb_info *cb_info,
}
static struct glink_link_info mpss_link_info = {
- .transport = NULL,
+ .transport = "smem",
.edge = "mpss",
.glink_link_state_notif_cb = apr_tal_link_state_cb,
};
static struct glink_link_info lpass_link_info = {
- .transport = NULL,
+ .transport = "smem",
.edge = "lpass",
.glink_link_state_notif_cb = apr_tal_link_state_cb,
};
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index 2bc425a437b2..9426e0751c4a 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -124,7 +124,7 @@ static void service_locator_svc_arrive(struct work_struct *work)
qmi_handle_destroy(service_locator.clnt_handle);
service_locator.clnt_handle = NULL;
mutex_unlock(&service_locator.service_mutex);
- pr_err("Unable to connnect to service\n");
+ pr_err("Unable to connnect to service rc:%d\n", rc);
return;
}
if (!service_inited)
@@ -148,10 +148,12 @@ static void service_locator_recv_msg(struct work_struct *work)
do {
pr_debug("Notified about a Receive event\n");
- } while ((ret = qmi_recv_msg(service_locator.clnt_handle)) == 0);
+ ret = qmi_recv_msg(service_locator.clnt_handle);
+ if (ret != -ENOMSG)
+ pr_err("Error receiving message rc:%d. Retrying...\n",
+ ret);
+ } while (ret == 0);
- if (ret != -ENOMSG)
- pr_err("Error receiving message\n");
}
static void store_get_domain_list_response(struct pd_qmi_client_data *pd,
@@ -255,7 +257,7 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd)
rc = servreg_loc_send_msg(&req_desc, &resp_desc, req, resp,
pd);
if (rc < 0) {
- pr_err("send msg failed! 0x%x\n", rc);
+ pr_err("send msg failed rc:%d\n", rc);
goto out;
}
if (!domains_read) {
@@ -325,7 +327,7 @@ static int init_service_locator(void)
SERVREG_LOC_SERVICE_VERS_V01, SERVREG_LOC_SERVICE_INSTANCE_ID,
&service_locator.notifier);
if (rc < 0) {
- pr_err("Notifier register failed!\n");
+ pr_err("Notifier register failed rc:%d\n", rc);
goto inited;
}
@@ -397,8 +399,8 @@ static void pd_locator_work(struct work_struct *work)
}
rc = service_locator_send_msg(data);
if (rc) {
- pr_err("Failed to get process domains for %s for client %s\n",
- data->service_name, data->client_name);
+ pr_err("Failed to get process domains for %s for client %s rc:%d\n",
+ data->service_name, data->client_name, rc);
pdqw->notifier->notifier_call(pdqw->notifier,
LOCATOR_DOWN, NULL);
goto err;
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index 1ada600495df..81dde8ca1ae8 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -140,21 +140,11 @@ static int service_notif_queue_notification(struct service_notif_info
enum qmi_servreg_notif_service_state_enum_type_v01 notif_type,
void *info)
{
- int ret = 0;
-
- if (!service_notif)
- return -EINVAL;
-
- if ((int) notif_type < QMI_STATE_MIN_VAL ||
- (int) notif_type > QMI_STATE_MAX_VAL)
- return -EINVAL;
+ int ret;
if (service_notif->curr_state == notif_type)
return 0;
- if (!service_notif->service_notif_rcvr_list.head)
- return 0;
-
ret = srcu_notifier_call_chain(&service_notif->service_notif_rcvr_list,
notif_type, info);
return ret;
@@ -244,8 +234,8 @@ static void root_service_service_ind_cb(struct qmi_handle *handle,
ind_desc.ei_array = qmi_servreg_notif_state_updated_ind_msg_v01_ei;
rc = qmi_kernel_decode(&ind_desc, &ind_msg, msg, msg_len);
if (rc < 0) {
- pr_err("Failed to decode message!\n");
- goto send_ind_resp;
+ pr_err("Failed to decode message rc:%d\n", rc);
+ return;
}
pr_debug("Indication received from %s, state: 0x%x, trans-id: %d\n",
@@ -263,15 +253,15 @@ static void root_service_service_ind_cb(struct qmi_handle *handle,
else {
mutex_lock(&notif_add_lock);
mutex_lock(&service_list_lock);
- if (service_notif_queue_notification(service_notif,
- ind_msg.curr_state, NULL))
- pr_err("Nnotification failed for %s\n",
- ind_msg.service_name);
+ rc = service_notif_queue_notification(service_notif,
+ ind_msg.curr_state, NULL);
+ if (rc & NOTIFY_STOP_MASK)
+ pr_err("Notifier callback aborted for %s with error %d\n",
+ ind_msg.service_name, rc);
service_notif->curr_state = ind_msg.curr_state;
mutex_unlock(&service_list_lock);
mutex_unlock(&notif_add_lock);
}
-send_ind_resp:
data->ind_msg.transaction_id = ind_msg.transaction_id;
snprintf(data->ind_msg.service_path,
ARRAY_SIZE(data->ind_msg.service_path), "%s",
@@ -320,7 +310,8 @@ static int send_notif_listener_msg_req(struct service_notif_info *service_notif,
if ((int) resp.curr_state < QMI_STATE_MIN_VAL ||
(int) resp.curr_state > QMI_STATE_MAX_VAL) {
- pr_err("Invalid notif info 0x%x\n", resp.curr_state);
+ pr_err("Invalid indication notification state %d\n",
+ resp.curr_state);
rc = -EINVAL;
}
*curr_state = resp.curr_state;
@@ -356,8 +347,8 @@ static void root_service_service_arrive(struct work_struct *work)
SERVREG_NOTIF_SERVICE_ID, SERVREG_NOTIF_SERVICE_VERS,
data->instance_id);
if (rc < 0) {
- pr_err("Could not connect handle to service(instance-id: %d)\n",
- data->instance_id);
+ pr_err("Could not connect to service(instance-id: %d) rc:%d\n",
+ data->instance_id, rc);
qmi_handle_destroy(data->clnt_handle);
data->clnt_handle = NULL;
return;
@@ -369,8 +360,8 @@ static void root_service_service_arrive(struct work_struct *work)
rc = qmi_register_ind_cb(data->clnt_handle, root_service_service_ind_cb,
(void *)data);
if (rc < 0)
- pr_err("Indication callback register failed(instance-id: %d)\n",
- data->instance_id);
+ pr_err("Indication callback register failed(instance-id: %d) rc:%d\n",
+ data->instance_id, rc);
mutex_lock(&notif_add_lock);
mutex_lock(&service_list_lock);
@@ -379,15 +370,14 @@ static void root_service_service_arrive(struct work_struct *work)
rc = register_notif_listener(service_notif, data,
&curr_state);
if (rc) {
- pr_err("Notifier registration failed for %s\n",
- service_notif->service_path);
+ pr_err("Notifier registration failed for %s rc:%d\n",
+ service_notif->service_path, rc);
} else {
rc = service_notif_queue_notification(
- service_notif,
- curr_state, NULL);
- if (rc)
- pr_err("Notifier failed for %s\n",
- service_notif->service_path);
+ service_notif, curr_state, NULL);
+ if (rc & NOTIFY_STOP_MASK)
+ pr_err("Notifier callback aborted for %s error:%d\n",
+ service_notif->service_path, rc);
service_notif->curr_state = curr_state;
}
}
@@ -412,9 +402,9 @@ static void root_service_service_exit(struct qmi_client_info *data)
rc = service_notif_queue_notification(service_notif,
SERVREG_NOTIF_SERVICE_STATE_DOWN_V01,
NULL);
- if (rc)
- pr_err("Notification failed for %s\n",
- service_notif->service_path);
+ if (rc & NOTIFY_STOP_MASK)
+ pr_err("Notifier callback aborted for %s with error %d\n",
+ service_notif->service_path, rc);
service_notif->curr_state =
SERVREG_NOTIF_SERVICE_STATE_DOWN_V01;
}
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 95191221bc3c..2c26ae1e3eb7 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1005,7 +1005,6 @@ struct dwc3 {
/* IRQ timing statistics */
int irq;
- struct tasklet_struct bh;
unsigned long irq_cnt;
unsigned bh_completion_time[MAX_INTR_STATS];
unsigned bh_handled_evt_cnt[MAX_INTR_STATS];
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 4d35de1c14c5..37a3c954a1dd 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -187,6 +187,7 @@ struct dwc3_msm {
u32 bus_perf_client;
struct msm_bus_scale_pdata *bus_scale_table;
struct power_supply *usb_psy;
+ struct work_struct vbus_draw_work;
bool in_host_mode;
unsigned int tx_fifo_size;
bool vbus_active;
@@ -1595,6 +1596,15 @@ static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
}
+static void dwc3_msm_vbus_draw_work(struct work_struct *w)
+{
+ struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
+ vbus_draw_work);
+ struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
+
+ dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
+}
+
static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
{
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
@@ -1680,7 +1690,7 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
break;
case DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT:
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT received\n");
- dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
+ schedule_work(&mdwc->vbus_draw_work);
break;
case DWC3_CONTROLLER_RESTART_USB_SESSION:
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESTART_USB_SESSION received\n");
@@ -1927,6 +1937,12 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
clk_disable_unprepare(mdwc->bus_aggr_clk);
clk_disable_unprepare(mdwc->utmi_clk);
+ /* Memory core: OFF, Memory periphery: OFF */
+ if (!mdwc->in_host_mode && !mdwc->vbus_active) {
+ clk_set_flags(mdwc->core_clk, CLKFLAG_NORETAIN_MEM);
+ clk_set_flags(mdwc->core_clk, CLKFLAG_NORETAIN_PERIPH);
+ }
+
clk_set_rate(mdwc->core_clk, 19200000);
clk_disable_unprepare(mdwc->core_clk);
/*
@@ -2338,14 +2354,23 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc)
return ret;
}
- /*
- * Get Max supported clk frequency for USB Core CLK and request
- * to set the same.
- */
- mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk, LONG_MAX);
+ if (!of_property_read_u32(mdwc->dev->of_node, "qcom,core-clk-rate",
+ (u32 *)&mdwc->core_clk_rate)) {
+ mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk,
+ mdwc->core_clk_rate);
+ } else {
+ /*
+ * Get Max supported clk frequency for USB Core CLK and request
+ * to set the same.
+ */
+ mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk, LONG_MAX);
+ }
+
if (IS_ERR_VALUE(mdwc->core_clk_rate)) {
dev_err(mdwc->dev, "fail to get core clk max freq.\n");
} else {
+ dev_dbg(mdwc->dev, "USB core frequency = %ld\n",
+ mdwc->core_clk_rate);
ret = clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate);
if (ret)
dev_err(mdwc->dev, "fail to set core_clk freq:%d\n",
@@ -2582,6 +2607,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
INIT_WORK(&mdwc->resume_work, dwc3_resume_work);
INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w);
+ INIT_WORK(&mdwc->vbus_draw_work, dwc3_msm_vbus_draw_work);
INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work);
mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0);
@@ -3165,7 +3191,8 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA)
{
- union power_supply_propval pval = {0,};
+ union power_supply_propval pval = {1000 * mA};
+ int ret;
if (mdwc->charging_disabled)
return 0;
@@ -3183,42 +3210,16 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA)
dev_info(mdwc->dev, "Avail curr from USB = %u\n", mA);
- if (mdwc->max_power <= 2 && mA > 2) {
- /* Enable Charging */
- pval.intval = true;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_ONLINE, &pval))
- goto psy_error;
- pval.intval = 1000 * mA;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &pval))
- goto psy_error;
- } else if (mdwc->max_power > 0 && (mA == 0 || mA == 2)) {
- /* Disable charging */
- pval.intval = false;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_ONLINE, &pval))
- goto psy_error;
- } else {
- /* Enable charging */
- pval.intval = true;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_ONLINE, &pval))
- goto psy_error;
- }
-
/* Set max current limit in uA */
- pval.intval = 1000 * mA;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &pval))
- goto psy_error;
+ ret = power_supply_set_property(mdwc->usb_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
+ if (ret) {
+ dev_dbg(mdwc->dev, "power supply error when setting property\n");
+ return ret;
+ }
mdwc->max_power = mA;
return 0;
-
-psy_error:
- dev_dbg(mdwc->dev, "power supply error when setting property\n");
- return -ENXIO;
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7d97aeb21340..acaa99615d33 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2141,8 +2141,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
atomic_read(&dwc->dev->power.usage_count));
dwc3_gadget_disable_irq(dwc);
- tasklet_kill(&dwc->bh);
-
spin_lock_irqsave(&dwc->lock, flags);
__dwc3_gadget_ep_disable(dwc->eps[0]);
@@ -3380,15 +3378,6 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
return ret;
}
-static void dwc3_interrupt_bh(unsigned long param)
-{
- struct dwc3 *dwc = (struct dwc3 *) param;
-
- pm_runtime_get(dwc->dev);
- dwc3_thread_interrupt(dwc->irq, dwc);
- enable_irq(dwc->irq);
-}
-
static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
{
struct dwc3 *dwc = _dwc;
@@ -3412,7 +3401,6 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
dwc->bh_completion_time[dwc->bh_dbg_index] = temp_time;
dwc->bh_dbg_index = (dwc->bh_dbg_index + 1) % 10;
- pm_runtime_put(dwc->dev);
return ret;
}
@@ -3478,10 +3466,8 @@ irqreturn_t dwc3_interrupt(int irq, void *_dwc)
dwc->irq_event_count[dwc->irq_dbg_index] = temp_cnt / 4;
dwc->irq_dbg_index = (dwc->irq_dbg_index + 1) % MAX_INTR_STATS;
- if (ret == IRQ_WAKE_THREAD) {
- disable_irq_nosync(irq);
- tasklet_schedule(&dwc->bh);
- }
+ if (ret == IRQ_WAKE_THREAD)
+ dwc3_thread_interrupt(dwc->irq, dwc);
return IRQ_HANDLED;
}
@@ -3529,9 +3515,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err3;
}
- dwc->bh.func = dwc3_interrupt_bh;
- dwc->bh.data = (unsigned long)dwc;
-
dwc->gadget.ops = &dwc3_gadget_ops;
dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->gadget.sg_supported = true;
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 3639890c0dc7..5db4fe9e3cdf 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1738,7 +1738,10 @@ void unregister_gadget_item(struct config_item *item)
{
struct gadget_info *gi = to_gadget_info(item);
+ /* to protect race with gadget_dev_desc_UDC_store*/
+ mutex_lock(&gi->lock);
unregister_gadget(gi);
+ mutex_unlock(&gi->lock);
}
EXPORT_SYMBOL_GPL(unregister_gadget_item);
diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c
index b22ea656367e..78c1ce793b5b 100644
--- a/drivers/usb/gadget/function/f_cdev.c
+++ b/drivers/usb/gadget/function/f_cdev.c
@@ -516,7 +516,6 @@ static void usb_cser_disable(struct usb_function *f)
usb_cser_disconnect(port);
usb_ep_disable(port->port_usb.notify);
- usb_cser_free_req(port->port_usb.notify, port->port_usb.notify_req);
port->port_usb.notify->driver_data = NULL;
}
@@ -817,7 +816,11 @@ static void cser_free_inst(struct usb_function_instance *fi)
static void usb_cser_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct f_cdev *port = func_to_port(f);
+
usb_free_all_descriptors(f);
+ usb_cser_free_req(port->port_usb.notify, port->port_usb.notify_req);
+ port->port_usb.notify_req = NULL;
}
static int usb_cser_alloc_requests(struct usb_ep *ep, struct list_head *head,
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 48f987d77e91..c5fd3ce3ed9a 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -24,6 +24,7 @@
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/uio.h>
+#include <linux/ipc_logging.h>
#include <asm/unaligned.h>
#include <linux/usb/composite.h>
@@ -41,6 +42,15 @@
#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
+#define NUM_PAGES 10 /* # of pages for ipc logging */
+
+static void *ffs_ipc_log;
+#define ffs_log(fmt, ...) do { \
+ ipc_log_string(ffs_ipc_log, "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
+ pr_debug(fmt, ##__VA_ARGS__); \
+} while (0)
+
/* Reference counter handling */
static void ffs_data_get(struct ffs_data *ffs);
static void ffs_data_put(struct ffs_data *ffs);
@@ -214,6 +224,9 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
spin_unlock_irq(&ffs->ev.waitq.lock);
+ ffs_log("enter: state %d setup_state %d flags %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
req->buf = data;
req->length = len;
@@ -238,11 +251,18 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
}
ffs->setup_state = FFS_NO_SETUP;
+
+ ffs_log("exit: state %d setup_state %d flags %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
return req->status ? req->status : req->actual;
}
static int __ffs_ep0_stall(struct ffs_data *ffs)
{
+ ffs_log("state %d setup_state %d flags %lu can_stall %d", ffs->state,
+ ffs->setup_state, ffs->flags, ffs->ev.can_stall);
+
if (ffs->ev.can_stall) {
pr_vdebug("ep0 stall\n");
usb_ep_set_halt(ffs->gadget->ep0);
@@ -263,6 +283,9 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
ENTER();
+ ffs_log("enter:len %zu state %d setup_state %d flags %lu", len,
+ ffs->state, ffs->setup_state, ffs->flags);
+
/* Fast check if setup was canceled */
if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
return -EIDRM;
@@ -391,6 +414,9 @@ done_spin:
break;
}
+ ffs_log("exit:ret %zu state %d setup_state %d flags %lu", ret,
+ ffs->state, ffs->setup_state, ffs->flags);
+
mutex_unlock(&ffs->mutex);
return ret;
}
@@ -424,6 +450,10 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
ffs->ev.count * sizeof *ffs->ev.types);
spin_unlock_irq(&ffs->ev.waitq.lock);
+
+ ffs_log("state %d setup_state %d flags %lu #evt %zu", ffs->state,
+ ffs->setup_state, ffs->flags, n);
+
mutex_unlock(&ffs->mutex);
return unlikely(copy_to_user(buf, events, size)) ? -EFAULT : size;
@@ -439,6 +469,9 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
ENTER();
+ ffs_log("enter:len %zu state %d setup_state %d flags %lu", len,
+ ffs->state, ffs->setup_state, ffs->flags);
+
/* Fast check if setup was canceled */
if (ffs_setup_state_clear_cancelled(ffs) == FFS_SETUP_CANCELLED)
return -EIDRM;
@@ -527,8 +560,12 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
spin_unlock_irq(&ffs->ev.waitq.lock);
done_mutex:
+ ffs_log("exit:ret %d state %d setup_state %d flags %lu", ret,
+ ffs->state, ffs->setup_state, ffs->flags);
+
mutex_unlock(&ffs->mutex);
kfree(data);
+
return ret;
}
@@ -538,6 +575,9 @@ static int ffs_ep0_open(struct inode *inode, struct file *file)
ENTER();
+ ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
if (unlikely(ffs->state == FFS_CLOSING))
return -EBUSY;
@@ -557,6 +597,9 @@ static int ffs_ep0_release(struct inode *inode, struct file *file)
ENTER();
+ ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
ffs_data_closed(ffs);
return 0;
@@ -570,6 +613,9 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
ENTER();
+ ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
if (code == FUNCTIONFS_INTERFACE_REVMAP) {
struct ffs_function *func = ffs->func;
ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
@@ -588,6 +634,9 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait)
unsigned int mask = POLLWRNORM;
int ret;
+ ffs_log("enter:state %d setup_state %d flags %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
poll_wait(file, &ffs->ev.waitq, wait);
ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
@@ -618,6 +667,8 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait)
break;
}
+ ffs_log("exit: mask %u", mask);
+
mutex_unlock(&ffs->mutex);
return mask;
@@ -648,6 +699,7 @@ static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
ep->status = req->status ? req->status : req->actual;
/* Set is_busy false to indicate completion of last request */
ep->is_busy = false;
+ ffs_log("ep status %d for req %p", ep->status, req);
complete(req->context);
}
}
@@ -659,6 +711,8 @@ static void ffs_user_copy_worker(struct work_struct *work)
int ret = io_data->req->status ? io_data->req->status :
io_data->req->actual;
+ ffs_log("enter: ret %d", ret);
+
if (io_data->read && ret > 0) {
use_mm(io_data->mm);
ret = copy_to_iter(io_data->buf, ret, &io_data->data);
@@ -680,6 +734,8 @@ static void ffs_user_copy_worker(struct work_struct *work)
kfree(io_data->to_free);
kfree(io_data->buf);
kfree(io_data);
+
+ ffs_log("exit");
}
static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
@@ -689,8 +745,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
ENTER();
+ ffs_log("enter");
+
INIT_WORK(&io_data->work, ffs_user_copy_worker);
schedule_work(&io_data->work);
+
+ ffs_log("exit");
}
static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
@@ -701,6 +761,9 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
ssize_t ret, data_len = -EINVAL;
int halt;
+ ffs_log("enter: epfile name %s epfile err %d", epfile->name,
+ atomic_read(&epfile->error));
+
smp_mb__before_atomic();
if (atomic_read(&epfile->error))
return -ENODEV;
@@ -927,6 +990,9 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
}
mutex_unlock(&epfile->mutex);
+
+ ffs_log("exit:ret %zu", ret);
+
return ret;
error_lock:
@@ -934,6 +1000,9 @@ error_lock:
mutex_unlock(&epfile->mutex);
error:
kfree(data);
+
+ ffs_log("exit: ret %zu", ret);
+
return ret;
}
@@ -944,6 +1013,9 @@ ffs_epfile_open(struct inode *inode, struct file *file)
ENTER();
+ ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
return -ENODEV;
@@ -962,6 +1034,9 @@ ffs_epfile_open(struct inode *inode, struct file *file)
smp_mb__before_atomic();
atomic_set(&epfile->error, 0);
+ ffs_log("exit:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
return 0;
}
@@ -973,6 +1048,9 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
ENTER();
+ ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
spin_lock_irq(&epfile->ffs->eps_lock);
if (likely(io_data && io_data->ep && io_data->req))
@@ -982,6 +1060,8 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
spin_unlock_irq(&epfile->ffs->eps_lock);
+ ffs_log("exit: value %d", value);
+
return value;
}
@@ -992,6 +1072,8 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
ENTER();
+ ffs_log("enter");
+
if (!is_sync_kiocb(kiocb)) {
p = kmalloc(sizeof(io_data), GFP_KERNEL);
if (unlikely(!p))
@@ -1018,6 +1100,9 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
kfree(p);
else
*from = p->data;
+
+ ffs_log("exit");
+
return res;
}
@@ -1028,6 +1113,8 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
ENTER();
+ ffs_log("enter");
+
if (!is_sync_kiocb(kiocb)) {
p = kmalloc(sizeof(io_data), GFP_KERNEL);
if (unlikely(!p))
@@ -1066,6 +1153,9 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
} else {
*to = p->data;
}
+
+ ffs_log("enter");
+
return res;
}
@@ -1076,12 +1166,17 @@ ffs_epfile_release(struct inode *inode, struct file *file)
ENTER();
+ ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
smp_mb__before_atomic();
atomic_set(&epfile->opened, 0);
atomic_set(&epfile->error, 1);
ffs_data_closed(epfile->ffs);
file->private_data = NULL;
+ ffs_log("exit");
+
return 0;
}
@@ -1093,6 +1188,9 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
ENTER();
+ ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
+ epfile->ffs->setup_state, epfile->ffs->flags);
+
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
return -ENODEV;
@@ -1143,6 +1241,8 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
}
spin_unlock_irq(&epfile->ffs->eps_lock);
+ ffs_log("exit:ret %d", ret);
+
return ret;
}
@@ -1174,6 +1274,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
ENTER();
+ ffs_log("enter");
+
inode = new_inode(sb);
if (likely(inode)) {
@@ -1193,6 +1295,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
inode->i_op = iops;
}
+ ffs_log("exit");
+
return inode;
}
@@ -1207,6 +1311,8 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb,
ENTER();
+ ffs_log("enter");
+
dentry = d_alloc_name(sb->s_root, name);
if (unlikely(!dentry))
return NULL;
@@ -1218,6 +1324,9 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb,
}
d_add(dentry, inode);
+
+ ffs_log("exit");
+
return dentry;
}
@@ -1243,6 +1352,8 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
ENTER();
+ ffs_log("enter");
+
ffs->sb = sb;
data->ffs_data = NULL;
sb->s_fs_info = ffs;
@@ -1267,6 +1378,8 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
&ffs_ep0_operations)))
return -ENOMEM;
+ ffs_log("exit");
+
return 0;
}
@@ -1274,6 +1387,8 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
{
ENTER();
+ ffs_log("enter");
+
if (!opts || !*opts)
return 0;
@@ -1356,6 +1471,8 @@ invalid:
opts = comma + 1;
}
+ ffs_log("exit");
+
return 0;
}
@@ -1381,6 +1498,8 @@ ffs_fs_mount(struct file_system_type *t, int flags,
ENTER();
+ ffs_log("enter");
+
ret = ffs_fs_parse_opts(&data, opts);
if (unlikely(ret < 0))
return ERR_PTR(ret);
@@ -1410,6 +1529,9 @@ ffs_fs_mount(struct file_system_type *t, int flags,
ffs_release_dev(data.ffs_data);
ffs_data_put(data.ffs_data);
}
+
+ ffs_log("exit");
+
return rv;
}
@@ -1418,12 +1540,16 @@ ffs_fs_kill_sb(struct super_block *sb)
{
ENTER();
+ ffs_log("enter");
+
kill_litter_super(sb);
if (sb->s_fs_info) {
ffs_release_dev(sb->s_fs_info);
ffs_data_closed(sb->s_fs_info);
ffs_data_put(sb->s_fs_info);
}
+
+ ffs_log("exit");
}
static struct file_system_type ffs_fs_type = {
@@ -1449,6 +1575,8 @@ static int functionfs_init(void)
else
pr_err("failed registering file system (%d)\n", ret);
+ ffs_ipc_log = ipc_log_context_create(NUM_PAGES, "f_fs", 0);
+
return ret;
}
@@ -1470,14 +1598,21 @@ static void ffs_data_get(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter");
+
smp_mb__before_atomic();
atomic_inc(&ffs->ref);
+
+ ffs_log("exit");
}
static void ffs_data_opened(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
smp_mb__before_atomic();
atomic_inc(&ffs->ref);
if (atomic_add_return(1, &ffs->opened) == 1 &&
@@ -1485,12 +1620,17 @@ static void ffs_data_opened(struct ffs_data *ffs)
ffs->state = FFS_CLOSING;
ffs_data_reset(ffs);
}
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
static void ffs_data_put(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter");
+
smp_mb__before_atomic();
if (unlikely(atomic_dec_and_test(&ffs->ref))) {
pr_info("%s(): freeing\n", __func__);
@@ -1500,12 +1640,17 @@ static void ffs_data_put(struct ffs_data *ffs)
kfree(ffs->dev_name);
kfree(ffs);
}
+
+ ffs_log("exit");
}
static void ffs_data_closed(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu opened %d", ffs->state,
+ ffs->setup_state, ffs->flags, atomic_read(&ffs->opened));
+
smp_mb__before_atomic();
if (atomic_dec_and_test(&ffs->opened)) {
if (ffs->no_disconnect) {
@@ -1529,6 +1674,9 @@ static void ffs_data_closed(struct ffs_data *ffs)
ffs_data_reset(ffs);
}
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
ffs_data_put(ffs);
}
@@ -1540,6 +1688,8 @@ static struct ffs_data *ffs_data_new(void)
ENTER();
+ ffs_log("enter");
+
atomic_set(&ffs->ref, 1);
atomic_set(&ffs->opened, 0);
ffs->state = FFS_READ_DESCRIPTORS;
@@ -1553,6 +1703,8 @@ static struct ffs_data *ffs_data_new(void)
/* XXX REVISIT need to update it in some places, or do we? */
ffs->ev.can_stall = 1;
+ ffs_log("exit");
+
return ffs;
}
@@ -1560,6 +1712,9 @@ static void ffs_data_clear(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
pr_debug("%s: ffs->gadget= %p, ffs->flags= %lu\n",
__func__, ffs->gadget, ffs->flags);
ffs_closed(ffs);
@@ -1578,12 +1733,18 @@ static void ffs_data_clear(struct ffs_data *ffs)
kfree(ffs->raw_descs_data);
kfree(ffs->raw_strings);
kfree(ffs->stringtabs);
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
static void ffs_data_reset(struct ffs_data *ffs)
{
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
ffs_data_clear(ffs);
ffs->epfiles = NULL;
@@ -1606,6 +1767,9 @@ static void ffs_data_reset(struct ffs_data *ffs)
ffs->state = FFS_READ_DESCRIPTORS;
ffs->setup_state = FFS_NO_SETUP;
ffs->flags = 0;
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
@@ -1616,6 +1780,9 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
if (WARN_ON(ffs->state != FFS_ACTIVE
|| test_and_set_bit(FFS_FL_BOUND, &ffs->flags)))
return -EBADFD;
@@ -1641,6 +1808,10 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
}
ffs->gadget = cdev->gadget;
+
+ ffs_log("exit: state %d setup_state %d flag %lu gadget %p\n",
+ ffs->state, ffs->setup_state, ffs->flags, ffs->gadget);
+
ffs_data_get(ffs);
return 0;
}
@@ -1654,6 +1825,8 @@ static void functionfs_unbind(struct ffs_data *ffs)
ffs->ep0req = NULL;
ffs->gadget = NULL;
clear_bit(FFS_FL_BOUND, &ffs->flags);
+ ffs_log("state %d setup_state %d flag %lu gadget %p\n",
+ ffs->state, ffs->setup_state, ffs->flags, ffs->gadget);
ffs_data_put(ffs);
}
}
@@ -1665,6 +1838,9 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
count = ffs->eps_count;
epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL);
if (!epfiles)
@@ -1690,6 +1866,10 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
}
ffs->epfiles = epfiles;
+
+ ffs_log("exit: epfile name %s state %d setup_state %d flag %lu",
+ epfile->name, ffs->state, ffs->setup_state, ffs->flags);
+
return 0;
}
@@ -1699,6 +1879,8 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
ENTER();
+ ffs_log("enter: epfilename %s", epfile->name);
+
for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex) ||
waitqueue_active(&epfile->wait));
@@ -1710,6 +1892,8 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
}
kfree(epfiles);
+
+ ffs_log("exit");
}
static void ffs_func_eps_disable(struct ffs_function *func)
@@ -1719,6 +1903,9 @@ static void ffs_func_eps_disable(struct ffs_function *func)
unsigned count = func->ffs->eps_count;
unsigned long flags;
+ ffs_log("enter: state %d setup_state %d flag %lu", func->ffs->state,
+ func->ffs->setup_state, func->ffs->flags);
+
spin_lock_irqsave(&func->ffs->eps_lock, flags);
do {
@@ -1738,6 +1925,8 @@ static void ffs_func_eps_disable(struct ffs_function *func)
}
} while (--count);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+
+ ffs_log("exit");
}
static int ffs_func_eps_enable(struct ffs_function *func)
@@ -1749,6 +1938,9 @@ static int ffs_func_eps_enable(struct ffs_function *func)
unsigned long flags;
int ret = 0;
+ ffs_log("enter: state %d setup_state %d flag %lu", func->ffs->state,
+ func->ffs->setup_state, func->ffs->flags);
+
spin_lock_irqsave(&func->ffs->eps_lock, flags);
do {
struct usb_endpoint_descriptor *ds;
@@ -1786,6 +1978,7 @@ static int ffs_func_eps_enable(struct ffs_function *func)
epfile->ep = ep;
epfile->in = usb_endpoint_dir_in(ds);
epfile->isoc = usb_endpoint_xfer_isoc(ds);
+ ffs_log("usb_ep_enable %s", ep->ep->name);
} else {
break;
}
@@ -1797,6 +1990,8 @@ static int ffs_func_eps_enable(struct ffs_function *func)
} while (--count);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+ ffs_log("exit: ret %d", ret);
+
return ret;
}
@@ -1837,6 +2032,8 @@ static int __must_check ffs_do_single_desc(char *data, unsigned len,
ENTER();
+ ffs_log("enter: len %u", len);
+
/* At least two bytes are required: length and type */
if (len < 2) {
pr_vdebug("descriptor too short\n");
@@ -1953,6 +2150,8 @@ inv_length:
#undef __entity_check_STRING
#undef __entity_check_ENDPOINT
+ ffs_log("exit: desc type %d length %d", _ds->bDescriptorType, length);
+
return length;
}
@@ -1964,6 +2163,8 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
ENTER();
+ ffs_log("enter: len %u", len);
+
for (;;) {
int ret;
@@ -1991,6 +2192,8 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
data += ret;
++num;
}
+
+ ffs_log("exit: len %u", len);
}
static int __ffs_data_do_entity(enum ffs_entity_type type,
@@ -2002,6 +2205,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
ENTER();
+ ffs_log("enter: type %u", type);
+
switch (type) {
case FFS_DESCRIPTOR:
break;
@@ -2040,6 +2245,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
break;
}
+ ffs_log("exit");
+
return 0;
}
@@ -2049,6 +2256,8 @@ static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
u16 bcd_version = le16_to_cpu(desc->bcdVersion);
u16 w_index = le16_to_cpu(desc->wIndex);
+ ffs_log("enter");
+
if (bcd_version != 1) {
pr_vdebug("unsupported os descriptors version: %d",
bcd_version);
@@ -2066,6 +2275,8 @@ static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
return -EINVAL;
}
+ ffs_log("exit: size of desc %lu", sizeof(*desc));
+
return sizeof(*desc);
}
@@ -2085,6 +2296,8 @@ static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
ENTER();
+ ffs_log("enter: len %u os desc type %d", len, type);
+
/* loop over all ext compat/ext prop descriptors */
while (feature_count--) {
ret = entity(type, h, data, len, priv);
@@ -2095,6 +2308,9 @@ static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
data += ret;
len -= ret;
}
+
+ ffs_log("exit");
+
return _len - len;
}
@@ -2108,6 +2324,8 @@ static int __must_check ffs_do_os_descs(unsigned count,
ENTER();
+ ffs_log("enter: len %u", len);
+
for (num = 0; num < count; ++num) {
int ret;
enum ffs_os_desc_type type;
@@ -2157,6 +2375,9 @@ static int __must_check ffs_do_os_descs(unsigned count,
len -= ret;
data += ret;
}
+
+ ffs_log("exit");
+
return _len - len;
}
@@ -2172,6 +2393,8 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
ENTER();
+ ffs_log("enter: len %u", len);
+
switch (type) {
case FFS_OS_DESC_EXT_COMPAT: {
struct usb_ext_compat_desc *d = data;
@@ -2226,6 +2449,9 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
pr_vdebug("unknown descriptor: %d\n", type);
return -EINVAL;
}
+
+ ffs_log("exit");
+
return length;
}
@@ -2239,6 +2465,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
ENTER();
+ ffs_log("enter: len %zu", len);
+
if (get_unaligned_le32(data + 4) != len)
goto error;
@@ -2349,10 +2577,13 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
ffs->ss_descs_count = counts[2];
ffs->ms_os_descs_count = os_descs_count;
+ ffs_log("exit");
+
return 0;
error:
kfree(_data);
+ ffs_log("exit: ret %d", ret);
return ret;
}
@@ -2366,6 +2597,8 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
ENTER();
+ ffs_log("enter: len %zu", len);
+
if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
get_unaligned_le32(data + 4) != len))
goto error;
@@ -2480,12 +2713,14 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
ffs->stringtabs = stringtabs;
ffs->raw_strings = _data;
+ ffs_log("exit");
return 0;
error_free:
kfree(stringtabs);
error:
kfree(_data);
+ ffs_log("exit: -EINVAL");
return -EINVAL;
}
@@ -2498,6 +2733,9 @@ static void __ffs_event_add(struct ffs_data *ffs,
enum usb_functionfs_event_type rem_type1, rem_type2 = type;
int neg = 0;
+ ffs_log("enter: type %d state %d setup_state %d flag %lu", type,
+ ffs->state, ffs->setup_state, ffs->flags);
+
/*
* Abort any unhandled setup
*
@@ -2557,6 +2795,9 @@ static void __ffs_event_add(struct ffs_data *ffs,
wake_up_locked(&ffs->ev.waitq);
if (ffs->ffs_eventfd)
eventfd_signal(ffs->ffs_eventfd, 1);
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
static void ffs_event_add(struct ffs_data *ffs,
@@ -2591,6 +2832,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
int idx;
static const char *speed_names[] = { "full", "high", "super" };
+ ffs_log("enter");
+
if (type != FFS_DESCRIPTOR)
return 0;
@@ -2666,6 +2909,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
}
ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
+ ffs_log("exit");
+
return 0;
}
@@ -2677,6 +2922,8 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
unsigned idx;
u8 newValue;
+ ffs_log("enter: type %d", type);
+
switch (type) {
default:
case FFS_DESCRIPTOR:
@@ -2721,6 +2968,9 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
pr_vdebug("%02x -> %02x\n", *valuep, newValue);
*valuep = newValue;
+
+ ffs_log("exit: newValue %d", newValue);
+
return 0;
}
@@ -2731,6 +2981,8 @@ static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
struct ffs_function *func = priv;
u8 length = 0;
+ ffs_log("enter: type %d", type);
+
switch (type) {
case FFS_OS_DESC_EXT_COMPAT: {
struct usb_ext_compat_desc *desc = data;
@@ -2800,6 +3052,8 @@ static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
pr_vdebug("unknown descriptor: %d\n", type);
}
+ ffs_log("exit");
+
return length;
}
@@ -2813,6 +3067,8 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
ENTER();
+ ffs_log("enter");
+
/*
* Legacy gadget triggers binding in functionfs_ready_callback,
* which already uses locking; taking the same lock here would
@@ -2847,6 +3103,8 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
ffs_opts->refcnt++;
func->function.strings = func->ffs->stringtabs;
+ ffs_log("exit");
+
return ffs_opts;
}
@@ -2889,6 +3147,9 @@ static int _ffs_func_bind(struct usb_configuration *c,
ENTER();
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
/* Has descriptors only for speeds gadget does not support */
if (unlikely(!(full | high | super)))
return -ENOTSUPP;
@@ -3006,10 +3267,15 @@ static int _ffs_func_bind(struct usb_configuration *c,
/* And we're done */
ffs_event_add(ffs, FUNCTIONFS_BIND);
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
return 0;
error:
/* XXX Do we need to release all claimed endpoints here? */
+ ffs_log("exit: ret %d", ret);
return ret;
}
@@ -3020,6 +3286,8 @@ static int ffs_func_bind(struct usb_configuration *c,
struct ffs_function *func = ffs_func_from_usb(f);
int ret;
+ ffs_log("enter");
+
if (IS_ERR(ffs_opts))
return PTR_ERR(ffs_opts);
@@ -3027,6 +3295,8 @@ static int ffs_func_bind(struct usb_configuration *c,
if (ret && !--ffs_opts->refcnt)
functionfs_unbind(func->ffs);
+ ffs_log("exit: ret %d", ret);
+
return ret;
}
@@ -3037,7 +3307,12 @@ static void ffs_reset_work(struct work_struct *work)
{
struct ffs_data *ffs = container_of(work,
struct ffs_data, reset_work);
+
+ ffs_log("enter");
+
ffs_data_reset(ffs);
+
+ ffs_log("exit");
}
static int ffs_func_set_alt(struct usb_function *f,
@@ -3047,6 +3322,8 @@ static int ffs_func_set_alt(struct usb_function *f,
struct ffs_data *ffs = func->ffs;
int ret = 0, intf;
+ ffs_log("enter");
+
if (alt != (unsigned)-1) {
intf = ffs_func_revmap_intf(func, interface);
if (unlikely(intf < 0))
@@ -3082,6 +3359,8 @@ static int ffs_func_set_alt(struct usb_function *f,
usb_gadget_autopm_get_async(ffs->gadget);
}
+ ffs_log("exit: ret %d", ret);
+
return ret;
}
@@ -3090,9 +3369,13 @@ static void ffs_func_disable(struct usb_function *f)
struct ffs_function *func = ffs_func_from_usb(f);
struct ffs_data *ffs = func->ffs;
+ ffs_log("enter");
+
ffs_func_set_alt(f, 0, (unsigned)-1);
/* matching put to allow LPM on disconnect */
usb_gadget_autopm_put_async(ffs->gadget);
+
+ ffs_log("exit");
}
static int ffs_func_setup(struct usb_function *f,
@@ -3105,6 +3388,8 @@ static int ffs_func_setup(struct usb_function *f,
ENTER();
+ ffs_log("enter");
+
pr_vdebug("creq->bRequestType = %02x\n", creq->bRequestType);
pr_vdebug("creq->bRequest = %02x\n", creq->bRequest);
pr_vdebug("creq->wValue = %04x\n", le16_to_cpu(creq->wValue));
@@ -3148,19 +3433,31 @@ static int ffs_func_setup(struct usb_function *f,
__ffs_event_add(ffs, FUNCTIONFS_SETUP);
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
+ ffs_log("exit");
+
return 0;
}
static void ffs_func_suspend(struct usb_function *f)
{
ENTER();
+
+ ffs_log("enter");
+
ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_SUSPEND);
+
+ ffs_log("exit");
}
static void ffs_func_resume(struct usb_function *f)
{
ENTER();
+
+ ffs_log("enter");
+
ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_RESUME);
+
+ ffs_log("exit");
}
@@ -3177,11 +3474,15 @@ static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf)
short *nums = func->interfaces_nums;
unsigned count = func->ffs->interfaces_count;
+ ffs_log("enter");
+
for (; count; --count, ++nums) {
if (*nums >= 0 && *nums == intf)
return nums - func->interfaces_nums;
}
+ ffs_log("exit");
+
return -EDOM;
}
@@ -3194,6 +3495,8 @@ static struct ffs_dev *_ffs_do_find_dev(const char *name)
{
struct ffs_dev *dev;
+ ffs_log("enter");
+
list_for_each_entry(dev, &ffs_devices, entry) {
if (!dev->name || !name)
continue;
@@ -3201,6 +3504,8 @@ static struct ffs_dev *_ffs_do_find_dev(const char *name)
return dev;
}
+ ffs_log("exit");
+
return NULL;
}
@@ -3211,12 +3516,16 @@ static struct ffs_dev *_ffs_get_single_dev(void)
{
struct ffs_dev *dev;
+ ffs_log("enter");
+
if (list_is_singular(&ffs_devices)) {
dev = list_first_entry(&ffs_devices, struct ffs_dev, entry);
if (dev->single)
return dev;
}
+ ffs_log("exit");
+
return NULL;
}
@@ -3227,11 +3536,17 @@ static struct ffs_dev *_ffs_find_dev(const char *name)
{
struct ffs_dev *dev;
+ ffs_log("enter");
+
dev = _ffs_get_single_dev();
if (dev)
return dev;
- return _ffs_do_find_dev(name);
+ dev = _ffs_do_find_dev(name);
+
+ ffs_log("exit");
+
+ return dev;
}
/* Configfs support *********************************************************/
@@ -3353,6 +3668,10 @@ static void ffs_func_unbind(struct usb_configuration *c,
unsigned long flags;
ENTER();
+
+ ffs_log("enter: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
+
if (ffs->func == func) {
ffs_func_eps_disable(func);
ffs->func = NULL;
@@ -3383,6 +3702,9 @@ static void ffs_func_unbind(struct usb_configuration *c,
func->interfaces_nums = NULL;
ffs_event_add(ffs, FUNCTIONFS_UNBIND);
+
+ ffs_log("exit: state %d setup_state %d flag %lu", ffs->state,
+ ffs->setup_state, ffs->flags);
}
static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
@@ -3445,12 +3767,16 @@ static int _ffs_name_dev(struct ffs_dev *dev, const char *name)
{
struct ffs_dev *existing;
+ ffs_log("enter");
+
existing = _ffs_do_find_dev(name);
if (existing)
return -EBUSY;
dev->name = name;
+ ffs_log("exit");
+
return 0;
}
@@ -3461,10 +3787,14 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name)
{
int ret;
+ ffs_log("enter");
+
ffs_dev_lock();
ret = _ffs_name_dev(dev, name);
ffs_dev_unlock();
+ ffs_log("exit");
+
return ret;
}
EXPORT_SYMBOL_GPL(ffs_name_dev);
@@ -3473,6 +3803,8 @@ int ffs_single_dev(struct ffs_dev *dev)
{
int ret;
+ ffs_log("enter");
+
ret = 0;
ffs_dev_lock();
@@ -3482,6 +3814,9 @@ int ffs_single_dev(struct ffs_dev *dev)
dev->single = true;
ffs_dev_unlock();
+
+ ffs_log("exit");
+
return ret;
}
EXPORT_SYMBOL_GPL(ffs_single_dev);
@@ -3491,12 +3826,17 @@ EXPORT_SYMBOL_GPL(ffs_single_dev);
*/
static void _ffs_free_dev(struct ffs_dev *dev)
{
+
+ ffs_log("enter");
+
list_del(&dev->entry);
if (dev->name_allocated)
kfree(dev->name);
kfree(dev);
if (list_empty(&ffs_devices))
functionfs_cleanup();
+
+ ffs_log("exit");
}
static void *ffs_acquire_dev(const char *dev_name)
@@ -3504,6 +3844,9 @@ static void *ffs_acquire_dev(const char *dev_name)
struct ffs_dev *ffs_dev;
ENTER();
+
+ ffs_log("enter");
+
ffs_dev_lock();
ffs_dev = _ffs_find_dev(dev_name);
@@ -3518,6 +3861,9 @@ static void *ffs_acquire_dev(const char *dev_name)
ffs_dev->mounted = true;
ffs_dev_unlock();
+
+ ffs_log("exit");
+
return ffs_dev;
}
@@ -3526,6 +3872,9 @@ static void ffs_release_dev(struct ffs_data *ffs_data)
struct ffs_dev *ffs_dev;
ENTER();
+
+ ffs_log("enter");
+
ffs_dev_lock();
ffs_dev = ffs_data->private_data;
@@ -3537,6 +3886,8 @@ static void ffs_release_dev(struct ffs_data *ffs_data)
}
ffs_dev_unlock();
+
+ ffs_log("exit");
}
static int ffs_ready(struct ffs_data *ffs)
@@ -3545,6 +3896,9 @@ static int ffs_ready(struct ffs_data *ffs)
int ret = 0;
ENTER();
+
+ ffs_log("enter");
+
ffs_dev_lock();
ffs_obj = ffs->private_data;
@@ -3569,6 +3923,9 @@ static int ffs_ready(struct ffs_data *ffs)
set_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags);
done:
ffs_dev_unlock();
+
+ ffs_log("exit");
+
return ret;
}
@@ -3578,11 +3935,16 @@ static void ffs_closed(struct ffs_data *ffs)
struct f_fs_opts *opts;
ENTER();
+
+ ffs_log("enter");
+
ffs_dev_lock();
ffs_obj = ffs->private_data;
- if (!ffs_obj)
+ if (!ffs_obj) {
+ ffs_dev_unlock();
goto done;
+ }
ffs_obj->desc_ready = false;
@@ -3590,20 +3952,29 @@ static void ffs_closed(struct ffs_data *ffs)
ffs_obj->ffs_closed_callback)
ffs_obj->ffs_closed_callback(ffs);
- if (ffs_obj->opts)
+ if (ffs_obj->opts) {
opts = ffs_obj->opts;
- else
+ } else {
+ ffs_dev_unlock();
goto done;
+ }
smp_mb__before_atomic();
if (opts->no_configfs || !opts->func_inst.group.cg_item.ci_parent
- || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
+ || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount)) {
+ ffs_dev_unlock();
goto done;
+ }
+
+ ffs_dev_unlock();
- unregister_gadget_item(ffs_obj->opts->
+ if (test_bit(FFS_FL_BOUND, &ffs->flags)) {
+ unregister_gadget_item(opts->
func_inst.group.cg_item.ci_parent->ci_parent);
+ ffs_log("unreg gadget done");
+ }
done:
- ffs_dev_unlock();
+ ffs_log("exit");
}
/* Misc helper functions ****************************************************/
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 5612645d7237..a629723d19cb 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -39,6 +39,8 @@ static struct workqueue_struct *ipa_usb_wq;
static void ipa_disconnect_handler(struct gsi_data_port *d_port);
static int gsi_ctrl_send_notification(struct f_gsi *gsi,
enum gsi_ctrl_notify_state);
+static int gsi_alloc_trb_buffer(struct f_gsi *gsi);
+static void gsi_free_trb_buffer(struct f_gsi *gsi);
void post_event(struct gsi_data_port *port, u8 event)
{
@@ -474,6 +476,9 @@ static void ipa_disconnect_work_handler(struct gsi_data_port *d_port)
if (gsi->d_port.out_ep)
usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_FREE_TRBS);
+
+ /* free buffers allocated with each TRB */
+ gsi_free_trb_buffer(gsi);
}
static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
@@ -547,6 +552,7 @@ static void ipa_work_handler(struct work_struct *w)
struct usb_gadget *gadget = d_port->gadget;
struct device *dev;
struct device *gad_dev;
+ struct f_gsi *gsi;
event = read_event(d_port);
@@ -566,31 +572,27 @@ static void ipa_work_handler(struct work_struct *w)
return;
}
+ gsi = d_port_to_gsi(d_port);
+
switch (d_port->sm_state) {
case STATE_UNINITIALIZED:
break;
case STATE_INITIALIZED:
if (event == EVT_CONNECT_IN_PROGRESS) {
+ usb_gadget_autopm_get(d_port->gadget);
+ log_event_dbg("%s: get = %d", __func__,
+ atomic_read(&gad_dev->power.usage_count));
+ /* allocate buffers used with each TRB */
+ ret = gsi_alloc_trb_buffer(gsi);
+ if (ret) {
+ log_event_err("%s: gsi_alloc_trb_failed\n",
+ __func__);
+ break;
+ }
ipa_connect_channels(d_port);
d_port->sm_state = STATE_CONNECT_IN_PROGRESS;
log_event_dbg("%s: ST_INIT_EVT_CONN_IN_PROG",
__func__);
- } else if (event == EVT_HOST_READY) {
- /*
- * When in a composition such as RNDIS + ADB,
- * RNDIS host sends a GEN_CURRENT_PACKET_FILTER msg
- * to enable/disable flow control eg. during RNDIS
- * adaptor disable/enable from device manager.
- * In the case of the msg to disable flow control,
- * connect IPA channels and enable data path.
- * EVT_HOST_READY is posted to the state machine
- * in the handler for this msg.
- */
- ipa_connect_channels(d_port);
- ipa_data_path_enable(d_port);
- d_port->sm_state = STATE_CONNECTED;
- log_event_dbg("%s: ST_INIT_EVT_HOST_READY",
- __func__);
}
break;
case STATE_CONNECT_IN_PROGRESS:
@@ -648,6 +650,7 @@ static void ipa_work_handler(struct work_struct *w)
&gad_dev->power.usage_count));
} else if (event == EVT_SUSPEND) {
if (peek_event(d_port) == EVT_DISCONNECTED) {
+ read_event(d_port);
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
usb_gadget_autopm_put_async(d_port->gadget);
@@ -718,19 +721,12 @@ static void ipa_work_handler(struct work_struct *w)
case STATE_SUSPENDED:
if (event == EVT_RESUMED) {
+ usb_gadget_autopm_get(d_port->gadget);
+ log_event_dbg("%s: ST_SUS_EVT_RES", __func__);
+ log_event_dbg("%s: get = %d", __func__,
+ atomic_read(&gad_dev->power.usage_count));
ipa_resume_work_handler(d_port);
d_port->sm_state = STATE_CONNECTED;
- /*
- * Increment usage count here to disallow gadget
- * parent suspend. This counter will decrement
- * after IPA handshake is done in disconnect work
- * (due to cable disconnect) or in suspended state.
- */
- usb_gadget_autopm_get_noresume(d_port->gadget);
- log_event_dbg("%s: ST_SUS_EVT_RES", __func__);
- log_event_dbg("%s: get_nores2 = %d", __func__,
- atomic_read(
- &gad_dev->power.usage_count));
} else if (event == EVT_DISCONNECTED) {
ipa_disconnect_work_handler(d_port);
d_port->sm_state = STATE_INITIALIZED;
@@ -1714,6 +1710,92 @@ static int gsi_get_alt(struct usb_function *f, unsigned intf)
return -EINVAL;
}
+static int gsi_alloc_trb_buffer(struct f_gsi *gsi)
+{
+ u32 len_in = 0, len_out = 0;
+ int ret = 0;
+
+ log_event_dbg("allocate trb's buffer\n");
+
+ if (gsi->d_port.in_ep && !gsi->d_port.in_request.buf_base_addr) {
+ log_event_dbg("IN: num_bufs:=%zu, buf_len=%zu\n",
+ gsi->d_port.in_request.num_bufs,
+ gsi->d_port.in_request.buf_len);
+
+ len_in = gsi->d_port.in_request.buf_len *
+ gsi->d_port.in_request.num_bufs;
+ gsi->d_port.in_request.buf_base_addr =
+ dma_zalloc_coherent(gsi->d_port.gadget->dev.parent,
+ len_in, &gsi->d_port.in_request.dma, GFP_KERNEL);
+ if (!gsi->d_port.in_request.buf_base_addr) {
+ dev_err(&gsi->d_port.gadget->dev,
+ "IN buf_base_addr allocate failed %s\n",
+ gsi->function.name);
+ ret = -ENOMEM;
+ goto fail1;
+ }
+ }
+
+ if (gsi->d_port.out_ep && !gsi->d_port.out_request.buf_base_addr) {
+ log_event_dbg("OUT: num_bufs:=%zu, buf_len=%zu\n",
+ gsi->d_port.out_request.num_bufs,
+ gsi->d_port.out_request.buf_len);
+
+ len_out = gsi->d_port.out_request.buf_len *
+ gsi->d_port.out_request.num_bufs;
+ gsi->d_port.out_request.buf_base_addr =
+ dma_zalloc_coherent(gsi->d_port.gadget->dev.parent,
+ len_out, &gsi->d_port.out_request.dma, GFP_KERNEL);
+ if (!gsi->d_port.out_request.buf_base_addr) {
+ dev_err(&gsi->d_port.gadget->dev,
+ "OUT buf_base_addr allocate failed %s\n",
+ gsi->function.name);
+ ret = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ log_event_dbg("finished allocating trb's buffer\n");
+ return ret;
+
+fail:
+ if (len_in && gsi->d_port.in_request.buf_base_addr) {
+ dma_free_coherent(gsi->d_port.gadget->dev.parent, len_in,
+ gsi->d_port.in_request.buf_base_addr,
+ gsi->d_port.in_request.dma);
+ gsi->d_port.in_request.buf_base_addr = NULL;
+ }
+fail1:
+ return ret;
+}
+
+static void gsi_free_trb_buffer(struct f_gsi *gsi)
+{
+ u32 len;
+
+ log_event_dbg("freeing trb's buffer\n");
+
+ if (gsi->d_port.out_ep &&
+ gsi->d_port.out_request.buf_base_addr) {
+ len = gsi->d_port.out_request.buf_len *
+ gsi->d_port.out_request.num_bufs;
+ dma_free_coherent(gsi->d_port.gadget->dev.parent, len,
+ gsi->d_port.out_request.buf_base_addr,
+ gsi->d_port.out_request.dma);
+ gsi->d_port.out_request.buf_base_addr = NULL;
+ }
+
+ if (gsi->d_port.in_ep &&
+ gsi->d_port.in_request.buf_base_addr) {
+ len = gsi->d_port.in_request.buf_len *
+ gsi->d_port.in_request.num_bufs;
+ dma_free_coherent(gsi->d_port.gadget->dev.parent, len,
+ gsi->d_port.in_request.buf_base_addr,
+ gsi->d_port.in_request.dma);
+ gsi->d_port.in_request.buf_base_addr = NULL;
+ }
+}
+
static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct f_gsi *gsi = func_to_gsi(f);
@@ -1827,14 +1909,14 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (gsi->prot_id == IPA_USB_ECM)
gsi->d_port.cdc_filter = DEFAULT_FILTER;
+ post_event(&gsi->d_port, EVT_CONNECT_IN_PROGRESS);
/*
- * Increment usage count upon cable connect. Decrement
- * after IPA disconnect is done in disconnect work
- * (due to cable disconnect) or in suspend work.
+ * For RNDIS the event is posted from the flow control
+ * handler which is invoked when the host sends the
+ * GEN_CURRENT_PACKET_FILTER message.
*/
- usb_gadget_autopm_get_noresume(gsi->d_port.gadget);
-
- post_event(&gsi->d_port, EVT_CONNECT_IN_PROGRESS);
+ if (gsi->prot_id != IPA_USB_RNDIS)
+ post_event(&gsi->d_port, EVT_HOST_READY);
queue_work(gsi->d_port.ipa_usb_wq,
&gsi->d_port.usb_ipa_w);
}
@@ -2042,7 +2124,6 @@ static int gsi_update_function_bind_params(struct f_gsi *gsi,
struct usb_ep *ep;
struct usb_cdc_notification *event;
struct usb_function *f = &gsi->function;
- u32 len = 0;
int status;
/* maybe allocate device-global string IDs */
@@ -2162,37 +2243,9 @@ skip_string_id_alloc:
gsi->d_port.in_request.buf_len = info->in_req_buf_len;
gsi->d_port.in_request.num_bufs = info->in_req_num_buf;
- len = gsi->d_port.in_request.buf_len * gsi->d_port.in_request.num_bufs;
- dev_dbg(&cdev->gadget->dev, "%zu %zu\n", gsi->d_port.in_request.buf_len,
- gsi->d_port.in_request.num_bufs);
- gsi->d_port.in_request.buf_base_addr =
- dma_zalloc_coherent(cdev->gadget->dev.parent, len,
- &gsi->d_port.in_request.dma, GFP_KERNEL);
- if (!gsi->d_port.in_request.buf_base_addr) {
- dev_err(&cdev->gadget->dev,
- "IN buf_base_addr allocate failed %s\n",
- gsi->function.name);
- goto fail;
- }
-
if (gsi->d_port.out_ep) {
gsi->d_port.out_request.buf_len = info->out_req_buf_len;
gsi->d_port.out_request.num_bufs = info->out_req_num_buf;
- len =
- gsi->d_port.out_request.buf_len *
- gsi->d_port.out_request.num_bufs;
- dev_dbg(&cdev->gadget->dev, "%zu %zu\n",
- gsi->d_port.out_request.buf_len,
- gsi->d_port.out_request.num_bufs);
- gsi->d_port.out_request.buf_base_addr =
- dma_zalloc_coherent(cdev->gadget->dev.parent, len,
- &gsi->d_port.out_request.dma, GFP_KERNEL);
- if (!gsi->d_port.out_request.buf_base_addr) {
- dev_err(&cdev->gadget->dev,
- "OUT buf_base_addr allocate failed %s\n",
- gsi->function.name);
- goto fail;
- }
}
/* Initialize event queue */
@@ -2263,14 +2316,6 @@ fail:
gsi->d_port.out_ep->driver_data = NULL;
if (gsi->d_port.in_ep && gsi->d_port.in_ep->desc)
gsi->d_port.in_ep->driver_data = NULL;
- if (len && gsi->d_port.in_request.buf_base_addr)
- dma_free_coherent(cdev->gadget->dev.parent, len,
- gsi->d_port.in_request.buf_base_addr,
- gsi->d_port.in_request.dma);
- if (len && gsi->d_port.out_request.buf_base_addr)
- dma_free_coherent(cdev->gadget->dev.parent, len,
- gsi->d_port.out_request.buf_base_addr,
- gsi->d_port.out_request.dma);
log_event_err("%s: bind failed for %s", __func__, f->name);
return -ENOMEM;
}
@@ -2564,8 +2609,6 @@ fail:
static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_gsi *gsi = func_to_gsi(f);
- struct usb_composite_dev *cdev = c->cdev;
- u32 len;
/*
* Use drain_workqueue to accomplish below conditions:
@@ -2600,19 +2643,7 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
if (gsi->c_port.notify) {
kfree(gsi->c_port.notify_req->buf);
usb_ep_free_request(gsi->c_port.notify, gsi->c_port.notify_req);
-
- len =
- gsi->d_port.out_request.buf_len *
- gsi->d_port.out_request.num_bufs;
- dma_free_coherent(&cdev->gadget->dev, len,
- gsi->d_port.out_request.buf_base_addr,
- gsi->d_port.out_request.dma);
}
-
- len = gsi->d_port.in_request.buf_len * gsi->d_port.in_request.num_bufs;
- dma_free_coherent(&cdev->gadget->dev, len,
- gsi->d_port.in_request.buf_base_addr,
- gsi->d_port.in_request.dma);
}
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index f29c275c490b..7bc6b5340dd7 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -849,10 +849,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
POWER_SUPPLY_PROP_VOLTAGE_MAX, &val);
pd->current_voltage = pd->requested_voltage;
- val.intval = pd->requested_current * 1000; /* mA->uA */
- power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &val);
-
/* recursive call; go back to beginning state */
usbpd_set_state(pd, PE_SNK_STARTUP);
break;
@@ -1615,7 +1611,12 @@ static void usbpd_sm(struct work_struct *w)
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
pd->requested_voltage = 5000000;
- pd->requested_current = max_sink_current;
+
+ if (pd->requested_current) {
+ val.intval = pd->requested_current = 0;
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &val);
+ }
val.intval = pd->requested_voltage;
power_supply_set_property(pd->usb_psy,
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index dd8149ef097d..f8121eb4f63a 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -799,7 +799,7 @@ static int qusb_phy_probe(struct platform_device *pdev)
}
of_property_read_u32_array(dev->of_node,
- "qcom,qemu-init-seq",
+ "qcom,emu-init-seq",
qphy->emu_init_seq,
qphy->emu_init_seq_len);
} else {
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index 325f5fcf161b..5ec08098d197 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -878,7 +878,7 @@ static int qusb_phy_probe(struct platform_device *pdev)
}
of_property_read_u32_array(dev->of_node,
- "qcom,qemu-init-seq",
+ "qcom,emu-init-seq",
qphy->emu_init_seq,
qphy->emu_init_seq_len);
} else {
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index b601cafba6fd..61e99f47f02f 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -460,6 +460,7 @@ struct mdss_data_type {
struct ion_client *iclient;
int iommu_attached;
+ u32 dbg_bus_flags;
struct debug_bus *dbg_bus;
u32 dbg_bus_size;
struct vbif_debug_bus *vbif_dbg_bus;
diff --git a/drivers/video/fbdev/msm/mdss_debug.h b/drivers/video/fbdev/msm/mdss_debug.h
index 35ae81e4709e..59ba4f3e5578 100644
--- a/drivers/video/fbdev/msm/mdss_debug.h
+++ b/drivers/video/fbdev/msm/mdss_debug.h
@@ -31,6 +31,8 @@
#define XLOG_FUNC_EXIT 0x2222
#define MDSS_REG_BLOCK_NAME_LEN (5)
+#define DEBUG_FLAGS_DSPP BIT(0)
+
enum mdss_dbg_reg_dump_flag {
MDSS_DBG_DUMP_IN_LOG = BIT(0),
MDSS_DBG_DUMP_IN_MEM = BIT(1),
diff --git a/drivers/video/fbdev/msm/mdss_debug_xlog.c b/drivers/video/fbdev/msm/mdss_debug_xlog.c
index a34bce1200d8..32bfb151eddd 100644
--- a/drivers/video/fbdev/msm/mdss_debug_xlog.c
+++ b/drivers/video/fbdev/msm/mdss_debug_xlog.c
@@ -234,6 +234,7 @@ static void mdss_dump_debug_bus(u32 bus_dump_flag,
phys_addr_t phys = 0;
int list_size = mdata->dbg_bus_size;
int i;
+ u32 offset;
if (!(mdata->dbg_bus && list_size))
return;
@@ -267,8 +268,14 @@ static void mdss_dump_debug_bus(u32 bus_dump_flag,
writel_relaxed(TEST_MASK(head->block_id, head->test_id),
mdss_res->mdp_base + head->wr_addr);
wmb(); /* make sure test bits were written */
+
+ if (mdata->dbg_bus_flags & DEBUG_FLAGS_DSPP)
+ offset = MDSS_MDP_DSPP_DEBUGBUS_STATUS;
+ else
+ offset = head->wr_addr + 0x4;
+
status = readl_relaxed(mdss_res->mdp_base +
- head->wr_addr + 0x4);
+ offset);
if (in_log)
pr_err("waddr=0x%x blk=%d tst=%d val=0x%x\n",
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index eefea9f117c0..0ac5ef4f750c 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -33,6 +33,7 @@
#include "mdss.h"
#include "mdss_dp.h"
#include "mdss_dp_util.h"
+#include "mdss_hdmi_panel.h"
#include "mdss_debug.h"
#define RGB_COMPONENTS 3
@@ -863,7 +864,7 @@ int mdss_dp_wait4train(struct mdss_dp_drv_pdata *dp_drv)
#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3
-static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
+static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
{
struct mdss_panel_info *pinfo;
struct msm_hdmi_mode_timing_info timing = {0};
@@ -875,8 +876,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
}
dp_drv->ds_data.ds_registered = false;
- ret = hdmi_get_supported_mode(&timing, &dp_drv->ds_data,
- DEFAULT_VIDEO_RESOLUTION);
+ ret = hdmi_get_supported_mode(&timing, &dp_drv->ds_data, vic);
pinfo = &dp_drv->panel_data.panel_info;
if (ret || !timing.supported || !pinfo) {
@@ -884,6 +884,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
return -EINVAL;
}
+ dp_drv->vic = vic;
pinfo->xres = timing.active_h;
pinfo->yres = timing.active_v;
pinfo->clk_rate = timing.pixel_freq * 1000;
@@ -895,7 +896,7 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
pinfo->lcdc.v_front_porch = timing.front_porch_v;
pinfo->lcdc.v_pulse_width = timing.pulse_width_v;
- pinfo->type = EDP_PANEL;
+ pinfo->type = DP_PANEL;
pinfo->pdest = DISPLAY_4;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
@@ -904,6 +905,10 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv)
pinfo->lcdc.border_clr = 0; /* blk */
pinfo->lcdc.underflow_clr = 0xff; /* blue */
pinfo->lcdc.hsync_skew = 0;
+ pinfo->is_pluggable = true;
+
+ pr_debug("update res. vic= %d, pclk_rate = %llu\n",
+ dp_drv->vic, pinfo->clk_rate);
return 0;
} /* dp_init_panel_info */
@@ -963,6 +968,9 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
}
+ if (dp_drv->new_vic && (dp_drv->new_vic != dp_drv->vic))
+ dp_init_panel_info(dp_drv, dp_drv->new_vic);
+
mdss_dp_phy_aux_setup(&dp_drv->phy_io);
mdss_dp_irq_enable(dp_drv);
@@ -1072,6 +1080,44 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
return 0;
}
+static void mdss_dp_send_cable_notification(
+ struct mdss_dp_drv_pdata *dp, int val)
+{
+ int state = 0;
+
+ if (!dp) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+ state = dp->sdev.state;
+
+ switch_set_state(&dp->sdev, val);
+
+ DEV_INFO("%s: cable state %s %d\n", __func__,
+ dp->sdev.state == state ?
+ "is same" : "switched to",
+ dp->sdev.state);
+}
+
+static int mdss_dp_register_switch_event(struct mdss_dp_drv_pdata *dp)
+{
+ int rc = -EINVAL;
+
+ if (!dp) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ goto end;
+ }
+
+ dp->sdev.name = "hdmi";
+ rc = switch_dev_register(&dp->sdev);
+ if (rc) {
+ DEV_ERR("%s: display switch registration failed\n", __func__);
+ goto end;
+ }
+end:
+ return rc;
+}
+
static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
{
struct mdss_dp_drv_pdata *dp_drv = NULL;
@@ -1097,9 +1143,6 @@ static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
return -ENODEV;
}
- edid_init_data.buf = edid_init_data.buf;
- edid_init_data.buf_size = edid_init_data.buf_size;
-
/* Use the existing EDID buffer for 1080p */
memcpy(edid_init_data.buf, edid_buf1, sizeof(edid_buf1));
dp_drv->panel_data.panel_info.edid_data = edid_data;
@@ -1152,6 +1195,8 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
goto edid_parser_error;
}
+ mdss_dp_send_cable_notification(dp_drv, true);
+
return ret;
edid_parser_error:
@@ -1162,6 +1207,44 @@ vreg_error:
return ret;
}
+static int mdss_dp_check_params(struct mdss_dp_drv_pdata *dp, void *arg)
+{
+ struct mdss_panel_info *var_pinfo, *pinfo;
+ int rc = 0;
+ int new_vic = -1;
+
+ if (!dp || !arg)
+ return 0;
+
+ pinfo = &dp->panel_data.panel_info;
+ var_pinfo = (struct mdss_panel_info *)arg;
+
+ pr_debug("reconfig xres: %d yres: %d, current xres: %d yres: %d\n",
+ var_pinfo->xres, var_pinfo->yres,
+ pinfo->xres, pinfo->yres);
+
+ new_vic = hdmi_panel_get_vic(var_pinfo, &dp->ds_data);
+
+ if ((new_vic < 0) || (new_vic > HDMI_VFRMT_MAX)) {
+ DEV_ERR("%s: invalid or not supported vic\n", __func__);
+ goto end;
+ }
+
+ /*
+ * return value of 1 lets mdss know that panel
+ * needs a reconfig due to new resolution and
+ * it will issue close and open subsequently.
+ */
+ if (new_vic != dp->vic) {
+ rc = 1;
+ DEV_ERR("%s: res change %d ==> %d\n", __func__,
+ dp->vic, new_vic);
+ }
+ dp->new_vic = new_vic;
+end:
+ return rc;
+}
+
static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -1194,9 +1277,13 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
dp->kobj = &fbi->dev->kobj;
dp->fb_node = fbi->node;
mdss_dp_edid_init(pdata);
+ mdss_dp_register_switch_event(dp);
+ break;
+ case MDSS_EVENT_CHECK_PARAMS:
+ rc = mdss_dp_check_params(dp, arg);
break;
default:
- pr_debug("%s: unhandled event=%d\n", __func__, event);
+ pr_debug("unhandled event=%d\n", event);
break;
}
return rc;
@@ -1220,7 +1307,7 @@ static int mdss_dp_device_register(struct mdss_dp_drv_pdata *dp_drv)
{
int ret;
- ret = dp_init_panel_info(dp_drv);
+ ret = dp_init_panel_info(dp_drv, DEFAULT_VIDEO_RESOLUTION);
if (ret) {
DEV_ERR("%s: dp_init_panel_info failed\n", __func__);
return ret;
@@ -1493,6 +1580,7 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
mutex_lock(&dp_drv->pd_msg_mutex);
dp_drv->cable_connected = false;
mutex_unlock(&dp_drv->pd_msg_mutex);
+ mdss_dp_send_cable_notification(dp_drv, false);
}
static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index 10fcdec49515..03646cd7cc65 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -21,6 +21,7 @@
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/usb/usbpd.h>
+#include <linux/switch.h>
#include "mdss_hdmi_util.h"
#include "mdss_hdmi_edid.h"
@@ -430,8 +431,11 @@ struct mdss_dp_drv_pdata {
spinlock_t event_lock;
spinlock_t lock;
struct hdmi_util_ds_data ds_data;
+ struct switch_dev sdev;
struct kobject *kobj;
u32 max_pclk_khz;
+ u32 vic;
+ u32 new_vic;
int fb_node;
};
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 2e54f335e948..4bd705bdc05f 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -389,8 +389,10 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
}
gpio_set_value((ctrl_pdata->rst_gpio), 0);
gpio_free(ctrl_pdata->rst_gpio);
- if (gpio_is_valid(ctrl_pdata->lcd_mode_sel_gpio))
+ if (gpio_is_valid(ctrl_pdata->lcd_mode_sel_gpio)) {
+ gpio_set_value(ctrl_pdata->lcd_mode_sel_gpio, 0);
gpio_free(ctrl_pdata->lcd_mode_sel_gpio);
+ }
}
exit:
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 99a924c38d65..b2c0c78d3f2b 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -331,8 +331,8 @@ static ssize_t mdss_fb_get_type(struct device *dev,
case WRITEBACK_PANEL:
ret = snprintf(buf, PAGE_SIZE, "writeback panel\n");
break;
- case EDP_PANEL:
- ret = snprintf(buf, PAGE_SIZE, "edp panel\n");
+ case DP_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "dp panel\n");
break;
default:
ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.c b/drivers/video/fbdev/msm/mdss_hdmi_panel.c
index b4d3dad50d45..0335bf900866 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.c
@@ -150,7 +150,7 @@ enum hdmi_scaling_info {
HDMI_SCALING_HORZ_VERT,
};
-static int hdmi_panel_get_vic(struct mdss_panel_info *pinfo,
+int hdmi_panel_get_vic(struct mdss_panel_info *pinfo,
struct hdmi_util_ds_data *ds_data)
{
int new_vic = -1;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.h b/drivers/video/fbdev/msm/mdss_hdmi_panel.h
index 24d3b9b52798..e5cc1486f222 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_panel.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.h
@@ -104,4 +104,7 @@ void *hdmi_panel_init(struct hdmi_panel_init_data *data);
*/
void hdmi_panel_deinit(void *input);
+int hdmi_panel_get_vic(struct mdss_panel_info *pinfo,
+ struct hdmi_util_ds_data *ds_data);
+
#endif /* __MDSS_HDMI_PANEL_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index da60570c7085..921391dc4bde 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -56,7 +56,8 @@
#define C0_G_Y 0 /* G/luma */
/* wait for at most 2 vsync for lowest refresh rate (24hz) */
-#define KOFF_TIMEOUT msecs_to_jiffies(84)
+#define KOFF_TIMEOUT_MS 84
+#define KOFF_TIMEOUT msecs_to_jiffies(KOFF_TIMEOUT_MS)
#define OVERFETCH_DISABLE_TOP BIT(0)
#define OVERFETCH_DISABLE_BOTTOM BIT(1)
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 1a0ba8f0e2a7..2218e9c4ac81 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -2668,7 +2668,7 @@ int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff)
{
switch (ctl->panel_data->panel_info.type) {
case MIPI_VIDEO_PANEL:
- case EDP_PANEL:
+ case DP_PANEL:
case DTV_PANEL:
return mdss_mdp_video_reconfigure_splash_done(ctl, handoff);
case MIPI_CMD_PANEL:
@@ -3686,7 +3686,7 @@ struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
ctl->disable_prefill = false;
switch (pdata->panel_info.type) {
- case EDP_PANEL:
+ case DP_PANEL:
ctl->is_video_mode = true;
ctl->intf_num = MDSS_MDP_INTF0;
ctl->intf_type = MDSS_INTF_EDP;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c
index f19161ad25c4..9e3c2b7cdd1b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_debug.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c
@@ -937,6 +937,785 @@ static struct debug_bus dbg_bus_8996[] = {
{ 0x418, 60, 0},
};
+
+static struct debug_bus dbg_bus_msmcobalt[] = {
+
+ /*
+ * sspp0 - 0x188
+ * sspp1 - 0x298
+ * dspp - 0x348
+ * periph - 0x418
+ */
+
+ /* Unpack 0 sspp 0*/
+ { 0x188, 50, 2 },
+ { 0x188, 60, 2 },
+ { 0x188, 70, 2 },
+ { 0x188, 85, 2 },
+ /* Upack 0 sspp 1*/
+ { 0x298, 50, 2 },
+ { 0x298, 60, 2 },
+ { 0x298, 70, 2 },
+ { 0x298, 85, 2 },
+ /* scheduler */
+ { 0x348, 130, 0 },
+ { 0x348, 130, 1 },
+ { 0x348, 130, 2 },
+ { 0x348, 130, 3 },
+ { 0x348, 130, 4 },
+ { 0x348, 130, 5 },
+
+ /* qseed */
+ {0x188, 6, 0},
+ {0x188, 6, 1},
+ {0x188, 26, 0},
+ {0x188, 26, 1},
+ {0x298, 6, 0},
+ {0x298, 6, 1},
+ {0x298, 26, 0},
+ {0x298, 26, 1},
+
+ /* scale */
+ {0x188, 16, 0},
+ {0x188, 16, 1},
+ {0x188, 36, 0},
+ {0x188, 36, 1},
+ {0x298, 16, 0},
+ {0x298, 16, 1},
+ {0x298, 36, 0},
+ {0x298, 36, 1},
+
+ /* fetch sspp0 */
+
+ /* vig 0 */
+ { 0x188, 0, 0 },
+ { 0x188, 0, 1 },
+ { 0x188, 0, 2 },
+ { 0x188, 0, 3 },
+ { 0x188, 0, 4 },
+ { 0x188, 0, 5 },
+ { 0x188, 0, 6 },
+ { 0x188, 0, 7 },
+
+ { 0x188, 1, 0 },
+ { 0x188, 1, 1 },
+ { 0x188, 1, 2 },
+ { 0x188, 1, 3 },
+ { 0x188, 1, 4 },
+ { 0x188, 1, 5 },
+ { 0x188, 1, 6 },
+ { 0x188, 1, 7 },
+
+ { 0x188, 2, 0 },
+ { 0x188, 2, 1 },
+ { 0x188, 2, 2 },
+ { 0x188, 2, 3 },
+ { 0x188, 2, 4 },
+ { 0x188, 2, 5 },
+ { 0x188, 2, 6 },
+ { 0x188, 2, 7 },
+
+ { 0x188, 4, 0 },
+ { 0x188, 4, 1 },
+ { 0x188, 4, 2 },
+ { 0x188, 4, 3 },
+ { 0x188, 4, 4 },
+ { 0x188, 4, 5 },
+ { 0x188, 4, 6 },
+ { 0x188, 4, 7 },
+
+ { 0x188, 5, 0 },
+ { 0x188, 5, 1 },
+ { 0x188, 5, 2 },
+ { 0x188, 5, 3 },
+ { 0x188, 5, 4 },
+ { 0x188, 5, 5 },
+ { 0x188, 5, 6 },
+ { 0x188, 5, 7 },
+
+ /* vig 2 */
+ { 0x188, 20, 0 },
+ { 0x188, 20, 1 },
+ { 0x188, 20, 2 },
+ { 0x188, 20, 3 },
+ { 0x188, 20, 4 },
+ { 0x188, 20, 5 },
+ { 0x188, 20, 6 },
+ { 0x188, 20, 7 },
+
+ { 0x188, 21, 0 },
+ { 0x188, 21, 1 },
+ { 0x188, 21, 2 },
+ { 0x188, 21, 3 },
+ { 0x188, 21, 4 },
+ { 0x188, 21, 5 },
+ { 0x188, 21, 6 },
+ { 0x188, 21, 7 },
+
+ { 0x188, 22, 0 },
+ { 0x188, 22, 1 },
+ { 0x188, 22, 2 },
+ { 0x188, 22, 3 },
+ { 0x188, 22, 4 },
+ { 0x188, 22, 5 },
+ { 0x188, 22, 6 },
+ { 0x188, 22, 7 },
+
+ { 0x188, 24, 0 },
+ { 0x188, 24, 1 },
+ { 0x188, 24, 2 },
+ { 0x188, 24, 3 },
+ { 0x188, 24, 4 },
+ { 0x188, 24, 5 },
+ { 0x188, 24, 6 },
+ { 0x188, 24, 7 },
+
+ { 0x188, 25, 0 },
+ { 0x188, 25, 1 },
+ { 0x188, 25, 2 },
+ { 0x188, 25, 3 },
+ { 0x188, 25, 4 },
+ { 0x188, 25, 5 },
+ { 0x188, 25, 6 },
+ { 0x188, 25, 7 },
+
+ /* dma 2 */
+ { 0x188, 30, 0 },
+ { 0x188, 30, 1 },
+ { 0x188, 30, 2 },
+ { 0x188, 30, 3 },
+ { 0x188, 30, 4 },
+ { 0x188, 30, 5 },
+ { 0x188, 30, 6 },
+ { 0x188, 30, 7 },
+
+ { 0x188, 31, 0 },
+ { 0x188, 31, 1 },
+ { 0x188, 31, 2 },
+ { 0x188, 31, 3 },
+ { 0x188, 31, 4 },
+ { 0x188, 31, 5 },
+ { 0x188, 31, 6 },
+ { 0x188, 31, 7 },
+
+ { 0x188, 32, 0 },
+ { 0x188, 32, 1 },
+ { 0x188, 32, 2 },
+ { 0x188, 32, 3 },
+ { 0x188, 32, 4 },
+ { 0x188, 32, 5 },
+ { 0x188, 32, 6 },
+ { 0x188, 32, 7 },
+
+ { 0x188, 33, 0 },
+ { 0x188, 33, 1 },
+ { 0x188, 33, 2 },
+ { 0x188, 33, 3 },
+ { 0x188, 33, 4 },
+ { 0x188, 33, 5 },
+ { 0x188, 33, 6 },
+ { 0x188, 33, 7 },
+
+ { 0x188, 34, 0 },
+ { 0x188, 34, 1 },
+ { 0x188, 34, 2 },
+ { 0x188, 34, 3 },
+ { 0x188, 34, 4 },
+ { 0x188, 34, 5 },
+ { 0x188, 34, 6 },
+ { 0x188, 34, 7 },
+
+ { 0x188, 35, 0 },
+ { 0x188, 35, 1 },
+ { 0x188, 35, 2 },
+ { 0x188, 35, 3 },
+
+ /* dma 0 */
+ { 0x188, 40, 0 },
+ { 0x188, 40, 1 },
+ { 0x188, 40, 2 },
+ { 0x188, 40, 3 },
+ { 0x188, 40, 4 },
+ { 0x188, 40, 5 },
+ { 0x188, 40, 6 },
+ { 0x188, 40, 7 },
+
+ { 0x188, 41, 0 },
+ { 0x188, 41, 1 },
+ { 0x188, 41, 2 },
+ { 0x188, 41, 3 },
+ { 0x188, 41, 4 },
+ { 0x188, 41, 5 },
+ { 0x188, 41, 6 },
+ { 0x188, 41, 7 },
+
+ { 0x188, 42, 0 },
+ { 0x188, 42, 1 },
+ { 0x188, 42, 2 },
+ { 0x188, 42, 3 },
+ { 0x188, 42, 4 },
+ { 0x188, 42, 5 },
+ { 0x188, 42, 6 },
+ { 0x188, 42, 7 },
+
+ { 0x188, 44, 0 },
+ { 0x188, 44, 1 },
+ { 0x188, 44, 2 },
+ { 0x188, 44, 3 },
+ { 0x188, 44, 4 },
+ { 0x188, 44, 5 },
+ { 0x188, 44, 6 },
+ { 0x188, 44, 7 },
+
+ { 0x188, 45, 0 },
+ { 0x188, 45, 1 },
+ { 0x188, 45, 2 },
+ { 0x188, 45, 3 },
+ { 0x188, 45, 4 },
+ { 0x188, 45, 5 },
+ { 0x188, 45, 6 },
+ { 0x188, 45, 7 },
+
+ /* fetch sspp1 */
+ /* vig 1 */
+ { 0x298, 0, 0 },
+ { 0x298, 0, 1 },
+ { 0x298, 0, 2 },
+ { 0x298, 0, 3 },
+ { 0x298, 0, 4 },
+ { 0x298, 0, 5 },
+ { 0x298, 0, 6 },
+ { 0x298, 0, 7 },
+
+ { 0x298, 1, 0 },
+ { 0x298, 1, 1 },
+ { 0x298, 1, 2 },
+ { 0x298, 1, 3 },
+ { 0x298, 1, 4 },
+ { 0x298, 1, 5 },
+ { 0x298, 1, 6 },
+ { 0x298, 1, 7 },
+
+ { 0x298, 2, 0 },
+ { 0x298, 2, 1 },
+ { 0x298, 2, 2 },
+ { 0x298, 2, 3 },
+ { 0x298, 2, 4 },
+ { 0x298, 2, 5 },
+ { 0x298, 2, 6 },
+ { 0x298, 2, 7 },
+
+ { 0x298, 4, 0 },
+ { 0x298, 4, 1 },
+ { 0x298, 4, 2 },
+ { 0x298, 4, 3 },
+ { 0x298, 4, 4 },
+ { 0x298, 4, 5 },
+ { 0x298, 4, 6 },
+ { 0x298, 4, 7 },
+
+ { 0x298, 5, 0 },
+ { 0x298, 5, 1 },
+ { 0x298, 5, 2 },
+ { 0x298, 5, 3 },
+ { 0x298, 5, 4 },
+ { 0x298, 5, 5 },
+ { 0x298, 5, 6 },
+ { 0x298, 5, 7 },
+
+ /* vig 3 */
+ { 0x298, 20, 0 },
+ { 0x298, 20, 1 },
+ { 0x298, 20, 2 },
+ { 0x298, 20, 3 },
+ { 0x298, 20, 4 },
+ { 0x298, 20, 5 },
+ { 0x298, 20, 6 },
+ { 0x298, 20, 7 },
+
+ { 0x298, 21, 0 },
+ { 0x298, 21, 1 },
+ { 0x298, 21, 2 },
+ { 0x298, 21, 3 },
+ { 0x298, 21, 4 },
+ { 0x298, 21, 5 },
+ { 0x298, 21, 6 },
+ { 0x298, 21, 7 },
+
+ { 0x298, 22, 0 },
+ { 0x298, 22, 1 },
+ { 0x298, 22, 2 },
+ { 0x298, 22, 3 },
+ { 0x298, 22, 4 },
+ { 0x298, 22, 5 },
+ { 0x298, 22, 6 },
+ { 0x298, 22, 7 },
+
+ { 0x298, 24, 0 },
+ { 0x298, 24, 1 },
+ { 0x298, 24, 2 },
+ { 0x298, 24, 3 },
+ { 0x298, 24, 4 },
+ { 0x298, 24, 5 },
+ { 0x298, 24, 6 },
+ { 0x298, 24, 7 },
+
+ { 0x298, 25, 0 },
+ { 0x298, 25, 1 },
+ { 0x298, 25, 2 },
+ { 0x298, 25, 3 },
+ { 0x298, 25, 4 },
+ { 0x298, 25, 5 },
+ { 0x298, 25, 6 },
+ { 0x298, 25, 7 },
+
+ /* dma 3 */
+ { 0x298, 30, 0 },
+ { 0x298, 30, 1 },
+ { 0x298, 30, 2 },
+ { 0x298, 30, 3 },
+ { 0x298, 30, 4 },
+ { 0x298, 30, 5 },
+ { 0x298, 30, 6 },
+ { 0x298, 30, 7 },
+
+ { 0x298, 31, 0 },
+ { 0x298, 31, 1 },
+ { 0x298, 31, 2 },
+ { 0x298, 31, 3 },
+ { 0x298, 31, 4 },
+ { 0x298, 31, 5 },
+ { 0x298, 31, 6 },
+ { 0x298, 31, 7 },
+
+ { 0x298, 32, 0 },
+ { 0x298, 32, 1 },
+ { 0x298, 32, 2 },
+ { 0x298, 32, 3 },
+ { 0x298, 32, 4 },
+ { 0x298, 32, 5 },
+ { 0x298, 32, 6 },
+ { 0x298, 32, 7 },
+
+ { 0x298, 33, 0 },
+ { 0x298, 33, 1 },
+ { 0x298, 33, 2 },
+ { 0x298, 33, 3 },
+ { 0x298, 33, 4 },
+ { 0x298, 33, 5 },
+ { 0x298, 33, 6 },
+ { 0x298, 33, 7 },
+
+ { 0x298, 34, 0 },
+ { 0x298, 34, 1 },
+ { 0x298, 34, 2 },
+ { 0x298, 34, 3 },
+ { 0x298, 34, 4 },
+ { 0x298, 34, 5 },
+ { 0x298, 34, 6 },
+ { 0x298, 34, 7 },
+
+ { 0x298, 35, 0 },
+ { 0x298, 35, 1 },
+ { 0x298, 35, 2 },
+
+ /* dma 1 */
+ { 0x298, 40, 0 },
+ { 0x298, 40, 1 },
+ { 0x298, 40, 2 },
+ { 0x298, 40, 3 },
+ { 0x298, 40, 4 },
+ { 0x298, 40, 5 },
+ { 0x298, 40, 6 },
+ { 0x298, 40, 7 },
+
+ { 0x298, 41, 0 },
+ { 0x298, 41, 1 },
+ { 0x298, 41, 2 },
+ { 0x298, 41, 3 },
+ { 0x298, 41, 4 },
+ { 0x298, 41, 5 },
+ { 0x298, 41, 6 },
+ { 0x298, 41, 7 },
+
+ { 0x298, 42, 0 },
+ { 0x298, 42, 1 },
+ { 0x298, 42, 2 },
+ { 0x298, 42, 3 },
+ { 0x298, 42, 4 },
+ { 0x298, 42, 5 },
+ { 0x298, 42, 6 },
+ { 0x298, 42, 7 },
+
+ { 0x298, 44, 0 },
+ { 0x298, 44, 1 },
+ { 0x298, 44, 2 },
+ { 0x298, 44, 3 },
+ { 0x298, 44, 4 },
+ { 0x298, 44, 5 },
+ { 0x298, 44, 6 },
+ { 0x298, 44, 7 },
+
+ { 0x298, 45, 0 },
+ { 0x298, 45, 1 },
+ { 0x298, 45, 2 },
+ { 0x298, 45, 3 },
+ { 0x298, 45, 4 },
+ { 0x298, 45, 5 },
+ { 0x298, 45, 6 },
+ { 0x298, 45, 7 },
+
+ /* cursor 1 */
+ { 0x298, 80, 0 },
+ { 0x298, 80, 1 },
+ { 0x298, 80, 2 },
+ { 0x298, 80, 3 },
+ { 0x298, 80, 4 },
+ { 0x298, 80, 5 },
+ { 0x298, 80, 6 },
+ { 0x298, 80, 7 },
+
+ { 0x298, 81, 0 },
+ { 0x298, 81, 1 },
+ { 0x298, 81, 2 },
+ { 0x298, 81, 3 },
+ { 0x298, 81, 4 },
+ { 0x298, 81, 5 },
+ { 0x298, 81, 6 },
+ { 0x298, 81, 7 },
+
+ { 0x298, 82, 0 },
+ { 0x298, 82, 1 },
+ { 0x298, 82, 2 },
+ { 0x298, 82, 3 },
+ { 0x298, 82, 4 },
+ { 0x298, 82, 5 },
+ { 0x298, 82, 6 },
+ { 0x298, 82, 7 },
+
+ { 0x298, 83, 0 },
+ { 0x298, 83, 1 },
+ { 0x298, 83, 2 },
+ { 0x298, 83, 3 },
+ { 0x298, 83, 4 },
+ { 0x298, 83, 5 },
+ { 0x298, 83, 6 },
+ { 0x298, 83, 7 },
+
+ { 0x298, 84, 0 },
+ { 0x298, 84, 1 },
+ { 0x298, 84, 2 },
+ { 0x298, 84, 3 },
+ { 0x298, 84, 4 },
+ { 0x298, 84, 5 },
+ { 0x298, 84, 6 },
+ { 0x298, 84, 7 },
+
+ /* dspp */
+ { 0x348, 13, 0 },
+ { 0x348, 19, 0 },
+ { 0x348, 14, 0 },
+ { 0x348, 14, 1 },
+ { 0x348, 14, 3 },
+ { 0x348, 20, 0 },
+ { 0x348, 20, 1 },
+ { 0x348, 20, 3 },
+
+ /* ppb_0 */
+ { 0x348, 31, 0 },
+ { 0x348, 33, 0 },
+ { 0x348, 35, 0 },
+ { 0x348, 42, 0 },
+
+ /* ppb_1 */
+ { 0x348, 32, 0 },
+ { 0x348, 34, 0 },
+ { 0x348, 36, 0 },
+ { 0x348, 43, 0 },
+
+ /* lm_lut */
+ { 0x348, 109, 0 },
+ { 0x348, 105, 0 },
+ { 0x348, 103, 0 },
+
+ /* tear-check */
+ { 0x418, 63, 0 },
+ { 0x418, 64, 0 },
+ { 0x418, 65, 0 },
+ { 0x418, 73, 0 },
+ { 0x418, 74, 0 },
+
+ /* crossbar */
+ { 0x348, 0, 0},
+
+ /* rotator */
+ { 0x348, 9, 0},
+
+ /* blend */
+ /* LM0 */
+ { 0x348, 63, 0},
+ { 0x348, 63, 1},
+ { 0x348, 63, 2},
+ { 0x348, 63, 3},
+ { 0x348, 63, 4},
+ { 0x348, 63, 5},
+ { 0x348, 63, 6},
+ { 0x348, 63, 7},
+
+ { 0x348, 64, 0},
+ { 0x348, 64, 1},
+ { 0x348, 64, 2},
+ { 0x348, 64, 3},
+ { 0x348, 64, 4},
+ { 0x348, 64, 5},
+ { 0x348, 64, 6},
+ { 0x348, 64, 7},
+
+ { 0x348, 65, 0},
+ { 0x348, 65, 1},
+ { 0x348, 65, 2},
+ { 0x348, 65, 3},
+ { 0x348, 65, 4},
+ { 0x348, 65, 5},
+ { 0x348, 65, 6},
+ { 0x348, 65, 7},
+
+ { 0x348, 66, 0},
+ { 0x348, 66, 1},
+ { 0x348, 66, 2},
+ { 0x348, 66, 3},
+ { 0x348, 66, 4},
+ { 0x348, 66, 5},
+ { 0x348, 66, 6},
+ { 0x348, 66, 7},
+
+ { 0x348, 67, 0},
+ { 0x348, 67, 1},
+ { 0x348, 67, 2},
+ { 0x348, 67, 3},
+ { 0x348, 67, 4},
+ { 0x348, 67, 5},
+ { 0x348, 67, 6},
+ { 0x348, 67, 7},
+
+ { 0x348, 68, 0},
+ { 0x348, 68, 1},
+ { 0x348, 68, 2},
+ { 0x348, 68, 3},
+ { 0x348, 68, 4},
+ { 0x348, 68, 5},
+ { 0x348, 68, 6},
+ { 0x348, 68, 7},
+
+ { 0x348, 69, 0},
+ { 0x348, 69, 1},
+ { 0x348, 69, 2},
+ { 0x348, 69, 3},
+ { 0x348, 69, 4},
+ { 0x348, 69, 5},
+ { 0x348, 69, 6},
+ { 0x348, 69, 7},
+
+ /* LM1 */
+ { 0x348, 70, 0},
+ { 0x348, 70, 1},
+ { 0x348, 70, 2},
+ { 0x348, 70, 3},
+ { 0x348, 70, 4},
+ { 0x348, 70, 5},
+ { 0x348, 70, 6},
+ { 0x348, 70, 7},
+
+ { 0x348, 71, 0},
+ { 0x348, 71, 1},
+ { 0x348, 71, 2},
+ { 0x348, 71, 3},
+ { 0x348, 71, 4},
+ { 0x348, 71, 5},
+ { 0x348, 71, 6},
+ { 0x348, 71, 7},
+
+ { 0x348, 72, 0},
+ { 0x348, 72, 1},
+ { 0x348, 72, 2},
+ { 0x348, 72, 3},
+ { 0x348, 72, 4},
+ { 0x348, 72, 5},
+ { 0x348, 72, 6},
+ { 0x348, 72, 7},
+
+ { 0x348, 73, 0},
+ { 0x348, 73, 1},
+ { 0x348, 73, 2},
+ { 0x348, 73, 3},
+ { 0x348, 73, 4},
+ { 0x348, 73, 5},
+ { 0x348, 73, 6},
+ { 0x348, 73, 7},
+
+ { 0x348, 74, 0},
+ { 0x348, 74, 1},
+ { 0x348, 74, 2},
+ { 0x348, 74, 3},
+ { 0x348, 74, 4},
+ { 0x348, 74, 5},
+ { 0x348, 74, 6},
+ { 0x348, 74, 7},
+
+ { 0x348, 75, 0},
+ { 0x348, 75, 1},
+ { 0x348, 75, 2},
+ { 0x348, 75, 3},
+ { 0x348, 75, 4},
+ { 0x348, 75, 5},
+ { 0x348, 75, 6},
+ { 0x348, 75, 7},
+
+ { 0x348, 76, 0},
+ { 0x348, 76, 1},
+ { 0x348, 76, 2},
+ { 0x348, 76, 3},
+ { 0x348, 76, 4},
+ { 0x348, 76, 5},
+ { 0x348, 76, 6},
+ { 0x348, 76, 7},
+
+ /* LM2 */
+ { 0x348, 77, 0},
+ { 0x348, 77, 1},
+ { 0x348, 77, 2},
+ { 0x348, 77, 3},
+ { 0x348, 77, 4},
+ { 0x348, 77, 5},
+ { 0x348, 77, 6},
+ { 0x348, 77, 7},
+
+ { 0x348, 78, 0},
+ { 0x348, 78, 1},
+ { 0x348, 78, 2},
+ { 0x348, 78, 3},
+ { 0x348, 78, 4},
+ { 0x348, 78, 5},
+ { 0x348, 78, 6},
+ { 0x348, 78, 7},
+
+ { 0x348, 79, 0},
+ { 0x348, 79, 1},
+ { 0x348, 79, 2},
+ { 0x348, 79, 3},
+ { 0x348, 79, 4},
+ { 0x348, 79, 5},
+ { 0x348, 79, 6},
+ { 0x348, 79, 7},
+
+ { 0x348, 80, 0},
+ { 0x348, 80, 1},
+ { 0x348, 80, 2},
+ { 0x348, 80, 3},
+ { 0x348, 80, 4},
+ { 0x348, 80, 5},
+ { 0x348, 80, 6},
+ { 0x348, 80, 7},
+
+ { 0x348, 81, 0},
+ { 0x348, 81, 1},
+ { 0x348, 81, 2},
+ { 0x348, 81, 3},
+ { 0x348, 81, 4},
+ { 0x348, 81, 5},
+ { 0x348, 81, 6},
+ { 0x348, 81, 7},
+
+ { 0x348, 82, 0},
+ { 0x348, 82, 1},
+ { 0x348, 82, 2},
+ { 0x348, 82, 3},
+ { 0x348, 82, 4},
+ { 0x348, 82, 5},
+ { 0x348, 82, 6},
+ { 0x348, 82, 7},
+
+ { 0x348, 83, 0},
+ { 0x348, 83, 1},
+ { 0x348, 83, 2},
+ { 0x348, 83, 3},
+ { 0x348, 83, 4},
+ { 0x348, 83, 5},
+ { 0x348, 83, 6},
+ { 0x348, 83, 7},
+
+ /* csc */
+ {0x188, 7, 0},
+ {0x188, 7, 1},
+ {0x188, 27, 0},
+ {0x188, 27, 1},
+ {0x298, 7, 0},
+ {0x298, 7, 1},
+ {0x298, 27, 0},
+ {0x298, 27, 1},
+
+ /* pcc */
+ { 0x188, 3, 3},
+ { 0x188, 23, 3},
+ { 0x188, 33, 3},
+ { 0x188, 43, 3},
+ { 0x298, 3, 3},
+ { 0x298, 23, 3},
+ { 0x298, 33, 3},
+ { 0x298, 43, 3},
+
+ /* spa */
+ { 0x188, 8, 0},
+ { 0x188, 28, 0},
+ { 0x298, 8, 0},
+ { 0x298, 28, 0},
+ { 0x348, 13, 0},
+ { 0x348, 19, 0},
+
+ /* igc */
+ { 0x188, 9, 0},
+ { 0x188, 9, 1},
+ { 0x188, 9, 3},
+ { 0x188, 29, 0},
+ { 0x188, 29, 1},
+ { 0x188, 29, 3},
+ { 0x188, 17, 0},
+ { 0x188, 17, 1},
+ { 0x188, 17, 3},
+ { 0x188, 37, 0},
+ { 0x188, 37, 1},
+ { 0x188, 37, 3},
+ { 0x188, 46, 0},
+ { 0x188, 46, 1},
+ { 0x188, 46, 3},
+
+ { 0x298, 9, 0},
+ { 0x298, 9, 1},
+ { 0x298, 9, 3},
+ { 0x298, 29, 0},
+ { 0x298, 29, 1},
+ { 0x298, 29, 3},
+ { 0x298, 17, 0},
+ { 0x298, 17, 1},
+ { 0x298, 17, 3},
+ { 0x298, 37, 0},
+ { 0x298, 37, 1},
+ { 0x298, 37, 3},
+ { 0x298, 46, 0},
+ { 0x298, 46, 1},
+ { 0x298, 46, 3},
+
+ { 0x348, 14, 0},
+ { 0x348, 14, 1},
+ { 0x348, 14, 3},
+ { 0x348, 20, 0},
+ { 0x348, 20, 1},
+ { 0x348, 20, 3},
+
+ { 0x418, 60, 0},
+};
+
+
static struct vbif_debug_bus vbif_dbg_bus_8996[] = {
{0x214, 0x21c, 16, 2, 0x10}, /* arb clients */
{0x214, 0x21c, 0, 14, 0x13}, /* xin blocks - axi side */
@@ -953,6 +1732,7 @@ void mdss_mdp_hw_rev_debug_caps_init(struct mdss_data_type *mdata)
{
mdata->dbg_bus = NULL;
mdata->dbg_bus_size = 0;
+ mdata->dbg_bus_flags = 0;
switch (mdata->mdp_rev) {
case MDSS_MDP_HW_REV_107:
@@ -966,6 +1746,17 @@ void mdss_mdp_hw_rev_debug_caps_init(struct mdss_data_type *mdata)
mdata->nrt_vbif_dbg_bus_size =
ARRAY_SIZE(nrt_vbif_dbg_bus_8996);
break;
+ case MDSS_MDP_HW_REV_300:
+ case MDSS_MDP_HW_REV_301:
+ mdata->dbg_bus = dbg_bus_msmcobalt;
+ mdata->dbg_bus_size = ARRAY_SIZE(dbg_bus_msmcobalt);
+ mdata->vbif_dbg_bus = vbif_dbg_bus_8996;
+ mdata->vbif_dbg_bus_size = ARRAY_SIZE(vbif_dbg_bus_8996);
+ mdata->nrt_vbif_dbg_bus = nrt_vbif_dbg_bus_8996;
+ mdata->nrt_vbif_dbg_bus_size =
+ ARRAY_SIZE(nrt_vbif_dbg_bus_8996);
+ mdata->dbg_bus_flags = DEBUG_FLAGS_DSPP;
+ break;
default:
break;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
index de868bcd8f6f..f54cbb575535 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
@@ -819,6 +819,8 @@ enum mdss_mdp_pingpong_index {
#define MDSS_MDP_REG_CDM_HDMI_PACK_OP_MODE 0x200
+#define MDSS_MDP_DSPP_DEBUGBUS_STATUS 0x34C
+
/* Following offsets are with respect to MDP base */
#define MDSS_MDP_MDP_OUT_CTL_0 0x410
#define MDSS_MDP_INTF_CMD_MISR_CTRL (MDSS_MDP_INTF_MISR_CTRL + 0x8)
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index a1e5982bccda..5a65451dc127 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -1835,6 +1835,26 @@ int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
return ret;
}
+static int __mdss_mdp_wait4pingpong(struct mdss_mdp_cmd_ctx *ctx)
+{
+ int rc = 0;
+ s64 expected_time = ktime_to_ms(ktime_get()) + KOFF_TIMEOUT_MS;
+ s64 time;
+
+ do {
+ rc = wait_event_timeout(ctx->pp_waitq,
+ atomic_read(&ctx->koff_cnt) == 0,
+ KOFF_TIMEOUT);
+ time = ktime_to_ms(ktime_get());
+
+ MDSS_XLOG(rc, time, expected_time, atomic_read(&ctx->koff_cnt));
+ /* If we timed out, counter is valid and time is less, wait again */
+ } while (atomic_read(&ctx->koff_cnt) && (rc == 0) &&
+ (time < expected_time));
+
+ return rc;
+}
+
static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
{
struct mdss_mdp_cmd_ctx *ctx;
@@ -1856,9 +1876,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
pr_debug("%s: intf_num=%d ctx=%p koff_cnt=%d\n", __func__,
ctl->intf_num, ctx, atomic_read(&ctx->koff_cnt));
- rc = wait_event_timeout(ctx->pp_waitq,
- atomic_read(&ctx->koff_cnt) == 0,
- KOFF_TIMEOUT);
+ rc = __mdss_mdp_wait4pingpong(ctx);
trace_mdp_cmd_wait_pingpong(ctl->num,
atomic_read(&ctx->koff_cnt));
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 7a49f37660dd..bde137269422 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -51,7 +51,7 @@ struct panel_id {
#define MIPI_CMD_PANEL 9 /* MIPI */
#define WRITEBACK_PANEL 10 /* Wifi display */
#define LVDS_PANEL 11 /* LVDS */
-#define EDP_PANEL 12 /* LVDS */
+#define DP_PANEL 12 /* LVDS */
#define DSC_PPS_LEN 128
@@ -61,7 +61,7 @@ static inline const char *mdss_panel2str(u32 panel)
#define PANEL_NAME(n) [n ## _PANEL] = __stringify(n)
PANEL_NAME(MIPI_VIDEO),
PANEL_NAME(MIPI_CMD),
- PANEL_NAME(EDP),
+ PANEL_NAME(DP),
PANEL_NAME(HDMI),
PANEL_NAME(DTV),
PANEL_NAME(WRITEBACK),
@@ -811,7 +811,7 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info)
case MIPI_CMD_PANEL:
frame_rate = panel_info->mipi.frame_rate;
break;
- case EDP_PANEL:
+ case DP_PANEL:
frame_rate = panel_info->edp.frame_rate;
break;
case WRITEBACK_PANEL:
diff --git a/include/dt-bindings/clock/msm-clocks-8996.h b/include/dt-bindings/clock/msm-clocks-8996.h
index 2f9cfd0e008c..22109a6766db 100644
--- a/include/dt-bindings/clock/msm-clocks-8996.h
+++ b/include/dt-bindings/clock/msm-clocks-8996.h
@@ -540,4 +540,33 @@
#define clk_sys_apcsaux_clk 0x0b0dd513
#define clk_cpu_debug_mux 0xc7acaa31
+/* GCC block resets */
+#define QUSB2PHY_PRIM_BCR 0
+#define QUSB2PHY_SEC_BCR 1
+#define BLSP1_BCR 2
+#define BLSP2_BCR 3
+#define BOOT_ROM_BCR 4
+#define PRNG_BCR 5
+#define UFS_BCR 6
+#define USB_20_BCR 7
+#define USB_30_BCR 8
+#define USB3_PHY_BCR 9
+#define USB3PHY_PHY_BCR 10
+#define PCIE_0_PHY_BCR 11
+#define PCIE_1_PHY_BCR 12
+#define PCIE_2_PHY_BCR 13
+#define PCIE_PHY_BCR 14
+#define PCIE_PHY_COM_BCR 15
+#define PCIE_PHY_NOCSR_COM_PHY_BCR 16
+
+/* MMSS Block resets */
+#define VIDEO_BCR 0
+#define MDSS_BCR 1
+#define CAMSS_MICRO_BCR 2
+#define CAMSS_JPEG_BCR 3
+#define CAMSS_VFE0_BCR 4
+#define CAMSS_VFE1_BCR 5
+#define FD_BCR 6
+#define GPU_GX_BCR 7
+
#endif
diff --git a/include/dt-bindings/clock/qcom,gcc-msmfalcon.h b/include/dt-bindings/clock/qcom,gcc-msmfalcon.h
index d0a8419ee54c..6860d78e020e 100644
--- a/include/dt-bindings/clock/qcom,gcc-msmfalcon.h
+++ b/include/dt-bindings/clock/qcom,gcc-msmfalcon.h
@@ -14,230 +14,229 @@
#ifndef _DT_BINDINGS_CLK_MSM_GCC_FALCON_H
#define _DT_BINDINGS_CLK_MSM_GCC_FALCON_H
-/* Clocks */
-#define GPLL0 0
-#define GPLL1 1
-#define GPLL2 2
-#define GPLL3 3
-#define GPLL4 4
-#define GPLL5 5
-#define GPLL6 6
-#define MMSS_QM_CORE_CLK_SRC 7
-#define USB30_MASTER_CLK_SRC 8
-#define USB30_MOCK_UTMI_CLK_SRC 9
-#define USB3_PHY_AUX_CLK_SRC 10
-#define USB20_MASTER_CLK_SRC 11
-#define USB20_MOCK_UTMI_CLK_SRC 12
-#define SDCC2_APPS_CLK_SRC 13
-#define SDCC1_ICE_CORE_CLK_SRC 14
-#define SDCC1_APPS_CLK_SRC 15
-#define BLSP1_QUP1_SPI_APPS_CLK_SRC 16
-#define BLSP1_QUP1_I2C_APPS_CLK_SRC 17
-#define BLSP1_UART1_APPS_CLK_SRC 18
-#define BLSP1_QUP2_SPI_APPS_CLK_SRC 19
-#define BLSP1_QUP2_I2C_APPS_CLK_SRC 20
-#define BLSP1_UART2_APPS_CLK_SRC 21
-#define BLSP1_QUP3_SPI_APPS_CLK_SRC 22
-#define BLSP1_QUP3_I2C_APPS_CLK_SRC 23
-#define BLSP1_QUP4_SPI_APPS_CLK_SRC 24
-#define BLSP1_QUP4_I2C_APPS_CLK_SRC 25
-#define BLSP2_QUP1_SPI_APPS_CLK_SRC 26
-#define BLSP2_QUP1_I2C_APPS_CLK_SRC 27
-#define BLSP2_UART1_APPS_CLK_SRC 28
-#define BLSP2_QUP2_SPI_APPS_CLK_SRC 29
-#define BLSP2_QUP2_I2C_APPS_CLK_SRC 30
-#define BLSP2_UART2_APPS_CLK_SRC 31
-#define BLSP2_QUP3_SPI_APPS_CLK_SRC 32
-#define BLSP2_QUP3_I2C_APPS_CLK_SRC 33
-#define BLSP2_QUP4_SPI_APPS_CLK_SRC 34
-#define BLSP2_QUP4_I2C_APPS_CLK_SRC 35
-#define PDM2_CLK_SRC 36
-#define HMSS_AHB_CLK_SRC 37
-#define BIMC_HMSS_AXI_CLK_SRC 38
-#define HMSS_RBCPR_CLK_SRC 39
-#define HMSS_GPLL0_CLK_SRC 40
-#define HMSS_GPLL4_CLK_SRC 41
-#define GP1_CLK_SRC 42
-#define GP2_CLK_SRC 43
-#define GP3_CLK_SRC 44
-#define UFS_AXI_CLK_SRC 45
-#define UFS_ICE_CORE_CLK_SRC 46
-#define UFS_UNIPRO_CORE_CLK_SRC 47
-#define UFS_PHY_AUX_CLK_SRC 48
-#define QSPI_SER_CLK_SRC 49
-#define GLM_CLK_SRC 50
-#define GCC_MMSS_SYS_NOC_AXI_CLK 51
-#define GCC_MMSS_NOC_CFG_AHB_CLK 52
-#define GCC_MMSS_QM_CORE_CLK 53
-#define GCC_MMSS_QM_AHB_CLK 54
-#define GCC_USB30_MASTER_CLK 55
-#define GCC_USB30_SLEEP_CLK 56
-#define GCC_USB30_MOCK_UTMI_CLK 57
-#define GCC_USB3_PHY_AUX_CLK 58
-#define GCC_USB3_PHY_PIPE_CLK 59
-#define GCC_USB20_MASTER_CLK 60
-#define GCC_USB20_SLEEP_CLK 61
-#define GCC_USB20_MOCK_UTMI_CLK 62
-#define GCC_USB_PHY_CFG_AHB2PHY_CLK 63
-#define GCC_SDCC2_APPS_CLK 64
-#define GCC_SDCC2_AHB_CLK 65
-#define GCC_SDCC1_APPS_CLK 66
-#define GCC_SDCC1_AHB_CLK 67
-#define GCC_SDCC1_ICE_CORE_CLK 68
-#define GCC_BLSP1_AHB_CLK 69
-#define GCC_BLSP1_SLEEP_CLK 70
-#define GCC_BLSP1_QUP1_SPI_APPS_CLK 71
-#define GCC_BLSP1_QUP1_I2C_APPS_CLK 72
-#define GCC_BLSP1_UART1_APPS_CLK 73
-#define GCC_BLSP1_QUP2_SPI_APPS_CLK 74
-#define GCC_BLSP1_QUP2_I2C_APPS_CLK 75
-#define GCC_BLSP1_UART2_APPS_CLK 76
-#define GCC_BLSP1_QUP3_SPI_APPS_CLK 77
-#define GCC_BLSP1_QUP3_I2C_APPS_CLK 78
-#define GCC_BLSP1_QUP4_SPI_APPS_CLK 79
-#define GCC_BLSP1_QUP4_I2C_APPS_CLK 80
-#define GCC_BLSP2_AHB_CLK 81
-#define GCC_BLSP2_SLEEP_CLK 82
-#define GCC_BLSP2_QUP1_SPI_APPS_CLK 83
-#define GCC_BLSP2_QUP1_I2C_APPS_CLK 84
-#define GCC_BLSP2_UART1_APPS_CLK 85
-#define GCC_BLSP2_QUP2_SPI_APPS_CLK 86
-#define GCC_BLSP2_QUP2_I2C_APPS_CLK 87
-#define GCC_BLSP2_UART2_APPS_CLK 88
-#define GCC_BLSP2_QUP3_SPI_APPS_CLK 89
-#define GCC_BLSP2_QUP3_I2C_APPS_CLK 90
-#define GCC_BLSP2_QUP4_SPI_APPS_CLK 91
-#define GCC_BLSP2_QUP4_I2C_APPS_CLK 92
-#define GCC_PDM_AHB_CLK 93
-#define GCC_PDM_XO4_CLK 94
-#define GCC_PDM2_CLK 95
-#define GCC_PRNG_AHB_CLK 96
-#define GCC_BIMC_GFX_CLK 97
-#define GCC_MCCC_CFG_AHB_CLK 98
-#define GCC_LPASS_TRIG_CLK 99
-#define GCC_LPASS_AT_CLK 100
-#define GCC_TURING_TRIG_CLK 101
-#define GCC_TURING_AT_CLK 102
-#define GCC_HMSS_AHB_CLK 103
-#define GCC_BIMC_HMSS_AXI_CLK 104
-#define GCC_HMSS_RBCPR_CLK 105
-#define GCC_HMSS_TRIG_CLK 106
-#define GCC_HMSS_AT_CLK 107
-#define GCC_HMSS_DVM_BUS_CLK 108
-#define GCC_GP1_CLK 109
-#define GCC_GP2_CLK 110
-#define GCC_GP3_CLK 111
-#define GCC_UFS_AXI_CLK 112
-#define GCC_UFS_AHB_CLK 113
-#define GCC_UFS_TX_SYMBOL_0_CLK 114
-#define GCC_UFS_RX_SYMBOL_0_CLK 115
-#define GCC_UFS_UNIPRO_CORE_CLK 116
-#define GCC_UFS_ICE_CORE_CLK 117
-#define GCC_UFS_PHY_AUX_CLK 118
-#define GCC_UFS_RX_SYMBOL_1_CLK 119
-#define GCC_AGGRE2_USB3_AXI_CLK 120
-#define GCC_AGGRE2_UFS_AXI_CLK 121
-#define GCC_QSPI_AHB_CLK 122
-#define GCC_QSPI_SER_CLK 123
-#define GCC_GLM_AHB_CLK 124
-#define GCC_GLM_CLK 125
-#define GCC_GLM_XO_CLK 126
-#define GCC_WCSS_AHB_S0_CLK 127
-#define GCC_WCSS_AXI_M_CLK 128
-#define GCC_WCSS_ECAHB_CLK 129
-#define GCC_WCSS_SHDREG_AHB_CLK 130
-#define GCC_GPU_CFG_AHB_CLK 131
-#define GCC_GPU_BIMC_GFX_SRC_CLK 132
-#define GCC_GPU_BIMC_GFX_CLK 133
-#define GCC_GPU_SNOC_DVM_GFX_CLK 134
+#define BIMC_HMSS_AXI_CLK_SRC 0
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 1
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 2
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 3
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 4
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 5
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 6
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 7
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 8
+#define BLSP1_UART1_APPS_CLK_SRC 9
+#define BLSP1_UART2_APPS_CLK_SRC 10
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 11
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 12
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 13
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 14
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 15
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 16
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 17
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 18
+#define BLSP2_UART1_APPS_CLK_SRC 19
+#define BLSP2_UART2_APPS_CLK_SRC 20
+#define GCC_AGGRE2_UFS_AXI_CLK 21
+#define GCC_AGGRE2_USB3_AXI_CLK 22
+#define GCC_BIMC_GFX_CLK 23
+#define GCC_BIMC_HMSS_AXI_CLK 24
+#define GCC_BIMC_MSS_Q6_AXI_CLK 25
+#define GCC_BLSP1_AHB_CLK 26
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 27
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 28
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 29
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 30
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 31
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 32
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 33
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 34
+#define GCC_BLSP1_UART1_APPS_CLK 35
+#define GCC_BLSP1_UART2_APPS_CLK 36
+#define GCC_BLSP2_AHB_CLK 37
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 38
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 39
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 40
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 41
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 42
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 43
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 44
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 45
+#define GCC_BLSP2_UART1_APPS_CLK 46
+#define GCC_BLSP2_UART2_APPS_CLK 47
+#define GCC_BOOT_ROM_AHB_CLK 48
+#define GCC_CFG_NOC_USB2_AXI_CLK 49
+#define GCC_CFG_NOC_USB3_AXI_CLK 50
+#define GCC_GLM_AHB_CLK 51
+#define GCC_GLM_CLK 52
+#define GCC_GP1_CLK 53
+#define GCC_GP2_CLK 54
+#define GCC_GP3_CLK 55
+#define GCC_GPU_BIMC_GFX_CLK 56
+#define GCC_GPU_BIMC_GFX_SRC_CLK 57
+#define GCC_GPU_CFG_AHB_CLK 58
+#define GCC_GPU_SNOC_DVM_GFX_CLK 59
+#define GCC_HMSS_AHB_CLK 60
+#define GCC_HMSS_DVM_BUS_CLK 61
+#define GCC_HMSS_RBCPR_CLK 62
+#define GCC_MMSS_NOC_CFG_AHB_CLK 63
+#define GCC_MMSS_QM_AHB_CLK 64
+#define GCC_MMSS_QM_CORE_CLK 65
+#define GCC_MMSS_SYS_NOC_AXI_CLK 66
+#define GCC_PDM2_CLK 67
+#define GCC_PDM_AHB_CLK 68
+#define GCC_PRNG_AHB_CLK 69
+#define GCC_QSPI_AHB_CLK 70
+#define GCC_QSPI_SER_CLK 71
+#define GCC_SDCC1_AHB_CLK 72
+#define GCC_SDCC1_APPS_CLK 73
+#define GCC_SDCC1_ICE_CORE_CLK 74
+#define GCC_SDCC2_AHB_CLK 75
+#define GCC_SDCC2_APPS_CLK 76
+#define GCC_UFS_AHB_CLK 77
+#define GCC_UFS_AXI_CLK 78
+#define GCC_UFS_ICE_CORE_CLK 79
+#define GCC_UFS_PHY_AUX_CLK 80
+#define GCC_UFS_RX_SYMBOL_0_CLK 81
+#define GCC_UFS_RX_SYMBOL_1_CLK 82
+#define GCC_UFS_TX_SYMBOL_0_CLK 83
+#define GCC_UFS_UNIPRO_CORE_CLK 84
+#define GCC_USB20_MASTER_CLK 85
+#define GCC_USB20_MOCK_UTMI_CLK 86
+#define GCC_USB20_SLEEP_CLK 87
+#define GCC_USB30_MASTER_CLK 88
+#define GCC_USB30_MOCK_UTMI_CLK 89
+#define GCC_USB30_SLEEP_CLK 90
+#define GCC_USB3_PHY_AUX_CLK 91
+#define GCC_USB3_PHY_PIPE_CLK 92
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK 93
+#define GCC_WCSS_AHB_S0_CLK 94
+#define GCC_WCSS_AXI_M_CLK 95
+#define GCC_WCSS_ECAHB_CLK 96
+#define GCC_WCSS_SHDREG_AHB_CLK 97
+#define GLM_CLK_SRC 98
+#define GP1_CLK_SRC 99
+#define GP2_CLK_SRC 100
+#define GP3_CLK_SRC 101
+#define GPLL0 102
+#define GPLL0_OUT_AUX 103
+#define GPLL0_OUT_AUX2 104
+#define GPLL0_OUT_EARLY 105
+#define GPLL0_OUT_MAIN 106
+#define GPLL0_OUT_TEST 107
+#define GPLL1 108
+#define GPLL1_OUT_AUX 109
+#define GPLL1_OUT_AUX2 110
+#define GPLL1_OUT_EARLY 111
+#define GPLL1_OUT_MAIN 112
+#define GPLL1_OUT_TEST 113
+#define GPLL2 114
+#define GPLL2_OUT_AUX 115
+#define GPLL2_OUT_AUX2 116
+#define GPLL2_OUT_EARLY 117
+#define GPLL2_OUT_MAIN 118
+#define GPLL2_OUT_TEST 119
+#define GPLL3 120
+#define GPLL3_OUT_AUX 121
+#define GPLL3_OUT_AUX2 122
+#define GPLL3_OUT_EARLY 123
+#define GPLL3_OUT_MAIN 124
+#define GPLL3_OUT_TEST 125
+#define GPLL4 126
+#define GPLL4_OUT_AUX 127
+#define GPLL4_OUT_AUX2 128
+#define GPLL4_OUT_EARLY 129
+#define GPLL4_OUT_MAIN 130
+#define GPLL4_OUT_TEST 131
+#define GPLL5 132
+#define GPLL5_OUT_AUX 133
+#define GPLL5_OUT_AUX2 134
+#define GPLL5_OUT_EARLY 135
+#define GPLL5_OUT_MAIN 136
+#define GPLL5_OUT_TEST 137
+#define GPLL6 138
+#define GPLL6_OUT_AUX 139
+#define GPLL6_OUT_AUX2 140
+#define GPLL6_OUT_EARLY 141
+#define GPLL6_OUT_MAIN 142
+#define GPLL6_OUT_TEST 143
+#define HMSS_AHB_CLK_SRC 144
+#define HMSS_GPLL0_CLK_SRC 145
+#define HMSS_GPLL4_CLK_SRC 146
+#define HMSS_RBCPR_CLK_SRC 147
+#define MMSS_QM_CORE_CLK_SRC 148
+#define PDM2_CLK_SRC 149
+#define QSPI_SER_CLK_SRC 150
+#define SDCC1_APPS_CLK_SRC 151
+#define SDCC1_ICE_CORE_CLK_SRC 152
+#define SDCC2_APPS_CLK_SRC 153
+#define UFS_AXI_CLK_SRC 154
+#define UFS_ICE_CORE_CLK_SRC 155
+#define UFS_PHY_AUX_CLK_SRC 156
+#define UFS_UNIPRO_CORE_CLK_SRC 157
+#define USB20_MASTER_CLK_SRC 158
+#define USB20_MOCK_UTMI_CLK_SRC 159
+#define USB30_MASTER_CLK_SRC 160
+#define USB30_MOCK_UTMI_CLK_SRC 161
+#define USB3_PHY_AUX_CLK_SRC 162
-/* Block Resets */
-#define GCC_SYSTEM_NOC_BCR 0
-#define GCC_CONFIG_NOC_BCR 1
-#define GCC_IMEM_BCR 2
-#define GCC_MMSS_BCR 3
-#define GCC_PIMEM_BCR 4
-#define GCC_QDSS_BCR 5
-#define GCC_USB_30_BCR 6
-#define GCC_USB_20_BCR 7
-#define GCC_QUSB2PHY_PRIM_BCR 8
-#define GCC_QUSB2PHY_SEC_BCR 9
-#define GCC_USB_PHY_CFG_AHB2PHY_BCR 10
-#define GCC_SDCC2_BCR 11
-#define GCC_SDCC1_BCR 12
-#define GCC_BLSP1_BCR 13
-#define GCC_BLSP1_QUP1_BCR 14
-#define GCC_BLSP1_UART1_BCR 15
-#define GCC_BLSP1_QUP2_BCR 16
-#define GCC_BLSP1_UART2_BCR 17
-#define GCC_BLSP1_QUP3_BCR 18
-#define GCC_BLSP1_QUP4_BCR 19
-#define GCC_BLSP2_BCR 20
-#define GCC_BLSP2_QUP1_BCR 21
-#define GCC_BLSP2_UART1_BCR 22
-#define GCC_BLSP2_QUP2_BCR 23
-#define GCC_BLSP2_UART2_BCR 24
-#define GCC_BLSP2_QUP3_BCR 25
-#define GCC_BLSP2_QUP4_BCR 26
-#define GCC_PDM_BCR 27
-#define GCC_PRNG_BCR 28
-#define GCC_TCSR_BCR 29
-#define GCC_BOOT_ROM_BCR 30
-#define GCC_MSG_RAM_BCR 31
-#define GCC_TLMM_BCR 32
-#define GCC_MPM_BCR 33
-#define GCC_SEC_CTRL_BCR 34
-#define GCC_SPMI_BCR 35
-#define GCC_SPDM_BCR 36
-#define GCC_CE1_BCR 37
-#define GCC_BIMC_BCR 38
-#define GCC_SNOC_BUS_TIMEOUT0_BCR 39
-#define GCC_SNOC_BUS_TIMEOUT1_BCR 40
-#define GCC_SNOC_BUS_TIMEOUT3_BCR 41
-#define GCC_SNOC_BUS_TIMEOUT_EXTREF_BCR 42
-#define GCC_SNOC_BUS_TIMEOUT4_BCR 43
-#define GCC_PNOC_BUS_TIMEOUT0_BCR 44
-#define GCC_CNOC_PERIPH_BUS_TIMEOUT1_BCR 45
-#define GCC_CNOC_PERIPH_BUS_TIMEOUT2_BCR 46
-#define GCC_CNOC_BUS_TIMEOUT0_BCR 47
-#define GCC_CNOC_BUS_TIMEOUT2_BCR 48
-#define GCC_CNOC_BUS_TIMEOUT3_BCR 49
-#define GCC_CNOC_BUS_TIMEOUT4_BCR 50
-#define GCC_CNOC_BUS_TIMEOUT5_BCR 51
-#define GCC_CNOC_BUS_TIMEOUT6_BCR 52
-#define GCC_CNOC_BUS_TIMEOUT7_BCR 53
-#define GCC_CNOC_BUS_TIMEOUT8_BCR 54
-#define GCC_CNOC_BUS_TIMEOUT9_BCR 55
-#define GCC_CNOC_BUS_TIMEOUT10_BCR 56
-#define GCC_CNOC_BUS_TIMEOUT11_BCR 57
-#define GCC_CNOC_BUS_TIMEOUT12_BCR 58
-#define GCC_CNOC_BUS_TIMEOUT13_BCR 59
-#define GCC_CNOC_BUS_TIMEOUT14_BCR 60
-#define GCC_CNOC_BUS_TIMEOUT_EXTREF_BCR 61
-#define GCC_APB2JTAG_BCR 62
-#define GCC_RBCPR_CX_BCR 63
-#define GCC_RBCPR_MX_BCR 64
-#define GCC_OBT_ODT_BCR 65
-#define GCC_UFS_BCR 66
-#define GCC_VS_BCR 67
-#define GCC_AGGRE2_NOC_BCR 68
-#define GCC_DCC_BCR 69
-#define GCC_QSPI_BCR 70
-#define GCC_IPA_BCR 71
-#define GCC_GLM_BCR 72
-#define GCC_MSMPU_BCR 73
-#define GCC_QREFS_VBG_CAL_BCR 74
-#define GCC_WCSS_BCR 75
-#define GCC_GPU_BCR 76
-#define GCC_AHB2PHY_EAST_BCR 77
-#define GCC_CM_PHY_REFGEN1_BCR 78
-#define GCC_CM_PHY_REFGEN2_BCR 79
-#define GCC_SRAM_SENSOR_BCR 80
+#define UFS_GDSC 0
+#define USB_30_GDSC 1
-/* GDSC */
-#define UFS_GDSC 0
-#define USB_30_GDSC 1
-#define DDR_DIM_WRAPPER_GDSC 2
-#define MMSS_GDSC 3
+#define GCC_QUSB2PHY_PRIM_BCR 0
+#define GCC_QUSB2PHY_SEC_BCR 1
+#define GCC_UFS_BCR 2
+#define GCC_USB3_DP_PHY_BCR 3
+#define GCC_USB3_PHY_BCR 4
+#define GCC_USB3PHY_PHY_BCR 5
+#define GCC_USB_20_BCR 6
+#define GCC_USB_30_BCR 7
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR 8
+
+/* RPM controlled clocks */
+#define RPM_CE1_CLK 1
+#define RPM_CE1_A_CLK 2
+#define RPM_CXO_CLK_SRC 3
+#define RPM_BIMC_CLK 4
+#define RPM_BIMC_A_CLK 5
+#define RPM_CNOC_CLK 6
+#define RPM_CNOC_A_CLK 7
+#define RPM_SNOC_CLK 8
+#define RPM_SNOC_A_CLK 9
+#define RPM_CNOC_PERIPH_CLK 10
+#define RPM_CNOC_PERIPH_A_CLK 11
+#define RPM_CNOC_PERIPH_KEEPALIVE_A_CLK 12
+#define RPM_LN_BB_CLK1 13
+#define RPM_LN_BB_CLK1_AO 14
+#define RPM_LN_BB_CLK1_PIN 15
+#define RPM_LN_BB_CLK1_PIN_AO 16
+#define RPM_BIMC_MSMBUS_CLK 17
+#define RPM_BIMC_MSMBUS_A_CLK 18
+#define RPM_CNOC_MSMBUS_CLK 19
+#define RPM_CNOC_MSMBUS_A_CLK 20
+#define RPM_CXO_CLK_SRC_AO 21
+#define RPM_CXO_DWC3_CLK 22
+#define RPM_CXO_LPM_CLK 23
+#define RPM_CXO_OTG_CLK 24
+#define RPM_CXO_PIL_LPASS_CLK 25
+#define RPM_CXO_PIL_SSC_CLK 26
+#define RPM_CXO_PIL_SPSS_CLK 27
+#define RPM_DIV_CLK1 28
+#define RPM_DIV_CLK1_AO 29
+#define RPM_IPA_CLK 30
+#define RPM_IPA_A_CLK 31
+#define RPM_MCD_CE1_CLK 32
+#define RPM_MMSSNOC_AXI_CLK 33
+#define RPM_MMSSNOC_AXI_A_CLK 34
+#define RPM_QCEDEV_CE1_CLK 35
+#define RPM_QCRYPTO_CE1_CLK 36
+#define RPM_QDSS_CLK 37
+#define RPM_QDSS_A_CLK 38
+#define RPM_QSEECOM_CE1_CLK 39
+#define RPM_RF_CLK2 40
+#define RPM_RF_CLK2_AO 41
+#define RPM_SCM_CE1_CLK 42
+#define RPM_SNOC_MSMBUS_CLK 43
+#define RPM_SNOC_MSMBUS_A_CLK 44
+#define RPM_AGGRE2_NOC_CLK 45
+#define RPM_AGGRE2_NOC_A_CLK 46
#endif
diff --git a/include/dt-bindings/clock/qcom,gpu-msmfalcon.h b/include/dt-bindings/clock/qcom,gpu-msmfalcon.h
index a167716e9cc6..427c6aae05d3 100644
--- a/include/dt-bindings/clock/qcom,gpu-msmfalcon.h
+++ b/include/dt-bindings/clock/qcom,gpu-msmfalcon.h
@@ -14,25 +14,27 @@
#ifndef _DT_BINDINGS_CLK_MSM_GPU_FALCON_H
#define _DT_BINDINGS_CLK_MSM_GPU_FALCON_H
-/* Clocks */
-#define GPU_PLL0_PLL 0
-#define GPU_PLL1_PLL 1
-#define GFX3D_CLK_SRC 2
-#define RBBMTIMER_CLK_SRC 3
-#define RBCPR_CLK_SRC 4
-#define GPUCC_CXO_CLK 5
-#define GPUCC_GFX3D_CLK 6
-#define GPUCC_RBBMTIMER_CLK 7
-#define GPUCC_RBCPR_CLK 8
+#define GFX3D_CLK_SRC 0
+#define GPU_PLL0_PLL 1
+#define GPU_PLL0_PLL_OUT_AUX 2
+#define GPU_PLL0_PLL_OUT_AUX2 3
+#define GPU_PLL0_PLL_OUT_EARLY 4
+#define GPU_PLL0_PLL_OUT_MAIN 5
+#define GPU_PLL0_PLL_OUT_TEST 6
+#define GPU_PLL1_PLL 7
+#define GPU_PLL1_PLL_OUT_AUX 8
+#define GPU_PLL1_PLL_OUT_AUX2 9
+#define GPU_PLL1_PLL_OUT_EARLY 10
+#define GPU_PLL1_PLL_OUT_MAIN 11
+#define GPU_PLL1_PLL_OUT_TEST 12
+#define GPUCC_CXO_CLK 13
+#define GPUCC_GFX3D_CLK 14
+#define GPUCC_RBBMTIMER_CLK 15
+#define GPUCC_RBCPR_CLK 16
+#define RBBMTIMER_CLK_SRC 18
+#define RBCPR_CLK_SRC 19
-/* Block Reset */
-#define GPU_CC_GPU_GX_BCR 0
-#define GPU_CC_GPU_CX_BCR 1
-#define GPU_CC_RBCPR_BCR 2
-#define GPU_CC_SPDM_BCR 3
-
-/* GDSC */
-#define GPU_GX_GDSC 0
-#define GPU_CX_GDSC 1
+#define GPU_CX_GDSC 0
+#define GPU_GX_GDSC 1
#endif
diff --git a/include/dt-bindings/clock/qcom,mmcc-msmfalcon.h b/include/dt-bindings/clock/qcom,mmcc-msmfalcon.h
index 57aed7c8f43f..ffb80a128dd6 100644
--- a/include/dt-bindings/clock/qcom,mmcc-msmfalcon.h
+++ b/include/dt-bindings/clock/qcom,mmcc-msmfalcon.h
@@ -14,181 +14,200 @@
#ifndef _DT_BINDINGS_CLK_MSM_MMCC_FALCON_H
#define _DT_BINDINGS_CLK_MSM_MMCC_FALCON_H
-/* Clocks */
-#define MMPLL3_PLL 0
-#define MMPLL4_PLL 1
-#define MMPLL5_PLL 2
-#define MMPLL6_PLL 3
-#define MMPLL7_PLL 4
-#define MMPLL8_PLL 5
-#define AHB_CLK_SRC 6
-#define VIDEO_CORE_CLK_SRC 7
-#define PCLK0_CLK_SRC 8
-#define PCLK1_CLK_SRC 9
-#define MDP_CLK_SRC 10
-#define ROT_CLK_SRC 11
-#define VSYNC_CLK_SRC 12
-#define BYTE0_CLK_SRC 13
-#define BYTE1_CLK_SRC 14
-#define ESC0_CLK_SRC 15
-#define ESC1_CLK_SRC 16
-#define DP_LINK_CLK_SRC 17
-#define DP_CRYPTO_CLK_SRC 18
-#define DP_PIXEL_CLK_SRC 19
-#define DP_AUX_CLK_SRC 20
-#define DP_GTC_CLK_SRC 21
-#define CAMSS_GP0_CLK_SRC 22
-#define CAMSS_GP1_CLK_SRC 23
-#define MCLK0_CLK_SRC 24
-#define MCLK1_CLK_SRC 25
-#define MCLK2_CLK_SRC 26
-#define MCLK3_CLK_SRC 27
-#define CCI_CLK_SRC 28
-#define CSI0PHYTIMER_CLK_SRC 29
-#define CSI1PHYTIMER_CLK_SRC 30
-#define CSI2PHYTIMER_CLK_SRC 31
-#define JPEG0_CLK_SRC 32
-#define VFE0_CLK_SRC 33
-#define VFE1_CLK_SRC 34
-#define CPP_CLK_SRC 35
-#define CSIPHY_CLK_SRC 36
-#define CSI0_CLK_SRC 37
-#define CSI1_CLK_SRC 38
-#define CSI2_CLK_SRC 39
-#define CSI3_CLK_SRC 40
-#define MMSS_CXO_CLK 41
-#define MMSS_SLEEP_CLK 42
-#define MMSS_MNOC_AHB_CLK 43
-#define MMSS_MISC_AHB_CLK 44
-#define MMSS_MISC_CXO_CLK 45
-#define MMSS_BIMC_SMMU_AHB_CLK 46
-#define MMSS_BIMC_SMMU_AXI_CLK 47
-#define MMSS_SNOC_DVM_AXI_CLK 48
-#define MMSS_THROTTLE_CAMSS_CXO_CLK 49
-#define MMSS_THROTTLE_CAMSS_AHB_CLK 50
-#define MMSS_THROTTLE_CAMSS_AXI_CLK 51
-#define MMSS_THROTTLE_MDSS_CXO_CLK 52
-#define MMSS_THROTTLE_MDSS_AHB_CLK 53
-#define MMSS_THROTTLE_MDSS_AXI_CLK 54
-#define MMSS_THROTTLE_VIDEO_CXO_CLK 55
-#define MMSS_THROTTLE_VIDEO_AHB_CLK 56
-#define MMSS_THROTTLE_VIDEO_AXI_CLK 57
-#define MMSS_VIDEO_CORE_CLK 58
-#define MMSS_VIDEO_AXI_CLK 59
-#define MMSS_VIDEO_AHB_CLK 60
-#define MMSS_MDSS_AHB_CLK 61
-#define MMSS_MDSS_HDMI_DP_AHB_CLK 62
-#define MMSS_MDSS_PCLK0_CLK 63
-#define MMSS_MDSS_PCLK1_CLK 64
-#define MMSS_MDSS_VSYNC_CLK 65
-#define MMSS_MDSS_BYTE0_CLK 66
-#define MMSS_MDSS_BYTE0_INTF_CLK 67
-#define MMSS_MDSS_BYTE1_CLK 68
-#define MMSS_MDSS_BYTE1_INTF_CLK 69
-#define MMSS_MDSS_ESC0_CLK 70
-#define MMSS_MDSS_ESC1_CLK 71
-#define MMSS_MDSS_DP_LINK_CLK 72
-#define MMSS_MDSS_DP_LINK_INTF_CLK 73
-#define MMSS_MDSS_DP_CRYPTO_CLK 74
-#define MMSS_MDSS_DP_PIXEL_CLK 75
-#define MMSS_MDSS_DP_AUX_CLK 76
-#define MMSS_MDSS_DP_GTC_CLK 77
-#define MMSS_CAMSS_TOP_AHB_CLK 78
-#define MMSS_CAMSS_AHB_CLK 79
-#define MMSS_CAMSS_GP0_CLK 80
-#define MMSS_CAMSS_GP1_CLK 81
-#define MMSS_CAMSS_MCLK0_CLK 82
-#define MMSS_CAMSS_MCLK1_CLK 83
-#define MMSS_CAMSS_MCLK2_CLK 84
-#define MMSS_CAMSS_MCLK3_CLK 85
-#define MMSS_CAMSS_CCI_CLK 86
-#define MMSS_CAMSS_CCI_AHB_CLK 87
-#define MMSS_CAMSS_CSI0PHYTIMER_CLK 88
-#define MMSS_CAMSS_CSI1PHYTIMER_CLK 89
-#define MMSS_CAMSS_CSI2PHYTIMER_CLK 90
-#define MMSS_CAMSS_JPEG_AHB_CLK 91
-#define MMSS_CAMSS_VFE_VBIF_AHB_CLK 92
-#define MMSS_CAMSS_VFE0_STREAM_CLK 93
-#define MMSS_CAMSS_VFE0_AHB_CLK 94
-#define MMSS_CAMSS_VFE1_STREAM_CLK 95
-#define MMSS_CAMSS_VFE1_AHB_CLK 96
-#define MMSS_CAMSS_CPP_VBIF_AHB_CLK 97
-#define MMSS_CAMSS_CPP_AHB_CLK 98
-#define MMSS_CAMSS_CSIPHY0_CLK 99
-#define MMSS_CAMSS_CSIPHY1_CLK 100
-#define MMSS_CAMSS_CSIPHY2_CLK 101
-#define MMSS_CSIPHY_AHB2CRIF_CLK 102
-#define MMSS_CAMSS_CSI0_CLK 103
-#define MMSS_CAMSS_CPHY_CSID0_CLK 104
-#define MMSS_CAMSS_CSI0_AHB_CLK 105
-#define MMSS_CAMSS_CSI0RDI_CLK 106
-#define MMSS_CAMSS_CSI0PIX_CLK 107
-#define MMSS_CAMSS_CSI1_CLK 108
-#define MMSS_CAMSS_CPHY_CSID1_CLK 109
-#define MMSS_CAMSS_CSI1_AHB_CLK 110
-#define MMSS_CAMSS_CSI1RDI_CLK 111
-#define MMSS_CAMSS_CSI1PIX_CLK 112
-#define MMSS_CAMSS_CSI2_CLK 113
-#define MMSS_CAMSS_CPHY_CSID2_CLK 114
-#define MMSS_CAMSS_CSI2_AHB_CLK 115
-#define MMSS_CAMSS_CSI2RDI_CLK 116
-#define MMSS_CAMSS_CSI2PIX_CLK 117
-#define MMSS_CAMSS_CSI3_CLK 118
-#define MMSS_CAMSS_CPHY_CSID3_CLK 119
-#define MMSS_CAMSS_CSI3_AHB_CLK 120
-#define MMSS_CAMSS_CSI3RDI_CLK 121
-#define MMSS_CAMSS_CSI3PIX_CLK 122
-#define MMSS_CAMSS_ISPIF_AHB_CLK 123
+#define AHB_CLK_SRC 0
+#define BYTE0_CLK_SRC 1
+#define BYTE1_CLK_SRC 2
+#define CAMSS_GP0_CLK_SRC 3
+#define CAMSS_GP1_CLK_SRC 4
+#define CCI_CLK_SRC 5
+#define CPP_CLK_SRC 6
+#define CSI0_CLK_SRC 7
+#define CSI0PHYTIMER_CLK_SRC 8
+#define CSI1_CLK_SRC 9
+#define CSI1PHYTIMER_CLK_SRC 10
+#define CSI2_CLK_SRC 11
+#define CSI2PHYTIMER_CLK_SRC 12
+#define CSI3_CLK_SRC 13
+#define CSIPHY_CLK_SRC 14
+#define DP_AUX_CLK_SRC 15
+#define DP_CRYPTO_CLK_SRC 16
+#define DP_GTC_CLK_SRC 17
+#define DP_LINK_CLK_SRC 18
+#define DP_PIXEL_CLK_SRC 19
+#define ESC0_CLK_SRC 20
+#define ESC1_CLK_SRC 21
+#define JPEG0_CLK_SRC 22
+#define MCLK0_CLK_SRC 23
+#define MCLK1_CLK_SRC 24
+#define MCLK2_CLK_SRC 25
+#define MCLK3_CLK_SRC 26
+#define MDP_CLK_SRC 27
+#define MMPLL0_PLL 28
+#define MMPLL0_PLL_OUT_AUX 29
+#define MMPLL0_PLL_OUT_AUX2 30
+#define MMPLL0_PLL_OUT_EARLY 31
+#define MMPLL0_PLL_OUT_MAIN 32
+#define MMPLL0_PLL_OUT_TEST 33
+#define MMPLL10_PLL 34
+#define MMPLL10_PLL_OUT_AUX 35
+#define MMPLL10_PLL_OUT_AUX2 36
+#define MMPLL10_PLL_OUT_EARLY 37
+#define MMPLL10_PLL_OUT_MAIN 38
+#define MMPLL10_PLL_OUT_TEST 39
+#define MMPLL1_PLL 40
+#define MMPLL1_PLL_OUT_AUX 41
+#define MMPLL1_PLL_OUT_AUX2 42
+#define MMPLL1_PLL_OUT_EARLY 43
+#define MMPLL1_PLL_OUT_MAIN 44
+#define MMPLL1_PLL_OUT_TEST 45
+#define MMPLL3_PLL 46
+#define MMPLL3_PLL_OUT_AUX 47
+#define MMPLL3_PLL_OUT_AUX2 48
+#define MMPLL3_PLL_OUT_EARLY 49
+#define MMPLL3_PLL_OUT_MAIN 50
+#define MMPLL3_PLL_OUT_TEST 51
+#define MMPLL4_PLL 52
+#define MMPLL4_PLL_OUT_AUX 53
+#define MMPLL4_PLL_OUT_AUX2 54
+#define MMPLL4_PLL_OUT_EARLY 55
+#define MMPLL4_PLL_OUT_MAIN 56
+#define MMPLL4_PLL_OUT_TEST 57
+#define MMPLL5_PLL 58
+#define MMPLL5_PLL_OUT_AUX 59
+#define MMPLL5_PLL_OUT_AUX2 60
+#define MMPLL5_PLL_OUT_EARLY 61
+#define MMPLL5_PLL_OUT_MAIN 62
+#define MMPLL5_PLL_OUT_TEST 63
+#define MMPLL6_PLL 64
+#define MMPLL6_PLL_OUT_AUX 65
+#define MMPLL6_PLL_OUT_AUX2 66
+#define MMPLL6_PLL_OUT_EARLY 67
+#define MMPLL6_PLL_OUT_MAIN 68
+#define MMPLL6_PLL_OUT_TEST 69
+#define MMPLL7_PLL 70
+#define MMPLL7_PLL_OUT_AUX 71
+#define MMPLL7_PLL_OUT_AUX2 72
+#define MMPLL7_PLL_OUT_EARLY 73
+#define MMPLL7_PLL_OUT_MAIN 74
+#define MMPLL7_PLL_OUT_TEST 75
+#define MMPLL8_PLL 76
+#define MMPLL8_PLL_OUT_AUX 77
+#define MMPLL8_PLL_OUT_AUX2 78
+#define MMPLL8_PLL_OUT_EARLY 79
+#define MMPLL8_PLL_OUT_MAIN 80
+#define MMPLL8_PLL_OUT_TEST 81
+#define MMSS_BIMC_SMMU_AHB_CLK 82
+#define MMSS_BIMC_SMMU_AXI_CLK 83
+#define MMSS_CAMSS_AHB_CLK 84
+#define MMSS_CAMSS_CCI_AHB_CLK 85
+#define MMSS_CAMSS_CCI_CLK 86
+#define MMSS_CAMSS_CPHY_CSID0_CLK 87
+#define MMSS_CAMSS_CPHY_CSID1_CLK 88
+#define MMSS_CAMSS_CPHY_CSID2_CLK 89
+#define MMSS_CAMSS_CPHY_CSID3_CLK 90
+#define MMSS_CAMSS_CPP_AHB_CLK 91
+#define MMSS_CAMSS_CPP_AXI_CLK 92
+#define MMSS_CAMSS_CPP_CLK 93
+#define MMSS_CAMSS_CPP_VBIF_AHB_CLK 94
+#define MMSS_CAMSS_CSI0_AHB_CLK 95
+#define MMSS_CAMSS_CSI0_CLK 96
+#define MMSS_CAMSS_CSI0PHYTIMER_CLK 97
+#define MMSS_CAMSS_CSI0PIX_CLK 98
+#define MMSS_CAMSS_CSI0RDI_CLK 99
+#define MMSS_CAMSS_CSI1_AHB_CLK 100
+#define MMSS_CAMSS_CSI1_CLK 101
+#define MMSS_CAMSS_CSI1PHYTIMER_CLK 102
+#define MMSS_CAMSS_CSI1PIX_CLK 103
+#define MMSS_CAMSS_CSI1RDI_CLK 104
+#define MMSS_CAMSS_CSI2_AHB_CLK 105
+#define MMSS_CAMSS_CSI2_CLK 106
+#define MMSS_CAMSS_CSI2PHYTIMER_CLK 107
+#define MMSS_CAMSS_CSI2PIX_CLK 108
+#define MMSS_CAMSS_CSI2RDI_CLK 109
+#define MMSS_CAMSS_CSI3_AHB_CLK 110
+#define MMSS_CAMSS_CSI3_CLK 111
+#define MMSS_CAMSS_CSI3PIX_CLK 112
+#define MMSS_CAMSS_CSI3RDI_CLK 113
+#define MMSS_CAMSS_CSI_VFE0_CLK 114
+#define MMSS_CAMSS_CSI_VFE1_CLK 115
+#define MMSS_CAMSS_CSIPHY0_CLK 116
+#define MMSS_CAMSS_CSIPHY1_CLK 117
+#define MMSS_CAMSS_CSIPHY2_CLK 118
+#define MMSS_CAMSS_GP0_CLK 119
+#define MMSS_CAMSS_GP1_CLK 120
+#define MMSS_CAMSS_ISPIF_AHB_CLK 121
+#define MMSS_CAMSS_JPEG0_CLK 122
+#define MMSS_CAMSS_JPEG_AHB_CLK 123
+#define MMSS_CAMSS_JPEG_AXI_CLK 124
+#define MMSS_CAMSS_MCLK0_CLK 125
+#define MMSS_CAMSS_MCLK1_CLK 126
+#define MMSS_CAMSS_MCLK2_CLK 127
+#define MMSS_CAMSS_MCLK3_CLK 128
+#define MMSS_CAMSS_MICRO_AHB_CLK 129
+#define MMSS_CAMSS_TOP_AHB_CLK 130
+#define MMSS_CAMSS_VFE0_AHB_CLK 131
+#define MMSS_CAMSS_VFE0_CLK 132
+#define MMSS_CAMSS_VFE0_STREAM_CLK 133
+#define MMSS_CAMSS_VFE1_AHB_CLK 134
+#define MMSS_CAMSS_VFE1_CLK 135
+#define MMSS_CAMSS_VFE1_STREAM_CLK 136
+#define MMSS_CAMSS_VFE_VBIF_AHB_CLK 137
+#define MMSS_CAMSS_VFE_VBIF_AXI_CLK 138
+#define MMSS_CSIPHY_AHB2CRIF_CLK 139
+#define MMSS_CXO_CLK 140
+#define MMSS_MDSS_AHB_CLK 141
+#define MMSS_MDSS_AXI_CLK 142
+#define MMSS_MDSS_BYTE0_CLK 143
+#define MMSS_MDSS_BYTE0_INTF_CLK 144
+#define MMSS_MDSS_BYTE1_CLK 145
+#define MMSS_MDSS_BYTE1_INTF_CLK 146
+#define MMSS_MDSS_DP_AUX_CLK 147
+#define MMSS_MDSS_DP_CRYPTO_CLK 148
+#define MMSS_MDSS_DP_GTC_CLK 149
+#define MMSS_MDSS_DP_LINK_CLK 150
+#define MMSS_MDSS_DP_LINK_INTF_CLK 151
+#define MMSS_MDSS_DP_PIXEL_CLK 152
+#define MMSS_MDSS_ESC0_CLK 153
+#define MMSS_MDSS_ESC1_CLK 154
+#define MMSS_MDSS_HDMI_DP_AHB_CLK 155
+#define MMSS_MDSS_MDP_CLK 156
+#define MMSS_MDSS_PCLK0_CLK 157
+#define MMSS_MDSS_PCLK1_CLK 158
+#define MMSS_MDSS_ROT_CLK 159
+#define MMSS_MDSS_VSYNC_CLK 160
+#define MMSS_MISC_AHB_CLK 161
+#define MMSS_MISC_CXO_CLK 162
+#define MMSS_MNOC_AHB_CLK 163
+#define MMSS_SNOC_DVM_AXI_CLK 164
+#define MMSS_THROTTLE_CAMSS_AHB_CLK 165
+#define MMSS_THROTTLE_CAMSS_AXI_CLK 166
+#define MMSS_THROTTLE_CAMSS_CXO_CLK 167
+#define MMSS_THROTTLE_MDSS_AHB_CLK 168
+#define MMSS_THROTTLE_MDSS_AXI_CLK 169
+#define MMSS_THROTTLE_MDSS_CXO_CLK 170
+#define MMSS_THROTTLE_VIDEO_AHB_CLK 171
+#define MMSS_THROTTLE_VIDEO_AXI_CLK 172
+#define MMSS_THROTTLE_VIDEO_CXO_CLK 173
+#define MMSS_VIDEO_AHB_CLK 174
+#define MMSS_VIDEO_AXI_CLK 175
+#define MMSS_VIDEO_CORE_CLK 176
+#define MMSS_VIDEO_SUBCORE0_CLK 177
+#define PCLK0_CLK_SRC 178
+#define PCLK1_CLK_SRC 179
+#define ROT_CLK_SRC 180
+#define VFE0_CLK_SRC 181
+#define VFE1_CLK_SRC 182
+#define VIDEO_CORE_CLK_SRC 183
+#define VSYNC_CLK_SRC 184
-/* Block Resets */
-#define MMSS_MNOCAHB_BCR 0
-#define MMSS_MISC_BCR 1
-#define MMSS_BTO_BCR 2
-#define MMSS_MNOCAXI_BCR 3
-#define MMSS_BIMC_SMMU_BCR 4
-#define MMSS_THROTTLE_CAMSS_BCR 5
-#define MMSS_THROTTLE_MDSS_BCR 6
-#define MMSS_THROTTLE_VIDEO_BCR 7
-#define MMSS_VIDEO_TOP_BCR 8
-#define MMSS_MDSS_BCR 9
-#define MMSS_CAMSS_TOP_BCR 10
-#define MMSS_CAMSS_AHB_BCR 11
-#define MMSS_CAMSS_MICRO_BCR 12
-#define MMSS_CAMSS_CCI_BCR 13
-#define MMSS_CAMSS_PHY0_BCR 14
-#define MMSS_CAMSS_PHY1_BCR 15
-#define MMSS_CAMSS_PHY2_BCR 16
-#define MMSS_CAMSS_JPEG_BCR 17
-#define MMSS_CAMSS_VFE_VBIF_BCR 18
-#define MMSS_CAMSS_VFE0_BCR 19
-#define MMSS_CAMSS_VFE1_BCR 20
-#define MMSS_CAMSS_CSI_VFE0_BCR 21
-#define MMSS_CAMSS_CSI_VFE1_BCR 22
-#define MMSS_CAMSS_CPP_TOP_BCR 23
-#define MMSS_CAMSS_CPP_BCR 24
-#define MMSS_CAMSS_CSIPHY_BCR 25
-#define MMSS_CAMSS_CSI0_BCR 26
-#define MMSS_CAMSS_CSI0RDI_BCR 27
-#define MMSS_CAMSS_CSI0PIX_BCR 28
-#define MMSS_CAMSS_CSI1_BCR 29
-#define MMSS_CAMSS_CSI1RDI_BCR 30
-#define MMSS_CAMSS_CSI1PIX_BCR 31
-#define MMSS_CAMSS_CSI2_BCR 32
-#define MMSS_CAMSS_CSI2RDI_BCR 33
-#define MMSS_CAMSS_CSI2PIX_BCR 34
-#define MMSS_CAMSS_CSI3_BCR 35
-#define MMSS_CAMSS_CSI3RDI_BCR 36
-#define MMSS_CAMSS_CSI3PIX_BCR 37
-#define MMSS_CAMSS_ISPIF_BCR 38
+#define BIMC_SMMU_GDSC 0
+#define CAMSS_CPP_GDSC 1
+#define CAMSS_TOP_GDSC 2
+#define CAMSS_VFE0_GDSC 3
+#define CAMSS_VFE1_GDSC 4
+#define MDSS_GDSC 5
+#define VIDEO_SUBCORE0_GDSC 6
+#define VIDEO_TOP_GDSC 7
-/* GDSC */
-#define VIDEO_TOP_GDSC 0
-#define VIDEO_SUBCORE0_GDSC 1
-#define CAMSS_VFE0_GDSC 2
-#define BIMC_SMMU_GDSC 3
-#define CAMSS_TOP_GDSC 4
-#define MDSS_GDSC 5
-#define CAMSS_CPP_GDSC 6
-#define CAMSS_VFE1_GDSC 7
#endif
diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h
index a9577b62cb07..08ccbc9bd71c 100644
--- a/include/linux/input/ft5x06_ts.h
+++ b/include/linux/input/ft5x06_ts.h
@@ -3,7 +3,7 @@
* FocalTech ft5x06 TouchScreen driver header file.
*
* Copyright (c) 2010 Focal tech Ltd.
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -18,12 +18,28 @@
#ifndef __LINUX_FT5X06_TS_H__
#define __LINUX_FT5X06_TS_H__
+#define FT5X06_ID 0x55
+#define FT5X16_ID 0x0A
+#define FT5X36_ID 0x14
+#define FT6X06_ID 0x06
+
struct ft5x06_ts_platform_data {
- unsigned long irqflags;
- u32 x_max;
- u32 y_max;
+ u32 irqflags;
u32 irq_gpio;
+ u32 irq_gpio_flags;
u32 reset_gpio;
+ u32 reset_gpio_flags;
+ u32 family_id;
+ u32 x_max;
+ u32 y_max;
+ u32 x_min;
+ u32 y_min;
+ u32 panel_minx;
+ u32 panel_miny;
+ u32 panel_maxx;
+ u32 panel_maxy;
+ bool no_force_update;
+ bool i2c_pull_up;
int (*power_init)(bool);
int (*power_on)(bool);
};
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index 52277f26b5a4..7bf2bff2f173 100755
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -189,6 +189,7 @@ struct wcd9xxx_pdata {
u32 mclk_rate;
u32 dmic_sample_rate;
u32 mad_dmic_sample_rate;
+ u32 ecpp_dmic_sample_rate;
u32 dmic_clk_drv;
u16 use_pinctrl;
};
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 7d1e374e176c..56e78254286e 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -174,9 +174,9 @@ enum power_supply_property {
/* Local extensions */
POWER_SUPPLY_PROP_USB_HC,
POWER_SUPPLY_PROP_USB_OTG,
- POWER_SUPPLY_PROP_CHARGE_ENABLED,
POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED,
POWER_SUPPLY_PROP_CHARGING_ENABLED,
+ POWER_SUPPLY_PROP_PIN_ENABLED,
POWER_SUPPLY_PROP_INPUT_SUSPEND,
POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
diff --git a/include/soc/qcom/irq-helper.h b/include/soc/qcom/irq-helper.h
new file mode 100644
index 000000000000..d992fb6f470a
--- /dev/null
+++ b/include/soc/qcom/irq-helper.h
@@ -0,0 +1,20 @@
+/* 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.
+ */
+
+#ifndef __SOC_QCOM_IRQ_HELPER_H
+#define __SOC_QCOM_IRQ_HELPER_H
+
+int irq_blacklist_on(void);
+int irq_blacklist_off(void);
+
+#endif
+
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 8d9016e3557c..3464726c408a 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -2738,6 +2738,333 @@ struct afe_param_id_set_topology_cfg {
u32 topology_id;
} __packed;
+
+/*
+ * Generic encoder module ID.
+ * This module supports the following parameter IDs:
+ * #AVS_ENCODER_PARAM_ID_ENC_FMT_ID (cannot be set run time)
+ * #AVS_ENCODER_PARAM_ID_ENC_CFG_BLK (may be set run time)
+ * #AVS_ENCODER_PARAM_ID_ENC_BITRATE (may be set run time)
+ * #AVS_ENCODER_PARAM_ID_PACKETIZER_ID (cannot be set run time)
+ * Opcode - AVS_MODULE_ID_ENCODER
+ * AFE Command AFE_PORT_CMD_SET_PARAM_V2 supports this module ID.
+ */
+#define AFE_MODULE_ID_ENCODER 0x00013229
+
+/* Macro for defining the packetizer ID: COP. */
+#define AFE_MODULE_ID_PACKETIZER_COP 0x0001322A
+
+/*
+ * Packetizer type parameter for the #AVS_MODULE_ID_ENCODER module.
+ * This parameter cannot be set runtime.
+ */
+#define AFE_ENCODER_PARAM_ID_PACKETIZER_ID 0x0001322E
+
+/*
+ * Encoder config block parameter for the #AVS_MODULE_ID_ENCODER module.
+ * This parameter may be set runtime.
+ */
+#define AFE_ENCODER_PARAM_ID_ENC_CFG_BLK 0x0001322C
+
+/*
+ * Encoder format ID parameter for the #AVS_MODULE_ID_ENCODER module.
+ * This parameter cannot be set runtime.
+ */
+#define AFE_ENCODER_PARAM_ID_ENC_FMT_ID 0x0001322B
+
+/*
+ * Data format to send compressed data
+ * is transmitted/received over Slimbus lines.
+ */
+#define AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED 0x3
+
+/*
+ * ID for AFE port module. This will be used to define port properties.
+ * This module supports following parameter IDs:
+ * #AFE_PARAM_ID_PORT_MEDIA_TYPE
+ * To configure the port property, the client must use the
+ * #AFE_PORT_CMD_SET_PARAM_V2 command,
+ * and fill the module ID with the respective parameter IDs as listed above.
+ * @apr_hdr_fields
+ * Opcode -- AFE_MODULE_PORT
+ */
+#define AFE_MODULE_PORT 0x000102a6
+
+/*
+ * ID of the parameter used by #AFE_MODULE_PORT to set the port media type.
+ * parameter ID is currently supported using#AFE_PORT_CMD_SET_PARAM_V2 command.
+ */
+#define AFE_PARAM_ID_PORT_MEDIA_TYPE 0x000102a7
+
+/*
+ * Macros for defining the "data_format" field in the
+ * #AFE_PARAM_ID_PORT_MEDIA_TYPE
+ */
+#define AFE_PORT_DATA_FORMAT_PCM 0x0
+#define AFE_PORT_DATA_FORMAT_GENERIC_COMPRESSED 0x1
+
+/*
+ * Macro for defining the "minor_version" field in the
+ * #AFE_PARAM_ID_PORT_MEDIA_TYPE
+ */
+#define AFE_API_VERSION_PORT_MEDIA_TYPE 0x1
+
+#define ASM_MEDIA_FMT_NONE 0x0
+
+/*
+ * Media format ID for SBC encode configuration.
+ * @par SBC encode configuration (asm_sbc_enc_cfg_t)
+ * @table{weak__asm__sbc__enc__cfg__t}
+ */
+#define ASM_MEDIA_FMT_SBC 0x00010BF2
+
+/* SBC channel Mono mode.*/
+#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_MONO 1
+
+/* SBC channel Stereo mode. */
+#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_STEREO 2
+
+/* SBC channel Dual Mono mode. */
+#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO 8
+
+/* SBC channel Joint Stereo mode. */
+#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO 9
+
+/* SBC bit allocation method = loudness. */
+#define ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS 0
+
+/* SBC bit allocation method = SNR. */
+#define ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR 1
+
+
+/*
+ * Payload of the SBC encoder configuration parameters in the
+ * #ASM_MEDIA_FMT_SBC media format.
+ */
+struct asm_sbc_enc_cfg_t {
+ /*
+ * Number of subbands.
+ * @values 4, 8
+ */
+ uint32_t num_subbands;
+
+ /*
+ * Size of the encoded block in samples.
+ * @values 4, 8, 12, 16
+ */
+ uint32_t blk_len;
+
+ /*
+ * Mode used to allocate bits between channels.
+ * @values
+ * 0 (Native mode)
+ * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_MONO
+ * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_STEREO
+ * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO
+ * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO
+ * Native mode indicates that encoding must be performed with the number
+ * of channels at the input.
+ * If postprocessing outputs one-channel data, Mono mode is used. If
+ * postprocessing outputs two-channel data, Stereo mode is used.
+ * The number of channels must not change during encoding.
+ */
+ uint32_t channel_mode;
+
+ /*
+ * Encoder bit allocation method.
+ * @values
+ * #ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS
+ * #ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR @tablebulletend
+ */
+ uint32_t alloc_method;
+
+ /*
+ * Number of encoded bits per second.
+ * @values
+ * Mono channel -- Maximum of 320 kbps
+ * Stereo channel -- Maximum of 512 kbps @tablebulletend
+ */
+ uint32_t bit_rate;
+
+ /*
+ * Number of samples per second.
+ * @values 0 (Native mode), 16000, 32000, 44100, 48000&nbsp;Hz
+ * Native mode indicates that encoding must be performed with the
+ * sampling rate at the input.
+ * The sampling rate must not change during encoding.
+ */
+ uint32_t sample_rate;
+};
+
+#define ASM_MEDIA_FMT_AAC_AOT_LC 2
+#define ASM_MEDIA_FMT_AAC_AOT_SBR 5
+#define ASM_MEDIA_FMT_AAC_AOT_PS 29
+#define ASM_MEDIA_FMT_AAC_FORMAT_FLAG_ADTS 0
+#define ASM_MEDIA_FMT_AAC_FORMAT_FLAG_RAW 3
+
+struct asm_aac_enc_cfg_v2_t {
+
+ /* Encoding rate in bits per second.*/
+ uint32_t bit_rate;
+
+ /*
+ * Encoding mode.
+ * Supported values:
+ * #ASM_MEDIA_FMT_AAC_AOT_LC
+ * #ASM_MEDIA_FMT_AAC_AOT_SBR
+ * #ASM_MEDIA_FMT_AAC_AOT_PS
+ */
+ uint32_t enc_mode;
+
+ /*
+ * AAC format flag.
+ * Supported values:
+ * #ASM_MEDIA_FMT_AAC_FORMAT_FLAG_ADTS
+ * #ASM_MEDIA_FMT_AAC_FORMAT_FLAG_RAW
+ */
+ uint16_t aac_fmt_flag;
+
+ /*
+ * Number of channels to encode.
+ * Supported values:
+ * 0 - Native mode
+ * 1 - Mono
+ * 2 - Stereo
+ * Other values are not supported.
+ * @note1hang The eAAC+ encoder mode supports only stereo.
+ * Native mode indicates that encoding must be performed with the
+ * number of channels at the input.
+ * The number of channels must not change during encoding.
+ */
+ uint32_t channel_cfg;
+
+ /*
+ * Number of samples per second.
+ * Supported values: - 0 -- Native mode - For other values,
+ * Native mode indicates that encoding must be performed with the
+ * sampling rate at the input.
+ * The sampling rate must not change during encoding.
+ */
+ uint32_t sample_rate;
+} __packed;
+
+/* FMT ID for apt-X Classic */
+#define ASM_MEDIA_FMT_APTX 0x000131ff
+
+/* FMT ID for apt-X HD */
+#define ASM_MEDIA_FMT_APTX_HD 0x00013200
+
+#define PCM_CHANNEL_L 1
+#define PCM_CHANNEL_R 2
+#define PCM_CHANNEL_C 3
+
+struct asm_custom_enc_cfg_aptx_t {
+ uint32_t sample_rate;
+ /* Mono or stereo */
+ uint16_t num_channels;
+ uint16_t reserved;
+ /* num_ch == 1, then PCM_CHANNEL_C,
+ * num_ch == 2, then {PCM_CHANNEL_L, PCM_CHANNEL_R}
+ */
+ uint8_t channel_mapping[8];
+ uint32_t custom_size;
+} __packed;
+
+struct afe_enc_fmt_id_param_t {
+ /*
+ * Supported values:
+ * #ASM_MEDIA_FMT_SBC
+ * #ASM_MEDIA_FMT_AAC_V2
+ * Any OpenDSP supported values
+ */
+ uint32_t fmt_id;
+} __packed;
+
+struct afe_port_media_type_t {
+ /*
+ * Minor version
+ * @values #AFE_API_VERSION_PORT_MEDIA_TYPE.
+ */
+ uint32_t minor_version;
+
+ /*
+ * Sampling rate of the port.
+ * @values
+ * #AFE_PORT_SAMPLE_RATE_8K
+ * #AFE_PORT_SAMPLE_RATE_11_025K
+ * #AFE_PORT_SAMPLE_RATE_12K
+ * #AFE_PORT_SAMPLE_RATE_16K
+ * #AFE_PORT_SAMPLE_RATE_22_05K
+ * #AFE_PORT_SAMPLE_RATE_24K
+ * #AFE_PORT_SAMPLE_RATE_32K
+ * #AFE_PORT_SAMPLE_RATE_44_1K
+ * #AFE_PORT_SAMPLE_RATE_48K
+ * #AFE_PORT_SAMPLE_RATE_88_2K
+ * #AFE_PORT_SAMPLE_RATE_96K
+ * #AFE_PORT_SAMPLE_RATE_176_4K
+ * #AFE_PORT_SAMPLE_RATE_192K
+ * #AFE_PORT_SAMPLE_RATE_352_8K
+ * #AFE_PORT_SAMPLE_RATE_384K
+ */
+ uint32_t sample_rate;
+
+ /*
+ * Bit width of the sample.
+ * @values 16, 24
+ */
+ uint16_t bit_width;
+
+ /*
+ * Number of channels.
+ * @values 1 to #AFE_PORT_MAX_AUDIO_CHAN_CNT
+ */
+ uint16_t num_channels;
+
+ /*
+ * Data format supported by this port.
+ * If the port media type and device media type are different,
+ * it signifies a encoding/decoding use case
+ * @values
+ * #AFE_PORT_DATA_FORMAT_PCM
+ * #AFE_PORT_DATA_FORMAT_GENERIC_COMPRESSED
+ */
+ uint16_t data_format;
+
+ /*This field must be set to zero.*/
+ uint16_t reserved;
+} __packed;
+
+union afe_enc_config_data {
+ struct asm_sbc_enc_cfg_t sbc_config;
+ struct asm_aac_enc_cfg_v2_t aac_config;
+ struct asm_custom_enc_cfg_aptx_t aptx_config;
+};
+
+struct afe_enc_config {
+ u32 format;
+ union afe_enc_config_data data;
+};
+
+struct afe_enc_cfg_blk_param_t {
+ uint32_t enc_cfg_blk_size;
+ /*
+ *Size of the encoder configuration block that follows this member
+ */
+ union afe_enc_config_data enc_blk_config;
+};
+
+/*
+ * Payload of the AVS_ENCODER_PARAM_ID_PACKETIZER_ID parameter.
+ */
+struct avs_enc_packetizer_id_param_t {
+ /*
+ * Supported values:
+ * #AVS_MODULE_ID_PACKETIZER_COP
+ * Any OpenDSP supported values
+ */
+ uint32_t enc_packetizer_id;
+};
+
union afe_port_config {
struct afe_param_id_pcm_cfg pcm;
struct afe_param_id_i2s_cfg i2s;
@@ -2751,6 +3078,10 @@ union afe_port_config {
struct afe_param_id_set_topology_cfg topology;
struct afe_param_id_tdm_cfg tdm;
struct afe_param_id_usb_audio_cfg usb_audio;
+ struct afe_enc_fmt_id_param_t enc_fmt;
+ struct afe_port_media_type_t media_type;
+ struct afe_enc_cfg_blk_param_t enc_blk_param;
+ struct avs_enc_packetizer_id_param_t enc_pkt_id_param;
} __packed;
struct afe_audioif_config_command_no_payload {
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 5cd65357dd95..6be903a4c8d0 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -274,6 +274,9 @@ int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode);
int afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate);
+int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
+ u32 rate, u16 afe_in_channels,
+ struct afe_enc_config *enc_config);
int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
int l_ch, int r_ch, u32 enable);
int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib);
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 2cf0469712b6..643c68f4c449 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -815,6 +815,12 @@ enum v4l2_mpeg_vidc_extradata {
#define V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO \
V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO
V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO = 28,
+#define V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY \
+ V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY
+ V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY = 29,
+#define V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE \
+ V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE
+ V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE = 30,
};
#define V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL (V4L2_CID_MPEG_MSM_VIDC_BASE + 26)
@@ -1176,6 +1182,23 @@ enum v4l2_mpeg_vidc_video_h264_transform_8x8 {
V4L2_MPEG_VIDC_VIDEO_H264_TRANSFORM_8x8_ENABLE = 1,
};
+#define V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 94)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 95)
+
+enum v4l2_cid_mpeg_vidc_video_full_range {
+ V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_DISABLE = 0,
+ V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE_ENABLE = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 96)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 97)
+
/* Camera class control IDs */
#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900)
diff --git a/include/uapi/media/msm_vidc.h b/include/uapi/media/msm_vidc.h
index 45cc81aaaf17..b259bdef8a93 100644
--- a/include/uapi/media/msm_vidc.h
+++ b/include/uapi/media/msm_vidc.h
@@ -55,6 +55,18 @@ struct msm_vidc_mpeg2_seqdisp_payload {
unsigned int disp_height;
};
+struct msm_vidc_vc1_seqdisp_payload {
+ unsigned int prog_seg_format;
+ unsigned int uv_sampl_fmt;
+ unsigned int color_format;
+ unsigned int color_primaries;
+ unsigned int transfer_char;
+ unsigned int matrix_coeffs;
+ unsigned int aspect_ratio;
+ unsigned int aspect_horiz;
+ unsigned int aspect_vert;
+};
+
struct msm_vidc_input_crop_payload {
unsigned int size;
unsigned int version;
@@ -154,6 +166,13 @@ struct msm_vidc_yuv_stats_payload {
unsigned int frame_difference;
};
+struct msm_vidc_vpx_colorspace_payload {
+ unsigned int color_space;
+ unsigned int yuv_range_flag;
+ unsigned int sumsampling_x;
+ unsigned int sumsampling_y;
+};
+
struct msm_vidc_roi_qp_payload {
int upper_qp_offset;
int lower_qp_offset;
@@ -176,6 +195,23 @@ struct msm_vidc_content_light_level_sei_payload {
unsigned int nMaxPicAverageLight;
};
+struct msm_vidc_vui_display_info_payload {
+ unsigned int video_signal_present_flag;
+ unsigned int video_format;
+ unsigned int bit_depth_y;
+ unsigned int bit_depth_c;
+ unsigned int video_full_range_flag;
+ unsigned int color_description_present_flag;
+ unsigned int color_primaries;
+ unsigned int transfer_characteristics;
+ unsigned int matrix_coefficients;
+ unsigned int chroma_location_info_present_flag;
+ unsigned int chroma_format_idc;
+ unsigned int separate_color_plane_flag;
+ unsigned int chroma_sample_loc_type_top_field;
+ unsigned int chroma_sample_loc_type_bottom_field;
+};
+
enum msm_vidc_extradata_type {
MSM_VIDC_EXTRADATA_NONE = 0x00000000,
MSM_VIDC_EXTRADATA_MB_QUANTIZATION = 0x00000001,
@@ -207,6 +243,9 @@ enum msm_vidc_extradata_type {
MSM_VIDC_EXTRADATA_OUTPUT_CROP
MSM_VIDC_EXTRADATA_OUTPUT_CROP = 0x0700000F,
MSM_VIDC_EXTRADATA_DIGITAL_ZOOM = 0x07000010,
+#define MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO \
+ MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO
+ MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO = 0x070000011,
MSM_VIDC_EXTRADATA_MULTISLICE_INFO = 0x7F100000,
MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
MSM_VIDC_EXTRADATA_INDEX = 0x7F100002,
@@ -214,6 +253,9 @@ enum msm_vidc_extradata_type {
MSM_VIDC_EXTRADATA_METADATA_LTR = 0x7F100004,
MSM_VIDC_EXTRADATA_METADATA_FILLER = 0x7FE00002,
MSM_VIDC_EXTRADATA_METADATA_MBI = 0x7F100005,
+#define MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO \
+ MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO
+ MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO = 0x7F100006,
MSM_VIDC_EXTRADATA_YUVSTATS_INFO = 0x7F100007,
};
enum msm_vidc_interlace_type {
@@ -243,12 +285,90 @@ enum msm_vidc_userdata_type {
MSM_VIDC_USERDATA_TYPE_BOTTOM_FIELD = 0x3,
};
+/* See colour_primaries of ISO/IEC 14496 for significance */
+enum msm_vidc_h264_color_primaries_values {
+ MSM_VIDC_RESERVED_1 = 0,
+ MSM_VIDC_BT709_5 = 1,
+ MSM_VIDC_UNSPECIFIED = 2,
+ MSM_VIDC_RESERVED_2 = 3,
+ MSM_VIDC_BT470_6_M = 4,
+ MSM_VIDC_BT601_6_625 = 5,
+ MSM_VIDC_BT470_6_BG = MSM_VIDC_BT601_6_625,
+ MSM_VIDC_BT601_6_525 = 6,
+ MSM_VIDC_SMPTE_240M = 7,
+ MSM_VIDC_GENERIC_FILM = 8,
+ MSM_VIDC_BT2020 = 9,
+};
+
+enum msm_vidc_vp9_color_primaries_values {
+ MSM_VIDC_CS_UNKNOWN,
+ MSM_VIDC_CS_BT_601,
+ MSM_VIDC_CS_BT_709,
+ MSM_VIDC_CS_SMPTE_170,
+ MSM_VIDC_CS_SMPTE_240,
+ MSM_VIDC_CS_BT_2020,
+ MSM_VIDC_CS_RESERVED,
+ MSM_VIDC_CS_RGB,
+};
+
+enum msm_vidc_h264_matrix_coeff_values {
+ MSM_VIDC_MATRIX_RGB = 0,
+ MSM_VIDC_MATRIX_BT_709_5 = 1,
+ MSM_VIDC_MATRIX_UNSPECIFIED = 2,
+ MSM_VIDC_MATRIX_RESERVED = 3,
+ MSM_VIDC_MATRIX_FCC_47 = 4,
+ MSM_VIDC_MATRIX_601_6_625 = 5,
+ MSM_VIDC_MATRIX_BT470_BG = MSM_VIDC_MATRIX_601_6_625,
+ MSM_VIDC_MATRIX_601_6_525 = 6,
+ MSM_VIDC_MATRIX_SMPTE_170M = MSM_VIDC_MATRIX_601_6_525,
+ MSM_VIDC_MATRIX_SMPTE_240M = 7,
+ MSM_VIDC_MATRIX_Y_CG_CO = 8,
+ MSM_VIDC_MATRIX_BT_2020 = 9,
+ MSM_VIDC_MATRIX_BT_2020_CONST = 10,
+};
+
+enum msm_vidc_h264_transfer_chars_values {
+ MSM_VIDC_TRANSFER_RESERVED_1 = 0,
+ MSM_VIDC_TRANSFER_BT709_5 = 1,
+ MSM_VIDC_TRANSFER_UNSPECIFIED = 2,
+ MSM_VIDC_TRANSFER_RESERVED_2 = 3,
+ MSM_VIDC_TRANSFER_BT_470_6_M = 4,
+ MSM_VIDC_TRANSFER_BT_470_6_BG = 5,
+ MSM_VIDC_TRANSFER_601_6_625 = 6,
+ MSM_VIDC_TRANSFER_601_6_525 = MSM_VIDC_TRANSFER_601_6_625,
+ MSM_VIDC_TRANSFER_SMPTE_240M = 7,
+ MSM_VIDC_TRANSFER_LINEAR = 8,
+ MSM_VIDC_TRANSFER_LOG_100_1 = 9,
+ MSM_VIDC_TRANSFER_LOG_100_SQRT10_1 = 10,
+ MSM_VIDC_TRANSFER_IEC_61966 = 11,
+ MSM_VIDC_TRANSFER_BT_1361 = 12,
+ MSM_VIDC_TRANSFER_SRGB = 13,
+ MSM_VIDC_TRANSFER_BT_2020_10 = 14,
+ MSM_VIDC_TRANSFER_BT_2020_12 = 15,
+};
+
enum msm_vidc_pixel_depth {
MSM_VIDC_BIT_DEPTH_8,
MSM_VIDC_BIT_DEPTH_10,
MSM_VIDC_BIT_DEPTH_UNSUPPORTED = 0XFFFFFFFF,
};
+enum msm_vidc_video_format {
+ MSM_VIDC_COMPONENT,
+ MSM_VIDC_PAL,
+ MSM_VIDC_NTSC,
+ MSM_VIDC_SECAM,
+ MSM_VIDC_MAC,
+ MSM_VIDC_UNSPECIFIED_FORMAT,
+ MSM_VIDC_RESERVED_1_FORMAT,
+ MSM_VIDC_RESERVED_2_FORMAT,
+};
+
+enum msm_vidc_color_desc_flag {
+ MSM_VIDC_COLOR_DESC_NOT_PRESENT,
+ MSM_VIDC_COLOR_DESC_PRESENT,
+};
+
/*enum msm_vidc_pic_struct */
#define MSM_VIDC_PIC_STRUCT_MAYBE_INTERLACED 0x0
#define MSM_VIDC_PIC_STRUCT_PROGRESSIVE 0x1
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 37731292f8a1..1cfd381642da 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -365,21 +365,6 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
goto out_release;
}
- /*
- * By now we've cleared cpu_active_mask, wait for all preempt-disabled
- * and RCU users of this state to go away such that all new such users
- * will observe it.
- *
- * For CONFIG_PREEMPT we have preemptible RCU and its sync_rcu() might
- * not imply sync_sched(), so wait for both.
- *
- * Do sync before park smpboot threads to take care the rcu boost case.
- */
- if (IS_ENABLED(CONFIG_PREEMPT))
- synchronize_rcu_mult(call_rcu, call_rcu_sched);
- else
- synchronize_rcu();
-
smpboot_park_threads(cpu);
/*
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 2ade632197d5..2df78d45a096 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2075,12 +2075,30 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
mutex_unlock(&cpuset_mutex);
}
+static int cpuset_allow_attach(struct cgroup_taskset *tset)
+{
+ const struct cred *cred = current_cred(), *tcred;
+ struct task_struct *task;
+ struct cgroup_subsys_state *css;
+
+ cgroup_taskset_for_each(task, css, tset) {
+ tcred = __task_cred(task);
+
+ if ((current != task) && !capable(CAP_SYS_ADMIN) &&
+ cred->euid.val != tcred->uid.val && cred->euid.val != tcred->suid.val)
+ return -EACCES;
+ }
+
+ return 0;
+}
+
struct cgroup_subsys cpuset_cgrp_subsys = {
.css_alloc = cpuset_css_alloc,
.css_online = cpuset_css_online,
.css_offline = cpuset_css_offline,
.css_free = cpuset_css_free,
.can_attach = cpuset_can_attach,
+ .allow_attach = cpuset_allow_attach,
.cancel_attach = cpuset_cancel_attach,
.attach = cpuset_attach,
.bind = cpuset_bind,
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index bc0e504f33a6..80649934cf3b 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -993,7 +993,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = {
static int genl_bind(struct net *net, int group)
{
- int i, err = -ENOENT;
+ int i, err = 0;
down_read(&cb_lock);
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 1626d1553986..8e1aff46ac23 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -375,13 +375,13 @@ country DK: DFS-ETSI
country DM: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
country DO: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
@@ -417,8 +417,8 @@ country EE: DFS-ETSI
country EG: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 20), (20)
- (5250 - 5330 @ 20), (20), DFS
+ (5170 - 5250 @ 20), (23)
+ (5250 - 5330 @ 20), (23), DFS
country ES: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -654,14 +654,14 @@ country IE: DFS-ETSI
country IL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country IN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5735 - 5835 @ 80), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
country IR:
(2402 - 2482 @ 40), (20)
@@ -737,8 +737,8 @@ country KH: DFS-ETSI
country KN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
(5735 - 5815 @ 80), (30)
@@ -758,8 +758,8 @@ country KP: DFS-ETSI
country KW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country KY: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -781,7 +781,7 @@ country LB: DFS-FCC
country LC: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5250 - 5330 @ 80), (30), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
(5735 - 5815 @ 80), (30)
@@ -866,8 +866,8 @@ country LV: DFS-ETSI
country MA: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country MC: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -984,19 +984,19 @@ country MX: DFS-FCC
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-country NA: DFS-ETSI
- (2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5735 - 5815 @ 80), (30)
-
country MY: DFS-FCC
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (24), AUTO-BW
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5650 @ 160), (24), DFS
- (5735 - 5835 @ 80), (24)
+ (5735 - 5815 @ 80), (24)
+
+country NA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5835 @ 80), (33)
country NG: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1065,7 +1065,7 @@ country OM: DFS-ETSI
country PA: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
@@ -1207,8 +1207,8 @@ country RS: DFS-ETSI
country RU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5730 @ 160), (30), DFS
(5735 - 5835 @ 80), (30)
@@ -1298,7 +1298,7 @@ country SR: DFS-ETSI
country SV: DFS-FCC
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 20), (17)
+ (5170 - 5250 @ 20), (23)
(5250 - 5330 @ 20), (23), DFS
(5735 - 5835 @ 20), (30)
@@ -1333,8 +1333,8 @@ country TH: DFS-FCC
country TN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country TR: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1416,7 +1416,7 @@ country UY: DFS-FCC
country UZ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (20), DFS, AUTO-BW
country VC: DFS-ETSI
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 6fc326421108..dc6e95b977c9 100755
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -739,9 +739,6 @@ config SND_SOC_WSA881X_ANALOG
tristate
select REGMAP_I2C
-config SND_SOC_MSM8X16_WCD
- tristate
-
config SND_SOC_WCD9XXX
tristate
default y if SND_SOC_WCD9320=y || SND_SOC_WCD9330=y || SND_SOC_WCD9335=y
@@ -984,4 +981,7 @@ config SND_SOC_MSM_HDMI_CODEC_RX
help
HDMI audio drivers should be built only if the platform
supports hdmi panel.
+
+source "sound/soc/codecs/msm8x16/Kconfig"
+
endmenu
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 4b79b277ce29..f237a2188fe1 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -140,7 +140,6 @@ audio-ext-clock-objs := audio-ext-clk.o
snd-soc-wcd-cpe-objs := wcd_cpe_services.o wcd_cpe_core.o
snd-soc-wsa881x-objs := wsa881x.o wsa881x-tables.o wsa881x-regmap.o wsa881x-temp-sensor.o
snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o
-snd-soc-msm8952-wcd-objs := msm8x16-wcd.o msm8x16-wcd-tables.o
snd-soc-wsa881x-analog-objs := wsa881x-analog.o wsa881x-tables-analog.o
snd-soc-wsa881x-analog-objs += wsa881x-regmap-analog.o wsa881x-irq.o
snd-soc-wcd-dsp-utils-objs := wcd-dsp-utils.o
@@ -348,7 +347,6 @@ obj-$(CONFIG_SND_SOC_WCD934X) += wcd934x/
obj-$(CONFIG_AUDIO_EXT_CLK) += audio-ext-clock.o
obj-$(CONFIG_SND_SOC_WCD9XXX) += snd-soc-wcd9xxx.o
obj-$(CONFIG_SND_SOC_WCD9XXX_V2) += snd-soc-wcd9xxx-v2.o
-obj-$(CONFIG_SND_SOC_MSM8X16_WCD) += snd-soc-msm8952-wcd.o msm8916-wcd-irq.o
obj-$(CONFIG_SND_SOC_WCD_CPE) += snd-soc-wcd-cpe.o
obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o
obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o
@@ -416,3 +414,4 @@ obj-$(CONFIG_SND_SOC_MSM_STUB) += snd-soc-msm-stub.o
# Amp
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
+obj-y += msm8x16/
diff --git a/sound/soc/codecs/msm8x16/Kconfig b/sound/soc/codecs/msm8x16/Kconfig
new file mode 100644
index 000000000000..d225b7a56925
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/Kconfig
@@ -0,0 +1,3 @@
+
+config SND_SOC_MSM8X16_WCD
+ tristate "MSM Internal PMIC based codec"
diff --git a/sound/soc/codecs/msm8x16/Makefile b/sound/soc/codecs/msm8x16/Makefile
new file mode 100644
index 000000000000..36a3d046a307
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/Makefile
@@ -0,0 +1,3 @@
+snd-soc-msm8952-wcd-objs := msm8x16-wcd.o msm8x16-wcd-tables.o msm89xx-regmap.o
+obj-$(CONFIG_SND_SOC_MSM8X16_WCD) += snd-soc-msm8952-wcd.o msm8916-wcd-irq.o
+
diff --git a/sound/soc/codecs/msm8916-wcd-irq.c b/sound/soc/codecs/msm8x16/msm8916-wcd-irq.c
index 8fbd72964108..a722842b106b 100644
--- a/sound/soc/codecs/msm8916-wcd-irq.c
+++ b/sound/soc/codecs/msm8x16/msm8916-wcd-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -56,20 +56,20 @@ char *irq_names[MAX_NUM_IRQS] = {
};
int order[MAX_NUM_IRQS] = {
- MSM8X16_WCD_IRQ_SPKR_CNP,
- MSM8X16_WCD_IRQ_SPKR_CLIP,
- MSM8X16_WCD_IRQ_SPKR_OCP,
- MSM8X16_WCD_IRQ_MBHC_INSREM_DET1,
- MSM8X16_WCD_IRQ_MBHC_RELEASE,
- MSM8X16_WCD_IRQ_MBHC_PRESS,
- MSM8X16_WCD_IRQ_MBHC_INSREM_DET,
- MSM8X16_WCD_IRQ_MBHC_HS_DET,
- MSM8X16_WCD_IRQ_EAR_OCP,
- MSM8X16_WCD_IRQ_HPHR_OCP,
- MSM8X16_WCD_IRQ_HPHL_OCP,
- MSM8X16_WCD_IRQ_EAR_CNP,
- MSM8X16_WCD_IRQ_HPHR_CNP,
- MSM8X16_WCD_IRQ_HPHL_CNP,
+ MSM89XX_IRQ_SPKR_CNP,
+ MSM89XX_IRQ_SPKR_CLIP,
+ MSM89XX_IRQ_SPKR_OCP,
+ MSM89XX_IRQ_MBHC_INSREM_DET1,
+ MSM89XX_IRQ_MBHC_RELEASE,
+ MSM89XX_IRQ_MBHC_PRESS,
+ MSM89XX_IRQ_MBHC_INSREM_DET,
+ MSM89XX_IRQ_MBHC_HS_DET,
+ MSM89XX_IRQ_EAR_OCP,
+ MSM89XX_IRQ_HPHR_OCP,
+ MSM89XX_IRQ_HPHL_OCP,
+ MSM89XX_IRQ_EAR_CNP,
+ MSM89XX_IRQ_HPHR_CNP,
+ MSM89XX_IRQ_HPHL_CNP,
};
enum wcd9xxx_spmi_pm_state {
@@ -101,18 +101,18 @@ void wcd9xxx_spmi_enable_irq(int irq)
pr_debug("%s: irqno =%d\n", __func__, irq);
if ((irq >= 0) && (irq <= 7)) {
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_DIGITAL_INT_EN_CLR,
+ MSM89XX_PMIC_DIGITAL_INT_EN_CLR,
(0x01 << irq), 0x00);
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_DIGITAL_INT_EN_SET,
+ MSM89XX_PMIC_DIGITAL_INT_EN_SET,
(0x01 << irq), (0x01 << irq));
}
if ((irq > 7) && (irq <= 15)) {
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_ANALOG_INT_EN_CLR,
+ MSM89XX_PMIC_ANALOG_INT_EN_CLR,
(0x01 << (irq - 8)), 0x00);
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_ANALOG_INT_EN_SET,
+ MSM89XX_PMIC_ANALOG_INT_EN_SET,
(0x01 << (irq - 8)), (0x01 << (irq - 8)));
}
@@ -130,19 +130,19 @@ void wcd9xxx_spmi_disable_irq(int irq)
pr_debug("%s: irqno =%d\n", __func__, irq);
if ((irq >= 0) && (irq <= 7)) {
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_DIGITAL_INT_EN_SET,
+ MSM89XX_PMIC_DIGITAL_INT_EN_SET,
(0x01 << (irq)), 0x00);
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_DIGITAL_INT_EN_CLR,
+ MSM89XX_PMIC_DIGITAL_INT_EN_CLR,
(0x01 << irq), (0x01 << irq));
}
if ((irq > 7) && (irq <= 15)) {
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_ANALOG_INT_EN_SET,
+ MSM89XX_PMIC_ANALOG_INT_EN_SET,
(0x01 << (irq - 8)), 0x00);
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_ANALOG_INT_EN_CLR,
+ MSM89XX_PMIC_ANALOG_INT_EN_CLR,
(0x01 << (irq - 8)), (0x01 << (irq - 8)));
}
@@ -161,10 +161,6 @@ int wcd9xxx_spmi_request_irq(int irq, irq_handler_t handler,
int rc;
unsigned long irq_flags;
- map.linuxirq[irq] =
- spmi_get_irq_byname(map.spmi[BIT_BYTE(irq)], NULL,
- irq_names[irq]);
-
if (strcmp(name, "mbhc sw intr"))
irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
IRQF_ONESHOT;
@@ -234,7 +230,7 @@ static irqreturn_t wcd9xxx_spmi_irq_handler(int linux_irq, void *data)
for (i = 0; i < NUM_IRQ_REGS; i++) {
status[i] |= snd_soc_read(map.codec,
BIT_BYTE(irq) * 0x100 +
- MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS);
+ MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS);
status[i] &= ~map.mask[i];
}
for (i = 0; i < MAX_NUM_IRQS; i++) {
@@ -418,10 +414,10 @@ void wcd9xxx_spmi_set_codec(struct snd_soc_codec *codec)
map.codec = codec;
}
-void wcd9xxx_spmi_set_dev(struct platform_device *pdev, int i)
+void wcd9xxx_spmi_set_dev(struct spmi_device *spmi, int i)
{
if (i < NUM_IRQ_REGS)
- map.spmi[i] = pdev;
+ map.spmi[i] = spmi;
}
int wcd9xxx_spmi_irq_init(void)
diff --git a/sound/soc/codecs/msm8916-wcd-irq.h b/sound/soc/codecs/msm8x16/msm8916-wcd-irq.h
index 659e52cc2a5e..659e52cc2a5e 100644
--- a/sound/soc/codecs/msm8916-wcd-irq.h
+++ b/sound/soc/codecs/msm8x16/msm8916-wcd-irq.h
diff --git a/sound/soc/codecs/msm8x16/msm89xx-regmap.c b/sound/soc/codecs/msm8x16/msm89xx-regmap.c
new file mode 100644
index 000000000000..007b74c8b867
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm89xx-regmap.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2015-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.
+ */
+
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "msm8x16-wcd.h"
+
+/*
+ * Default register reset values that are common across different versions
+ * are defined here. If a register reset value is changed based on version
+ * then remove it from this structure and add it in version specific
+ * structures.
+ */
+static struct reg_default
+ msm89xx_cdc_core_defaults[MSM89XX_CDC_CORE_CACHE_SIZE] = {
+ {MSM89XX_CDC_CORE_CLK_RX_RESET_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x13},
+ {MSM89XX_CDC_CORE_CLK_TX_I2S_CTL, 0x13},
+ {MSM89XX_CDC_CORE_CLK_OTHR_RESET_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_OTHR_CTL, 0x04},
+ {MSM89XX_CDC_CORE_CLK_RX_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_MCLK_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_PDM_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_SD_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_RX_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B5_CTL, 0x68},
+ {MSM89XX_CDC_CORE_RX2_B5_CTL, 0x68},
+ {MSM89XX_CDC_CORE_RX3_B5_CTL, 0x68},
+ {MSM89XX_CDC_CORE_RX1_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_VOL_CTL_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_VOL_CTL_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_VOL_CTL_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TOP_GAIN_UPDATE, 0x00},
+ {MSM89XX_CDC_CORE_TOP_CTL, 0x01},
+ {MSM89XX_CDC_CORE_COMP0_B1_CTL, 0x30},
+ {MSM89XX_CDC_CORE_COMP0_B2_CTL, 0xB5},
+ {MSM89XX_CDC_CORE_COMP0_B3_CTL, 0x28},
+ {MSM89XX_CDC_CORE_COMP0_B4_CTL, 0x37},
+ {MSM89XX_CDC_CORE_COMP0_B5_CTL, 0x7F},
+ {MSM89XX_CDC_CORE_COMP0_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_COMP0_SHUT_DOWN_STATUS, 0x03},
+ {MSM89XX_CDC_CORE_COMP0_FS_CFG, 0x03},
+ {MSM89XX_CDC_CORE_COMP0_DELAY_BUF_CTL, 0x02},
+ {MSM89XX_CDC_CORE_DEBUG_DESER1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_DEBUG_DESER2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_DEBUG_B1_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_DEBUG_B2_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_DEBUG_B3_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B5_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B5_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B7_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B7_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B8_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B8_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_CTL, 0x40},
+ {MSM89XX_CDC_CORE_IIR2_CTL, 0x40},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_TIMER_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_TIMER_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_COEF_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX1_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX1_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX1_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX2_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX2_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX2_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX3_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX3_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_TX_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ1_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ1_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ1_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ2_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ2_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ2_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX1_VOL_CTL_TIMER, 0x00},
+ {MSM89XX_CDC_CORE_TX2_VOL_CTL_TIMER, 0x00},
+ {MSM89XX_CDC_CORE_TX3_VOL_CTL_TIMER, 0x00},
+ {MSM89XX_CDC_CORE_TX4_VOL_CTL_TIMER, 0x00},
+ {MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN, 0x00},
+ {MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN, 0x00},
+ {MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN, 0x00},
+ {MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN, 0x00},
+ {MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_TX3_VOL_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_TX4_VOL_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_TX1_MUX_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX2_MUX_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX3_MUX_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX4_MUX_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX1_CLK_FS_CTL, 0x03},
+ {MSM89XX_CDC_CORE_TX2_CLK_FS_CTL, 0x03},
+ {MSM89XX_CDC_CORE_TX3_CLK_FS_CTL, 0x03},
+ {MSM89XX_CDC_CORE_TX4_CLK_FS_CTL, 0x03},
+ {MSM89XX_CDC_CORE_TX1_DMIC_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX2_DMIC_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX3_DMIC_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX4_DMIC_CTL, 0x00},
+};
+
+static struct reg_default
+ msm89xx_pmic_cdc_defaults[MSM89XX_PMIC_CDC_CACHE_SIZE] = {
+ {MSM89XX_PMIC_DIGITAL_REVISION1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_REVISION2, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PERPH_TYPE, 0x23},
+ {MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE, 0x01},
+ {MSM89XX_PMIC_DIGITAL_INT_RT_STS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_SET_TYPE, 0xFF},
+ {MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH, 0xFF},
+ {MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_LATCHED_CLR, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_EN_SET, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_EN_CLR, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_PENDING_STS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_MID_SEL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_PRIORITY, 0x00},
+ {MSM89XX_PMIC_DIGITAL_GPIO_MODE, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PIN_CTL_OE, 0x01},
+ {MSM89XX_PMIC_DIGITAL_PIN_CTL_DATA, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PIN_STATUS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_HDRIVE_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL, 0x02},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL, 0x02},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_RX1_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_RX2_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_RX3_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_RX_LB_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_RX_CTL1, 0x7C},
+ {MSM89XX_PMIC_DIGITAL_CDC_RX_CTL2, 0x7C},
+ {MSM89XX_PMIC_DIGITAL_CDC_RX_CTL3, 0x7C},
+ {MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA0, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA2, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA3, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DIG_DEBUG_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DIG_DEBUG_EN, 0x00},
+ {MSM89XX_PMIC_DIGITAL_SPARE_0, 0x00},
+ {MSM89XX_PMIC_DIGITAL_SPARE_1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_SPARE_2, 0x00},
+ {MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL2, 0x02},
+ {MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x05},
+ {MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_TEST1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_TEST_VAL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_TRIM_NUM, 0x00},
+ {MSM89XX_PMIC_DIGITAL_TRIM_CTRL, 0x00},
+ {MSM89XX_PMIC_ANALOG_REVISION1, 0x00},
+ {MSM89XX_PMIC_ANALOG_REVISION2, 0x00},
+ {MSM89XX_PMIC_ANALOG_REVISION3, 0x00},
+ {MSM89XX_PMIC_ANALOG_REVISION4, 0x00},
+ {MSM89XX_PMIC_ANALOG_PERPH_TYPE, 0x23},
+ {MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE, 0x09},
+ {MSM89XX_PMIC_ANALOG_INT_RT_STS, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_SET_TYPE, 0x3F},
+ {MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH, 0x3F},
+ {MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_LATCHED_CLR, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_EN_SET, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_EN_CLR, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_LATCHED_STS, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_PENDING_STS, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_MID_SEL, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_PRIORITY, 0x00},
+ {MSM89XX_PMIC_ANALOG_MICB_1_EN, 0x00},
+ {MSM89XX_PMIC_ANALOG_MICB_1_VAL, 0x20},
+ {MSM89XX_PMIC_ANALOG_MICB_1_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS, 0x49},
+ {MSM89XX_PMIC_ANALOG_MICB_2_EN, 0x20},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2, 0x00},
+ {MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x35},
+ {MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x08},
+ {MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, 0x98},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL, 0x20},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL, 0x40},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL, 0x61},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN4_CTL, 0x80},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT, 0x00},
+ {MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x00},
+ {MSM89XX_PMIC_ANALOG_TX_1_EN, 0x03},
+ {MSM89XX_PMIC_ANALOG_TX_2_EN, 0x03},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_1, 0xBF},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2, 0x8C},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x6B},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV, 0x51},
+ {MSM89XX_PMIC_ANALOG_TX_3_EN, 0x02},
+ {MSM89XX_PMIC_ANALOG_NCP_EN, 0x26},
+ {MSM89XX_PMIC_ANALOG_NCP_CLK, 0x23},
+ {MSM89XX_PMIC_ANALOG_NCP_DEGLITCH, 0x5B},
+ {MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0x08},
+ {MSM89XX_PMIC_ANALOG_NCP_BIAS, 0x29},
+ {MSM89XX_PMIC_ANALOG_NCP_VCTRL, 0x24},
+ {MSM89XX_PMIC_ANALOG_NCP_TEST, 0x00},
+ {MSM89XX_PMIC_ANALOG_NCP_CLIM_ADDR, 0xD5},
+ {MSM89XX_PMIC_ANALOG_RX_CLOCK_DIVIDER, 0xE8},
+ {MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL, 0xCF},
+ {MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT, 0x6E},
+ {MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC, 0x18},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA, 0x5A},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_LDO_OCP, 0x69},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP, 0x29},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN, 0x80},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_CTL, 0xDA},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME, 0x16},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x20},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x20},
+ {MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x12},
+ {MSM89XX_PMIC_ANALOG_RX_ATEST, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_STATUS, 0x0C},
+ {MSM89XX_PMIC_ANALOG_RX_EAR_STATUS, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x83},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_CLIP_DET, 0x91},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x29},
+ {MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET, 0x4D},
+ {MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1},
+ {MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0x1E},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_MISC, 0xCB},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x00},
+ {MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0x02},
+ {MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE, 0x14},
+ {MSM89XX_PMIC_ANALOG_BYPASS_MODE, 0x00},
+ {MSM89XX_PMIC_ANALOG_BOOST_EN_CTL, 0x1F},
+ {MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO, 0x8C},
+ {MSM89XX_PMIC_ANALOG_RDSON_MAX_DUTY_CYCLE, 0xC0},
+ {MSM89XX_PMIC_ANALOG_BOOST_TEST1_1, 0x00},
+ {MSM89XX_PMIC_ANALOG_BOOST_TEST_2, 0x00},
+ {MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS, 0x00},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS, 0x00},
+ {MSM89XX_PMIC_ANALOG_PBUS_ADD_CSR, 0x00},
+ {MSM89XX_PMIC_ANALOG_PBUS_ADD_SEL, 0x00},
+ {MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0x00},
+ {MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL1, 0x00},
+ {MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL2, 0x01},
+ {MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x05},
+ {MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_TEST1, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_TEST_VAL, 0x00},
+ {MSM89XX_PMIC_ANALOG_TRIM_NUM, 0x04},
+ {MSM89XX_PMIC_ANALOG_TRIM_CTRL1, 0x00},
+ {MSM89XX_PMIC_ANALOG_TRIM_CTRL2, 0x00},
+ {MSM89XX_PMIC_ANALOG_TRIM_CTRL3, 0x00},
+ {MSM89XX_PMIC_ANALOG_TRIM_CTRL4, 0x00},
+};
+
+static bool msm89xx_cdc_core_readable_reg(struct device *dev, unsigned int reg)
+{
+ return msm89xx_cdc_core_reg_readable[reg];
+}
+
+static bool msm89xx_pmic_cdc_readable_reg(struct device *dev, unsigned int reg)
+{
+ return msm89xx_pmic_cdc_reg_readable[reg];
+}
+
+static bool msm89xx_cdc_core_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MSM89XX_CDC_CORE_RX1_B1_CTL:
+ case MSM89XX_CDC_CORE_RX2_B1_CTL:
+ case MSM89XX_CDC_CORE_RX3_B1_CTL:
+ case MSM89XX_CDC_CORE_RX1_B6_CTL:
+ case MSM89XX_CDC_CORE_RX2_B6_CTL:
+ case MSM89XX_CDC_CORE_RX3_B6_CTL:
+ case MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG:
+ case MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG:
+ case MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL:
+ case MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL:
+ case MSM89XX_CDC_CORE_CLK_MCLK_CTL:
+ case MSM89XX_CDC_CORE_CLK_PDM_CTL:
+ case MSM89XX_PMIC_ANALOG_BYPASS_MODE:
+ case MSM89XX_PMIC_ANALOG_BOOST_EN_CTL:
+ case MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL:
+ case MSM89XX_PMIC_ANALOG_CURRENT_LIMIT:
+ case MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL:
+ case MSM89XX_PMIC_ANALOG_NCP_FBCTRL:
+ case MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool msm89xx_pmic_cdc_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MSM89XX_PMIC_DIGITAL_REVISION1:
+ case MSM89XX_PMIC_DIGITAL_REVISION2:
+ case MSM89XX_PMIC_DIGITAL_PERPH_TYPE:
+ case MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE:
+ case MSM89XX_PMIC_DIGITAL_INT_RT_STS:
+ case MSM89XX_PMIC_DIGITAL_INT_SET_TYPE:
+ case MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH:
+ case MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW:
+ case MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS:
+ case MSM89XX_PMIC_DIGITAL_INT_PENDING_STS:
+ case MSM89XX_PMIC_DIGITAL_PIN_STATUS:
+ case MSM89XX_PMIC_DIGITAL_SEC_ACCESS:
+ case MSM89XX_PMIC_ANALOG_SEC_ACCESS:
+ case MSM89XX_PMIC_ANALOG_REVISION1:
+ case MSM89XX_PMIC_ANALOG_REVISION2:
+ case MSM89XX_PMIC_ANALOG_REVISION3:
+ case MSM89XX_PMIC_ANALOG_REVISION4:
+ case MSM89XX_PMIC_ANALOG_PERPH_TYPE:
+ case MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE:
+ case MSM89XX_PMIC_ANALOG_INT_RT_STS:
+ case MSM89XX_PMIC_ANALOG_INT_SET_TYPE:
+ case MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH:
+ case MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW:
+ case MSM89XX_PMIC_ANALOG_INT_LATCHED_STS:
+ case MSM89XX_PMIC_ANALOG_INT_PENDING_STS:
+ case MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT:
+ case MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT:
+ case MSM89XX_PMIC_ANALOG_RX_HPH_STATUS:
+ case MSM89XX_PMIC_ANALOG_RX_EAR_STATUS:
+ case MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS:
+ case MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+struct regmap_config msm89xx_pmic_cdc_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = MSM89XX_PMIC_CDC_CACHE_SIZE,
+ .fast_io = true,
+ .reg_defaults = msm89xx_pmic_cdc_defaults,
+ .num_reg_defaults = ARRAY_SIZE(msm89xx_pmic_cdc_defaults),
+ .readable_reg = msm89xx_pmic_cdc_readable_reg,
+ .volatile_reg = msm89xx_pmic_cdc_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_format_endian = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian = REGMAP_ENDIAN_NATIVE,
+ .can_multi_write = true,
+ .lock = enable_digital_callback,
+ .unlock = disable_digital_callback,
+
+};
+
+struct regmap_config msm89xx_cdc_core_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+
+ .max_register = MSM89XX_CDC_CORE_CACHE_SIZE,
+ .reg_defaults = msm89xx_cdc_core_defaults,
+ .num_reg_defaults = ARRAY_SIZE(msm89xx_cdc_core_defaults),
+ .readable_reg = msm89xx_cdc_core_readable_reg,
+ .volatile_reg = msm89xx_cdc_core_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_format_endian = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian = REGMAP_ENDIAN_NATIVE,
+ .can_multi_write = true,
+};
diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd-tables.c b/sound/soc/codecs/msm8x16/msm8x16-wcd-tables.c
new file mode 100644
index 000000000000..b969639b10eb
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm8x16-wcd-tables.c
@@ -0,0 +1,263 @@
+/* Copyright (c) 2015-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.
+ */
+
+#include "msm8x16-wcd.h"
+
+const u8 msm89xx_pmic_cdc_reg_readable[MSM89XX_PMIC_CDC_CACHE_SIZE] = {
+ [MSM89XX_PMIC_DIGITAL_REVISION1] = 1,
+ [MSM89XX_PMIC_DIGITAL_REVISION2] = 1,
+ [MSM89XX_PMIC_DIGITAL_PERPH_TYPE] = 1,
+ [MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_RT_STS] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_SET_TYPE] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_EN_SET] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_EN_CLR] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_PENDING_STS] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_MID_SEL] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_PRIORITY] = 1,
+ [MSM89XX_PMIC_DIGITAL_GPIO_MODE] = 1,
+ [MSM89XX_PMIC_DIGITAL_PIN_CTL_OE] = 1,
+ [MSM89XX_PMIC_DIGITAL_PIN_CTL_DATA] = 1,
+ [MSM89XX_PMIC_DIGITAL_PIN_STATUS] = 1,
+ [MSM89XX_PMIC_DIGITAL_HDRIVE_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_RST_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_RX1_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_RX2_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_RX3_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_RX_LB_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_RX_CTL1] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_RX_CTL2] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_RX_CTL3] = 1,
+ [MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA0] = 1,
+ [MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA1] = 1,
+ [MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA2] = 1,
+ [MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA3] = 1,
+ [MSM89XX_PMIC_DIGITAL_DIG_DEBUG_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_SPARE_0] = 1,
+ [MSM89XX_PMIC_DIGITAL_SPARE_1] = 1,
+ [MSM89XX_PMIC_DIGITAL_SPARE_2] = 1,
+ [MSM89XX_PMIC_ANALOG_REVISION1] = 1,
+ [MSM89XX_PMIC_ANALOG_REVISION2] = 1,
+ [MSM89XX_PMIC_ANALOG_REVISION3] = 1,
+ [MSM89XX_PMIC_ANALOG_REVISION4] = 1,
+ [MSM89XX_PMIC_ANALOG_PERPH_TYPE] = 1,
+ [MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_RT_STS] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_SET_TYPE] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_EN_SET] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_EN_CLR] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_LATCHED_STS] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_PENDING_STS] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_MID_SEL] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_PRIORITY] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_1_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_1_VAL] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_1_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_2_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN4_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_2_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_1] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_3_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_CLK] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_DEGLITCH] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_FBCTRL] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_BIAS] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_VCTRL] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_TEST] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_CLOCK_DIVIDER] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_LDO_OCP] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_EAR_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_ATEST] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_STATUS] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_EAR_STATUS] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_CLIP_DET] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_MISC] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG] = 1,
+ [MSM89XX_PMIC_ANALOG_CURRENT_LIMIT] = 1,
+ [MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE] = 1,
+ [MSM89XX_PMIC_ANALOG_BYPASS_MODE] = 1,
+ [MSM89XX_PMIC_ANALOG_BOOST_EN_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO] = 1,
+ [MSM89XX_PMIC_ANALOG_RDSON_MAX_DUTY_CYCLE] = 1,
+ [MSM89XX_PMIC_ANALOG_BOOST_TEST1_1] = 1,
+ [MSM89XX_PMIC_ANALOG_BOOST_TEST_2] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS] = 1,
+ [MSM89XX_PMIC_ANALOG_PBUS_ADD_CSR] = 1,
+ [MSM89XX_PMIC_ANALOG_PBUS_ADD_SEL] = 1,
+ [MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_LATCHED_CLR] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_LATCHED_CLR] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_CLIM_ADDR] = 1,
+ [MSM89XX_PMIC_DIGITAL_SEC_ACCESS] = 1,
+ [MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3] = 1,
+ [MSM89XX_PMIC_ANALOG_SEC_ACCESS] = 1,
+};
+
+const u8 msm89xx_cdc_core_reg_readable[MSM89XX_CDC_CORE_CACHE_SIZE] = {
+ [MSM89XX_CDC_CORE_CLK_RX_RESET_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_RX_I2S_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_TX_I2S_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_OTHR_RESET_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_OTHR_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_RX_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_MCLK_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_PDM_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_SD_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_VOL_CTL_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_VOL_CTL_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_VOL_CTL_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_TOP_GAIN_UPDATE] = 1,
+ [MSM89XX_CDC_CORE_TOP_CTL] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_DESER1_CTL] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_DESER2_CTL] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_B1_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_B2_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_B3_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B7_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B7_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B8_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B8_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_TIMER_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_TIMER_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_COEF_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX1_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX1_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX1_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX2_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX2_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX2_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX3_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX3_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_TX_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ1_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ1_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ1_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ2_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ2_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ2_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX1_VOL_CTL_TIMER] = 1,
+ [MSM89XX_CDC_CORE_TX2_VOL_CTL_TIMER] = 1,
+ [MSM89XX_CDC_CORE_TX3_VOL_CTL_TIMER] = 1,
+ [MSM89XX_CDC_CORE_TX4_VOL_CTL_TIMER] = 1,
+ [MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN] = 1,
+ [MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN] = 1,
+ [MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN] = 1,
+ [MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN] = 1,
+ [MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_TX3_VOL_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_TX4_VOL_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_TX1_MUX_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX2_MUX_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX3_MUX_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX4_MUX_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX1_CLK_FS_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX2_CLK_FS_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX3_CLK_FS_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX4_CLK_FS_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX1_DMIC_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX2_DMIC_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX3_DMIC_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX4_DMIC_CTL] = 1,
+};
diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd.c b/sound/soc/codecs/msm8x16/msm8x16-wcd.c
new file mode 100644
index 000000000000..481e1efdf015
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm8x16-wcd.c
@@ -0,0 +1,6037 @@
+/* Copyright (c) 2015-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.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/spmi.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/qdsp6v2/apr.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <sound/q6afe-v2.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/q6core.h>
+#include <soc/qcom/subsystem_notif.h>
+#include "msm8x16-wcd.h"
+#include "../wcd-mbhc-v2.h"
+#include "msm8916-wcd-irq.h"
+
+#define DRV_NAME "msm-codec"
+#define MSM89XX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+#define MSM89XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+#define NUM_INTERPOLATORS 3
+#define BITS_PER_REG 8
+#define MSM89XX_TX_PORT_NUMBER 4
+
+#define MSM89XX_I2S_MASTER_MODE_MASK 0x08
+#define MSM89XX_DIGITAL_CODEC_BASE_ADDR 0x771C000
+#define PMIC_SLAVE_ID_0 0
+#define PMIC_SLAVE_ID_1 1
+
+#define PMIC_MBG_OK 0x2C08
+#define PMIC_LDO7_EN_CTL 0x4646
+#define MASK_MSB_BIT 0x80
+
+#define CODEC_DT_MAX_PROP_SIZE 40
+#define MSM89XX_DIGITAL_CODEC_REG_SIZE 0x400
+#define MAX_ON_DEMAND_SUPPLY_NAME_LENGTH 64
+
+#define MCLK_RATE_9P6MHZ 9600000
+#define MCLK_RATE_12P288MHZ 12288000
+
+#define BUS_DOWN 1
+
+/*
+ *50 Milliseconds sufficient for DSP bring up in the modem
+ * after Sub System Restart
+ */
+#define ADSP_STATE_READY_TIMEOUT_MS 50
+
+#define HPHL_PA_DISABLE (0x01 << 1)
+#define HPHR_PA_DISABLE (0x01 << 2)
+#define EAR_PA_DISABLE (0x01 << 3)
+#define SPKR_PA_DISABLE (0x01 << 4)
+
+enum {
+ BOOST_SWITCH = 0,
+ BOOST_ALWAYS,
+ BYPASS_ALWAYS,
+ BOOST_ON_FOREVER,
+};
+
+#define EAR_PMD 0
+#define EAR_PMU 1
+#define SPK_PMD 2
+#define SPK_PMU 3
+
+#define MICBIAS_DEFAULT_VAL 1800000
+#define MICBIAS_MIN_VAL 1600000
+#define MICBIAS_STEP_SIZE 50000
+
+#define DEFAULT_BOOST_VOLTAGE 5000
+#define MIN_BOOST_VOLTAGE 4000
+#define MAX_BOOST_VOLTAGE 5550
+#define BOOST_VOLTAGE_STEP 50
+
+#define MSM89XX_MBHC_BTN_COARSE_ADJ 100 /* in mV */
+#define MSM89XX_MBHC_BTN_FINE_ADJ 12 /* in mV */
+
+#define VOLTAGE_CONVERTER(value, min_value, step_size)\
+ ((value - min_value)/step_size)
+
+enum {
+ AIF1_PB = 0,
+ AIF1_CAP,
+ AIF2_VIFEED,
+ NUM_CODEC_DAIS,
+};
+
+enum {
+ RX_MIX1_INP_SEL_ZERO = 0,
+ RX_MIX1_INP_SEL_IIR1,
+ RX_MIX1_INP_SEL_IIR2,
+ RX_MIX1_INP_SEL_RX1,
+ RX_MIX1_INP_SEL_RX2,
+ RX_MIX1_INP_SEL_RX3,
+};
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver msm8x16_wcd_i2s_dai[];
+/* By default enable the internal speaker boost */
+static bool spkr_boost_en = true;
+
+#define MSM89XX_ACQUIRE_LOCK(x) \
+ mutex_lock_nested(&x, SINGLE_DEPTH_NESTING)
+
+#define MSM89XX_RELEASE_LOCK(x) mutex_unlock(&x)
+
+
+/* Codec supports 2 IIR filters */
+enum {
+ IIR1 = 0,
+ IIR2,
+ IIR_MAX,
+};
+
+/* Codec supports 5 bands */
+enum {
+ BAND1 = 0,
+ BAND2,
+ BAND3,
+ BAND4,
+ BAND5,
+ BAND_MAX,
+};
+
+struct hpf_work {
+ struct msm8x16_wcd_priv *msm8x16_wcd;
+ u32 decimator;
+ u8 tx_hpf_cut_of_freq;
+ struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
+static char on_demand_supply_name[][MAX_ON_DEMAND_SUPPLY_NAME_LENGTH] = {
+ "cdc-vdd-mic-bias",
+};
+
+static unsigned long rx_digital_gain_reg[] = {
+ MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL,
+ MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL,
+ MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL,
+};
+
+static unsigned long tx_digital_gain_reg[] = {
+ MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN,
+ MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN,
+};
+
+enum {
+ MSM89XX_SPMI_DIGITAL = 0,
+ MSM89XX_SPMI_ANALOG,
+ MSM89XX_CODEC_CORE,
+ MAX_MSM89XX_DEVICE
+};
+
+static struct wcd_mbhc_register
+ wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {
+
+ WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x80, 7, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_GND_DET_EN",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x40, 6, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MECH_DETECTION_TYPE",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x20, 5, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MIC_CLAMP_CTL",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x18, 3, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_ELECT_DETECTION_TYPE",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x01, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_CTRL",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0xC0, 6, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x20, 5, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PLUG_TYPE",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x10, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_GND_PLUG_TYPE",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x08, 3, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_SW_HPH_LP_100K_TO_GND",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x01, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_ELECT_SCHMT_ISRC",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x06, 1, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_FSM_EN",
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, 0x80, 7, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_INSREM_DBNC",
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, 0xF0, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_BTN_DBNC",
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, 0x0C, 2, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HS_VREF",
+ MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL, 0x03, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HS_COMP_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x01,
+ 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MIC_SCHMT_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x02,
+ 1, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHL_SCHMT_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x08,
+ 3, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHR_SCHMT_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x04,
+ 2, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_OCP_FSM_EN",
+ MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL, 0x10, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_BTN_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT, 0xFF, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_BTN_ISRC_CTL",
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, 0x70, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_ELECT_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0xFF,
+ 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MICB_CTRL",
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, 0xC0, 6, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPH_CNP_WG_TIME",
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME, 0xFC, 2, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHR_PA_EN",
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN, 0x10, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PA_EN",
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN, 0x20, 5, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPH_PA_EN",
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN, 0x30, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_SWCH_LEVEL_REMOVE",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT,
+ 0x10, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MOISTURE_VREF",
+ 0, 0, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_PULLDOWN_CTRL",
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, 0x20, 5, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_ANC_DET_EN",
+ 0, 0, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_FSM_STATUS",
+ 0, 0, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MUX_CTL",
+ 0, 0, 0, 0),
+};
+
+struct msm8x16_wcd_spmi {
+ struct spmi_device *spmi;
+ int base;
+};
+
+/* Multiply gain_adj and offset by 1000 and 100 to avoid float arithmetic */
+static const struct wcd_imped_i_ref imped_i_ref[] = {
+ {I_h4_UA, 8, 800, 9000, 10000},
+ {I_pt5_UA, 10, 100, 990, 4600},
+ {I_14_UA, 17, 14, 1050, 700},
+ {I_l4_UA, 10, 4, 1165, 110},
+ {I_1_UA, 0, 1, 1200, 65},
+};
+
+static const struct wcd_mbhc_intr intr_ids = {
+ .mbhc_sw_intr = MSM89XX_IRQ_MBHC_HS_DET,
+ .mbhc_btn_press_intr = MSM89XX_IRQ_MBHC_PRESS,
+ .mbhc_btn_release_intr = MSM89XX_IRQ_MBHC_RELEASE,
+ .mbhc_hs_ins_intr = MSM89XX_IRQ_MBHC_INSREM_DET1,
+ .mbhc_hs_rem_intr = MSM89XX_IRQ_MBHC_INSREM_DET,
+ .hph_left_ocp = MSM89XX_IRQ_HPHL_OCP,
+ .hph_right_ocp = MSM89XX_IRQ_HPHR_OCP,
+};
+
+static int msm_digcdc_clock_control(bool flag);
+static int msm8x16_wcd_dt_parse_vreg_info(struct device *dev,
+ struct msm8x16_wcd_regulator *vreg,
+ const char *vreg_name, bool ondemand);
+static struct msm8x16_wcd_pdata *msm8x16_wcd_populate_dt_pdata(
+ struct device *dev);
+static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec,
+ bool turn_on);
+static void msm8x16_trim_btn_reg(struct snd_soc_codec *codec);
+static void msm8x16_wcd_set_micb_v(struct snd_soc_codec *codec);
+static void msm8x16_wcd_set_boost_v(struct snd_soc_codec *codec);
+static void msm8x16_wcd_set_auto_zeroing(struct snd_soc_codec *codec,
+ bool enable);
+static void msm8x16_wcd_configure_cap(struct snd_soc_codec *codec,
+ bool micbias1, bool micbias2);
+static bool msm8x16_wcd_use_mb(struct snd_soc_codec *codec);
+
+struct msm8x16_wcd_spmi msm8x16_wcd_modules[MAX_MSM89XX_DEVICE];
+
+static void *adsp_state_notifier;
+
+static struct snd_soc_codec *registered_codec;
+static struct snd_soc_codec *registered_digcodec;
+
+static int get_codec_version(struct msm8x16_wcd_priv *msm8x16_wcd)
+{
+ if (msm8x16_wcd->codec_version == DIANGU)
+ return DIANGU;
+ else if (msm8x16_wcd->codec_version == CAJON_2_0)
+ return CAJON_2_0;
+ else if (msm8x16_wcd->codec_version == CAJON)
+ return CAJON;
+ else if (msm8x16_wcd->codec_version == CONGA)
+ return CONGA;
+ else if (msm8x16_wcd->pmic_rev == TOMBAK_2_0)
+ return TOMBAK_2_0;
+ else if (msm8x16_wcd->pmic_rev == TOMBAK_1_0)
+ return TOMBAK_1_0;
+
+ pr_err("%s: unsupported codec version\n", __func__);
+ return UNSUPPORTED;
+}
+
+static int msm_digcdc_clock_control(bool flag)
+{
+ int ret = -EINVAL;
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(registered_codec->component.card);
+
+ if (flag) {
+ mutex_lock(&pdata->cdc_mclk_mutex);
+ if (atomic_read(&pdata->mclk_enabled) == false) {
+ if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
+ pdata->digital_cdc_clk.clk_val =
+ pdata->mclk_freq;
+ ret = afe_set_digital_codec_core_clock(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_clk);
+ } else {
+ pdata->digital_cdc_core_clk.enable = 1;
+ ret = afe_set_lpass_clock_v2(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ }
+ if (ret < 0) {
+ pr_err("failed to enable the MCLK\n");
+ goto err;
+ }
+ pr_err("enabled digital codec core clk\n");
+ atomic_set(&pdata->mclk_enabled, true);
+ schedule_delayed_work(&pdata->disable_mclk_work, 50);
+ }
+err:
+ mutex_unlock(&pdata->cdc_mclk_mutex);
+ return ret;
+ }
+ return 0;
+}
+
+void enable_digital_callback(void *flag)
+{
+ msm_digcdc_clock_control(true);
+}
+
+void disable_digital_callback(void *flag)
+{
+ msm_digcdc_clock_control(false);
+}
+
+static int snd_soc_read_wrapper(struct snd_soc_codec *codec, u16 reg)
+{
+ int ret = -EINVAL;
+ struct msm8x16_wcd *msm8x16_wcd = codec->control_data;
+
+ pr_err("%s reg = %x\n", __func__, reg);
+ mutex_lock(&msm8x16_wcd->io_lock);
+ if (MSM89XX_IS_PMIC_CDC_REG(reg))
+ ret = snd_soc_read(codec, reg);
+ else if (MSM89XX_IS_CDC_CORE_REG(reg))
+ ret = snd_soc_read(registered_digcodec, reg);
+ mutex_unlock(&msm8x16_wcd->io_lock);
+
+ return ret;
+}
+
+static int snd_soc_write_wrapper(struct snd_soc_codec *codec, u16 reg, u8 val)
+{
+ int ret = -EINVAL;
+ struct msm8x16_wcd *msm8x16_wcd = codec->control_data;
+
+ pr_err("%s reg = %x\n", __func__, reg);
+ mutex_lock(&msm8x16_wcd->io_lock);
+ if (MSM89XX_IS_PMIC_CDC_REG(reg))
+ ret = snd_soc_write(codec, reg, val);
+ else if (MSM89XX_IS_CDC_CORE_REG(reg))
+ ret = snd_soc_write(registered_digcodec, reg, val);
+ mutex_unlock(&msm8x16_wcd->io_lock);
+
+ return ret;
+}
+
+static int snd_soc_update_bits_wrapper(struct snd_soc_codec *codec,
+ u16 reg, u8 mask, u8 val)
+{
+ int ret = -EINVAL;
+ struct msm8x16_wcd *msm8x16_wcd = codec->control_data;
+
+ pr_err("%s reg = %x\n", __func__, reg);
+ mutex_lock(&msm8x16_wcd->io_lock);
+ if (MSM89XX_IS_PMIC_CDC_REG(reg))
+ ret = snd_soc_update_bits(codec, reg, mask, val);
+ else if (MSM89XX_IS_CDC_CORE_REG(reg))
+ ret = snd_soc_update_bits(registered_digcodec, reg, mask, val);
+ mutex_unlock(&msm8x16_wcd->io_lock);
+
+ return ret;
+}
+
+static void wcd_mbhc_meas_imped(struct snd_soc_codec *codec,
+ s16 *impedance_l, s16 *impedance_r)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if ((msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_BOTH) ||
+ (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHL)) {
+ /* Enable ZDET_L_MEAS_EN */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x08, 0x08);
+ /* Wait for 2ms for measurement to complete */
+ usleep_range(2000, 2100);
+ /* Read Left impedance value from Result1 */
+ *impedance_l = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
+ /* Enable ZDET_R_MEAS_EN */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x08, 0x00);
+ }
+ if ((msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_BOTH) ||
+ (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR)) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x04, 0x04);
+ /* Wait for 2ms for measurement to complete */
+ usleep_range(2000, 2100);
+ /* Read Right impedance value from Result1 */
+ *impedance_r = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x04, 0x00);
+ }
+}
+
+static void msm8x16_set_ref_current(struct snd_soc_codec *codec,
+ enum wcd_curr_ref curr_ref)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s: curr_ref: %d\n", __func__, curr_ref);
+
+ if (get_codec_version(msm8x16_wcd) < CAJON)
+ pr_err("%s: Setting ref current not required\n", __func__);
+
+ msm8x16_wcd->imped_i_ref = imped_i_ref[curr_ref];
+
+ switch (curr_ref) {
+ case I_h4_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x01);
+ break;
+ case I_pt5_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x04);
+ break;
+ case I_14_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x03);
+ break;
+ case I_l4_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x01);
+ break;
+ case I_1_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x00);
+ break;
+ default:
+ pr_err("%s: No ref current set\n", __func__);
+ break;
+ }
+}
+
+static bool msm8x16_adj_ref_current(struct snd_soc_codec *codec,
+ s16 *impedance_l, s16 *impedance_r)
+{
+ int i = 2;
+ s16 compare_imp = 0;
+
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR)
+ compare_imp = *impedance_r;
+ else
+ compare_imp = *impedance_l;
+
+ if (get_codec_version(msm8x16_wcd) < CAJON) {
+ pr_err("%s: Reference current adjustment not required\n",
+ __func__);
+ return false;
+ }
+
+ while (compare_imp < imped_i_ref[i].min_val) {
+ msm8x16_set_ref_current(codec,
+ imped_i_ref[++i].curr_ref);
+ wcd_mbhc_meas_imped(codec,
+ impedance_l, impedance_r);
+ compare_imp = (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR)
+ ? *impedance_r : *impedance_l;
+ }
+
+ return true;
+}
+
+void msm8x16_wcd_spk_ext_pa_cb(
+ int (*codec_spk_ext_pa)(struct snd_soc_codec *codec,
+ int enable), struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s: Enter\n", __func__);
+ msm8x16_wcd->codec_spk_ext_pa_cb = codec_spk_ext_pa;
+}
+
+void msm8x16_wcd_hph_comp_cb(
+ int (*codec_hph_comp_gpio)(bool enable), struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s: Enter\n", __func__);
+ msm8x16_wcd->codec_hph_comp_gpio = codec_hph_comp_gpio;
+}
+
+static void msm8x16_wcd_compute_impedance(struct snd_soc_codec *codec, s16 l,
+ s16 r, uint32_t *zl, uint32_t *zr, bool high)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ uint32_t rl = 0, rr = 0;
+ struct wcd_imped_i_ref R = msm8x16_wcd->imped_i_ref;
+ int codec_ver = get_codec_version(msm8x16_wcd);
+
+ switch (codec_ver) {
+ case TOMBAK_1_0:
+ case TOMBAK_2_0:
+ case CONGA:
+ if (high) {
+ pr_err("%s: This plug has high range impedance\n",
+ __func__);
+ rl = (uint32_t)(((100 * (l * 400 - 200))/96) - 230);
+ rr = (uint32_t)(((100 * (r * 400 - 200))/96) - 230);
+ } else {
+ pr_err("%s: This plug has low range impedance\n",
+ __func__);
+ rl = (uint32_t)(((1000 * (l * 2 - 1))/1165) - (13/10));
+ rr = (uint32_t)(((1000 * (r * 2 - 1))/1165) - (13/10));
+ }
+ break;
+ case CAJON:
+ case CAJON_2_0:
+ case DIANGU:
+ if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHL) {
+ rr = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * r - 5)) -
+ (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
+ rl = (uint32_t)(((10000 * (R.multiplier * (10 * l - 5)))
+ - R.offset * R.gain_adj)/(R.gain_adj * 100));
+ } else if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR) {
+ rr = (uint32_t)(((10000 * (R.multiplier * (10 * r - 5)))
+ - R.offset * R.gain_adj)/(R.gain_adj * 100));
+ rl = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * l - 5))-
+ (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
+ } else if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_NONE) {
+ rr = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * r - 5)) -
+ (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
+ rl = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * l - 5))-
+ (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
+ } else {
+ rr = (uint32_t)(((10000 * (R.multiplier * (10 * r - 5)))
+ - R.offset * R.gain_adj)/(R.gain_adj * 100));
+ rl = (uint32_t)(((10000 * (R.multiplier * (10 * l - 5)))
+ - R.offset * R.gain_adj)/(R.gain_adj * 100));
+ }
+ break;
+ default:
+ pr_err("%s: No codec mentioned\n", __func__);
+ break;
+ }
+ *zl = rl;
+ *zr = rr;
+}
+
+static struct firmware_cal *msm8x16_wcd_get_hwdep_fw_cal(
+ struct snd_soc_codec *codec,
+ enum wcd_cal_type type)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd;
+ struct firmware_cal *hwdep_cal;
+
+ if (!codec) {
+ pr_err("%s: NULL codec pointer\n", __func__);
+ return NULL;
+ }
+ msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ hwdep_cal = wcdcal_get_fw_cal(msm8x16_wcd->fw_data, type);
+ if (!hwdep_cal) {
+ dev_err(codec->dev, "%s: cal not sent by %d\n",
+ __func__, type);
+ return NULL;
+ }
+ return hwdep_cal;
+}
+
+static void wcd9xxx_spmi_irq_control(struct snd_soc_codec *codec,
+ int irq, bool enable)
+{
+ if (enable)
+ wcd9xxx_spmi_enable_irq(irq);
+ else
+ wcd9xxx_spmi_disable_irq(irq);
+}
+
+static void msm8x16_mbhc_clk_setup(struct snd_soc_codec *codec,
+ bool enable)
+{
+ if (enable)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x08, 0x08);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x08, 0x00);
+}
+
+static int msm8x16_mbhc_map_btn_code_to_num(struct snd_soc_codec *codec)
+{
+ int btn_code;
+ int btn;
+
+ btn_code = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
+
+ switch (btn_code) {
+ case 0:
+ btn = 0;
+ break;
+ case 1:
+ btn = 1;
+ break;
+ case 3:
+ btn = 2;
+ break;
+ case 7:
+ btn = 3;
+ break;
+ case 15:
+ btn = 4;
+ break;
+ default:
+ btn = -EINVAL;
+ break;
+ };
+
+ return btn;
+}
+
+static bool msm8x16_spmi_lock_sleep(struct wcd_mbhc *mbhc, bool lock)
+{
+ if (lock)
+ return wcd9xxx_spmi_lock_sleep();
+ wcd9xxx_spmi_unlock_sleep();
+ return 0;
+}
+
+static bool msm8x16_wcd_micb_en_status(struct wcd_mbhc *mbhc, int micb_num)
+{
+ if (micb_num == MIC_BIAS_1)
+ return (snd_soc_read_wrapper(mbhc->codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN) &
+ 0x80);
+ if (micb_num == MIC_BIAS_2)
+ return (snd_soc_read_wrapper(mbhc->codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN) &
+ 0x80);
+ return false;
+}
+
+static void msm8x16_wcd_enable_master_bias(struct snd_soc_codec *codec,
+ bool enable)
+{
+ if (enable)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL,
+ 0x30, 0x30);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL,
+ 0x30, 0x00);
+}
+
+static void msm8x16_wcd_mbhc_common_micb_ctrl(struct snd_soc_codec *codec,
+ int event, bool enable)
+{
+ u16 reg;
+ u8 mask;
+ u8 val;
+
+ switch (event) {
+ case MBHC_COMMON_MICB_PRECHARGE:
+ reg = MSM89XX_PMIC_ANALOG_MICB_1_CTL;
+ mask = 0x60;
+ val = (enable ? 0x60 : 0x00);
+ break;
+ case MBHC_COMMON_MICB_SET_VAL:
+ reg = MSM89XX_PMIC_ANALOG_MICB_1_VAL;
+ mask = 0xFF;
+ val = (enable ? 0xC0 : 0x00);
+ break;
+ case MBHC_COMMON_MICB_TAIL_CURR:
+ reg = MSM89XX_PMIC_ANALOG_MICB_1_EN;
+ mask = 0x04;
+ val = (enable ? 0x04 : 0x00);
+ break;
+ };
+ snd_soc_update_bits_wrapper(codec, reg, mask, val);
+}
+
+static void msm8x16_wcd_mbhc_internal_micbias_ctrl(struct snd_soc_codec *codec,
+ int micbias_num, bool enable)
+{
+ if (micbias_num == 1) {
+ if (enable)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS,
+ 0x10, 0x10);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS,
+ 0x10, 0x00);
+ }
+}
+
+static bool msm8x16_wcd_mbhc_hph_pa_on_status(struct snd_soc_codec *codec)
+{
+ return (snd_soc_read_wrapper(codec, MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN) &
+ 0x30) ? true : false;
+}
+
+static void msm8x16_wcd_mbhc_program_btn_thr(struct snd_soc_codec *codec,
+ s16 *btn_low, s16 *btn_high,
+ int num_btn, bool is_micbias)
+{
+ int i;
+ u32 course, fine, reg_val;
+ u16 reg_addr = MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL;
+ s16 *btn_voltage;
+
+ btn_voltage = ((is_micbias) ? btn_high : btn_low);
+
+ for (i = 0; i < num_btn; i++) {
+ course = (btn_voltage[i] / MSM89XX_MBHC_BTN_COARSE_ADJ);
+ fine = ((btn_voltage[i] % MSM89XX_MBHC_BTN_COARSE_ADJ) /
+ MSM89XX_MBHC_BTN_FINE_ADJ);
+
+ reg_val = (course << 5) | (fine << 2);
+ snd_soc_update_bits_wrapper(codec, reg_addr, 0xFC, reg_val);
+ pr_err("%s: course: %d fine: %d reg_addr: %x reg_val: %x\n",
+ __func__, course, fine, reg_addr, reg_val);
+ reg_addr++;
+ }
+}
+
+static void msm8x16_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
+ uint32_t *zr)
+{
+ struct snd_soc_codec *codec = mbhc->codec;
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ s16 impedance_l, impedance_r;
+ s16 impedance_l_fixed;
+ s16 reg0, reg1, reg2, reg3, reg4;
+ bool high = false;
+ bool min_range_used = false;
+
+ WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
+ reg0 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER);
+ reg1 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL);
+ reg2 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2);
+ reg3 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN);
+ reg4 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL);
+
+ msm8x16_wcd->imped_det_pin = WCD_MBHC_DET_BOTH;
+ mbhc->hph_type = WCD_MBHC_HPH_NONE;
+
+ /* disable FSM and micbias and enable pullup*/
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0xA5, 0x25);
+ /*
+ * Enable legacy electrical detection current sources
+ * and disable fast ramp and enable manual switching
+ * of extra capacitance
+ */
+ pr_err("%s: Setup for impedance det\n", __func__);
+
+ msm8x16_set_ref_current(codec, I_h4_UA);
+
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2,
+ 0x06, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER,
+ 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL,
+ 0x02, 0x00);
+
+ pr_err("%s: Start performing impedance detection\n",
+ __func__);
+
+ wcd_mbhc_meas_imped(codec, &impedance_l, &impedance_r);
+
+ if (impedance_l > 2 || impedance_r > 2) {
+ high = true;
+ if (!mbhc->mbhc_cfg->mono_stero_detection) {
+ /* Set ZDET_CHG to 0 to discharge ramp */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x00);
+ /* wait 40ms for the discharge ramp to complete */
+ usleep_range(40000, 40100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x03, 0x00);
+ msm8x16_wcd->imped_det_pin = (impedance_l > 2 &&
+ impedance_r > 2) ?
+ WCD_MBHC_DET_NONE :
+ ((impedance_l > 2) ?
+ WCD_MBHC_DET_HPHR :
+ WCD_MBHC_DET_HPHL);
+ if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_NONE)
+ goto exit;
+ } else {
+ if (get_codec_version(msm8x16_wcd) >= CAJON) {
+ if (impedance_l == 63 && impedance_r == 63) {
+ pr_err("%s: HPHL and HPHR are floating\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_NONE;
+ mbhc->hph_type = WCD_MBHC_HPH_NONE;
+ } else if (impedance_l == 63
+ && impedance_r < 63) {
+ pr_err("%s: Mono HS with HPHL floating\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_HPHR;
+ mbhc->hph_type = WCD_MBHC_HPH_MONO;
+ } else if (impedance_r == 63 &&
+ impedance_l < 63) {
+ pr_err("%s: Mono HS with HPHR floating\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_HPHL;
+ mbhc->hph_type = WCD_MBHC_HPH_MONO;
+ } else if (impedance_l > 3 && impedance_r > 3 &&
+ (impedance_l == impedance_r)) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2,
+ 0x06, 0x06);
+ wcd_mbhc_meas_imped(codec, &impedance_l,
+ &impedance_r);
+ if (impedance_r == impedance_l)
+ pr_err("%s: Mono Headset\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_NONE;
+ mbhc->hph_type =
+ WCD_MBHC_HPH_MONO;
+ } else {
+ pr_err("%s: STEREO headset is found\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_BOTH;
+ mbhc->hph_type = WCD_MBHC_HPH_STEREO;
+ }
+ }
+ }
+ }
+
+ msm8x16_set_ref_current(codec, I_pt5_UA);
+ msm8x16_set_ref_current(codec, I_14_UA);
+
+ /* Enable RAMP_L, RAMP_R & ZDET_CHG*/
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x03, 0x03);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x02);
+ /* wait for 50msec for the HW to apply ramp on HPHL and HPHR */
+ usleep_range(50000, 50100);
+ /* Enable ZDET_DISCHG_CAP_CTL to add extra capacitance */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x01, 0x01);
+ /* wait for 5msec for the voltage to get stable */
+ usleep_range(5000, 5100);
+
+
+ wcd_mbhc_meas_imped(codec, &impedance_l, &impedance_r);
+
+ min_range_used = msm8x16_adj_ref_current(codec,
+ &impedance_l, &impedance_r);
+ if (!mbhc->mbhc_cfg->mono_stero_detection) {
+ /* Set ZDET_CHG to 0 to discharge ramp */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x00);
+ /* wait for 40msec for the capacitor to discharge */
+ usleep_range(40000, 40100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x03, 0x00);
+ goto exit;
+ }
+
+ /* we are setting ref current to the minimun range or the measured
+ * value larger than the minimum value, so min_range_used is true.
+ * If the headset is mono headset with either HPHL or HPHR floating
+ * then we have already done the mono stereo detection and do not
+ * need to continue further.
+ */
+
+ if (!min_range_used ||
+ msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHL ||
+ msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR)
+ goto exit;
+
+
+ /* Disable Set ZDET_CONN_RAMP_L and enable ZDET_CONN_FIXED_L */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x02, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL,
+ 0x02, 0x02);
+ /* Set ZDET_CHG to 0 */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x00);
+ /* wait for 40msec for the capacitor to discharge */
+ usleep_range(40000, 40100);
+
+ /* Set ZDET_CONN_RAMP_R to 0 */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x01, 0x00);
+ /* Enable ZDET_L_MEAS_EN */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x08, 0x08);
+ /* wait for 2msec for the HW to compute left inpedance value */
+ usleep_range(2000, 2100);
+ /* Read Left impedance value from Result1 */
+ impedance_l_fixed = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
+ /* Disable ZDET_L_MEAS_EN */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x08, 0x00);
+ /*
+ * Assume impedance_l is L1, impedance_l_fixed is L2.
+ * If the following condition is met, we can take this
+ * headset as mono one with impedance of L2.
+ * Otherwise, take it as stereo with impedance of L1.
+ * Condition:
+ * abs[(L2-0.5L1)/(L2+0.5L1)] < abs [(L2-L1)/(L2+L1)]
+ */
+ if ((abs(impedance_l_fixed - impedance_l/2) *
+ (impedance_l_fixed + impedance_l)) >=
+ (abs(impedance_l_fixed - impedance_l) *
+ (impedance_l_fixed + impedance_l/2))) {
+ pr_err("%s: STEREO plug type detected\n",
+ __func__);
+ mbhc->hph_type = WCD_MBHC_HPH_STEREO;
+ } else {
+ pr_err("%s: MONO plug type detected\n",
+ __func__);
+ mbhc->hph_type = WCD_MBHC_HPH_MONO;
+ impedance_l = impedance_l_fixed;
+ }
+ /* Enable ZDET_CHG */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x02);
+ /* wait for 10msec for the capacitor to charge */
+ usleep_range(10000, 10100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL,
+ 0x02, 0x00);
+ /* Set ZDET_CHG to 0 to discharge HPHL */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x00);
+ /* wait for 40msec for the capacitor to discharge */
+ usleep_range(40000, 40100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x02, 0x00);
+
+exit:
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, reg4);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, reg3);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL, reg1);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, reg0);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, reg2);
+ msm8x16_wcd_compute_impedance(codec, impedance_l, impedance_r,
+ zl, zr, high);
+
+ pr_err("%s: RL %d ohm, RR %d ohm\n", __func__, *zl, *zr);
+ pr_err("%s: Impedance detection completed\n", __func__);
+}
+
+static int msm8x16_register_notifier(struct snd_soc_codec *codec,
+ struct notifier_block *nblock,
+ bool enable)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(codec);
+
+ if (enable)
+ return blocking_notifier_chain_register(&msm8x16_wcd->notifier,
+ nblock);
+ return blocking_notifier_chain_unregister(
+ &msm8x16_wcd->notifier, nblock);
+}
+
+static int msm8x16_wcd_request_irq(struct snd_soc_codec *codec,
+ int irq, irq_handler_t handler,
+ const char *name, void *data)
+{
+ return wcd9xxx_spmi_request_irq(irq, handler, name, data);
+}
+
+static int msm8x16_wcd_free_irq(struct snd_soc_codec *codec,
+ int irq, void *data)
+{
+ return wcd9xxx_spmi_free_irq(irq, data);
+}
+
+static const struct wcd_mbhc_cb mbhc_cb = {
+ .enable_mb_source = msm8x16_wcd_enable_ext_mb_source,
+ .trim_btn_reg = msm8x16_trim_btn_reg,
+ .compute_impedance = msm8x16_wcd_mbhc_calc_impedance,
+ .set_micbias_value = msm8x16_wcd_set_micb_v,
+ .set_auto_zeroing = msm8x16_wcd_set_auto_zeroing,
+ .get_hwdep_fw_cal = msm8x16_wcd_get_hwdep_fw_cal,
+ .set_cap_mode = msm8x16_wcd_configure_cap,
+ .register_notifier = msm8x16_register_notifier,
+ .request_irq = msm8x16_wcd_request_irq,
+ .irq_control = wcd9xxx_spmi_irq_control,
+ .free_irq = msm8x16_wcd_free_irq,
+ .clk_setup = msm8x16_mbhc_clk_setup,
+ .map_btn_code_to_num = msm8x16_mbhc_map_btn_code_to_num,
+ .lock_sleep = msm8x16_spmi_lock_sleep,
+ .micbias_enable_status = msm8x16_wcd_micb_en_status,
+ .mbhc_bias = msm8x16_wcd_enable_master_bias,
+ .mbhc_common_micb_ctrl = msm8x16_wcd_mbhc_common_micb_ctrl,
+ .micb_internal = msm8x16_wcd_mbhc_internal_micbias_ctrl,
+ .hph_pa_on_status = msm8x16_wcd_mbhc_hph_pa_on_status,
+ .set_btn_thr = msm8x16_wcd_mbhc_program_btn_thr,
+ .extn_use_mb = msm8x16_wcd_use_mb,
+};
+
+static const uint32_t wcd_imped_val[] = {4, 8, 12, 13, 16,
+ 20, 24, 28, 32,
+ 36, 40, 44, 48};
+
+void msm8x16_notifier_call(struct snd_soc_codec *codec,
+ const enum wcd_notify_event event)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s: notifier call event %d\n", __func__, event);
+ blocking_notifier_call_chain(&msm8x16_wcd->notifier, event,
+ &msm8x16_wcd->mbhc);
+}
+
+static void msm8x16_wcd_boost_on(struct snd_soc_codec *codec)
+{
+ u8 dest = 0x00;
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+
+ if ((dest & MASK_MSB_BIT) == 0) {
+ pr_err("PMIC MBG not ON, enable codec hw_en MB bit again\n");
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL, 0x30);
+ /* Allow 1ms for PMIC MBG state to be updated */
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3,
+ 0x0F, 0x0F);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3,
+ 0x0F);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL,
+ 0x30);
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0) {
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_CURRENT_LIMIT,
+ 0x82);
+ } else {
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_CURRENT_LIMIT,
+ 0xA2);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0x69, 0x69);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG,
+ 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO,
+ 0x88, 0x88);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x03, 0x03);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL,
+ 0xE1, 0xE1);
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x20);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0xDF, 0xDF);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0x40, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0x80, 0x80);
+ usleep_range(500, 510);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0x40, 0x40);
+ usleep_range(500, 510);
+ }
+}
+
+static void msm8x16_wcd_boost_off(struct snd_soc_codec *codec)
+{
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0xDF, 0x5F);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x00);
+}
+
+static void msm8x16_wcd_bypass_on(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0) {
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3,
+ 0x07);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x40, 0x40);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0xDF, 0xDF);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x20, 0x20);
+ }
+}
+
+static void msm8x16_wcd_bypass_off(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x02, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x40, 0x00);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x20, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x00);
+ }
+}
+
+static void msm8x16_wcd_boost_mode_sequence(struct snd_soc_codec *codec,
+ int flag)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (flag == EAR_PMU) {
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->ear_pa_boost_set) {
+ msm8x16_wcd_boost_off(codec);
+ msm8x16_wcd_bypass_on(codec);
+ }
+ break;
+ case BOOST_ALWAYS:
+ msm8x16_wcd_boost_on(codec);
+ break;
+ case BYPASS_ALWAYS:
+ msm8x16_wcd_bypass_on(codec);
+ break;
+ case BOOST_ON_FOREVER:
+ msm8x16_wcd_boost_on(codec);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ } else if (flag == EAR_PMD) {
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->ear_pa_boost_set)
+ msm8x16_wcd_bypass_off(codec);
+ break;
+ case BOOST_ALWAYS:
+ msm8x16_wcd_boost_off(codec);
+ /* 80ms for EAR boost to settle down */
+ msleep(80);
+ break;
+ case BYPASS_ALWAYS:
+ /* nothing to do as bypass on always */
+ break;
+ case BOOST_ON_FOREVER:
+ /* nothing to do as boost on forever */
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ } else if (flag == SPK_PMU) {
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->spk_boost_set) {
+ msm8x16_wcd_bypass_off(codec);
+ msm8x16_wcd_boost_on(codec);
+ }
+ break;
+ case BOOST_ALWAYS:
+ msm8x16_wcd_boost_on(codec);
+ break;
+ case BYPASS_ALWAYS:
+ msm8x16_wcd_bypass_on(codec);
+ break;
+ case BOOST_ON_FOREVER:
+ msm8x16_wcd_boost_on(codec);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ } else if (flag == SPK_PMD) {
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->spk_boost_set) {
+ msm8x16_wcd_boost_off(codec);
+ /*
+ * Add 40 ms sleep for the spk
+ * boost to settle down
+ */
+ msleep(40);
+ }
+ break;
+ case BOOST_ALWAYS:
+ msm8x16_wcd_boost_off(codec);
+ /*
+ * Add 40 ms sleep for the spk
+ * boost to settle down
+ */
+ msleep(40);
+ break;
+ case BYPASS_ALWAYS:
+ /* nothing to do as bypass on always */
+ break;
+ case BOOST_ON_FOREVER:
+ /* nothing to do as boost on forever */
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ }
+}
+
+static int msm8x16_wcd_dt_parse_vreg_info(struct device *dev,
+ struct msm8x16_wcd_regulator *vreg, const char *vreg_name,
+ bool ondemand)
+{
+ int len, ret = 0;
+ const __be32 *prop;
+ char prop_name[CODEC_DT_MAX_PROP_SIZE];
+ struct device_node *regnode = NULL;
+ u32 prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
+ vreg_name);
+ regnode = of_parse_phandle(dev->of_node, prop_name, 0);
+
+ if (!regnode) {
+ dev_err(dev, "Looking up %s property in node %s failed\n",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+
+ dev_err(dev, "Looking up %s property in node %s\n",
+ prop_name, dev->of_node->full_name);
+
+ vreg->name = vreg_name;
+ vreg->ondemand = ondemand;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,%s-voltage", vreg_name);
+ prop = of_get_property(dev->of_node, prop_name, &len);
+
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ dev_err(dev, "%s %s property\n",
+ prop ? "invalid format" : "no", prop_name);
+ return -EINVAL;
+ }
+ vreg->min_uv = be32_to_cpup(&prop[0]);
+ vreg->max_uv = be32_to_cpup(&prop[1]);
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,%s-current", vreg_name);
+
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -EFAULT;
+ }
+ vreg->optimum_ua = prop_val;
+
+ dev_err(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n\n", vreg->name,
+ vreg->min_uv, vreg->max_uv, vreg->optimum_ua, vreg->ondemand);
+ return 0;
+}
+
+static void msm8x16_wcd_dt_parse_boost_info(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+ const char *prop_name = "qcom,cdc-boost-voltage";
+ int boost_voltage, ret;
+
+ ret = of_property_read_u32(codec->dev->of_node, prop_name,
+ &boost_voltage);
+ if (ret) {
+ dev_err(codec->dev, "Looking up %s property in node %s failed\n",
+ prop_name, codec->dev->of_node->full_name);
+ boost_voltage = DEFAULT_BOOST_VOLTAGE;
+ }
+ if (boost_voltage < MIN_BOOST_VOLTAGE ||
+ boost_voltage > MAX_BOOST_VOLTAGE) {
+ dev_err(codec->dev,
+ "Incorrect boost voltage. Reverting to default\n");
+ boost_voltage = DEFAULT_BOOST_VOLTAGE;
+ }
+
+ msm8x16_wcd_priv->boost_voltage =
+ VOLTAGE_CONVERTER(boost_voltage, MIN_BOOST_VOLTAGE,
+ BOOST_VOLTAGE_STEP);
+ dev_err(codec->dev, "Boost voltage value is: %d\n",
+ boost_voltage);
+}
+
+static void msm8x16_wcd_dt_parse_micbias_info(struct device *dev,
+ struct wcd9xxx_micbias_setting *micbias)
+{
+ const char *prop_name = "qcom,cdc-micbias-cfilt-mv";
+ int ret;
+
+ ret = of_property_read_u32(dev->of_node, prop_name,
+ &micbias->cfilt1_mv);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ micbias->cfilt1_mv = MICBIAS_DEFAULT_VAL;
+ }
+}
+
+static struct msm8x16_wcd_pdata *msm8x16_wcd_populate_dt_pdata(
+ struct device *dev)
+{
+ struct msm8x16_wcd_pdata *pdata;
+ int ret, static_cnt, ond_cnt, idx, i;
+ const char *name = NULL;
+ const char *static_prop_name = "qcom,cdc-static-supplies";
+ const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return NULL;
+
+ static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
+ if (IS_ERR_VALUE(static_cnt)) {
+ dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
+ static_cnt);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* On-demand supply list is an optional property */
+ ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
+ if (IS_ERR_VALUE(ond_cnt))
+ ond_cnt = 0;
+
+ WARN_ON(static_cnt <= 0 || ond_cnt < 0);
+ if ((static_cnt + ond_cnt) > ARRAY_SIZE(pdata->regulator)) {
+ dev_err(dev, "%s: Num of supplies %u > max supported %zd\n",
+ __func__, (static_cnt + ond_cnt),
+ ARRAY_SIZE(pdata->regulator));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ for (idx = 0; idx < static_cnt; idx++) {
+ ret = of_property_read_string_index(dev->of_node,
+ static_prop_name, idx,
+ &name);
+ if (ret) {
+ dev_err(dev, "%s: of read string %s idx %d error %d\n",
+ __func__, static_prop_name, idx, ret);
+ goto err;
+ }
+
+ dev_err(dev, "%s: Found static cdc supply %s\n", __func__,
+ name);
+ ret = msm8x16_wcd_dt_parse_vreg_info(dev,
+ &pdata->regulator[idx],
+ name, false);
+ if (ret) {
+ dev_err(dev, "%s:err parsing vreg for %s idx %d\n",
+ __func__, name, idx);
+ goto err;
+ }
+ }
+
+ for (i = 0; i < ond_cnt; i++, idx++) {
+ ret = of_property_read_string_index(dev->of_node, ond_prop_name,
+ i, &name);
+ if (ret) {
+ dev_err(dev, "%s: err parsing on_demand for %s idx %d\n",
+ __func__, ond_prop_name, i);
+ goto err;
+ }
+
+ dev_err(dev, "%s: Found on-demand cdc supply %s\n", __func__,
+ name);
+ ret = msm8x16_wcd_dt_parse_vreg_info(dev,
+ &pdata->regulator[idx],
+ name, true);
+ if (ret) {
+ dev_err(dev, "%s: err parsing vreg on_demand for %s idx %d\n",
+ __func__, name, idx);
+ goto err;
+ }
+ }
+ msm8x16_wcd_dt_parse_micbias_info(dev, &pdata->micbias);
+ return pdata;
+err:
+ devm_kfree(dev, pdata);
+ dev_err(dev, "%s: Failed to populate DT data ret = %d\n",
+ __func__, ret);
+ return NULL;
+}
+
+static int msm8x16_wcd_codec_enable_on_demand_supply(
+ struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ int ret = 0;
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ struct on_demand_supply *supply;
+
+ if (w->shift >= ON_DEMAND_SUPPLIES_MAX) {
+ dev_err(codec->dev, "%s: error index > MAX Demand supplies",
+ __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+ dev_err(codec->dev, "%s: supply: %s event: %d ref: %d\n",
+ __func__, on_demand_supply_name[w->shift], event,
+ atomic_read(&msm8x16_wcd->on_demand_list[w->shift].ref));
+
+ supply = &msm8x16_wcd->on_demand_list[w->shift];
+ WARN_ONCE(!supply->supply, "%s isn't defined\n",
+ on_demand_supply_name[w->shift]);
+ if (!supply->supply) {
+ dev_err(codec->dev, "%s: err supply not present ond for %d",
+ __func__, w->shift);
+ goto out;
+ }
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (atomic_inc_return(&supply->ref) == 1)
+ ret = regulator_enable(supply->supply);
+ if (ret)
+ dev_err(codec->dev, "%s: Failed to enable %s\n",
+ __func__,
+ on_demand_supply_name[w->shift]);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (atomic_read(&supply->ref) == 0) {
+ dev_err(codec->dev, "%s: %s supply has been disabled.\n",
+ __func__, on_demand_supply_name[w->shift]);
+ goto out;
+ }
+ if (atomic_dec_return(&supply->ref) == 0)
+ ret = regulator_disable(supply->supply);
+ if (ret)
+ dev_err(codec->dev, "%s: Failed to disable %s\n",
+ __func__,
+ on_demand_supply_name[w->shift]);
+ break;
+ default:
+ break;
+ }
+out:
+ return ret;
+}
+
+static int msm8x16_wcd_codec_enable_clock_block(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ if (enable) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_MCLK_CTL, 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_PDM_CTL, 0x03, 0x03);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL, 0x30, 0x30);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL, 0x0C, 0x0C);
+ if (pdata->mclk_freq == MCLK_RATE_12P288MHZ)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TOP_CTL, 0x01, 0x00);
+ else if (pdata->mclk_freq == MCLK_RATE_9P6MHZ)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TOP_CTL, 0x01, 0x01);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL, 0x0C, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_PDM_CTL, 0x03, 0x00);
+
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: event = %d\n", __func__, event);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x16_wcd_codec_enable_clock_block(codec, 1);
+ if (!(strcmp(w->name, "EAR CP"))) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x80);
+ msm8x16_wcd_boost_mode_sequence(codec, EAR_PMU);
+ } else if (get_codec_version(msm8x16_wcd) == DIANGU) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x80);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0xC0, 0xC0);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ if (!(strcmp(w->name, "EAR CP"))) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x00);
+ if (msm8x16_wcd->boost_option != BOOST_ALWAYS) {
+ dev_err(codec->dev,
+ "%s: boost_option:%d, tear down ear\n",
+ __func__, msm8x16_wcd->boost_option);
+ msm8x16_wcd_boost_mode_sequence(codec, EAR_PMD);
+ }
+ /*
+ * Reset pa select bit from ear to hph after ear pa
+ * is disabled and HPH DAC disable to reduce ear
+ * turn off pop and avoid HPH pop in concurrency
+ */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x80, 0x00);
+ } else {
+ if (get_codec_version(msm8x16_wcd) < DIANGU)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x40, 0x00);
+ if (msm8x16_wcd->rx_bias_count == 0)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x00);
+ dev_err(codec->dev, "%s: rx_bias_count = %d\n",
+ __func__, msm8x16_wcd->rx_bias_count);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_ear_pa_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] =
+ (msm8x16_wcd->ear_pa_boost_set ? 1 : 0);
+ dev_err(codec->dev, "%s: msm8x16_wcd->ear_pa_boost_set = %d\n",
+ __func__, msm8x16_wcd->ear_pa_boost_set);
+ return 0;
+}
+
+static int msm8x16_wcd_ear_pa_boost_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+ msm8x16_wcd->ear_pa_boost_set =
+ (ucontrol->value.integer.value[0] ? true : false);
+ return 0;
+}
+
+static int msm8x16_wcd_pa_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+ ear_pa_gain = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL);
+
+ ear_pa_gain = (ear_pa_gain >> 5) & 0x1;
+
+ if (ear_pa_gain == 0x00) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (ear_pa_gain == 0x01) {
+ ucontrol->value.integer.value[0] = 1;
+ } else {
+ dev_err(codec->dev, "%s: ERROR: Unsupported Ear Gain = 0x%x\n",
+ __func__, ear_pa_gain);
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = ear_pa_gain;
+ dev_err(codec->dev, "%s: ear_pa_gain = 0x%x\n",
+ __func__, ear_pa_gain);
+ return 0;
+}
+
+static int msm8x16_wcd_loopback_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ return pdata->lb_mode;
+}
+
+static int msm8x16_wcd_loopback_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ pdata->lb_mode = false;
+ break;
+ case 1:
+ pdata->lb_mode = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int msm8x16_wcd_pa_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ ear_pa_gain = 0x00;
+ break;
+ case 1:
+ ear_pa_gain = 0x20;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, ear_pa_gain);
+ return 0;
+}
+
+static int msm8x16_wcd_hph_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (msm8x16_wcd->hph_mode == NORMAL_MODE) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ ucontrol->value.integer.value[0] = 1;
+ } else {
+ dev_err(codec->dev, "%s: ERROR: Default HPH Mode= %d\n",
+ __func__, msm8x16_wcd->hph_mode);
+ }
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->hph_mode = %d\n", __func__,
+ msm8x16_wcd->hph_mode);
+ return 0;
+}
+
+static int msm8x16_wcd_hph_mode_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ msm8x16_wcd->hph_mode = NORMAL_MODE;
+ break;
+ case 1:
+ if (get_codec_version(msm8x16_wcd) >= DIANGU)
+ msm8x16_wcd->hph_mode = HD2_MODE;
+ break;
+ default:
+ msm8x16_wcd->hph_mode = NORMAL_MODE;
+ break;
+ }
+ dev_err(codec->dev, "%s: msm8x16_wcd->hph_mode_set = %d\n",
+ __func__, msm8x16_wcd->hph_mode);
+ return 0;
+}
+
+static int msm8x16_wcd_boost_option_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (msm8x16_wcd->boost_option == BOOST_SWITCH) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (msm8x16_wcd->boost_option == BOOST_ALWAYS) {
+ ucontrol->value.integer.value[0] = 1;
+ } else if (msm8x16_wcd->boost_option == BYPASS_ALWAYS) {
+ ucontrol->value.integer.value[0] = 2;
+ } else if (msm8x16_wcd->boost_option == BOOST_ON_FOREVER) {
+ ucontrol->value.integer.value[0] = 3;
+ } else {
+ dev_err(codec->dev, "%s: ERROR: Unsupported Boost option= %d\n",
+ __func__, msm8x16_wcd->boost_option);
+ return -EINVAL;
+ }
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->boost_option = %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ return 0;
+}
+
+static int msm8x16_wcd_boost_option_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ msm8x16_wcd->boost_option = BOOST_SWITCH;
+ break;
+ case 1:
+ msm8x16_wcd->boost_option = BOOST_ALWAYS;
+ break;
+ case 2:
+ msm8x16_wcd->boost_option = BYPASS_ALWAYS;
+ msm8x16_wcd_bypass_on(codec);
+ break;
+ case 3:
+ msm8x16_wcd->boost_option = BOOST_ON_FOREVER;
+ msm8x16_wcd_boost_on(codec);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ return -EINVAL;
+ }
+ dev_err(codec->dev, "%s: msm8x16_wcd->boost_option_set = %d\n",
+ __func__, msm8x16_wcd->boost_option);
+ return 0;
+}
+
+static int msm8x16_wcd_ext_spk_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (msm8x16_wcd->ext_spk_boost_set == false)
+ ucontrol->value.integer.value[0] = 0;
+ else
+ ucontrol->value.integer.value[0] = 1;
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->ext_spk_boost_set = %d\n",
+ __func__, msm8x16_wcd->ext_spk_boost_set);
+ return 0;
+}
+
+static int msm8x16_wcd_ext_spk_boost_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ msm8x16_wcd->ext_spk_boost_set = false;
+ break;
+ case 1:
+ msm8x16_wcd->ext_spk_boost_set = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ dev_err(codec->dev, "%s: msm8x16_wcd->spk_boost_set = %d\n",
+ __func__, msm8x16_wcd->spk_boost_set);
+ return 0;
+}
+static int msm8x16_wcd_get_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ (snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_CTL + 64 * iir_idx)) &
+ (1 << band_idx)) != 0;
+
+ dev_err(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm8x16_wcd_put_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+
+ /* Mask first 5 bits, 6-8 are reserved */
+ snd_soc_update_bits_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_CTL + 64 * iir_idx),
+ (1 << band_idx), (value << band_idx));
+
+ dev_err(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx,
+ ((snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_CTL + 64 * iir_idx)) &
+ (1 << band_idx)) != 0));
+
+ return 0;
+}
+static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ int coeff_idx)
+{
+ uint32_t value = 0;
+
+ /* Address does not automatically update if reading */
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t)) & 0x7F);
+
+ value |= snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx));
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 1) & 0x7F);
+
+ value |= (snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8);
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 2) & 0x7F);
+
+ value |= (snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16);
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 3) & 0x7F);
+
+ /* Mask bits top 2 bits since they are reserved */
+ value |= ((snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL
+ + 64 * iir_idx)) & 0x3f) << 24);
+
+ return value;
+
+}
+
+static int msm8x16_wcd_get_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0);
+ ucontrol->value.integer.value[1] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1);
+ ucontrol->value.integer.value[2] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2);
+ ucontrol->value.integer.value[3] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3);
+ ucontrol->value.integer.value[4] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4);
+
+ dev_err(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[1],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[2],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[3],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[4]);
+ return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ uint32_t value)
+{
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value & 0xFF));
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 8) & 0xFF);
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 16) & 0xFF);
+
+ /* Mask top 2 bits, 7-8 are reserved */
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 24) & 0x3F);
+
+}
+
+static int msm8x16_wcd_put_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ /* Mask top bit it is reserved */
+ /* Updates addr automatically for each B2 write */
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[0]);
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[1]);
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[2]);
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[3]);
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[4]);
+
+ dev_err(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4));
+ return 0;
+}
+
+static int msm8x16_wcd_compander_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ int comp_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int rx_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->comp[%d]_enabled[%d] = %d\n",
+ __func__, comp_idx, rx_idx,
+ msm8x16_wcd->comp_enabled[rx_idx]);
+
+ ucontrol->value.integer.value[0] = msm8x16_wcd->comp_enabled[rx_idx];
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ return 0;
+}
+
+static int msm8x16_wcd_compander_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ int comp_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int rx_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ if (get_codec_version(msm8x16_wcd) >= DIANGU) {
+ if (!value)
+ msm8x16_wcd->comp_enabled[rx_idx] = 0;
+ else
+ msm8x16_wcd->comp_enabled[rx_idx] = comp_idx;
+ }
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->comp[%d]_enabled[%d] = %d\n",
+ __func__, comp_idx, rx_idx,
+ msm8x16_wcd->comp_enabled[rx_idx]);
+
+ return 0;
+}
+
+static const char * const msm8x16_wcd_loopback_mode_ctrl_text[] = {
+ "DISABLE", "ENABLE"};
+static const struct soc_enum msm8x16_wcd_loopback_mode_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_loopback_mode_ctrl_text),
+};
+
+static const char * const msm8x16_wcd_ear_pa_boost_ctrl_text[] = {
+ "DISABLE", "ENABLE"};
+static const struct soc_enum msm8x16_wcd_ear_pa_boost_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_ear_pa_boost_ctrl_text),
+};
+
+static const char * const msm8x16_wcd_ear_pa_gain_text[] = {
+ "POS_1P5_DB", "POS_6_DB"};
+static const struct soc_enum msm8x16_wcd_ear_pa_gain_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_ear_pa_gain_text),
+};
+
+static const char * const msm8x16_wcd_boost_option_ctrl_text[] = {
+ "BOOST_SWITCH", "BOOST_ALWAYS", "BYPASS_ALWAYS",
+ "BOOST_ON_FOREVER"};
+static const struct soc_enum msm8x16_wcd_boost_option_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(4, msm8x16_wcd_boost_option_ctrl_text),
+};
+static const char * const msm8x16_wcd_spk_boost_ctrl_text[] = {
+ "DISABLE", "ENABLE"};
+static const struct soc_enum msm8x16_wcd_spk_boost_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_spk_boost_ctrl_text),
+};
+
+static const char * const msm8x16_wcd_ext_spk_boost_ctrl_text[] = {
+ "DISABLE", "ENABLE"};
+static const struct soc_enum msm8x16_wcd_ext_spk_boost_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_ext_spk_boost_ctrl_text),
+};
+
+static const char * const msm8x16_wcd_hph_mode_ctrl_text[] = {
+ "NORMAL", "HD2"};
+static const struct soc_enum msm8x16_wcd_hph_mode_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(msm8x16_wcd_hph_mode_ctrl_text),
+ msm8x16_wcd_hph_mode_ctrl_text),
+};
+
+/*cut of frequency for high pass filter*/
+static const char * const cf_text[] = {
+ "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
+};
+
+static const struct soc_enum cf_dec1_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_TX1_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec2_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_TX2_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_rxmix1_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_RX1_B4_CTL, 0, 3, cf_text);
+
+static const struct soc_enum cf_rxmix2_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_RX2_B4_CTL, 0, 3, cf_text);
+
+static const struct soc_enum cf_rxmix3_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_RX3_B4_CTL, 0, 3, cf_text);
+
+static const struct snd_kcontrol_new msm8x16_wcd_snd_controls[] = {
+
+ SOC_ENUM_EXT("RX HPH Mode", msm8x16_wcd_hph_mode_ctl_enum[0],
+ msm8x16_wcd_hph_mode_get, msm8x16_wcd_hph_mode_set),
+
+ SOC_ENUM_EXT("Boost Option", msm8x16_wcd_boost_option_ctl_enum[0],
+ msm8x16_wcd_boost_option_get, msm8x16_wcd_boost_option_set),
+
+ SOC_ENUM_EXT("EAR PA Boost", msm8x16_wcd_ear_pa_boost_ctl_enum[0],
+ msm8x16_wcd_ear_pa_boost_get, msm8x16_wcd_ear_pa_boost_set),
+
+ SOC_ENUM_EXT("EAR PA Gain", msm8x16_wcd_ear_pa_gain_enum[0],
+ msm8x16_wcd_pa_gain_get, msm8x16_wcd_pa_gain_put),
+
+ SOC_ENUM_EXT("Ext Spk Boost", msm8x16_wcd_ext_spk_boost_ctl_enum[0],
+ msm8x16_wcd_ext_spk_boost_get, msm8x16_wcd_ext_spk_boost_set),
+
+ SOC_ENUM_EXT("LOOPBACK Mode", msm8x16_wcd_loopback_mode_ctl_enum[0],
+ msm8x16_wcd_loopback_mode_get, msm8x16_wcd_loopback_mode_put),
+
+ SOC_SINGLE_TLV("ADC1 Volume", MSM89XX_PMIC_ANALOG_TX_1_EN, 3,
+ 8, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", MSM89XX_PMIC_ANALOG_TX_2_EN, 3,
+ 8, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", MSM89XX_PMIC_ANALOG_TX_3_EN, 3,
+ 8, 0, analog_gain),
+
+ SOC_SINGLE_SX_TLV("RX1 Digital Volume",
+ MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX2 Digital Volume",
+ MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX3 Digital Volume",
+ MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+
+ SOC_SINGLE_SX_TLV("DEC1 Volume",
+ MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("DEC2 Volume",
+ MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN,
+ 0, -84, 40, digital_gain),
+
+ SOC_SINGLE_SX_TLV("IIR1 INP1 Volume",
+ MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP2 Volume",
+ MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP3 Volume",
+ MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP4 Volume",
+ MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR2 INP1 Volume",
+ MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL,
+ 0, -84, 40, digital_gain),
+
+ SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+ SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+
+ SOC_SINGLE("TX1 HPF Switch",
+ MSM89XX_CDC_CORE_TX1_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX2 HPF Switch",
+ MSM89XX_CDC_CORE_TX2_MUX_CTL, 3, 1, 0),
+
+ SOC_SINGLE("RX1 HPF Switch",
+ MSM89XX_CDC_CORE_RX1_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX2 HPF Switch",
+ MSM89XX_CDC_CORE_RX2_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX3 HPF Switch",
+ MSM89XX_CDC_CORE_RX3_B5_CTL, 2, 1, 0),
+
+ SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
+ SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
+ SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
+
+ SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+
+ SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+
+ SOC_SINGLE_EXT("COMP0 RX1", COMPANDER_1, MSM89XX_RX1, 1, 0,
+ msm8x16_wcd_compander_get, msm8x16_wcd_compander_set),
+
+ SOC_SINGLE_EXT("COMP0 RX2", COMPANDER_1, MSM89XX_RX2, 1, 0,
+ msm8x16_wcd_compander_get, msm8x16_wcd_compander_set),
+};
+
+static int tombak_hph_impedance_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret;
+ uint32_t zl, zr;
+ bool hphr;
+ struct soc_multi_mixer_control *mc;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
+
+ hphr = mc->shift;
+ ret = wcd_mbhc_get_impedance(&priv->mbhc, &zl, &zr);
+ if (ret)
+ pr_err("%s: Failed to get mbhc imped", __func__);
+ pr_err("%s: zl %u, zr %u\n", __func__, zl, zr);
+ ucontrol->value.integer.value[0] = hphr ? zr : zl;
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new impedance_detect_controls[] = {
+ SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+ tombak_hph_impedance_get, NULL),
+ SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+ tombak_hph_impedance_get, NULL),
+};
+
+static int tombak_get_hph_type(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct wcd_mbhc *mbhc;
+
+ if (!priv) {
+ pr_err("%s: msm8x16-wcd private data is NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ mbhc = &priv->mbhc;
+ if (!mbhc) {
+ pr_err("%s: mbhc not initialized\n", __func__);
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = (u32) mbhc->hph_type;
+ pr_err("%s: hph_type = %u\n", __func__, mbhc->hph_type);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new hph_type_detect_controls[] = {
+ SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
+ tombak_get_hph_type, NULL),
+};
+
+static const char * const rx_mix1_text[] = {
+ "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3"
+};
+
+static const char * const rx_mix2_text[] = {
+ "ZERO", "IIR1", "IIR2"
+};
+
+static const char * const dec_mux_text[] = {
+ "ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2"
+};
+
+static const char * const dec3_mux_text[] = {
+ "ZERO", "DMIC3"
+};
+
+static const char * const dec4_mux_text[] = {
+ "ZERO", "DMIC4"
+};
+
+static const char * const adc2_mux_text[] = {
+ "ZERO", "INP2", "INP3"
+};
+
+static const char * const ext_spk_text[] = {
+ "Off", "On"
+};
+
+static const char * const wsa_spk_text[] = {
+ "ZERO", "WSA"
+};
+
+static const char * const rdac2_mux_text[] = {
+ "ZERO", "RX2", "RX1"
+};
+
+static const char * const iir_inp1_text[] = {
+ "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3"
+};
+
+static const struct soc_enum adc2_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+ ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
+
+static const struct soc_enum ext_spk_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+ ARRAY_SIZE(ext_spk_text), ext_spk_text);
+
+static const struct soc_enum wsa_spk_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+ ARRAY_SIZE(wsa_spk_text), wsa_spk_text);
+
+/* RX1 MIX1 */
+static const struct soc_enum rx_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B1_CTL,
+ 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp3_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B2_CTL,
+ 0, 6, rx_mix1_text);
+
+/* RX1 MIX2 */
+static const struct soc_enum rx_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B3_CTL,
+ 0, 3, rx_mix2_text);
+
+/* RX2 MIX1 */
+static const struct soc_enum rx2_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX2_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX2_B1_CTL,
+ 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp3_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX2_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+/* RX2 MIX2 */
+static const struct soc_enum rx2_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX2_B3_CTL,
+ 0, 3, rx_mix2_text);
+
+/* RX3 MIX1 */
+static const struct soc_enum rx3_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX3_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX3_B1_CTL,
+ 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp3_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX3_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+/* DEC */
+static const struct soc_enum dec1_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_TX_B1_CTL,
+ 0, 6, dec_mux_text);
+
+static const struct soc_enum dec2_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_TX_B1_CTL,
+ 3, 6, dec_mux_text);
+
+static const struct soc_enum dec3_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_TX3_MUX_CTL, 0,
+ ARRAY_SIZE(dec3_mux_text), dec3_mux_text);
+
+static const struct soc_enum dec4_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_TX4_MUX_CTL, 0,
+ ARRAY_SIZE(dec4_mux_text), dec4_mux_text);
+
+static const struct soc_enum rdac2_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL,
+ 0, 3, rdac2_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL,
+ 0, 6, iir_inp1_text);
+
+static const struct soc_enum iir2_inp1_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL,
+ 0, 6, iir_inp1_text);
+
+static const struct snd_kcontrol_new ext_spk_mux =
+ SOC_DAPM_ENUM("Ext Spk Switch Mux", ext_spk_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp3_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp3_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP3 Mux", rx2_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp3_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP3 Mux", rx3_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new tx_adc2_mux =
+ SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
+
+static int msm8x16_wcd_put_dec_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist =
+ dapm_kcontrol_get_wlist(kcontrol);
+ struct snd_soc_dapm_widget *w = wlist->widgets[0];
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int dec_mux, decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ u16 tx_mux_ctl_reg;
+ u8 adc_dmic_sel = 0x0;
+ int ret = 0;
+ char *dec_num;
+
+ if (ucontrol->value.enumerated.item[0] > e->items) {
+ dev_err(codec->dev, "%s: Invalid enum value: %d\n",
+ __func__, ucontrol->value.enumerated.item[0]);
+ return -EINVAL;
+ }
+ dec_mux = ucontrol->value.enumerated.item[0];
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name) {
+ dev_err(codec->dev, "%s: failed to copy string\n",
+ __func__);
+ return -ENOMEM;
+ }
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ dev_err(codec->dev, "%s: Invalid decimator = %s\n",
+ __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dec_num = strpbrk(dec_name, "12");
+ if (dec_num == NULL) {
+ dev_err(codec->dev, "%s: Invalid DEC selected\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(dec_num, 10, &decimator);
+ if (ret < 0) {
+ dev_err(codec->dev, "%s: Invalid decimator = %s\n",
+ __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dev_err(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
+ , __func__, w->name, decimator, dec_mux);
+
+ switch (decimator) {
+ case 1:
+ case 2:
+ if ((dec_mux == 4) || (dec_mux == 5))
+ adc_dmic_sel = 0x1;
+ else
+ adc_dmic_sel = 0x0;
+ break;
+ default:
+ dev_err(codec->dev, "%s: Invalid Decimator = %u\n",
+ __func__, decimator);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_mux_ctl_reg =
+ MSM89XX_CDC_CORE_TX1_MUX_CTL + 32 * (decimator - 1);
+
+ snd_soc_update_bits_wrapper(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
+
+ ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+out:
+ kfree(widget_name);
+ return ret;
+}
+
+#define MSM89XX_DEC_ENUM(xname, xenum) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_info_enum_double, \
+ .get = snd_soc_dapm_get_enum_double, \
+ .put = msm8x16_wcd_put_dec_enum, \
+ .private_value = (unsigned long)&xenum }
+
+static const struct snd_kcontrol_new dec1_mux =
+ MSM89XX_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+
+static const struct snd_kcontrol_new dec2_mux =
+ MSM89XX_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+
+static const struct snd_kcontrol_new dec3_mux =
+ SOC_DAPM_ENUM("DEC3 MUX Mux", dec3_mux_enum);
+
+static const struct snd_kcontrol_new dec4_mux =
+ SOC_DAPM_ENUM("DEC4 MUX Mux", dec4_mux_enum);
+
+static const struct snd_kcontrol_new rdac2_mux =
+ SOC_DAPM_ENUM("RDAC2 MUX Mux", rdac2_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp1_mux =
+ SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+
+static const char * const ear_text[] = {
+ "ZERO", "Switch",
+};
+
+static const struct soc_enum ear_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(ear_text), ear_text);
+
+static const struct snd_kcontrol_new ear_pa_mux[] = {
+ SOC_DAPM_ENUM("EAR_S", ear_enum)
+};
+
+static const struct snd_kcontrol_new wsa_spk_mux[] = {
+ SOC_DAPM_ENUM("WSA Spk Switch", wsa_spk_enum)
+};
+
+static const struct snd_kcontrol_new iir2_inp1_mux =
+ SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
+
+static const char * const hph_text[] = {
+ "ZERO", "Switch",
+};
+
+static const struct soc_enum hph_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hph_text), hph_text);
+
+static const struct snd_kcontrol_new hphl_mux[] = {
+ SOC_DAPM_ENUM("HPHL", hph_enum)
+};
+
+static const struct snd_kcontrol_new hphr_mux[] = {
+ SOC_DAPM_ENUM("HPHR", hph_enum)
+};
+
+static const struct snd_kcontrol_new spkr_mux[] = {
+ SOC_DAPM_ENUM("SPK", hph_enum)
+};
+
+static const char * const lo_text[] = {
+ "ZERO", "Switch",
+};
+
+static const struct soc_enum lo_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hph_text), hph_text);
+
+static const struct snd_kcontrol_new lo_mux[] = {
+ SOC_DAPM_ENUM("LINE_OUT", lo_enum)
+};
+
+static void msm8x16_wcd_codec_enable_adc_block(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct msm8x16_wcd_priv *wcd8x16 = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %d\n", __func__, enable);
+
+ if (enable) {
+ wcd8x16->adc_count++;
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL,
+ 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x10, 0x10);
+ } else {
+ wcd8x16->adc_count--;
+ if (!wcd8x16->adc_count) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x10, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL,
+ 0x20, 0x0);
+ }
+ }
+}
+
+static int msm8x16_wcd_codec_enable_adc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ u16 adc_reg;
+ u8 init_bit_shift;
+
+ dev_err(codec->dev, "%s %d\n", __func__, event);
+
+ adc_reg = MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2;
+
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_1_EN)
+ init_bit_shift = 5;
+ else if ((w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN) ||
+ (w->reg == MSM89XX_PMIC_ANALOG_TX_3_EN))
+ init_bit_shift = 4;
+ else {
+ dev_err(codec->dev, "%s: Error, invalid adc register\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x16_wcd_codec_enable_adc_block(codec, 1);
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_CTL, 0x02, 0x02);
+ /*
+ * Add delay of 10 ms to give sufficient time for the voltage
+ * to shoot up and settle so that the txfe init does not
+ * happen when the input voltage is changing too much.
+ */
+ usleep_range(10000, 10010);
+ snd_soc_update_bits_wrapper(codec,
+ adc_reg, 1 << init_bit_shift,
+ 1 << init_bit_shift);
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_1_EN)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL,
+ 0x03, 0x00);
+ else if ((w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN) ||
+ (w->reg == MSM89XX_PMIC_ANALOG_TX_3_EN))
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL,
+ 0x03, 0x00);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /*
+ * Add delay of 12 ms before deasserting the init
+ * to reduce the tx pop
+ */
+ usleep_range(12000, 12010);
+ snd_soc_update_bits_wrapper(codec,
+ adc_reg, 1 << init_bit_shift, 0x00);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msm8x16_wcd_codec_enable_adc_block(codec, 0);
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_CTL, 0x02, 0x00);
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_1_EN)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL,
+ 0x03, 0x02);
+ else if ((w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN) ||
+ (w->reg == MSM89XX_PMIC_ANALOG_TX_3_EN))
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL,
+ 0x03, 0x02);
+
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %d %s\n", __func__, event, w->name);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0x01, 0x01);
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (!msm8x16_wcd->spk_boost_set)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x10, 0x10);
+ break;
+ case BOOST_ALWAYS:
+ case BOOST_ON_FOREVER:
+ break;
+ case BYPASS_ALWAYS:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x10, 0x10);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0xE0, 0xE0);
+ if (get_codec_version(msm8x16_wcd) != TOMBAK_1_0)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x01, 0x01);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->spk_boost_set)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xEF, 0xEF);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x10, 0x00);
+ break;
+ case BOOST_ALWAYS:
+ case BOOST_ON_FOREVER:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xEF, 0xEF);
+ break;
+ case BYPASS_ALWAYS:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x10, 0x00);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec, w->reg, 0x80, 0x80);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x01);
+ msm8x16_wcd->mute_mask |= SPKR_PA_DISABLE;
+ /*
+ * Add 1 ms sleep for the mute to take effect
+ */
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x10, 0x10);
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0)
+ msm8x16_wcd_boost_mode_sequence(codec, SPK_PMD);
+ snd_soc_update_bits_wrapper(codec, w->reg, 0x80, 0x00);
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->spk_boost_set)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xEF, 0x69);
+ break;
+ case BOOST_ALWAYS:
+ case BOOST_ON_FOREVER:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xEF, 0x69);
+ break;
+ case BYPASS_ALWAYS:
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0xE0, 0x00);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x10, 0x00);
+ if (get_codec_version(msm8x16_wcd) != TOMBAK_1_0)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00);
+ if (get_codec_version(msm8x16_wcd) >= CAJON_2_0)
+ msm8x16_wcd_boost_mode_sequence(codec, SPK_PMD);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_dig_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+
+ dev_err(codec->dev, "%s event %d w->name %s\n", __func__,
+ event, w->name);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x16_wcd_codec_enable_clock_block(codec, 1);
+ snd_soc_update_bits_wrapper(codec, w->reg, 0x80, 0x80);
+ msm8x16_wcd_boost_mode_sequence(codec, SPK_PMU);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (msm8x16_wcd->rx_bias_count == 0)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x00);
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ u8 dmic_clk_en;
+ u16 dmic_clk_reg;
+ s32 *dmic_clk_cnt;
+ unsigned int dmic;
+ int ret;
+ char *dec_num = strpbrk(w->name, "12");
+
+ if (dec_num == NULL) {
+ dev_err(codec->dev, "%s: Invalid DMIC\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = kstrtouint(dec_num, 10, &dmic);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "%s: Invalid DMIC line on the codec\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (dmic) {
+ case 1:
+ case 2:
+ dmic_clk_en = 0x01;
+ dmic_clk_cnt = &(msm8x16_wcd->dmic_1_2_clk_cnt);
+ dmic_clk_reg = MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL;
+ dev_err(codec->dev,
+ "%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
+ __func__, event, dmic, *dmic_clk_cnt);
+ break;
+ default:
+ dev_err(codec->dev, "%s: Invalid DMIC Selection\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ (*dmic_clk_cnt)++;
+ if (*dmic_clk_cnt == 1) {
+ snd_soc_update_bits_wrapper(codec, dmic_clk_reg,
+ 0x0E, 0x02);
+ snd_soc_update_bits_wrapper(codec, dmic_clk_reg,
+ dmic_clk_en, dmic_clk_en);
+ }
+ if (dmic == 1)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL, 0x07, 0x01);
+ if (dmic == 2)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX2_DMIC_CTL, 0x07, 0x01);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ (*dmic_clk_cnt)--;
+ if (*dmic_clk_cnt == 0)
+ snd_soc_update_bits_wrapper(codec, dmic_clk_reg,
+ dmic_clk_en, 0);
+ break;
+ }
+ return 0;
+}
+
+static bool msm8x16_wcd_use_mb(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) < CAJON)
+ return true;
+ else
+ return false;
+}
+
+static void msm8x16_wcd_set_auto_zeroing(struct snd_soc_codec *codec,
+ bool enable)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) < CONGA) {
+ if (enable)
+ /*
+ * Set autozeroing for special headset detection and
+ * buttons to work.
+ */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x18, 0x10);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x18, 0x00);
+
+ } else {
+ pr_err("%s: Auto Zeroing is not required from CONGA\n",
+ __func__);
+ }
+}
+
+static void msm8x16_trim_btn_reg(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) == TOMBAK_1_0) {
+ pr_err("%s: This device needs to be trimmed\n", __func__);
+ /*
+ * Calculate the trim value for each device used
+ * till is comes in production by hardware team
+ */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5, 0xA5);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TRIM_CTRL2,
+ 0xFF, 0x30);
+ } else {
+ pr_err("%s: This device is trimmed at ATE\n", __func__);
+ }
+}
+static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec,
+ bool turn_on)
+{
+ int ret = 0;
+ static int count;
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+
+ dev_err(codec->dev, "%s turn_on: %d count: %d\n", __func__, turn_on,
+ count);
+ if (turn_on) {
+ if (!count) {
+ ret = snd_soc_dapm_force_enable_pin(dapm,
+ "MICBIAS_REGULATOR");
+ snd_soc_dapm_sync(dapm);
+ }
+ count++;
+ } else {
+ if (count > 0)
+ count--;
+ if (!count) {
+ ret = snd_soc_dapm_disable_pin(dapm,
+ "MICBIAS_REGULATOR");
+ snd_soc_dapm_sync(dapm);
+ }
+ }
+
+ if (ret)
+ dev_err(codec->dev, "%s: Failed to %s external micbias source\n",
+ __func__, turn_on ? "enable" : "disabled");
+ else
+ dev_err(codec->dev, "%s: %s external micbias source\n",
+ __func__, turn_on ? "Enabled" : "Disabled");
+
+ return ret;
+}
+
+static int msm8x16_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(codec);
+ u16 micb_int_reg;
+ char *internal1_text = "Internal1";
+ char *internal2_text = "Internal2";
+ char *internal3_text = "Internal3";
+ char *external2_text = "External2";
+ char *external_text = "External";
+ bool micbias2;
+
+ dev_err(codec->dev, "%s %d\n", __func__, event);
+ switch (w->reg) {
+ case MSM89XX_PMIC_ANALOG_MICB_1_EN:
+ case MSM89XX_PMIC_ANALOG_MICB_2_EN:
+ micb_int_reg = MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS;
+ break;
+ default:
+ dev_err(codec->dev,
+ "%s: Error, invalid micbias register 0x%x\n",
+ __func__, w->reg);
+ return -EINVAL;
+ }
+
+ micbias2 = (snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN) & 0x80);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (strnstr(w->name, internal1_text, strlen(w->name))) {
+ if (get_codec_version(msm8x16_wcd) >= CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2,
+ 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x80, 0x80);
+ } else if (strnstr(w->name, internal2_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x10, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ w->reg, 0x60, 0x00);
+ } else if (strnstr(w->name, internal3_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x2, 0x2);
+ /*
+ * update MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2
+ * for external bias only, not for external2.
+ */
+ } else if (!strnstr(w->name, external2_text, strlen(w->name)) &&
+ strnstr(w->name, external_text,
+ strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2,
+ 0x02, 0x02);
+ }
+ if (!strnstr(w->name, external_text, strlen(w->name)))
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN, 0x05, 0x04);
+ if (w->reg == MSM89XX_PMIC_ANALOG_MICB_1_EN)
+ msm8x16_wcd_configure_cap(codec, true, micbias2);
+
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ if (get_codec_version(msm8x16_wcd) <= TOMBAK_2_0)
+ usleep_range(20000, 20100);
+ if (strnstr(w->name, internal1_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x40, 0x40);
+ } else if (strnstr(w->name, internal2_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x08, 0x08);
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_MICBIAS_2_ON);
+ } else if (strnstr(w->name, internal3_text, 30)) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x01, 0x01);
+ } else if (strnstr(w->name, external2_text, strlen(w->name))) {
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_MICBIAS_2_ON);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (strnstr(w->name, internal1_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0xC0, 0x40);
+ } else if (strnstr(w->name, internal2_text, strlen(w->name))) {
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_MICBIAS_2_OFF);
+ } else if (strnstr(w->name, internal3_text, 30)) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x2, 0x0);
+ } else if (strnstr(w->name, external2_text, strlen(w->name))) {
+ /*
+ * send micbias turn off event to mbhc driver and then
+ * break, as no need to set MICB_1_EN register.
+ */
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_MICBIAS_2_OFF);
+ break;
+ }
+ if (w->reg == MSM89XX_PMIC_ANALOG_MICB_1_EN)
+ msm8x16_wcd_configure_cap(codec, false, micbias2);
+ break;
+ }
+ return 0;
+}
+
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+ struct delayed_work *hpf_delayed_work;
+ struct hpf_work *hpf_work;
+ struct msm8x16_wcd_priv *msm8x16_wcd;
+ struct snd_soc_codec *codec;
+ u16 tx_mux_ctl_reg;
+ u8 hpf_cut_of_freq;
+
+ hpf_delayed_work = to_delayed_work(work);
+ hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+ msm8x16_wcd = hpf_work->msm8x16_wcd;
+ codec = hpf_work->msm8x16_wcd->codec;
+ hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+ tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX1_MUX_CTL +
+ (hpf_work->decimator - 1) * 32;
+
+ dev_err(codec->dev, "%s(): decimator %u hpf_cut_of_freq 0x%x\n",
+ __func__, hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV, 0xFF, 0x51);
+
+ snd_soc_update_bits_wrapper(codec,
+ tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
+}
+
+
+#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
+#define CF_MIN_3DB_4HZ 0x0
+#define CF_MIN_3DB_75HZ 0x1
+#define CF_MIN_3DB_150HZ 0x2
+
+static int msm8x16_wcd_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ int value = 0, reg;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (w->shift == 0)
+ reg = MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL;
+ else if (w->shift == 1)
+ reg = MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL;
+ value = snd_soc_read_wrapper(codec, reg);
+ snd_soc_write_wrapper(codec, reg, value);
+ break;
+ default:
+ pr_err("%s: event = %d not expected\n", __func__, event);
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_dec(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8916_asoc_mach_data *pdata = NULL;
+ unsigned int decimator;
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ int ret = 0, i;
+ u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+ u8 dec_hpf_cut_of_freq;
+ int offset;
+ char *dec_num;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ dev_err(codec->dev, "%s %d\n", __func__, event);
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ dev_err(codec->dev,
+ "%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dec_num = strpbrk(dec_name, "1234");
+ if (dec_num == NULL) {
+ dev_err(codec->dev, "%s: Invalid Decimator\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(dec_num, 10, &decimator);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dev_err(codec->dev,
+ "%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+ w->name, dec_name, decimator);
+
+ if (w->reg == MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL) {
+ dec_reset_reg = MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL;
+ offset = 0;
+ } else {
+ dev_err(codec->dev, "%s: Error, incorrect dec\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_vol_ctl_reg = MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG +
+ 32 * (decimator - 1);
+ tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX1_MUX_CTL +
+ 32 * (decimator - 1);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (decimator == 3 || decimator == 4) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL,
+ 0xFF, 0x5);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL +
+ (decimator - 1) * 0x20, 0x7, 0x2);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL +
+ (decimator - 1) * 0x20, 0x7, 0x2);
+ }
+ /* Enableable TX digital mute */
+ snd_soc_update_bits_wrapper(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ if (decimator == i + 1)
+ msm8x16_wcd->dec_active[i] = true;
+ }
+
+ dec_hpf_cut_of_freq =
+ snd_soc_read_wrapper(codec, tx_mux_ctl_reg);
+
+ dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
+
+ tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+ dec_hpf_cut_of_freq;
+
+ if (dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ) {
+
+ /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
+ snd_soc_update_bits_wrapper(codec, tx_mux_ctl_reg, 0x30,
+ CF_MIN_3DB_150HZ << 4);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV,
+ 0xFF, 0x42);
+
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* enable HPF */
+ snd_soc_update_bits_wrapper(codec, tx_mux_ctl_reg, 0x08, 0x00);
+
+ if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+ CF_MIN_3DB_150HZ) {
+
+ schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+ msecs_to_jiffies(300));
+ }
+ /* apply the digital gain after the decimator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(tx_digital_gain_reg))
+ snd_soc_write_wrapper(codec,
+ tx_digital_gain_reg[w->shift + offset],
+ snd_soc_read_wrapper(codec,
+ tx_digital_gain_reg[w->shift + offset])
+ );
+ if (pdata->lb_mode) {
+ pr_err("%s: loopback mode unmute the DEC\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec,
+ tx_vol_ctl_reg, 0x01, 0x00);
+ }
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits_wrapper(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ msleep(20);
+ snd_soc_update_bits_wrapper(codec, tx_mux_ctl_reg, 0x08, 0x08);
+ cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ dec_reset_reg, 1 << w->shift, 1 << w->shift);
+ snd_soc_update_bits_wrapper(codec,
+ dec_reset_reg, 1 << w->shift, 0x0);
+ snd_soc_update_bits_wrapper(codec,
+ tx_mux_ctl_reg, 0x08, 0x08);
+ snd_soc_update_bits_wrapper(codec,
+ tx_mux_ctl_reg, 0x30,
+ (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+ snd_soc_update_bits_wrapper(codec,
+ tx_vol_ctl_reg, 0x01, 0x00);
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ if (decimator == i + 1)
+ msm8x16_wcd->dec_active[i] = false;
+ }
+ if (decimator == 3 || decimator == 4) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL,
+ 0xFF, 0x0);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL +
+ (decimator - 1) * 0x20, 0x7, 0x0);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL +
+ (decimator - 1) * 0x20, 0x7, 0x0);
+ }
+ break;
+ }
+out:
+ kfree(widget_name);
+ return ret;
+}
+
+static int msm89xx_wcd_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ if (!msm8x16_wcd->ext_spk_boost_set) {
+ dev_err(codec->dev, "%s: ext_boost not supported/disabled\n",
+ __func__);
+ return 0;
+ }
+ dev_err(codec->dev, "%s: %s %d\n", __func__, w->name, event);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (msm8x16_wcd->spkdrv_reg) {
+ ret = regulator_enable(msm8x16_wcd->spkdrv_reg);
+ if (ret)
+ dev_err(codec->dev,
+ "%s Failed to enable spkdrv reg %s\n",
+ __func__, MSM89XX_VDD_SPKDRV_NAME);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (msm8x16_wcd->spkdrv_reg) {
+ ret = regulator_disable(msm8x16_wcd->spkdrv_reg);
+ if (ret)
+ dev_err(codec->dev,
+ "%s: Failed to disable spkdrv_reg %s\n",
+ __func__, MSM89XX_VDD_SPKDRV_NAME);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_config_compander(struct snd_soc_codec *codec,
+ int interp_n, int event)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: event %d shift %d, enabled %d\n",
+ __func__, event, interp_n,
+ msm8x16_wcd->comp_enabled[interp_n]);
+
+ /* compander is not enabled */
+ if (!msm8x16_wcd->comp_enabled[interp_n])
+ return 0;
+
+ switch (msm8x16_wcd->comp_enabled[interp_n]) {
+ case COMPANDER_1:
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ /* Enable Compander Clock */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B2_CTL, 0x0F, 0x09);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_RX_B2_CTL, 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B1_CTL,
+ 1 << interp_n, 1 << interp_n);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B3_CTL, 0xFF, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B2_CTL, 0xF0, 0x50);
+ /* add sleep for compander to settle */
+ usleep_range(1000, 1100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B3_CTL, 0xFF, 0x28);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B2_CTL, 0xF0, 0xB0);
+
+ /* Enable Compander GPIO */
+ if (msm8x16_wcd->codec_hph_comp_gpio)
+ msm8x16_wcd->codec_hph_comp_gpio(1);
+ } else if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ /* Disable Compander GPIO */
+ if (msm8x16_wcd->codec_hph_comp_gpio)
+ msm8x16_wcd->codec_hph_comp_gpio(0);
+
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B2_CTL, 0x0F, 0x05);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B1_CTL,
+ 1 << interp_n, 0);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_RX_B2_CTL, 0x01, 0x00);
+ }
+ break;
+ default:
+ dev_err(codec->dev, "%s: Invalid compander %d\n", __func__,
+ msm8x16_wcd->comp_enabled[interp_n]);
+ break;
+ };
+
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %d %s\n", __func__, event, w->name);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ msm8x16_wcd_codec_config_compander(codec, w->shift, event);
+ /* apply the digital gain after the interpolator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ snd_soc_write_wrapper(codec,
+ rx_digital_gain_reg[w->shift],
+ snd_soc_read_wrapper(codec,
+ rx_digital_gain_reg[w->shift])
+ );
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msm8x16_wcd_codec_config_compander(codec, w->shift, event);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_RX_RESET_CTL,
+ 1 << w->shift, 1 << w->shift);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_RX_RESET_CTL,
+ 1 << w->shift, 0x0);
+ /*
+ * disable the mute enabled during the PMD of this device
+ */
+ if ((w->shift == 0) &&
+ (msm8x16_wcd->mute_mask & HPHL_PA_DISABLE)) {
+ pr_err("disabling HPHL mute\n");
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x00);
+ if (get_codec_version(msm8x16_wcd) >= CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP,
+ 0xF0, 0x20);
+ msm8x16_wcd->mute_mask &= ~(HPHL_PA_DISABLE);
+ } else if ((w->shift == 1) &&
+ (msm8x16_wcd->mute_mask & HPHR_PA_DISABLE)) {
+ pr_err("disabling HPHR mute\n");
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B6_CTL, 0x01, 0x00);
+ if (get_codec_version(msm8x16_wcd) >= CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP,
+ 0xF0, 0x20);
+ msm8x16_wcd->mute_mask &= ~(HPHR_PA_DISABLE);
+ } else if ((w->shift == 2) &&
+ (msm8x16_wcd->mute_mask & SPKR_PA_DISABLE)) {
+ pr_err("disabling SPKR mute\n");
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x00);
+ msm8x16_wcd->mute_mask &= ~(SPKR_PA_DISABLE);
+ } else if ((w->shift == 0) &&
+ (msm8x16_wcd->mute_mask & EAR_PA_DISABLE)) {
+ pr_err("disabling EAR mute\n");
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x00);
+ msm8x16_wcd->mute_mask &= ~(EAR_PA_DISABLE);
+ }
+ }
+ return 0;
+}
+
+
+/* The register address is the same as other codec so it can use resmgr */
+static int msm8x16_wcd_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x16_wcd->rx_bias_count++;
+ if (msm8x16_wcd->rx_bias_count == 1) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x01, 0x01);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msm8x16_wcd->rx_bias_count--;
+ if (msm8x16_wcd->rx_bias_count == 0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x80, 0x00);
+ }
+ break;
+ }
+ dev_err(codec->dev, "%s rx_bias_count = %d\n",
+ __func__, msm8x16_wcd->rx_bias_count);
+ return 0;
+}
+
+static uint32_t wcd_get_impedance_value(uint32_t imped)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wcd_imped_val) - 1; i++) {
+ if (imped >= wcd_imped_val[i] &&
+ imped < wcd_imped_val[i + 1])
+ break;
+ }
+
+ pr_err("%s: selected impedance value = %d\n",
+ __func__, wcd_imped_val[i]);
+ return wcd_imped_val[i];
+}
+
+void wcd_imped_config(struct snd_soc_codec *codec,
+ uint32_t imped, bool set_gain)
+{
+ uint32_t value;
+ int codec_version;
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(codec);
+
+ value = wcd_get_impedance_value(imped);
+
+ if (value < wcd_imped_val[0]) {
+ pr_err("%s, detected impedance is less than 4 Ohm\n",
+ __func__);
+ return;
+ }
+ if (value >= wcd_imped_val[ARRAY_SIZE(wcd_imped_val) - 1]) {
+ pr_err("%s, invalid imped, greater than 48 Ohm\n = %d\n",
+ __func__, value);
+ return;
+ }
+
+ codec_version = get_codec_version(msm8x16_wcd);
+
+ if (set_gain) {
+ switch (codec_version) {
+ case TOMBAK_1_0:
+ case TOMBAK_2_0:
+ case CONGA:
+ /*
+ * For 32Ohm load and higher loads, Set 0x19E
+ * bit 5 to 1 (POS_6_DB_DI). For loads lower
+ * than 32Ohm (such as 16Ohm load), Set 0x19E
+ * bit 5 to 0 (POS_1P5_DB_DI)
+ */
+ if (value >= 32)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x20);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x00);
+ break;
+ case CAJON:
+ case CAJON_2_0:
+ case DIANGU:
+ if (value >= 13) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_VCTRL,
+ 0x07, 0x07);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_VCTRL,
+ 0x07, 0x04);
+ }
+ break;
+ }
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_VCTRL,
+ 0x07, 0x04);
+ }
+
+ pr_err("%s: Exit\n", __func__);
+}
+
+static int msm8x16_wcd_hphl_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ uint32_t impedl, impedr;
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ dev_err(codec->dev, "%s %s %d\n", __func__, w->name, event);
+ ret = wcd_mbhc_get_impedance(&msm8x16_wcd->mbhc,
+ &impedl, &impedr);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (get_codec_version(msm8x16_wcd) > CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 0x08, 0x08);
+ if (get_codec_version(msm8x16_wcd) == CAJON ||
+ get_codec_version(msm8x16_wcd) == CAJON_2_0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST,
+ 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST,
+ 0x80, 0x80);
+ }
+ if (get_codec_version(msm8x16_wcd) > CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 0x08, 0x00);
+ if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B3_CTL, 0x1C, 0x14);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B4_CTL, 0x18, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B3_CTL, 0x80, 0x80);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x02);
+ if (!ret)
+ wcd_imped_config(codec, impedl, true);
+ else
+ dev_err(codec->dev, "Failed to get mbhc impedance %d\n",
+ ret);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x02, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd_imped_config(codec, impedl, false);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x00);
+ if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B3_CTL, 0x1C, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B4_CTL, 0x18, 0xFF);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B3_CTL, 0x80, 0x00);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_lo_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ dev_err(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x08, 0x08);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x08, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ usleep_range(20000, 20100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x40, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x08, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x40, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x20, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B3_CTL, 0x1C, 0x14);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B4_CTL, 0x18, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B3_CTL, 0x80, 0x80);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x01);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x02, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x02, 0x00);
+ if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B3_CTL, 0x1C, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B4_CTL, 0x18, 0xFF);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B3_CTL, 0x80, 0x00);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (w->shift == 5)
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_PRE_HPHL_PA_ON);
+ else if (w->shift == 4)
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_PRE_HPHR_PA_ON);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0x20, 0x20);
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(7000, 7100);
+ if (w->shift == 5) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST, 0x04, 0x04);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x00);
+ } else if (w->shift == 4) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST, 0x04, 0x04);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B6_CTL, 0x01, 0x00);
+ }
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ if (w->shift == 5) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x01);
+ msleep(20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST, 0x04, 0x00);
+ msm8x16_wcd->mute_mask |= HPHL_PA_DISABLE;
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_PRE_HPHL_PA_OFF);
+ } else if (w->shift == 4) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B6_CTL, 0x01, 0x01);
+ msleep(20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST, 0x04, 0x00);
+ msm8x16_wcd->mute_mask |= HPHR_PA_DISABLE;
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_PRE_HPHR_PA_OFF);
+ }
+ if (get_codec_version(msm8x16_wcd) >= CAJON) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP,
+ 0xF0, 0x30);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (w->shift == 5) {
+ clear_bit(WCD_MBHC_HPHL_PA_OFF_ACK,
+ &msm8x16_wcd->mbhc.hph_pa_dac_state);
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_HPHL_PA_OFF);
+ } else if (w->shift == 4) {
+ clear_bit(WCD_MBHC_HPHR_PA_OFF_ACK,
+ &msm8x16_wcd->mbhc.hph_pa_dac_state);
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_HPHR_PA_OFF);
+ }
+ usleep_range(4000, 4100);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+
+ dev_err(codec->dev,
+ "%s: sleep 10 ms after %s PA disable.\n", __func__,
+ w->name);
+ usleep_range(10000, 10100);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"RX_I2S_CLK", NULL, "CDC_CONN"},
+ {"I2S RX1", NULL, "RX_I2S_CLK"},
+ {"I2S RX2", NULL, "RX_I2S_CLK"},
+ {"I2S RX3", NULL, "RX_I2S_CLK"},
+
+ {"I2S TX1", NULL, "TX_I2S_CLK"},
+ {"I2S TX2", NULL, "TX_I2S_CLK"},
+ {"AIF2 VI", NULL, "TX_I2S_CLK"},
+
+ {"I2S TX1", NULL, "DEC1 MUX"},
+ {"I2S TX2", NULL, "DEC2 MUX"},
+ {"AIF2 VI", NULL, "DEC3 MUX"},
+ {"AIF2 VI", NULL, "DEC4 MUX"},
+
+ /* RDAC Connections */
+ {"HPHR DAC", NULL, "RDAC2 MUX"},
+ {"RDAC2 MUX", "RX1", "RX1 CHAIN"},
+ {"RDAC2 MUX", "RX2", "RX2 CHAIN"},
+
+ /* WSA */
+ {"WSA_SPK OUT", NULL, "WSA Spk Switch"},
+ {"WSA Spk Switch", "WSA", "EAR PA"},
+
+ /* Earpiece (RX MIX1) */
+ {"EAR", NULL, "EAR_S"},
+ {"EAR_S", "Switch", "EAR PA"},
+ {"EAR PA", NULL, "RX_BIAS"},
+ {"EAR PA", NULL, "HPHL DAC"},
+ {"EAR PA", NULL, "HPHR DAC"},
+ {"EAR PA", NULL, "EAR CP"},
+
+ /* Headset (RX MIX1 and RX MIX2) */
+ {"HEADPHONE", NULL, "HPHL PA"},
+ {"HEADPHONE", NULL, "HPHR PA"},
+
+ {"Ext Spk", NULL, "Ext Spk Switch"},
+ {"Ext Spk Switch", "On", "HPHL PA"},
+ {"Ext Spk Switch", "On", "HPHR PA"},
+
+ {"HPHL PA", NULL, "HPHL"},
+ {"HPHR PA", NULL, "HPHR"},
+ {"HPHL", "Switch", "HPHL DAC"},
+ {"HPHR", "Switch", "HPHR DAC"},
+ {"HPHL PA", NULL, "CP"},
+ {"HPHL PA", NULL, "RX_BIAS"},
+ {"HPHR PA", NULL, "CP"},
+ {"HPHR PA", NULL, "RX_BIAS"},
+ {"HPHL DAC", NULL, "RX1 CHAIN"},
+
+ {"SPK_OUT", NULL, "SPK PA"},
+ {"SPK PA", NULL, "SPK_RX_BIAS"},
+ {"SPK PA", NULL, "SPK"},
+ {"SPK", "Switch", "SPK DAC"},
+ {"SPK DAC", NULL, "RX3 CHAIN"},
+ {"SPK DAC", NULL, "VDD_SPKDRV"},
+
+ /* lineout */
+ {"LINEOUT", NULL, "LINEOUT PA"},
+ {"LINEOUT PA", NULL, "SPK_RX_BIAS"},
+ {"LINEOUT PA", NULL, "LINE_OUT"},
+ {"LINE_OUT", "Switch", "LINEOUT DAC"},
+ {"LINEOUT DAC", NULL, "RX3 CHAIN"},
+
+ /* lineout to WSA */
+ {"WSA_SPK OUT", NULL, "LINEOUT PA"},
+
+ {"RX1 CHAIN", NULL, "RX1 CLK"},
+ {"RX2 CHAIN", NULL, "RX2 CLK"},
+ {"RX3 CHAIN", NULL, "RX3 CLK"},
+ {"RX1 CHAIN", NULL, "RX1 MIX2"},
+ {"RX2 CHAIN", NULL, "RX2 MIX2"},
+ {"RX3 CHAIN", NULL, "RX3 MIX1"},
+
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+ {"RX1 MIX2", NULL, "RX1 MIX1"},
+ {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
+ {"RX2 MIX2", NULL, "RX2 MIX1"},
+ {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
+
+ {"RX1 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP1", "IIR2", "IIR2"},
+ {"RX1 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP2", "IIR2", "IIR2"},
+ {"RX1 MIX1 INP3", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP3", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP3", "RX3", "I2S RX3"},
+
+ {"RX2 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX2 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX2 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX2 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP1", "IIR2", "IIR2"},
+ {"RX2 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX2 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX2 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX2 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP2", "IIR2", "IIR2"},
+
+ {"RX3 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX3 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX3 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX3 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP1", "IIR2", "IIR2"},
+ {"RX3 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX3 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX3 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX3 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP2", "IIR2", "IIR2"},
+
+ {"RX1 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX2 INP1", "IIR2", "IIR2"},
+ {"RX2 MIX2 INP1", "IIR2", "IIR2"},
+
+ /* Decimator Inputs */
+ {"DEC1 MUX", "DMIC1", "DMIC1"},
+ {"DEC1 MUX", "DMIC2", "DMIC2"},
+ {"DEC1 MUX", "ADC1", "ADC1"},
+ {"DEC1 MUX", "ADC2", "ADC2"},
+ {"DEC1 MUX", "ADC3", "ADC3"},
+ {"DEC1 MUX", NULL, "CDC_CONN"},
+
+ {"DEC2 MUX", "DMIC1", "DMIC1"},
+ {"DEC2 MUX", "DMIC2", "DMIC2"},
+ {"DEC2 MUX", "ADC1", "ADC1"},
+ {"DEC2 MUX", "ADC2", "ADC2"},
+ {"DEC2 MUX", "ADC3", "ADC3"},
+ {"DEC2 MUX", NULL, "CDC_CONN"},
+
+ {"DEC3 MUX", "DMIC3", "DMIC3"},
+ {"DEC4 MUX", "DMIC4", "DMIC4"},
+ {"DEC3 MUX", NULL, "CDC_CONN"},
+ {"DEC4 MUX", NULL, "CDC_CONN"},
+ /* ADC Connections */
+ {"ADC2", NULL, "ADC2 MUX"},
+ {"ADC3", NULL, "ADC2 MUX"},
+ {"ADC2 MUX", "INP2", "ADC2_INP2"},
+ {"ADC2 MUX", "INP3", "ADC2_INP3"},
+
+ {"ADC1", NULL, "AMIC1"},
+ {"ADC2_INP2", NULL, "AMIC2"},
+ {"ADC2_INP3", NULL, "AMIC3"},
+
+ /* TODO: Fix this */
+ {"IIR1", NULL, "IIR1 INP1 MUX"},
+ {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
+ {"IIR2", NULL, "IIR2 INP1 MUX"},
+ {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
+ {"MIC BIAS Internal1", NULL, "INT_LDO_H"},
+ {"MIC BIAS Internal2", NULL, "INT_LDO_H"},
+ {"MIC BIAS External", NULL, "INT_LDO_H"},
+ {"MIC BIAS External2", NULL, "INT_LDO_H"},
+ {"MIC BIAS Internal1", NULL, "MICBIAS_REGULATOR"},
+ {"MIC BIAS Internal2", NULL, "MICBIAS_REGULATOR"},
+ {"MIC BIAS External", NULL, "MICBIAS_REGULATOR"},
+ {"MIC BIAS External2", NULL, "MICBIAS_REGULATOR"},
+};
+
+static int msm8x16_wcd_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(dai->codec);
+
+ dev_err(dai->codec->dev, "%s(): substream = %s stream = %d\n",
+ __func__,
+ substream->name, substream->stream);
+ /*
+ * If status_mask is BU_DOWN it means SSR is not complete.
+ * So retun error.
+ */
+ if (test_bit(BUS_DOWN, &msm8x16_wcd->status_mask)) {
+ dev_err(dai->codec->dev, "Error, Device is not up post SSR\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void msm8x16_wcd_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ dev_err(dai->codec->dev,
+ "%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+}
+
+int msm8x16_wcd_mclk_enable(struct snd_soc_codec *codec,
+ int mclk_enable, bool dapm)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: mclk_enable = %u, dapm = %d\n",
+ __func__, mclk_enable, dapm);
+ if (mclk_enable) {
+ msm8x16_wcd->mclk_enabled = true;
+ msm8x16_wcd_codec_enable_clock_block(codec, 1);
+ } else {
+ if (!msm8x16_wcd->mclk_enabled) {
+ dev_err(codec->dev, "Error, MCLK already diabled\n");
+ return -EINVAL;
+ }
+ msm8x16_wcd->mclk_enabled = false;
+ msm8x16_wcd_codec_enable_clock_block(codec, 0);
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ dev_err(dai->codec->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int msm8x16_wcd_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ dev_err(dai->codec->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int msm8x16_wcd_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_slot,
+ unsigned int rx_num, unsigned int *rx_slot)
+
+{
+ dev_err(dai->codec->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int msm8x16_wcd_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+ dev_err(dai->codec->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int msm8x16_wcd_set_interpolator_rate(struct snd_soc_dai *dai,
+ u8 rx_fs_rate_reg_val, u32 sample_rate)
+{
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_RX1_B5_CTL, 0xF0, rx_fs_rate_reg_val);
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_RX2_B5_CTL, 0xF0, rx_fs_rate_reg_val);
+ return 0;
+}
+
+static int msm8x16_wcd_set_decimator_rate(struct snd_soc_dai *dai,
+ u8 tx_fs_rate_reg_val, u32 sample_rate)
+{
+ return 0;
+}
+
+static int msm8x16_wcd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ u8 tx_fs_rate, rx_fs_rate, rx_clk_fs_rate;
+ int ret;
+
+ dev_err(dai->codec->dev,
+ "%s: dai_name = %s DAI-ID %x rate %d num_ch %d format %d\n",
+ __func__, dai->name, dai->id, params_rate(params),
+ params_channels(params), params_format(params));
+
+ switch (params_rate(params)) {
+ case 8000:
+ tx_fs_rate = 0x00;
+ rx_fs_rate = 0x00;
+ rx_clk_fs_rate = 0x00;
+ break;
+ case 16000:
+ tx_fs_rate = 0x20;
+ rx_fs_rate = 0x20;
+ rx_clk_fs_rate = 0x01;
+ break;
+ case 32000:
+ tx_fs_rate = 0x40;
+ rx_fs_rate = 0x40;
+ rx_clk_fs_rate = 0x02;
+ break;
+ case 48000:
+ tx_fs_rate = 0x60;
+ rx_fs_rate = 0x60;
+ rx_clk_fs_rate = 0x03;
+ break;
+ case 96000:
+ tx_fs_rate = 0x80;
+ rx_fs_rate = 0x80;
+ rx_clk_fs_rate = 0x04;
+ break;
+ case 192000:
+ tx_fs_rate = 0xA0;
+ rx_fs_rate = 0xA0;
+ rx_clk_fs_rate = 0x05;
+ break;
+ default:
+ dev_err(dai->codec->dev,
+ "%s: Invalid sampling rate %d\n", __func__,
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x0F, rx_clk_fs_rate);
+
+ switch (substream->stream) {
+ case SNDRV_PCM_STREAM_CAPTURE:
+ ret = msm8x16_wcd_set_decimator_rate(dai, tx_fs_rate,
+ params_rate(params));
+ if (ret < 0) {
+ dev_err(dai->codec->dev,
+ "%s: set decimator rate failed %d\n", __func__,
+ ret);
+ return ret;
+ }
+ break;
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ ret = msm8x16_wcd_set_interpolator_rate(dai, rx_fs_rate,
+ params_rate(params));
+ if (ret < 0) {
+ dev_err(dai->codec->dev,
+ "%s: set decimator rate failed %d\n", __func__,
+ ret);
+ return ret;
+ }
+ break;
+ default:
+ dev_err(dai->codec->dev,
+ "%s: Invalid stream type %d\n", __func__,
+ substream->stream);
+ return -EINVAL;
+ }
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x20, 0x20);
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x20, 0x00);
+ break;
+ default:
+ dev_err(dai->codec->dev, "%s: wrong format selected\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int msm8x16_wcd_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = NULL;
+ u16 tx_vol_ctl_reg = 0;
+ u8 decimator = 0, i;
+ struct msm8x16_wcd_priv *msm8x16_wcd;
+
+ pr_err("%s: Digital Mute val = %d\n", __func__, mute);
+
+ if (!dai || !dai->codec) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+ codec = dai->codec;
+ msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if ((dai->id != AIF1_CAP) && (dai->id != AIF2_VIFEED)) {
+ dev_err(codec->dev, "%s: Not capture use case skip\n",
+ __func__);
+ return 0;
+ }
+
+ mute = (mute) ? 1 : 0;
+ if (!mute) {
+ /*
+ * 15 ms is an emperical value for the mute time
+ * that was arrived by checking the pop level
+ * to be inaudible
+ */
+ usleep_range(15000, 15010);
+ }
+
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ if (msm8x16_wcd->dec_active[i])
+ decimator = i + 1;
+ if (decimator && decimator <= NUM_DECIMATORS) {
+ pr_err("%s: Mute = %d Decimator = %d", __func__,
+ mute, decimator);
+ tx_vol_ctl_reg = MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG +
+ 32 * (decimator - 1);
+ snd_soc_update_bits_wrapper(codec,
+ tx_vol_ctl_reg, 0x01, mute);
+ }
+ decimator = 0;
+ }
+ return 0;
+}
+
+static struct snd_soc_dai_ops msm8x16_wcd_dai_ops = {
+ .startup = msm8x16_wcd_startup,
+ .shutdown = msm8x16_wcd_shutdown,
+ .hw_params = msm8x16_wcd_hw_params,
+ .set_sysclk = msm8x16_wcd_set_dai_sysclk,
+ .set_fmt = msm8x16_wcd_set_dai_fmt,
+ .set_channel_map = msm8x16_wcd_set_channel_map,
+ .get_channel_map = msm8x16_wcd_get_channel_map,
+ .digital_mute = msm8x16_wcd_digital_mute,
+};
+
+static struct snd_soc_dai_driver msm8x16_wcd_i2s_dai[] = {
+ {
+ .name = "msm8x16_wcd_i2s_rx1",
+ .id = AIF1_PB,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .rates = MSM89XX_RATES,
+ .formats = MSM89XX_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 3,
+ },
+ .ops = &msm8x16_wcd_dai_ops,
+ },
+ {
+ .name = "msm8x16_wcd_i2s_tx1",
+ .id = AIF1_CAP,
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .rates = MSM89XX_RATES,
+ .formats = MSM89XX_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &msm8x16_wcd_dai_ops,
+ },
+ {
+ .name = "cajon_vifeedback",
+ .id = AIF2_VIFEED,
+ .capture = {
+ .stream_name = "VIfeed",
+ .rates = MSM89XX_RATES,
+ .formats = MSM89XX_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .ops = &msm8x16_wcd_dai_ops,
+ },
+};
+
+static int msm8x16_wcd_codec_enable_rx_chain(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ dev_err(codec->dev,
+ "%s: PMU:Sleeping 20ms after disabling mute\n",
+ __func__);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ dev_err(codec->dev,
+ "%s: PMD:Sleeping 20ms after disabling mute\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec, w->reg,
+ 1 << w->shift, 0x00);
+ msleep(20);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_lo_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ dev_err(codec->dev, "%s: %d %s\n", __func__, event, w->name);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x00);
+ break;
+ }
+
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_spk_ext_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ dev_err(codec->dev,
+ "%s: enable external speaker PA\n", __func__);
+ if (msm8x16_wcd->codec_spk_ext_pa_cb)
+ msm8x16_wcd->codec_spk_ext_pa_cb(codec, 1);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ dev_err(codec->dev,
+ "%s: enable external speaker PA\n", __func__);
+ if (msm8x16_wcd->codec_spk_ext_pa_cb)
+ msm8x16_wcd->codec_spk_ext_pa_cb(codec, 0);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dev_err(codec->dev,
+ "%s: Sleeping 20ms after select EAR PA\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x80, 0x80);
+ if (get_codec_version(msm8x16_wcd) < CONGA)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME, 0xFF, 0x2A);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ dev_err(codec->dev,
+ "%s: Sleeping 20ms after enabling EAR PA\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x40, 0x40);
+ usleep_range(7000, 7100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x00);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x01);
+ msleep(20);
+ msm8x16_wcd->mute_mask |= EAR_PA_DISABLE;
+ if (msm8x16_wcd->boost_option == BOOST_ALWAYS) {
+ dev_err(codec->dev,
+ "%s: boost_option:%d, tear down ear\n",
+ __func__, msm8x16_wcd->boost_option);
+ msm8x16_wcd_boost_mode_sequence(codec, EAR_PMD);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ dev_err(codec->dev,
+ "%s: Sleeping 7ms after disabling EAR PA\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x40, 0x00);
+ usleep_range(7000, 7100);
+ if (get_codec_version(msm8x16_wcd) < CONGA)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME, 0xFF, 0x16);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget msm8x16_wcd_dapm_widgets[] = {
+ /*RX stuff */
+ SND_SOC_DAPM_OUTPUT("EAR"),
+ SND_SOC_DAPM_OUTPUT("WSA_SPK OUT"),
+
+ SND_SOC_DAPM_PGA_E("EAR PA", SND_SOC_NOPM,
+ 0, 0, NULL, 0, msm8x16_wcd_codec_enable_ear_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX("EAR_S", SND_SOC_NOPM, 0, 0,
+ ear_pa_mux),
+
+ SND_SOC_DAPM_MUX("WSA Spk Switch", SND_SOC_NOPM, 0, 0,
+ wsa_spk_mux),
+
+ SND_SOC_DAPM_AIF_IN("I2S RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("I2S RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("I2S RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_SUPPLY("INT_LDO_H", SND_SOC_NOPM, 1, 0, NULL, 0),
+
+ SND_SOC_DAPM_SPK("Ext Spk", msm8x16_wcd_codec_enable_spk_ext_pa),
+
+ SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("HPHL PA", MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 5, 0, NULL, 0,
+ msm8x16_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("HPHL", SND_SOC_NOPM, 0, 0,
+ hphl_mux),
+
+ SND_SOC_DAPM_MIXER_E("HPHL DAC",
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 3, 0, NULL,
+ 0, msm8x16_wcd_hphl_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("HPHR PA", MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 4, 0, NULL, 0,
+ msm8x16_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("HPHR", SND_SOC_NOPM, 0, 0,
+ hphr_mux),
+
+ SND_SOC_DAPM_MIXER_E("HPHR DAC",
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 3, 0, NULL,
+ 0, msm8x16_wcd_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SPK", SND_SOC_NOPM, 0, 0,
+ spkr_mux),
+
+ SND_SOC_DAPM_DAC("SPK DAC", NULL,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 7, 0),
+
+ SND_SOC_DAPM_MUX("LINE_OUT",
+ SND_SOC_NOPM, 0, 0, lo_mux),
+
+ SND_SOC_DAPM_DAC_E("LINEOUT DAC", NULL,
+ SND_SOC_NOPM, 0, 0, msm8x16_wcd_lo_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Speaker */
+ SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+
+ /* Lineout */
+ SND_SOC_DAPM_OUTPUT("LINEOUT"),
+
+ SND_SOC_DAPM_PGA_E("SPK PA", MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 6, 0, NULL, 0, msm8x16_wcd_codec_enable_spk_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("LINEOUT PA", MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL,
+ 5, 0, NULL, 0, msm8x16_wcd_codec_enable_lo_pa,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
+ msm89xx_wcd_codec_enable_vdd_spkr,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("Ext Spk Switch", SND_SOC_NOPM, 0, 0,
+ &ext_spk_mux),
+
+ SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER_E("RX1 MIX2",
+ MSM89XX_CDC_CORE_CLK_RX_B1_CTL, MSM89XX_RX1, 0, NULL,
+ 0, msm8x16_wcd_codec_enable_interpolator,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX2 MIX2",
+ MSM89XX_CDC_CORE_CLK_RX_B1_CTL, MSM89XX_RX2, 0, NULL,
+ 0, msm8x16_wcd_codec_enable_interpolator,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX3 MIX1",
+ MSM89XX_CDC_CORE_CLK_RX_B1_CTL, MSM89XX_RX3, 0, NULL,
+ 0, msm8x16_wcd_codec_enable_interpolator,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("RX1 CLK", MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("RX2 CLK", MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("RX3 CLK", MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 2, 0, msm8x16_wcd_codec_enable_dig_clk, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX1 CHAIN", MSM89XX_CDC_CORE_RX1_B6_CTL, 0, 0,
+ NULL, 0,
+ msm8x16_wcd_codec_enable_rx_chain,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX2 CHAIN", MSM89XX_CDC_CORE_RX2_B6_CTL, 0, 0,
+ NULL, 0,
+ msm8x16_wcd_codec_enable_rx_chain,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX3 CHAIN", MSM89XX_CDC_CORE_RX3_B6_CTL, 0, 0,
+ NULL, 0,
+ msm8x16_wcd_codec_enable_rx_chain,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp3_mux),
+
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp3_mux),
+
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp3_mux),
+
+ SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx1_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix2_inp1_mux),
+
+ SND_SOC_DAPM_SUPPLY("MICBIAS_REGULATOR", SND_SOC_NOPM,
+ ON_DEMAND_MICBIAS, 0,
+ msm8x16_wcd_codec_enable_on_demand_supply,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("CP", MSM89XX_PMIC_ANALOG_NCP_EN, 0, 0,
+ msm8x16_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("EAR CP", MSM89XX_PMIC_ANALOG_NCP_EN, 4, 0,
+ msm8x16_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("RX_BIAS", 1, SND_SOC_NOPM,
+ 0, 0, msm8x16_wcd_codec_enable_rx_bias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("SPK_RX_BIAS", 1, SND_SOC_NOPM, 0, 0,
+ msm8x16_wcd_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* TX */
+
+ SND_SOC_DAPM_SUPPLY_S("CDC_CONN", -2, MSM89XX_CDC_CORE_CLK_OTHR_CTL,
+ 2, 0, NULL, 0),
+
+
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal1",
+ MSM89XX_PMIC_ANALOG_MICB_1_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal2",
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal3",
+ MSM89XX_PMIC_ANALOG_MICB_1_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM89XX_PMIC_ANALOG_TX_1_EN, 7, 0,
+ msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC2_INP2",
+ NULL, MSM89XX_PMIC_ANALOG_TX_2_EN, 7, 0,
+ msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC2_INP3",
+ NULL, MSM89XX_PMIC_ANALOG_TX_3_EN, 7, 0,
+ msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
+ &tx_adc2_mux),
+
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS External",
+ MSM89XX_PMIC_ANALOG_MICB_1_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS External2",
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+
+ SND_SOC_DAPM_INPUT("AMIC3"),
+
+ SND_SOC_DAPM_MUX_E("DEC1 MUX",
+ MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+ &dec1_mux, msm8x16_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC2 MUX",
+ MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+ &dec2_mux, msm8x16_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC3 MUX",
+ MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+ &dec3_mux, msm8x16_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC4 MUX",
+ MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+ &dec4_mux, msm8x16_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RDAC2 MUX", SND_SOC_NOPM, 0, 0, &rdac2_mux),
+
+ SND_SOC_DAPM_INPUT("AMIC2"),
+
+ SND_SOC_DAPM_AIF_OUT("I2S TX1", "AIF1 Capture", 0, SND_SOC_NOPM,
+ 0, 0),
+ SND_SOC_DAPM_AIF_OUT("I2S TX2", "AIF1 Capture", 0, SND_SOC_NOPM,
+ 0, 0),
+ SND_SOC_DAPM_AIF_OUT("I2S TX3", "AIF1 Capture", 0, SND_SOC_NOPM,
+ 0, 0),
+
+ SND_SOC_DAPM_AIF_OUT("AIF2 VI", "VIfeed", 0, SND_SOC_NOPM,
+ 0, 0),
+ /* Digital Mic Inputs */
+ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+ msm8x16_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+ msm8x16_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("DMIC3"),
+
+ SND_SOC_DAPM_INPUT("DMIC4"),
+
+ /* Sidetone */
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_PGA_E("IIR1", MSM89XX_CDC_CORE_CLK_SD_CTL, 0, 0, NULL, 0,
+ msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
+ SND_SOC_DAPM_PGA_E("IIR2", MSM89XX_CDC_CORE_CLK_SD_CTL, 1, 0, NULL, 0,
+ msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_SUPPLY("RX_I2S_CLK",
+ MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("TX_I2S_CLK",
+ MSM89XX_CDC_CORE_CLK_TX_I2S_CTL, 4, 0,
+ NULL, 0),
+};
+
+static const struct msm8x16_wcd_reg_mask_val msm8x16_wcd_reg_defaults[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0x82),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+};
+
+static const struct msm8x16_wcd_reg_mask_val msm8x16_wcd_reg_defaults_2_0[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x4F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0x28),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x69),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x01),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_BOOST_EN_CTL, 0x5F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO, 0x88),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0x82),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80),
+};
+
+static const struct msm8x16_wcd_reg_mask_val msm8909_wcd_reg_defaults[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x4C),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0x28),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x69),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x01),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE, 0x0A),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80),
+};
+
+static const struct msm8x16_wcd_reg_mask_val cajon_wcd_reg_defaults[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x4C),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0x82),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0xA8),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_VCTRL, 0xA4),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET, 0x41),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x69),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x01),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA, 0xFA),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80),
+};
+
+static const struct msm8x16_wcd_reg_mask_val cajon2p0_wcd_reg_defaults[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x4C),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0xA2),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0xA8),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_VCTRL, 0xA4),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET, 0x41),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x69),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x01),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_RX_EAR_STATUS, 0x10),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_BYPASS_MODE, 0x18),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA, 0xFA),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80),
+};
+
+static void msm8x16_wcd_update_reg_defaults(struct snd_soc_codec *codec)
+{
+ u32 i, version;
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ version = get_codec_version(msm8x16_wcd);
+ if (version == TOMBAK_1_0) {
+ for (i = 0; i < ARRAY_SIZE(msm8x16_wcd_reg_defaults); i++)
+ snd_soc_write_wrapper(codec,
+ msm8x16_wcd_reg_defaults[i].reg,
+ msm8x16_wcd_reg_defaults[i].val);
+ } else if (version == TOMBAK_2_0) {
+ for (i = 0; i < ARRAY_SIZE(msm8x16_wcd_reg_defaults_2_0); i++)
+ snd_soc_write_wrapper(codec,
+ msm8x16_wcd_reg_defaults_2_0[i].reg,
+ msm8x16_wcd_reg_defaults_2_0[i].val);
+ } else if (version == CONGA) {
+ for (i = 0; i < ARRAY_SIZE(msm8909_wcd_reg_defaults); i++)
+ snd_soc_write_wrapper(codec,
+ msm8909_wcd_reg_defaults[i].reg,
+ msm8909_wcd_reg_defaults[i].val);
+ } else if (version == CAJON) {
+ for (i = 0; i < ARRAY_SIZE(cajon_wcd_reg_defaults); i++)
+ snd_soc_write_wrapper(codec,
+ cajon_wcd_reg_defaults[i].reg,
+ cajon_wcd_reg_defaults[i].val);
+ } else if (version == CAJON_2_0 || version == DIANGU) {
+ for (i = 0; i < ARRAY_SIZE(cajon2p0_wcd_reg_defaults); i++)
+ snd_soc_write_wrapper(codec,
+ cajon2p0_wcd_reg_defaults[i].reg,
+ cajon2p0_wcd_reg_defaults[i].val);
+ }
+}
+
+static const struct msm8x16_wcd_reg_mask_val
+ msm8x16_wcd_codec_reg_init_val[] = {
+
+ /* Initialize current threshold to 350MA
+ * number of wait and run cycles to 4096
+ */
+ {MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL, 0xFF, 0x12},
+ {MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+};
+
+static void msm8x16_wcd_codec_init_reg(struct snd_soc_codec *codec)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(msm8x16_wcd_codec_reg_init_val); i++)
+ snd_soc_update_bits_wrapper(codec,
+ msm8x16_wcd_codec_reg_init_val[i].reg,
+ msm8x16_wcd_codec_reg_init_val[i].mask,
+ msm8x16_wcd_codec_reg_init_val[i].val);
+}
+
+static int msm8x16_wcd_bringup(struct snd_soc_codec *codec)
+{
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4, 0x01);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4, 0x01);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4, 0x00);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4, 0x00);
+ return 0;
+}
+
+static struct regulator *wcd8x16_wcd_codec_find_regulator(
+ const struct msm8x16_wcd *msm8x16,
+ const char *name)
+{
+ int i;
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (msm8x16->supplies[i].supply &&
+ !strcmp(msm8x16->supplies[i].supply, name))
+ return msm8x16->supplies[i].consumer;
+ }
+
+ dev_err(msm8x16->dev, "Error: regulator not found:%s\n"
+ , name);
+ return NULL;
+}
+
+static int msm8x16_wcd_device_down(struct snd_soc_codec *codec)
+{
+ struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ dev_err(codec->dev, "%s: device down!\n", __func__);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_EN, 0x3);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_2_EN, 0x3);
+ if (msm8x16_wcd_priv->boost_option == BOOST_ON_FOREVER) {
+ if ((snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL)
+ & 0x80) == 0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_MCLK_CTL, 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_PDM_CTL, 0x03, 0x03);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL, 0x30);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL,
+ 0x0C, 0x0C);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x84, 0x84);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL,
+ 0x10, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL,
+ 0x1F, 0x1F);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x90, 0x90);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0xFF, 0xFF);
+ usleep_range(20, 21);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL,
+ 0xFF, 0xFF);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xE9, 0xE9);
+ }
+ }
+ msm8x16_wcd_boost_off(codec);
+ msm8x16_wcd_priv->hph_mode = NORMAL_MODE;
+ for (i = 0; i < MSM89XX_RX_MAX; i++)
+ msm8x16_wcd_priv->comp_enabled[i] = COMPANDER_NONE;
+
+ /* 40ms to allow boost to discharge */
+ msleep(40);
+ /* Disable PA to avoid pop during codec bring up */
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 0x30, 0x00);
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0x80, 0x00);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x20);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x20);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x12);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x93);
+
+ msm8x16_wcd_bringup(codec);
+ atomic_set(&pdata->mclk_enabled, false);
+ set_bit(BUS_DOWN, &msm8x16_wcd_priv->status_mask);
+ snd_soc_card_change_online_state(codec->component.card, 0);
+ return 0;
+}
+
+static int msm8x16_wcd_device_up(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ dev_err(codec->dev, "%s: device up!\n", __func__);
+
+ clear_bit(BUS_DOWN, &msm8x16_wcd_priv->status_mask);
+
+ snd_soc_card_change_online_state(codec->component.card, 1);
+ /* delay is required to make sure sound card state updated */
+ usleep_range(5000, 5100);
+
+ msm8x16_wcd_codec_init_reg(codec);
+ msm8x16_wcd_update_reg_defaults(codec);
+
+ snd_soc_write_wrapper(codec, MSM89XX_PMIC_DIGITAL_INT_EN_SET,
+ MSM89XX_PMIC_DIGITAL_INT_EN_SET__POR);
+ snd_soc_write_wrapper(codec, MSM89XX_PMIC_DIGITAL_INT_EN_CLR,
+ MSM89XX_PMIC_DIGITAL_INT_EN_CLR__POR);
+
+ msm8x16_wcd_set_boost_v(codec);
+
+ msm8x16_wcd_set_micb_v(codec);
+ if (msm8x16_wcd_priv->boost_option == BOOST_ON_FOREVER)
+ msm8x16_wcd_boost_on(codec);
+ else if (msm8x16_wcd_priv->boost_option == BYPASS_ALWAYS)
+ msm8x16_wcd_bypass_on(codec);
+
+ msm8x16_wcd_configure_cap(codec, false, false);
+ wcd_mbhc_stop(&msm8x16_wcd_priv->mbhc);
+ wcd_mbhc_deinit(&msm8x16_wcd_priv->mbhc);
+ ret = wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
+ wcd_mbhc_registers, true);
+ if (ret)
+ dev_err(codec->dev, "%s: mbhc initialization failed\n",
+ __func__);
+ else
+ wcd_mbhc_start(&msm8x16_wcd_priv->mbhc,
+ msm8x16_wcd_priv->mbhc.mbhc_cfg);
+
+
+ return 0;
+}
+
+static int adsp_state_callback(struct notifier_block *nb, unsigned long value,
+ void *priv)
+{
+ bool timedout;
+ unsigned long timeout;
+
+ if (value == SUBSYS_BEFORE_SHUTDOWN)
+ msm8x16_wcd_device_down(registered_codec);
+ else if (value == SUBSYS_AFTER_POWERUP) {
+
+ dev_err(registered_codec->dev,
+ "ADSP is about to power up. bring up codec\n");
+
+ if (!q6core_is_adsp_ready()) {
+ dev_err(registered_codec->dev,
+ "ADSP isn't ready\n");
+ timeout = jiffies +
+ msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+ while (!(timedout = time_after(jiffies, timeout))) {
+ if (!q6core_is_adsp_ready()) {
+ dev_err(registered_codec->dev,
+ "ADSP isn't ready\n");
+ } else {
+ dev_err(registered_codec->dev,
+ "ADSP is ready\n");
+ break;
+ }
+ }
+ } else {
+ dev_err(registered_codec->dev,
+ "%s: DSP is ready\n", __func__);
+ }
+
+ msm8x16_wcd_device_up(registered_codec);
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+ .notifier_call = adsp_state_callback,
+ .priority = -INT_MAX,
+};
+
+int msm8x16_wcd_hs_detect(struct snd_soc_codec *codec,
+ struct wcd_mbhc_config *mbhc_cfg)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+
+ return wcd_mbhc_start(&msm8x16_wcd_priv->mbhc, mbhc_cfg);
+}
+EXPORT_SYMBOL(msm8x16_wcd_hs_detect);
+
+void msm8x16_wcd_hs_detect_exit(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+
+ wcd_mbhc_stop(&msm8x16_wcd_priv->mbhc);
+}
+EXPORT_SYMBOL(msm8x16_wcd_hs_detect_exit);
+
+void msm8x16_update_int_spk_boost(bool enable)
+{
+ pr_err("%s: enable = %d\n", __func__, enable);
+ spkr_boost_en = enable;
+}
+EXPORT_SYMBOL(msm8x16_update_int_spk_boost);
+
+static void msm8x16_wcd_set_micb_v(struct snd_soc_codec *codec)
+{
+
+ struct msm8x16_wcd *msm8x16 = codec->control_data;
+ struct msm8x16_wcd_pdata *pdata = msm8x16->dev->platform_data;
+ u8 reg_val;
+
+ reg_val = VOLTAGE_CONVERTER(pdata->micbias.cfilt1_mv, MICBIAS_MIN_VAL,
+ MICBIAS_STEP_SIZE);
+ dev_err(codec->dev, "cfilt1_mv %d reg_val %x\n",
+ (u32)pdata->micbias.cfilt1_mv, reg_val);
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_MICB_1_VAL,
+ 0xF8, (reg_val << 3));
+}
+
+static void msm8x16_wcd_set_boost_v(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE,
+ 0x1F, msm8x16_wcd_priv->boost_voltage);
+}
+
+static void msm8x16_wcd_configure_cap(struct snd_soc_codec *codec,
+ bool micbias1, bool micbias2)
+{
+
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+
+ pr_err("\n %s: micbias1 %x micbias2 = %d\n", __func__, micbias1,
+ micbias2);
+ if (micbias1 && micbias2) {
+ if ((pdata->micbias1_cap_mode
+ == MICBIAS_EXT_BYP_CAP) ||
+ (pdata->micbias2_cap_mode
+ == MICBIAS_EXT_BYP_CAP))
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, (MICBIAS_EXT_BYP_CAP << 6));
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, (MICBIAS_NO_EXT_BYP_CAP << 6));
+ } else if (micbias2) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, (pdata->micbias2_cap_mode << 6));
+ } else if (micbias1) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, (pdata->micbias1_cap_mode << 6));
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, 0x00);
+ }
+}
+
+static int msm89xx_digcodec_probe(struct snd_soc_codec *codec)
+{
+ registered_digcodec = codec;
+
+ return 0;
+}
+
+
+static int msm89xx_digcodec_remove(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv;
+ int i, ret;
+
+ dev_err(codec->dev, "%s()\n", __func__);
+
+ msm8x16_wcd_priv = kzalloc(sizeof(struct msm8x16_wcd_priv), GFP_KERNEL);
+ if (!msm8x16_wcd_priv)
+ return -ENOMEM;
+
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ tx_hpf_work[i].msm8x16_wcd = msm8x16_wcd_priv;
+ tx_hpf_work[i].decimator = i + 1;
+ INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+ tx_hpf_corner_freq_callback);
+ }
+
+ codec->control_data = dev_get_drvdata(codec->dev);
+ snd_soc_codec_set_drvdata(codec, msm8x16_wcd_priv);
+ msm8x16_wcd_priv->codec = codec;
+
+ msm8x16_wcd_priv->spkdrv_reg =
+ wcd8x16_wcd_codec_find_regulator(codec->control_data,
+ MSM89XX_VDD_SPKDRV_NAME);
+ msm8x16_wcd_priv->pmic_rev = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_REVISION1);
+ msm8x16_wcd_priv->codec_version = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE);
+ if (msm8x16_wcd_priv->codec_version == CONGA) {
+ dev_err(codec->dev, "%s :Conga REV: %d\n", __func__,
+ msm8x16_wcd_priv->codec_version);
+ msm8x16_wcd_priv->ext_spk_boost_set = true;
+ } else {
+ dev_err(codec->dev, "%s :PMIC REV: %d\n", __func__,
+ msm8x16_wcd_priv->pmic_rev);
+ if (msm8x16_wcd_priv->pmic_rev == TOMBAK_1_0 &&
+ msm8x16_wcd_priv->codec_version == CAJON_2_0) {
+ msm8x16_wcd_priv->codec_version = DIANGU;
+ dev_err(codec->dev, "%s : Diangu detected\n",
+ __func__);
+ } else if (msm8x16_wcd_priv->pmic_rev == TOMBAK_1_0 &&
+ (snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_FBCTRL)
+ & 0x80)) {
+ msm8x16_wcd_priv->codec_version = CAJON;
+ dev_err(codec->dev, "%s : Cajon detected\n", __func__);
+ } else if (msm8x16_wcd_priv->pmic_rev == TOMBAK_2_0 &&
+ (snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_FBCTRL)
+ & 0x80)) {
+ msm8x16_wcd_priv->codec_version = CAJON_2_0;
+ dev_err(codec->dev, "%s : Cajon 2.0 detected\n",
+ __func__);
+ }
+ }
+ /*
+ * set to default boost option BOOST_SWITCH, user mixer path can change
+ * it to BOOST_ALWAYS or BOOST_BYPASS based on solution chosen.
+ */
+ msm8x16_wcd_priv->boost_option = BOOST_SWITCH;
+ msm8x16_wcd_priv->hph_mode = NORMAL_MODE;
+
+ for (i = 0; i < MSM89XX_RX_MAX; i++)
+ msm8x16_wcd_priv->comp_enabled[i] = COMPANDER_NONE;
+
+ msm8x16_wcd_dt_parse_boost_info(codec);
+ msm8x16_wcd_set_boost_v(codec);
+
+ snd_soc_add_codec_controls(codec, impedance_detect_controls,
+ ARRAY_SIZE(impedance_detect_controls));
+ snd_soc_add_codec_controls(codec, hph_type_detect_controls,
+ ARRAY_SIZE(hph_type_detect_controls));
+
+ msm8x16_wcd_bringup(codec);
+ msm8x16_wcd_codec_init_reg(codec);
+ msm8x16_wcd_update_reg_defaults(codec);
+
+ wcd9xxx_spmi_set_codec(codec);
+
+ msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].supply =
+ wcd8x16_wcd_codec_find_regulator(
+ codec->control_data,
+ on_demand_supply_name[ON_DEMAND_MICBIAS]);
+ atomic_set(&msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
+
+ BLOCKING_INIT_NOTIFIER_HEAD(&msm8x16_wcd_priv->notifier);
+
+ msm8x16_wcd_priv->fw_data = kzalloc(sizeof(*(msm8x16_wcd_priv->fw_data))
+ , GFP_KERNEL);
+ if (!msm8x16_wcd_priv->fw_data) {
+ kfree(msm8x16_wcd_priv);
+ return -ENOMEM;
+ }
+
+ set_bit(WCD9XXX_MBHC_CAL, msm8x16_wcd_priv->fw_data->cal_bit);
+ ret = wcd_cal_create_hwdep(msm8x16_wcd_priv->fw_data,
+ WCD9XXX_CODEC_HWDEP_NODE, codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
+ kfree(msm8x16_wcd_priv->fw_data);
+ kfree(msm8x16_wcd_priv);
+ return ret;
+ }
+
+ wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
+ wcd_mbhc_registers, true);
+
+ msm8x16_wcd_priv->mclk_enabled = false;
+ msm8x16_wcd_priv->clock_active = false;
+ msm8x16_wcd_priv->config_mode_active = false;
+
+ /*Update speaker boost configuration*/
+ msm8x16_wcd_priv->spk_boost_set = spkr_boost_en;
+ pr_err("%s: speaker boost configured = %d\n",
+ __func__, msm8x16_wcd_priv->spk_boost_set);
+
+ /* Set initial MICBIAS voltage level */
+ msm8x16_wcd_set_micb_v(codec);
+
+ /* Set initial cap mode */
+ msm8x16_wcd_configure_cap(codec, false, false);
+ registered_codec = codec;
+ adsp_state_notifier =
+ subsys_notif_register_notifier("adsp",
+ &adsp_state_notifier_block);
+ if (!adsp_state_notifier) {
+ dev_err(codec->dev, "Failed to register adsp state notifier\n");
+ kfree(msm8x16_wcd_priv->fw_data);
+ kfree(msm8x16_wcd_priv);
+ registered_codec = NULL;
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_remove(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+ struct msm8x16_wcd *msm8x16_wcd;
+
+ msm8x16_wcd = codec->control_data;
+ msm8x16_wcd_priv->spkdrv_reg = NULL;
+ msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].supply = NULL;
+ atomic_set(&msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
+ kfree(msm8x16_wcd_priv->fw_data);
+ kfree(msm8x16_wcd_priv);
+
+ return 0;
+}
+
+static int msm8x16_wcd_enable_static_supplies_to_optimum(
+ struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (pdata->regulator[i].ondemand)
+ continue;
+ if (regulator_count_voltages(msm8x16->supplies[i].consumer) <=
+ 0)
+ continue;
+
+ ret = regulator_set_voltage(msm8x16->supplies[i].consumer,
+ pdata->regulator[i].min_uv,
+ pdata->regulator[i].max_uv);
+ if (ret) {
+ dev_err(msm8x16->dev,
+ "Setting volt failed for regulator %s err %d\n",
+ msm8x16->supplies[i].supply, ret);
+ }
+
+ ret = regulator_set_load(msm8x16->supplies[i].consumer,
+ pdata->regulator[i].optimum_ua);
+ dev_err(msm8x16->dev, "Regulator %s set optimum mode\n",
+ msm8x16->supplies[i].supply);
+ }
+
+ return ret;
+}
+
+static int msm8x16_wcd_disable_static_supplies_to_optimum(
+ struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (pdata->regulator[i].ondemand)
+ continue;
+ if (regulator_count_voltages(msm8x16->supplies[i].consumer) <=
+ 0)
+ continue;
+ regulator_set_voltage(msm8x16->supplies[i].consumer, 0,
+ pdata->regulator[i].max_uv);
+ regulator_set_load(msm8x16->supplies[i].consumer, 0);
+ dev_err(msm8x16->dev, "Regulator %s set optimum mode\n",
+ msm8x16->supplies[i].supply);
+ }
+
+ return ret;
+}
+
+int msm8x16_wcd_suspend(struct snd_soc_codec *codec)
+{
+ struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm8x16_wcd *msm8x16 = codec->control_data;
+ struct msm8x16_wcd_pdata *msm8x16_pdata = msm8x16->dev->platform_data;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ pr_err("%s: mclk cnt = %d, mclk_enabled = %d\n",
+ __func__, atomic_read(&pdata->mclk_rsc_ref),
+ atomic_read(&pdata->mclk_enabled));
+ if (atomic_read(&pdata->mclk_enabled) == true) {
+ cancel_delayed_work_sync(
+ &pdata->disable_mclk_work);
+ mutex_lock(&pdata->cdc_mclk_mutex);
+ if (atomic_read(&pdata->mclk_enabled) == true) {
+ if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
+ pdata->digital_cdc_clk.clk_val = 0;
+ afe_set_digital_codec_core_clock(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_clk);
+ } else {
+ pdata->digital_cdc_core_clk.enable = 0;
+ afe_set_lpass_clock_v2(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ }
+ atomic_set(&pdata->mclk_enabled, false);
+ }
+ mutex_unlock(&pdata->cdc_mclk_mutex);
+ }
+ msm8x16_wcd_disable_static_supplies_to_optimum(msm8x16, msm8x16_pdata);
+ return 0;
+}
+
+int msm8x16_wcd_resume(struct snd_soc_codec *codec)
+{
+ struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm8x16_wcd *msm8x16 = codec->control_data;
+ struct msm8x16_wcd_pdata *msm8x16_pdata = msm8x16->dev->platform_data;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ msm8x16_wcd_enable_static_supplies_to_optimum(msm8x16, msm8x16_pdata);
+ return 0;
+}
+
+static struct regmap *msm89xx_pmic_cdc_regmap;
+static struct regmap *msm89xx_pmic_cdc_get_regmap(struct device *dev)
+{
+ return msm89xx_pmic_cdc_regmap;
+}
+
+static const struct snd_soc_codec_driver soc_codec_dev_msm8x16_wcd = {
+ .probe = msm8x16_wcd_codec_probe,
+ .remove = msm8x16_wcd_codec_remove,
+
+ .suspend = msm8x16_wcd_suspend,
+ .resume = msm8x16_wcd_resume,
+
+ .controls = msm8x16_wcd_snd_controls,
+ .num_controls = ARRAY_SIZE(msm8x16_wcd_snd_controls),
+ .dapm_widgets = msm8x16_wcd_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(msm8x16_wcd_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+ .get_regmap = msm89xx_pmic_cdc_get_regmap,
+};
+
+static int msm8x16_wcd_init_supplies(struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int ret;
+ int i;
+
+ msm8x16->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
+ ARRAY_SIZE(pdata->regulator),
+ GFP_KERNEL);
+ if (!msm8x16->supplies) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ msm8x16->num_of_supplies = 0;
+
+ if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
+ dev_err(msm8x16->dev, "%s: Array Size out of bound\n",
+ __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ if (pdata->regulator[i].name) {
+ msm8x16->supplies[i].supply = pdata->regulator[i].name;
+ msm8x16->num_of_supplies++;
+ }
+ }
+
+ ret = regulator_bulk_get(msm8x16->dev, msm8x16->num_of_supplies,
+ msm8x16->supplies);
+ if (ret != 0) {
+ dev_err(msm8x16->dev, "Failed to get supplies: err = %d\n",
+ ret);
+ goto err_supplies;
+ }
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (regulator_count_voltages(msm8x16->supplies[i].consumer) <=
+ 0)
+ continue;
+
+ ret = regulator_set_voltage(msm8x16->supplies[i].consumer,
+ pdata->regulator[i].min_uv,
+ pdata->regulator[i].max_uv);
+ if (ret) {
+ dev_err(msm8x16->dev, "Setting regulator voltage failed for regulator %s err = %d\n",
+ msm8x16->supplies[i].supply, ret);
+ goto err_get;
+ }
+
+ ret = regulator_set_load(msm8x16->supplies[i].consumer,
+ pdata->regulator[i].optimum_ua);
+ if (ret < 0) {
+ dev_err(msm8x16->dev, "Setting regulator optimum mode failed for regulator %s err = %d\n",
+ msm8x16->supplies[i].supply, ret);
+ goto err_get;
+ } else {
+ ret = 0;
+ }
+ }
+
+ return ret;
+
+err_get:
+ regulator_bulk_free(msm8x16->num_of_supplies, msm8x16->supplies);
+err_supplies:
+ kfree(msm8x16->supplies);
+err:
+ return ret;
+}
+
+static int msm8x16_wcd_enable_static_supplies(struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (pdata->regulator[i].ondemand)
+ continue;
+ ret = regulator_enable(msm8x16->supplies[i].consumer);
+ if (ret) {
+ dev_err(msm8x16->dev, "Failed to enable %s\n",
+ msm8x16->supplies[i].supply);
+ break;
+ }
+ dev_err(msm8x16->dev, "Enabled regulator %s\n",
+ msm8x16->supplies[i].supply);
+ }
+
+ while (ret && --i)
+ if (!pdata->regulator[i].ondemand)
+ regulator_disable(msm8x16->supplies[i].consumer);
+
+ return ret;
+}
+
+
+
+static void msm8x16_wcd_disable_supplies(struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int i;
+
+ regulator_bulk_disable(msm8x16->num_of_supplies,
+ msm8x16->supplies);
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (regulator_count_voltages(msm8x16->supplies[i].consumer) <=
+ 0)
+ continue;
+ regulator_set_voltage(msm8x16->supplies[i].consumer, 0,
+ pdata->regulator[i].max_uv);
+ regulator_set_load(msm8x16->supplies[i].consumer, 0);
+ }
+ regulator_bulk_free(msm8x16->num_of_supplies, msm8x16->supplies);
+ kfree(msm8x16->supplies);
+}
+
+static struct snd_soc_dai_driver msm_codec_dais[] = {
+ {
+ .name = "msm-codec-rx",
+ .playback = { /* Support maximum range */
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ },
+ {
+ .name = "msm-codec-tx",
+ .capture = { /* Support maximum range */
+ .stream_name = "Record",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ },
+};
+
+static struct regmap *msm89xx_codec_regmap;
+static struct regmap *msm89xx_codec_get_regmap(struct device *dev)
+{
+ return msm89xx_codec_regmap;
+}
+
+static struct snd_soc_codec_driver soc_msm89xx_codec = {
+ .probe = msm89xx_digcodec_probe,
+ .remove = msm89xx_digcodec_remove,
+ .get_regmap = msm89xx_codec_get_regmap,
+};
+
+static const struct of_device_id msm89xx_codec_of_match[] = {
+ { .compatible = "qcom,msm-codec-core",
+ .data = "msm_codec"},
+ { .compatible = "qcom,pmic-codec-digital",
+ .data = "pmic-digital-codec"},
+ { .compatible = "qcom,pmic-codec-analog",
+ .data = "pmic-analog-codec"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, msm89xx_codec_of_match);
+
+static struct msm8x16_wcd *temp_89xx;
+static int msm89xx_codec_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm8x16_wcd *msm8x16 = NULL;
+ struct msm8x16_wcd_pdata *pdata;
+ int adsp_state;
+ static int dev_registered_cnt;
+ const struct of_device_id *match;
+ const char *addr_prop_name = "qcom,dig-cdc-base-addr";
+ u32 dig_cdc_addr;
+ char __iomem *dig_base;
+
+ adsp_state = apr_get_subsys_state();
+ if (adsp_state != APR_SUBSYS_LOADED) {
+ dev_err(&pdev->dev, "Adsp is not loaded yet %d\n",
+ adsp_state);
+ return -EPROBE_DEFER;
+ }
+
+ match = of_match_node(msm89xx_codec_of_match,
+ pdev->dev.of_node);
+
+ dev_dbg(&pdev->dev, "%s(%d):%s\n",
+ __func__, __LINE__, (char *)match->data);
+
+ if (!strcmp(match->data, "pmic-digital-codec")) {
+ device_init_wakeup(&pdev->dev, true);
+
+ if (pdev->dev.of_node) {
+ dev_err(&pdev->dev, "%s:Platform data from device tree\n",
+ __func__);
+ pdata = msm8x16_wcd_populate_dt_pdata(&pdev->dev);
+ pdev->dev.platform_data = pdata;
+ } else {
+ dev_err(&pdev->dev, "%s:Platform data from board file\n",
+ __func__);
+ pdata = pdev->dev.platform_data;
+ }
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "%s:Platform data failed to populate\n",
+ __func__);
+ goto rtn;
+ }
+ msm8x16 = kzalloc(sizeof(struct msm8x16_wcd), GFP_KERNEL);
+ if (msm8x16 == NULL) {
+ ret = -ENOMEM;
+ goto rtn;
+ }
+
+ msm8x16->dev = &pdev->dev;
+ ret = msm8x16_wcd_init_supplies(msm8x16, pdata);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Fail to enable Codec supplies\n",
+ __func__);
+ goto err_codec;
+ }
+
+ ret = msm8x16_wcd_enable_static_supplies(msm8x16, pdata);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: Fail to enable Codec pre-reset supplies\n",
+ __func__);
+ goto err_codec;
+ }
+ usleep_range(5, 6);
+
+ mutex_init(&msm8x16->io_lock);
+ dev_set_drvdata(&pdev->dev, msm8x16);
+ temp_89xx = msm8x16;
+ dev_registered_cnt++;
+ } else if (!strcmp(match->data, "pmic-analog-codec")) {
+ if (wcd9xxx_spmi_irq_init()) {
+ dev_err(&pdev->dev,
+ "%s: irq initialization failed\n", __func__);
+ } else {
+ dev_err(&pdev->dev,
+ "%s: irq initialization passed\n", __func__);
+ }
+ dev_registered_cnt++;
+ } else if (!strcmp(match->data, "msm-codec")) {
+ ret = of_property_read_u32(pdev->dev.of_node, addr_prop_name,
+ &dig_cdc_addr);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+ __func__, addr_prop_name);
+ dig_cdc_addr = MSM89XX_DIGITAL_CODEC_BASE_ADDR;
+ }
+ dig_base = ioremap(dig_cdc_addr,
+ MSM89XX_DIGITAL_CODEC_REG_SIZE);
+ if (dig_base == NULL) {
+ dev_err(&pdev->dev, "%s ioremap failed\n", __func__);
+ return -ENOMEM;
+ }
+ msm89xx_codec_regmap =
+ devm_regmap_init_mmio_clk(&pdev->dev, NULL,
+ dig_base, &msm89xx_cdc_core_regmap_config);
+ snd_soc_register_codec(&pdev->dev, &soc_msm89xx_codec,
+ msm_codec_dais, ARRAY_SIZE(msm_codec_dais));
+ dev_registered_cnt++;
+ }
+
+ if ((dev_registered_cnt == MAX_MSM89XX_DEVICE) && (!ret)) {
+ msm89xx_pmic_cdc_regmap =
+ devm_regmap_init_spmi_ext(
+ (struct spmi_device *) &pdev->dev.parent,
+ &msm89xx_pmic_cdc_regmap_config);
+ ret = snd_soc_register_codec(temp_89xx->dev,
+ &soc_codec_dev_msm8x16_wcd,
+ msm8x16_wcd_i2s_dai,
+ ARRAY_SIZE(msm8x16_wcd_i2s_dai));
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s:snd_soc_register_codec failed with error %d\n",
+ __func__, ret);
+ goto err_supplies;
+ }
+ }
+ return ret;
+err_supplies:
+ msm8x16_wcd_disable_supplies(msm8x16, pdata);
+err_codec:
+ kfree(msm8x16);
+rtn:
+ return ret;
+}
+
+static int msm89xx_codec_remove(struct platform_device *pdev)
+{
+ struct msm8x16_wcd *msm8x16 = dev_get_drvdata(&pdev->dev);
+
+ mutex_destroy(&msm8x16->io_lock);
+ kfree(msm8x16);
+
+ return 0;
+}
+
+static struct platform_driver msm_codec_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .of_match_table = of_match_ptr(msm89xx_codec_of_match)
+ },
+ .probe = msm89xx_codec_probe,
+ .remove = msm89xx_codec_remove,
+};
+module_platform_driver(msm_codec_driver);
+
+MODULE_DESCRIPTION("MSM89xx Audio codec driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd.h b/sound/soc/codecs/msm8x16/msm8x16-wcd.h
new file mode 100644
index 000000000000..d2e782b07cb2
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm8x16-wcd.h
@@ -0,0 +1,341 @@
+/* Copyright (c) 2015-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.
+ */
+#ifndef MSM8X16_WCD_H
+#define MSM8X16_WCD_H
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/q6afe-v2.h>
+#include "../wcd-mbhc-v2.h"
+#include "../wcdcal-hwdep.h"
+#include "msm8x16_wcd_registers.h"
+
+#define MICBIAS_EXT_BYP_CAP 0x00
+#define MICBIAS_NO_EXT_BYP_CAP 0x01
+
+#define MSM89XX_NUM_IRQ_REGS 2
+#define MAX_REGULATOR 7
+#define MSM89XX_REG_VAL(reg, val) {reg, 0, val}
+#define MSM8X16_TOMBAK_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL 0xFE03B004
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_CMD_RCGR 0x0181C09C
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_CFG_RCGR 0x0181C0A0
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_M 0x0181C0A4
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_N 0x0181C0A8
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_D 0x0181C0AC
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_CBCR 0x0181C0B0
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_AHB_CBCR 0x0181C0B4
+
+#define MSM8X16_CODEC_NAME "msm8x16_wcd_codec"
+
+#define MSM89XX_IS_CDC_CORE_REG(reg) \
+ (((reg >= 0x00) && (reg <= 0x3FF)) ? 1 : 0)
+#define MSM89XX_IS_PMIC_CDC_REG(reg) \
+ (((reg >= 0xF000) && (reg <= 0xF1FF)) ? 1 : 0)
+/*
+ * MCLK activity indicators during suspend and resume call
+ */
+#define MCLK_SUS_DIS 1
+#define MCLK_SUS_RSC 2
+#define MCLK_SUS_NO_ACT 3
+
+#define NUM_DECIMATORS 4
+#define MSM89XX_VDD_SPKDRV_NAME "cdc-vdd-spkdrv"
+
+#define DEFAULT_MULTIPLIER 800
+#define DEFAULT_GAIN 9
+#define DEFAULT_OFFSET 100
+
+extern const u8 msm89xx_pmic_cdc_reg_readable[MSM89XX_PMIC_CDC_CACHE_SIZE];
+extern const u8 msm89xx_cdc_core_reg_readable[MSM89XX_CDC_CORE_CACHE_SIZE];
+extern struct regmap_config msm89xx_cdc_core_regmap_config;
+extern struct regmap_config msm89xx_pmic_cdc_regmap_config;
+
+enum codec_versions {
+ TOMBAK_1_0,
+ TOMBAK_2_0,
+ CONGA,
+ CAJON,
+ CAJON_2_0,
+ DIANGU,
+ UNSUPPORTED,
+};
+
+/* Support different hph modes */
+enum {
+ NORMAL_MODE = 0,
+ HD2_MODE,
+};
+
+/* Codec supports 1 compander */
+enum {
+ COMPANDER_NONE = 0,
+ COMPANDER_1, /* HPHL/R */
+ COMPANDER_MAX,
+};
+
+enum wcd_curr_ref {
+ I_h4_UA = 0,
+ I_pt5_UA,
+ I_14_UA,
+ I_l4_UA,
+ I_1_UA,
+};
+
+enum wcd_mbhc_imp_det_pin {
+ WCD_MBHC_DET_NONE = 0,
+ WCD_MBHC_DET_HPHL,
+ WCD_MBHC_DET_HPHR,
+ WCD_MBHC_DET_BOTH,
+};
+
+
+/* Each micbias can be assigned to one of three cfilters
+ * Vbatt_min >= .15V + ldoh_v
+ * ldoh_v >= .15v + cfiltx_mv
+ * If ldoh_v = 1.95 160 mv < cfiltx_mv < 1800 mv
+ * If ldoh_v = 2.35 200 mv < cfiltx_mv < 2200 mv
+ * If ldoh_v = 2.75 240 mv < cfiltx_mv < 2600 mv
+ * If ldoh_v = 2.85 250 mv < cfiltx_mv < 2700 mv
+ */
+
+struct wcd9xxx_micbias_setting {
+ u8 ldoh_v;
+ u32 cfilt1_mv; /* in mv */
+ u32 cfilt2_mv; /* in mv */
+ u32 cfilt3_mv; /* in mv */
+ /* Different WCD9xxx series codecs may not
+ * have 4 mic biases. If a codec has fewer
+ * mic biases, some of these properties will
+ * not be used.
+ */
+ u8 bias1_cfilt_sel;
+ u8 bias2_cfilt_sel;
+ u8 bias3_cfilt_sel;
+ u8 bias4_cfilt_sel;
+ u8 bias1_cap_mode;
+ u8 bias2_cap_mode;
+ u8 bias3_cap_mode;
+ u8 bias4_cap_mode;
+ bool bias2_is_headset_only;
+};
+
+enum msm8x16_wcd_pid_current {
+ MSM89XX_PID_MIC_2P5_UA,
+ MSM89XX_PID_MIC_5_UA,
+ MSM89XX_PID_MIC_10_UA,
+ MSM89XX_PID_MIC_20_UA,
+};
+
+struct msm8x16_wcd_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
+enum msm8x16_wcd_mbhc_analog_pwr_cfg {
+ MSM89XX_ANALOG_PWR_COLLAPSED = 0,
+ MSM89XX_ANALOG_PWR_ON,
+ MSM89XX_NUM_ANALOG_PWR_CONFIGS,
+};
+
+/* Number of input and output I2S port */
+enum {
+ MSM89XX_RX1 = 0,
+ MSM89XX_RX2,
+ MSM89XX_RX3,
+ MSM89XX_RX_MAX,
+};
+
+enum {
+ MSM89XX_TX1 = 0,
+ MSM89XX_TX2,
+ MSM89XX_TX3,
+ MSM89XX_TX4,
+ MSM89XX_TX_MAX,
+};
+
+enum {
+ /* INTR_REG 0 - Digital Periph */
+ MSM89XX_IRQ_SPKR_CNP = 0,
+ MSM89XX_IRQ_SPKR_CLIP,
+ MSM89XX_IRQ_SPKR_OCP,
+ MSM89XX_IRQ_MBHC_INSREM_DET1,
+ MSM89XX_IRQ_MBHC_RELEASE,
+ MSM89XX_IRQ_MBHC_PRESS,
+ MSM89XX_IRQ_MBHC_INSREM_DET,
+ MSM89XX_IRQ_MBHC_HS_DET,
+ /* INTR_REG 1 - Analog Periph */
+ MSM89XX_IRQ_EAR_OCP,
+ MSM89XX_IRQ_HPHR_OCP,
+ MSM89XX_IRQ_HPHL_OCP,
+ MSM89XX_IRQ_EAR_CNP,
+ MSM89XX_IRQ_HPHR_CNP,
+ MSM89XX_IRQ_HPHL_CNP,
+ MSM89XX_NUM_IRQS,
+};
+
+enum {
+ ON_DEMAND_MICBIAS = 0,
+ ON_DEMAND_SPKDRV,
+ ON_DEMAND_SUPPLIES_MAX,
+};
+
+/*
+ * The delay list is per codec HW specification.
+ * Please add delay in the list in the future instead
+ * of magic number
+ */
+enum {
+ CODEC_DELAY_1_MS = 1000,
+ CODEC_DELAY_1_1_MS = 1100,
+};
+
+struct msm8x16_wcd_regulator {
+ const char *name;
+ int min_uv;
+ int max_uv;
+ int optimum_ua;
+ bool ondemand;
+ struct regulator *regulator;
+};
+
+struct on_demand_supply {
+ struct regulator *supply;
+ atomic_t ref;
+};
+
+struct wcd_imped_i_ref {
+ enum wcd_curr_ref curr_ref;
+ int min_val;
+ int multiplier;
+ int gain_adj;
+ int offset;
+};
+
+struct msm8916_asoc_mach_data {
+ int codec_type;
+ int ext_pa;
+ int us_euro_gpio;
+ int spk_ext_pa_gpio;
+ int mclk_freq;
+ int lb_mode;
+ int afe_clk_ver;
+ u8 micbias1_cap_mode;
+ u8 micbias2_cap_mode;
+ atomic_t mclk_rsc_ref;
+ atomic_t mclk_enabled;
+ atomic_t wsa_mclk_rsc_ref;
+ struct mutex cdc_mclk_mutex;
+ struct mutex wsa_mclk_mutex;
+ struct delayed_work disable_mclk_work;
+ struct afe_digital_clk_cfg digital_cdc_clk;
+ struct afe_clk_set digital_cdc_core_clk;
+ void __iomem *vaddr_gpio_mux_spkr_ctl;
+ void __iomem *vaddr_gpio_mux_mic_ctl;
+ void __iomem *vaddr_gpio_mux_quin_ctl;
+ void __iomem *vaddr_gpio_mux_pcm_ctl;
+ struct on_demand_supply wsa_switch_supply;
+};
+
+struct msm8x16_wcd_pdata {
+ int irq;
+ int irq_base;
+ int num_irqs;
+ int reset_gpio;
+ void *msm8x16_wcd_ahb_base_vaddr;
+ struct wcd9xxx_micbias_setting micbias;
+ struct msm8x16_wcd_regulator regulator[MAX_REGULATOR];
+ u32 mclk_rate;
+ u32 is_lpass;
+};
+
+enum msm8x16_wcd_micbias_num {
+ MSM89XX_MICBIAS1 = 0,
+};
+
+struct msm8x16_wcd {
+ struct device *dev;
+ struct mutex io_lock;
+ u8 version;
+
+ int reset_gpio;
+ int (*read_dev)(struct snd_soc_codec *codec,
+ unsigned short reg);
+ int (*write_dev)(struct snd_soc_codec *codec,
+ unsigned short reg, u8 val);
+
+ u32 num_of_supplies;
+ struct regulator_bulk_data *supplies;
+
+ u8 idbyte[4];
+
+ int num_irqs;
+ u32 mclk_rate;
+};
+
+struct msm8x16_wcd_priv {
+ struct snd_soc_codec *codec;
+ u16 pmic_rev;
+ u16 codec_version;
+ u32 boost_voltage;
+ u32 adc_count;
+ u32 rx_bias_count;
+ s32 dmic_1_2_clk_cnt;
+ u32 mute_mask;
+ bool mclk_enabled;
+ bool clock_active;
+ bool config_mode_active;
+ u16 boost_option;
+ /* mode to select hd2 */
+ u32 hph_mode;
+ /* compander used for each rx chain */
+ u32 comp_enabled[MSM89XX_RX_MAX];
+ bool spk_boost_set;
+ bool ear_pa_boost_set;
+ bool ext_spk_boost_set;
+ bool dec_active[NUM_DECIMATORS];
+ struct on_demand_supply on_demand_list[ON_DEMAND_SUPPLIES_MAX];
+ struct regulator *spkdrv_reg;
+ /* mbhc module */
+ struct wcd_mbhc mbhc;
+ /* cal info for codec */
+ struct fw_info *fw_data;
+ struct blocking_notifier_head notifier;
+ int (*codec_spk_ext_pa_cb)(struct snd_soc_codec *codec, int enable);
+ int (*codec_hph_comp_gpio)(bool enable);
+ unsigned long status_mask;
+ struct wcd_imped_i_ref imped_i_ref;
+ enum wcd_mbhc_imp_det_pin imped_det_pin;
+};
+
+extern int msm8x16_wcd_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
+ bool dapm);
+
+extern int msm8x16_wcd_hs_detect(struct snd_soc_codec *codec,
+ struct wcd_mbhc_config *mbhc_cfg);
+
+extern void msm8x16_wcd_hs_detect_exit(struct snd_soc_codec *codec);
+
+extern void msm8x16_update_int_spk_boost(bool enable);
+
+extern void msm8x16_wcd_spk_ext_pa_cb(
+ int (*codec_spk_ext_pa)(struct snd_soc_codec *codec,
+ int enable), struct snd_soc_codec *codec);
+
+extern void msm8x16_wcd_hph_comp_cb(
+ int (*codec_hph_comp_gpio)(bool enable),
+ struct snd_soc_codec *codec);
+void enable_digital_callback(void *flag);
+void disable_digital_callback(void *flag);
+
+#endif
+
diff --git a/sound/soc/codecs/msm8x16/msm8x16_wcd_registers.h b/sound/soc/codecs/msm8x16/msm8x16_wcd_registers.h
new file mode 100644
index 000000000000..280e6f28682a
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm8x16_wcd_registers.h
@@ -0,0 +1,585 @@
+ /* Copyright (c) 2015-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.
+ */
+#ifndef MSM8X16_WCD_REGISTERS_H
+#define MSM8X16_WCD_REGISTERS_H
+
+#define CDC_DIG_BASE 0xF000
+#define CDC_ANA_BASE 0xF100
+
+#define MSM89XX_PMIC_DIGITAL_REVISION1 (CDC_DIG_BASE+0x000)
+#define MSM89XX_PMIC_DIGITAL_REVISION1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_REVISION2 (CDC_DIG_BASE+0x001)
+#define MSM89XX_PMIC_DIGITAL_REVISION2__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PERPH_TYPE (CDC_DIG_BASE+0x004)
+#define MSM89XX_PMIC_DIGITAL_PERPH_TYPE__POR (0x23)
+#define MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE (CDC_DIG_BASE+0x005)
+#define MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE__POR (0x01)
+#define MSM89XX_PMIC_DIGITAL_INT_RT_STS (CDC_DIG_BASE+0x010)
+#define MSM89XX_PMIC_DIGITAL_INT_RT_STS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_SET_TYPE (CDC_DIG_BASE+0x011)
+#define MSM89XX_PMIC_DIGITAL_INT_SET_TYPE__POR (0xFF)
+#define MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH (CDC_DIG_BASE+0x012)
+#define MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH__POR (0xFF)
+#define MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW (CDC_DIG_BASE+0x013)
+#define MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_LATCHED_CLR (CDC_DIG_BASE+0x014)
+#define MSM89XX_PMIC_DIGITAL_INT_LATCHED_CLR__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_EN_SET (CDC_DIG_BASE+0x015)
+#define MSM89XX_PMIC_DIGITAL_INT_EN_SET__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_EN_CLR (CDC_DIG_BASE+0x016)
+#define MSM89XX_PMIC_DIGITAL_INT_EN_CLR__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS (CDC_DIG_BASE+0x018)
+#define MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_PENDING_STS (CDC_DIG_BASE+0x019)
+#define MSM89XX_PMIC_DIGITAL_INT_PENDING_STS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_MID_SEL (CDC_DIG_BASE+0x01A)
+#define MSM89XX_PMIC_DIGITAL_INT_MID_SEL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_PRIORITY (CDC_DIG_BASE+0x01B)
+#define MSM89XX_PMIC_DIGITAL_INT_PRIORITY__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_GPIO_MODE (CDC_DIG_BASE+0x040)
+#define MSM89XX_PMIC_DIGITAL_GPIO_MODE__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PIN_CTL_OE (CDC_DIG_BASE+0x041)
+#define MSM89XX_PMIC_DIGITAL_PIN_CTL_OE__POR (0x01)
+#define MSM89XX_PMIC_DIGITAL_PIN_CTL_DATA (CDC_DIG_BASE+0x042)
+#define MSM89XX_PMIC_DIGITAL_PIN_CTL_DATA__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PIN_STATUS (CDC_DIG_BASE+0x043)
+#define MSM89XX_PMIC_DIGITAL_PIN_STATUS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_HDRIVE_CTL (CDC_DIG_BASE+0x044)
+#define MSM89XX_PMIC_DIGITAL_HDRIVE_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_RST_CTL (CDC_DIG_BASE+0x046)
+#define MSM89XX_PMIC_DIGITAL_CDC_RST_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL (CDC_DIG_BASE+0x048)
+#define MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL (CDC_DIG_BASE+0x049)
+#define MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL (CDC_DIG_BASE+0x04A)
+#define MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL (CDC_DIG_BASE+0x050)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL__POR (0x02)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL (CDC_DIG_BASE+0x051)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL__POR (0x02)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL (CDC_DIG_BASE+0x052)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX1_CTL (CDC_DIG_BASE+0x053)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX1_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX2_CTL (CDC_DIG_BASE+0x054)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX2_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX3_CTL (CDC_DIG_BASE+0x055)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX3_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX_LB_CTL (CDC_DIG_BASE+0x056)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX_LB_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL1 (CDC_DIG_BASE+0x058)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL1__POR (0x7C)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL2 (CDC_DIG_BASE+0x059)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL2__POR (0x7C)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL3 (CDC_DIG_BASE+0x05A)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL3__POR (0x7C)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA0 (CDC_DIG_BASE+0x05B)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA0__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA1 (CDC_DIG_BASE+0x05C)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA2 (CDC_DIG_BASE+0x05D)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA2__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA3 (CDC_DIG_BASE+0x05E)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA3__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DIG_DEBUG_CTL (CDC_DIG_BASE+0x068)
+#define MSM89XX_PMIC_DIGITAL_DIG_DEBUG_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DIG_DEBUG_EN (CDC_DIG_BASE+0x069)
+#define MSM89XX_PMIC_DIGITAL_DIG_DEBUG_EN__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_SPARE_0 (CDC_DIG_BASE+0x070)
+#define MSM89XX_PMIC_DIGITAL_SPARE_0__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_SPARE_1 (CDC_DIG_BASE+0x071)
+#define MSM89XX_PMIC_DIGITAL_SPARE_1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_SPARE_2 (CDC_DIG_BASE+0x072)
+#define MSM89XX_PMIC_DIGITAL_SPARE_2__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_SEC_ACCESS (CDC_DIG_BASE+0x0D0)
+#define MSM89XX_PMIC_DIGITAL_SEC_ACCESS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL1 (CDC_DIG_BASE+0x0D8)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL2 (CDC_DIG_BASE+0x0D9)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL2__POR (0x01)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3 (CDC_DIG_BASE+0x0DA)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3__POR (0x05)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4 (CDC_DIG_BASE+0x0DB)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_TEST1 (CDC_DIG_BASE+0x0E0)
+#define MSM89XX_PMIC_DIGITAL_INT_TEST1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_TEST_VAL (CDC_DIG_BASE+0x0E1)
+#define MSM89XX_PMIC_DIGITAL_INT_TEST_VAL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_TRIM_NUM (CDC_DIG_BASE+0x0F0)
+#define MSM89XX_PMIC_DIGITAL_TRIM_NUM__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_TRIM_CTRL (CDC_DIG_BASE+0x0F1)
+#define MSM89XX_PMIC_DIGITAL_TRIM_CTRL__POR (0x00)
+
+#define MSM89XX_PMIC_ANALOG_REVISION1 (CDC_ANA_BASE+0x00)
+#define MSM89XX_PMIC_ANALOG_REVISION1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_REVISION2 (CDC_ANA_BASE+0x01)
+#define MSM89XX_PMIC_ANALOG_REVISION2__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_REVISION3 (CDC_ANA_BASE+0x02)
+#define MSM89XX_PMIC_ANALOG_REVISION3__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_REVISION4 (CDC_ANA_BASE+0x03)
+#define MSM89XX_PMIC_ANALOG_REVISION4__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PERPH_TYPE (CDC_ANA_BASE+0x04)
+#define MSM89XX_PMIC_ANALOG_PERPH_TYPE__POR (0x23)
+#define MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE (CDC_ANA_BASE+0x05)
+#define MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE__POR (0x09)
+#define MSM89XX_PMIC_ANALOG_INT_RT_STS (CDC_ANA_BASE+0x10)
+#define MSM89XX_PMIC_ANALOG_INT_RT_STS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_SET_TYPE (CDC_ANA_BASE+0x11)
+#define MSM89XX_PMIC_ANALOG_INT_SET_TYPE__POR (0x3F)
+#define MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH (CDC_ANA_BASE+0x12)
+#define MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH__POR (0x3F)
+#define MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW (CDC_ANA_BASE+0x13)
+#define MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_LATCHED_CLR (CDC_ANA_BASE+0x14)
+#define MSM89XX_PMIC_ANALOG_INT_LATCHED_CLR__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_EN_SET (CDC_ANA_BASE+0x15)
+#define MSM89XX_PMIC_ANALOG_INT_EN_SET__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_EN_CLR (CDC_ANA_BASE+0x16)
+#define MSM89XX_PMIC_ANALOG_INT_EN_CLR__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_LATCHED_STS (CDC_ANA_BASE+0x18)
+#define MSM89XX_PMIC_ANALOG_INT_LATCHED_STS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_PENDING_STS (CDC_ANA_BASE+0x19)
+#define MSM89XX_PMIC_ANALOG_INT_PENDING_STS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_MID_SEL (CDC_ANA_BASE+0x1A)
+#define MSM89XX_PMIC_ANALOG_INT_MID_SEL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_PRIORITY (CDC_ANA_BASE+0x1B)
+#define MSM89XX_PMIC_ANALOG_INT_PRIORITY__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MICB_1_EN (CDC_ANA_BASE+0x40)
+#define MSM89XX_PMIC_ANALOG_MICB_1_EN__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MICB_1_VAL (CDC_ANA_BASE+0x41)
+#define MSM89XX_PMIC_ANALOG_MICB_1_VAL__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_MICB_1_CTL (CDC_ANA_BASE+0x42)
+#define MSM89XX_PMIC_ANALOG_MICB_1_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS (CDC_ANA_BASE+0x43)
+#define MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS__POR (0x49)
+#define MSM89XX_PMIC_ANALOG_MICB_2_EN (CDC_ANA_BASE+0x44)
+#define MSM89XX_PMIC_ANALOG_MICB_2_EN__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2 (CDC_ANA_BASE+0x45)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL (CDC_ANA_BASE+0x46)
+#define MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1 (CDC_ANA_BASE+0x47)
+#define MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1__POR (0x35)
+#define MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2 (CDC_ANA_BASE+0x50)
+#define MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2__POR (0x08)
+#define MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL (CDC_ANA_BASE+0x51)
+#define MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER (CDC_ANA_BASE+0x52)
+#define MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER__POR (0x98)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL (CDC_ANA_BASE+0x53)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL (CDC_ANA_BASE+0x54)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL (CDC_ANA_BASE+0x55)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL__POR (0x40)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL (CDC_ANA_BASE+0x56)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL__POR (0x61)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN4_CTL (CDC_ANA_BASE+0x57)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN4_CTL__POR (0x80)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT (CDC_ANA_BASE+0x58)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT (CDC_ANA_BASE+0x59)
+#define MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TX_1_EN (CDC_ANA_BASE+0x60)
+#define MSM89XX_PMIC_ANALOG_TX_1_EN__POR (0x03)
+#define MSM89XX_PMIC_ANALOG_TX_2_EN (CDC_ANA_BASE+0x61)
+#define MSM89XX_PMIC_ANALOG_TX_2_EN__POR (0x03)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_1 (CDC_ANA_BASE+0x62)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_1__POR (0xBF)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2 (CDC_ANA_BASE+0x63)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2__POR (0x8C)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL (CDC_ANA_BASE+0x64)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS (CDC_ANA_BASE+0x65)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS__POR (0x6B)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV (CDC_ANA_BASE+0x66)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV__POR (0x51)
+#define MSM89XX_PMIC_ANALOG_TX_3_EN (CDC_ANA_BASE+0x67)
+#define MSM89XX_PMIC_ANALOG_TX_3_EN__POR (0x02)
+#define MSM89XX_PMIC_ANALOG_NCP_EN (CDC_ANA_BASE+0x80)
+#define MSM89XX_PMIC_ANALOG_NCP_EN__POR (0x26)
+#define MSM89XX_PMIC_ANALOG_NCP_CLK (CDC_ANA_BASE+0x81)
+#define MSM89XX_PMIC_ANALOG_NCP_CLK__POR (0x23)
+#define MSM89XX_PMIC_ANALOG_NCP_DEGLITCH (CDC_ANA_BASE+0x82)
+#define MSM89XX_PMIC_ANALOG_NCP_DEGLITCH__POR (0x5B)
+#define MSM89XX_PMIC_ANALOG_NCP_FBCTRL (CDC_ANA_BASE+0x83)
+#define MSM89XX_PMIC_ANALOG_NCP_FBCTRL__POR (0x08)
+#define MSM89XX_PMIC_ANALOG_NCP_BIAS (CDC_ANA_BASE+0x84)
+#define MSM89XX_PMIC_ANALOG_NCP_BIAS__POR (0x29)
+#define MSM89XX_PMIC_ANALOG_NCP_VCTRL (CDC_ANA_BASE+0x85)
+#define MSM89XX_PMIC_ANALOG_NCP_VCTRL__POR (0x24)
+#define MSM89XX_PMIC_ANALOG_NCP_TEST (CDC_ANA_BASE+0x86)
+#define MSM89XX_PMIC_ANALOG_NCP_TEST__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_NCP_CLIM_ADDR (CDC_ANA_BASE+0x87)
+#define MSM89XX_PMIC_ANALOG_NCP_CLIM_ADDR__POR (0xD5)
+#define MSM89XX_PMIC_ANALOG_RX_CLOCK_DIVIDER (CDC_ANA_BASE+0x90)
+#define MSM89XX_PMIC_ANALOG_RX_CLOCK_DIVIDER__POR (0xE8)
+#define MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL (CDC_ANA_BASE+0x91)
+#define MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL__POR (0xCF)
+#define MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT (CDC_ANA_BASE+0x92)
+#define MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT__POR (0x6E)
+#define MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC (CDC_ANA_BASE+0x93)
+#define MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC__POR (0x18)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA (CDC_ANA_BASE+0x94)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA__POR (0x5A)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_LDO_OCP (CDC_ANA_BASE+0x95)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_LDO_OCP__POR (0x69)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP (CDC_ANA_BASE+0x96)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP__POR (0x29)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN (CDC_ANA_BASE+0x97)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN__POR (0x80)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_CTL (CDC_ANA_BASE+0x98)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_CTL__POR (0xDA)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME (CDC_ANA_BASE+0x99)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME__POR (0x16)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST (CDC_ANA_BASE+0x9A)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL (CDC_ANA_BASE+0x9B)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST (CDC_ANA_BASE+0x9C)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL (CDC_ANA_BASE+0x9D)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_RX_EAR_CTL (CDC_ANA_BASE+0x9E)
+#define MSM89XX_PMIC_ANALOG_RX_EAR_CTL___POR (0x12)
+#define MSM89XX_PMIC_ANALOG_RX_ATEST (CDC_ANA_BASE+0x9F)
+#define MSM89XX_PMIC_ANALOG_RX_ATEST__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_STATUS (CDC_ANA_BASE+0xA0)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_STATUS__POR (0x0C)
+#define MSM89XX_PMIC_ANALOG_RX_EAR_STATUS (CDC_ANA_BASE+0xA1)
+#define MSM89XX_PMIC_ANALOG_RX_EAR_STATUS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL (CDC_ANA_BASE+0xAC)
+#define MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL (CDC_ANA_BASE+0xAD)
+#define MSM89XX_PMIC_ANALOG_RX_RX_LO_EN_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL (CDC_ANA_BASE+0xB0)
+#define MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL__POR (0x83)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_CLIP_DET (CDC_ANA_BASE+0xB1)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_CLIP_DET__POR (0x91)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL (CDC_ANA_BASE+0xB2)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL__POR (0x29)
+#define MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET (CDC_ANA_BASE+0xB3)
+#define MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET__POR (0x4D)
+#define MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL (CDC_ANA_BASE+0xB4)
+#define MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL__POR (0xE1)
+#define MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL (CDC_ANA_BASE+0xB5)
+#define MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL__POR (0x1E)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_MISC (CDC_ANA_BASE+0xB6)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_MISC__POR (0xCB)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG (CDC_ANA_BASE+0xB7)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_CURRENT_LIMIT (CDC_ANA_BASE+0xC0)
+#define MSM89XX_PMIC_ANALOG_CURRENT_LIMIT__POR (0x02)
+#define MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE (CDC_ANA_BASE+0xC1)
+#define MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE__POR (0x14)
+#define MSM89XX_PMIC_ANALOG_BYPASS_MODE (CDC_ANA_BASE+0xC2)
+#define MSM89XX_PMIC_ANALOG_BYPASS_MODE__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_BOOST_EN_CTL (CDC_ANA_BASE+0xC3)
+#define MSM89XX_PMIC_ANALOG_BOOST_EN_CTL__POR (0x1F)
+#define MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO (CDC_ANA_BASE+0xC4)
+#define MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO__POR (0x8C)
+#define MSM89XX_PMIC_ANALOG_RDSON_MAX_DUTY_CYCLE (CDC_ANA_BASE+0xC5)
+#define MSM89XX_PMIC_ANALOG_RDSON_MAX_DUTY_CYCLE__POR (0xC0)
+#define MSM89XX_PMIC_ANALOG_BOOST_TEST1_1 (CDC_ANA_BASE+0xC6)
+#define MSM89XX_PMIC_ANALOG_BOOST_TEST1_1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_BOOST_TEST_2 (CDC_ANA_BASE+0xC7)
+#define MSM89XX_PMIC_ANALOG_BOOST_TEST_2__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS (CDC_ANA_BASE+0xC8)
+#define MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS (CDC_ANA_BASE+0xC9)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PBUS_ADD_CSR (CDC_ANA_BASE+0xCE)
+#define MSM89XX_PMIC_ANALOG_PBUS_ADD_CSR__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PBUS_ADD_SEL (CDC_ANA_BASE+0xCF)
+#define MSM89XX_PMIC_ANALOG_PBUS_ADD_SEL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_SEC_ACCESS (CDC_ANA_BASE+0xD0)
+#define MSM89XX_PMIC_ANALOG_SEC_ACCESS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL1 (CDC_ANA_BASE+0xD8)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL2 (CDC_ANA_BASE+0xD9)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL2__POR (0x01)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3 (CDC_ANA_BASE+0xDA)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3__POR (0x05)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4 (CDC_ANA_BASE+0xDB)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_TEST1 (CDC_ANA_BASE+0xE0)
+#define MSM89XX_PMIC_ANALOG_INT_TEST1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_TEST_VAL (CDC_ANA_BASE+0xE1)
+#define MSM89XX_PMIC_ANALOG_INT_TEST_VAL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TRIM_NUM (CDC_ANA_BASE+0xF0)
+#define MSM89XX_PMIC_ANALOG_TRIM_NUM__POR (0x04)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL1 (CDC_ANA_BASE+0xF1)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL2 (CDC_ANA_BASE+0xF2)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL2__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL3 (CDC_ANA_BASE+0xF3)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL3__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL4 (CDC_ANA_BASE+0xF4)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL4__POR (0x00)
+
+#define MSM89XX_PMIC_CDC_NUM_REGISTERS \
+ (MSM89XX_PMIC_ANALOG_TRIM_CTRL4+1)
+#define MSM89XX_PMIC_CDC_MAX_REGISTER \
+ (MSM89XX_PMIC_CDC_NUM_REGISTERS-1)
+#define MSM89XX_PMIC_CDC_CACHE_SIZE \
+ MSM89XX_PMIC_CDC_NUM_REGISTERS
+
+
+#define MSM89XX_CDC_CORE_CLK_RX_RESET_CTL (0x00)
+#define MSM89XX_CDC_CORE_CLK_RX_RESET_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL (0x04)
+#define MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL (0x08)
+#define MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_RX_I2S_CTL (0x0C)
+#define MSM89XX_CDC_CORE_CLK_RX_I2S_CTL__POR (0x13)
+#define MSM89XX_CDC_CORE_CLK_TX_I2S_CTL (0x10)
+#define MSM89XX_CDC_CORE_CLK_TX_I2S_CTL__POR (0x13)
+#define MSM89XX_CDC_CORE_CLK_OTHR_RESET_B1_CTL (0x14)
+#define MSM89XX_CDC_CORE_CLK_OTHR_RESET_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL (0x18)
+#define MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_OTHR_CTL (0x1C)
+#define MSM89XX_CDC_CORE_CLK_OTHR_CTL__POR (0x04)
+#define MSM89XX_CDC_CORE_CLK_RX_B1_CTL (0x20)
+#define MSM89XX_CDC_CORE_CLK_RX_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_MCLK_CTL (0x24)
+#define MSM89XX_CDC_CORE_CLK_MCLK_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_PDM_CTL (0x28)
+#define MSM89XX_CDC_CORE_CLK_PDM_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_SD_CTL (0x2C)
+#define MSM89XX_CDC_CORE_CLK_SD_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL (0x30)
+#define MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_RX_B2_CTL (0x34)
+#define MSM89XX_CDC_CORE_CLK_RX_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B1_CTL (0x40)
+#define MSM89XX_CDC_CORE_RX1_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B1_CTL (0x60)
+#define MSM89XX_CDC_CORE_RX2_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B1_CTL (0x80)
+#define MSM89XX_CDC_CORE_RX3_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B2_CTL (0x44)
+#define MSM89XX_CDC_CORE_RX1_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B2_CTL (0x64)
+#define MSM89XX_CDC_CORE_RX2_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B2_CTL (0x84)
+#define MSM89XX_CDC_CORE_RX3_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B3_CTL (0x48)
+#define MSM89XX_CDC_CORE_RX1_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B3_CTL (0x68)
+#define MSM89XX_CDC_CORE_RX2_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B3_CTL (0x88)
+#define MSM89XX_CDC_CORE_RX3_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B4_CTL (0x4C)
+#define MSM89XX_CDC_CORE_RX1_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B4_CTL (0x6C)
+#define MSM89XX_CDC_CORE_RX2_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B4_CTL (0x8C)
+#define MSM89XX_CDC_CORE_RX3_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B5_CTL (0x50)
+#define MSM89XX_CDC_CORE_RX1_B5_CTL__POR (0x68)
+#define MSM89XX_CDC_CORE_RX2_B5_CTL (0x70)
+#define MSM89XX_CDC_CORE_RX2_B5_CTL__POR (0x68)
+#define MSM89XX_CDC_CORE_RX3_B5_CTL (0x90)
+#define MSM89XX_CDC_CORE_RX3_B5_CTL__POR (0x68)
+#define MSM89XX_CDC_CORE_RX1_B6_CTL (0x54)
+#define MSM89XX_CDC_CORE_RX1_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B6_CTL (0x74)
+#define MSM89XX_CDC_CORE_RX2_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B6_CTL (0x94)
+#define MSM89XX_CDC_CORE_RX3_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_VOL_CTL_B1_CTL (0x58)
+#define MSM89XX_CDC_CORE_RX1_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_VOL_CTL_B1_CTL (0x78)
+#define MSM89XX_CDC_CORE_RX2_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_VOL_CTL_B1_CTL (0x98)
+#define MSM89XX_CDC_CORE_RX3_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL (0x5C)
+#define MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL (0x7C)
+#define MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL (0x9C)
+#define MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TOP_GAIN_UPDATE (0xA0)
+#define MSM89XX_CDC_CORE_TOP_GAIN_UPDATE__POR (0x00)
+#define MSM89XX_CDC_CORE_TOP_CTL (0xA4)
+#define MSM89XX_CDC_CORE_TOP_CTL__POR (0x01)
+#define MSM89XX_CDC_CORE_COMP0_B1_CTL (0xB0)
+#define MSM89XX_CDC_CORE_COMP0_B1_CTL__POR (0x30)
+#define MSM89XX_CDC_CORE_COMP0_B2_CTL (0xB4)
+#define MSM89XX_CDC_CORE_COMP0_B2_CTL__POR (0xB5)
+#define MSM89XX_CDC_CORE_COMP0_B3_CTL (0xB8)
+#define MSM89XX_CDC_CORE_COMP0_B3_CTL__POR (0x28)
+#define MSM89XX_CDC_CORE_COMP0_B4_CTL (0xBC)
+#define MSM89XX_CDC_CORE_COMP0_B4_CTL__POR (0x37)
+#define MSM89XX_CDC_CORE_COMP0_B5_CTL (0xC0)
+#define MSM89XX_CDC_CORE_COMP0_B5_CTL__POR (0x7F)
+#define MSM89XX_CDC_CORE_COMP0_B6_CTL (0xC4)
+#define MSM89XX_CDC_CORE_COMP0_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_COMP0_SHUT_DOWN_STATUS (0xC8)
+#define MSM89XX_CDC_CORE_COMP0_SHUT_DOWN_STATUS__POR (0x03)
+#define MSM89XX_CDC_CORE_COMP0_FS_CFG (0xCC)
+#define MSM89XX_CDC_CORE_COMP0_FS_CFG__POR (0x03)
+#define MSM89XX_CDC_CORE_COMP0_DELAY_BUF_CTL (0xD0)
+#define MSM89XX_CDC_CORE_COMP0_DELAY_BUF_CTL__POR (0x02)
+#define MSM89XX_CDC_CORE_DEBUG_DESER1_CTL (0xE0)
+#define MSM89XX_CDC_CORE_DEBUG_DESER1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_DEBUG_DESER2_CTL (0xE4)
+#define MSM89XX_CDC_CORE_DEBUG_DESER2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_DEBUG_B1_CTL_CFG (0xE8)
+#define MSM89XX_CDC_CORE_DEBUG_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_DEBUG_B2_CTL_CFG (0xEC)
+#define MSM89XX_CDC_CORE_DEBUG_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_DEBUG_B3_CTL_CFG (0xF0)
+#define MSM89XX_CDC_CORE_DEBUG_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL (0x100)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL (0x140)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL (0x104)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B2_CTL (0x144)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL (0x108)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B3_CTL (0x148)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL (0x10C)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B4_CTL (0x14C)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B5_CTL (0x110)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B5_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B5_CTL (0x150)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B5_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B6_CTL (0x114)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B6_CTL (0x154)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B7_CTL (0x118)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B7_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B7_CTL (0x158)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B7_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B8_CTL (0x11C)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B8_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B8_CTL (0x15C)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B8_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_CTL (0x120)
+#define MSM89XX_CDC_CORE_IIR1_CTL__POR (0x40)
+#define MSM89XX_CDC_CORE_IIR2_CTL (0x160)
+#define MSM89XX_CDC_CORE_IIR2_CTL__POR (0x40)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_TIMER_CTL (0x124)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_TIMER_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_TIMER_CTL (0x164)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_TIMER_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL (0x128)
+#define MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL (0x168)
+#define MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL (0x12C)
+#define MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_COEF_B2_CTL (0x16C)
+#define MSM89XX_CDC_CORE_IIR2_COEF_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX1_B1_CTL (0x180)
+#define MSM89XX_CDC_CORE_CONN_RX1_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX1_B2_CTL (0x184)
+#define MSM89XX_CDC_CORE_CONN_RX1_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX1_B3_CTL (0x188)
+#define MSM89XX_CDC_CORE_CONN_RX1_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX2_B1_CTL (0x18C)
+#define MSM89XX_CDC_CORE_CONN_RX2_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX2_B2_CTL (0x190)
+#define MSM89XX_CDC_CORE_CONN_RX2_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX2_B3_CTL (0x194)
+#define MSM89XX_CDC_CORE_CONN_RX2_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX3_B1_CTL (0x198)
+#define MSM89XX_CDC_CORE_CONN_RX3_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX3_B2_CTL (0x19C)
+#define MSM89XX_CDC_CORE_CONN_RX3_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_TX_B1_CTL (0x1A0)
+#define MSM89XX_CDC_CORE_CONN_TX_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL (0x1A8)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B2_CTL (0x1AC)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B3_CTL (0x1B0)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B4_CTL (0x1B4)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL (0x1B8)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B2_CTL (0x1BC)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B3_CTL (0x1C0)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B4_CTL (0x1C4)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL (0x1C8)
+#define MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_TIMER (0x280)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_TIMER__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_TIMER (0x2A0)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_TIMER__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_TIMER (0x2C0)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_TIMER__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_TIMER (0x2E0)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_TIMER__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN (0x284)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN (0x2A4)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN (0x2C4)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN (0x2E4)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG (0x288)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG (0x2A8)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_CFG (0x2C8)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_CFG__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_CFG (0x2E8)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_CFG__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_MUX_CTL (0x28C)
+#define MSM89XX_CDC_CORE_TX1_MUX_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_MUX_CTL (0x2AC)
+#define MSM89XX_CDC_CORE_TX2_MUX_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_MUX_CTL (0x2CC)
+#define MSM89XX_CDC_CORE_TX3_MUX_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_MUX_CTL (0x2EC)
+#define MSM89XX_CDC_CORE_TX4_MUX_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_CLK_FS_CTL (0x290)
+#define MSM89XX_CDC_CORE_TX1_CLK_FS_CTL__POR (0x03)
+#define MSM89XX_CDC_CORE_TX2_CLK_FS_CTL (0x2B0)
+#define MSM89XX_CDC_CORE_TX2_CLK_FS_CTL__POR (0x03)
+#define MSM89XX_CDC_CORE_TX3_CLK_FS_CTL (0x2D0)
+#define MSM89XX_CDC_CORE_TX3_CLK_FS_CTL__POR (0x03)
+#define MSM89XX_CDC_CORE_TX4_CLK_FS_CTL (0x2F0)
+#define MSM89XX_CDC_CORE_TX4_CLK_FS_CTL__POR (0x03)
+#define MSM89XX_CDC_CORE_TX1_DMIC_CTL (0x294)
+#define MSM89XX_CDC_CORE_TX1_DMIC_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_DMIC_CTL (0x2B4)
+#define MSM89XX_CDC_CORE_TX2_DMIC_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_DMIC_CTL (0x2D4)
+#define MSM89XX_CDC_CORE_TX3_DMIC_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_DMIC_CTL (0x2F4)
+#define MSM89XX_CDC_CORE_TX4_DMIC_CTL__POR (0x00)
+
+#define MSM89XX_CDC_CORE_NUM_REGISTERS \
+ (MSM89XX_CDC_CORE_TX4_DMIC_CTL+1)
+#define MSM89XX_CDC_CORE_MAX_REGISTER \
+ (MSM89XX_CDC_CORE_NUM_REGISTERS-1)
+#define MSM89XX_CDC_CORE_CACHE_SIZE \
+ MSM89XX_CDC_CORE_NUM_REGISTERS
+#endif
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 0af7314f1b7b..11993bb9a639 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -5820,6 +5820,18 @@ static u32 tasha_get_dmic_sample_rate(struct snd_soc_codec *codec,
tx_stream_fs = snd_soc_read(codec, tx_fs_reg) & 0x0F;
dmic_fs = tx_stream_fs <= 4 ? WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ :
WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
+
+ /*
+ * Check for ECPP path selection and DEC1 not connected to
+ * any other audio path to apply ECPP DMIC sample rate
+ */
+ if ((adc_mux_index == 1) &&
+ ((snd_soc_read(codec, WCD9335_CPE_SS_US_EC_MUX_CFG)
+ & 0x0F) == 0x0A) &&
+ ((snd_soc_read(codec, WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0)
+ & 0x0C) == 0x00)) {
+ dmic_fs = pdata->ecpp_dmic_sample_rate;
+ }
} else {
dmic_fs = pdata->dmic_sample_rate;
}
@@ -12476,6 +12488,17 @@ static int tasha_handle_pdata(struct tasha_priv *tasha,
*/
pdata->mad_dmic_sample_rate = pdata->dmic_sample_rate;
}
+ if (pdata->ecpp_dmic_sample_rate ==
+ WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
+ dev_info(codec->dev,
+ "%s: ecpp_dmic_rate invalid default = %d\n",
+ __func__, def_dmic_rate);
+ /*
+ * use dmic_sample_rate as the default for ECPP DMIC
+ * if ecpp dmic sample rate is undefined
+ */
+ pdata->ecpp_dmic_sample_rate = pdata->dmic_sample_rate;
+ }
if (pdata->dmic_clk_drv ==
WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED) {
diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c
index 45eed236c5c9..8270cfb98de8 100644
--- a/sound/soc/msm/msm-cpe-lsm.c
+++ b/sound/soc/msm/msm-cpe-lsm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, 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
@@ -1208,6 +1208,7 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
dev_err(rtd->dev, "%s: No memory for sound model\n",
__func__);
kfree(session->conf_levels);
+ session->conf_levels = NULL;
return -ENOMEM;
}
session->snd_model_size = snd_model.data_size;
@@ -1219,6 +1220,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
__func__);
kfree(session->conf_levels);
kfree(session->snd_model_data);
+ session->conf_levels = NULL;
+ session->snd_model_data = NULL;
return -EFAULT;
}
@@ -1230,6 +1233,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
__func__, rc);
kfree(session->snd_model_data);
kfree(session->conf_levels);
+ session->snd_model_data = NULL;
+ session->conf_levels = NULL;
return rc;
}
@@ -1243,6 +1248,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
kfree(session->snd_model_data);
kfree(session->conf_levels);
+ session->snd_model_data = NULL;
+ session->conf_levels = NULL;
return rc;
}
diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c
index 945250babf2d..763854061966 100644
--- a/sound/soc/msm/msmcobalt.c
+++ b/sound/soc/msm/msmcobalt.c
@@ -174,7 +174,7 @@ static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
"KHZ_32", "KHZ_44P1", "KHZ_48",
"KHZ_96", "KHZ_192"};
-static char const *bt_sco_sample_rate_text[] = {"KHZ_8", "KHZ_16"};
+static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_48"};
static const char *const usb_ch_text[] = {"One", "Two"};
static char const *ch_text[] = {"Two", "Three", "Four", "Five",
"Six", "Seven", "Eight"};
@@ -206,7 +206,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
-static SOC_ENUM_SINGLE_EXT_DECL(bt_sco_sample_rate, bt_sco_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(hdmi_rx_sample_rate, hdmi_rx_sample_rate_text);
@@ -611,29 +611,44 @@ static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static int msm_bt_sco_sample_rate_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
/*
* Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
* when used for BT_SCO use case. Return either Rx or Tx sample rate
* value.
*/
- ucontrol->value.integer.value[0] = slim_rx_cfg[SLIM_RX_7].sample_rate;
+ switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
+ case SAMPLING_RATE_48KHZ:
+ ucontrol->value.integer.value[0] = 2;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ ucontrol->value.integer.value[0] = 1;
+ break;
+ case SAMPLING_RATE_8KHZ:
+ default:
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ }
pr_debug("%s: sample rate = %d", __func__,
slim_rx_cfg[SLIM_RX_7].sample_rate);
return 0;
}
-static int msm_bt_sco_sample_rate_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
switch (ucontrol->value.integer.value[0]) {
case 1:
slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
break;
+ case 2:
+ slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
+ slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
+ break;
case 0:
default:
slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
@@ -1134,9 +1149,9 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
slim_rx_sample_rate_get, slim_rx_sample_rate_put),
SOC_ENUM_EXT("SLIM_6_RX SampleRate", slim_6_rx_sample_rate,
slim_rx_sample_rate_get, slim_rx_sample_rate_put),
- SOC_ENUM_EXT("BT_SCO SampleRate", bt_sco_sample_rate,
- msm_bt_sco_sample_rate_get,
- msm_bt_sco_sample_rate_put),
+ SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
+ msm_bt_sample_rate_get,
+ msm_bt_sample_rate_put),
SOC_ENUM_EXT("USB_AUDIO_RX SampleRate", usb_rx_sample_rate,
usb_audio_rx_sample_rate_get,
usb_audio_rx_sample_rate_put),
@@ -1341,6 +1356,8 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
break;
case MSM_BACKEND_DAI_SLIMBUS_7_RX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_rx_cfg[SLIM_RX_7].bit_format);
rate->min = rate->max = slim_rx_cfg[SLIM_RX_7].sample_rate;
channels->min = channels->max =
slim_rx_cfg[SLIM_RX_7].channels;
@@ -3131,7 +3148,11 @@ static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
.cpu_dai_name = "msm-dai-q6-dev.16398",
.platform_name = "msm-pcm-routing",
.codec_name = "btfmslim_slave",
- .codec_dai_name = "btfm_bt_sco_slim_rx",
+ /* BT codec driver determines capabilities based on
+ * dai name, bt codecdai name should always contains
+ * supported usecase information
+ */
+ .codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
@@ -3950,8 +3971,6 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
goto err;
}
- spdev = pdev;
-
ret = msm_populate_dai_link_component_of_node(card);
if (ret) {
ret = -EPROBE_DEFER;
@@ -3989,6 +4008,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
goto err;
}
dev_info(&pdev->dev, "Sound card %s registered\n", card->name);
+ spdev = pdev;
ret = of_property_read_string(pdev->dev.of_node,
"qcom,mbhc-audio-jack-type", &mbhc_audio_jack_type);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index f577637ee2b2..26528e6a2bb8 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -1070,6 +1070,7 @@ static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream,
__func__, ddp->params_length);
return -EINVAL;
}
+ params_length = ddp->params_length*sizeof(int);
if (params_length > MAX_AC3_PARAM_SIZE) {
/*MAX is 36*sizeof(int) this should not happen*/
pr_err("%s: params_length(%d) is greater than %zd\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 7684d27d60a0..c439c5cf2de5 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -37,6 +37,14 @@
#define CHANNEL_STATUS_MASK 0x4
#define AFE_API_VERSION_CLOCK_SET 1
+enum {
+ ENC_FMT_NONE,
+ ENC_FMT_SBC = ASM_MEDIA_FMT_SBC,
+ ENC_FMT_AAC_V2 = ASM_MEDIA_FMT_AAC_V2,
+ ENC_FMT_APTX = ASM_MEDIA_FMT_APTX,
+ ENC_FMT_APTX_HD = ASM_MEDIA_FMT_APTX_HD,
+};
+
static const struct afe_clk_set lpass_clk_set_default = {
AFE_API_VERSION_CLOCK_SET,
Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT,
@@ -157,6 +165,8 @@ struct msm_dai_q6_dai_data {
u32 channels;
u32 bitwidth;
u32 cal_mode;
+ u32 afe_in_channels;
+ struct afe_enc_config enc_config;
union afe_port_config port_config;
};
@@ -1330,9 +1340,20 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
int rc = 0;
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
- rc = afe_port_start(dai->id, &dai_data->port_config,
- dai_data->rate);
-
+ if (dai_data->enc_config.format != ENC_FMT_NONE) {
+ pr_debug("%s: calling AFE_PORT_START_V2 with enc_format: %d\n",
+ __func__, dai_data->enc_config.format);
+ rc = afe_port_start_v2(dai->id, &dai_data->port_config,
+ dai_data->rate,
+ dai_data->afe_in_channels,
+ &dai_data->enc_config);
+ if (rc < 0)
+ pr_err("%s: afe_port_start_v2 failed error: %d\n",
+ __func__, rc);
+ } else {
+ rc = afe_port_start(dai->id, &dai_data->port_config,
+ dai_data->rate);
+ }
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to open AFE port 0x%x\n",
dai->id);
@@ -1941,6 +1962,151 @@ static int msm_dai_q6_usb_audio_cfg_get(struct snd_kcontrol *kcontrol,
return 0;
}
+static int msm_dai_q6_afe_enc_cfg_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = sizeof(struct afe_enc_config);
+
+ return 0;
+}
+
+static int msm_dai_q6_afe_enc_cfg_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret = 0;
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ if (dai_data) {
+ int format_size = sizeof(dai_data->enc_config.format);
+
+ pr_debug("%s:encoder config for %d format\n",
+ __func__, dai_data->enc_config.format);
+ memcpy(ucontrol->value.bytes.data,
+ &dai_data->enc_config.format,
+ format_size);
+ switch (dai_data->enc_config.format) {
+ case ENC_FMT_SBC:
+ memcpy(ucontrol->value.bytes.data + format_size,
+ &dai_data->enc_config.data,
+ sizeof(struct asm_sbc_enc_cfg_t));
+ break;
+ case ENC_FMT_AAC_V2:
+ memcpy(ucontrol->value.bytes.data + format_size,
+ &dai_data->enc_config.data,
+ sizeof(struct asm_aac_enc_cfg_v2_t));
+ break;
+ case ENC_FMT_APTX:
+ case ENC_FMT_APTX_HD:
+ memcpy(ucontrol->value.bytes.data + format_size,
+ &dai_data->enc_config.data,
+ sizeof(struct asm_aac_enc_cfg_v2_t));
+ break;
+ default:
+ pr_debug("%s: unknown format = %d\n",
+ __func__, dai_data->enc_config.format);
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int msm_dai_q6_afe_enc_cfg_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret = 0;
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ if (dai_data) {
+ int format_size = sizeof(dai_data->enc_config.format);
+
+ memset(&dai_data->enc_config, 0x0,
+ sizeof(struct afe_enc_config));
+ memcpy(&dai_data->enc_config.format,
+ ucontrol->value.bytes.data,
+ format_size);
+ pr_debug("%s: Received encoder config for %d format\n",
+ __func__, dai_data->enc_config.format);
+ switch (dai_data->enc_config.format) {
+ case ENC_FMT_SBC:
+ memcpy(&dai_data->enc_config.data,
+ ucontrol->value.bytes.data + format_size,
+ sizeof(struct asm_sbc_enc_cfg_t));
+ break;
+ case ENC_FMT_AAC_V2:
+ memcpy(&dai_data->enc_config.data,
+ ucontrol->value.bytes.data + format_size,
+ sizeof(struct asm_aac_enc_cfg_v2_t));
+ break;
+ case ENC_FMT_APTX:
+ case ENC_FMT_APTX_HD:
+ memcpy(&dai_data->enc_config.data,
+ ucontrol->value.bytes.data + format_size,
+ sizeof(struct asm_custom_enc_cfg_aptx_t));
+ break;
+ default:
+ pr_debug("%s: Ignore enc config for unknown format = %d\n",
+ __func__, dai_data->enc_config.format);
+ ret = -EINVAL;
+ break;
+ }
+ } else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static const char *const afe_input_chs_text[] = {"Zero", "One", "Two"};
+
+static const struct soc_enum afe_input_chs_enum[] = {
+ SOC_ENUM_SINGLE_EXT(3, afe_input_chs_text),
+};
+
+static int msm_dai_q6_afe_input_channel_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ if (dai_data) {
+ ucontrol->value.integer.value[0] = dai_data->afe_in_channels;
+ pr_debug("%s:afe input channel = %d\n",
+ __func__, dai_data->afe_in_channels);
+ }
+
+ return 0;
+}
+
+static int msm_dai_q6_afe_input_channel_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ if (dai_data) {
+ dai_data->afe_in_channels = ucontrol->value.integer.value[0];
+ pr_debug("%s: updating afe input channel : %d\n",
+ __func__, dai_data->afe_in_channels);
+ }
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new afe_enc_config_controls[] = {
+ {
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE),
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SLIM_7_RX Encoder Config",
+ .info = msm_dai_q6_afe_enc_cfg_info,
+ .get = msm_dai_q6_afe_enc_cfg_get,
+ .put = msm_dai_q6_afe_enc_cfg_put,
+ },
+ SOC_ENUM_EXT("AFE Input Channels", afe_input_chs_enum[0],
+ msm_dai_q6_afe_input_channel_get,
+ msm_dai_q6_afe_input_channel_put),
+};
+
static const char * const afe_cal_mode_text[] = {
"CAL_MODE_DEFAULT", "CAL_MODE_NONE"
};
@@ -2020,6 +2186,17 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
snd_ctl_new1(&sb_config_controls[1],
dai_data));
break;
+ case SLIMBUS_7_RX:
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_enc_config_controls[0],
+ dai_data));
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_enc_config_controls[1],
+ dai_data));
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_enc_config_controls[2],
+ dai_data));
+ break;
case RT_PROXY_DAI_001_RX:
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&rt_proxy_config_controls[0],
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-slim.c b/sound/soc/msm/qdsp6v2/msm-dai-slim.c
index 2d8177c9712d..7c56f4ad8884 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-slim.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-slim.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 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
@@ -467,7 +467,9 @@ static void msm_dai_slim_remove_dai_data(
dai_data_t = &drv_data->slim_dai_data[i];
kfree(dai_data_t->chan_h);
+ dai_data_t->chan_h = NULL;
kfree(dai_data_t->sh_ch);
+ dai_data_t->sh_ch = NULL;
}
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 8ca9bb7b2ad8..9e3d85b807aa 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -244,205 +244,209 @@ static void msm_pcm_routng_cfg_matrix_map_pp(struct route_payload payload,
#define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
- { PRIMARY_I2S_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX},
- { PRIMARY_I2S_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX},
- { SLIMBUS_0_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX},
- { SLIMBUS_0_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX},
- { HDMI_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_HDMI},
- { INT_BT_SCO_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX},
- { INT_BT_SCO_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX},
- { INT_FM_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_RX},
- { INT_FM_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_TX},
- { RT_PROXY_PORT_001_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_RX},
- { RT_PROXY_PORT_001_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_TX},
- { AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AUXPCM_RX},
- { AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AUXPCM_TX},
- { VOICE_PLAYBACK_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_VOICE_PLAYBACK_TX},
- { VOICE2_PLAYBACK_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_VOICE2_PLAYBACK_TX},
- { VOICE_RECORD_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_RX},
- { VOICE_RECORD_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_TX},
- { MI2S_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_MI2S_RX},
- { MI2S_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_MI2S_TX},
- { SECONDARY_I2S_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX},
- { SLIMBUS_1_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX},
- { SLIMBUS_1_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX},
- { SLIMBUS_4_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX},
- { SLIMBUS_4_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX},
- { SLIMBUS_3_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX},
- { SLIMBUS_3_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX},
- { SLIMBUS_5_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX},
- { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_RX},
- { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_TX},
- { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_1_TX},
- { AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { PRIMARY_I2S_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX},
+ { PRIMARY_I2S_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX},
+ { SLIMBUS_0_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX},
+ { SLIMBUS_0_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX},
+ { HDMI_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_HDMI},
+ { INT_BT_SCO_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX},
+ { INT_BT_SCO_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX},
+ { INT_FM_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_RX},
+ { INT_FM_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_TX},
+ { RT_PROXY_PORT_001_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_RX},
+ { RT_PROXY_PORT_001_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_TX},
+ { AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
+ LPASS_BE_AUXPCM_RX},
+ { AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
+ LPASS_BE_AUXPCM_TX},
+ { VOICE_PLAYBACK_TX, 0, 0, 0, 0, 0, 0, 0, 0,
+ LPASS_BE_VOICE_PLAYBACK_TX},
+ { VOICE2_PLAYBACK_TX, 0, 0, 0, 0, 0, 0, 0, 0,
+ LPASS_BE_VOICE2_PLAYBACK_TX},
+ { VOICE_RECORD_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_RX},
+ { VOICE_RECORD_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_TX},
+ { MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_MI2S_RX},
+ { MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_MI2S_TX},
+ { SECONDARY_I2S_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX},
+ { SLIMBUS_1_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX},
+ { SLIMBUS_1_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX},
+ { SLIMBUS_4_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX},
+ { SLIMBUS_4_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX},
+ { SLIMBUS_3_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX},
+ { SLIMBUS_3_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX},
+ { SLIMBUS_5_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX},
+ { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_RX},
+ { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_TX},
+ { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_1_TX},
+ { AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_MI2S_RX},
- { AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_MI2S_TX},
- { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_MI2S_RX},
- { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_MI2S_TX},
- { AFE_PORT_ID_PRIMARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_MI2S_RX},
- { AFE_PORT_ID_PRIMARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_MI2S_TX},
- { AFE_PORT_ID_TERTIARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_MI2S_RX},
- { AFE_PORT_ID_TERTIARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_MI2S_TX},
- { AUDIO_PORT_ID_I2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AUDIO_PORT_ID_I2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_AUDIO_I2S_RX},
- { AFE_PORT_ID_SECONDARY_PCM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_PCM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_AUXPCM_RX},
- { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_AUXPCM_TX},
- { SLIMBUS_6_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX},
- { SLIMBUS_6_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX},
- { AFE_PORT_ID_SPDIF_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SPDIF_RX},
- { AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, 0, 0, 0, 0, 0, 0,
+ { SLIMBUS_6_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX},
+ { SLIMBUS_6_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX},
+ { AFE_PORT_ID_SPDIF_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SPDIF_RX},
+ { AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_MI2S_RX_SD1},
- { SLIMBUS_5_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX},
- { AFE_PORT_ID_QUINARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { SLIMBUS_5_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX},
+ { AFE_PORT_ID_QUINARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUIN_MI2S_RX},
- { AFE_PORT_ID_QUINARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUINARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUIN_MI2S_TX},
- { AFE_PORT_ID_SENARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SENARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SENARY_MI2S_TX},
- { AFE_PORT_ID_PRIMARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_0},
- { AFE_PORT_ID_PRIMARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_0},
- { AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_1},
- { AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_1},
- { AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_2},
- { AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_2},
- { AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_3},
- { AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_3},
- { AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_4},
- { AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_4},
- { AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_5},
- { AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_5},
- { AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_6},
- { AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_6},
- { AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_7},
- { AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_7},
- { AFE_PORT_ID_SECONDARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_0},
- { AFE_PORT_ID_SECONDARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_0},
- { AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_1},
- { AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_1},
- { AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_2},
- { AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_2},
- { AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_3},
- { AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_3},
- { AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_4},
- { AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_4},
- { AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_5},
- { AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_5},
- { AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_6},
- { AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_6},
- { AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_7},
- { AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_7},
- { AFE_PORT_ID_TERTIARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_0},
- { AFE_PORT_ID_TERTIARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_0},
- { AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_1},
- { AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_1},
- { AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_2},
- { AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_2},
- { AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_3},
- { AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_3},
- { AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_4},
- { AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_4},
- { AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_5},
- { AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_5},
- { AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_6},
- { AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_6},
- { AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_7},
- { AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_7},
- { AFE_PORT_ID_QUATERNARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_0},
- { AFE_PORT_ID_QUATERNARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_0},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_1},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_1},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_2},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_2},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_3},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_3},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_4},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_4},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_5},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_5},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_6},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_6},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_7},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_7},
- { INT_BT_A2DP_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_A2DP_RX},
- { SLIMBUS_7_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX},
- { SLIMBUS_7_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX},
- { SLIMBUS_8_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX},
- { SLIMBUS_8_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX},
- { AFE_PORT_ID_USB_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_RX},
- { AFE_PORT_ID_USB_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_TX},
+ { INT_BT_A2DP_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_A2DP_RX},
+ { SLIMBUS_7_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX},
+ { SLIMBUS_7_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX},
+ { SLIMBUS_8_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX},
+ { SLIMBUS_8_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX},
+ { AFE_PORT_ID_USB_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_RX},
+ { AFE_PORT_ID_USB_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_TX},
};
/* Track ASM playback & capture sessions of DAI */
@@ -828,7 +832,15 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
(msm_bedais[i].active) &&
(test_bit(fe_id, &msm_bedais[i].fe_sessions))) {
int app_type, app_type_idx, copp_idx, acdb_dev_id;
- channels = msm_bedais[i].channel;
+
+ /*
+ * check if ADM needs to be configured with different
+ * channel mapping than backend
+ */
+ if (!msm_bedais[i].adm_override_ch)
+ channels = msm_bedais[i].channel;
+ else
+ channels = msm_bedais[i].adm_override_ch;
bit_width = msm_routing_get_bit_width(
msm_bedais[i].format);
@@ -976,7 +988,14 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
(msm_bedais[i].active) &&
(test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
int app_type, app_type_idx, copp_idx, acdb_dev_id;
- channels = msm_bedais[i].channel;
+ /*
+ * check if ADM needs to be configured with different
+ * channel mapping than backend
+ */
+ if (!msm_bedais[i].adm_override_ch)
+ channels = msm_bedais[i].channel;
+ else
+ channels = msm_bedais[i].adm_override_ch;
msm_bedais[i].compr_passthr_mode =
LEGACY_PCM;
@@ -1188,7 +1207,14 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
if (msm_bedais[reg].active && fdai->strm_id !=
INVALID_SESSION) {
int app_type, app_type_idx, copp_idx, acdb_dev_id;
- channels = msm_bedais[reg].channel;
+ /*
+ * check if ADM needs to be configured with different
+ * channel mapping than backend
+ */
+ if (!msm_bedais[reg].adm_override_ch)
+ channels = msm_bedais[reg].channel;
+ else
+ channels = msm_bedais[reg].adm_override_ch;
if (session_type == SESSION_TYPE_TX &&
fdai->be_srate &&
(fdai->be_srate != msm_bedais[reg].sample_rate)) {
@@ -1855,6 +1881,68 @@ static int msm_routing_lsm_func_put(struct snd_kcontrol *kcontrol,
return afe_port_set_mad_type(port_id, mad_type);
}
+static const char *const adm_override_chs_text[] = {"Zero", "One", "Two"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(slim_7_rx_adm_override_chs,
+ adm_override_chs_text);
+
+static int msm_routing_adm_get_backend_idx(struct snd_kcontrol *kcontrol)
+{
+ int backend_id;
+
+ if (strnstr(kcontrol->id.name, "SLIM7_RX", sizeof("SLIM7_RX"))) {
+ backend_id = MSM_BACKEND_DAI_SLIMBUS_7_RX;
+ } else {
+ pr_err("%s: unsupported backend id: %s",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+
+ return backend_id;
+}
+static int msm_routing_adm_channel_config_get(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int backend_id = msm_routing_adm_get_backend_idx(kcontrol);
+
+ if (backend_id >= 0) {
+ mutex_lock(&routing_lock);
+ ucontrol->value.integer.value[0] =
+ msm_bedais[backend_id].adm_override_ch;
+ pr_debug("%s: adm channel count %ld for BE:%d\n", __func__,
+ ucontrol->value.integer.value[0], backend_id);
+ mutex_unlock(&routing_lock);
+ }
+
+ return 0;
+}
+
+static int msm_routing_adm_channel_config_put(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int backend_id = msm_routing_adm_get_backend_idx(kcontrol);
+
+ if (backend_id >= 0) {
+ mutex_lock(&routing_lock);
+ msm_bedais[backend_id].adm_override_ch =
+ ucontrol->value.integer.value[0];
+ pr_debug("%s:updating BE :%d adm channels: %d\n",
+ __func__, backend_id,
+ msm_bedais[backend_id].adm_override_ch);
+ mutex_unlock(&routing_lock);
+ }
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new adm_channel_config_controls[] = {
+ SOC_ENUM_EXT("SLIM7_RX ADM Channels", slim_7_rx_adm_override_chs,
+ msm_routing_adm_channel_config_get,
+ msm_routing_adm_channel_config_put),
+};
+
static int msm_routing_slim_0_rx_aanc_mux_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -9641,7 +9729,14 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
app_type_cfg[app_type_idx].bit_width;
} else
sample_rate = bedai->sample_rate;
- channels = bedai->channel;
+ /*
+ * check if ADM needs to be configured with different
+ * channel mapping than backend
+ */
+ if (!bedai->adm_override_ch)
+ channels = bedai->channel;
+ else
+ channels = bedai->adm_override_ch;
acdb_dev_id = fe_dai_app_type_cfg[i].acdb_dev_id;
topology = msm_routing_get_adm_topology(path_type, i);
copp_idx = adm_open(bedai->port_id, path_type,
@@ -9919,7 +10014,9 @@ static int msm_routing_probe(struct snd_soc_platform *platform)
msm_dts_eagle_add_controls(platform);
snd_soc_add_platform_controls(platform, msm_source_tracking_controls,
- ARRAY_SIZE(msm_source_tracking_controls));
+ ARRAY_SIZE(msm_source_tracking_controls));
+ snd_soc_add_platform_controls(platform, adm_channel_config_controls,
+ ARRAY_SIZE(adm_channel_config_controls));
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 992d0d48e999..f422fd7d3e85 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -360,6 +360,7 @@ struct msm_pcm_routing_bdai_data {
unsigned int sample_rate;
unsigned int channel;
unsigned int format;
+ unsigned int adm_override_ch;
u32 compr_passthr_mode;
char *name;
};
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 8efa04c3807e..16c7ef4c0bf5 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -292,11 +292,13 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
this_afe.tx_cb(data->opcode, data->token,
data->payload,
this_afe.tx_private_data);
+ this_afe.tx_cb = NULL;
}
if (this_afe.rx_cb) {
this_afe.rx_cb(data->opcode, data->token,
data->payload,
this_afe.rx_private_data);
+ this_afe.rx_cb = NULL;
}
return 0;
@@ -2632,8 +2634,113 @@ exit:
return ret;
}
-int afe_port_start(u16 port_id, union afe_port_config *afe_config,
- u32 rate) /* This function is no blocking */
+static int q6afe_send_enc_config(u16 port_id,
+ union afe_enc_config_data *cfg, u32 format,
+ union afe_port_config afe_config, u16 afe_in_channels)
+{
+ struct afe_audioif_config_command config;
+ int index;
+ int ret;
+ int payload_size = sizeof(config) - sizeof(struct apr_hdr) -
+ sizeof(config.param) - sizeof(config.port);
+
+ pr_debug("%s:update DSP for enc format = %d\n", __func__, format);
+ if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
+ format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD) {
+ pr_err("%s:Unsuppported format Ignore AFE config\n", __func__);
+ return 0;
+ }
+ memset(&config, 0, sizeof(config));
+ index = q6audio_get_port_index(port_id);
+ config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ config.hdr.pkt_size = sizeof(config);
+ config.hdr.src_port = 0;
+ config.hdr.dest_port = 0;
+ config.hdr.token = index;
+
+ config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+ config.param.port_id = q6audio_get_port_id(port_id);
+ config.param.payload_size = payload_size + sizeof(config.port.enc_fmt);
+ config.param.payload_address_lsw = 0x00;
+ config.param.payload_address_msw = 0x00;
+ config.param.mem_map_handle = 0x00;
+ config.pdata.module_id = AFE_MODULE_ID_ENCODER;
+ config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_FMT_ID;
+ config.pdata.param_size = sizeof(config.port.enc_fmt);
+ config.port.enc_fmt.fmt_id = format;
+ pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENC_FMT_ID payload: %d\n",
+ __func__, config.param.payload_size);
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s:unable to send AFE_ENCODER_PARAM_ID_ENC_FMT_ID",
+ __func__);
+ goto exit;
+ }
+
+ config.param.payload_size = payload_size
+ + sizeof(config.port.enc_blk_param);
+ pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload:%d\n",
+ __func__, config.param.payload_size);
+ config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK;
+ config.pdata.param_size = sizeof(config.port.enc_blk_param);
+ config.port.enc_blk_param.enc_cfg_blk_size =
+ sizeof(config.port.enc_blk_param.enc_blk_config);
+ config.port.enc_blk_param.enc_blk_config = *cfg;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+ config.param.payload_size =
+ payload_size + sizeof(config.port.enc_pkt_id_param);
+ pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP payload = %d",
+ __func__, config.param.payload_size);
+ config.pdata.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID;
+ config.pdata.param_size = sizeof(config.port.enc_pkt_id_param);
+ config.port.enc_pkt_id_param.enc_packetizer_id =
+ AFE_MODULE_ID_PACKETIZER_COP;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+ config.param.payload_size =
+ payload_size + sizeof(config.port.media_type);
+ config.pdata.param_size = sizeof(config.port.media_type);
+
+ pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP", __func__);
+ config.pdata.module_id = AFE_MODULE_PORT;
+ config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
+ config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
+ config.port.media_type.sample_rate = afe_config.slim_sch.sample_rate;
+ config.port.media_type.bit_width = afe_config.slim_sch.bit_width;
+ if (afe_in_channels != 0)
+ config.port.media_type.num_channels = afe_in_channels;
+ else
+ config.port.media_type.num_channels =
+ afe_config.slim_sch.num_channels;
+ config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
+ config.port.media_type.reserved = 0;
+
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
+ u32 rate, u16 afe_in_channels,
+ union afe_enc_config_data *cfg, u32 enc_format)
{
struct afe_audioif_config_command config;
int ret = 0;
@@ -2850,7 +2957,11 @@ int afe_port_start(u16 port_id, union afe_port_config *afe_config,
config.pdata.param_size = sizeof(config.port);
config.port = *afe_config;
-
+ if ((enc_format != ASM_MEDIA_FMT_NONE) &&
+ (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
+ config.port.slim_sch.data_format =
+ AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
+ }
ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
if (ret) {
pr_err("%s: AFE enable for port 0x%x failed %d\n",
@@ -2858,6 +2969,19 @@ int afe_port_start(u16 port_id, union afe_port_config *afe_config,
goto fail_cmd;
}
+ if ((enc_format != ASM_MEDIA_FMT_NONE) &&
+ (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
+ pr_debug("%s: Found AFE encoder support for SLIMBUS enc_format = %d\n",
+ __func__, enc_format);
+ ret = q6afe_send_enc_config(port_id, cfg, enc_format,
+ *afe_config, afe_in_channels);
+ if (ret) {
+ pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto fail_cmd;
+ }
+ }
+
port_index = afe_get_port_index(port_id);
if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
this_afe.afe_sample_rates[port_index] = rate;
@@ -2890,6 +3014,47 @@ fail_cmd:
return ret;
}
+/**
+ * afe_port_start - to configure AFE session with
+ * specified port configuration
+ *
+ * @port_id: AFE port id number
+ * @afe_config: port configutation
+ * @rate: sampling rate of port
+ *
+ * Returns 0 on success or error value on port start failure.
+ */
+int afe_port_start(u16 port_id, union afe_port_config *afe_config,
+ u32 rate)
+{
+ return __afe_port_start(port_id, afe_config, rate,
+ 0, NULL, ASM_MEDIA_FMT_NONE);
+}
+EXPORT_SYMBOL(afe_port_start);
+
+/**
+ * afe_port_start_v2 - to configure AFE session with
+ * specified port configuration and encoder params
+ *
+ * @port_id: AFE port id number
+ * @afe_config: port configutation
+ * @rate: sampling rate of port
+ * @cfg: AFE encoder configuration information to setup encoder
+ * @afe_in_channels: AFE input channel configuration, this needs
+ * update only if input channel is differ from AFE output
+ *
+ * Returns 0 on success or error value on port start failure.
+ */
+int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
+ u32 rate, u16 afe_in_channels,
+ struct afe_enc_config *enc_cfg)
+{
+ return __afe_port_start(port_id, afe_config, rate,
+ afe_in_channels, &enc_cfg->data,
+ enc_cfg->format);
+}
+EXPORT_SYMBOL(afe_port_start_v2);
+
int afe_get_port_index(u16 port_id)
{
switch (port_id) {
@@ -3312,7 +3477,7 @@ int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
sizeof(struct afe_port_param_data_v2);
lb_cmd.dst_port_id = rx_port;
- lb_cmd.routing_mode = LB_MODE_EC_REF_VOICE_AUDIO;
+ lb_cmd.routing_mode = LB_MODE_DEFAULT;
lb_cmd.enable = (enable ? 1 : 0);
lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
index d0250535c69b..2bf0c490e834 100644
--- a/sound/soc/msm/qdsp6v2/q6lsm.c
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, 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
@@ -348,6 +348,7 @@ void q6lsm_client_free(struct lsm_client *client)
q6lsm_mmap_apr_dereg();
mutex_destroy(&client->cmd_lock);
kfree(client);
+ client = NULL;
}
/*