diff options
257 files changed, 18150 insertions, 13615 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt index c4d651e36d02..782fb6c4124d 100644 --- a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt +++ b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt @@ -18,13 +18,15 @@ Properties: Definition: Addresses and sizes for the memory of the OSM controller, cluster PLL management, and APCS common register regions. Optionally, the address of the efuse registers used to - determine the pwrcl or perfcl speed-bins. + determine the pwrcl or perfcl speed-bins and/or the ACD + register space to initialize prior to enabling OSM. + - reg-names Usage: required Value type: <stringlist> Definition: Address names. Must be "osm", "pwrcl_pll", "perfcl_pll", - "apcs_common" and "debug". Optionally, "pwrcl_efuse" or - "perfcl_efuse". + "apcs_common", and "debug". Optionally, "pwrcl_efuse", + "perfcl_efuse", "pwrcl_acd", or "perfcl_acd". Must be specified in the same order as the corresponding addresses are specified in the reg property. @@ -216,6 +218,45 @@ Properties: override values to write to the OSM controller for each of the two clusters. Each tuple must contain three elements. +- qcom,acdtd-val + Usage: required if pwrcl_acd or perfcl_acd registers are specified + Value type: <prop-encoded-array> + Definition: Array which defines the values to program to the ACD + Tunable-Length Delay register for the power and performance + clusters. + +- qcom,acdcr-val + Usage: required if pwrcl_acd or perfcl_acd registers are specified + Value type: <prop-encoded-array> + Definition: Array which defines the values for the ACD control register + for the power and performance clusters. + +- qcom,acdsscr-val + Usage: required if pwrcl_acd or perfcl_acd registers are specified + Value type: <prop-encoded-array> + Definition: Array which defines the values for the ACD Soft Start Control + register for the power and performance clusters. + +- qcom,acdextint0-val + Usage: required if pwrcl_acd or perfcl_acd registers are specified + Value type: <prop-encoded-array> + Definition: Array which defines the initial values for the ACD + external interface configuration register for the power + and performance clusters. + +- qcom,acdextint1-val + Usage: required if pwrcl_acd or perfcl_acd registers are specified + Value type: <prop-encoded-array> + Definition: Array which defines the final values for the ACD + external interface configuration register for the power + and performance clusters. + +- qcom,acdautoxfer-val + Usage: required if pwrcl_acd or perfcl_acd registers are specified + Value type: <prop-encoded-array> + Definition: Array which defines the values for the ACD auto transfer + control register for the power and performance clusters. + - qcom,pwrcl-apcs-mem-acc-cfg Usage: required if qcom,osm-no-tz is specified Value type: <prop-encoded-array> diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index 68b8f09238e0..56ad8c361219 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -350,8 +350,13 @@ the fps window. as below: --> Reset GPIO value --> Sleep value (in ms) -- qcom,partial-update-enabled: Boolean used to enable partial +- qcom,partial-update-enabled: String used to enable partial panel update for command mode panels. + "none": partial update is disabled + "single_roi": default enable mode, only single roi is sent to panel + "dual_roi": two rois are merged into one big roi. Panel ddic should be able + to process two roi's along with the DCS command to send two rois. + disabled if property is not specified. - qcom,mdss-dsi-horizontal-line-idle: List of width ranges (EC - SC) in pixels indicating additional idle time in dsi clock cycles that is needed to compensate for smaller line width. @@ -632,7 +637,7 @@ Example: qcom,mdss-tear-check-rd-ptr-trigger-intr = <1281>; qcom,mdss-tear-check-frame-rate = <6000>; qcom,mdss-dsi-reset-sequence = <1 2>, <0 10>, <1 10>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,dcs-cmd-by-left; qcom,mdss-dsi-lp11-init; qcom,mdss-dsi-init-delay-us = <100>; diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt index 44c874a7a080..8a79626125d9 100644 --- a/Documentation/devicetree/bindings/gpu/adreno.txt +++ b/Documentation/devicetree/bindings/gpu/adreno.txt @@ -154,6 +154,9 @@ GPU Quirks: detection logic - qcom,gpu-quirk-dp2clockgating-disable: Disable RB sampler data path clock gating optimization +- qcom,gpu-quirk-lmloadkill-disable: + Use register setting to disable local memory(LM) feature + to avoid corner case error KGSL Memory Pools: - qcom,gpu-mempools: Container for sets of GPU mempools.Multiple sets diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt index 8365762e520f..8844a816052e 100644 --- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt +++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt @@ -32,6 +32,18 @@ Optional properties: - qcom,vph-droop-debounce-us : Integer property to specify VPH droop debounce time. It is only used if qcom,vph-droop-det is specified. Valid values are 0, 8, 16 and 26. Unit is uS. +- qcom,led1n2-iclamp-low-ma : Integer property to specify current clamp low + level for mitigation. Unit is mA. Allowed + values are same as under qcom,max-current. +- qcom,led1n2-iclamp-mid-ma : Integer property to specify current clamp mid + level for mitigation. Unit is mA. Allowed + values are same as under qcom,max-current. +- qcom,led3-iclamp-low-ma : Integer property to specify current clamp low + level for mitigation. Unit is mA. Allowed + values are same as under qcom,max-current. +- qcom,led3-iclamp-mid-ma : Integer property to specify current clamp mid + level for mitigation. Unit is mA. Allowed + values are same as under qcom,max-current. - qcom,vled-max-uv : Integer property for flash current predictive mitigation. Default value is 3500000 uV. - qcom,ibatt-ocp-threshold-ua : Integer property for flash current predictive mitigation. @@ -70,6 +82,8 @@ Optional properties: 0: Flash strobe is used for LED1, LED2, LED3 1: Flash strobe is used for LED1, LED2 and GPIO10 is used for LED3 2: Flash strobe is used for LED1; GPIO9 is used for LED2; GPIO10 is used for LED3 +- switchX-supply : phandle of the regulator that needs to be used + as a supply for flash switch_X device. Child node: Contains settings for each individual LED. Each LED channel needs a flash node and torch node for itself, and an individual switch node to serve as an overall switch. @@ -126,15 +140,6 @@ Optional properties: be edge triggered. Otherwise, it is level triggered. - qcom,hw-strobe-active-low : Boolean property to select strobe signal polarity. If defined, hw-strobe signal polarity is set to active-low, else it is active-high. -- reg<n> : reg<n> (<n> represents number. e.g. 0,1,2,..) subnode is to add support for - multiple power sources. This subnode should only be specified for switch nodes. - Required property inside regulator node: - - regulator-name : Name of the regulator which has to be used for this - switch node. - Optional property inside regulator node: - - max-voltage-uv : This specifies max voltage of regulator. Some switch - or boost regulator does not need this property. - Example: qcom,leds@d300 { compatible = "qcom,qpnp-flash-led-v2"; @@ -160,6 +165,7 @@ Example: qcom,hdrm-auto-mode; qcom,isc-delay = <192>; + switch0-supply = <&pmicobalt_bob>; pmi8998_flash0: qcom,flash_0 { label = "flash"; @@ -254,10 +260,6 @@ Example: qcom,led-mask = <3>; qcom,default-led-trigger = "switch0_trigger"; - reg0 { - regulator-name = "pmicobalt_bob"; - max-voltage-uv = <3600000>; - }; }; pmi8998_switch1: qcom,led_switch_1 { @@ -266,10 +268,6 @@ Example: qcom,led-mask = <4>; qcom,default-led-trigger = "switch1_trigger"; - reg0 { - regulator-name = "pmicobalt_bob"; - max-voltage-uv = <3600000>; - }; }; }; diff --git a/Documentation/devicetree/bindings/pci/msm_pcie.txt b/Documentation/devicetree/bindings/pci/msm_pcie.txt index 21b6d99424c0..a50e0c2b2c35 100644 --- a/Documentation/devicetree/bindings/pci/msm_pcie.txt +++ b/Documentation/devicetree/bindings/pci/msm_pcie.txt @@ -93,6 +93,8 @@ Optional Properties: and assign for each endpoint. - qcom,ep-latency: The time (unit: ms) to wait for the PCIe endpoint to become stable after power on, before de-assert the PERST to the endpoint. + - qcom,wr-halt-size: With base 2, this exponent determines the size of the + data that PCIe core will halt on for each write transaction. - qcom,cpl-timeout: Completion timeout value. This value specifies the time range which the root complex will send out a completion packet if there is no response from the endpoint. @@ -270,6 +272,7 @@ Example: qcom,smmu-exist; qcom,smmu-sid-base = <0x1480>; qcom,ep-latency = <100>; + qcom,wr-halt-size = <0xa>; /* 1KB */ qcom,cpl-timeout = <0x2>; iommus = <&anoc0_smmu>; diff --git a/Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt b/Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt index 102b304f5fb3..d8934c01cc71 100644 --- a/Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt +++ b/Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt @@ -12,9 +12,11 @@ Optional: regarding scatter-gather capability - qcom,ipa-napi-enable: Boolean context flag to indicate whether to enable napi framework or not +- qcom,wan-rx-desc-size: size of WAN rx desc fifo ring, default is 256 Example: qcom,rmnet-ipa { compatible = "qcom,rmnet-ipa"; + qcom,wan-rx-desc-size = <256>; } diff --git a/Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt b/Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt index 7ee28664668b..e9575f150c5e 100644 --- a/Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt +++ b/Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt @@ -12,9 +12,11 @@ Optional: regarding scatter-gather capability - qcom,ipa-napi-enable: Boolean context flag to indicate whether to enable napi framework or not +- qcom,wan-rx-desc-size: size of WAN rx desc fifo ring, default is 256 Example: qcom,rmnet-ipa3 { compatible = "qcom,rmnet-ipa3"; + qcom,wan-rx-desc-size = <256>; } diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt index caabcd347a72..4f5e0a117b2d 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt @@ -55,7 +55,7 @@ First Level Node - FG Gen3 device be notified via the power supply framework. The userspace will read 0% soc and immediately shutdown. If this property is not specified, then the default value used will be - 3100mV. + 2800mV. - qcom,fg-vbatt-low-thr Usage: optional diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt index 82386ba9b082..7090426c68f8 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt @@ -129,6 +129,15 @@ Charger specific properties: happen but the adapter won't be asked to switch to a higher voltage point. +- qcom,chg-inhibit-threshold-mv + Usage: optional + Value type: <u32> + Definition: Charge inhibit threshold in milli-volts. Charging will be + inhibited when the battery voltage is within this threshold + from Vfloat at charger insertion. If this is not specified + then charge inhibit will be disabled by default. + Allowed values are: 50, 100, 200, 300. + ============================================= Second Level Nodes - SMB2 Charger Peripherals ============================================= diff --git a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt index 7be400da0d62..0545f6b7b59a 100644 --- a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt @@ -8,7 +8,7 @@ display panels, LCD or AMOLED. Main node required properties: - compatible: Must be "qcom,qpnp-labibb-regulator" -- qpnp,qpnp-labibb-mode: A string used to specify the working mode of LAB/IBB +- qcom,qpnp-labibb-mode: A string used to specify the working mode of LAB/IBB regulators when bootloader does not turned on the display panel. Could be "lcd" or "amoled". "lcd" means using LAB and IBB regulators are @@ -26,9 +26,9 @@ Main node optional properties: in LAB and IBB modules. Make sure the hardware has needed support before enabling this property. -- qpnp,swire-control: A bool property which indicates if the LAB/IBB is +- qcom,swire-control: A bool property which indicates if the LAB/IBB is controlled by the SWIRE interface. Enable only - if qpnp,qpnp-labibb-mode = "amoled". + if qcom,qpnp-labibb-mode = "amoled". - qcom,labibb-ttw-force-lab-on: A boolean property which forces LAB to be always on during TTW mode. - qcom,skip-2nd-swire-cmd: A boolean property which indicates if @@ -82,8 +82,10 @@ LAB subnode required properties: are 25, 50, 75 and 100. - qcom,qpnp-lab-nfet-size: NFET size in percentage. Supported values are 25, 50, 75 and 100. -- qcom,qpnp-lab-max-precharge-time: Precharge time in us of LAB regulator. +- qcom,qpnp-lab-max-precharge-time: Precharge time in uS for LAB regulator. Supported values are 200, 300, 400 and 500. + Suggested values for LCD and AMOLED mode + are 500 and 300uS respectively. - qcom,qpnp-lab-switching-clock-frequency: The PWM switching clock frequency in kHz of Lab regulator, Supported values are: 3200, 2740, 2400, 2130, 1920, @@ -91,11 +93,22 @@ LAB subnode required properties: 1130, 1070, 1010, 960, 910. - qcom,qpnp-lab-limit-maximum-current: The maximum inductor current limit in mA of LAB regulator. Supported values - are 200, 400, 600 and 800. + are 200, 400, 600, 800, 1000, 1200, + 1400 and 1600. +- interrupts: Specify the interrupts as per the interrupt + encoding. + Currently "lab-vreg-ok" is required for + LCD mode in pmicobalt. For AMOLED mode, + "lab-vreg-ok" is required only when SWIRE + control is enabled and skipping 2nd SWIRE + pulse is required in pmi8952/8996. +- interrupt-names: Interrupt names to match up 1-to-1 with + the interrupts specified in 'interrupts' + property. LAB subnode optional properties: -- qpnp,qpnp-lab-current-sense: If this property is specified, the LAB current +- qcom,qpnp-lab-current-sense: If this property is specified, the LAB current sense gain will be programmed for LAB regulator. Otherwise, LAB current sense gain will be default to "1x". A string is used to specify the @@ -209,7 +222,7 @@ IBB subnode optional properties: any value in the allowed limit. - qcom,output-voltage-one-pulse The expected voltage (in mV) of VDISN signal on the first SWIRE pulse. This property - can be specified only if 'qpnp,swire-control' + can be specified only if 'qcom,swire-control' is defined. The minimum and maximum values are 1400mV and 7700mV. @@ -219,7 +232,7 @@ Example: compatible = "qcom,qpnp-labibb-regulator"; #address-cells = <1>; #size-cells = <1>; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; qcom,pmic-revid = <&pmi8994_revid>; qcom,skip-2nd-swire-cmd; @@ -227,7 +240,8 @@ Example: reg = <0xde00 0x100>; reg-names = "lab"; - interrupts = <0x3 0xde 0x0>; + interrupts = <0x3 0xde 0x0 + IRQ_TYPE_EDGE_RISING>; interrupt-names = "lab-vreg-ok"; regulator-name = "lab_reg"; @@ -247,7 +261,7 @@ Example: qcom,qpnp-lab-full-pull-down; qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; - qcom,qpnp-lab-limit-maximum-current = <800>; + qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <40>; qcom,qpnp-lab-ps-enable; diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index 82befcbd24a3..c3d58ce2c864 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -1606,6 +1606,130 @@ Example: asoc-wsa-codec-prefixes = "SpkrMono"; }; +* MSMFALCON ASoC Machine driver + +Required properties: +- compatible : "qcom,msmfalcon-asoc-snd" +- qcom,model : The user-visible name of this sound card. +- qcom,msm-hs-micbias-type : This property is used to recognize the headset + micbias type, internal or external. +- qcom,msm-mbhc-hphl-swh: This property is used to distinguish headset HPHL +switch type on target typically the switch type will be normally open or +normally close, value for this property 0 for normally close and 1 for +normally open. +- qcom,msm-mbhc-gnd-swh: This property is used to distinguish headset GND +switch type on target typically the switch type will be normally open or +normally close, value for this property 0 for normally close and 1 for +normally open. +- qcom,audio-routing : A list of the connections between audio components. +- qcom,msm-gpios : Lists down all the gpio sets that are supported. +- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets +mentioned in qcom,msm-gpios. +- pinctrl-names : The combinations of gpio sets from above that are supported in +the flavor. +- pinctrl-# : Pinctrl states as mentioned in pinctrl-names. + +Optional properties: +- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming. +- qcom,msm-micbias1-ext-cap : Boolean. Enable micbias1 external +capacitor mode. +- qcom,msm-micbias2-ext-cap : Boolean. Enable micbias2 external +capacitor mode. +- qcom,msm-spk-ext-pa : GPIO which enables external speaker pa. +- qcom,msm-mclk-freq : This property is used to inform machine driver about +mclk frequency needs to be configured for internal and external PA. +- asoc-platform: This is phandle list containing the references to platform device + nodes that are used as part of the sound card dai-links. +- asoc-platform-names: This property contains list of platform names. The order of + the platform names should match to that of the phandle order + given in "asoc-platform". +- asoc-cpu: This is phandle list containing the references to cpu dai device nodes + that are used as part of the sound card dai-links. +- asoc-cpu-names: This property contains list of cpu dai names. The order of the + cpu dai names should match to that of the phandle order given. +- asoc-codec: This is phandle list containing the references to codec dai device + nodes that are used as part of the sound card dai-links. +- asoc-codec-names: This property contains list of codec dai names. The order of the + codec dai names should match to that of the phandle order given + in "asoc-codec". +- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target +- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target +- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device + +Example: + sound { + compatible = "qcom,msmfalcon-asoc-snd"; + qcom,model = "msmfalcon-snd-card"; + qcom,msm-mclk-freq = <9600000>; + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; + qcom,msm-hs-micbias-type = "internal"; + qcom,msm-micbias1-ext-cap; + qcom,audio-routing = + "RX_BIAS", "MCLK", + "SPK_RX_BIAS", "MCLK", + "INT_LDO_H", "MCLK", + "MIC BIAS External", "Handset Mic", + "MIC BIAS Internal2", "Headset Mic", + "MIC BIAS External", "Secondary Mic", + "AMIC1", "MIC BIAS External", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External"; + qcom,msm-gpios = + "int_pdm", + "us_eu_gpio"; + qcom,pinctrl-names = + "all_off", + "int_pdm_act", + "us_eu_gpio_act", + "int_pdm_us_eu_gpio_act"; + pinctrl-names = + "all_off", + "int_pdm_act", + "us_eu_gpio_act", + "int_pdm_us_eu_gpio_act"; + pinctrl-0 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus &cross_conn_det_sus>; + pinctrl-1 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act &cross_conn_det_sus>; + pinctrl-2 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus &cross_conn_det_act>; + pinctrl-3 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act &cross_conn_det_act>; + qcom,cdc-us-euro-gpios = <&msm_gpio 63 0>; + asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>, + <&loopback>, <&compress>, <&hostless>, + <&afe>, <&lsm>, <&routing>, <&lpa>; + asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", + "msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback", + "msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe", + "msm-lsm-client", "msm-pcm-routing", "msm-pcm-lpa"; + asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>, + <&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>, <&dai_mi2s3>, + <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, + <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>, + <&bt_sco_rx>, <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>, + <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>, + <&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>, + <&incall_music_2_rx>; + asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8", + "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", + "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", + "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", + "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", + "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", + "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", + "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289", + "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293", + "msm-dai-q6-dev.224", "msm-dai-q6-dev.225", + "msm-dai-q6-dev.241", "msm-dai-q6-dev.240", + "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772", + "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770"; + asoc-codec = <&stub_codec>; + asoc-codec-names = "msm-stub-codec.1"; + qcom,wsa-max-devs = <2>; + qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>, + <&wsa881x_213>, <&wsa881x_214>; + qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft", + "SpkrRight", "SpkrLeft"; + }; + * MSM8952 Slimbus ASoC Machine driver Required properties: @@ -2032,6 +2156,139 @@ Example: asoc-codec-names = "msm-stub-codec.1"; }; +* MSMFALCON ASoC Slimbus Machine driver + +Required properties: +- compatible : "qcom,msmfalcon-asoc-snd-tasha" for tasha codec, + "qcom,msmfalcon-asoc-snd-tavil" for tavil codec. +- qcom,model : The user-visible name of this sound card. +- qcom,msm-mclk-freq : MCLK frequency value for external codec +- qcom,msm-gpios : Lists down all the gpio sets that are supported. +- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets +mentioned in qcom,msm-gpios. Say we have 2^N combinations for N GPIOs, +this would list all the 2^N combinations. +- pinctrl-names : The combinations of gpio sets from above that are supported in +the flavor. This can be sometimes same as qcom, pinctrl-names i.e with 2^N +combinations or will have less incase if some combination is not supported. +- pinctrl-# : Pinctrl states as mentioned in pinctrl-names. +- qcom,audio-routing : A list of the connections between audio components. +- asoc-platform: This is phandle list containing the references to platform device + nodes that are used as part of the sound card dai-links. +- asoc-platform-names: This property contains list of platform names. The order of + the platform names should match to that of the phandle order + given in "asoc-platform". +- asoc-cpu: This is phandle list containing the references to cpu dai device nodes + that are used as part of the sound card dai-links. +- asoc-cpu-names: This property contains list of cpu dai names. The order of the + cpu dai names should match to that of the phandle order given + in "asoc-cpu". The cpu names are in the form of "%s.%d" form, + where the id (%d) field represents the back-end AFE port id that + this CPU dai is associated with. +- asoc-codec: This is phandle list containing the references to codec dai device + nodes that are used as part of the sound card dai-links. +- asoc-codec-names: This property contains list of codec dai names. The order of the + codec dai names should match to that of the phandle order given + in "asoc-codec". +Optional properties: +- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming. +- clock-names : clock name defined for external clock. +- clocks : external clock defined for codec clock. +- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target +- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target +- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device + +Example: + + sound-9335 { + compatible = "qcom,msmfalcon-asoc-snd-tasha"; + qcom,model = "msmfalcon-tasha-snd-card"; + + qcom,audio-routing = + "RX_BIAS", "MCLK", + "LDO_H", "MCLK", + "AIF4 MAD", "MCLK", + "ultrasound amp", "LINEOUT1", + "ultrasound amp", "LINEOUT3", + "AMIC1", "MIC BIAS1 Internal1", + "MIC BIAS1 Internal1", "Handset Mic", + "AMIC2", "MIC BIAS2 External", + "MIC BIAS2 External", "Headset Mic", + "AMIC3", "MIC BIAS2 External", + "MIC BIAS2 External", "ANCRight Headset Mic", + "AMIC4", "MIC BIAS2 External", + "MIC BIAS2 External", "ANCLeft Headset Mic", + "DMIC1", "MIC BIAS1 External", + "MIC BIAS1 External", "Digital Mic1", + "DMIC2", "MIC BIAS1 External", + "MIC BIAS1 External", "Digital Mic2", + "DMIC3", "MIC BIAS3 External", + "MIC BIAS3 External", "Digital Mic3", + "DMIC4", "MIC BIAS3 External", + "MIC BIAS3 External", "Digital Mic4", + "DMIC5", "MIC BIAS4 External", + "MIC BIAS4 External", "Digital Mic5", + "DMIC6", "MIC BIAS4 External", + "MIC BIAS4 External", "Digital Mic6"; + + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; + qcom,msm-mclk-freq = <9600000>; + qcom,msm-gpios = + "slim", + "us_eu_gpio"; + qcom,pinctrl-names = + "all_off", + "slim_act", + "us_eu_gpio_act", + "slim_us_eu_gpio_act"; + pinctrl-names = + "all_off", + "slim_act", + "us_eu_gpio_act", + "slim_us_eu_gpio_act"; + pinctrl-0 = <&cdc_slim_lines_sus &cross_conn_det_sus>; + pinctrl-1 = <&cdc_slim_lines_act &cross_conn_det_sus>; + pinctrl-2 = <&cdc_slim_lines_sus &cross_conn_det_act>; + pinctrl-3 = <&cdc_slim_lines_act &cross_conn_det_act>; + qcom,cdc-us-euro-gpios = <&msm_gpio 63 0>; + asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>, + <&loopback>, <&compress>, <&hostless>, + <&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>; + asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", + "msm-pcm-dsp.2", "msm-voip-dsp", + "msm-pcm-voice", "msm-pcm-loopback", + "msm-compress-dsp", "msm-pcm-hostless", + "msm-pcm-afe", "msm-lsm-client", + "msm-pcm-routing", "msm-cpe-lsm", + "msm-compr-dsp"; + asoc-cpu = <&dai_hdmi>, + <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, + <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, + <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>, + <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, + <&afe_proxy_tx>, <&incall_record_rx>, + <&incall_record_tx>, <&incall_music_rx>, + <&incall_music_2_rx>, <&sb_5_rx>; + asoc-cpu-names = "msm-dai-q6-hdmi.8", + "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", + "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", + "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", + "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", + "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", + "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224", + "msm-dai-q6-dev.225", "msm-dai-q6-dev.241", + "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", + "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773", + "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394"; + asoc-codec = <&stub_codec>; + asoc-codec-names = "msm-stub-codec.1"; + qcom,wsa-max-devs = <2>; + qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>, + <&wsa881x_213>, <&wsa881x_214>; + qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft", + "SpkrRight", "SpkrLeft"; + }; + * MSMCOBALT ASoC Machine driver Required properties: diff --git a/Documentation/scheduler/sched-hmp.txt b/Documentation/scheduler/sched-hmp.txt index 298064bc44d7..091d49ea80cf 100644 --- a/Documentation/scheduler/sched-hmp.txt +++ b/Documentation/scheduler/sched-hmp.txt @@ -31,6 +31,7 @@ CONTENTS 6.1 Per-CPU Window-Based Stats 6.2 Per-task Window-Based Stats 6.3 Effect of various task events + 6.4 Tying it all together 7. Tunables 8. HMP Scheduler Trace Points 8.1 sched_enq_deq_task @@ -872,11 +873,17 @@ both in what they mean and also how they are derived. *** 6.1 Per-CPU Window-Based Stats -In addition to the per-task window-based demand, the HMP scheduler -extensions also track the aggregate demand seen on each CPU. This is -done using the same windows that the task demand is tracked with -(which is in turn set by the governor when frequency guidance is in -use). There are four quantities maintained for each CPU by the HMP scheduler: +The scheduler tracks two separate types of quantities on a per CPU basis. +The first type has to deal with the aggregate load on a CPU and the second +type deals with top-tasks on that same CPU. We will first proceed to explain +what is maintained as part of each type of statistics and then provide the +connection between these two types of statistics at the end. + +First lets describe the HMP scheduler extensions to track the aggregate load +seen on each CPU. This is done using the same windows that the task demand +is tracked with (which is in turn set by the governor when frequency guidance +is in use). There are four quantities maintained for each CPU by the HMP +scheduler for tracking CPU load: curr_runnable_sum: aggregate demand from all tasks which executed during the current (not yet completed) window @@ -903,24 +910,86 @@ A 'new' task is defined as a task whose number of active windows since fork is less than sysctl_sched_new_task_windows. An active window is defined as a window where a task was observed to be runnable. +Moving on the second type of statistics; top-tasks, the scheduler tracks a list +of top tasks per CPU. A top-task is defined as the task that runs the most in a +given window on that CPU. This includes task that ran on that CPU through out +the window or were migrated to that CPU prior to window expiration. It does not +include tasks that were migrated away from that CPU prior to window expiration. + +To track top tasks, we first realize that there is no strict need to maintain +the task struct itself as long as we know the load exerted by the top task. We +also realize that to maintain top tasks on every CPU we have to track the +execution of every single task that runs during the window. The load associated +with a task needs to be migrated when the task migrates from one CPU to another. +When the top task migrates away, we need to locate the second top task and so +on. + +Given the above realizations, we use hashmaps to track top task load both +for the current and the previous window. This hashmap is implemented as an array +of fixed size. The key of the hashmap is given by +task_execution_time_in_a_window / array_size. The size of the array (number of +buckets in the hashmap) dictate the load granularity of each bucket. The value +stored in each bucket is a refcount of all the tasks that executed long enough +to be in that bucket. This approach has a few benefits. Firstly, any top task +stats update now take O(1) time. While task migration is also O(1), it does +still involve going through up to the size of the array to find the second top +task. We optimize this search by using bitmaps. The next set bit in the bitmap +gives the position of the second top task in our hashamp. + +Secondly, and more importantly, not having to store the task struct itself +saves a lot of memory usage in that 1) there is no need to retrieve task structs +later causing cache misses and 2) we don't have to unnecessarily hold up task +memory for up to 2 full windows by calling get_task_struct() after a task exits. + +Given the motivation above, here are a list of quantities tracked as part of +per CPU task top-tasks management + + top_tasks[NUM_TRACKED_WINDOWS] - Hashmap of top-task load for the current and + previous window + + BITMAP_ARRAY(top_tasks_bitmap) - Two bitmaps for the current and previous + windows corresponding to the top-task + hashmap. + + load_subs[NUM_TRACKED_WINDOWS] - An array of load subtractions to be carried + out form curr/prev_runnable_sums for each CPU + prior to reporting load to the governor. The + purpose for this will be explained later in + the section pertaining to the TASK_MIGRATE + event. The type struct load_subtractions, + stores the value of the subtraction along + with the window start value for the window + for which the subtraction has to take place. + + + curr_table - Indication of which index of the array points to the current + window. + + curr_top - The top task on a CPU at any given moment in the current window + + prev_top - The top task on a CPU in the previous window + + *** 6.2 Per-task window-based stats Corresponding to curr_runnable_sum and prev_runnable_sum, two counters are maintained per-task -curr_window - represents cpu demand of task in its most recently tracked - window -prev_window - represents cpu demand of task in the window prior to the one - being tracked by curr_window +curr_window_cpu - represents task's contribution to cpu busy time on + various CPUs in the current window -The above counters are resued for nt_curr_runnable_sum and -nt_prev_runnable_sum. +prev_window_cpu - represents task's contribution to cpu busy time on + various CPUs in the previous window + +curr_window - represents the sum of all entries in curr_window_cpu + +prev_window - represents the sum of all entries in prev_window_cpu "cpu demand" of a task includes its execution time and can also include its wait time. 'SCHED_FREQ_ACCOUNT_WAIT_TIME' controls whether task's wait -time is included in its 'curr_window' and 'prev_window' counters or not. +time is included in its CPU load counters or not. -Needless to say, curr_runnable_sum counter of a cpu is derived from curr_window +Curr_runnable_sum counter of a cpu is derived from curr_window_cpu[cpu] counter of various tasks that ran on it in its most recent window. *** 6.3 Effect of various task events @@ -931,11 +1000,17 @@ PICK_NEXT_TASK This represents beginning of execution for a task. Provided the task refers to a non-idle task, a portion of task's wait time that corresponds to the current window being tracked on a cpu is added to - task's curr_window counter, provided SCHED_FREQ_ACCOUNT_WAIT_TIME is - set. The same quantum is also added to cpu's curr_runnable_sum counter. - The remaining portion, which corresponds to task's wait time in previous - window is added to task's prev_window and cpu's prev_runnable_sum - counters. + task's curr_window_cpu and curr_window counter, provided + SCHED_FREQ_ACCOUNT_WAIT_TIME is set. The same quantum is also added to + cpu's curr_runnable_sum counter. The remaining portion, which + corresponds to task's wait time in previous window is added to task's + prev_window, prev_window_cpu and cpu's prev_runnable_sum counters. + + CPUs top_tasks hashmap is updated if needed with the new information. + Any previous entries in the hashmap are deleted and newer entries are + created. The top_tasks_bitmap reflects the updated state of the + hashmap. If the top task for the current and/or previous window has + changed, curr_top and prev_top are updated accordingly. PUT_PREV_TASK This represents end of execution of a time-slice for a task, where the @@ -943,9 +1018,16 @@ PUT_PREV_TASK or (in case of task being idle with cpu having non-zero rq->nr_iowait count and sched_io_is_busy =1), a portion of task's execution time, that corresponds to current window being tracked on a cpu is added to task's - curr_window_counter and also to cpu's curr_runnable_sum counter. Portion - of task's execution that corresponds to the previous window is added to - task's prev_window and cpu's prev_runnable_sum counters. + curr_window_cpu and curr_window counter and also to cpu's + curr_runnable_sum counter. Portion of task's execution that corresponds + to the previous window is added to task's prev_window, prev_window_cpu + and cpu's prev_runnable_sum counters. + + CPUs top_tasks hashmap is updated if needed with the new information. + Any previous entries in the hashmap are deleted and newer entries are + created. The top_tasks_bitmap reflects the updated state of the + hashmap. If the top task for the current and/or previous window has + changed, curr_top and prev_top are updated accordingly. TASK_UPDATE This event is called on a cpu's currently running task and hence @@ -955,34 +1037,128 @@ TASK_UPDATE TASK_WAKE This event signifies a task waking from sleep. Since many windows - could have elapsed since the task went to sleep, its curr_window - and prev_window are updated to reflect task's demand in the most - recent and its previous window that is being tracked on a cpu. + could have elapsed since the task went to sleep, its + curr_window_cpu/curr_window and prev_window_cpu/prev_window are + updated to reflect task's demand in the most recent and its previous + window that is being tracked on a cpu. Updated stats will trigger + the same book-keeping for top-tasks as other events. TASK_MIGRATE This event signifies task migration across cpus. It is invoked on the task prior to being moved. Thus at the time of this event, the task can be considered to be in "waiting" state on src_cpu. In that way this event reflects actions taken under PICK_NEXT_TASK (i.e its - wait time is added to task's curr/prev_window counters as well + wait time is added to task's curr/prev_window/_cpu counters as well as src_cpu's curr/prev_runnable_sum counters, provided - SCHED_FREQ_ACCOUNT_WAIT_TIME is non-zero). After that update, - src_cpu's curr_runnable_sum is reduced by task's curr_window value - and dst_cpu's curr_runnable_sum is increased by task's curr_window - value. Similarly, src_cpu's prev_runnable_sum is reduced by task's - prev_window value and dst_cpu's prev_runnable_sum is increased by - task's prev_window value. + SCHED_FREQ_ACCOUNT_WAIT_TIME is non-zero). + + After that update, we make a distinction between intra-cluster and + inter-cluster migrations for further book-keeping. + + For intra-cluster migrations, we simply remove the entry for the task + in the top_tasks hashmap from the source CPU and add the entry to the + destination CPU. The top_tasks_bitmap, curr_top and prev_top are + updated accordingly. We then find the second top-task top in our + top_tasks hashmap for both the current and previous window and set + curr_top and prev_top to their new values. + + For inter-cluster migrations we have a much more complicated scheme. + Firstly we add to the destination CPU's curr/prev_runnable_sum + the tasks curr/prev_window. Note we add the sum and not the + contribution any individual CPU. This is because when a tasks migrates + across clusters, we need the new cluster to ramp up to the appropriate + frequency given the task's total execution summed up across all CPUs + in the previous cluster. + + Secondly the src_cpu's curr/prev_runnable_sum are reduced by task's + curr/prev_window_cpu values. + + Thirdly, we need to walk all the CPUs in the cluster and subtract from + each CPU's curr/prev_runnable_sum the task's respective + curr/prev_window_cpu values. However, subtracting load from each of + the source CPUs is not trivial, as it would require all runqueue + locks to be held. To get around this we introduce a deferred load + subtraction mechanism whereby subtracting load from each of the source + CPUs is deferred until an opportune moment. This opportune moment is + when the governor comes asking the scheduler for load. At that time, all + necessary runqueue locks are already held. + + There are a few cases to consider when doing deferred subtraction. Since + we are not holding all runqueue locks other CPUs in the source cluster + can be in a different window than the source CPU where the task is + migrating from. + + Case 1: + Other CPU in the source cluster is in the same window. No special + consideration. + + Case 2: + Other CPU in the source cluster is ahead by 1 window. In this + case, we will be doing redundant updates to subtraction load for the + prev window. There is no way to avoid this redundant update though, + without holding the rq lock. + + Case 3: + Other CPU in the source cluster is trailing by 1 window In this + case, we might end up overwriting old data for that CPU. But this is not + a problem as when the other CPU calls update_task_ravg() it will move to + the same window. This relies on maintaining synchronized windows between + CPUs, which is true today. + + To achieve all the above, we simple add the task's curr/prev_window_cpu + contributions to the per CPU load_subtractions array. These load + subtractions are subtracted from the respective CPU's + curr/prev_runnable_sums before the governor queries CPU load. Once this + is complete, the scheduler sets all curr/prev_window_cpu contributions + of the task to 0 for all CPUs in the source cluster. The destination + CPUs's curr/prev_window_cpu is updated with the tasks curr/prev_window + sums. + + Finally, we must deal with frequency aggregation. When frequency + aggregation is in effect, there is little point in dealing with per CPU + footprint since the load of all related tasks have to be reported on a + single CPU. Therefore when a task enters a related group we clear out + all per CPU contributions and add it to the task CPU's cpu_time struct. + From that point onwards we stop managing per CPU contributions upon + inter cluster migrations since that work is redundant. Finally when a + task exits a related group we must walk every CPU in reset all CPU + contributions. We then set the task CPU contribution to the respective + curr/prev sum values and add that sum to the task CPU rq runnable sum. + + Top-task management is the same as in the case of intra-cluster + migrations. IRQ_UPDATE This event signifies end of execution of an interrupt handler. This event results in update of cpu's busy time counters, curr_runnable_sum - and prev_runnable_sum, provided cpu was idle. - When sched_io_is_busy = 0, only the interrupt handling time is added - to cpu's curr_runnable_sum and prev_runnable_sum counters. When - sched_io_is_busy = 1, the event mirrors actions taken under - TASK_UPDATED event i.e time since last accounting of idle task's cpu - usage is added to cpu's curr_runnable_sum and prev_runnable_sum - counters. + and prev_runnable_sum, provided cpu was idle. When sched_io_is_busy = 0, + only the interrupt handling time is added to cpu's curr_runnable_sum and + prev_runnable_sum counters. When sched_io_is_busy = 1, the event mirrors + actions taken under TASK_UPDATED event i.e time since last accounting + of idle task's cpu usage is added to cpu's curr_runnable_sum and + prev_runnable_sum counters. No update is needed for top-tasks in this + case. + +*** 6.4 Tying it all together + +Now the scheduler maintains two independent quantities for load reporing 1) CPU +load as represented by prev_runnable_sum and 2) top-tasks. The reported load +is governed by tunable sched_freq_reporting_policy. The default choice is +FREQ_REPORT_MAX_CPU_LOAD_TOP_TASK. In other words: + +max(prev_runnable_sum, top_task load) + +Let's explain the rationale behind the choice. CPU load tracks the exact amount +of execution observed on a CPU. This is close to the quantity that the vanilla +governor used to track. It offers the advantages of no load over-reporting that +our earlier load fixup mechanisms had deal with. It then also tackles the part +picture problem by keeping of track of tasks that might be migrating across +CPUs leaving a small footprint on each CPU. Since we maintain one top task per +CPU, we can handle as many top tasks as the number of CPUs in a cluster. We +might miss a few cases where the combined load of the top and non-top tasks on +a CPU are more representative of the true load. However, those cases have been +deemed to rare and have little impact on overall load/frequency behavior. + =========== 7. TUNABLES @@ -1238,6 +1414,18 @@ However LPM exit latency associated with an idle CPU outweigh the above benefits on some targets. When this knob is turned on, the waker CPU is selected if it has only 1 runnable task. +*** 7.20 sched_freq_reporting_policy + +Appears at: /proc/sys/kernel/sched_freq_reporting_policy + +Default value: 0 + +This dictates what the load reporting policy to the governor should be. The +default value is FREQ_REPORT_MAX_CPU_LOAD_TOP_TASK. Other values include +FREQ_REPORT_CPU_LOAD which only reports CPU load to the governor and +FREQ_REPORT_TOP_TASK which only reports the load of the top task on a CPU +to the governor. + ========================= 8. HMP SCHEDULER TRACE POINTS ========================= @@ -1318,7 +1506,7 @@ frequency of the CPU for real time task placement). Logged when window-based stats are updated for a task. The update may happen for a variety of reasons, see section 2.5, "Task Events." -<idle>-0 [004] d.h4 12700.711513: sched_update_task_ravg: wc 12700711473496 ws 12700691772135 delta 19701361 event TASK_WAKE cpu 4 cur_freq 199200 cur_pid 0 task 13227 (powertop) ms 12640648272532 delta 60063200964 demand 13364423 sum 0 irqtime 0 cs 0 ps 495018 cur_window 0 prev_window 0 +rcu_preempt-7 [000] d..3 262857.738888: sched_update_task_ravg: wc 262857521127957 ws 262857490000000 delta 31127957 event PICK_NEXT_TASK cpu 0 cur_freq 291055 cur_pid 7 task 9309 (kworker/u16:0) ms 262857520627280 delta 500677 demand 282196 sum 156201 irqtime 0 pred_demand 267103 rq_cs 478718 rq_ps 0 cur_window 78433 (78433 0 0 0 0 0 0 0 ) prev_window 146430 (0 146430 0 0 0 0 0 0 ) nt_cs 0 nt_ps 0 active_wins 149 grp_cs 0 grp_ps 0, grp_nt_cs 0, grp_nt_ps: 0 curr_top 6 prev_top 2 - wc: wallclock, output of sched_clock(), monotonically increasing time since boot (will roll over in 585 years) (ns) @@ -1344,9 +1532,27 @@ for a variety of reasons, see section 2.5, "Task Events." counter. - ps: prev_runnable_sum of cpu (ns). See section 6.1 for more details of this counter. -- cur_window: cpu demand of task in its most recently tracked window (ns) -- prev_window: cpu demand of task in the window prior to the one being tracked - by cur_window +- cur_window: cpu demand of task in its most recently tracked window summed up + across all CPUs (ns). This is followed by a list of contributions on each + individual CPU. +- prev_window: cpu demand of task in its previous window summed up across + all CPUs (ns). This is followed by a list of contributions on each individual + CPU. +- nt_cs: curr_runnable_sum of a cpu for new tasks only (ns). +- nt_ps: prev_runnable_sum of a cpu for new tasks only (ns). +- active_wins: No. of active windows since task statistics were initialized +- grp_cs: curr_runnable_sum for colocated tasks. This is independent from + cs described above. The addition of these two fields give the total CPU + load for the most recent window +- grp_ps: prev_runnable_sum for colocated tasks. This is independent from + ps described above. The addition of these two fields give the total CPU + load for the previous window. +- grp_nt_cs: curr_runnable_sum of a cpu for grouped new tasks only (ns). +- grp_nt_ps: prev_runnable_sum for a cpu for grouped new tasks only (ns). +- curr_top: index of the top task in the top_tasks array in the current + window for a CPU. +- prev_top: index of the top task in the top_tasks array in the previous + window for a CPU *** 8.5 sched_update_history diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 7ab87629378a..7810842100cd 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -128,7 +128,8 @@ dtb-$(CONFIG_ARCH_MSMCOBALT) += msmcobalt-sim.dtb \ apqcobalt-v2.1-cdp.dtb \ apqcobalt-v2.1-qrd.dtb \ msmcobalt-v2.1-interposer-msmfalcon-cdp.dtb \ - msmcobalt-v2.1-interposer-msmfalcon-mtp.dtb + msmcobalt-v2.1-interposer-msmfalcon-mtp.dtb \ + msmcobalt-v2.1-interposer-msmfalcon-qrd.dtb dtb-$(CONFIG_ARCH_MSMHAMSTER) += msmhamster-rumi.dtb diff --git a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi index 9083c89802f3..70156b1f8493 100644 --- a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi +++ b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi @@ -361,7 +361,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &ibb_regulator { diff --git a/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi b/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi index a2085945ac33..a7482bcce112 100644 --- a/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi +++ b/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi @@ -361,7 +361,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &rpm_bus { diff --git a/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi b/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi index 4e7379d9e164..0ee28c2c427e 100644 --- a/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi +++ b/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi @@ -364,7 +364,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &ibb_regulator { diff --git a/arch/arm/boot/dts/qcom/batterydata-qrd-skuk-4v4-3000mah.dtsi b/arch/arm/boot/dts/qcom/batterydata-qrd-skuk-4v4-3000mah.dtsi index 76126c21c43a..8bf98d83d381 100644 --- a/arch/arm/boot/dts/qcom/batterydata-qrd-skuk-4v4-3000mah.dtsi +++ b/arch/arm/boot/dts/qcom/batterydata-qrd-skuk-4v4-3000mah.dtsi @@ -18,44 +18,44 @@ qcom,qrd_msmcobalt_skuk_3000mah { qcom,battery-type = "qrd_msmcobalt_skuk_300mah"; qcom,checksum = <0x0F19>; qcom,fg-profile-data = [ - 05 B2 1F 6F - FC A3 0A 6E - FD DB 1D 8C - 1D AE 12 C2 - 23 00 18 7E - 52 B4 45 8D - 00 00 00 55 - 00 00 00 0F - C5 92 00 00 - CA A0 CD 95 - 00 0C 00 1F - EC C3 F2 56 - F3 27 06 7B - 12 FF 01 02 - 3A 21 DA 1C - 40 40 09 1C - 00 05 00 07 - 05 B4 1F AC - FC EF 0A 57 - 00 2E 1D 6A - 14 BA 0B 12 - 22 DC 19 40 - 53 03 45 79 - 00 00 00 53 - 00 00 00 0E - CC 05 00 00 - CA 24 BB 3A - 00 00 00 1C - EC C3 F2 56 - F2 A2 06 A6 - 01 C7 06 96 - 1A CF EA 8B - 33 08 33 BA - 00 00 10 07 - 46 66 0C 3A - 00 19 00 1C - FA 0A 01 98 - 00 00 00 FF + 6F 1F B2 05 + 6E 0A A3 FC + 8C 1D DB FD + C2 12 AE 1D + 7E 18 00 23 + 8D 45 B4 52 + 55 00 00 00 + 0F 00 00 00 + 00 00 92 C5 + 95 CD A0 CA + 1F 00 0C 00 + 56 F2 C3 EC + 7B 06 27 F3 + 02 01 FF 12 + 1C DA 21 3A + 1C 09 40 40 + 07 00 05 00 + AC 1F B4 05 + 57 0A EF FC + 6A 1D 2E 00 + 12 0B BA 14 + 40 19 DC 22 + 79 45 03 53 + 53 00 00 00 + 0E 00 00 00 + 00 00 05 CC + 3A BB 24 CA + 1C 00 00 00 + 56 F2 C3 EC + A6 06 A2 F2 + 96 06 C7 01 + 8B EA CF 1A + BA 33 08 33 + 07 10 00 00 + 3A 0C 66 46 + 1C 00 19 00 + 98 01 0A FA + FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon-rpm-regulator.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon-rpm-regulator.dtsi new file mode 100644 index 000000000000..f500079e6953 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm-pm2falcon-rpm-regulator.dtsi @@ -0,0 +1,238 @@ +/* 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. + */ + +&rpm_bus { + rpm-regulator-smpb1 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "smpb"; + qcom,resource-id = <1>; + qcom,regulator-type = <1>; + status = "disabled"; + + regulator-s1 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s1"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-smpb2 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "smpb"; + qcom,resource-id = <2>; + qcom,regulator-type = <1>; + status = "disabled"; + + regulator-s2 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s2"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-smpb3 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "smpb"; + qcom,resource-id = <3>; + qcom,regulator-type = <1>; + status = "disabled"; + + regulator-s3 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s3"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-smpb5 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "smpb"; + qcom,resource-id = <5>; + qcom,regulator-type = <1>; + status = "disabled"; + + regulator-s5 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s5"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob1 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldob"; + qcom,resource-id = <1>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l1 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l1"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob2 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldob"; + qcom,resource-id = <2>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l2 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l2"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob3 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldob"; + qcom,resource-id = <3>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l3 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l3"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob4 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldob"; + qcom,resource-id = <4>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l4 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l4"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob5 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldob"; + qcom,resource-id = <5>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l5 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l5"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob6 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldob"; + qcom,resource-id = <6>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l6 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l6"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob7 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldob"; + qcom,resource-id = <7>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l7 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l7"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob8 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldob"; + qcom,resource-id = <8>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l8 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l8"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob9 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "rwsc"; + qcom,resource-id = <9>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l9 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l9"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldob10 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "rwsm"; + qcom,resource-id = <10>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l10 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l10"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-bobb { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "bobb"; + qcom,resource-id = <1>; + qcom,regulator-type = <4>; + status = "disabled"; + + regulator-bob { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_bob"; + qcom,set = <3>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi index 41589d02f6fc..0e5a999e4642 100644 --- a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi @@ -357,10 +357,6 @@ qcom,led-name = "led:switch_0"; qcom,led-mask = <3>; qcom,default-led-trigger = "switch0_trigger"; - reg0 { - regulator-name = "pmfalcon_bob"; - max-voltage-uv = <3600000>; - }; }; pm2falcon_switch1: qcom,led_switch_1 { @@ -368,10 +364,6 @@ qcom,led-name = "led:switch_1"; qcom,led-mask = <4>; qcom,default-led-trigger = "switch1_trigger"; - reg0 { - regulator-name = "pmfalcon_bob"; - max-voltage-uv = <3600000>; - }; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msm-pmfalcon-rpm-regulator.dtsi b/arch/arm/boot/dts/qcom/msm-pmfalcon-rpm-regulator.dtsi new file mode 100644 index 000000000000..0b625bf04ef5 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm-pmfalcon-rpm-regulator.dtsi @@ -0,0 +1,298 @@ +/* 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. + */ + +&rpm_bus { + rpm-regulator-smpa4 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "smpa"; + qcom,resource-id = <4>; + qcom,regulator-type = <1>; + status = "disabled"; + + regulator-s4 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_s4"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-smpa5 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "smpa"; + qcom,resource-id = <5>; + qcom,regulator-type = <1>; + status = "disabled"; + + regulator-s5 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_s5"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-smpa6 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "smpa"; + qcom,resource-id = <6>; + qcom,regulator-type = <1>; + status = "disabled"; + + regulator-s6 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_s6"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa1 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <1>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l1 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l1"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa2 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <2>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l2 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l2"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa3 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <3>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l3 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l3"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa5 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <5>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l5 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l5"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa6 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <6>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l6 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l6"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa7 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <7>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l7 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l7"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa8 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <8>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l8 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l8"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa9 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <9>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l9 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l9"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa10 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <10>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l10 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l10"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa11 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <11>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l11 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l11"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa12 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <12>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l12 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l12"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa13 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <13>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l13 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l13"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa14 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <14>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l14 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l14"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa15 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <15>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l15 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l15"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa17 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <17>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l17 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l17"; + qcom,set = <3>; + status = "disabled"; + }; + }; + + rpm-regulator-ldoa19 { + compatible = "qcom,rpm-smd-regulator-resource"; + qcom,resource-name = "ldoa"; + qcom,resource-id = <19>; + qcom,regulator-type = <0>; + status = "disabled"; + + regulator-l19 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l19"; + qcom,set = <3>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi index bba70329c819..c46c0963ff56 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi @@ -497,7 +497,7 @@ qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; - qcom,qpnp-lab-limit-maximum-current = <800>; + qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <20>; qcom,qpnp-lab-ps-enable; diff --git a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi index a5243aff4282..640aa53364a5 100644 --- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi @@ -321,7 +321,7 @@ qcom,pmic-revid = <&pmicobalt_revid>; io-channels = <&pmicobalt_rradc 0>; io-channel-names = "rradc_batt_id"; - qcom,fg-esr-timer-awake = <64>; + qcom,fg-esr-timer-awake = <96>; qcom,fg-esr-timer-asleep = <256>; qcom,cycle-counter-en; status = "okay"; @@ -334,7 +334,8 @@ <0x2 0x40 0x2 IRQ_TYPE_EDGE_BOTH>, <0x2 0x40 0x3 IRQ_TYPE_EDGE_BOTH>, <0x2 0x40 0x4 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x40 0x5 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x40 0x5 + IRQ_TYPE_EDGE_RISING>, <0x2 0x40 0x6 IRQ_TYPE_EDGE_BOTH>, <0x2 0x40 0x7 IRQ_TYPE_EDGE_BOTH>; interrupt-names = "soc-update", @@ -554,6 +555,9 @@ regulator-min-microvolt = <4600000>; regulator-max-microvolt = <6000000>; + interrupts = <0x3 0xde 0x0 + IRQ_TYPE_EDGE_RISING>; + interrupt-names = "lab-vreg-ok"; qcom,qpnp-lab-min-voltage = <4600000>; qcom,qpnp-lab-step-size = <100000>; qcom,qpnp-lab-slew-rate = <5000>; @@ -568,13 +572,13 @@ qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; - qcom,qpnp-lab-limit-maximum-current = <800>; + qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <20>; qcom,qpnp-lab-ps-enable; qcom,qpnp-lab-nfet-size = <100>; qcom,qpnp-lab-pfet-size = <100>; - qcom,qpnp-lab-max-precharge-time = <300>; + qcom,qpnp-lab-max-precharge-time = <500>; }; }; @@ -740,10 +744,6 @@ qcom,led-name = "led:switch_0"; qcom,led-mask = <3>; qcom,default-led-trigger = "switch0_trigger"; - reg0 { - regulator-name = "pmicobalt_bob"; - max-voltage-uv = <3600000>; - }; }; pmicobalt_switch1: qcom,led_switch_1 { @@ -751,10 +751,6 @@ qcom,led-name = "led:switch_1"; qcom,led-mask = <4>; qcom,default-led-trigger = "switch1_trigger"; - reg0 { - regulator-name = "pmicobalt_bob"; - max-voltage-uv = <3600000>; - }; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi index 40df8b7ff4de..48cf099b84a8 100644 --- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi @@ -388,7 +388,7 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,cont-splash-enabled; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <720 128 720 64 720 64>; }; @@ -432,7 +432,7 @@ qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>; qcom,cont-splash-enabled; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <4 4 2 2 20 20>; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi index 30646dba1cd9..34e41c2bf28f 100644 --- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi @@ -376,7 +376,7 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,cont-splash-enabled; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <720 128 720 64 720 64>; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi index 4855da387e21..165c7de039e5 100644 --- a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi @@ -387,7 +387,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &dsi_dual_sharp_video { @@ -409,7 +409,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <720 128 720 64 720 64>; }; @@ -432,7 +432,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; /* panel supports slice height of 8/16/32/48/3840 */ qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>; }; @@ -480,7 +480,7 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <4 2 4 2 20 20>; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi index 19d052791c9a..5c62766b1a26 100644 --- a/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi @@ -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 @@ -452,7 +452,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &mdss_mdp { diff --git a/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi b/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi index 824d31afb7d8..baecf4b8574e 100644 --- a/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi @@ -629,14 +629,14 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; /* panel supports slice height of 8/16/32/48/3840 */ qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>; }; &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &pmi8994_mpps { diff --git a/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi index 07423a601b35..215608959dc5 100644 --- a/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi @@ -129,6 +129,40 @@ vddcx-supply = <&gdsc_gpu>; vdd-supply = <&gdsc_gpu_gx>; + /* GPU Mempools */ + qcom,gpu-mempools { + #address-cells= <1>; + #size-cells = <0>; + compatible = "qcom,gpu-mempools"; + + /* 4K Page Pool configuration */ + qcom,gpu-mempool@0 { + reg = <0>; + qcom,mempool-page-size = <4096>; + qcom,mempool-reserved = <2048>; + qcom,mempool-allocate; + }; + /* 8K Page Pool configuration */ + qcom,gpu-mempool@1 { + reg = <1>; + qcom,mempool-page-size = <8192>; + qcom,mempool-reserved = <1024>; + qcom,mempool-allocate; + }; + /* 64K Page Pool configuration */ + qcom,gpu-mempool@2 { + reg = <2>; + qcom,mempool-page-size = <65536>; + qcom,mempool-reserved = <256>; + }; + /* 1M Page Pool configuration */ + qcom,gpu-mempool@3 { + reg = <3>; + qcom,mempool-page-size = <1048576>; + qcom,mempool-reserved = <32>; + }; + }; + /* Power levels */ qcom,gpu-pwrlevels { #address-cells = <1>; diff --git a/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi b/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi index 33397e3e4762..dae7306cdd07 100644 --- a/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi @@ -319,7 +319,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &dsi_dual_jdi_4k_nofbc_video { diff --git a/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi index 3d534ff1550e..bd8aa7fe02f7 100644 --- a/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi @@ -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 @@ -343,7 +343,7 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,cont-splash-enabled; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <720 128 720 64 720 64>; }; @@ -387,7 +387,7 @@ qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>; qcom,cont-splash-enabled; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <4 4 2 2 20 20>; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi index 96279288d336..27d3eea5bc20 100644 --- a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi @@ -368,7 +368,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &dsi_dual_sharp_video { @@ -397,7 +397,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <720 128 720 64 720 64>; }; @@ -420,7 +420,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; /* panel supports slice height of 8/16/32/48/3840 */ qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>; }; @@ -468,7 +468,7 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <4 4 2 2 20 20>; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-qrd-vr1.dtsi new file mode 100644 index 000000000000..0fb1a0425dd5 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-qrd-vr1.dtsi @@ -0,0 +1,369 @@ +/* + * 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. + */ + +&soc { + led_flash0: qcom,camera-flash@0 { + cell-index = <0>; + compatible = "qcom,camera-flash"; + qcom,flash-source = <&pmicobalt_flash0 &pmicobalt_flash1>; + qcom,switch-source = <&pmicobalt_switch0>; + status = "ok"; + }; + + led_flash1: qcom,camera-flash@1 { + cell-index = <1>; + compatible = "qcom,camera-flash"; + qcom,flash-source = <&pmicobalt_flash2>; + qcom,switch-source = <&pmicobalt_switch1>; + status = "ok"; + }; +}; + +&tlmm{ + cam_sensor_front_active: cam_sensor_front_active { + /* RESET */ + mux { + pins = "gpio9"; + function = "gpio"; + }; + + config { + pins = "gpio9"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_front_suspend: cam_sensor_front_suspend { + /* RESET */ + mux { + pins = "gpio9"; + function = "gpio"; + }; + + config { + pins = "gpio9"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear2_active: cam_sensor_rear2_active { + /* RESET, STANDBY */ + mux { + pins = "gpio27","gpio8"; + function = "gpio"; + }; + + config { + pins = "gpio27","gpio8"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear2_suspend: cam_sensor_rear2_suspend { + /* RESET, STANDBY */ + mux { + pins = "gpio27","gpio8"; + function = "gpio"; + }; + config { + pins = "gpio27","gpio8"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; + + +&cci { + actuator0: qcom,actuator@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + }; + + actuator1: qcom,actuator@1 { + cell-index = <1>; + reg = <0x1>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + }; + + eeprom0: qcom,eeprom@0 { + cell-index = <0>; + reg = <0>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&pmcobalt_lvs1>; + cam_vana-supply = <&pmicobalt_bob>; + cam_vdig-supply = <&pmcobalt_s3>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <0 3312000 1352000>; + qcom,cam-vreg-max-voltage = <0 3600000 1352000>; + qcom,cam-vreg-op-mode = <0 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_rear_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_rear_suspend>; + gpios = <&tlmm 13 0>, + <&tlmm 30 0>, + <&pmcobalt_gpios 20 0>, + <&tlmm 29 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VDIG", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_mmss clk_mclk0_clk_src>, + <&clock_mmss clk_mmss_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom1: qcom,eeprom@1 { + cell-index = <1>; + reg = <0x1>; + compatible = "qcom,eeprom"; + cam_vdig-supply = <&pmcobalt_lvs1>; + cam_vio-supply = <&pmcobalt_lvs1>; + cam_vana-supply = <&pmicobalt_bob>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <0 0 3312000>; + qcom,cam-vreg-max-voltage = <0 0 3600000>; + qcom,cam-vreg-op-mode = <0 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_rear2_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_rear2_suspend>; + gpios = <&tlmm 14 0>, + <&tlmm 27 0>, + <&tlmm 8 0>; + qcom,gpio-standby = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_STANDBY1", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_mmss clk_mclk1_clk_src>, + <&clock_mmss clk_mmss_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom2: qcom,eeprom@2 { + cell-index = <2>; + reg = <0x2>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&pmcobalt_lvs1>; + cam_vana-supply = <&pmcobalt_l22>; + cam_vdig-supply = <&pmcobalt_s3>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <0 2864000 1352000>; + qcom,cam-vreg-max-voltage = <0 2864000 1352000>; + qcom,cam-vreg-op-mode = <0 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_front_active>; + pinctrl-1 = <&cam_sensor_mclk2_active + &cam_sensor_front_suspend>; + gpios = <&tlmm 15 0>, + <&tlmm 9 0>, + <&pmcobalt_gpios 9 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_VDIG"; + qcom,sensor-position = <1>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_mmss clk_mclk2_clk_src>, + <&clock_mmss clk_mmss_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@0 { + cell-index = <0>; + compatible = "qcom,camera"; + reg = <0x0>; + qcom,csiphy-sd-index = <0>; + qcom,csid-sd-index = <0>; + qcom,mount-angle = <270>; + qcom,led-flash-src = <&led_flash0>; + qcom,actuator-src = <&actuator0>; + qcom,eeprom-src = <&eeprom0>; + cam_vio-supply = <&pmcobalt_lvs1>; + cam_vana-supply = <&pmicobalt_bob>; + cam_vdig-supply = <&pmcobalt_s3>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <0 3312000 1352000>; + qcom,cam-vreg-max-voltage = <0 3600000 1352000>; + qcom,cam-vreg-op-mode = <0 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_rear_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_rear_suspend>; + gpios = <&tlmm 13 0>, + <&tlmm 30 0>, + <&pmcobalt_gpios 20 0>, + <&tlmm 29 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VDIG", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_mmss clk_mclk0_clk_src>, + <&clock_mmss clk_mmss_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@1 { + cell-index = <1>; + compatible = "qcom,camera"; + reg = <0x1>; + qcom,csiphy-sd-index = <1>; + qcom,csid-sd-index = <1>; + qcom,mount-angle = <90>; + qcom,eeprom-src = <&eeprom1>; + cam_vio-supply = <&pmcobalt_lvs1>; + cam_vana-supply = <&pmicobalt_bob>; + qcom,cam-vreg-name = "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <0 3312000>; + qcom,cam-vreg-max-voltage = <0 3600000>; + qcom,cam-vreg-op-mode = <0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_rear2_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_rear2_suspend>; + gpios = <&tlmm 14 0>, + <&tlmm 27 0>, + <&tlmm 8 0>; + qcom,gpio-standby = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_STANDBY1", + "CAM_VANA1"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_mmss clk_mclk1_clk_src>, + <&clock_mmss clk_mmss_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@2 { + cell-index = <2>; + compatible = "qcom,camera"; + reg = <0x02>; + qcom,csiphy-sd-index = <2>; + qcom,csid-sd-index = <2>; + qcom,mount-angle = <90>; + qcom,eeprom-src = <&eeprom2>; + qcom,led-flash-src = <&led_flash1>; + qcom,actuator-src = <&actuator1>; + cam_vio-supply = <&pmcobalt_lvs1>; + cam_vana-supply = <&pmcobalt_l22>; + cam_vdig-supply = <&pmcobalt_s3>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <0 2864000 1352000>; + qcom,cam-vreg-max-voltage = <0 2864000 1352000>; + qcom,cam-vreg-op-mode = <0 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_front_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_front_suspend>; + gpios = <&tlmm 15 0>, + <&tlmm 9 0>, + <&pmcobalt_gpios 9 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_VDIG"; + qcom,sensor-position = <1>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_mmss clk_mclk2_clk_src>, + <&clock_mmss clk_mmss_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; +}; + +&pmcobalt_gpios { + gpio@c800 { /* GPIO 9 - CAMERA SENSOR 2 VDIG */ + qcom,mode = <1>; /* Output */ + qcom,pull = <5>; /* No Pull */ + qcom,vin-sel = <0>; /* VIN1 GPIO_LV */ + qcom,src-sel = <0>; /* GPIO */ + qcom,invert = <0>; /* Invert */ + qcom,master-en = <1>; /* Enable GPIO */ + status = "ok"; + }; + + gpio@d300 { /* GPIO 20 - CAMERA SENSOR 0 VDIG */ + qcom,mode = <1>; /* Output */ + qcom,pull = <5>; /* No Pull */ + qcom,vin-sel = <1>; /* VIN1 GPIO_MV */ + qcom,src-sel = <0>; /* GPIO */ + qcom,invert = <0>; /* Invert */ + qcom,master-en = <1>; /* Enable GPIO */ + status = "ok"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi index 4822823aa63f..ca504a798659 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi @@ -17,11 +17,11 @@ compatible = "qca,wcn3990"; qca,bt-vdd-io-supply = <&pmcobalt_s3>; qca,bt-vdd-xtal-supply = <&pmcobalt_s5>; - qca,bt-vdd-core-supply = <&pmcobalt_l7_pin_ctrl>; - qca,bt-vdd-pa-supply = <&pmcobalt_l17_pin_ctrl>; - qca,bt-vdd-ldo-supply = <&pmcobalt_l25_pin_ctrl>; + qca,bt-vdd-core-supply = <&pmcobalt_l7>; + qca,bt-vdd-pa-supply = <&pmcobalt_l17>; + qca,bt-vdd-ldo-supply = <&pmcobalt_l25>; qca,bt-chip-pwd-supply = <&pmicobalt_bob_pin1>; - clocks = <&clock_gcc clk_rf_clk2>; + clocks = <&clock_gcc clk_rf_clk2_pin>; clock-names = "rf_clk2"; qca,bt-vdd-io-voltage-level = <1352000 1352000>; @@ -299,7 +299,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &pmicobalt_wled { @@ -382,7 +382,7 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,5v-boost-gpio = <&tlmm 51 0>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; - qcom,partial-update-enabled; + qcom,partial-update-enabled = "single_roi"; qcom,panel-roi-alignment = <4 2 4 2 20 20>; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi index e140074465ef..8739e8f22549 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi @@ -77,6 +77,9 @@ qcom,tsens-name = "tsens_tz_sensor12"; + /* Quirks */ + qcom,gpu-quirk-lmloadkill-disable; + clocks = <&clock_gfx clk_gpucc_gfx3d_clk>, <&clock_gcc clk_gcc_gpu_cfg_ahb_clk>, <&clock_gpu clk_gpucc_rbbmtimer_clk>, @@ -119,6 +122,40 @@ vddcx-supply = <&gdsc_gpu_cx>; vdd-supply = <&gdsc_gpu_gx>; + /* GPU Mempools */ + qcom,gpu-mempools { + #address-cells= <1>; + #size-cells = <0>; + compatible = "qcom,gpu-mempools"; + + /* 4K Page Pool configuration */ + qcom,gpu-mempool@0 { + reg = <0>; + qcom,mempool-page-size = <4096>; + qcom,mempool-reserved = <2048>; + qcom,mempool-allocate; + }; + /* 8K Page Pool configuration */ + qcom,gpu-mempool@1 { + reg = <1>; + qcom,mempool-page-size = <8192>; + qcom,mempool-reserved = <1024>; + qcom,mempool-allocate; + }; + /* 64K Page Pool configuration */ + qcom,gpu-mempool@2 { + reg = <2>; + qcom,mempool-page-size = <65536>; + qcom,mempool-reserved = <256>; + }; + /* 1M Page Pool configuration */ + qcom,gpu-mempool@3 { + reg = <3>; + qcom,mempool-page-size = <1048576>; + qcom,mempool-reserved = <32>; + }; + }; + /* Power levels */ qcom,gpu-pwrlevels { #address-cells = <1>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi index 32f616e1dc7a..ffb42576ffd3 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi @@ -3088,3 +3088,48 @@ #include "msmcobalt-mdss-pll.dtsi" #include "msmcobalt-blsp.dtsi" #include "msmcobalt-audio.dtsi" + + +/* GPU overrides */ +&msm_gpu { + qcom,initial-pwrlevel = <0>; + + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qcom,gpu-pwrlevels"; + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <332000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <6>; + qcom,bus-max = <8>; + }; + + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <251000000>; + qcom,bus-freq = <4>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <171000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <27000000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; + +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi index 9c72ebf4a0bd..75c985189842 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi @@ -468,9 +468,10 @@ reg = <0xc990000 0xa84>, <0xc011000 0x910>, <0x1fcb200 0x050>, + <0xc8c2200 0x1a0>, <0x780000 0x621c>, <0xc9e1000 0x02c>; - reg-names = "dp_ctrl", "dp_phy", "tcsr_regs", + reg-names = "dp_ctrl", "dp_phy", "tcsr_regs", "dp_mmss_cc", "qfprom_physical","hdcp_physical"; clocks = <&clock_mmss clk_mmss_mnoc_ahb_clk>, diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi index 81f53f1512fd..0cd6d0ab1f1d 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi @@ -18,11 +18,11 @@ compatible = "qca,wcn3990"; qca,bt-vdd-io-supply = <&pmcobalt_s3>; qca,bt-vdd-xtal-supply = <&pmcobalt_s5>; - qca,bt-vdd-core-supply = <&pmcobalt_l7_pin_ctrl>; - qca,bt-vdd-pa-supply = <&pmcobalt_l17_pin_ctrl>; - qca,bt-vdd-ldo-supply = <&pmcobalt_l25_pin_ctrl>; + qca,bt-vdd-core-supply = <&pmcobalt_l7>; + qca,bt-vdd-pa-supply = <&pmcobalt_l17>; + qca,bt-vdd-ldo-supply = <&pmcobalt_l25>; qca,bt-chip-pwd-supply = <&pmicobalt_bob_pin1>; - clocks = <&clock_gcc clk_rf_clk2>; + clocks = <&clock_gcc clk_rf_clk2_pin>; clock-names = "rf_clk2"; qca,bt-vdd-io-voltage-level = <1352000 1352000>; @@ -269,7 +269,7 @@ batt_i@3 { reg = <3>; qcom,channel = <3>; - qcom,scale = <20000000>; + qcom,scale = <(-20000000)>; }; batt_v@4 { @@ -362,7 +362,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &pmicobalt_wled { @@ -469,6 +469,10 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; }; +&mem_client_3_size { + qcom,peripheral-size = <0x500000>; +}; + &pmicobalt_haptics { status = "okay"; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dts b/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dts index b5a94de9aab7..88a5e945436c 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dts +++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dts @@ -15,7 +15,6 @@ #include "msmcobalt.dtsi" #include "msmcobalt-qrd-skuk.dtsi" -#include "msmcobalt-camera-sensor-skuk.dtsi" / { model = "Qualcomm Technologies, Inc. MSM COBALT SKUK"; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi index 58471f6d0fd1..15756d13d2e0 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi @@ -13,6 +13,7 @@ #include <dt-bindings/interrupt-controller/irq.h> #include "msmcobalt-pinctrl.dtsi" #include "msmcobalt-audio.dtsi" +#include "msmcobalt-camera-sensor-skuk.dtsi" &blsp1_uart3_hs { status = "ok"; @@ -184,7 +185,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &dsi_dual_jdi_a407_cmd { @@ -193,3 +194,19 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; }; + +/{ + qrd_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <15>; + + #include "batterydata-qrd-skuk-4v4-3000mah.dtsi" + }; +}; + +&pmicobalt_fg { + qcom,battery-data = <&qrd_batterydata>; +}; + +&pmicobalt_haptics { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi index f0607ac3a34a..71fd5cc1383f 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi @@ -12,6 +12,7 @@ #include <dt-bindings/interrupt-controller/irq.h> #include "msmcobalt-pinctrl.dtsi" +#include "msmcobalt-camera-sensor-qrd-vr1.dtsi" &blsp1_uart3_hs { status = "ok"; @@ -127,3 +128,19 @@ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft"; }; }; + +/{ + qrd_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <15>; + + #include "batterydata-qrd-skuk-4v4-3000mah.dtsi" + }; +}; + +&pmicobalt_fg { + qcom,battery-data = <&qrd_batterydata>; +}; + +&pmicobalt_haptics { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi index 682ea8a260ef..6483453ec5fa 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi @@ -260,7 +260,7 @@ &labibb { status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + qcom,qpnp-labibb-mode = "lcd"; }; &pmicobalt_wled { diff --git a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi index bb72cf3a0d2c..32cf1663cf43 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi @@ -590,8 +590,9 @@ qcom,cpr-idle-cycles = <15>; qcom,cpr-up-down-delay-time = <3000>; qcom,cpr-step-quot-init-min = <11>; - qcom,cpr-step-quot-init-max = <13>; + qcom,cpr-step-quot-init-max = <12>; qcom,cpr-count-mode = <0>; /* All at once */ + qcom,cpr-count-repeat = <1>; qcom,cpr-down-error-step-limit = <1>; qcom,cpr-up-error-step-limit = <1>; qcom,cpr-corner-switch-delay-time = <209>; @@ -618,7 +619,7 @@ thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <0>; - qcom,cpr-consecutive-down = <0>; + qcom,cpr-consecutive-down = <2>; qcom,cpr-up-threshold = <2>; qcom,cpr-down-threshold = <2>; @@ -740,7 +741,7 @@ qcom,cpr-aging-max-voltage-adjustment = <15000>; qcom,cpr-aging-ref-corner = <22>; - qcom,cpr-aging-ro-scaling-factor = <2950>; + qcom,cpr-aging-ro-scaling-factor = <1620>; qcom,allow-aging-voltage-adjustment = <0>; qcom,allow-aging-open-loop-voltage-adjustment = <1>; @@ -761,9 +762,10 @@ qcom,cpr-loop-time = <5000000>; qcom,cpr-idle-cycles = <15>; qcom,cpr-up-down-delay-time = <3000>; - qcom,cpr-step-quot-init-min = <11>; - qcom,cpr-step-quot-init-max = <13>; + qcom,cpr-step-quot-init-min = <9>; + qcom,cpr-step-quot-init-max = <14>; qcom,cpr-count-mode = <0>; /* All at once */ + qcom,cpr-count-repeat = <1>; qcom,cpr-down-error-step-limit = <1>; qcom,cpr-up-error-step-limit = <1>; qcom,cpr-corner-switch-delay-time = <209>; @@ -790,7 +792,7 @@ thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <0>; - qcom,cpr-consecutive-down = <0>; + qcom,cpr-consecutive-down = <2>; qcom,cpr-up-threshold = <2>; qcom,cpr-down-threshold = <2>; @@ -932,7 +934,7 @@ qcom,cpr-aging-max-voltage-adjustment = <15000>; qcom,cpr-aging-ref-corner = <25>; - qcom,cpr-aging-ro-scaling-factor = <2950>; + qcom,cpr-aging-ro-scaling-factor = <1700>; qcom,allow-aging-voltage-adjustment = <0>; qcom,allow-aging-open-loop-voltage-adjustment = <1>; @@ -959,6 +961,7 @@ qcom,cpr-step-quot-init-min = <8>; qcom,cpr-step-quot-init-max = <12>; qcom,cpr-count-mode = <0>; /* All-at-once min */ + qcom,cpr-count-repeat = <1>; vdd-supply = <&pm8005_s1>; qcom,voltage-step = <4000>; @@ -1098,6 +1101,8 @@ qcom,cpr-aging-ref-corner = <6>; qcom,cpr-aging-ro-scaling-factor = <2950>; qcom,allow-aging-voltage-adjustment = <0>; + qcom,allow-aging-open-loop-voltage-adjustment = + <1>; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi index 02cc86212301..46ed1f219970 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi @@ -750,7 +750,7 @@ &msm_gpu { /* Updated chip ID */ qcom,chipid = <0x05040001>; - qcom,initial-pwrlevel = <5>; + qcom,initial-pwrlevel = <0>; qcom,gpu-pwrlevels { #address-cells = <1>; @@ -760,61 +760,29 @@ qcom,gpu-pwrlevel@0 { reg = <0>; - qcom,gpu-freq = <670000000>; - qcom,bus-freq = <12>; - qcom,bus-min = <11>; - qcom,bus-max = <12>; - }; - - qcom,gpu-pwrlevel@1 { - reg = <1>; - qcom,gpu-freq = <596000000>; - qcom,bus-freq = <11>; - qcom,bus-min = <9>; - qcom,bus-max = <12>; - }; - - qcom,gpu-pwrlevel@2 { - reg = <2>; - qcom,gpu-freq = <515000000>; - qcom,bus-freq = <11>; - qcom,bus-min = <9>; - qcom,bus-max = <12>; - }; - - qcom,gpu-pwrlevel@3 { - reg = <3>; - qcom,gpu-freq = <414000000>; - qcom,bus-freq = <9>; - qcom,bus-min = <8>; - qcom,bus-max = <11>; - }; - - qcom,gpu-pwrlevel@4 { - reg = <4>; qcom,gpu-freq = <342000000>; qcom,bus-freq = <8>; qcom,bus-min = <5>; qcom,bus-max = <9>; }; - qcom,gpu-pwrlevel@5 { - reg = <5>; + qcom,gpu-pwrlevel@1 { + reg = <1>; qcom,gpu-freq = <257000000>; qcom,bus-freq = <5>; qcom,bus-min = <3>; qcom,bus-max = <8>; }; - qcom,gpu-pwrlevel@6 { - reg = <6>; + qcom,gpu-pwrlevel@2 { + reg = <2>; qcom,gpu-freq = <180000000>; qcom,bus-freq = <3>; qcom,bus-min = <1>; qcom,bus-max = <5>; }; - qcom,gpu-pwrlevel@7 { - reg = <7>; + qcom,gpu-pwrlevel@3 { + reg = <3>; qcom,gpu-freq = <27000000>; qcom,bus-freq = <0>; qcom,bus-min = <0>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2-qrd-skuk.dts b/arch/arm/boot/dts/qcom/msmcobalt-v2-qrd-skuk.dts index 78e810b816c9..581e9fef1aeb 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2-qrd-skuk.dts +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2-qrd-skuk.dts @@ -19,5 +19,5 @@ / { model = "Qualcomm Technologies, Inc. MSM COBALT V2 SKUK"; compatible = "qcom,msmcobalt-qrd", "qcom,msmcobalt", "qcom,qrd"; - qcom,board-id = <0x01000b 0x80>; + qcom,board-id = <0x01000b 0x10>; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts new file mode 100644 index 000000000000..e5ad123f52a7 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts @@ -0,0 +1,214 @@ +/* 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. + */ + + +/dts-v1/; + +#include "msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi" + +/ { + model = + "Qualcomm Technologies, Inc. MSM COBALT v2.1 MSM FALCON Interposer QRD"; + compatible = "qcom,msmcobalt-qrd", "qcom,msmcobalt", "qcom,qrd"; + qcom,board-id = <0x03000b 0x80>; +}; + +&slim_aud { + tasha_codec { + /delete-property/cdc-vdd-buck-supply; + /delete-property/cdc-buck-sido-supply; + /delete-property/cdc-vdd-tx-h-supply; + /delete-property/cdc-vdd-rx-h-supply; + /delete-property/cdc-vddpx-1-supply; + }; + + tavil_codec { + /delete-property/cdc-vdd-buck-supply; + /delete-property/cdc-buck-sido-supply; + /delete-property/cdc-vdd-tx-h-supply; + /delete-property/cdc-vdd-rx-h-supply; + /delete-property/cdc-vddpx-1-supply; + }; +}; + +&clock_gcc { + /delete-property/vdd_dig-supply; + /delete-property/vdd_dig_ao-supply; +}; + +&clock_mmss { + /delete-property/vdd_dig-supply; + /delete-property/vdd_mmsscc_mx-supply; +}; + +&clock_gpu { + /delete-property/vdd_dig-supply; +}; + +&clock_gfx { + /delete-property/vdd_mx-supply; + /delete-property/vdd_gpu_mx-supply; +}; + +&pcie0 { + /delete-property/vreg-1.8-supply; + /delete-property/vreg-0.9-supply; + /delete-property/vreg-cx-supply; +}; + +&qusb_phy0 { + /delete-property/vdd-supply; + /delete-property/vdda18-supply; + /delete-property/vdda33-supply; +}; + +&ssphy { + /delete-property/vdd-supply; + /delete-property/core-supply; +}; + +&usb3 { + /delete-property/extcon; +}; + +&mdss_dsi { + /delete-property/vdda-1p2-supply; + /delete-property/vdda-0p9-supply; +}; + +&mdss_dsi0 { + /delete-property/wqhd-vddio-supply; + /delete-property/lab-supply; + /delete-property/ibb-supply; +}; + +&mdss_dsi1 { + /delete-property/wqhd-vddio-supply; + /delete-property/lab-supply; + /delete-property/ibb-supply; +}; + +&mdss_hdmi_pll { + /delete-property/vdda-pll-supply; + /delete-property/vdda-phy-supply; +}; + +&mdss_dp_ctrl { + /delete-property/vdda-1p2-supply; + /delete-property/vdda-0p9-supply; + /delete-property/qcom,dp-usbpd-detection; +}; + +&apc0_cpr { + /* disable aging and closed-loop */ + /delete-property/vdd-supply; + /delete-property/qcom,cpr-enable; + /delete-property/qcom,cpr-hw-closed-loop; + /delete-property/qcom,cpr-aging-ref-voltage; +}; + +&apc0_pwrcl_vreg { + /delete-property/qcom,cpr-aging-max-voltage-adjustment; + /delete-property/qcom,cpr-aging-ref-corner; + /delete-property/qcom,cpr-aging-ro-scaling-factor; + /delete-property/qcom,allow-aging-voltage-adjustment; + /delete-property/qcom,allow-aging-open-loop-voltage-adjustment; +}; + +&apc1_cpr { + /* disable aging and closed-loop */ + /delete-property/vdd-supply; + /delete-property/qcom,cpr-enable; + /delete-property/qcom,cpr-hw-closed-loop; + /delete-property/qcom,cpr-aging-ref-voltage; +}; + +&apc1_perfcl_vreg { + /delete-property/qcom,cpr-aging-max-voltage-adjustment; + /delete-property/qcom,cpr-aging-ref-corner; + /delete-property/qcom,cpr-aging-ro-scaling-factor; + /delete-property/qcom,allow-aging-voltage-adjustment; + /delete-property/qcom,allow-aging-open-loop-voltage-adjustment; +}; + +&gfx_cpr { + reg = <0x05061000 0x4000>, + <0x00784000 0x1000>; + reg-names = "cpr_ctrl", "fuse_base"; + + /* disable aging and closed-loop */ + /delete-property/vdd-supply; + /delete-property/qcom,cpr-enable; + /delete-property/qcom,cpr-aging-ref-voltage; + /delete-property/qcom,cpr-aging-allowed-reg-mask; + /delete-property/qcom,cpr-aging-allowed-reg-value; +}; + +&gfx_vreg { + /delete-property/qcom,cpr-aging-max-voltage-adjustment; + /delete-property/qcom,cpr-aging-ref-corner; + /delete-property/qcom,cpr-aging-ro-scaling-factor; + /delete-property/qcom,allow-aging-voltage-adjustment; + /delete-property/qcom,allow-aging-open-loop-voltage-adjustment; +}; + +&clock_audio { + /delete-property/qcom,audio-ref-clk-gpio; +}; + +&soc { + /delete-node/qcom,csid@ca30000; + /delete-node/qcom,csid@ca30400; + /delete-node/qcom,csid@ca30800; + /delete-node/qcom,csid@ca30c00; + + /delete-node/qcom,lpass@17300000; + /delete-node/qcom,mss@4080000; + /delete-node/qcom,spss@1d00000; + /delete-node/qcom,bcl; + /delete-node/qcom,msm-thermal; + /delete-node/qcom,ssc@5c00000; + /delete-node/qcom,icnss@18800000; + /delete-node/qcom,wil6210; + /delete-node/qcom,rpm-smd; + /delete-node/qcom,spmi@800f000; + + + rpm_bus: qcom,rpm-smd { + compatible = "qcom,rpm-glink"; + qcom,glink-edge = "rpm"; + rpm-channel-name = "rpm_requests"; + }; + + spmi_bus: qcom,spmi@800f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x800f000 0x1000>, + <0x8400000 0x1000000>, + <0x9400000 0x1000000>, + <0xa400000 0x220000>, + <0x800a000 0x3000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + cell-index = <0>; + }; +}; + +#include "msm-pmfalcon.dtsi" +#include "msm-pm2falcon.dtsi" +#include "msmfalcon-regulator.dtsi" diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi new file mode 100644 index 000000000000..b257281466a9 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi @@ -0,0 +1,85 @@ +/* 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 <dt-bindings/interrupt-controller/irq.h> +#include "msmcobalt-v2.1-interposer-msmfalcon.dtsi" + +&uartblsp2dm1 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_console_active>; +}; + +&ufsphy1 { + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14600>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-max-microamp = <750000>; + vccq-max-microamp = <560000>; + vccq2-max-microamp = <750000>; + status = "ok"; +}; + +&ufs_ice { + status = "ok"; +}; + +&sdc2_cd_on { + mux { + pins = "gpio54"; + }; + + config { + pins = "gpio54"; + /delete-property/ bias-pull-up; + bias-disable; + }; +}; + +&sdc2_cd_off { + mux { + pins = "gpio54"; + }; + + config { + pins = "gpio54"; + /delete-property/ bias-pull-up; + bias-disable; + }; +}; + +&sdhc_2 { + qcom,vdd-voltage-level = <2950000 2960000>; + qcom,vdd-current-level = <200 800000>; + + qcom,vdd-io-voltage-level = <1808000 2960000>; + qcom,vdd-io-current-level = <200 22000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + + qcom,clk-rates = <400000 20000000 25000000 + 50000000 100000000 200000000>; + qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104"; + + cd-gpios = <&tlmm 54 0x0>; + + status = "ok"; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi index beecee843778..93b586df5640 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi @@ -26,6 +26,25 @@ &clock_cpu { compatible = "qcom,cpu-clock-osm-msmcobalt-v2"; + reg = <0x179c0000 0x4000>, + <0x17916000 0x1000>, + <0x17816000 0x1000>, + <0x179d1000 0x1000>, + <0x17914800 0x800>, + <0x17814800 0x800>, + <0x00784130 0x8>, + <0x1791101c 0x8>; + reg-names = "osm", "pwrcl_pll", "perfcl_pll", + "apcs_common", "pwrcl_acd", "perfcl_acd", + "perfcl_efuse", "debug"; + + qcom,acdtd-val = <0x00009611 0x00009611>; + qcom,acdcr-val = <0x002b5ffd 0x002b5ffd>; + qcom,acdsscr-val = <0x00000501 0x00000501>; + qcom,acdextint0-val = <0x2cf9ae8 0x2cf9ae8>; + qcom,acdextint1-val = <0x2cf9afc 0x2cf9afc>; + qcom,acdautoxfer-val = <0x00000015 0x00000015>; + /delete-property/ qcom,llm-sw-overr; qcom,pwrcl-speedbin0-v0 = < 300000000 0x0004000f 0x01200020 0x1 1 >, @@ -186,6 +205,24 @@ }; }; +&devfreq_memlat_0 { + qcom,core-dev-table = + < 595200 3143 >, + < 1324800 4173 >, + < 1555200 5859 >, + < 1747200 5859 >, + < 1900800 7759 >; +}; + +&devfreq_memlat_4 { + qcom,core-dev-table = + < 576000 3143 >, + < 1132800 4173 >, + < 1344000 5859 >, + < 1728000 7759 >, + < 1958400 11863 >, + < 2208000 13763 >; +}; &clock_gcc { compatible = "qcom,gcc-cobalt-v2"; }; @@ -208,7 +245,8 @@ < 414000000 4 RPM_SMD_REGULATOR_LEVEL_SVS >, < 515000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >, < 596000000 6 RPM_SMD_REGULATOR_LEVEL_NOM >, - < 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >; + < 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >, + < 710000000 8 RPM_SMD_REGULATOR_LEVEL_TURBO >; qcom,gfxfreq-mx-speedbin0 = < 0 0 >, < 180000000 RPM_SMD_REGULATOR_LEVEL_SVS >, @@ -217,7 +255,8 @@ < 414000000 RPM_SMD_REGULATOR_LEVEL_SVS >, < 515000000 RPM_SMD_REGULATOR_LEVEL_NOM >, < 596000000 RPM_SMD_REGULATOR_LEVEL_NOM >, - < 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >; + < 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >, + < 710000000 RPM_SMD_REGULATOR_LEVEL_TURBO >; }; &mdss_mdp { @@ -419,51 +458,53 @@ qcom,cpr-open-loop-voltage-fuse-adjustment = /* Speed bin 0 */ - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, /* Speed bin 1 */ - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>; + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>; qcom,cpr-closed-loop-voltage-fuse-adjustment = /* Speed bin 0 */ - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, /* Speed bin 1 */ - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>; + <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; qcom,cpr-scaled-open-loop-voltage-as-ceiling; qcom,cpr-aging-ref-corner = <22 22>; - qcom,cpr-aging-ro-scaling-factor = <2950>; - qcom,allow-aging-voltage-adjustment = <0>; + qcom,cpr-aging-ro-scaling-factor = <1620>; + qcom,allow-aging-voltage-adjustment = + <0 0 0 0 1 1 1 1>, + <0 0 0 0 1 1 1 1>; }; &apc1_cpr { @@ -580,51 +621,53 @@ qcom,cpr-open-loop-voltage-fuse-adjustment = /* Speed bin 0 */ - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + <(-7000) (-15000) (-15000) 37000>, + <(-7000) (-15000) (-15000) 37000>, + <(-7000) (-15000) (-15000) 37000>, + <(-7000) (-15000) (-15000) 37000>, /* Speed bin 1 */ - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>; + < 8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + <(-7000) (-15000) (-15000) 37000>, + <(-7000) (-15000) (-15000) 37000>, + <(-7000) (-15000) (-15000) 37000>, + <(-7000) (-15000) (-15000) 37000>; qcom,cpr-closed-loop-voltage-fuse-adjustment = /* Speed bin 0 */ - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + <(-15000) (-15000) (-15000) 35000>, + <(-15000) (-15000) (-15000) 35000>, + <(-15000) (-15000) (-15000) 35000>, + <(-15000) (-15000) (-15000) 35000>, /* Speed bin 1 */ - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>; + < 0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + <(-15000) (-15000) (-15000) 35000>, + <(-15000) (-15000) (-15000) 35000>, + <(-15000) (-15000) (-15000) 35000>, + <(-15000) (-15000) (-15000) 35000>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; qcom,cpr-scaled-open-loop-voltage-as-ceiling; qcom,cpr-aging-ref-corner = <30 26>; - qcom,cpr-aging-ro-scaling-factor = <2950>; - qcom,allow-aging-voltage-adjustment = <0>; + qcom,cpr-aging-ro-scaling-factor = <1700>; + qcom,allow-aging-voltage-adjustment = + <0 0 0 0 1 1 1 1>, + <0 0 0 0 1 1 1 1>; }; &pm8005_s1 { @@ -648,14 +691,14 @@ qcom,cpr-corner-fmax-map = <1 3 5 8>; qcom,cpr-voltage-ceiling = - <656000 716000 772000 880000 908000 948000 1016000 1088000>, - <660000 724000 772000 832000 916000 968000 1024000 1024000>, - <660000 724000 772000 832000 916000 968000 1024000 1024000>, - <660000 724000 772000 832000 916000 968000 1024000 1024000>, - <660000 724000 772000 832000 916000 968000 1024000 1024000>, - <660000 724000 772000 832000 916000 968000 1024000 1024000>, - <660000 724000 772000 832000 916000 968000 1024000 1024000>, - <660000 724000 772000 832000 916000 968000 1024000 1024000>; + <716000 716000 772000 880000 908000 948000 1016000 1088000>, + <724000 724000 772000 832000 916000 968000 1024000 1024000>, + <724000 724000 772000 832000 916000 968000 1024000 1024000>, + <724000 724000 772000 832000 916000 968000 1024000 1024000>, + <724000 724000 772000 832000 916000 968000 1024000 1024000>, + <724000 724000 772000 832000 916000 968000 1024000 1024000>, + <724000 724000 772000 832000 916000 968000 1024000 1024000>, + <724000 724000 772000 832000 916000 968000 1024000 1024000>; qcom,cpr-voltage-floor = <516000 516000 532000 584000 632000 672000 712000 756000>; @@ -703,46 +746,46 @@ 0 0 2168 0 2209 1849 1997 0>; qcom,cpr-open-loop-voltage-fuse-adjustment = - < 100000 0 0 0>, - < 100000 0 0 0>, - < 85000 (-15000) (-15000) (-15000)>, - < 85000 (-15000) (-15000) (-15000)>, - < 85000 (-15000) (-15000) (-15000)>, - < 85000 (-15000) (-15000) (-15000)>, - < 85000 (-15000) (-15000) (-15000)>, - < 85000 (-15000) (-15000) (-15000)>; + < 60000 0 0 0>, + < 60000 0 0 0>, + < 60000 0 0 0>, + < 45000 (-15000) (-15000) (-15000)>, + < 45000 (-15000) (-15000) (-15000)>, + < 45000 (-15000) (-15000) (-15000)>, + < 45000 (-15000) (-15000) (-15000)>, + < 45000 (-15000) (-15000) (-15000)>; qcom,cpr-closed-loop-voltage-adjustment = - < 96000 18000 4000 0 - 0 13000 9000 0>, - < 96000 18000 4000 0 - 0 13000 9000 0>, - < 81000 3000 (-11000) (-15000) - (-15000) (-2000) (-6000) (-15000)>, - < 81000 3000 (-11000) (-15000) - (-15000) (-2000) (-6000) (-15000)>, - < 81000 3000 (-11000) (-15000) - (-15000) (-2000) (-6000) (-15000)>, - < 81000 3000 (-11000) (-15000) - (-15000) (-2000) (-6000) (-15000)>, - < 81000 3000 (-11000) (-15000) - (-15000) (-2000) (-6000) (-15000)>, - < 81000 3000 (-11000) (-15000) - (-15000) (-2000) (-6000) (-15000)>; + < 90000 38000 28000 8000 + 0 29000 11000 0>, + < 90000 38000 28000 8000 + 0 29000 11000 0>, + < 90000 38000 28000 8000 + 0 29000 11000 0>, + < 75000 23000 13000 (-7000) + (-15000) 14000 (-4000) (-15000)>, + < 75000 23000 13000 (-7000) + (-15000) 14000 (-4000) (-15000)>, + < 75000 23000 13000 (-7000) + (-15000) 14000 (-4000) (-15000)>, + < 75000 23000 13000 (-7000) + (-15000) 14000 (-4000) (-15000)>, + < 75000 23000 13000 (-7000) + (-15000) 14000 (-4000) (-15000)>; qcom,cpr-floor-to-ceiling-max-range = <50000 50000 50000 50000 50000 50000 70000 70000>; qcom,cpr-fused-closed-loop-voltage-adjustment-map = - <0 0 1 2 3 0 0 4>; + <0 0 0 0 1 2 3 4>; qcom,allow-voltage-interpolation; qcom,cpr-scaled-open-loop-voltage-as-ceiling; qcom,cpr-aging-max-voltage-adjustment = <15000>; qcom,cpr-aging-ref-corner = <8>; - qcom,cpr-aging-ro-scaling-factor = <2950>; - qcom,allow-aging-voltage-adjustment = <0 0 1 1 1 1 1 1>; + qcom,cpr-aging-ro-scaling-factor = <1620>; + qcom,allow-aging-voltage-adjustment = <0 0 0 1 1 1 1 1>; }; &qusb_phy0 { @@ -886,13 +929,6 @@ qcom,gpu-pwrlevel@6 { reg = <6>; - qcom,gpu-freq = <180000000>; - qcom,bus-freq = <3>; - qcom,bus-min = <1>; - qcom,bus-max = <5>; - }; - qcom,gpu-pwrlevel@7 { - reg = <7>; qcom,gpu-freq = <27000000>; qcom,bus-freq = <0>; qcom,bus-min = <0>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi index f17be7570742..a8655c2e88a0 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi @@ -25,6 +25,7 @@ qcom,firmware-name = "venus"; qcom,never-unload-fw; qcom,sw-power-collapse; + qcom,max-secure-instances = <5>; qcom,debug-timeout; qcom,reg-presets = <0x80124 0x00000003>, diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi index 3ad4b6b5622d..9b0d3f674032 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi @@ -611,7 +611,7 @@ < 13763 /* 1804 MHz */ >; }; - qcom,arm-memlat-mon-0 { + devfreq_memlat_0: qcom,arm-memlat-mon-0 { compatible = "qcom,arm-memlat-mon"; qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>; qcom,target-dev = <&memlat_cpu0>; @@ -622,7 +622,7 @@ < 1881600 5859 >; }; - qcom,arm-memlat-mon-4 { + devfreq_memlat_4: qcom,arm-memlat-mon-4 { compatible = "qcom,arm-memlat-mon"; qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>; qcom,target-dev = <&memlat_cpu4>; @@ -1568,6 +1568,10 @@ qcom,vreg-cx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_BINNING RPM_SMD_REGULATOR_LEVEL_SVS 0>; + qcom,l1-supported; + qcom,l1ss-supported; + qcom,aux-clk-sync; + qcom,ep-latency = <10>; qcom,ep-wakeirq; @@ -1887,6 +1891,7 @@ usb-phy = <&qusb_phy0>, <&ssphy>; tx-fifo-resize; snps,nominal-elastic-buffer; + snps,disable-clk-gating; snps,hird_thresh = <0x10>; snps,num-gsi-evt-buffs = <0x3>; }; @@ -2157,6 +2162,32 @@ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>; }; + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x300000>; + qcom,client-id = <2>; + label = "modem"; + }; + + mem_client_3_size: qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + label = "modem"; + }; + }; + pil_modem: qcom,mss@4080000 { compatible = "qcom,pil-q6v55-mss"; reg = <0x4080000 0x100>, @@ -3117,5 +3148,6 @@ #include "msm-audio-lpass.dtsi" #include "msmcobalt-mdss.dtsi" #include "msmcobalt-mdss-pll.dtsi" +#include "msm-rdbg.dtsi" #include "msmcobalt-blsp.dtsi" #include "msmcobalt-audio.dtsi" diff --git a/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi index 124ab341ba6b..cfe968a7310a 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi @@ -10,351 +10,438 @@ * GNU General Public License for more details. */ -/* Stub regulators */ - -/ { - /* PMFALCON S1 - VDD_APC0 supply */ - pmfalcon_s1a: regulator-pmfalcon-s1a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s1a"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <565000>; - regulator-max-microvolt = <1170000>; - }; - - /* PMFALCON S2 + S3 = VDD_APC1 supply */ - pmfalcon_s2a: regulator-pmfalcon-s2a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s2a"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <565000>; - regulator-max-microvolt = <1170000>; - }; - - pmfalcon_s4a: regulator-pmfalcon-s4a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s4a"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <1805000>; - regulator-max-microvolt = <2040000>; - }; - - pmfalcon_s5a: regulator-pmfalcon-s5a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s5a"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <1350000>; - regulator-max-microvolt = <1350000>; - }; - - pmfalcon_s6a: regulator-pmfalcon-s6a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s6a"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <504000>; - regulator-max-microvolt = <992000>; - }; - - pmfalcon_s1b: regulator-pmfalcon-s1b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s1b"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <1125000>; - regulator-max-microvolt = <1125000>; - }; - - pmfalcon_s2b: regulator-pmfalcon-s2b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s2b"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <1050000>; - regulator-max-microvolt = <1050000>; - }; - - /* PMFALCON S3 + S4 - VDD_CX supply */ - pmfalcon_s3b_level: regulator-pmfalcon-s3b-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s3b_level"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - pmfalcon_s3b_floor_level: regulator-pmfalcon-s3b-floor-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s3b_floor_level"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - pmfalcon_s3b_level_ao: regulator-pmfalcon-s3b-level-ao { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s3b_level_ao"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - /* PMFALCON S5 - VDD_MX supply */ - pmfalcon_s5b_level: regulator-pmfalcon-s5b-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s5b_level"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - pmfalcon_s5b_floor_level: regulator-pmfalcon-s5b-floor-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s5b_floor_level"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - pmfalcon_s5b_level_ao: regulator-pmfalcon-s5b-level-ao { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s5b_level_ao"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - pmfalcon_l1a: regulator-pmfalcon-l1a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l1a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1150000>; - regulator-max-microvolt = <1250000>; - }; - - pmfalcon_l2a: regulator-pmfalcon-l2a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l2a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1010000>; - }; - - pmfalcon_l3a: regulator-pmfalcon-l3a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l3a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1010000>; +&rpm_bus { + rpm-regulator-smpa4 { + status = "okay"; + pmfalcon_s4: regulator-s4 { + regulator-min-microvolt = <1805000>; + regulator-max-microvolt = <2040000>; + status = "okay"; + }; + }; + + rpm-regulator-smpa5 { + status = "okay"; + pmfalcon_s5: regulator-s5 { + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + status = "okay"; + }; + }; + + rpm-regulator-smpa6 { + status = "okay"; + pmfalcon_s6: regulator-s6 { + regulator-min-microvolt = <504000>; + regulator-max-microvolt = <992000>; + status = "okay"; + }; + }; + + rpm-regulator-smpb1 { + status = "okay"; + pm2falcon_s1: regulator-s1 { + regulator-min-microvolt = <1125000>; + regulator-max-microvolt = <1125000>; + status = "okay"; + }; + }; + + rpm-regulator-smpb2 { + status = "okay"; + pm2falcon_s2: regulator-s2 { + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + status = "okay"; + }; + }; + + /* PM2FALCON S3 + S4 - VDD_CX supply */ + rpm-regulator-smpb3 { + status = "okay"; + pm2falcon_s3_level: regulator-s3-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s3_level"; + qcom,set = <3>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-level; + }; + + pm2falcon_s3_floor_level: regulator-s3-floor-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s3_floor_level"; + qcom,set = <3>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-floor-level; + qcom,always-send-voltage; + }; + + pm2falcon_s3_level_ao: regulator-s3-level-ao { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s3_level_ao"; + qcom,set = <1>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-level; + }; + }; + + /* PM2FALCON S5 - VDD_MX supply */ + rpm-regulator-smpb5 { + status = "okay"; + pm2falcon_s5_level: regulator-s5-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s5_level"; + qcom,set = <3>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-level; + }; + + pm2falcon_s5_floor_level: regulator-s5-floor-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s5_floor_level"; + qcom,set = <3>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-floor-level; + qcom,always-send-voltage; + }; + + pm2falcon_s5_level_ao: regulator-s5-level-ao { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s5_level_ao"; + qcom,set = <1>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-level; + }; + }; + + rpm-regulator-ldoa1 { + status = "okay"; + pmfalcon_l1: regulator-l1 { + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1250000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa2 { + status = "okay"; + pmfalcon_l2: regulator-l2 { + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1010000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa3 { + status = "okay"; + pmfalcon_l3: regulator-l3 { + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1010000>; + status = "okay"; + }; }; /* TODO: remove if ADRASTEA CX/MX not voted from APPS */ - pmfalcon_l5a: regulator-pmfalcon-l5a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l5a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <525000>; - regulator-max-microvolt = <950000>; - }; - - pmfalcon_l6a: regulator-pmfalcon-l6a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l6a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1370000>; - }; - - pmfalcon_l7a: regulator-pmfalcon-l7a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l7a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - pmfalcon_l8a: regulator-pmfalcon-l8a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l8a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <1900000>; - }; - - pmfalcon_l9a: regulator-pmfalcon-l9a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l9a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <1900000>; - }; - - pmfalcon_l10a: regulator-pmfalcon-l10a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l10a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1780000>; - regulator-max-microvolt = <1950000>; - }; - - pmfalcon_l11a: regulator-pmfalcon-l11a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l11a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1780000>; - regulator-max-microvolt = <1950000>; - }; - - pmfalcon_l12a: regulator-pmfalcon-l12a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l12a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1780000>; - regulator-max-microvolt = <1950000>; - }; - - pmfalcon_l13a: regulator-pmfalcon-l13a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l13a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <1950000>; - }; - - pmfalcon_l14a: regulator-pmfalcon-l14a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l14a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1710000>; - regulator-max-microvolt = <1900000>; - }; - - pmfalcon_l15a: regulator-pmfalcon-l15a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l15a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1650000>; - regulator-max-microvolt = <2950000>; - }; - - pmfalcon_l17a: regulator-pmfalcon-l17a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l17a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1650000>; - regulator-max-microvolt = <2950000>; - }; - - pmfalcon_l19a: regulator-pmfalcon-l19a { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l19a"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <3200000>; - regulator-max-microvolt = <3400000>; - }; - - pmfalcon_l1b: regulator-pmfalcon-l1b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l1b"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <925000>; - }; - - pmfalcon_l2b: regulator-pmfalcon-l2b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l2b"; - qcom,hpm-min-load = <5000>; - regulator-min-microvolt = <350000>; - regulator-max-microvolt = <3100000>; - }; - - pmfalcon_l3b: regulator-pmfalcon-l3b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l3b"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1710000>; - regulator-max-microvolt = <3600000>; - }; - - pmfalcon_l4b: regulator-pmfalcon-l4b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l4b"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <2950000>; - }; - - pmfalcon_l5b: regulator-pmfalcon-l5b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l5b"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1721000>; - regulator-max-microvolt = <3600000>; - }; - - pmfalcon_l6b: regulator-pmfalcon-l6b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l6b"; - qcom,hpm-min-load = <5000>; - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <3300000>; - }; - - pmfalcon_l7b: regulator-pmfalcon-l7b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l7b"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <3125000>; - }; - - pmfalcon_l8b: regulator-pmfalcon-l8b { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l8b"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <3200000>; - regulator-max-microvolt = <3400000>; - }; - - /* PMFALCON L9 = VDD_SSC_CX supply */ - pmfalcon_l9b_level: regulator-pmfalcon-l9b-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l9b_level"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - pmfalcon_l9b_floor_level: regulator-pmfalcon-l9b-floor-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l9b_floor_level"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - /* PMFALCON L10 = VDD_SSC_MX supply */ - pmfalcon_l10b_level: regulator-pmfalcon-l10b-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l10b_level"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - pmfalcon_l10b_floor_level: regulator-pmfalcon-l10b-floor-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l10b_floor_level"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; - regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - }; - - pmfalcon_bob: regulator-pmfalcon-bob { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_bob"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; + rpm-regulator-ldoa5 { + status = "okay"; + pmfalcon_l5: regulator-l5 { + regulator-min-microvolt = <525000>; + regulator-max-microvolt = <950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa6 { + status = "okay"; + pmfalcon_l6: regulator-l6 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1370000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa7 { + status = "okay"; + pmfalcon_l7: regulator-l7 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa8 { + status = "okay"; + pmfalcon_l8: regulator-l8 { + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1900000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa9 { + status = "okay"; + pmfalcon_l9: regulator-l9 { + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1900000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa10 { + status = "okay"; + pmfalcon_l10: regulator-l10 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa11 { + status = "okay"; + pmfalcon_l11: regulator-l11 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa12 { + status = "okay"; + pmfalcon_l12: regulator-l12 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa13 { + status = "okay"; + pmfalcon_l13: regulator-l13 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa14 { + status = "okay"; + pmfalcon_l14: regulator-l14 { + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <1900000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa15 { + status = "okay"; + pmfalcon_l15: regulator-l15 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa17 { + status = "okay"; + pmfalcon_l17: regulator-l17 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa19 { + status = "okay"; + pmfalcon_l19: regulator-l19 { + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob1 { + status = "okay"; + pm2falcon_l1: regulator-l1 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <925000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob2 { + status = "okay"; + pm2falcon_l2: regulator-l2 { + regulator-min-microvolt = <350000>; + regulator-max-microvolt = <3100000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob3 { + status = "okay"; + pm2falcon_l3: regulator-l3 { + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob4 { + status = "okay"; + pm2falcon_l4: regulator-l4 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob5 { + status = "okay"; + pm2falcon_l5: regulator-l5 { + regulator-min-microvolt = <1721000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob6 { + status = "okay"; + pm2falcon_l6: regulator-l6 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3300000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob7 { + status = "okay"; + pm2falcon_l7: regulator-l7 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3125000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob8 { + status = "okay"; + pm2falcon_l8: regulator-l8 { + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + status = "okay"; + }; + }; + + /* PM2FALCON L9 = VDD_SSC_CX supply */ + rpm-regulator-ldob9 { + status = "okay"; + pm2falcon_l9_level: regulator-l9-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l9_level"; + qcom,set = <3>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-level; + }; + + pm2falcon_l9_floor_level: regulator-l9-floor-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l9_floor_level"; + qcom,set = <3>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-floor-level; + qcom,always-send-voltage; + }; + }; + + /* PM2FALCON L10 = VDD_SSC_MX supply */ + rpm-regulator-ldob10 { + status = "okay"; + pm2falcon_l10_level: regulator-l10-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l10_level"; + qcom,set = <3>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-level; + }; + + pm2falcon_l10_floor_level: regulator-l10-floor-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l10_floor_level"; + qcom,set = <3>; + regulator-min-microvolt = + <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = + <RPM_SMD_REGULATOR_LEVEL_TURBO>; + qcom,use-voltage-floor-level; + qcom,always-send-voltage; + }; + }; + + rpm-regulator-bobb { + status = "okay"; + pm2falcon_bob: regulator-bob { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; + + pm2falcon_bob_pin1: regulator-bob-pin1 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_bob_pin1"; + qcom,set = <3>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + qcom,use-pin-ctrl-voltage1; + }; + + pm2falcon_bob_pin2: regulator-bob-pin2 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_bob_pin2"; + qcom,set = <3>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + qcom,use-pin-ctrl-voltage2; + }; + + pm2falcon_bob_pin3: regulator-bob-pin3 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_bob_pin3"; + qcom,set = <3>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + qcom,use-pin-ctrl-voltage3; + }; }; +}; +/* Stub regulators */ +/ { /* GFX Supply */ gfx_vreg_corner: regulator-gfx-corner { compatible = "qcom,stub-regulator"; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts index f0ba8b115120..c94ba0df3e6e 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts +++ b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts @@ -20,6 +20,10 @@ model = "Qualcomm Technologies, Inc. MSM FALCON RUMI"; compatible = "qcom,msmfalcon-rumi", "qcom,msmfalcon", "qcom,rumi"; qcom,board-id = <15 0>; + + chosen { + bootargs = "lpm_levels.sleep_disabled=1"; + }; }; &uartblsp1dm1 { @@ -30,12 +34,12 @@ &sdhc_1 { /* device core power supply */ - vdd-supply = <&pmfalcon_l4b>; + vdd-supply = <&pm2falcon_l4>; qcom,vdd-voltage-level = <2950000 2950000>; qcom,vdd-current-level = <200 570000>; /* device communication power supply */ - vdd-io-supply = <&pmfalcon_l8a>; + vdd-io-supply = <&pmfalcon_l8>; qcom,vdd-io-always-on; qcom,vdd-io-lpm-sup; qcom,vdd-io-voltage-level = <1800000 1800000>; @@ -53,3 +57,8 @@ status = "ok"; }; + +&clock_gcc { + compatible = "qcom,dummycc"; + clock-output-names = "gcc_clocks"; +}; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts index 085419b7e108..00d97c8fdd32 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts +++ b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts @@ -20,6 +20,10 @@ model = "Qualcomm Technologies, Inc. MSM FALCON SIM"; compatible = "qcom,msmfalcon-sim", "qcom,msmfalcon", "qcom,sim"; qcom,board-id = <16 0>; + + chosen { + bootargs = "lpm_levels.sleep_disabled=1"; + }; }; &uartblsp1dm1 { @@ -30,12 +34,12 @@ &sdhc_1 { /* device core power supply */ - vdd-supply = <&pmfalcon_l4b>; + vdd-supply = <&pm2falcon_l4>; qcom,vdd-voltage-level = <2950000 2950000>; qcom,vdd-current-level = <200 570000>; /* device communication power supply */ - vdd-io-supply = <&pmfalcon_l8a>; + vdd-io-supply = <&pmfalcon_l8>; qcom,vdd-io-always-on; qcom,vdd-io-lpm-sup; qcom,vdd-io-voltage-level = <1800000 1800000>; diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index f2adc32fb732..473270d6e87d 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -287,6 +287,32 @@ qcom,pipe-attr-ee; }; + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x300000>; + qcom,client-id = <2>; + label = "modem"; + }; + + mem_client_3_size: qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + label = "modem"; + }; + }; + tsens: tsens@10ad000 { compatible = "qcom,msmfalcon-tsens"; reg = <0x10ad000 0x2000>, @@ -319,6 +345,31 @@ clock-names = "core", "iface"; }; + slim_aud: slim@151c0000 { + cell-index = <1>; + compatible = "qcom,slim-ngd"; + reg = <0x151c0000 0x2c000>, + <0x15180000 0x2e000>; + reg-names = "slimbus_physical", "slimbus_bam_physical"; + interrupts = <0 163 0>, <0 164 0>; + interrupt-names = "slimbus_irq", "slimbus_bam_irq"; + qcom,apps-ch-pipes = <0x7e0000>; + qcom,ea-pc = <0x260>; + status = "disabled"; + }; + + slim_qca: slim@15240000 { + cell-index = <3>; + compatible = "qcom,slim-ngd"; + reg = <0x15240000 0x2c000>, + <0x15200000 0x24000>; + reg-names = "slimbus_physical", "slimbus_bam_physical"; + interrupts = <0 291 0>, <0 292 0>; + interrupt-names = "slimbus_irq", "slimbus_bam_irq"; + qcom,apps-ch-pipes = <0x1800>; + status = "disabled"; + }; + timer@17920000 { #address-cells = <1>; #size-cells = <1>; @@ -384,8 +435,10 @@ }; clock_gcc: clock-controller@100000 { - compatible = "qcom,dummycc"; - clock-output-names = "gcc_clocks"; + compatible = "qcom,gcc-msmfalcon"; + reg = <0x100000 0x94000>; + vdd_dig-supply = <&pm2falcon_s3_level>; + vdd_dig_ao-supply = <&pm2falcon_s3_level_ao>; #clock-cells = <1>; #reset-cells = <1>; }; @@ -696,7 +749,7 @@ reg = <0x15700000 0x00100>; interrupts = <0 162 1>; - vdd_cx-supply = <&pmfalcon_s3b_level>; + vdd_cx-supply = <&pm2falcon_s3_level>; qcom,proxy-reg-names = "vdd_cx"; qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>; @@ -728,7 +781,7 @@ reg = <0x1a300000 0x00100>; interrupts = <0 518 1>; - vdd_cx-supply = <&pmfalcon_s3b_level>; + vdd_cx-supply = <&pm2falcon_s3_level>; qcom,proxy-reg-names = "vdd_cx"; qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>; @@ -783,9 +836,9 @@ "mnoc_axi_clk"; interrupts = <0 448 1>; - vdd_cx-supply = <&pmfalcon_s3b_level>; + vdd_cx-supply = <&pm2falcon_s3_level>; vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - vdd_mx-supply = <&pmfalcon_s5b_level>; + vdd_mx-supply = <&pm2falcon_s5_level>; vdd_mx-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>; qcom,firmware-name = "modem"; qcom,pil-self-auth; @@ -807,10 +860,25 @@ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>; status = "ok"; }; + + qcom,msm-imem@146bf000 { + compatible = "qcom,msm-imem"; + reg = <0x146bf000 0x1000>; + ranges = <0x0 0x146bf000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + pil@94c { + compatible = "qcom,msm-imem-pil"; + reg = <0x94c 200>; + }; + }; }; #include "msmfalcon-ion.dtsi" #include "msmfalcon-bus.dtsi" +#include "msm-pmfalcon-rpm-regulator.dtsi" +#include "msm-pm2falcon-rpm-regulator.dtsi" #include "msmfalcon-regulator.dtsi" #include "msm-gdsc-falcon.dtsi" diff --git a/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi new file mode 100644 index 000000000000..323024278406 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi @@ -0,0 +1,365 @@ +/* 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. + */ + +/* Stub regulators */ + +/ { + /* PMFALCON S1 - VDD_APC0 supply */ + pmfalcon_s1: regulator-pmfalcon-s1 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_s1"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <565000>; + regulator-max-microvolt = <1170000>; + }; + + /* PMFALCON S2 + S3 = VDD_APC1 supply */ + pmfalcon_s2: regulator-pmfalcon-s2 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_s2"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <565000>; + regulator-max-microvolt = <1170000>; + }; + + pmfalcon_s4: regulator-pmfalcon-s4 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_s4"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <1805000>; + regulator-max-microvolt = <2040000>; + }; + + pmfalcon_s5: regulator-pmfalcon-s5 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_s5"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + }; + + pmfalcon_s6: regulator-pmfalcon-s6 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_s6"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <504000>; + regulator-max-microvolt = <992000>; + }; + + pm2falcon_s1: regulator-pm2falcon-s1 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_s1"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <1125000>; + regulator-max-microvolt = <1125000>; + }; + + pm2falcon_s2: regulator-pm2falcon-s2 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_s2"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + }; + + /* PMFALCON S3 + S4 - VDD_CX supply */ + pm2falcon_s3_level: regulator-pm2falcon-s3-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_s3_level"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + pm2falcon_s3_floor_level: regulator-pm2falcon-s3-floor-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_s3_floor_level"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + pm2falcon_s3_level_ao: regulator-pm2falcon-s3-level-ao { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_s3_level_ao"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + /* PMFALCON S5 - VDD_MX supply */ + pm2falcon_s5_level: regulator-pm2falcon-s5-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_s5_level"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + pm2falcon_s5_floor_level: regulator-pm2falcon-s5-floor-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_s5_floor_level"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + pm2falcon_s5_level_ao: regulator-pm2falcon-s5-level-ao { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_s5_level_ao"; + qcom,hpm-min-load = <100000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + pmfalcon_l1: regulator-pmfalcon-l1 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l1"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1250000>; + }; + + pmfalcon_l2: regulator-pmfalcon-l2 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l2"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1010000>; + }; + + pmfalcon_l3: regulator-pmfalcon-l3 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l3"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1010000>; + }; + + /* TODO: remove if ADRASTEA CX/MX not voted from APPS */ + pmfalcon_l5: regulator-pmfalcon-l5 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l5"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <525000>; + regulator-max-microvolt = <950000>; + }; + + pmfalcon_l6: regulator-pmfalcon-l6 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l6"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1370000>; + }; + + pmfalcon_l7: regulator-pmfalcon-l7 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l7"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + pmfalcon_l8: regulator-pmfalcon-l8 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l8"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1900000>; + }; + + pmfalcon_l9: regulator-pmfalcon-l9 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l9"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1900000>; + }; + + pmfalcon_l10: regulator-pmfalcon-l10 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l10"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + }; + + pmfalcon_l11: regulator-pmfalcon-l11 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l11"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + }; + + pmfalcon_l12: regulator-pmfalcon-l12 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l12"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + }; + + pmfalcon_l13: regulator-pmfalcon-l13 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l13"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1950000>; + }; + + pmfalcon_l14: regulator-pmfalcon-l14 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l14"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <1900000>; + }; + + pmfalcon_l15: regulator-pmfalcon-l15 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l15"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + }; + + pmfalcon_l17: regulator-pmfalcon-l17 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l17"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + }; + + pmfalcon_l19: regulator-pmfalcon-l19 { + compatible = "qcom,stub-regulator"; + regulator-name = "pmfalcon_l19"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + }; + + pm2falcon_l1: regulator-pm2falcon-l1 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l1"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <925000>; + }; + + pm2falcon_l2: regulator-pm2falcon-l2 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l2"; + qcom,hpm-min-load = <5000>; + regulator-min-microvolt = <350000>; + regulator-max-microvolt = <3100000>; + }; + + pm2falcon_l3: regulator-pm2falcon-l3 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l3"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <3600000>; + }; + + pm2falcon_l4: regulator-pm2falcon-l4 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l4"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <2950000>; + }; + + pm2falcon_l5: regulator-pm2falcon-l5 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l5"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <1721000>; + regulator-max-microvolt = <3600000>; + }; + + pm2falcon_l6: regulator-pm2falcon-l6 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l6"; + qcom,hpm-min-load = <5000>; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3300000>; + }; + + pm2falcon_l7: regulator-pm2falcon-l7 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l7"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3125000>; + }; + + pm2falcon_l8: regulator-pm2falcon-l8 { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l8"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + }; + + /* PMFALCON L9 = VDD_SSC_CX supply */ + pm2falcon_l9_level: regulator-pm2falcon-l9-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l9_level"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + pm2falcon_l9_floor_level: regulator-pm2falcon-l9-floor-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l9_floor_level"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + /* PMFALCON L10 = VDD_SSC_MX supply */ + pm2falcon_l10_level: regulator-pm2falcon-l10-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l10_level"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + pm2falcon_l10_floor_level: regulator-pm2falcon-l10-floor-level { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_l10_floor_level"; + qcom,hpm-min-load = <10000>; + regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>; + regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>; + }; + + pm2falcon_bob: regulator-pm2falcon-bob { + compatible = "qcom,stub-regulator"; + regulator-name = "pm2falcon_bob"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + /* GFX Supply */ + gfx_vreg_corner: regulator-gfx-corner { + compatible = "qcom,stub-regulator"; + regulator-name = "gfx_corner"; + regulator-min-microvolt = <1>; + regulator-max-microvolt = <7>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msmtriton-rumi.dts b/arch/arm/boot/dts/qcom/msmtriton-rumi.dts index d3c62dbf99f2..0317c35d1f44 100644 --- a/arch/arm/boot/dts/qcom/msmtriton-rumi.dts +++ b/arch/arm/boot/dts/qcom/msmtriton-rumi.dts @@ -27,3 +27,8 @@ pinctrl-names = "default"; pinctrl-0 = <&uart_console_active>; }; + +&clock_gcc { + compatible = "qcom,dummycc"; + clock-output-names = "gcc_clocks"; +}; diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi index 8374d27e5b56..06f296a49113 100644 --- a/arch/arm/boot/dts/qcom/msmtriton.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi @@ -246,6 +246,32 @@ qcom,pipe-attr-ee; }; + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x300000>; + qcom,client-id = <2>; + label = "modem"; + }; + + mem_client_3_size: qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + label = "modem"; + }; + }; + tsens: tsens@10ad000 { compatible = "qcom,msmtriton-tsens"; reg = <0x10ad000 0x2000>; @@ -340,8 +366,10 @@ }; clock_gcc: clock-controller@100000 { - compatible = "qcom,dummycc"; - clock-output-names = "gcc_clocks"; + compatible = "qcom,gcc-msmfalcon"; + reg = <0x100000 0x94000>; + vdd_dig-supply = <&pm2falcon_s3_level>; + vdd_dig_ao-supply = <&pm2falcon_s3_level_ao>; #clock-cells = <1>; #reset-cells = <1>; }; @@ -503,6 +531,13 @@ qcom,xprt = "smem"; }; + rpm_bus: qcom,rpm-smd { + compatible = "qcom,rpm-glink"; + qcom,glink-edge = "rpm"; + rpm-channel-name = "rpm_requests"; + rpm-standalone; + }; + qcom,ipc_router { compatible = "qcom,ipc_router"; qcom,node-id = <1>; @@ -554,7 +589,7 @@ reg = <0x15700000 0x00100>; interrupts = <0 162 1>; - vdd_cx-supply = <&pmfalcon_s3b_level>; + vdd_cx-supply = <&pm2falcon_s3_level>; qcom,proxy-reg-names = "vdd_cx"; qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>; @@ -638,9 +673,9 @@ "mnoc_axi_clk"; interrupts = <0 448 1>; - vdd_cx-supply = <&pmfalcon_s3b_level>; + vdd_cx-supply = <&pm2falcon_s3_level>; vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>; - vdd_mx-supply = <&pmfalcon_s5b_level>; + vdd_mx-supply = <&pm2falcon_s5_level>; vdd_mx-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>; qcom,firmware-name = "modem"; qcom,pil-self-auth; @@ -662,10 +697,23 @@ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>; status = "ok"; }; + + qcom,msm-imem@146bf000 { + compatible = "qcom,msm-imem"; + reg = <0x146bf000 0x1000>; + ranges = <0x0 0x146bf000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + pil@94c { + compatible = "qcom,msm-imem-pil"; + reg = <0x94c 200>; + }; + }; }; #include "msmtriton-ion.dtsi" -#include "msmfalcon-regulator.dtsi" +#include "msmtriton-regulator.dtsi" #include "msm-gdsc-falcon.dtsi" &gdsc_usb30 { diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index 8be2b187a524..f8743e760054 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -27,6 +27,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y @@ -440,6 +441,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_ICNSS_DEBUG=y diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig index 74ee9792a284..511b9fe32b9b 100644 --- a/arch/arm/configs/msmfalcon_defconfig +++ b/arch/arm/configs/msmfalcon_defconfig @@ -38,6 +38,7 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_IOSCHED_DEADLINE is not set CONFIG_ARCH_QCOM=y CONFIG_ARCH_MSMFALCON=y +CONFIG_ARCH_MSMTRITON=y CONFIG_SMP=y CONFIG_SCHED_MC=y CONFIG_NR_CPUS=8 @@ -450,6 +451,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_ICNSS_DEBUG=y diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig index d4d355531169..cbccbeb483c9 100644 --- a/arch/arm/mach-qcom/Kconfig +++ b/arch/arm/mach-qcom/Kconfig @@ -39,6 +39,38 @@ config ARCH_MSMFALCON This enables support for the MSMFALCON chipset. If you do not wish to build a kernel that runs on this chipset, say 'N' here. +config ARCH_MSMTRITON + bool "Enable Support for Qualcomm MSMTRITON" + select CLKDEV_LOOKUP + select HAVE_CLK + select HAVE_CLK_PREPARE + select PM_OPP + select SOC_BUS + select MSM_IRQ + select THERMAL_WRITABLE_TRIPS + select ARM_GIC_V3 + select ARM_AMBA + select SPARSE_IRQ + select MULTI_IRQ_HANDLER + select HAVE_ARM_ARCH_TIMER + select MAY_HAVE_SPARSE_IRQ + select MSM_PM if PM + select QMI_ENCDEC + select CPU_FREQ + select CPU_FREQ_MSM + select PM_DEVFREQ + select MSM_DEVFREQ_DEVBW + select DEVFREQ_SIMPLE_DEV + select DEVFREQ_GOV_MSM_BW_HWMON + select MSM_BIMC_BWMON + select MSM_QDSP6V2_CODECS + select MSM_AUDIO_QDSP6V2 if SND_SOC + select MSM_RPM_SMD + select MSM_JTAGV8 if CORESIGHT_ETMV4 + help + This enables support for the MSMTRITON chipset. If you do not + wish to build a kernel that runs on this chipset, say 'N' here. + config ARCH_MSM8X60 bool "Enable support for MSM8X60" select ARCH_SUPPORTS_BIG_ENDIAN diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 52486c0e6598..80c4c50814d8 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -807,6 +807,7 @@ static void arm_dma_unremap(struct device *dev, void *remapped_addr, unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP; struct vm_struct *area; + size = PAGE_ALIGN(size); remapped_addr = (void *)((unsigned long)remapped_addr & PAGE_MASK); area = find_vm_area(remapped_addr); @@ -1818,7 +1819,7 @@ void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, total_length = PAGE_ALIGN((iova & ~PAGE_MASK) + total_length); iova &= PAGE_MASK; - iommu_unmap_range(mapping->domain, iova, total_length); + iommu_unmap(mapping->domain, iova, total_length); __free_iova(mapping, iova, total_length); } diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 5f8b02904d49..520a60c46106 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -32,6 +32,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index c1c0ae9da001..6249b604466b 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -29,6 +29,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 0bda100dfb5a..3990bece1dd1 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -35,6 +35,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y @@ -249,6 +250,8 @@ CONFIG_DM_CRYPT=y CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y @@ -380,9 +383,9 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y CONFIG_MSMB_JPEG=y CONFIG_MSM_FD=y CONFIG_MSM_JPEGDMA=y -CONFIG_MSM_VIDC_V4L2=m -CONFIG_MSM_VIDC_VMEM=m -CONFIG_MSM_VIDC_GOVERNORS=m +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y CONFIG_MSM_SDE_ROTATOR=y CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y CONFIG_QCOM_KGSL=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 3568fe4ed29f..15ca50859eca 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -34,6 +34,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y @@ -251,6 +252,8 @@ CONFIG_DM_CRYPT=y CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y @@ -383,9 +386,9 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y CONFIG_MSMB_JPEG=y CONFIG_MSM_FD=y CONFIG_MSM_JPEGDMA=y -CONFIG_MSM_VIDC_V4L2=m -CONFIG_MSM_VIDC_VMEM=m -CONFIG_MSM_VIDC_GOVERNORS=m +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y CONFIG_MSM_SDE_ROTATOR=y CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y CONFIG_QCOM_KGSL=y diff --git a/arch/arm64/configs/msmfalcon-perf_defconfig b/arch/arm64/configs/msmfalcon-perf_defconfig index dde7a01a9a36..df695f993ed9 100644 --- a/arch/arm64/configs/msmfalcon-perf_defconfig +++ b/arch/arm64/configs/msmfalcon-perf_defconfig @@ -259,9 +259,15 @@ CONFIG_SMSC911X=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y CONFIG_PPPOLAC=y CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y diff --git a/arch/arm64/configs/msmfalcon_defconfig b/arch/arm64/configs/msmfalcon_defconfig index 7c56e933c853..8719eb7cb92e 100644 --- a/arch/arm64/configs/msmfalcon_defconfig +++ b/arch/arm64/configs/msmfalcon_defconfig @@ -260,9 +260,15 @@ CONFIG_PHYLIB=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y CONFIG_PPPOLAC=y CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 07c67348b815..df083e9350c4 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -455,6 +455,7 @@ static void arm64_dma_unremap(struct device *dev, void *remapped_addr, { struct vm_struct *area; + size = PAGE_ALIGN(size); remapped_addr = (void *)((unsigned long)remapped_addr & PAGE_MASK); area = find_vm_area(remapped_addr); diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f80cfc36a354..a3f458fd2238 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1074,7 +1074,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) static struct binder_ref *binder_get_ref(struct binder_proc *proc, - uint32_t desc) + uint32_t desc, bool need_strong_ref) { struct rb_node *n = proc->refs_by_desc.rb_node; struct binder_ref *ref; @@ -1082,12 +1082,16 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, while (n) { ref = rb_entry(n, struct binder_ref, rb_node_desc); - if (desc < ref->desc) + if (desc < ref->desc) { n = n->rb_left; - else if (desc > ref->desc) + } else if (desc > ref->desc) { n = n->rb_right; - else + } else if (need_strong_ref && !ref->strong) { + binder_user_error("tried to use weak ref as strong ref\n"); + return NULL; + } else { return ref; + } } return NULL; } @@ -1357,7 +1361,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { - struct binder_ref *ref = binder_get_ref(proc, fp->handle); + struct binder_ref *ref = binder_get_ref(proc, fp->handle, + fp->type == BINDER_TYPE_HANDLE); if (ref == NULL) { pr_err("transaction release %d bad handle %d\n", @@ -1452,7 +1457,7 @@ static void binder_transaction(struct binder_proc *proc, if (tr->target.handle) { struct binder_ref *ref; - ref = binder_get_ref(proc, tr->target.handle); + ref = binder_get_ref(proc, tr->target.handle, true); if (ref == NULL) { binder_user_error("%d:%d got transaction to invalid handle\n", proc->pid, thread->pid); @@ -1649,7 +1654,9 @@ static void binder_transaction(struct binder_proc *proc, fp->type = BINDER_TYPE_HANDLE; else fp->type = BINDER_TYPE_WEAK_HANDLE; + fp->binder = 0; fp->handle = ref->desc; + fp->cookie = 0; binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo); @@ -1661,7 +1668,8 @@ static void binder_transaction(struct binder_proc *proc, } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { - struct binder_ref *ref = binder_get_ref(proc, fp->handle); + struct binder_ref *ref = binder_get_ref(proc, fp->handle, + fp->type == BINDER_TYPE_HANDLE); if (ref == NULL) { binder_user_error("%d:%d got transaction with invalid handle, %d\n", @@ -1696,7 +1704,9 @@ static void binder_transaction(struct binder_proc *proc, return_error = BR_FAILED_REPLY; goto err_binder_get_ref_for_node_failed; } + fp->binder = 0; fp->handle = new_ref->desc; + fp->cookie = 0; binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL); trace_binder_transaction_ref_to_ref(t, ref, new_ref); @@ -1750,6 +1760,7 @@ static void binder_transaction(struct binder_proc *proc, binder_debug(BINDER_DEBUG_TRANSACTION, " fd %d -> %d\n", fp->handle, target_fd); /* TODO: fput? */ + fp->binder = 0; fp->handle = target_fd; } break; @@ -1880,7 +1891,9 @@ static int binder_thread_write(struct binder_proc *proc, ref->desc); } } else - ref = binder_get_ref(proc, target); + ref = binder_get_ref(proc, target, + cmd == BC_ACQUIRE || + cmd == BC_RELEASE); if (ref == NULL) { binder_user_error("%d:%d refcount change on invalid ref %d\n", proc->pid, thread->pid, target); @@ -2076,7 +2089,7 @@ static int binder_thread_write(struct binder_proc *proc, if (get_user_preempt_disabled(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; ptr += sizeof(binder_uintptr_t); - ref = binder_get_ref(proc, target); + ref = binder_get_ref(proc, target, false); if (ref == NULL) { binder_user_error("%d:%d %s invalid ref %d\n", proc->pid, thread->pid, diff --git a/drivers/clk/msm/clock-gpu-cobalt.c b/drivers/clk/msm/clock-gpu-cobalt.c index 9d93351a083e..7cec9be1f42c 100644 --- a/drivers/clk/msm/clock-gpu-cobalt.c +++ b/drivers/clk/msm/clock-gpu-cobalt.c @@ -173,6 +173,7 @@ static struct clk_freq_tbl ftbl_gfx3d_clk_src_v2[] = { F_SLEW( 515000000, 1030000000, gpu_pll0_pll_out_even, 1, 0, 0), F_SLEW( 596000000, 1192000000, gpu_pll0_pll_out_even, 1, 0, 0), F_SLEW( 670000000, 1340000000, gpu_pll0_pll_out_even, 1, 0, 0), + F_SLEW( 710000000, 1420000000, gpu_pll0_pll_out_even, 1, 0, 0), F_END }; @@ -611,7 +612,7 @@ static void msm_gfxcc_hamster_fixup(void) static void msm_gfxcc_cobalt_v2_fixup(void) { - gpu_pll0_pll.c.fmax[VDD_DIG_MIN] = 1340000500; + gpu_pll0_pll.c.fmax[VDD_DIG_MIN] = 1420000500; gfx3d_clk_src.freq_tbl = ftbl_gfx3d_clk_src_v2; } diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c index 5391ef456aae..3e45aee1c0f7 100644 --- a/drivers/clk/msm/clock-osm.c +++ b/drivers/clk/msm/clock-osm.c @@ -49,6 +49,7 @@ enum clk_osm_bases { OSM_BASE, PLL_BASE, EFUSE_BASE, + ACD_BASE, NUM_BASES, }; @@ -228,11 +229,43 @@ enum clk_osm_trace_packet_id { #define MSMCOBALTV2_PWRCL_BOOT_RATE 1555200000 #define MSMCOBALTV2_PERFCL_BOOT_RATE 1728000000 +/* ACD registers */ +#define ACD_HW_VERSION 0x0 +#define ACDCR 0x4 +#define ACDTD 0x8 +#define ACDSSCR 0x28 +#define ACD_EXTINT_CFG 0x30 +#define ACD_DCVS_SW 0x34 +#define ACD_GFMUX_CFG 0x3c +#define ACD_READOUT_CFG 0x48 +#define ACD_AUTOXFER_CFG 0x80 +#define ACD_AUTOXFER 0x84 +#define ACD_AUTOXFER_CTL 0x88 +#define ACD_AUTOXFER_STATUS 0x8c +#define ACD_WRITE_CTL 0x90 +#define ACD_WRITE_STATUS 0x94 +#define ACD_READOUT 0x98 + +#define ACD_MASTER_ONLY_REG_ADDR 0x80 +#define ACD_WRITE_CTL_UPDATE_EN BIT(0) +#define ACD_WRITE_CTL_SELECT_SHIFT 1 +#define ACD_GFMUX_CFG_SELECT BIT(0) +#define ACD_AUTOXFER_START_CLEAR 0 +#define ACD_AUTOXFER_START_SET BIT(0) +#define AUTO_XFER_DONE_MASK BIT(0) +#define ACD_DCVS_SW_DCVS_IN_PRGR_SET BIT(0) +#define ACD_DCVS_SW_DCVS_IN_PRGR_CLEAR 0 +#define ACD_LOCAL_TRANSFER_TIMEOUT_NS 500 + static void __iomem *virt_base; static void __iomem *debug_base; #define lmh_lite_clk_src_source_val 1 +#define ACD_REG_RELATIVE_ADDR(addr) (addr / 4) +#define ACD_REG_RELATIVE_ADDR_BITMASK(addr) \ + (1 << (ACD_REG_RELATIVE_ADDR(addr))) + #define FIXDIV(div) (div ? (2 * (div) - 1) : (0)) #define F(f, s, div, m, n) \ @@ -341,6 +374,14 @@ struct clk_osm { u32 apm_ctrl_status; u32 osm_clk_rate; u32 xo_clk_rate; + u32 acd_td; + u32 acd_cr; + u32 acd_sscr; + u32 acd_extint0_cfg; + u32 acd_extint1_cfg; + u32 acd_autoxfer_ctl; + u32 acd_debugfs_addr; + bool acd_init; bool secure_init; bool red_fsm_en; bool boost_fsm_en; @@ -394,6 +435,161 @@ static inline int clk_osm_mb(struct clk_osm *c, int base) return readl_relaxed_no_log((char *)c->vbases[base] + VERSION_REG); } +static inline int clk_osm_acd_mb(struct clk_osm *c) +{ + return readl_relaxed_no_log((char *)c->vbases[ACD_BASE] + + ACD_HW_VERSION); +} + +static inline void clk_osm_acd_master_write_reg(struct clk_osm *c, + u32 val, u32 offset) +{ + writel_relaxed(val, (char *)c->vbases[ACD_BASE] + offset); +} + +static int clk_osm_acd_local_read_reg(struct clk_osm *c, u32 offset) +{ + u32 reg = 0; + int timeout; + + if (offset >= ACD_MASTER_ONLY_REG_ADDR) { + pr_err("ACD register at offset=0x%x not locally readable\n", + offset); + return -EINVAL; + } + + /* Set select field in read control register */ + writel_relaxed(ACD_REG_RELATIVE_ADDR(offset), + (char *)c->vbases[ACD_BASE] + ACD_READOUT_CFG); + + /* Clear write control register */ + writel_relaxed(reg, (char *)c->vbases[ACD_BASE] + ACD_WRITE_CTL); + + /* Set select and update_en fields in write control register */ + reg = (ACD_REG_RELATIVE_ADDR(ACD_READOUT_CFG) + << ACD_WRITE_CTL_SELECT_SHIFT) + | ACD_WRITE_CTL_UPDATE_EN; + writel_relaxed(reg, (char *)c->vbases[ACD_BASE] + ACD_WRITE_CTL); + + /* Ensure writes complete before polling */ + clk_osm_acd_mb(c); + + /* Poll write status register */ + for (timeout = ACD_LOCAL_TRANSFER_TIMEOUT_NS; timeout > 0; + timeout -= 100) { + reg = readl_relaxed((char *)c->vbases[ACD_BASE] + + ACD_WRITE_STATUS); + if ((reg & (ACD_REG_RELATIVE_ADDR_BITMASK(ACD_READOUT_CFG)))) + break; + ndelay(100); + } + + if (!timeout) { + pr_err("local read timed out, offset=0x%x status=0x%x\n", + offset, reg); + return -ETIMEDOUT; + } + + reg = readl_relaxed((char *)c->vbases[ACD_BASE] + + ACD_READOUT); + return reg; +} + +static int clk_osm_acd_local_write_reg(struct clk_osm *c, u32 val, u32 offset) +{ + u32 reg = 0; + int timeout; + + if (offset >= ACD_MASTER_ONLY_REG_ADDR) { + pr_err("ACD register at offset=0x%x not transferrable\n", + offset); + return -EINVAL; + } + + /* Clear write control register */ + writel_relaxed(reg, (char *)c->vbases[ACD_BASE] + ACD_WRITE_CTL); + + /* Set select and update_en fields in write control register */ + reg = (ACD_REG_RELATIVE_ADDR(offset) << ACD_WRITE_CTL_SELECT_SHIFT) + | ACD_WRITE_CTL_UPDATE_EN; + writel_relaxed(reg, (char *)c->vbases[ACD_BASE] + ACD_WRITE_CTL); + + /* Ensure writes complete before polling */ + clk_osm_acd_mb(c); + + /* Poll write status register */ + for (timeout = ACD_LOCAL_TRANSFER_TIMEOUT_NS; timeout > 0; + timeout -= 100) { + reg = readl_relaxed((char *)c->vbases[ACD_BASE] + + ACD_WRITE_STATUS); + if ((reg & (ACD_REG_RELATIVE_ADDR_BITMASK(offset)))) + break; + ndelay(100); + } + + if (!timeout) { + pr_err("local write timed out, offset=0x%x val=0x%x status=0x%x\n", + offset, val, reg); + return -ETIMEDOUT; + } + + return 0; +} + +static int clk_osm_acd_master_write_through_reg(struct clk_osm *c, + u32 val, u32 offset) +{ + writel_relaxed(val, (char *)c->vbases[ACD_BASE] + offset); + + /* Ensure writes complete before transfer to local copy */ + clk_osm_acd_mb(c); + + return clk_osm_acd_local_write_reg(c, val, offset); +} + +static int clk_osm_acd_auto_local_write_reg(struct clk_osm *c, u32 mask) +{ + u32 numregs, bitmask = mask; + u32 reg = 0; + int timeout; + + /* count number of bits set in register mask */ + for (numregs = 0; bitmask; numregs++) + bitmask &= bitmask - 1; + + /* Program auto-transfter mask */ + writel_relaxed(mask, (char *)c->vbases[ACD_BASE] + ACD_AUTOXFER_CFG); + + /* Clear start field in auto-transfer register */ + writel_relaxed(ACD_AUTOXFER_START_CLEAR, + (char *)c->vbases[ACD_BASE] + ACD_AUTOXFER); + + /* Set start field in auto-transfer register */ + writel_relaxed(ACD_AUTOXFER_START_SET, + (char *)c->vbases[ACD_BASE] + ACD_AUTOXFER); + + /* Ensure writes complete before polling */ + clk_osm_acd_mb(c); + + /* Poll auto-transfer status register */ + for (timeout = ACD_LOCAL_TRANSFER_TIMEOUT_NS * numregs; + timeout > 0; timeout -= 100) { + reg = readl_relaxed((char *)c->vbases[ACD_BASE] + + ACD_AUTOXFER_STATUS); + if (reg & AUTO_XFER_DONE_MASK) + break; + ndelay(100); + } + + if (!timeout) { + pr_err("local register auto-transfer timed out, mask=0x%x registers=%d status=0x%x\n", + mask, numregs, reg); + return -ETIMEDOUT; + } + + return 0; +} + static inline int clk_osm_count_ns(struct clk_osm *c, u64 nsec) { u64 temp; @@ -813,6 +1009,74 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev) LLM_SW_OVERRIDE_CNT + i, &perfcl_clk.llm_sw_overr[i]); + if (pwrcl_clk.acd_init || perfcl_clk.acd_init) { + rc = of_property_read_u32_array(of, "qcom,acdtd-val", + array, MAX_CLUSTER_CNT); + if (rc) { + dev_err(&pdev->dev, "unable to find qcom,acdtd-val property, rc=%d\n", + rc); + return -EINVAL; + } + + pwrcl_clk.acd_td = array[pwrcl_clk.cluster_num]; + perfcl_clk.acd_td = array[perfcl_clk.cluster_num]; + + rc = of_property_read_u32_array(of, "qcom,acdcr-val", + array, MAX_CLUSTER_CNT); + if (rc) { + dev_err(&pdev->dev, "unable to find qcom,acdcr-val property, rc=%d\n", + rc); + return -EINVAL; + } + + pwrcl_clk.acd_cr = array[pwrcl_clk.cluster_num]; + perfcl_clk.acd_cr = array[perfcl_clk.cluster_num]; + + rc = of_property_read_u32_array(of, "qcom,acdsscr-val", + array, MAX_CLUSTER_CNT); + if (rc) { + dev_err(&pdev->dev, "unable to find qcom,acdsscr-val property, rc=%d\n", + rc); + return -EINVAL; + } + + pwrcl_clk.acd_sscr = array[pwrcl_clk.cluster_num]; + perfcl_clk.acd_sscr = array[perfcl_clk.cluster_num]; + + rc = of_property_read_u32_array(of, "qcom,acdextint0-val", + array, MAX_CLUSTER_CNT); + if (rc) { + dev_err(&pdev->dev, "unable to find qcom,acdextint0-val property, rc=%d\n", + rc); + return -EINVAL; + } + + pwrcl_clk.acd_extint0_cfg = array[pwrcl_clk.cluster_num]; + perfcl_clk.acd_extint0_cfg = array[perfcl_clk.cluster_num]; + + rc = of_property_read_u32_array(of, "qcom,acdextint1-val", + array, MAX_CLUSTER_CNT); + if (rc) { + dev_err(&pdev->dev, "unable to find qcom,acdextint1-val property, rc=%d\n", + rc); + return -EINVAL; + } + + pwrcl_clk.acd_extint1_cfg = array[pwrcl_clk.cluster_num]; + perfcl_clk.acd_extint1_cfg = array[perfcl_clk.cluster_num]; + + rc = of_property_read_u32_array(of, "qcom,acdautoxfer-val", + array, MAX_CLUSTER_CNT); + if (rc) { + dev_err(&pdev->dev, "unable to find qcom,acdautoxfer-val property, rc=%d\n", + rc); + return -EINVAL; + } + + pwrcl_clk.acd_autoxfer_ctl = array[pwrcl_clk.cluster_num]; + perfcl_clk.acd_autoxfer_ctl = array[perfcl_clk.cluster_num]; + } + rc = of_property_read_u32(of, "qcom,xo-clk-rate", &pwrcl_clk.xo_clk_rate); if (rc) { @@ -1037,6 +1301,40 @@ static int clk_osm_resources_init(struct platform_device *pdev) perfcl_clk.vbases[EFUSE_BASE] = vbase; } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "pwrcl_acd"); + if (res) { + pbase = (unsigned long)res->start; + vbase = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!vbase) { + dev_err(&pdev->dev, "Unable to map in pwrcl_acd base\n"); + return -ENOMEM; + } + pwrcl_clk.pbases[ACD_BASE] = pbase; + pwrcl_clk.vbases[ACD_BASE] = vbase; + pwrcl_clk.acd_init = true; + } else { + pwrcl_clk.acd_init = false; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "perfcl_acd"); + if (res) { + pbase = (unsigned long)res->start; + vbase = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!vbase) { + dev_err(&pdev->dev, "Unable to map in perfcl_acd base\n"); + return -ENOMEM; + } + perfcl_clk.pbases[ACD_BASE] = pbase; + perfcl_clk.vbases[ACD_BASE] = vbase; + perfcl_clk.acd_init = true; + } else { + perfcl_clk.acd_init = false; + } + vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl"); if (IS_ERR(vdd_pwrcl)) { rc = PTR_ERR(vdd_pwrcl); @@ -2402,6 +2700,55 @@ DEFINE_SIMPLE_ATTRIBUTE(debugfs_perf_state_deviation_corrected_irq_fops, debugfs_set_perf_state_deviation_corrected_irq, "%llu\n"); +static int debugfs_get_debug_reg(void *data, u64 *val) +{ + struct clk_osm *c = data; + + if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR) + *val = readl_relaxed((char *)c->vbases[ACD_BASE] + + c->acd_debugfs_addr); + else + *val = clk_osm_acd_local_read_reg(c, c->acd_debugfs_addr); + return 0; +} + +static int debugfs_set_debug_reg(void *data, u64 val) +{ + struct clk_osm *c = data; + + if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR) + clk_osm_acd_master_write_reg(c, val, c->acd_debugfs_addr); + else + clk_osm_acd_master_write_through_reg(c, val, + c->acd_debugfs_addr); + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(debugfs_acd_debug_reg_fops, + debugfs_get_debug_reg, + debugfs_set_debug_reg, + "0x%llx\n"); + +static int debugfs_get_debug_reg_addr(void *data, u64 *val) +{ + struct clk_osm *c = data; + + *val = c->acd_debugfs_addr; + return 0; +} + +static int debugfs_set_debug_reg_addr(void *data, u64 val) +{ + struct clk_osm *c = data; + + c->acd_debugfs_addr = val; + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(debugfs_acd_debug_reg_addr_fops, + debugfs_get_debug_reg_addr, + debugfs_set_debug_reg_addr, + "%llu\n"); + static void populate_debugfs_dir(struct clk_osm *c) { struct dentry *temp; @@ -2493,6 +2840,24 @@ static void populate_debugfs_dir(struct clk_osm *c) goto exit; } + temp = debugfs_create_file("acd_debug_reg", + S_IRUGO | S_IWUSR, + c->debugfs, c, + &debugfs_acd_debug_reg_fops); + if (IS_ERR_OR_NULL(temp)) { + pr_err("debugfs_acd_debug_reg_fops debugfs file creation failed\n"); + goto exit; + } + + temp = debugfs_create_file("acd_debug_reg_addr", + S_IRUGO | S_IWUSR, + c->debugfs, c, + &debugfs_acd_debug_reg_addr_fops); + if (IS_ERR_OR_NULL(temp)) { + pr_err("debugfs_acd_debug_reg_addr_fops debugfs file creation failed\n"); + goto exit; + } + exit: if (IS_ERR_OR_NULL(temp)) debugfs_remove_recursive(c->debugfs); @@ -2537,6 +2902,81 @@ static int clk_osm_panic_callback(struct notifier_block *nfb, return NOTIFY_OK; } +static int clk_osm_acd_init(struct clk_osm *c) +{ + + int rc = 0; + u32 auto_xfer_mask = 0; + + if (!c->acd_init) + return 0; + + c->acd_debugfs_addr = ACD_HW_VERSION; + + /* Program ACD tunable-length delay register */ + clk_osm_acd_master_write_reg(c, c->acd_td, ACDTD); + auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDTD); + + /* Program ACD control register */ + clk_osm_acd_master_write_reg(c, c->acd_cr, ACDCR); + auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDCR); + + /* Program ACD soft start control register */ + clk_osm_acd_master_write_reg(c, c->acd_sscr, ACDSSCR); + auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDSSCR); + + /* Program initial ACD external interface configuration register */ + clk_osm_acd_master_write_reg(c, c->acd_extint0_cfg, ACD_EXTINT_CFG); + auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACD_EXTINT_CFG); + + /* Program ACD auto-register transfer control register */ + clk_osm_acd_master_write_reg(c, c->acd_autoxfer_ctl, ACD_AUTOXFER_CTL); + + /* Ensure writes complete before transfers to local copy */ + clk_osm_acd_mb(c); + + /* Transfer master copies */ + rc = clk_osm_acd_auto_local_write_reg(c, auto_xfer_mask); + if (rc) + return rc; + + /* Switch CPUSS clock source to ACD clock */ + rc = clk_osm_acd_master_write_through_reg(c, ACD_GFMUX_CFG_SELECT, + ACD_GFMUX_CFG); + if (rc) + return rc; + + /* Program ACD_DCVS_SW */ + rc = clk_osm_acd_master_write_through_reg(c, + ACD_DCVS_SW_DCVS_IN_PRGR_SET, + ACD_DCVS_SW); + if (rc) + return rc; + + rc = clk_osm_acd_master_write_through_reg(c, + ACD_DCVS_SW_DCVS_IN_PRGR_CLEAR, + ACD_DCVS_SW); + if (rc) + return rc; + + udelay(1); + + /* Program final ACD external interface configuration register */ + rc = clk_osm_acd_master_write_through_reg(c, c->acd_extint1_cfg, + ACD_EXTINT_CFG); + if (rc) + return rc; + + /* + * ACDCR, ACDTD, ACDSSCR, ACD_EXTINT_CFG, ACD_GFMUX_CFG + * must be copied from master to local copy on PC exit. + */ + auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACD_GFMUX_CFG); + clk_osm_acd_master_write_reg(c, auto_xfer_mask, ACD_AUTOXFER_CFG); + + return 0; +} + static unsigned long init_rate = 300000000; static unsigned long osm_clk_init_rate = 200000000; @@ -2717,6 +3157,17 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev) clk_osm_setup_cluster_pll(&perfcl_clk); } + rc = clk_osm_acd_init(&pwrcl_clk); + if (rc) { + pr_err("failed to initialize ACD for pwrcl, rc=%d\n", rc); + return rc; + } + rc = clk_osm_acd_init(&perfcl_clk); + if (rc) { + pr_err("failed to initialize ACD for perfcl, rc=%d\n", rc); + return rc; + } + spin_lock_init(&pwrcl_clk.lock); spin_lock_init(&perfcl_clk.lock); diff --git a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c index a574a9cd2b5a..93bbcf5d40f5 100644 --- a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c +++ b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c @@ -275,7 +275,7 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0, 0xa0); + QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x12); MDSS_PLL_REG_W(dp_res->pll_base, @@ -733,7 +733,7 @@ unsigned long dp_vco_get_rate(struct clk *c) { struct dp_pll_vco_clk *vco = mdss_dp_to_vco_clk(c); int rc; - u32 div, hsclk_div, link2xclk_div; + u32 div, hsclk_div, link2xclk_div = 0; u64 vco_rate; struct mdss_pll_resources *pll = vco->priv; diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c b/drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c index 4b2d8bba0940..299934c86d05 100644 --- a/drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c +++ b/drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c @@ -205,18 +205,34 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_cobalt *pll, struct dsi_pll_regs *regs = &pll->reg_setup; u64 target_freq; u64 fref = rsc->vco_ref_clk_rate; - u32 computed_output_div, div_log; + u32 computed_output_div, div_log = 0; u64 pll_freq; u64 divider; u64 dec, dec_multiple; u32 frac; u64 multiplier; + u32 i; target_freq = rsc->vco_current_rate; pr_debug("target_freq = %llu\n", target_freq); if (config->div_override) { computed_output_div = config->output_div; + + /* + * Computed_output_div = 2 ^ div_log + * To get div_log from output div just get the index of the + * 1 bit in the value. + * div_log ranges from 0-3. so check the 4 lsbs + */ + + for (i = 0; i < 4; i++) { + if (computed_output_div & (1 << i)) { + div_log = i; + break; + } + } + } else { if (target_freq < MHZ_375) { computed_output_div = 8; diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 4d46d65898d1..085b9acfb9d5 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1,5 +1,5 @@ /* - * 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 @@ -20,28 +20,34 @@ #include "clk-alpha-pll.h" #define PLL_MODE 0x00 -# define PLL_OUTCTRL BIT(0) -# define PLL_BYPASSNL BIT(1) -# define PLL_RESET_N BIT(2) -# define PLL_LOCK_COUNT_SHIFT 8 -# define PLL_LOCK_COUNT_MASK 0x3f -# define PLL_BIAS_COUNT_SHIFT 14 -# define PLL_BIAS_COUNT_MASK 0x3f -# define PLL_VOTE_FSM_ENA BIT(20) -# define PLL_VOTE_FSM_RESET BIT(21) -# define PLL_ACTIVE_FLAG BIT(30) -# define PLL_LOCK_DET BIT(31) +#define PLL_OUTCTRL BIT(0) +#define PLL_BYPASSNL BIT(1) +#define PLL_RESET_N BIT(2) +#define PLL_LOCK_COUNT_SHIFT 8 +#define PLL_LOCK_COUNT_MASK 0x3f +#define PLL_LOCK_COUNT_VAL 0x0 +#define PLL_BIAS_COUNT_SHIFT 14 +#define PLL_BIAS_COUNT_MASK 0x3f +#define PLL_BIAS_COUNT_VAL 0x6 +#define PLL_LATCH_INTERFACE BIT(11) +#define PLL_VOTE_FSM_ENA BIT(20) +#define PLL_VOTE_FSM_RESET BIT(21) +#define PLL_UPDATE BIT(22) +#define PLL_HW_UPDATE_LOGIC_BYPASS BIT(23) +#define PLL_ALPHA_EN BIT(24) +#define PLL_ACTIVE_FLAG BIT(30) +#define PLL_LOCK_DET BIT(31) +#define PLL_ACK_LATCH BIT(29) #define PLL_L_VAL 0x04 #define PLL_ALPHA_VAL 0x08 #define PLL_ALPHA_VAL_U 0x0c #define PLL_USER_CTL 0x10 -# define PLL_POST_DIV_SHIFT 8 -# define PLL_POST_DIV_MASK 0xf -# define PLL_ALPHA_EN BIT(24) -# define PLL_VCO_SHIFT 20 -# define PLL_VCO_MASK 0x3 +#define PLL_POST_DIV_SHIFT 8 +#define PLL_POST_DIV_MASK 0xf +#define PLL_VCO_SHIFT 20 +#define PLL_VCO_MASK 0x3 #define PLL_USER_CTL_U 0x14 @@ -79,7 +85,7 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse, ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); if (ret) return ret; - if (inverse && (val & mask)) + if (inverse && !(val & mask)) return 0; else if ((val & mask) == mask) return 0; @@ -106,6 +112,10 @@ static int wait_for_pll_offline(struct clk_alpha_pll *pll, u32 mask) return wait_for_pll(pll, mask, 0, "offline"); } +static int wait_for_pll_latch_ack(struct clk_alpha_pll *pll, u32 mask) +{ + return wait_for_pll(pll, mask, 0, "latch_ack"); +} /* alpha pll with hwfsm support */ @@ -114,29 +124,103 @@ static int wait_for_pll_offline(struct clk_alpha_pll *pll, u32 mask) #define PLL_OFFLINE_ACK BIT(28) #define PLL_ACTIVE_FLAG BIT(30) +static void clk_alpha_set_fsm_mode(struct clk_alpha_pll *pll) +{ + u32 val; + + regmap_read(pll->clkr.regmap, pll->offset + PLL_MODE, &val); + + /* De-assert reset to FSM */ + val &= ~PLL_VOTE_FSM_RESET; + + /* Program bias count */ + val &= ~(PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT); + val |= PLL_BIAS_COUNT_VAL << PLL_BIAS_COUNT_SHIFT; + + /* Program lock count */ + val &= ~(PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT); + val |= PLL_LOCK_COUNT_VAL << PLL_LOCK_COUNT_SHIFT; + + /* Enable PLL FSM voting */ + val |= PLL_VOTE_FSM_ENA; + + regmap_write(pll->clkr.regmap, pll->offset + PLL_MODE, val); +} + void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, - const struct pll_config *config) + const struct pll_config *config) { u32 val, mask; - regmap_write(regmap, pll->offset + PLL_CONFIG_CTL, - config->config_ctl_val); + if (config->l) + regmap_write(regmap, pll->offset + PLL_L_VAL, + config->l); + if (config->alpha) + regmap_write(regmap, pll->offset + PLL_ALPHA_VAL, + config->alpha); + if (config->alpha_u) + regmap_write(regmap, pll->offset + PLL_ALPHA_VAL_U, + config->alpha_u); + if (config->config_ctl_val) + regmap_write(regmap, pll->offset + PLL_CONFIG_CTL, + config->config_ctl_val); + + if (config->main_output_mask || config->aux_output_mask || + config->aux2_output_mask || config->early_output_mask || + config->vco_val || config->alpha_en_mask) { + + val = config->main_output_mask; + val |= config->aux_output_mask; + val |= config->aux2_output_mask; + val |= config->early_output_mask; + val |= config->vco_val; + val |= config->alpha_en_mask; + + mask = config->main_output_mask; + mask |= config->aux_output_mask; + mask |= config->aux2_output_mask; + mask |= config->early_output_mask; + mask |= config->vco_mask; + mask |= config->alpha_en_mask; + + regmap_update_bits(regmap, pll->offset + PLL_USER_CTL, + mask, val); + } - val = config->main_output_mask; - val |= config->aux_output_mask; - val |= config->aux2_output_mask; - val |= config->early_output_mask; - val |= config->post_div_val; + if (config->post_div_mask) { + mask = config->post_div_mask; + val = config->post_div_val; + regmap_update_bits(regmap, pll->offset + PLL_USER_CTL, + mask, val); + } - mask = config->main_output_mask; - mask |= config->aux_output_mask; - mask |= config->aux2_output_mask; - mask |= config->early_output_mask; - mask |= config->post_div_mask; + /* Do not bypass the latch interface */ + if (pll->flags & SUPPORTS_SLEW) + regmap_update_bits(regmap, pll->offset + PLL_USER_CTL_U, + PLL_LATCH_INTERFACE, (u32)~PLL_LATCH_INTERFACE); - regmap_update_bits(regmap, pll->offset + PLL_USER_CTL, mask, val); + if (pll->flags & SUPPORTS_DYNAMIC_UPDATE) { + regmap_update_bits(regmap, pll->offset + PLL_MODE, + PLL_HW_UPDATE_LOGIC_BYPASS, + PLL_HW_UPDATE_LOGIC_BYPASS); + } - return; + if (config->test_ctl_lo_mask) { + mask = config->test_ctl_lo_mask; + val = config->test_ctl_lo_val; + regmap_update_bits(regmap, pll->offset + PLL_TEST_CTL, + mask, val); + } + + if (config->test_ctl_hi_mask) { + mask = config->test_ctl_hi_mask; + val = config->test_ctl_hi_val; + regmap_update_bits(regmap, pll->offset + PLL_TEST_CTL_U, + mask, val); + } + + if (pll->flags & SUPPORTS_FSM_MODE) + clk_alpha_set_fsm_mode(pll); } static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw) @@ -190,8 +274,9 @@ static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw) PLL_FSM_ENA, 0); if (ret) return; + wait_for_pll_disable(pll, PLL_ACTIVE_FLAG); - return; + } static int clk_alpha_pll_enable(struct clk_hw *hw) @@ -201,7 +286,6 @@ static int clk_alpha_pll_enable(struct clk_hw *hw) u32 val, mask, off; off = pll->offset; - mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL; ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); if (ret) @@ -339,7 +423,53 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH; } - return alpha_pll_calc_rate(prate, l, a); + ctl >>= PLL_POST_DIV_SHIFT; + ctl &= PLL_POST_DIV_MASK; + + return alpha_pll_calc_rate(prate, l, a) >> fls(ctl); +} + +static int clk_alpha_pll_dynamic_update(struct clk_alpha_pll *pll) +{ + int ret; + + /* Latch the input to the PLL */ + regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_MODE, + PLL_UPDATE, PLL_UPDATE); + + /* Wait for 2 reference cycle before checking ACK bit */ + udelay(1); + + ret = wait_for_pll_latch_ack(pll, PLL_ACK_LATCH); + if (ret) + return ret; + + /* Return latch input to 0 */ + regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_MODE, + PLL_UPDATE, (u32)~PLL_UPDATE); + + ret = wait_for_pll_enable(pll, PLL_LOCK_DET); + if (ret) + return ret; + + return 0; +} + +static const struct pll_vco_data + *find_vco_data(const struct pll_vco_data *data, + unsigned long rate, size_t size) +{ + int i; + + if (!data) + return NULL; + + for (i = 0; i < size; i++) { + if (rate == data[i].freq) + return &data[i]; + } + + return &data[i - 1]; } static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, @@ -347,16 +477,36 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); const struct pll_vco *vco; + const struct pll_vco_data *data; + bool is_enabled; u32 l, off = pll->offset; u64 a; + unsigned long rrate; + + rrate = alpha_pll_round_rate(rate, prate, &l, &a); - rate = alpha_pll_round_rate(rate, prate, &l, &a); - vco = alpha_pll_find_vco(pll, rate); + if (rrate != rate) { + pr_err("alpha_pll: Call clk_set_rate with rounded rates!\n"); + return -EINVAL; + } + + vco = alpha_pll_find_vco(pll, rrate); if (!vco) { pr_err("alpha pll not in a valid vco range\n"); return -EINVAL; } + is_enabled = clk_hw_is_enabled(hw); + + /* + * For PLLs that do not support dynamic programming (dynamic_update + * is not set), ensure PLL is off before changing rate. For + * optimization reasons, assume no downstream clock is actively + * using it. + */ + if (is_enabled && !(pll->flags & SUPPORTS_DYNAMIC_UPDATE)) + hw->init->ops->disable(hw); + a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH); regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l); @@ -367,9 +517,27 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, PLL_VCO_MASK << PLL_VCO_SHIFT, vco->val << PLL_VCO_SHIFT); + data = find_vco_data(pll->vco_data, rate, pll->num_vco_data); + if (data) { + if (data->freq == rate) + regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, + PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT, + data->post_div_val << PLL_POST_DIV_SHIFT); + else + regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, + PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT, + 0x0 << PLL_VCO_SHIFT); + } + regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN, PLL_ALPHA_EN); + if (is_enabled && (pll->flags & SUPPORTS_DYNAMIC_UPDATE)) + clk_alpha_pll_dynamic_update(pll); + + if (is_enabled && !(pll->flags & SUPPORTS_DYNAMIC_UPDATE)) + hw->init->ops->enable(hw); + return 0; } @@ -381,6 +549,9 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate, u64 a; unsigned long min_freq, max_freq; + if (rate < pll->min_supported_freq) + return pll->min_supported_freq; + rate = alpha_pll_round_rate(rate, *prate, &l, &a); if (alpha_pll_find_vco(pll, rate)) return rate; diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 7718bd5beefc..9b1d3ee61cac 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -1,5 +1,5 @@ /* - * 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 @@ -18,6 +18,11 @@ #include "clk-regmap.h" #include "clk-pll.h" +struct pll_vco_data { + unsigned long freq; + u8 post_div_val; +}; + struct pll_vco { unsigned long min_freq; unsigned long max_freq; @@ -28,21 +33,35 @@ struct pll_vco { * struct clk_alpha_pll - phase locked loop (PLL) * @offset: base address of registers * @vco_table: array of VCO settings + * @vco_data: array of VCO data settings like post div * @clkr: regmap clock handle */ struct clk_alpha_pll { u32 offset; + struct pll_config *config; const struct pll_vco *vco_table; size_t num_vco; + const struct pll_vco_data *vco_data; + size_t num_vco_data; + + u8 flags; +#define SUPPORTS_FSM_MODE BIT(0) + /* some PLLs support dynamically updating their rate + * without disabling the PLL first. Set this flag + * to enable this support. + */ +#define SUPPORTS_DYNAMIC_UPDATE BIT(1) +#define SUPPORTS_SLEW BIT(2) + struct clk_regmap clkr; - u32 config_ctl_val; #define PLLOUT_MAIN BIT(0) #define PLLOUT_AUX BIT(1) #define PLLOUT_AUX2 BIT(2) #define PLLOUT_EARLY BIT(3) u32 pllout_flags; + unsigned long min_supported_freq; }; /** diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h index 1e64fe9326d6..4f779fda785b 100644 --- a/drivers/clk/qcom/clk-pll.h +++ b/drivers/clk/qcom/clk-pll.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 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 @@ -70,6 +70,8 @@ struct pll_config { u16 l; u32 m; u32 n; + u32 alpha; + u32 alpha_u; u32 vco_val; u32 vco_mask; u32 pre_div_val; @@ -77,11 +79,16 @@ struct pll_config { u32 post_div_val; u32 post_div_mask; u32 mn_ena_mask; + u32 alpha_en_mask; u32 main_output_mask; u32 aux_output_mask; u32 aux2_output_mask; u32 early_output_mask; u32 config_ctl_val; + u32 test_ctl_lo_val; + u32 test_ctl_lo_mask; + u32 test_ctl_hi_val; + u32 test_ctl_hi_mask; }; void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap, diff --git a/drivers/clk/qcom/gpucc-msmfalcon.c b/drivers/clk/qcom/gpucc-msmfalcon.c index f194abb471cd..fe7cff443250 100644 --- a/drivers/clk/qcom/gpucc-msmfalcon.c +++ b/drivers/clk/qcom/gpucc-msmfalcon.c @@ -35,8 +35,8 @@ #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } #define F_GFX(f, s, h, m, n, sf) { (f), (s), (2 * (h) - 1), (m), (n), (sf) } -static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL); -static DEFINE_VDD_REGULATORS(vdd_mx, VDD_DIG_NUM, 1, vdd_corner, NULL); +static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner); +static DEFINE_VDD_REGULATORS(vdd_mx, VDD_DIG_NUM, 1, vdd_corner); static DEFINE_VDD_REGS_INIT(vdd_gfx, 1); enum { @@ -181,6 +181,7 @@ static struct clk_init_data gpu_clks_init[] = { * | 465000000 | 930000000 | 1 | 2 | * | 588000000 | 1176000000 | 1 | 2 | * | 647000000 | 1294000000 | 1 | 2 | + * | 700000000 | 1400000000 | 1 | 2 | * | 750000000 | 1500000000 | 1 | 2 | * ==================================================== */ @@ -193,6 +194,7 @@ static const struct freq_tbl ftbl_gfx3d_clk_src[] = { F_GFX(465000000, 0, 2, 0, 0, 930000000), F_GFX(588000000, 0, 2, 0, 0, 1176000000), F_GFX(647000000, 0, 2, 0, 0, 1294000000), + F_GFX(700000000, 0, 2, 0, 0, 1400000000), F_GFX(750000000, 0, 2, 0, 0, 1500000000), { } }; @@ -376,9 +378,9 @@ static int of_get_fmax_vdd_class(struct platform_device *pdev, if (!vdd->vdd_uv) return -ENOMEM; - gpu_clks_init[index].fmax = devm_kzalloc(&pdev->dev, prop_len * + gpu_clks_init[index].rate_max = devm_kzalloc(&pdev->dev, prop_len * sizeof(unsigned long), GFP_KERNEL); - if (!gpu_clks_init[index].fmax) + if (!gpu_clks_init[index].rate_max) return -ENOMEM; array = devm_kzalloc(&pdev->dev, prop_len * sizeof(u32) * num, @@ -388,7 +390,7 @@ static int of_get_fmax_vdd_class(struct platform_device *pdev, of_property_read_u32_array(of, prop_name, array, prop_len * num); for (i = 0; i < prop_len; i++) { - gpu_clks_init[index].fmax[i] = array[num * i]; + gpu_clks_init[index].rate_max[i] = array[num * i]; for (j = 1; j < num; j++) { vdd->vdd_uv[(num - 1) * i + (j - 1)] = array[num * i + j]; @@ -398,7 +400,7 @@ static int of_get_fmax_vdd_class(struct platform_device *pdev, devm_kfree(&pdev->dev, array); vdd->num_levels = prop_len; vdd->cur_level = prop_len; - gpu_clks_init[index].num_fmax = prop_len; + gpu_clks_init[index].num_rate_max = prop_len; return 0; } diff --git a/drivers/cpufreq/qcom-cpufreq.c b/drivers/cpufreq/qcom-cpufreq.c index 82861b1dbe46..2aa7b783f276 100644 --- a/drivers/cpufreq/qcom-cpufreq.c +++ b/drivers/cpufreq/qcom-cpufreq.c @@ -3,7 +3,7 @@ * MSM architecture cpufreq driver * * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2007-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved. * Author: Mike A. Chan <mikechan@google.com> * * This software is licensed under the terms of the GNU General Public @@ -320,7 +320,7 @@ static struct cpufreq_driver msm_cpufreq_driver = { static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, char *tbl_name, int cpu) { - int ret, nf, i; + int ret, nf, i, j; u32 *data; struct cpufreq_frequency_table *ftbl; @@ -344,6 +344,7 @@ static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, if (!ftbl) return ERR_PTR(-ENOMEM); + j = 0; for (i = 0; i < nf; i++) { unsigned long f; @@ -353,29 +354,20 @@ static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, f /= 1000; /* - * Check if this is the last feasible frequency in the table. + * Don't repeat frequencies if they round up to the same clock + * frequency. * - * The table listing frequencies higher than what the HW can - * support is not an error since the table might be shared - * across CPUs in different speed bins. It's also not - * sufficient to check if the rounded rate is lower than the - * requested rate as it doesn't cover the following example: - * - * Table lists: 2.2 GHz and 2.5 GHz. - * Rounded rate returns: 2.2 GHz and 2.3 GHz. - * - * In this case, we can CPUfreq to use 2.2 GHz and 2.3 GHz - * instead of rejecting the 2.5 GHz table entry. */ - if (i > 0 && f <= ftbl[i-1].frequency) - break; + if (j > 0 && f <= ftbl[j - 1].frequency) + continue; - ftbl[i].driver_data = i; - ftbl[i].frequency = f; + ftbl[j].driver_data = j; + ftbl[j].frequency = f; + j++; } - ftbl[i].driver_data = i; - ftbl[i].frequency = CPUFREQ_TABLE_END; + ftbl[j].driver_data = j; + ftbl[j].frequency = CPUFREQ_TABLE_END; devm_kfree(dev, data); diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 386c85fc714b..77aea1f41714 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -372,18 +372,18 @@ config CRYPTO_DEV_QCRYPTO config CRYPTO_DEV_QCOM_MSM_QCE tristate "Qualcomm Crypto Engine (QCE) module" - select CRYPTO_DEV_QCE50 if ARCH_APQ8084 || ARCH_MSM8916 || ARCH_MSM8994 || ARCH_MSM8996 || ARCH_MSM8992 || ARCH_MSMTITANIUM || ARCH_MSM8909 || ARCH_MSMCOBALT || ARCH_MSMFALCON + select CRYPTO_DEV_QCE50 if ARCH_APQ8084 || ARCH_MSM8916 || ARCH_MSM8994 || ARCH_MSM8996 || ARCH_MSM8992 || ARCH_MSMTITANIUM || ARCH_MSM8909 || ARCH_MSMCOBALT || ARCH_MSMFALCON || ARCH_MSMTRITON default n help This driver supports Qualcomm Crypto Engine in MSM7x30, MSM8660 MSM8x55, MSM8960, MSM9615, MSM8916, MSM8994, MSM8996, FSM9900, - MSMTITANINUM, APQ8084, MSMCOBALT and MSMFALCON. + MSMTITANINUM, APQ8084, MSMCOBALT, MSMFALCON and MSMTRITON. To compile this driver as a module, choose M here: the For MSM7x30 MSM8660 and MSM8x55 the module is called qce For MSM8960, APQ8064 and MSM9615 the module is called qce40 For MSM8974, MSM8916, MSM8994, MSM8996, MSM8992, MSMTITANIUM, - APQ8084, MSMCOBALT and MSMFALCON the module is called qce50. + APQ8084, MSMCOBALT, MSMFALCON and MSMTRITON the module is called qce50. config CRYPTO_DEV_QCEDEV tristate "QCEDEV Interface to CE module" @@ -391,8 +391,8 @@ config CRYPTO_DEV_QCEDEV help This driver supports Qualcomm QCEDEV Crypto in MSM7x30, MSM8660, MSM8960, MSM9615, APQ8064, MSM8974, MSM8916, MSM8994, MSM8996, - APQ8084, MSMCOBALT, MSMFALCON. This exposes the interface to the QCE hardware - accelerator via IOCTLs. + APQ8084, MSMCOBALT, MSMFALCON, MSMTRITON. This exposes the + interface to the QCE hardware accelerator via IOCTLs. To compile this driver as a module, choose M here: the module will be called qcedev. diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 3562de7fc967..55c043b44cea 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -3023,6 +3023,7 @@ static void qce_multireq_timeout(unsigned long data) struct qce_device *pce_dev = (struct qce_device *)data; int ret = 0; int last_seq; + unsigned long flags; last_seq = atomic_read(&pce_dev->bunch_cmd_seq); if (last_seq == 0 || @@ -3032,21 +3033,33 @@ static void qce_multireq_timeout(unsigned long data) return; } /* last bunch mode command time out */ + + /* + * From here to dummy request finish sps request and set owner back + * to none, we disable interrupt. + * So it won't get preempted or interrupted. If bam inerrupts happen + * between, and completion callback gets called from BAM, a new + * request may be issued by the client driver. Deadlock may happen. + */ + local_irq_save(flags); if (cmpxchg(&pce_dev->owner, QCE_OWNER_NONE, QCE_OWNER_TIMEOUT) != QCE_OWNER_NONE) { + local_irq_restore(flags); mod_timer(&(pce_dev->timer), (jiffies + DELAY_IN_JIFFIES)); return; } - del_timer(&(pce_dev->timer)); - pce_dev->mode = IN_INTERRUPT_MODE; - pce_dev->qce_stats.no_of_timeouts++; - pr_debug("pcedev %d mode switch to INTR\n", pce_dev->dev_no); ret = qce_dummy_req(pce_dev); if (ret) pr_warn("pcedev %d: Failed to insert dummy req\n", pce_dev->dev_no); cmpxchg(&pce_dev->owner, QCE_OWNER_TIMEOUT, QCE_OWNER_NONE); + pce_dev->mode = IN_INTERRUPT_MODE; + local_irq_restore(flags); + + del_timer(&(pce_dev->timer)); + pce_dev->qce_stats.no_of_timeouts++; + pr_debug("pcedev %d mode switch to INTR\n", pce_dev->dev_no); } void qce_get_driver_stats(void *handle) diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index e63f061175ad..e2099c4e7877 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1234,44 +1234,6 @@ static int qcedev_vbuf_ablk_cipher(struct qcedev_async_req *areq, struct qcedev_cipher_op_req *saved_req; struct qcedev_cipher_op_req *creq = &areq->cipher_op_req; - /* Verify Source Address's */ - for (i = 0; i < areq->cipher_op_req.entries; i++) - if (!access_ok(VERIFY_READ, - (void __user *)areq->cipher_op_req.vbuf.src[i].vaddr, - areq->cipher_op_req.vbuf.src[i].len)) - return -EFAULT; - - /* Verify Destination Address's */ - if (creq->in_place_op != 1) { - for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) { - if ((areq->cipher_op_req.vbuf.dst[i].vaddr != 0) && - (total < creq->data_len)) { - if (!access_ok(VERIFY_WRITE, - (void __user *)creq->vbuf.dst[i].vaddr, - creq->vbuf.dst[i].len)) { - pr_err("%s:DST WR_VERIFY err %d=0x%lx\n", - __func__, i, (uintptr_t) - creq->vbuf.dst[i].vaddr); - return -EFAULT; - } - total += creq->vbuf.dst[i].len; - } - } - } else { - for (i = 0, total = 0; i < creq->entries; i++) { - if (total < creq->data_len) { - if (!access_ok(VERIFY_WRITE, - (void __user *)creq->vbuf.src[i].vaddr, - creq->vbuf.src[i].len)) { - pr_err("%s:SRC WR_VERIFY err %d=0x%lx\n", - __func__, i, (uintptr_t) - creq->vbuf.src[i].vaddr); - return -EFAULT; - } - total += creq->vbuf.src[i].len; - } - } - } total = 0; if (areq->cipher_op_req.mode == QCEDEV_AES_MODE_CTR) @@ -1569,6 +1531,36 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, __func__, total, req->data_len); goto error; } + /* Verify Source Address's */ + for (i = 0, total = 0; i < req->entries; i++) { + if (total < req->data_len) { + if (!access_ok(VERIFY_READ, + (void __user *)req->vbuf.src[i].vaddr, + req->vbuf.src[i].len)) { + pr_err("%s:SRC RD_VERIFY err %d=0x%lx\n", + __func__, i, (uintptr_t) + req->vbuf.src[i].vaddr); + goto error; + } + total += req->vbuf.src[i].len; + } + } + + /* Verify Destination Address's */ + for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) { + if ((req->vbuf.dst[i].vaddr != 0) && + (total < req->data_len)) { + if (!access_ok(VERIFY_WRITE, + (void __user *)req->vbuf.dst[i].vaddr, + req->vbuf.dst[i].len)) { + pr_err("%s:DST WR_VERIFY err %d=0x%lx\n", + __func__, i, (uintptr_t) + req->vbuf.dst[i].vaddr); + goto error; + } + total += req->vbuf.dst[i].len; + } + } return 0; error: return -EINVAL; diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index bc1c5f6dd4bd..844a8ad666a9 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -806,7 +806,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, struct devfreq *df = to_devfreq(dev); int ret; char str_governor[DEVFREQ_NAME_LEN + 1]; - struct devfreq_governor *governor; + const struct devfreq_governor *governor, *prev_gov; ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor); if (ret != 1) @@ -831,12 +831,21 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, goto out; } } + prev_gov = df->governor; df->governor = governor; strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN); ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); - if (ret) + if (ret) { dev_warn(dev, "%s: Governor %s not started(%d)\n", __func__, df->governor->name, ret); + if (prev_gov) { + df->governor = prev_gov; + strncpy(df->governor_name, prev_gov->name, + DEVFREQ_NAME_LEN); + df->governor->event_handler(df, DEVFREQ_GOV_START, + NULL); + } + } out: mutex_unlock(&devfreq_list_lock); diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c index 182c6074985e..483bb9338ac3 100644 --- a/drivers/gpio/qpnp-pin.c +++ b/drivers/gpio/qpnp-pin.c @@ -827,9 +827,17 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) if (WARN_ON(!q_spec)) return -ENODEV; + if (is_gpio_lv_mv(q_spec)) { + mask = Q_REG_LV_MV_MODE_SEL_MASK; + shift = Q_REG_LV_MV_MODE_SEL_SHIFT; + } else { + mask = Q_REG_MODE_SEL_MASK; + shift = Q_REG_MODE_SEL_SHIFT; + } + /* gpio val is from RT status iff input is enabled */ - if ((q_spec->regs[Q_REG_I_MODE_CTL] & Q_REG_MODE_SEL_MASK) - == QPNP_PIN_MODE_DIG_IN) { + if (q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL], shift, mask) + == QPNP_PIN_MODE_DIG_IN) { rc = regmap_read(q_chip->regmap, Q_REG_ADDR(q_spec, Q_REG_STATUS1), &val); buf[0] = (u8)val; diff --git a/drivers/gpu/msm/a5xx_reg.h b/drivers/gpu/msm/a5xx_reg.h index f3b4e6622043..436b6949c414 100644 --- a/drivers/gpu/msm/a5xx_reg.h +++ b/drivers/gpu/msm/a5xx_reg.h @@ -608,6 +608,7 @@ #define A5XX_PC_PERFCTR_PC_SEL_7 0xD17 /* HLSQ registers */ +#define A5XX_HLSQ_DBG_ECO_CNTL 0xE04 #define A5XX_HLSQ_ADDR_MODE_CNTL 0xE05 #define A5XX_HLSQ_PERFCTR_HLSQ_SEL_0 0xE10 #define A5XX_HLSQ_PERFCTR_HLSQ_SEL_1 0xE11 @@ -632,6 +633,7 @@ #define A5XX_VFD_PERFCTR_VFD_SEL_7 0xE57 /* VPC registers */ +#define A5XX_VPC_DBG_ECO_CNTL 0xE60 #define A5XX_VPC_ADDR_MODE_CNTL 0xE61 #define A5XX_VPC_PERFCTR_VPC_SEL_0 0xE64 #define A5XX_VPC_PERFCTR_VPC_SEL_1 0xE65 diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 3615be45b6d9..a02ed40ba9d5 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -269,7 +269,7 @@ static const struct adreno_gpu_core adreno_gpulist[] = { .patchid = ANY_ID, .features = ADRENO_PREEMPTION | ADRENO_64BIT | ADRENO_CONTENT_PROTECTION | - ADRENO_GPMU | ADRENO_SPTP_PC, + ADRENO_GPMU | ADRENO_SPTP_PC | ADRENO_LM, .pm4fw_name = "a530_pm4.fw", .pfpfw_name = "a530_pfp.fw", .zap_name = "a540_zap", diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 6160aa567fbf..11226472d801 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -843,6 +843,8 @@ static struct { { ADRENO_QUIRK_FAULT_DETECT_MASK, "qcom,gpu-quirk-fault-detect-mask" }, { ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING, "qcom,gpu-quirk-dp2clockgating-disable" }, + { ADRENO_QUIRK_DISABLE_LMLOADKILL, + "qcom,gpu-quirk-lmloadkill-disable" }, }; static int adreno_of_get_power(struct adreno_device *adreno_dev, @@ -2109,8 +2111,6 @@ static int adreno_soft_reset(struct kgsl_device *device) adreno_support_64bit(adreno_dev)) gpudev->enable_64bit(adreno_dev); - /* Restore physical performance counter values after soft reset */ - adreno_perfcounter_restore(adreno_dev); /* Reinitialize the GPU */ gpudev->start(adreno_dev); @@ -2137,6 +2137,9 @@ static int adreno_soft_reset(struct kgsl_device *device) set_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv); } + /* Restore physical performance counter values after soft reset */ + adreno_perfcounter_restore(adreno_dev); + return ret; } @@ -2291,9 +2294,9 @@ static void adreno_read(struct kgsl_device *device, void __iomem *base, unsigned int mem_len) { - unsigned int __iomem *reg; + void __iomem *reg; BUG_ON(offsetwords*sizeof(uint32_t) >= mem_len); - reg = (unsigned int __iomem *)(base + (offsetwords << 2)); + reg = (base + (offsetwords << 2)); if (!in_interrupt()) kgsl_pre_hwaccess(device); @@ -2333,7 +2336,7 @@ static void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords, unsigned int value) { - unsigned int __iomem *reg; + void __iomem *reg; BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len); @@ -2343,7 +2346,7 @@ static void adreno_regwrite(struct kgsl_device *device, trace_kgsl_regwrite(device, offsetwords, value); kgsl_cffdump_regwrite(device, offsetwords << 2, value); - reg = (unsigned int __iomem *)(device->reg_virt + (offsetwords << 2)); + reg = (device->reg_virt + (offsetwords << 2)); /*ensure previous writes post before this one, * i.e. act like normal writel() */ diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index a2af26c81f50..d81142db5b58 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -123,6 +123,8 @@ #define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(3) /* Disable RB sampler datapath clock gating optimization */ #define ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING BIT(4) +/* Disable local memory(LM) feature to avoid corner case error */ +#define ADRENO_QUIRK_DISABLE_LMLOADKILL BIT(5) /* Flags to control command packet settings */ #define KGSL_CMD_FLAGS_NONE 0 diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 3f5a9c6318f6..423071811b43 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -151,6 +151,43 @@ static const unsigned int _a3xx_pwron_fixup_fs_instructions[] = { 0x00000000, 0x03000000, 0x00000000, 0x00000000, }; +static void a3xx_efuse_speed_bin(struct adreno_device *adreno_dev) +{ + unsigned int val; + unsigned int speed_bin[3]; + struct kgsl_device *device = &adreno_dev->dev; + + if (of_property_read_u32_array(device->pdev->dev.of_node, + "qcom,gpu-speed-bin", speed_bin, 3)) + return; + + adreno_efuse_read_u32(adreno_dev, speed_bin[0], &val); + + adreno_dev->speed_bin = (val & speed_bin[1]) >> speed_bin[2]; +} + +static const struct { + int (*check)(struct adreno_device *adreno_dev); + void (*func)(struct adreno_device *adreno_dev); +} a3xx_efuse_funcs[] = { + { adreno_is_a306a, a3xx_efuse_speed_bin }, +}; + +static void a3xx_check_features(struct adreno_device *adreno_dev) +{ + unsigned int i; + + if (adreno_efuse_map(adreno_dev)) + return; + + for (i = 0; i < ARRAY_SIZE(a3xx_efuse_funcs); i++) { + if (a3xx_efuse_funcs[i].check(adreno_dev)) + a3xx_efuse_funcs[i].func(adreno_dev); + } + + adreno_efuse_unmap(adreno_dev); +} + /** * _a3xx_pwron_fixup() - Initialize a special command buffer to run a * post-power collapse shader workaround @@ -604,6 +641,9 @@ static void a3xx_platform_setup(struct adreno_device *adreno_dev) gpudev->vbif_xin_halt_ctrl0_mask = A30X_VBIF_XIN_HALT_CTRL0_MASK; } + + /* Check efuse bits for various capabilties */ + a3xx_check_features(adreno_dev); } static int a3xx_send_me_init(struct adreno_device *adreno_dev, diff --git a/drivers/gpu/msm/adreno_a4xx_preempt.c b/drivers/gpu/msm/adreno_a4xx_preempt.c index 4087ac60c89e..ef837dc4b7ea 100644 --- a/drivers/gpu/msm/adreno_a4xx_preempt.c +++ b/drivers/gpu/msm/adreno_a4xx_preempt.c @@ -146,6 +146,8 @@ static int a4xx_submit_preempt_token(struct adreno_ringbuffer *rb, &ptname, PT_INFO_OFFSET(current_rb_ptname)); pt = kgsl_mmu_get_pt_from_ptname(&(device->mmu), ptname); + if (IS_ERR_OR_NULL(pt)) + return (pt == NULL) ? -ENOENT : PTR_ERR(pt); /* set the ringbuffer for incoming RB */ pt_switch_sizedwords = adreno_iommu_set_pt_generate_cmds(incoming_rb, diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 860f6d2925f1..f652e955b07c 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -196,6 +196,8 @@ static void a5xx_platform_setup(struct adreno_device *adreno_dev) /* A510 has 3 XIN ports in VBIF */ gpudev->vbif_xin_halt_ctrl0_mask = A510_VBIF_XIN_HALT_CTRL0_MASK; + } else if (adreno_is_a540(adreno_dev)) { + gpudev->snapshot_data->sect_sizes->cp_merciu = 1024; } /* Calculate SP local and private mem addresses */ @@ -1534,12 +1536,12 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev, const char *name, struct clk *clk) { if (adreno_is_a540(adreno_dev)) { - if (!strcmp(name, "mem_iface_clk")) - clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); - clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); - if (!strcmp(name, "core_clk")) { + if (!strcmp(name, "mem_iface_clk")) { clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); + } else if (!strcmp(name, "core_clk")) { + clk_set_flags(clk, CLKFLAG_RETAIN_PERIPH); + clk_set_flags(clk, CLKFLAG_RETAIN_MEM); } } } @@ -1781,11 +1783,11 @@ static void a5xx_start(struct adreno_device *adreno_dev) set_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv); gpudev->irq->mask |= (1 << A5XX_INT_MISC_HANG_DETECT); /* - * Set hang detection threshold to 1 million cycles - * (0xFFFF*16) + * Set hang detection threshold to 4 million cycles + * (0x3FFFF*16) */ kgsl_regwrite(device, A5XX_RBBM_INTERFACE_HANG_INT_CNTL, - (1 << 30) | 0xFFFF); + (1 << 30) | 0x3FFFF); } @@ -1944,6 +1946,16 @@ static void a5xx_start(struct adreno_device *adreno_dev) } + /* + * VPC corner case with local memory load kill leads to corrupt + * internal state. Normal Disable does not work for all a5x chips. + * So do the following setting to disable it. + */ + if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_DISABLE_LMLOADKILL)) { + kgsl_regrmw(device, A5XX_VPC_DBG_ECO_CNTL, 0, 0x1 << 23); + kgsl_regrmw(device, A5XX_HLSQ_DBG_ECO_CNTL, 0x1 << 18, 0); + } + a5xx_preemption_start(adreno_dev); a5xx_protect_init(adreno_dev); } diff --git a/drivers/gpu/msm/adreno_perfcounter.c b/drivers/gpu/msm/adreno_perfcounter.c index 42f8119ad8b4..f5f99c3ebb4a 100644 --- a/drivers/gpu/msm/adreno_perfcounter.c +++ b/drivers/gpu/msm/adreno_perfcounter.c @@ -522,12 +522,18 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, if (empty == -1) return -EBUSY; + /* initialize the new counter */ + group->regs[empty].countable = countable; + /* enable the new counter */ ret = adreno_perfcounter_enable(adreno_dev, groupid, empty, countable); - if (ret) + if (ret) { + /* Put back the perfcounter */ + if (!(group->flags & ADRENO_PERFCOUNTER_GROUP_FIXED)) + group->regs[empty].countable = + KGSL_PERFCOUNTER_NOT_USED; return ret; - /* initialize the new counter */ - group->regs[empty].countable = countable; + } /* set initial kernel and user count */ if (flags & PERFCOUNTER_FLAG_KERNEL) { @@ -720,10 +726,22 @@ static int _perfcounter_enable_default(struct adreno_device *adreno_dev, /* wait for the above commands submitted to complete */ ret = adreno_ringbuffer_waittimestamp(rb, rb->timestamp, ADRENO_IDLE_TIMEOUT); - if (ret) - KGSL_DRV_ERR(device, - "Perfcounter %u/%u/%u start via commands failed %d\n", - group, counter, countable, ret); + if (ret) { + /* + * If we were woken up because of cancelling rb events + * either due to soft reset or adreno_stop, ignore the + * error and return 0 here. The perfcounter is already + * set up in software and it will be programmed in + * hardware when we wake up or come up after soft reset, + * by adreno_perfcounter_restore. + */ + if (ret == -EAGAIN) + ret = 0; + else + KGSL_DRV_ERR(device, + "Perfcounter %u/%u/%u start via commands failed %d\n", + group, counter, countable, ret); + } } else { /* Select the desired perfcounter */ kgsl_regwrite(device, reg->select, countable); diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index fe0715629825..554eb2dffae4 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2507,6 +2507,8 @@ static int kgsl_setup_dma_buf(struct kgsl_device *device, meta->dmabuf = dmabuf; meta->attach = attach; + attach->priv = entry; + entry->priv_data = meta; entry->memdesc.pagetable = pagetable; entry->memdesc.size = 0; @@ -2557,6 +2559,45 @@ out: } #endif +#ifdef CONFIG_DMA_SHARED_BUFFER +void kgsl_get_egl_counts(struct kgsl_mem_entry *entry, + int *egl_surface_count, int *egl_image_count) +{ + struct kgsl_dma_buf_meta *meta = entry->priv_data; + struct dma_buf *dmabuf = meta->dmabuf; + struct dma_buf_attachment *mem_entry_buf_attachment = meta->attach; + struct device *buf_attachment_dev = mem_entry_buf_attachment->dev; + struct dma_buf_attachment *attachment = NULL; + + mutex_lock(&dmabuf->lock); + list_for_each_entry(attachment, &dmabuf->attachments, node) { + struct kgsl_mem_entry *scan_mem_entry = NULL; + + if (attachment->dev != buf_attachment_dev) + continue; + + scan_mem_entry = attachment->priv; + if (!scan_mem_entry) + continue; + + switch (kgsl_memdesc_get_memtype(&scan_mem_entry->memdesc)) { + case KGSL_MEMTYPE_EGL_SURFACE: + (*egl_surface_count)++; + break; + case KGSL_MEMTYPE_EGL_IMAGE: + (*egl_image_count)++; + break; + } + } + mutex_unlock(&dmabuf->lock); +} +#else +void kgsl_get_egl_counts(struct kgsl_mem_entry *entry, + int *egl_surface_count, int *egl_image_count) +{ +} +#endif + long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { @@ -3891,7 +3932,7 @@ kgsl_mmap_memstore(struct kgsl_device *device, struct vm_area_struct *vma) return -EINVAL; } - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); result = remap_pfn_range(vma, vma->vm_start, device->memstore.physaddr >> PAGE_SHIFT, diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 826c4edb3582..fbf9197b6d1b 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -435,6 +435,9 @@ long kgsl_ioctl_sparse_unbind(struct kgsl_device_private *dev_priv, void kgsl_mem_entry_destroy(struct kref *kref); +void kgsl_get_egl_counts(struct kgsl_mem_entry *entry, + int *egl_surface_count, int *egl_image_count); + struct kgsl_mem_entry * __must_check kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr); diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c index 2f293e4da398..7758fc956055 100644 --- a/drivers/gpu/msm/kgsl_debugfs.c +++ b/drivers/gpu/msm/kgsl_debugfs.c @@ -125,13 +125,15 @@ static char get_cacheflag(const struct kgsl_memdesc *m) } -static int print_mem_entry(int id, void *ptr, void *data) +static int print_mem_entry(void *data, void *ptr) { struct seq_file *s = data; struct kgsl_mem_entry *entry = ptr; char flags[10]; char usage[16]; struct kgsl_memdesc *m = &entry->memdesc; + unsigned int usermem_type = kgsl_memdesc_usermem_type(m); + int egl_surface_count = 0, egl_image_count = 0; if (m->flags & KGSL_MEMFLAGS_SPARSE_VIRT) return 0; @@ -149,12 +151,17 @@ static int print_mem_entry(int id, void *ptr, void *data) kgsl_get_memory_usage(usage, sizeof(usage), m->flags); - seq_printf(s, "%pK %pK %16llu %5d %9s %10s %16s %5d %16llu", + if (usermem_type == KGSL_MEM_ENTRY_ION) + kgsl_get_egl_counts(entry, &egl_surface_count, + &egl_image_count); + + seq_printf(s, "%pK %pK %16llu %5d %9s %10s %16s %5d %16llu %6d %6d", (uint64_t *)(uintptr_t) m->gpuaddr, (unsigned long *) m->useraddr, m->size, entry->id, flags, - memtype_str(kgsl_memdesc_usermem_type(m)), - usage, (m->sgt ? m->sgt->nents : 0), m->mapsize); + memtype_str(usermem_type), + usage, (m->sgt ? m->sgt->nents : 0), m->mapsize, + egl_surface_count, egl_image_count); if (entry->metadata[0] != 0) seq_printf(s, " %s", entry->metadata); @@ -164,25 +171,83 @@ static int print_mem_entry(int id, void *ptr, void *data) return 0; } -static int process_mem_print(struct seq_file *s, void *unused) +static struct kgsl_mem_entry *process_mem_seq_find(struct seq_file *s, + void *ptr, loff_t pos) { + struct kgsl_mem_entry *entry = ptr; struct kgsl_process_private *private = s->private; + int id = 0; + loff_t temp_pos = 1; - seq_printf(s, "%16s %16s %16s %5s %9s %10s %16s %5s %16s\n", - "gpuaddr", "useraddr", "size", "id", "flags", "type", - "usage", "sglen", "mapsize"); + if (entry != SEQ_START_TOKEN) + id = entry->id + 1; spin_lock(&private->mem_lock); - idr_for_each(&private->mem_idr, print_mem_entry, s); + for (entry = idr_get_next(&private->mem_idr, &id); entry; + id++, entry = idr_get_next(&private->mem_idr, &id), + temp_pos++) { + if (temp_pos == pos && kgsl_mem_entry_get(entry)) { + spin_unlock(&private->mem_lock); + goto found; + } + } spin_unlock(&private->mem_lock); - return 0; + entry = NULL; +found: + if (ptr != SEQ_START_TOKEN) + kgsl_mem_entry_put(ptr); + + return entry; +} + +static void *process_mem_seq_start(struct seq_file *s, loff_t *pos) +{ + loff_t seq_file_offset = *pos; + + if (seq_file_offset == 0) + return SEQ_START_TOKEN; + else + return process_mem_seq_find(s, SEQ_START_TOKEN, + seq_file_offset); +} + +static void process_mem_seq_stop(struct seq_file *s, void *ptr) +{ + if (ptr && ptr != SEQ_START_TOKEN) + kgsl_mem_entry_put(ptr); } +static void *process_mem_seq_next(struct seq_file *s, void *ptr, + loff_t *pos) +{ + ++*pos; + return process_mem_seq_find(s, ptr, 1); +} + +static int process_mem_seq_show(struct seq_file *s, void *ptr) +{ + if (ptr == SEQ_START_TOKEN) { + seq_printf(s, "%16s %16s %16s %5s %9s %10s %16s %5s %16s %6s %6s\n", + "gpuaddr", "useraddr", "size", "id", "flags", "type", + "usage", "sglen", "mapsize", "eglsrf", "eglimg"); + return 0; + } else + return print_mem_entry(s, ptr); +} + +static const struct seq_operations process_mem_seq_fops = { + .start = process_mem_seq_start, + .stop = process_mem_seq_stop, + .next = process_mem_seq_next, + .show = process_mem_seq_show, +}; + static int process_mem_open(struct inode *inode, struct file *file) { int ret; pid_t pid = (pid_t) (unsigned long) inode->i_private; + struct seq_file *s = NULL; struct kgsl_process_private *private = NULL; private = kgsl_process_private_find(pid); @@ -190,9 +255,13 @@ static int process_mem_open(struct inode *inode, struct file *file) if (!private) return -ENODEV; - ret = single_open(file, process_mem_print, private); + ret = seq_open(file, &process_mem_seq_fops); if (ret) kgsl_process_private_put(private); + else { + s = file->private_data; + s->private = private; + } return ret; } @@ -205,7 +274,7 @@ static int process_mem_release(struct inode *inode, struct file *file) if (private) kgsl_process_private_put(private); - return single_release(inode, file); + return seq_release(inode, file); } static const struct file_operations process_mem_fops = { diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index ba564b2851f9..f516b7cd245a 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -390,6 +390,13 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable, if (!memdesc->gpuaddr) return -EINVAL; + if (!(memdesc->flags & (KGSL_MEMFLAGS_SPARSE_VIRT | + KGSL_MEMFLAGS_SPARSE_PHYS))) { + /* Only global mappings should be mapped multiple times */ + if (!kgsl_memdesc_is_global(memdesc) && + (KGSL_MEMDESC_MAPPED & memdesc->priv)) + return -EINVAL; + } size = kgsl_memdesc_footprint(memdesc); @@ -403,6 +410,9 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable, atomic_inc(&pagetable->stats.entries); KGSL_STATS_ADD(size, &pagetable->stats.mapped, &pagetable->stats.max_mapped); + + /* This is needed for non-sparse mappings */ + memdesc->priv |= KGSL_MEMDESC_MAPPED; } return 0; @@ -455,6 +465,13 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, if (memdesc->size == 0) return -EINVAL; + if (!(memdesc->flags & (KGSL_MEMFLAGS_SPARSE_VIRT | + KGSL_MEMFLAGS_SPARSE_PHYS))) { + /* Only global mappings should be mapped multiple times */ + if (!(KGSL_MEMDESC_MAPPED & memdesc->priv)) + return -EINVAL; + } + if (PT_OP_VALID(pagetable, mmu_unmap)) { uint64_t size; @@ -464,6 +481,9 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, atomic_dec(&pagetable->stats.entries); atomic_long_sub(size, &pagetable->stats.mapped); + + if (!kgsl_memdesc_is_global(memdesc)) + memdesc->priv &= ~KGSL_MEMDESC_MAPPED; } return ret; diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 72895c18119f..618e9e9a33a3 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -574,12 +574,11 @@ int kgsl_cache_range_op(struct kgsl_memdesc *memdesc, uint64_t offset, void *addr = (memdesc->hostptr) ? memdesc->hostptr : (void *) memdesc->useraddr; - /* Make sure that size is non-zero */ - if (!size) + if (size == 0 || size > UINT_MAX) return -EINVAL; - /* Make sure that the offset + size isn't bigger than we can handle */ - if ((offset + size) > ULONG_MAX) + /* Make sure that the offset + size does not overflow */ + if ((offset + size < offset) || (offset + size < size)) return -ERANGE; /* Make sure the offset + size do not overflow the address */ diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index fb95a83007b7..cc8d957e0581 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -1545,8 +1545,8 @@ static ssize_t mem_size_store(struct device *dev, mutex_lock(&drvdata->mem_lock); if (kstrtoul(buf, 16, &val)) { - return -EINVAL; mutex_unlock(&drvdata->mem_lock); + return -EINVAL; } drvdata->mem_size = val; diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c index ebb49230d4d7..e08de7a808eb 100644 --- a/drivers/iio/adc/qcom-rradc.c +++ b/drivers/iio/adc/qcom-rradc.c @@ -165,7 +165,8 @@ #define FG_ADC_RR_CHG_THRESHOLD_SCALE 4 #define FG_ADC_RR_VOLT_INPUT_FACTOR 8 -#define FG_ADC_RR_CURR_INPUT_FACTOR 2 +#define FG_ADC_RR_CURR_INPUT_FACTOR 2000 +#define FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL 1886 #define FG_ADC_SCALE_MILLI_FACTOR 1000 #define FG_ADC_KELVINMIL_CELSIUSMIL 273150 @@ -323,12 +324,20 @@ static int rradc_post_process_curr(struct rradc_chip *chip, struct rradc_chan_prop *prop, u16 adc_code, int *result_ua) { - int64_t ua = 0; + int64_t ua = 0, scale = 0; - /* 0.5 V/A; 2.5V ADC full scale */ - ua = ((int64_t)adc_code * FG_ADC_RR_CURR_INPUT_FACTOR); + if (!prop) + return -EINVAL; + + if (prop->channel == RR_ADC_USBIN_I) + scale = FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL; + else + scale = FG_ADC_RR_CURR_INPUT_FACTOR; + + /* scale * V/A; 2.5V ADC full scale */ + ua = ((int64_t)adc_code * scale); ua *= (FG_ADC_RR_FS_VOLTAGE_MV * FG_ADC_SCALE_MILLI_FACTOR); - ua = div64_s64(ua, FG_MAX_ADC_READINGS); + ua = div64_s64(ua, (FG_MAX_ADC_READINGS * 1000)); *result_ua = ua; return 0; diff --git a/drivers/iio/adc/qcom-tadc.c b/drivers/iio/adc/qcom-tadc.c index 3cc2694f9a03..4a56847a43e7 100644 --- a/drivers/iio/adc/qcom-tadc.c +++ b/drivers/iio/adc/qcom-tadc.c @@ -398,7 +398,7 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) } for (i = 0; i < TADC_NUM_CH; i++) - adc[i] = val[i * 2] | val[i * 2 + 1] << BITS_PER_BYTE; + adc[i] = (s16)(val[i * 2] | (u16)val[i * 2 + 1] << 8); return jiffies_to_msecs(timeout - timeleft); } diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fda10abae58a..eac6d07e6097 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -528,6 +528,8 @@ static bool arm_smmu_is_static_cb(struct arm_smmu_device *smmu); static bool arm_smmu_is_slave_side_secure(struct arm_smmu_domain *smmu_domain); static bool arm_smmu_has_secure_vmid(struct arm_smmu_domain *smmu_domain); +static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain); + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -1604,7 +1606,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, /* SCTLR */ reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_EAE_SBOP; - if (!(smmu_domain->attributes & (1 << DOMAIN_ATTR_S1_BYPASS)) || + if ((!(smmu_domain->attributes & (1 << DOMAIN_ATTR_S1_BYPASS)) && + !(smmu_domain->attributes & (1 << DOMAIN_ATTR_EARLY_MAP))) || !stage1) reg |= SCTLR_M; if (stage1) @@ -1651,7 +1654,7 @@ static void arm_smmu_secure_domain_unlock(struct arm_smmu_domain *smmu_domain) static unsigned long arm_smmu_pgtbl_lock(struct arm_smmu_domain *smmu_domain) { - unsigned long flags; + unsigned long flags = 0; if (arm_smmu_is_slave_side_secure(smmu_domain)) mutex_lock(&smmu_domain->pgtbl_mutex_lock); @@ -3043,6 +3046,11 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain, ret = 0; break; } + case DOMAIN_ATTR_EARLY_MAP: + *((int *)data) = !!(smmu_domain->attributes + & (1 << DOMAIN_ATTR_EARLY_MAP)); + ret = 0; + break; default: ret = -ENODEV; break; @@ -3148,6 +3156,24 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain, smmu_domain->attributes |= 1 << DOMAIN_ATTR_FAST; ret = 0; break; + case DOMAIN_ATTR_EARLY_MAP: { + int early_map = *((int *)data); + + ret = 0; + if (early_map) { + smmu_domain->attributes |= + 1 << DOMAIN_ATTR_EARLY_MAP; + } else { + if (smmu_domain->smmu) + ret = arm_smmu_enable_s1_translations( + smmu_domain); + + if (!ret) + smmu_domain->attributes &= + ~(1 << DOMAIN_ATTR_EARLY_MAP); + } + break; + } default: ret = -ENODEV; break; @@ -3158,6 +3184,28 @@ out_unlock: return ret; } + +static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain) +{ + struct arm_smmu_cfg *cfg = &smmu_domain->cfg; + struct arm_smmu_device *smmu = smmu_domain->smmu; + void __iomem *cb_base; + u32 reg; + int ret; + + cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx); + ret = arm_smmu_enable_clocks(smmu); + if (ret) + return ret; + + reg = readl_relaxed(cb_base + ARM_SMMU_CB_SCTLR); + reg |= SCTLR_M; + + writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR); + arm_smmu_disable_clocks(smmu); + return ret; +} + static int arm_smmu_dma_supported(struct iommu_domain *domain, struct device *dev, u64 mask) { diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c index 3b54fd4a77e6..7b0c1ae5a48d 100644 --- a/drivers/iommu/iommu-debug.c +++ b/drivers/iommu/iommu-debug.c @@ -70,6 +70,8 @@ static const char *iommu_debug_attr_to_string(enum iommu_attr attr) return "DOMAIN_ATTR_S1_BYPASS"; case DOMAIN_ATTR_FAST: return "DOMAIN_ATTR_FAST"; + case DOMAIN_ATTR_EARLY_MAP: + return "DOMAIN_ATTR_EARLY_MAP"; default: return "Unknown attr!"; } diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index 51fd79f101c8..ea3d0eed47e1 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -49,6 +49,10 @@ #define FLASH_LED_REG_VPH_DROOP_THRESHOLD(base) (base + 0x61) #define FLASH_LED_REG_VPH_DROOP_DEBOUNCE(base) (base + 0x62) #define FLASH_LED_REG_ILED_GRT_THRSH(base) (base + 0x67) +#define FLASH_LED_REG_LED1N2_ICLAMP_LOW(base) (base + 0x68) +#define FLASH_LED_REG_LED1N2_ICLAMP_MID(base) (base + 0x69) +#define FLASH_LED_REG_LED3_ICLAMP_LOW(base) (base + 0x6A) +#define FLASH_LED_REG_LED3_ICLAMP_MID(base) (base + 0x6B) #define FLASH_LED_REG_MITIGATION_SEL(base) (base + 0x6E) #define FLASH_LED_REG_MITIGATION_SW(base) (base + 0x6F) #define FLASH_LED_REG_LMH_LEVEL(base) (base + 0x70) @@ -173,18 +177,12 @@ struct flash_node_data { bool led_on; }; -struct flash_regulator_data { - struct regulator *vreg; - const char *reg_name; - u32 max_volt_uv; -}; struct flash_switch_data { struct platform_device *pdev; + struct regulator *vreg; struct led_classdev cdev; - struct flash_regulator_data *reg_data; int led_mask; - int num_regulators; bool regulator_on; bool enabled; }; @@ -202,6 +200,10 @@ struct flash_led_platform_data { int rpara_uohm; int lmh_rbatt_threshold_uohm; int lmh_ocv_threshold_uv; + u32 led1n2_iclamp_low_ma; + u32 led1n2_iclamp_mid_ma; + u32 led3_iclamp_low_ma; + u32 led3_iclamp_mid_ma; u8 isc_delay; u8 warmup_delay; u8 current_derate_en_cfg; @@ -385,6 +387,46 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) if (rc < 0) return rc; + if (led->pdata->led1n2_iclamp_low_ma) { + val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_low_ma, + led->fnode[0].ires_ua); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LED1N2_ICLAMP_LOW(led->base), + FLASH_LED_CURRENT_MASK, val); + if (rc < 0) + return rc; + } + + if (led->pdata->led1n2_iclamp_mid_ma) { + val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_mid_ma, + led->fnode[0].ires_ua); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LED1N2_ICLAMP_MID(led->base), + FLASH_LED_CURRENT_MASK, val); + if (rc < 0) + return rc; + } + + if (led->pdata->led3_iclamp_low_ma) { + val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_low_ma, + led->fnode[3].ires_ua); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LED3_ICLAMP_LOW(led->base), + FLASH_LED_CURRENT_MASK, val); + if (rc < 0) + return rc; + } + + if (led->pdata->led3_iclamp_mid_ma) { + val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_mid_ma, + led->fnode[3].ires_ua); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LED3_ICLAMP_MID(led->base), + FLASH_LED_CURRENT_MASK, val); + if (rc < 0) + return rc; + } + return 0; } @@ -426,34 +468,27 @@ static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode, static int qpnp_flash_led_regulator_enable(struct qpnp_flash_led *led, struct flash_switch_data *snode, bool on) { - int i, rc = 0; + int rc = 0; + + if (!snode || !snode->vreg) + return 0; if (snode->regulator_on == on) return 0; - if (on == false) { - i = snode->num_regulators; - goto out; - } + if (on) + rc = regulator_enable(snode->vreg); + else + rc = regulator_disable(snode->vreg); - for (i = 0; i < snode->num_regulators; i++) { - rc = regulator_enable(snode->reg_data[i].vreg); - if (rc < 0) { - dev_err(&led->pdev->dev, - "regulator enable failed, rc=%d\n", rc); - goto out; - } + if (rc < 0) { + dev_err(&led->pdev->dev, "regulator_%s failed, rc=%d\n", + on ? "enable" : "disable", rc); + return rc; } - snode->regulator_on = true; - return rc; - -out: - while (i--) - regulator_disable(snode->reg_data[i].vreg); - - snode->regulator_on = false; - return rc; + snode->regulator_on = on ? true : false; + return 0; } static int get_property_from_fg(struct qpnp_flash_led *led, @@ -835,7 +870,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) u8 val, mask; if (snode->enabled == on) { - dev_warn(&led->pdev->dev, "Switch node is already %s!\n", + dev_dbg(&led->pdev->dev, "Switch node is already %s!\n", on ? "enabled" : "disabled"); return 0; } @@ -1050,6 +1085,32 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, spin_unlock(&led->lock); } +/* sysfs show function for flash_max_current */ +static ssize_t qpnp_flash_led_max_current_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int rc; + struct flash_switch_data *snode; + struct qpnp_flash_led *led; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + snode = container_of(led_cdev, struct flash_switch_data, cdev); + led = dev_get_drvdata(&snode->pdev->dev); + + rc = qpnp_flash_led_get_max_avail_current(led); + if (rc < 0) + dev_err(&led->pdev->dev, "query max current failed, rc=%d\n", + rc); + + return snprintf(buf, PAGE_SIZE, "%d\n", rc); +} + +/* sysfs attributes exported by flash_led */ +static struct device_attribute qpnp_flash_led_attrs[] = { + __ATTR(max_current, (S_IRUGO | S_IWUSR | S_IWGRP), + qpnp_flash_led_max_current_show, NULL), +}; + static int flash_led_psy_notifier_call(struct notifier_block *nb, unsigned long ev, void *v) { @@ -1156,104 +1217,6 @@ int qpnp_flash_led_unregister_irq_notifier(struct notifier_block *nb) return atomic_notifier_chain_unregister(&irq_notifier_list, nb); } -static int qpnp_flash_led_regulator_setup(struct qpnp_flash_led *led, - struct flash_switch_data *snode, bool on) -{ - int i, rc = 0; - - if (on == false) { - i = snode->num_regulators; - goto out; - } - - for (i = 0; i < snode->num_regulators; i++) { - snode->reg_data[i].vreg = regulator_get(snode->cdev.dev, - snode->reg_data[i].reg_name); - if (IS_ERR(snode->reg_data[i].vreg)) { - rc = PTR_ERR(snode->reg_data[i].vreg); - dev_err(&led->pdev->dev, - "Failed to get regulator, rc=%d\n", rc); - goto out; - } - - if (regulator_count_voltages(snode->reg_data[i].vreg) > 0) { - rc = regulator_set_voltage(snode->reg_data[i].vreg, - snode->reg_data[i].max_volt_uv, - snode->reg_data[i].max_volt_uv); - if (rc < 0) { - dev_err(&led->pdev->dev, - "regulator set voltage failed, rc=%d\n", - rc); - regulator_put(snode->reg_data[i].vreg); - goto out; - } - } - } - - return rc; - -out: - while (i--) { - if (regulator_count_voltages(snode->reg_data[i].vreg) > 0) - regulator_set_voltage(snode->reg_data[i].vreg, 0, - snode->reg_data[i].max_volt_uv); - - regulator_put(snode->reg_data[i].vreg); - } - - return rc; -} - -static int qpnp_flash_led_regulator_parse_dt(struct qpnp_flash_led *led, - struct flash_switch_data *snode, - struct device_node *node) { - - int i = 0, rc = 0, num_regs = 0; - struct device_node *temp = NULL; - const char *temp_string; - u32 val; - - while ((temp = of_get_next_available_child(node, temp))) { - if (of_find_property(temp, "regulator-name", NULL)) - num_regs++; - } - snode->num_regulators = num_regs; - - if (snode->num_regulators == 0) - return 0; - - snode->reg_data = devm_kcalloc(&led->pdev->dev, snode->num_regulators, - sizeof(*snode->reg_data), - GFP_KERNEL); - if (!snode->reg_data) - return -ENOMEM; - - for_each_available_child_of_node(node, temp) { - rc = of_property_read_string(temp, "regulator-name", - &temp_string); - if (!rc) - snode->reg_data[i].reg_name = temp_string; - else { - dev_err(&led->pdev->dev, - "Unable to read regulator name, rc=%d\n", rc); - return rc; - } - - rc = of_property_read_u32(temp, "max-voltage-uv", &val); - if (!rc) { - snode->reg_data[i].max_volt_uv = val; - } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to read max voltage, rc=%d\n", rc); - return rc; - } - - i++; - } - - return 0; -} - static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, struct flash_node_data *fnode, struct device_node *node) { @@ -1440,7 +1403,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, fnode->pinctrl = devm_pinctrl_get(fnode->cdev.dev); if (IS_ERR_OR_NULL(fnode->pinctrl)) { - dev_warn(&led->pdev->dev, "No pinctrl defined\n"); + dev_dbg(&led->pdev->dev, "No pinctrl defined\n"); fnode->pinctrl = NULL; } else { fnode->gpio_state_active = @@ -1471,7 +1434,8 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led, struct flash_switch_data *snode, struct device_node *node) { - int rc = 0; + int rc = 0, num; + char reg_name[16], reg_sup_name[16]; rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name); if (rc < 0) { @@ -1480,6 +1444,12 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led, return rc; } + rc = sscanf(snode->cdev.name, "led:switch_%d", &num); + if (!rc) { + pr_err("No number for switch device?\n"); + return -EINVAL; + } + rc = of_property_read_string(node, "qcom,default-led-trigger", &snode->cdev.default_trigger); if (rc < 0) { @@ -1499,18 +1469,16 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led, return -EINVAL; } - rc = qpnp_flash_led_regulator_parse_dt(led, snode, node); - if (rc < 0) { - dev_err(&led->pdev->dev, - "Unable to parse regulator data, rc=%d\n", rc); - return rc; - } - - if (snode->num_regulators) { - rc = qpnp_flash_led_regulator_setup(led, snode, true); - if (rc < 0) { - dev_err(&led->pdev->dev, - "Unable to setup regulator, rc=%d\n", rc); + scnprintf(reg_name, sizeof(reg_name), "switch%d-supply", num); + if (of_find_property(led->pdev->dev.of_node, reg_name, NULL)) { + scnprintf(reg_sup_name, sizeof(reg_sup_name), "switch%d", num); + snode->vreg = devm_regulator_get(&led->pdev->dev, reg_sup_name); + if (IS_ERR_OR_NULL(snode->vreg)) { + rc = PTR_ERR(snode->vreg); + if (rc != -EPROBE_DEFER) + dev_err(&led->pdev->dev, "Failed to get regulator, rc=%d\n", + rc); + snode->vreg = NULL; return rc; } } @@ -1651,6 +1619,42 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, return rc; } + rc = of_property_read_u32(node, "qcom,led1n2-iclamp-low-ma", &val); + if (!rc) { + led->pdata->led1n2_iclamp_low_ma = val; + } else if (rc != -EINVAL) { + dev_err(&led->pdev->dev, "Unable to read led1n2_iclamp_low current, rc=%d\n", + rc); + return rc; + } + + rc = of_property_read_u32(node, "qcom,led1n2-iclamp-mid-ma", &val); + if (!rc) { + led->pdata->led1n2_iclamp_mid_ma = val; + } else if (rc != -EINVAL) { + dev_err(&led->pdev->dev, "Unable to read led1n2_iclamp_mid current, rc=%d\n", + rc); + return rc; + } + + rc = of_property_read_u32(node, "qcom,led3-iclamp-low-ma", &val); + if (!rc) { + led->pdata->led3_iclamp_low_ma = val; + } else if (rc != -EINVAL) { + dev_err(&led->pdev->dev, "Unable to read led3_iclamp_low current, rc=%d\n", + rc); + return rc; + } + + rc = of_property_read_u32(node, "qcom,led3-iclamp-mid-ma", &val); + if (!rc) { + led->pdata->led3_iclamp_mid_ma = val; + } else if (rc != -EINVAL) { + dev_err(&led->pdev->dev, "Unable to read led3_iclamp_mid current, rc=%d\n", + rc); + return rc; + } + led->pdata->vled_max_uv = FLASH_LED_VLED_MAX_DEFAULT_UV; rc = of_property_read_u32(node, "qcom,vled-max-uv", &val); if (!rc) { @@ -1785,7 +1789,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) struct device_node *node, *temp; const char *temp_string; unsigned int base; - int rc, i = 0; + int rc, i = 0, j = 0; node = pdev->dev.of_node; if (!node) { @@ -1863,26 +1867,35 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) return -ENOMEM; temp = NULL; - for (i = 0; i < led->num_fnodes; i++) { - temp = of_get_next_available_child(node, temp); - rc = qpnp_flash_led_parse_each_led_dt(led, - &led->fnode[i], temp); + i = 0; + j = 0; + for_each_available_child_of_node(node, temp) { + rc = of_property_read_string(temp, "label", &temp_string); if (rc < 0) { dev_err(&pdev->dev, - "Unable to parse flash node %d rc=%d\n", i, rc); - goto error_led_register; + "Failed to parse label, rc=%d\n", rc); + return rc; } - } - for (i = 0; i < led->num_snodes; i++) { - temp = of_get_next_available_child(node, temp); - rc = qpnp_flash_led_parse_and_register_switch(led, - &led->snode[i], temp); - if (rc < 0) { - dev_err(&pdev->dev, - "Unable to parse and register switch node, rc=%d\n", - rc); - goto error_switch_register; + if (!strcmp("flash", temp_string) || + !strcmp("torch", temp_string)) { + rc = qpnp_flash_led_parse_each_led_dt(led, + &led->fnode[i++], temp); + if (rc < 0) { + dev_err(&pdev->dev, "Unable to parse flash node %d rc=%d\n", + i, rc); + goto error_led_register; + } + } + + if (!strcmp("switch", temp_string)) { + rc = qpnp_flash_led_parse_and_register_switch(led, + &led->snode[j++], temp); + if (rc < 0) { + dev_err(&pdev->dev, "Unable to parse and register switch node, rc=%d\n", + rc); + goto error_switch_register; + } } } @@ -1946,12 +1959,36 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) goto unreg_notifier; } + for (i = 0; i < led->num_snodes; i++) { + for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) { + rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj, + &qpnp_flash_led_attrs[j].attr); + if (rc < 0) { + dev_err(&pdev->dev, "sysfs creation failed, rc=%d\n", + rc); + goto sysfs_fail; + } + } + } + spin_lock_init(&led->lock); dev_set_drvdata(&pdev->dev, led); return 0; +sysfs_fail: + for (--j; j >= 0; j--) + sysfs_remove_file(&led->snode[i].cdev.dev->kobj, + &qpnp_flash_led_attrs[j].attr); + + for (--i; i >= 0; i--) { + for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) + sysfs_remove_file(&led->snode[i].cdev.dev->kobj, + &qpnp_flash_led_attrs[j].attr); + } + + i = led->num_snodes; unreg_notifier: power_supply_unreg_notifier(&led->nb); error_switch_register: @@ -1968,20 +2005,21 @@ error_led_register: static int qpnp_flash_led_remove(struct platform_device *pdev) { struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev); - int i; + int i, j; for (i = 0; i < led->num_snodes; i++) { - if (led->snode[i].num_regulators) { - if (led->snode[i].regulator_on) - qpnp_flash_led_regulator_enable(led, - &led->snode[i], false); - qpnp_flash_led_regulator_setup(led, + for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) + sysfs_remove_file(&led->snode[i].cdev.dev->kobj, + &qpnp_flash_led_attrs[j].attr); + + if (led->snode[i].regulator_on) + qpnp_flash_led_regulator_enable(led, &led->snode[i], false); - } } while (i > 0) led_classdev_unregister(&led->snode[--i].cdev); + i = led->num_fnodes; while (i > 0) led_classdev_unregister(&led->fnode[--i].cdev); diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c index d6bb18522e0c..6c09f3820dfd 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c +++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c @@ -460,7 +460,7 @@ int msm_camera_set_clk_flags(struct clk *clk, unsigned long flags) if (!clk) return -EINVAL; - CDBG("clk : %p, flags : %ld\n", clk, flags); + CDBG("clk : %pK, flags : %ld\n", clk, flags); return clk_set_flags(clk, flags); } @@ -1040,8 +1040,11 @@ uint32_t msm_camera_unregister_bus_client(enum cam_bus_client id) mutex_destroy(&g_cv[id].lock); msm_bus_scale_unregister_client(g_cv[id].bus_client); - msm_bus_cl_clear_pdata(g_cv[id].pdata); - memset(&g_cv[id], 0, sizeof(struct msm_cam_bus_pscale_data)); + g_cv[id].bus_client = 0; + g_cv[id].num_usecases = 0; + g_cv[id].num_paths = 0; + g_cv[id].vector_index = 0; + g_cv[id].dyn_vote = 0; return 0; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index 1529e2aa740c..96f9e61578f2 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -1027,7 +1027,7 @@ static int msm_vfe40_start_fetch_engine(struct vfe_device *vfe_dev, rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0 || !buf) { - pr_err("%s: No fetch buffer rc= %d buf= %p\n", + pr_err("%s: No fetch buffer rc= %d buf= %pK\n", __func__, rc, buf); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index fdc98436a105..e8289f05d28f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -67,7 +67,7 @@ static int msm_isp_axi_create_stream(struct vfe_device *vfe_dev, } else { /* check if the stream has been added for the vfe-device */ if (stream_info->vfe_mask & (1 << vfe_dev->pdev->id)) { - pr_err("%s: stream %p/%x is already added for vfe dev %d vfe_mask %x\n", + pr_err("%s: stream %pK/%x is already added for vfe dev %d vfe_mask %x\n", __func__, stream_info, stream_info->stream_id, vfe_dev->pdev->id, stream_info->vfe_mask); return -EINVAL; @@ -1255,7 +1255,7 @@ int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg) if (vfe_idx == -ENOTTY || stream_release_cmd->stream_handle != stream_info->stream_handle[vfe_idx]) { - pr_err("%s: Invalid stream %p handle %x/%x vfe_idx %d vfe_dev %d num_isp %d\n", + pr_err("%s: Invalid stream %pK handle %x/%x vfe_idx %d vfe_dev %d num_isp %d\n", __func__, stream_info, stream_release_cmd->stream_handle, vfe_idx != -ENOTTY ? @@ -3483,7 +3483,7 @@ static int msm_isp_stream_axi_cfg_update(struct vfe_device *vfe_dev, if (stream_info->update_vfe_mask) { if (stream_info->update_vfe_mask & (1 << vfe_dev->pdev->id)) { spin_unlock_irqrestore(&stream_info->lock, flags); - pr_err("%s: Stream %p/%x Update already in progress for vfe %d\n", + pr_err("%s: Stream %pK/%x Update already in progress for vfe %d\n", __func__, stream_info, stream_info->stream_src, vfe_dev->pdev->id); return -EINVAL; diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c index df95e5cb9b99..094a7861831a 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c @@ -840,7 +840,7 @@ static uint16_t msm_ispif_get_cids_mask_from_cfg( uint16_t cids_mask = 0; BUG_ON(!entry); - for (i = 0; i < entry->num_cids; i++) + for (i = 0; i < entry->num_cids && i < MAX_CID_CH_PARAM_ENTRY; i++) cids_mask |= (1 << entry->cids[i]); return cids_mask; @@ -970,7 +970,7 @@ static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint32_t cmd_bits, pr_err("%s: invalid interface type\n", __func__); return; } - if (params->entries[i].num_cids > MAX_CID_CH) { + if (params->entries[i].num_cids > MAX_CID_CH_PARAM_ENTRY) { pr_err("%s: out of range of cid_num %d\n", __func__, params->entries[i].num_cids); return; diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c index 59135225cb15..c779ee46c19a 100644 --- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c +++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c @@ -286,7 +286,7 @@ static int msm_vb2_put_buf(struct vb2_v4l2_buffer *vb, int session_id, break; } if (vb2_v4l2_buf != vb) { - pr_err("VB buffer is INVALID vb=%p, ses_id=%d, str_id=%d\n", + pr_err("VB buffer is INVALID vb=%pK, ses_id=%d, str_id=%d\n", vb, session_id, stream_id); spin_unlock_irqrestore(&stream->stream_lock, flags); return -EINVAL; @@ -329,7 +329,7 @@ static int msm_vb2_buf_done(struct vb2_v4l2_buffer *vb, int session_id, break; } if (vb2_v4l2_buf != vb) { - pr_err("VB buffer is INVALID ses_id=%d, str_id=%d, vb=%p\n", + pr_err("VB buffer is INVALID ses_id=%d, str_id=%d, vb=%pK\n", session_id, stream_id, vb); spin_unlock_irqrestore(&stream->stream_lock, flags); return -EINVAL; diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 106d76aae3bb..ab074ffbcdfb 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -1074,6 +1074,13 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) goto end; } + rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP, + CAM_AHB_NOMINAL_VOTE); + if (rc < 0) { + pr_err("%s:%d: failed to vote for AHB\n", __func__, __LINE__); + goto end; + } + msm_camera_io_w(0x1, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL); msm_camera_io_w(0x1, cpp_dev->base + MSM_CPP_MICRO_BOOT_START); @@ -1082,7 +1089,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) if (rc) { pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__, MSM_CPP_MSG_ID_CMD, rc); - goto end; + goto vote; } msm_camera_io_w(0xFFFFFFFF, cpp_dev->base + @@ -1092,7 +1099,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) if (rc) { pr_err("%s:%d] poll rx empty failed %d", __func__, __LINE__, rc); - goto end; + goto vote; } /*Start firmware loading*/ msm_cpp_write(MSM_CPP_CMD_FW_LOAD, cpp_dev->base); @@ -1102,7 +1109,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) if (rc) { pr_err("%s:%d] poll rx empty failed %d", __func__, __LINE__, rc); - goto end; + goto vote; } for (i = 0; i < cpp_dev->fw->size/4; i++) { msm_cpp_write(*ptr_bin, cpp_dev->base); @@ -1111,7 +1118,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) if (rc) { pr_err("%s:%d] poll rx empty failed %d", __func__, __LINE__, rc); - goto end; + goto vote; } } ptr_bin++; @@ -1124,21 +1131,21 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) if (rc) { pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__, MSM_CPP_MSG_ID_OK, rc); - goto end; + goto vote; } rc = msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_CMD); if (rc) { pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__, MSM_CPP_MSG_ID_CMD, rc); - goto end; + goto vote; } rc = msm_cpp_poll_rx_empty(cpp_dev->base); if (rc) { pr_err("%s:%d] poll rx empty failed %d", __func__, __LINE__, rc); - goto end; + goto vote; } /*Trigger MC to jump to start address*/ msm_cpp_write(MSM_CPP_CMD_EXEC_JUMP, cpp_dev->base); @@ -1148,21 +1155,21 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) if (rc) { pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__, MSM_CPP_MSG_ID_CMD, rc); - goto end; + goto vote; } rc = msm_cpp_poll(cpp_dev->base, 0x1); if (rc) { pr_err("%s:%d] poll command 0x1 failed %d", __func__, __LINE__, rc); - goto end; + goto vote; } rc = msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_JUMP_ACK); if (rc) { pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__, MSM_CPP_MSG_ID_JUMP_ACK, rc); - goto end; + goto vote; } rc = msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_TRAILER); @@ -1171,6 +1178,11 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) MSM_CPP_MSG_ID_JUMP_ACK, rc); } +vote: + rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP, + CAM_AHB_SVS_VOTE); + if (rc < 0) + pr_err("%s:%d: failed to vote for AHB\n", __func__, __LINE__); end: return rc; } @@ -4186,7 +4198,7 @@ static int cpp_probe(struct platform_device *pdev) cpp_dev->state = CPP_STATE_BOOT; rc = cpp_init_hardware(cpp_dev); if (rc < 0) - goto cpp_probe_init_error; + goto bus_de_init; media_entity_init(&cpp_dev->msm_sd.sd.entity, 0, NULL, 0); cpp_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; @@ -4225,7 +4237,7 @@ static int cpp_probe(struct platform_device *pdev) if (!cpp_dev->work) { pr_err("no enough memory\n"); rc = -ENOMEM; - goto cpp_probe_init_error; + goto bus_de_init; } INIT_WORK((struct work_struct *)cpp_dev->work, msm_cpp_do_timeout_work); @@ -4245,6 +4257,12 @@ static int cpp_probe(struct platform_device *pdev) else CPP_DBG("FAILED."); return rc; + +bus_de_init: + if (cpp_dev->bus_master_flag) + msm_cpp_deinit_bandwidth_mgr(cpp_dev); + else + msm_isp_deinit_bandwidth_mgr(ISP_CPP); cpp_probe_init_error: media_entity_cleanup(&cpp_dev->msm_sd.sd.entity); msm_sd_unregister(&cpp_dev->msm_sd); diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c index 5f749bd46273..0d27de5c9b4b 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c @@ -645,7 +645,7 @@ static int32_t msm_flash_release( static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl, void __user *argp) { - int32_t rc = -EINVAL; + int32_t rc = 0; struct msm_flash_cfg_data_t *flash_data = (struct msm_flash_cfg_data_t *) argp; diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c index 25c152be2b71..5a330db0f9a5 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c @@ -794,7 +794,7 @@ int32_t msm_camera_tz_i2c_register_sensor( return -EINVAL; } - CDBG("id=%d, client=%p\n", s_ctrl->id, s_ctrl); + CDBG("id=%d, client=%pK\n", s_ctrl->id, s_ctrl); sensor_info[s_ctrl->id].s_ctrl = s_ctrl; sensor_info[s_ctrl->id].secure = s_ctrl->is_secure; return 0; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c index 94223b557990..cf33bc6437cc 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c @@ -49,6 +49,10 @@ #define SDE_ROT_EVTLOG_BUF_ALIGN 32 #define SDE_ROT_DEBUG_BASE_MAX 10 +#define SDE_ROT_DEFAULT_BASE_REG_CNT 0x100 +#define GROUP_BYTES 4 +#define ROW_BYTES 16 + static DEFINE_SPINLOCK(sde_rot_xlock); /* @@ -963,6 +967,273 @@ static const struct file_operations sde_rotator_raw_ops = { .release = single_release }; +static int sde_rotator_debug_base_open(struct inode *inode, struct file *file) +{ + /* non-seekable */ + file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); + file->private_data = inode->i_private; + return 0; +} + +static int sde_rotator_debug_base_release(struct inode *inode, + struct file *file) +{ + struct sde_rotator_debug_base *dbg = file->private_data; + + if (dbg && dbg->buf) { + kfree(dbg->buf); + dbg->buf_len = 0; + dbg->buf = NULL; + } + return 0; +} + +static ssize_t sde_rotator_debug_base_offset_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct sde_rotator_debug_base *dbg = file->private_data; + u32 off = 0; + u32 cnt = SDE_ROT_DEFAULT_BASE_REG_CNT; + char buf[24]; + + if (!dbg) + return -ENODEV; + + if (count >= sizeof(buf)) + return -EFAULT; + + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + + buf[count] = 0; + + if (sscanf(buf, "%5x %x", &off, &cnt) < 2) + return -EINVAL; + + if (off > dbg->max_offset) + return -EINVAL; + + if (cnt > (dbg->max_offset - off)) + cnt = dbg->max_offset - off; + + dbg->off = off; + dbg->cnt = cnt; + + SDEROT_DBG("offset=%x cnt=%x\n", off, cnt); + + return count; +} + +static ssize_t sde_rotator_debug_base_offset_read(struct file *file, + char __user *buff, size_t count, loff_t *ppos) +{ + struct sde_rotator_debug_base *dbg = file->private_data; + int len = 0; + char buf[24] = {'\0'}; + + if (!dbg) + return -ENODEV; + + if (*ppos) + return 0; /* the end */ + + len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt); + if (len < 0 || len >= sizeof(buf)) + return 0; + + if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + return -EFAULT; + + *ppos += len; /* increase offset */ + + return len; +} + +static ssize_t sde_rotator_debug_base_reg_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct sde_rotator_debug_base *dbg = file->private_data; + size_t off; + u32 data, cnt; + char buf[24]; + + if (!dbg) + return -ENODEV; + + if (count >= sizeof(buf)) + return -EFAULT; + + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + + buf[count] = 0; + + cnt = sscanf(buf, "%zx %x", &off, &data); + + if (cnt < 2) + return -EFAULT; + + if (off >= dbg->max_offset) + return -EFAULT; + + /* Enable Clock for register access */ + sde_rotator_clk_ctrl(dbg->mgr, true); + + writel_relaxed(data, dbg->base + off); + + /* Disable Clock after register access */ + sde_rotator_clk_ctrl(dbg->mgr, false); + + SDEROT_DBG("addr=%zx data=%x\n", off, data); + + return count; +} + +static ssize_t sde_rotator_debug_base_reg_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + struct sde_rotator_debug_base *dbg = file->private_data; + size_t len; + + if (!dbg) { + SDEROT_ERR("invalid handle\n"); + return -ENODEV; + } + + if (!dbg->buf) { + char dump_buf[64]; + char *ptr; + int cnt, tot; + + dbg->buf_len = sizeof(dump_buf) * + DIV_ROUND_UP(dbg->cnt, ROW_BYTES); + dbg->buf = kzalloc(dbg->buf_len, GFP_KERNEL); + + if (!dbg->buf) { + SDEROT_ERR("not enough memory to hold reg dump\n"); + return -ENOMEM; + } + + ptr = dbg->base + dbg->off; + tot = 0; + + /* Enable clock for register access */ + sde_rotator_clk_ctrl(dbg->mgr, true); + + for (cnt = dbg->cnt; cnt > 0; cnt -= ROW_BYTES) { + hex_dump_to_buffer(ptr, min(cnt, ROW_BYTES), + ROW_BYTES, GROUP_BYTES, dump_buf, + sizeof(dump_buf), false); + len = scnprintf(dbg->buf + tot, dbg->buf_len - tot, + "0x%08x: %s\n", + ((int) (unsigned long) ptr) - + ((int) (unsigned long) dbg->base), + dump_buf); + + ptr += ROW_BYTES; + tot += len; + if (tot >= dbg->buf_len) + break; + } + /* Disable clock after register access */ + sde_rotator_clk_ctrl(dbg->mgr, false); + + dbg->buf_len = tot; + } + + if (*ppos >= dbg->buf_len) + return 0; /* done reading */ + + len = min(count, dbg->buf_len - (size_t) *ppos); + if (copy_to_user(user_buf, dbg->buf + *ppos, len)) { + SDEROT_ERR("failed to copy to user\n"); + return -EFAULT; + } + + *ppos += len; /* increase offset */ + + return len; +} + +static const struct file_operations sde_rotator_off_fops = { + .open = sde_rotator_debug_base_open, + .release = sde_rotator_debug_base_release, + .read = sde_rotator_debug_base_offset_read, + .write = sde_rotator_debug_base_offset_write, +}; + +static const struct file_operations sde_rotator_reg_fops = { + .open = sde_rotator_debug_base_open, + .release = sde_rotator_debug_base_release, + .read = sde_rotator_debug_base_reg_read, + .write = sde_rotator_debug_base_reg_write, +}; + +int sde_rotator_debug_register_base(struct sde_rotator_device *rot_dev, + struct dentry *debugfs_root, + const char *name, + struct sde_io_data *io_data) +{ + struct sde_rotator_debug_base *dbg; + struct dentry *ent_off, *ent_reg; + char dbgname[80] = ""; + int prefix_len = 0; + + if (!io_data) + return -EINVAL; + + dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); + if (!dbg) + return -ENOMEM; + + if (name) + strlcpy(dbg->name, name, sizeof(dbg->name)); + dbg->base = io_data->base; + dbg->max_offset = io_data->len; + dbg->off = 0; + dbg->cnt = SDE_ROT_DEFAULT_BASE_REG_CNT; + + if (name) { + if (strcmp(name, "sde")) + prefix_len = snprintf(dbgname, sizeof(dbgname), "%s_", + name); + else + /* + * For SDE Rotator registers block, the IO base address + * is based on MDP IO address base. It is necessary to + * apply the initial offset to it from the first + * regdump setting. + */ + dbg->base += rot_dev->mdata->regdump ? + rot_dev->mdata->regdump[0].offset : 0; + } + + strlcpy(dbgname + prefix_len, "off", sizeof(dbgname) - prefix_len); + ent_off = debugfs_create_file(dbgname, 0644, debugfs_root, dbg, + &sde_rotator_off_fops); + if (IS_ERR_OR_NULL(ent_off)) { + SDEROT_ERR("debugfs_create_file: offset fail\n"); + goto off_fail; + } + + strlcpy(dbgname + prefix_len, "reg", sizeof(dbgname) - prefix_len); + ent_reg = debugfs_create_file(dbgname, 0644, debugfs_root, dbg, + &sde_rotator_reg_fops); + if (IS_ERR_OR_NULL(ent_reg)) { + SDEROT_ERR("debugfs_create_file: reg fail\n"); + goto reg_fail; + } + + dbg->mgr = rot_dev->mgr; + + return 0; +reg_fail: + debugfs_remove(ent_off); +off_fail: + kfree(dbg); + return -ENODEV; +} + /* * sde_rotator_create_debugfs - Setup rotator debugfs directory structure. * @rot_dev: Pointer to rotator device @@ -1040,6 +1311,20 @@ struct dentry *sde_rotator_create_debugfs( return NULL; } + if (sde_rotator_debug_register_base(rot_dev, debugfs_root, + "sde", &rot_dev->mdata->sde_io)) { + SDEROT_ERR("fail create debug register for sde rotator\n"); + debugfs_remove_recursive(debugfs_root); + return NULL; + } + + if (sde_rotator_debug_register_base(rot_dev, debugfs_root, + "vbif_nrt", &rot_dev->mdata->vbif_nrt_io)) { + SDEROT_ERR("fail create debug register for sderot vbif_nrt\n"); + debugfs_remove_recursive(debugfs_root); + return NULL; + } + return debugfs_root; } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h index dcda54274fad..c2c6f9775602 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h @@ -44,6 +44,17 @@ void sde_rot_evtlog_tout_handler(bool queue, const char *name, ...); struct sde_rotator_device; +struct sde_rotator_debug_base { + char name[80]; + void __iomem *base; + size_t off; + size_t cnt; + size_t max_offset; + char *buf; + size_t buf_len; + struct sde_rot_mgr *mgr; +}; + #if defined(CONFIG_DEBUG_FS) struct dentry *sde_rotator_create_debugfs( struct sde_rotator_device *rot_dev); diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c index b88f03ce89ae..08075ae90507 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c @@ -305,6 +305,39 @@ static void sde_rotator_buf_queue(struct vb2_buffer *vb) } /* + * sde_rotator_buf_finish - vb2_ops buf_finish to finalize buffer before going + * back to user space + * @vb: Pointer to vb2 buffer struct. + */ +static void sde_rotator_buf_finish(struct vb2_buffer *vb) +{ + struct sde_rotator_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + int i; + + SDEDEV_DBG(ctx->rot_dev->dev, + "buf_finish t:%d i:%d s:%d m:%u np:%d up:%lu\n", + vb->type, vb->index, vb->state, + vb->vb2_queue->memory, + vb->num_planes, + vb->planes[0].m.userptr); + + if (vb->vb2_queue->memory != VB2_MEMORY_USERPTR) + return; + + /* + * We use userptr to tunnel fd, and fd can be the same across qbuf + * even though the underlying buffer is different. Since vb2 layer + * optimizes memory mapping for userptr by first checking if userptr + * has changed, it will not trigger put_userptr if fd value does + * not change. In order to force buffer release, we need to clear + * userptr when the current buffer is done and ready to go back to + * user mode. Since 0 is a valid fd, reset userptr to -1 instead. + */ + for (i = 0; i < vb->num_planes; i++) + vb->planes[i].m.userptr = ~0; +} + +/* * sde_rotator_return_all_buffers - Return all buffers with the given status. * @q: Pointer to vb2 buffer queue struct. * @state: State of the buffer @@ -460,6 +493,7 @@ static struct vb2_ops sde_rotator_vb2_q_ops = { .stop_streaming = sde_rotator_stop_streaming, .wait_prepare = vb2_ops_wait_prepare, .wait_finish = vb2_ops_wait_finish, + .buf_finish = sde_rotator_buf_finish, }; /* diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c index 0b44896bf6b3..7388dab92c34 100644 --- a/drivers/media/platform/msm/vidc/hfi_packetization.c +++ b/drivers/media/platform/msm/vidc/hfi_packetization.c @@ -2153,6 +2153,33 @@ int create_pkt_cmd_session_set_property( pkt->size += sizeof(u32) + sizeof(*signal_info); break; } + case HAL_PARAM_VENC_IFRAMESIZE_TYPE: + { + enum hal_iframesize_type hal = + *(enum hal_iframesize_type *)pdata; + struct hfi_iframe_size *hfi = (struct hfi_iframe_size *) + &pkt->rg_property_data[1]; + + switch (hal) { + case HAL_IFRAMESIZE_TYPE_DEFAULT: + hfi->type = HFI_IFRAME_SIZE_DEFAULT; + break; + case HAL_IFRAMESIZE_TYPE_MEDIUM: + hfi->type = HFI_IFRAME_SIZE_MEDIUM; + break; + case HAL_IFRAMESIZE_TYPE_HUGE: + hfi->type = HFI_IFRAME_SIZE_HIGH; + break; + case HAL_IFRAMESIZE_TYPE_UNLIMITED: + hfi->type = HFI_IFRAME_SIZE_UNLIMITED; + break; + default: + return -ENOTSUPP; + } + pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_VENC_IFRAMESIZE; + pkt->size += sizeof(u32) + sizeof(struct hfi_iframe_size); + 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_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c index 3633d1fb3cd1..fbdccea56f67 100644 --- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c @@ -36,7 +36,7 @@ struct msm_vidc_drv *vidc_driver; -uint32_t msm_vidc_pwr_collapse_delay = 2000; +uint32_t msm_vidc_pwr_collapse_delay = 3000; static inline struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh) { @@ -138,12 +138,20 @@ int msm_v4l2_reqbufs(struct file *file, void *fh, { struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh); int rc = 0; - if (!b->count) + if (!b->count) { rc = msm_vidc_release_buffers(vidc_inst, b->type); - if (rc) - dprintk(VIDC_WARN, - "Failed in %s for release output buffers\n", __func__); - return msm_vidc_reqbufs((void *)vidc_inst, b); + if (rc) + dprintk(VIDC_WARN, + "Failed in %s for release output buffers\n", + __func__); + } else { + rc = msm_vidc_reqbufs((void *)vidc_inst, b); + if (rc) + dprintk(VIDC_WARN, + "Failed in %s for buffer requirements\n", + __func__); + } + return rc; } int msm_v4l2_prepare_buf(struct file *file, void *fh, diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index f071aae3ccab..4ec331d121d9 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -185,6 +185,13 @@ static const char *const timestamp_mode[] = { "Ignore", }; +static const char *const iframe_sizes[] = { + "Default", + "Medium", + "Huge", + "Unlimited" +}; + static struct msm_vidc_ctrl msm_venc_ctrls[] = { { .id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD, @@ -1281,6 +1288,20 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { .step = 1, .qmenu = NULL, }, + { + .id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE, + .name = "Bounds of I-frame size", + .type = V4L2_CTRL_TYPE_MENU, + .minimum = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + .maximum = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED, + .default_value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + .menu_skip_mask = ~( + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED)), + .qmenu = iframe_sizes, + }, }; @@ -2117,6 +2138,19 @@ static inline int venc_v4l2_to_hal(int id, int value) default: goto unknown_value; } + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE: + switch (value) { + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT: + return HAL_IFRAMESIZE_TYPE_DEFAULT; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM: + return HAL_IFRAMESIZE_TYPE_MEDIUM; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE: + return HAL_IFRAMESIZE_TYPE_HUGE; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED: + return HAL_IFRAMESIZE_TYPE_UNLIMITED; + default: + goto unknown_value; + } } unknown_value: @@ -2159,6 +2193,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) int frameqp = 0; int pic_order_cnt = 0; struct hal_video_signal_info signal_info = {0}; + enum hal_iframesize_type iframesize_type = HAL_IFRAMESIZE_TYPE_DEFAULT; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s invalid parameters\n", __func__); @@ -2940,7 +2975,10 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL: switch (ctrl->val) { case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL: - inst->flags &= ~VIDC_TURBO; + if (inst->flags & VIDC_TURBO) { + inst->flags &= ~VIDC_TURBO; + msm_dcvs_init_load(inst); + } break; case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO: inst->flags |= VIDC_TURBO; @@ -3239,6 +3277,13 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } pdata = &enable; break; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE: + property_id = HAL_PARAM_VENC_IFRAMESIZE_TYPE; + iframesize_type = venc_v4l2_to_hal( + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE, + ctrl->val); + pdata = &iframesize_type; + break; default: dprintk(VIDC_ERR, "Unsupported index: %x\n", ctrl->id); rc = -ENOTSUPP; diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 93e32ef4ac35..c4d06b658b30 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -652,10 +652,6 @@ int output_buffer_cache_invalidate(struct msm_vidc_inst *inst, return -EINVAL; } - if (binfo->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return 0; - - for (i = 0; i < binfo->num_planes; i++) { if (binfo->handle[i]) { rc = msm_comm_smem_cache_operations(inst, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index e612c6ed11c7..fa2ad1754e77 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -5286,24 +5286,28 @@ void msm_comm_print_inst_info(struct msm_vidc_inst *inst) int i = 0; bool is_decode = false; enum vidc_ports port; + bool is_secure = false; if (!inst) { - dprintk(VIDC_ERR, "%s - invalid param %p\n", + dprintk(VIDC_ERR, "%s - invalid param %pK\n", __func__, inst); return; } is_decode = inst->session_type == MSM_VIDC_DECODER; port = is_decode ? OUTPUT_PORT : CAPTURE_PORT; + is_secure = inst->flags & VIDC_SECURE; dprintk(VIDC_ERR, - "%s session, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n", - is_decode ? "Decode" : "Encode", inst->fmts[port].name, + "%s session, %s, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n", + is_decode ? "Decode" : "Encode", + is_secure ? "Secure" : "Non-Secure", + inst->fmts[port].name, inst->prop.height[port], inst->prop.width[port], inst->prop.fps, inst->prop.bitrate, !inst->bit_depth ? "8" : "10"); dprintk(VIDC_ERR, - "---Buffer details for inst: %p of type: %d---\n", + "---Buffer details for inst: %pK of type: %d---\n", inst, inst->session_type); mutex_lock(&inst->registeredbufs.lock); dprintk(VIDC_ERR, "registered buffer list:\n"); @@ -5347,7 +5351,7 @@ static void msm_comm_print_debug_info(struct msm_vidc_inst *inst) struct msm_vidc_inst *temp = NULL; if (!inst || !inst->core) { - dprintk(VIDC_ERR, "%s - invalid param %p %p\n", + dprintk(VIDC_ERR, "%s - invalid param %pK %pK\n", __func__, inst, core); return; } diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c index 011941c6d4eb..2e1df75cb248 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c @@ -24,7 +24,7 @@ EXPORT_SYMBOL(msm_vidc_debug_out); int msm_vidc_fw_debug = 0x18; int msm_vidc_fw_debug_mode = 1; int msm_vidc_fw_low_power_mode = 1; -int msm_vidc_hw_rsp_timeout = 1000; +int msm_vidc_hw_rsp_timeout = 2000; bool msm_vidc_fw_coverage = false; bool msm_vidc_vpe_csc_601_to_709 = false; bool msm_vidc_dec_dcvs_mode = true; diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index c87b6fc585c7..787ee43ccbd2 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -3407,10 +3407,12 @@ static int __response_handler(struct venus_hfi_device *device) packets = device->response_pkt; - raw_packet = kzalloc(VIDC_IFACEQ_VAR_HUGE_PKT_SIZE, GFP_TEMPORARY); + raw_packet = device->raw_packet; + if (!raw_packet || !packets) { - dprintk(VIDC_ERR, "%s: Failed to allocate memory\n", __func__); - kfree(raw_packet); + dprintk(VIDC_ERR, + "%s: Invalid args : Res packet = %p, Raw packet = %p\n", + __func__, packets, raw_packet); return 0; } @@ -3566,7 +3568,6 @@ static int __response_handler(struct venus_hfi_device *device) exit: __flush_debug_queue(device, raw_packet); - kfree(raw_packet); return packet_count; } @@ -4553,6 +4554,13 @@ static struct venus_hfi_device *__add_device(u32 device_id, goto err_cleanup; } + hdevice->raw_packet = + kzalloc(VIDC_IFACEQ_VAR_HUGE_PKT_SIZE, GFP_TEMPORARY); + if (!hdevice->raw_packet) { + dprintk(VIDC_ERR, "failed to allocate raw packet\n"); + goto err_cleanup; + } + rc = __init_regs_and_interrupts(hdevice, res); if (rc) goto err_cleanup; @@ -4590,6 +4598,7 @@ err_cleanup: if (hdevice->vidc_workq) destroy_workqueue(hdevice->vidc_workq); kfree(hdevice->response_pkt); + kfree(hdevice->raw_packet); kfree(hdevice); exit: return NULL; @@ -4631,6 +4640,7 @@ void venus_hfi_delete_device(void *device) iounmap(dev->hal_data->register_base); kfree(close->hal_data); kfree(close->response_pkt); + kfree(close->raw_packet); kfree(close); break; } diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h index 7cc71a470c2e..1d2ca88a3c1d 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.h +++ b/drivers/media/platform/msm/vidc/venus_hfi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -247,6 +247,7 @@ struct venus_hfi_device { struct hfi_packetization_ops *pkt_ops; enum hfi_packetization_type packetization_type; struct msm_vidc_cb_info *response_pkt; + u8 *raw_packet; struct pm_qos_request qos; unsigned int skip_pc_count; struct msm_vidc_capability *sys_init_capabilities; diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h index aa566159c393..116ce12c8dba 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h @@ -242,6 +242,7 @@ enum hal_property { HAL_PARAM_VENC_SESSION_QP_RANGE_PACKED, HAL_PARAM_VENC_H264_TRANSFORM_8x8, HAL_PARAM_VENC_VIDEO_SIGNAL_INFO, + HAL_PARAM_VENC_IFRAMESIZE_TYPE, }; enum hal_domain { @@ -1002,6 +1003,13 @@ struct hal_video_signal_info { bool full_range; }; +enum hal_iframesize_type { + HAL_IFRAMESIZE_TYPE_DEFAULT, + HAL_IFRAMESIZE_TYPE_MEDIUM, + HAL_IFRAMESIZE_TYPE_HUGE, + HAL_IFRAMESIZE_TYPE_UNLIMITED, +}; + 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 5e5ef6abc303..bb9958b0a819 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h @@ -386,6 +386,8 @@ struct hfi_buffer_info { (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x031) #define HFI_PROPERTY_PARAM_VENC_VQZIP_SEI_TYPE \ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x033) +#define HFI_PROPERTY_PARAM_VENC_IFRAMESIZE \ + (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x034) #define HFI_PROPERTY_CONFIG_VENC_COMMON_START \ (HFI_DOMAIN_BASE_VENC + HFI_ARCH_COMMON_OFFSET + 0x6000) @@ -888,6 +890,14 @@ struct hfi_aspect_ratio { u32 aspect_height; }; +#define HFI_IFRAME_SIZE_DEFAULT (HFI_COMMON_BASE + 0x1) +#define HFI_IFRAME_SIZE_MEDIUM (HFI_COMMON_BASE + 0x2) +#define HFI_IFRAME_SIZE_HIGH (HFI_COMMON_BASE + 0x3) +#define HFI_IFRAME_SIZE_UNLIMITED (HFI_COMMON_BASE + 0x4) +struct hfi_iframe_size { + u32 type; +}; + #define HFI_MVC_BUFFER_LAYOUT_TOP_BOTTOM (0) #define HFI_MVC_BUFFER_LAYOUT_SIDEBYSIDE (1) #define HFI_MVC_BUFFER_LAYOUT_SEQ (2) diff --git a/drivers/mfd/wcd9xxx-utils.c b/drivers/mfd/wcd9xxx-utils.c index 344a0d5330aa..2b0a5f8ce7f2 100644 --- a/drivers/mfd/wcd9xxx-utils.c +++ b/drivers/mfd/wcd9xxx-utils.c @@ -311,6 +311,7 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev) u32 ecpp_dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED; u32 dmic_clk_drive = WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED; u32 prop_val; + int rc = 0; if (!dev || !dev->of_node) return NULL; @@ -369,9 +370,13 @@ 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; + if (of_find_property(dev->of_node, "qcom,cdc-ecpp-dmic-rate", NULL)) { + rc = wcd9xxx_read_of_property_u32(dev, + "qcom,cdc-ecpp-dmic-rate", + &prop_val); + if (!rc) + ecpp_dmic_sample_rate = prop_val; + } pdata->ecpp_dmic_sample_rate = wcd9xxx_validate_dmic_sample_rate(dev, ecpp_dmic_sample_rate, @@ -380,13 +385,14 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev) if (!(of_property_read_u32(dev->of_node, "qcom,cdc-dmic-clk-drv-strength", - &prop_val))) + &prop_val))) { dmic_clk_drive = prop_val; - if (dmic_clk_drive != 2 && dmic_clk_drive != 4 && - dmic_clk_drive != 8 && dmic_clk_drive != 16) - dev_err(dev, "Invalid cdc-dmic-clk-drv-strength %d\n", - dmic_clk_drive); + if (dmic_clk_drive != 2 && dmic_clk_drive != 4 && + dmic_clk_drive != 8 && dmic_clk_drive != 16) + dev_err(dev, "Invalid cdc-dmic-clk-drv-strength %d\n", + dmic_clk_drive); + } pdata->dmic_clk_drv = dmic_clk_drive; diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c index 69ec7127102c..56ddf8467d16 100644 --- a/drivers/misc/hdcp.c +++ b/drivers/misc/hdcp.c @@ -255,6 +255,15 @@ struct __attribute__ ((__packed__)) hdcp_version_rsp { uint32_t appversion; }; +struct __attribute__ ((__packed__)) hdcp_verify_key_req { + uint32_t commandid; +}; + +struct __attribute__ ((__packed__)) hdcp_verify_key_rsp { + uint32_t status; + uint32_t commandId; +}; + struct __attribute__ ((__packed__)) hdcp_lib_init_req_v1 { uint32_t commandid; }; @@ -794,6 +803,48 @@ exit: return rc; } +static int hdcp_lib_verify_keys(struct hdcp_lib_handle *handle) +{ + int rc = -EINVAL; + struct hdcp_verify_key_req *req_buf; + struct hdcp_verify_key_rsp *rsp_buf; + + if (!handle) { + pr_err("invalid input\n"); + goto exit; + } + + if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { + pr_err("app not loaded\n"); + goto exit; + } + + req_buf = (struct hdcp_verify_key_req *)handle->qseecom_handle->sbuf; + req_buf->commandid = HDCP_TXMTR_VERIFY_KEY; + + rsp_buf = (struct hdcp_verify_key_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_verify_key_req))); + + rc = qseecom_send_command(handle->qseecom_handle, + req_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_verify_key_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_verify_key_rsp))); + + if (rc < 0) { + pr_err("qseecom cmd failed err = %d\n", rc); + goto exit; + } + + return rsp_buf->status; +exit: + return rc; +} + + static int hdcp_app_init_legacy(struct hdcp_lib_handle *handle) { int rc = 0; @@ -1456,10 +1507,12 @@ static bool hdcp_lib_client_feature_supported(void *phdcpcontext) rc = hdcp_lib_library_load(handle); if (!rc) { - pr_debug("HDCP2p2 supported\n"); - handle->feature_supported = true; + if (!hdcp_lib_verify_keys(handle)) { + pr_debug("HDCP2p2 supported\n"); + handle->feature_supported = true; + supported = true; + } hdcp_lib_library_unload(handle); - supported = true; } exit: return supported; diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index ff838ebefba6..7dc7271b05c1 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -131,6 +131,35 @@ static DEFINE_MUTEX(qsee_bw_mutex); static DEFINE_MUTEX(app_access_lock); static DEFINE_MUTEX(clk_access_lock); +struct sglist_info { + uint32_t indexAndFlags; + uint32_t sizeOrCount; +}; + +/* + * The 31th bit indicates only one or multiple physical address inside + * the request buffer. If it is set, the index locates a single physical addr + * inside the request buffer, and `sizeOrCount` is the size of the memory being + * shared at that physical address. + * Otherwise, the index locates an array of {start, len} pairs (a + * "scatter/gather list"), and `sizeOrCount` gives the number of entries in + * that array. + * + * The 30th bit indicates 64 or 32bit address; when it is set, physical addr + * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values. + * + * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer. + */ +#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \ + ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff))) + +#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD) + +#define FEATURE_ID_WHITELIST 15 /*whitelist feature id*/ + +#define MAKE_WHITELIST_VERSION(major, minor, patch) \ + (((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF)) + struct qseecom_registered_listener_list { struct list_head list; struct qseecom_register_listener_req svc; @@ -145,6 +174,8 @@ struct qseecom_registered_listener_list { bool listener_in_use; /* wq for thread blocked on this listener*/ wait_queue_head_t listener_block_app_wq; + struct sglist_info sglistinfo_ptr[MAX_ION_FD]; + uint32_t sglist_cnt; }; struct qseecom_registered_app_list { @@ -268,30 +299,6 @@ struct qseecom_listener_handle { static struct qseecom_control qseecom; -struct sglist_info { - uint32_t indexAndFlags; - uint32_t sizeOrCount; -}; - -/* - * The 31th bit indicates only one or multiple physical address inside - * the request buffer. If it is set, the index locates a single physical addr - * inside the request buffer, and `sizeOrCount` is the size of the memory being - * shared at that physical address. - * Otherwise, the index locates an array of {start, len} pairs (a - * "scatter/gather list"), and `sizeOrCount` gives the number of entries in - * that array. - * - * The 30th bit indicates 64 or 32bit address; when it is set, physical addr - * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values. - * - * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer. - */ -#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \ - ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff))) - -#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD) - struct qseecom_dev_handle { enum qseecom_client_handle_type type; union { @@ -305,8 +312,9 @@ struct qseecom_dev_handle { bool perf_enabled; bool fast_load_enabled; enum qseecom_bandwidth_request_mode mode; - struct sglist_info *sglistinfo_ptr; + struct sglist_info sglistinfo_ptr[MAX_ION_FD]; uint32_t sglist_cnt; + bool use_legacy_cmd; }; struct qseecom_key_id_usage_desc { @@ -584,6 +592,34 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, ret = scm_call2(smc_id, &desc); break; } + case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: { + struct qseecom_client_listener_data_irsp *req; + struct qseecom_client_listener_data_64bit_irsp *req_64; + + smc_id = + TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID; + desc.arginfo = + TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID; + if (qseecom.qsee_version < QSEE_VERSION_40) { + req = + (struct qseecom_client_listener_data_irsp *) + req_buf; + desc.args[0] = req->listener_id; + desc.args[1] = req->status; + desc.args[2] = req->sglistinfo_ptr; + desc.args[3] = req->sglistinfo_len; + } else { + req_64 = + (struct qseecom_client_listener_data_64bit_irsp *) + req_buf; + desc.args[0] = req_64->listener_id; + desc.args[1] = req_64->status; + desc.args[2] = req_64->sglistinfo_ptr; + desc.args[3] = req_64->sglistinfo_len; + } + ret = scm_call2(smc_id, &desc); + break; + } case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: { struct qseecom_load_app_ireq *req; struct qseecom_load_app_64bit_ireq *req_64bit; @@ -1128,7 +1164,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, return -EBUSY; } - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); if (!new_entry) { pr_err("kmalloc failed\n"); return -ENOMEM; @@ -1593,6 +1629,16 @@ static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data, return ret; } +static void __qseecom_clean_listener_sglistinfo( + struct qseecom_registered_listener_list *ptr_svc) +{ + if (ptr_svc->sglist_cnt) { + memset(ptr_svc->sglistinfo_ptr, 0, + SGLISTINFO_TABLE_SIZE); + ptr_svc->sglist_cnt = 0; + } +} + static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) { @@ -1601,9 +1647,14 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, uint32_t lstnr; unsigned long flags; struct qseecom_client_listener_data_irsp send_data_rsp; + struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit; struct qseecom_registered_listener_list *ptr_svc = NULL; sigset_t new_sigset; sigset_t old_sigset; + uint32_t status; + void *cmd_buf = NULL; + size_t cmd_len; + struct sglist_info *table = NULL; while (resp->result == QSEOS_RESULT_INCOMPLETE) { lstnr = resp->data; @@ -1677,15 +1728,42 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", data->client.app_id, lstnr, ret); rc = -ENODEV; - send_data_rsp.status = QSEOS_RESULT_FAILURE; + status = QSEOS_RESULT_FAILURE; } else { - send_data_rsp.status = QSEOS_RESULT_SUCCESS; + status = QSEOS_RESULT_SUCCESS; } qseecom.send_resp_flag = 0; ptr_svc->send_resp_flag = 0; - send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; - send_data_rsp.listener_id = lstnr; + table = ptr_svc->sglistinfo_ptr; + if (qseecom.qsee_version < QSEE_VERSION_40) { + send_data_rsp.listener_id = lstnr; + send_data_rsp.status = status; + send_data_rsp.sglistinfo_ptr = + (uint32_t)virt_to_phys(table); + send_data_rsp.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp; + cmd_len = sizeof(send_data_rsp); + } else { + send_data_rsp_64bit.listener_id = lstnr; + send_data_rsp_64bit.status = status; + send_data_rsp_64bit.sglistinfo_ptr = + virt_to_phys(table); + send_data_rsp_64bit.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp_64bit; + cmd_len = sizeof(send_data_rsp_64bit); + } + if (qseecom.whitelist_support == false) + *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND; + else + *(uint32_t *)cmd_buf = + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; if (ptr_svc) msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, @@ -1695,10 +1773,9 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, __qseecom_enable_clk(CLK_QSEE); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, - (const void *)&send_data_rsp, - sizeof(send_data_rsp), resp, - sizeof(*resp)); + cmd_buf, cmd_len, resp, sizeof(*resp)); ptr_svc->listener_in_use = false; + __qseecom_clean_listener_sglistinfo(ptr_svc); if (ret) { pr_err("scm_call() failed with err: %d (app_id = %d)\n", ret, data->client.app_id); @@ -1826,9 +1903,14 @@ static int __qseecom_reentrancy_process_incomplete_cmd( uint32_t lstnr; unsigned long flags; struct qseecom_client_listener_data_irsp send_data_rsp; + struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit; struct qseecom_registered_listener_list *ptr_svc = NULL; sigset_t new_sigset; sigset_t old_sigset; + uint32_t status; + void *cmd_buf = NULL; + size_t cmd_len; + struct sglist_info *table = NULL; while (ret == 0 && rc == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) { lstnr = resp->data; @@ -1891,13 +1973,38 @@ static int __qseecom_reentrancy_process_incomplete_cmd( pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", data->client.app_id, lstnr, ret); rc = -ENODEV; - send_data_rsp.status = QSEOS_RESULT_FAILURE; + status = QSEOS_RESULT_FAILURE; } else { - send_data_rsp.status = QSEOS_RESULT_SUCCESS; + status = QSEOS_RESULT_SUCCESS; } - - send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; - send_data_rsp.listener_id = lstnr; + table = ptr_svc->sglistinfo_ptr; + if (qseecom.qsee_version < QSEE_VERSION_40) { + send_data_rsp.listener_id = lstnr; + send_data_rsp.status = status; + send_data_rsp.sglistinfo_ptr = + (uint32_t)virt_to_phys(table); + send_data_rsp.sglistinfo_len = SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp; + cmd_len = sizeof(send_data_rsp); + } else { + send_data_rsp_64bit.listener_id = lstnr; + send_data_rsp_64bit.status = status; + send_data_rsp_64bit.sglistinfo_ptr = + virt_to_phys(table); + send_data_rsp_64bit.sglistinfo_len = + SGLISTINFO_TABLE_SIZE; + dmac_flush_range((void *)table, + (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_rsp_64bit; + cmd_len = sizeof(send_data_rsp_64bit); + } + if (qseecom.whitelist_support == false) + *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND; + else + *(uint32_t *)cmd_buf = + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; if (ptr_svc) msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, ptr_svc->sb_virt, ptr_svc->sb_length, @@ -1907,11 +2014,9 @@ static int __qseecom_reentrancy_process_incomplete_cmd( __qseecom_enable_clk(CLK_QSEE); ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, - (const void *)&send_data_rsp, - sizeof(send_data_rsp), resp, - sizeof(*resp)); - + cmd_buf, cmd_len, resp, sizeof(*resp)); ptr_svc->listener_in_use = false; + __qseecom_clean_listener_sglistinfo(ptr_svc); wake_up_interruptible(&ptr_svc->listener_block_app_wq); if (ret) { @@ -2079,6 +2184,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) struct qseecom_load_app_64bit_ireq load_req_64bit; void *cmd_buf = NULL; size_t cmd_len; + bool first_time = false; /* Copy the relevant information needed for loading the image */ if (copy_from_user(&load_img_req, @@ -2150,6 +2256,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) &qseecom.registered_app_list_lock, flags); ret = 0; } else { + first_time = true; pr_warn("App (%s) does'nt exist, loading apps for first time\n", (char *)(load_img_req.img_name)); /* Get the handle of the shared fd */ @@ -2281,8 +2388,15 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) load_img_req.app_id = app_id; if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) { pr_err("copy_to_user failed\n"); - kzfree(entry); ret = -EFAULT; + if (first_time == true) { + spin_lock_irqsave( + &qseecom.registered_app_list_lock, flags); + list_del(&entry->list); + spin_unlock_irqrestore( + &qseecom.registered_app_list_lock, flags); + kzfree(entry); + } } loadapp_err: @@ -2910,7 +3024,7 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); } - if (qseecom.whitelist_support == false) + if (qseecom.whitelist_support == false || data->use_legacy_cmd == true) *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND; else *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; @@ -3015,6 +3129,8 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, struct qseecom_send_modfd_cmd_req *req = NULL; struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL; struct qseecom_registered_listener_list *this_lstnr = NULL; + uint32_t offset; + struct sg_table *sg_ptr; if ((data->type != QSEECOM_LISTENER_SERVICE) && (data->type != QSEECOM_CLIENT_APP)) @@ -3036,7 +3152,6 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, } for (i = 0; i < MAX_ION_FD; i++) { - struct sg_table *sg_ptr = NULL; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { ihandle = ion_import_dma_buf(qseecom.ion_clnt, @@ -3178,14 +3293,25 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); if (data->type == QSEECOM_CLIENT_APP) { + offset = req->ifd_data[i].cmd_buf_offset; data->sglistinfo_ptr[i].indexAndFlags = SGLISTINFO_SET_INDEX_FLAG( - (sg_ptr->nents == 1), 0, - req->ifd_data[i].cmd_buf_offset); + (sg_ptr->nents == 1), 0, offset); data->sglistinfo_ptr[i].sizeOrCount = (sg_ptr->nents == 1) ? sg->length : sg_ptr->nents; data->sglist_cnt = i + 1; + } else { + offset = (lstnr_resp->ifd_data[i].cmd_buf_offset + + (uintptr_t)lstnr_resp->resp_buf_ptr - + (uintptr_t)this_lstnr->sb_virt); + this_lstnr->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 0, offset); + this_lstnr->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + this_lstnr->sglist_cnt = i + 1; } } /* Deallocate the handle */ @@ -3258,6 +3384,8 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, struct qseecom_send_modfd_cmd_req *req = NULL; struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL; struct qseecom_registered_listener_list *this_lstnr = NULL; + uint32_t offset; + struct sg_table *sg_ptr; if ((data->type != QSEECOM_LISTENER_SERVICE) && (data->type != QSEECOM_CLIENT_APP)) @@ -3279,7 +3407,6 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, } for (i = 0; i < MAX_ION_FD; i++) { - struct sg_table *sg_ptr = NULL; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { ihandle = ion_import_dma_buf(qseecom.ion_clnt, @@ -3396,14 +3523,25 @@ cleanup: ihandle, NULL, len, ION_IOC_CLEAN_INV_CACHES); if (data->type == QSEECOM_CLIENT_APP) { + offset = req->ifd_data[i].cmd_buf_offset; data->sglistinfo_ptr[i].indexAndFlags = SGLISTINFO_SET_INDEX_FLAG( - (sg_ptr->nents == 1), 1, - req->ifd_data[i].cmd_buf_offset); + (sg_ptr->nents == 1), 1, offset); data->sglistinfo_ptr[i].sizeOrCount = (sg_ptr->nents == 1) ? sg->length : sg_ptr->nents; data->sglist_cnt = i + 1; + } else { + offset = (lstnr_resp->ifd_data[i].cmd_buf_offset + + (uintptr_t)lstnr_resp->resp_buf_ptr - + (uintptr_t)this_lstnr->sb_virt); + this_lstnr->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( + (sg_ptr->nents == 1), 1, offset); + this_lstnr->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + this_lstnr->sglist_cnt = i + 1; } } /* Deallocate the handle */ @@ -4122,21 +4260,12 @@ int qseecom_start_app(struct qseecom_handle **handle, data->client.user_virt_sb_base = 0; data->client.ihandle = NULL; - /* Allocate sglistinfo buffer for kernel client */ - data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); - if (!(data->sglistinfo_ptr)) { - kfree(data); - kfree(*handle); - *handle = NULL; - return -ENOMEM; - } init_waitqueue_head(&data->abort_wq); data->client.ihandle = ion_alloc(qseecom.ion_clnt, size, 4096, ION_HEAP(ION_QSECOM_HEAP_ID), 0); if (IS_ERR_OR_NULL(data->client.ihandle)) { pr_err("Ion client could not retrieve the handle\n"); - kfree(data->sglistinfo_ptr); kfree(data); kfree(*handle); *handle = NULL; @@ -4239,7 +4368,6 @@ int qseecom_start_app(struct qseecom_handle **handle, return 0; err: - kfree(data->sglistinfo_ptr); kfree(data); kfree(*handle); *handle = NULL; @@ -4287,7 +4415,6 @@ int qseecom_shutdown_app(struct qseecom_handle **handle) mutex_unlock(&app_access_lock); if (ret == 0) { - kzfree(data->sglistinfo_ptr); kzfree(data); kzfree(*handle); kzfree(kclient); @@ -4353,8 +4480,11 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, } perf_enabled = true; } + if (!strcmp(data->client.app_name, "securemm")) + data->use_legacy_cmd = true; ret = __qseecom_send_cmd(data, &req); + data->use_legacy_cmd = false; if (qseecom.support_bus_scaling) __qseecom_add_bw_scale_down_timer( QSEECOM_SEND_CMD_CRYPTO_TIMEOUT); @@ -7030,6 +7160,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) wake_up_all(&data->abort_wq); if (ret) pr_err("failed qseecom_send_mod_resp: %d\n", ret); + __qseecom_clean_data_sglistinfo(data); break; } case QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ: { @@ -7179,12 +7310,6 @@ static int qseecom_open(struct inode *inode, struct file *file) data->mode = INACTIVE; init_waitqueue_head(&data->abort_wq); atomic_set(&data->ioctl_count, 0); - - data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); - if (!(data->sglistinfo_ptr)) { - kzfree(data); - return -ENOMEM; - } return ret; } @@ -7239,7 +7364,6 @@ static int qseecom_release(struct inode *inode, struct file *file) if (data->perf_enabled == true) qsee_disable_clock_vote(data, CLK_DFAB); } - kfree(data->sglistinfo_ptr); kfree(data); return ret; @@ -7988,73 +8112,14 @@ out: } /* - * Check if whitelist feature is supported by making a test scm_call - * to send a whitelist command to an invalid app ID 0 + * Check whitelist feature, and if TZ feature version is < 1.0.0, + * then whitelist feature is not supported. */ static int qseecom_check_whitelist_feature(void) { - struct qseecom_client_send_data_ireq send_data_req = {0}; - struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0}; - struct qseecom_command_scm_resp resp; - uint32_t buf_size = 128; - void *buf = NULL; - void *cmd_buf = NULL; - size_t cmd_len; - int ret = 0; - phys_addr_t pa; + int version = scm_get_feat_version(FEATURE_ID_WHITELIST); - buf = kzalloc(buf_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - pa = virt_to_phys(buf); - if (qseecom.qsee_version < QSEE_VERSION_40) { - send_data_req.qsee_cmd_id = - QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; - send_data_req.app_id = 0; - send_data_req.req_ptr = (uint32_t)pa; - send_data_req.req_len = buf_size; - send_data_req.rsp_ptr = (uint32_t)pa; - send_data_req.rsp_len = buf_size; - send_data_req.sglistinfo_ptr = (uint32_t)pa; - send_data_req.sglistinfo_len = buf_size; - cmd_buf = (void *)&send_data_req; - cmd_len = sizeof(struct qseecom_client_send_data_ireq); - } else { - send_data_req_64bit.qsee_cmd_id = - QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; - send_data_req_64bit.app_id = 0; - send_data_req_64bit.req_ptr = (uint64_t)pa; - send_data_req_64bit.req_len = buf_size; - send_data_req_64bit.rsp_ptr = (uint64_t)pa; - send_data_req_64bit.rsp_len = buf_size; - send_data_req_64bit.sglistinfo_ptr = (uint64_t)pa; - send_data_req_64bit.sglistinfo_len = buf_size; - cmd_buf = (void *)&send_data_req_64bit; - cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); - } - ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, - cmd_buf, cmd_len, - &resp, sizeof(resp)); -/* - * If this cmd exists and whitelist is supported, scm_call return -2 (scm - * driver remap it to -EINVAL) and resp.result 0xFFFFFFED(-19); Otherwise, - * scm_call return -1 (remap to -EIO). - */ - if (ret == -EIO) { - qseecom.whitelist_support = false; - ret = 0; - } else if (ret == -EINVAL && - resp.result == QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD) { - qseecom.whitelist_support = true; - ret = 0; - } else { - pr_info("Check whitelist with ret = %d, result = 0x%x\n", - ret, resp.result); - qseecom.whitelist_support = false; - ret = 0; - } - kfree(buf); - return ret; + return version >= MAKE_WHITELIST_VERSION(1, 0, 0); } static int qseecom_probe(struct platform_device *pdev) @@ -8305,11 +8370,7 @@ static int qseecom_probe(struct platform_device *pdev) qseecom.qsee_perf_client = msm_bus_scale_register_client( qseecom_platform_support); - rc = qseecom_check_whitelist_feature(); - if (rc) { - rc = -EINVAL; - goto exit_destroy_ion_client; - } + qseecom.whitelist_support = qseecom_check_whitelist_feature(); pr_warn("qseecom.whitelist_support = %d\n", qseecom.whitelist_support); diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c index 5ca0307a3274..b9faae0278c9 100644 --- a/drivers/net/wireless/ath/wil6210/pmc.c +++ b/drivers/net/wireless/ath/wil6210/pmc.c @@ -54,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, struct pmc_ctx *pmc = &wil->pmc; struct device *dev = wil_to_dev(wil); struct wmi_pmc_cmd pmc_cmd = {0}; + int last_cmd_err = -ENOMEM; mutex_lock(&pmc->lock); @@ -62,6 +63,29 @@ void wil_pmc_alloc(struct wil6210_priv *wil, wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__); goto no_release_err; } + if ((num_descriptors <= 0) || (descriptor_size <= 0)) { + wil_err(wil, + "Invalid params num_descriptors(%d), descriptor_size(%d)\n", + num_descriptors, descriptor_size); + last_cmd_err = -EINVAL; + goto no_release_err; + } + + if (num_descriptors > (1 << WIL_RING_SIZE_ORDER_MAX)) { + wil_err(wil, + "num_descriptors(%d) exceeds max ring size %d\n", + num_descriptors, 1 << WIL_RING_SIZE_ORDER_MAX); + last_cmd_err = -EINVAL; + goto no_release_err; + } + + if (num_descriptors > INT_MAX / descriptor_size) { + wil_err(wil, + "Overflow in num_descriptors(%d)*descriptor_size(%d)\n", + num_descriptors, descriptor_size); + last_cmd_err = -EINVAL; + goto no_release_err; + } pmc->num_descriptors = num_descriptors; pmc->descriptor_size = descriptor_size; @@ -189,7 +213,7 @@ release_pmc_skb_list: pmc->descriptors = NULL; no_release_err: - pmc->last_cmd_status = -ENOMEM; + pmc->last_cmd_status = last_cmd_err; mutex_unlock(&pmc->lock); } @@ -295,7 +319,7 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, size_t retval = 0; unsigned long long idx; loff_t offset; - size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors; + size_t pmc_size; mutex_lock(&pmc->lock); @@ -306,6 +330,8 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, return -EPERM; } + pmc_size = pmc->descriptor_size * pmc->num_descriptors; + wil_dbg_misc(wil, "%s: size %u, pos %lld\n", __func__, (unsigned)count, *f_pos); @@ -345,7 +371,18 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence) loff_t newpos; struct wil6210_priv *wil = filp->private_data; struct pmc_ctx *pmc = &wil->pmc; - size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors; + size_t pmc_size; + + mutex_lock(&pmc->lock); + + if (!wil_is_pmc_allocated(pmc)) { + wil_err(wil, "error, pmc is not allocated!\n"); + pmc->last_cmd_status = -EPERM; + mutex_unlock(&pmc->lock); + return -EPERM; + } + + pmc_size = pmc->descriptor_size * pmc->num_descriptors; switch (whence) { case 0: /* SEEK_SET */ @@ -361,15 +398,21 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence) break; default: /* can't happen */ - return -EINVAL; + newpos = -EINVAL; + goto out; } - if (newpos < 0) - return -EINVAL; + if (newpos < 0) { + newpos = -EINVAL; + goto out; + } if (newpos > pmc_size) newpos = pmc_size; filp->f_pos = newpos; +out: + mutex_unlock(&pmc->lock); + return newpos; } diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c index 154310020997..2dd18dd78677 100644 --- a/drivers/nfc/nq-nci.c +++ b/drivers/nfc/nq-nci.c @@ -53,6 +53,7 @@ struct nqx_dev { struct mutex read_mutex; struct i2c_client *client; struct miscdevice nqx_device; + union nqx_uinfo nqx_info; /* NFC GPIO variables */ unsigned int irq_gpio; unsigned int en_gpio; @@ -467,6 +468,25 @@ int nfc_ioctl_core_reset_ntf(struct file *filp) return nqx_dev->core_reset_ntf; } +/* + * Inside nfc_ioctl_nfcc_info + * + * @brief nfc_ioctl_nfcc_info + * + * Check the NQ Chipset and firmware version details + */ +unsigned int nfc_ioctl_nfcc_info(struct file *filp, unsigned long arg) +{ + unsigned int r = 0; + struct nqx_dev *nqx_dev = filp->private_data; + + r = nqx_dev->nqx_info.i; + dev_dbg(&nqx_dev->client->dev, + "nqx nfc : nfc_ioctl_nfcc_info r = %d\n", r); + + return r; +} + static long nfc_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) { @@ -489,6 +509,9 @@ static long nfc_ioctl(struct file *pfile, unsigned int cmd, case NFCC_INITIAL_CORE_RESET_NTF: r = nfc_ioctl_core_reset_ntf(pfile); break; + case NFCC_GET_INFO: + r = nfc_ioctl_nfcc_info(pfile, arg); + break; default: r = -ENOIOCTLCMD; } @@ -508,13 +531,16 @@ static const struct file_operations nfc_dev_fops = { }; /* Check for availability of NQ_ NFC controller hardware */ -static int nfcc_hw_check(struct i2c_client *client, unsigned int enable_gpio) +static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) { int ret = 0; unsigned char raw_nci_reset_cmd[] = {0x20, 0x00, 0x01, 0x00}; + unsigned char raw_nci_init_cmd[] = {0x20, 0x01, 0x00}; + unsigned char nci_init_rsp[28]; unsigned char nci_reset_rsp[6]; - + unsigned char init_rsp_len = 0; + unsigned int enable_gpio = nqx_dev->en_gpio; /* making sure that the NFCC starts in a clean state. */ gpio_set_value(enable_gpio, 0);/* ULPM: Disable */ /* hardware dependent delay */ @@ -536,16 +562,75 @@ static int nfcc_hw_check(struct i2c_client *client, unsigned int enable_gpio) /* Read Response of RESET command */ ret = i2c_master_recv(client, nci_reset_rsp, - sizeof(nci_reset_rsp)); + sizeof(nci_reset_rsp)); dev_err(&client->dev, - "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n", - __func__, nci_reset_rsp[0], - nci_reset_rsp[1], nci_reset_rsp[2]); + "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n", + __func__, nci_reset_rsp[0], + nci_reset_rsp[1], nci_reset_rsp[2]); + if (ret < 0) { + dev_err(&client->dev, + "%s: - i2c_master_recv Error\n", __func__); + goto err_nfcc_hw_check; + } + ret = i2c_master_send(client, raw_nci_init_cmd, + sizeof(raw_nci_init_cmd)); + if (ret < 0) { + dev_err(&client->dev, + "%s: - i2c_master_send Error\n", __func__); + goto err_nfcc_hw_check; + } + /* hardware dependent delay */ + msleep(30); + /* Read Response of INIT command */ + ret = i2c_master_recv(client, nci_init_rsp, + sizeof(nci_init_rsp)); if (ret < 0) { dev_err(&client->dev, "%s: - i2c_master_recv Error\n", __func__); goto err_nfcc_hw_check; } + init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/ + if (init_rsp_len > PAYLOAD_HEADER_LENGTH) { + nqx_dev->nqx_info.info.chip_type = + nci_init_rsp[init_rsp_len - 3]; + nqx_dev->nqx_info.info.rom_version = + nci_init_rsp[init_rsp_len - 2]; + nqx_dev->nqx_info.info.fw_major = + nci_init_rsp[init_rsp_len - 1]; + nqx_dev->nqx_info.info.fw_minor = + nci_init_rsp[init_rsp_len]; + } + dev_dbg(&nqx_dev->client->dev, "NQ NFCC chip_type = %x\n", + nqx_dev->nqx_info.info.chip_type); + dev_dbg(&nqx_dev->client->dev, "NQ fw version = %x.%x.%x\n", + nqx_dev->nqx_info.info.rom_version, + nqx_dev->nqx_info.info.fw_major, + nqx_dev->nqx_info.info.fw_minor); + + switch (nqx_dev->nqx_info.info.chip_type) { + case NFCC_NQ_210: + dev_dbg(&client->dev, + "%s: ## NFCC == NQ210 ##\n", __func__); + break; + case NFCC_NQ_220: + dev_dbg(&client->dev, + "%s: ## NFCC == NQ220 ##\n", __func__); + break; + case NFCC_NQ_310: + dev_dbg(&client->dev, + "%s: ## NFCC == NQ310 ##\n", __func__); + break; + case NFCC_NQ_330: + dev_dbg(&client->dev, + "%s: ## NFCC == NQ330 ##\n", __func__); + break; + default: + dev_err(&client->dev, + "%s: - NFCC HW not Supported\n", __func__); + break; + } + + /*Disable NFC by default to save power on boot*/ gpio_set_value(enable_gpio, 0);/* ULPM: Disable */ ret = 0; goto done; @@ -566,9 +651,7 @@ done: static int nqx_clock_select(struct nqx_dev *nqx_dev) { int r = 0; - - nqx_dev->s_clk = - clk_get(&nqx_dev->client->dev, "ref_clk"); + nqx_dev->s_clk = clk_get(&nqx_dev->client->dev, "ref_clk"); if (nqx_dev->s_clk == NULL) goto err_clk; @@ -867,8 +950,7 @@ static int nqx_probe(struct i2c_client *client, * present before attempting further hardware initialisation. * */ - - r = nfcc_hw_check(client, platform_data->en_gpio); + r = nfcc_hw_check(client, nqx_dev); if (r) { /* make sure NFCC is not enabled */ gpio_set_value(platform_data->en_gpio, 0); diff --git a/drivers/nfc/nq-nci.h b/drivers/nfc/nq-nci.h index d62100c2d15a..c635e818b1f3 100644 --- a/drivers/nfc/nq-nci.h +++ b/drivers/nfc/nq-nci.h @@ -22,6 +22,7 @@ #include <linux/ioctl.h> #include <linux/miscdevice.h> +#include <linux/nfcinfo.h> #define NFC_SET_PWR _IOW(0xE9, 0x01, unsigned int) #define ESE_SET_PWR _IOW(0xE9, 0x02, unsigned int) @@ -42,4 +43,12 @@ enum nfcc_initial_core_reset_ntf { DEFAULT_INITIAL_CORE_RESET_NTF, /*2*/ }; +enum nfcc_chip_variant { + NFCC_NQ_210 = 0x48, /**< NFCC NQ210 */ + NFCC_NQ_220 = 0x58, /**< NFCC NQ220 */ + NFCC_NQ_310 = 0x40, /**< NFCC NQ310 */ + NFCC_NQ_330 = 0x51, /**< NFCC NQ330 */ + NFCC_NOT_SUPPORTED = 0xFF /**< NFCC is not supported */ +}; + #endif diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index 14af8ca66d1c..240bf2903308 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -619,6 +619,7 @@ struct msm_pcie_dev_t { bool ext_ref_clk; bool common_phy; uint32_t ep_latency; + uint32_t wr_halt_size; uint32_t cpl_timeout; uint32_t current_bdf; short current_short_bdf; @@ -1976,6 +1977,8 @@ static void msm_pcie_show_status(struct msm_pcie_dev_t *dev) dev->common_phy); PCIE_DBG_FS(dev, "ep_latency: %dms\n", dev->ep_latency); + PCIE_DBG_FS(dev, "wr_halt_size: 0x%x\n", + dev->wr_halt_size); PCIE_DBG_FS(dev, "cpl_timeout: 0x%x\n", dev->cpl_timeout); PCIE_DBG_FS(dev, "current_bdf: 0x%x\n", @@ -4495,8 +4498,19 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) if (dev->use_msi) { PCIE_DBG(dev, "RC%d: enable WR halt.\n", dev->rc_idx); - msm_pcie_write_mask(dev->parf + - PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT, 0, BIT(31)); + val = dev->wr_halt_size ? dev->wr_halt_size : + readl_relaxed(dev->parf + + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); + + msm_pcie_write_reg(dev->parf, + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT, + BIT(31) | val); + + PCIE_DBG(dev, + "RC%d: PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT: 0x%x.\n", + dev->rc_idx, + readl_relaxed(dev->parf + + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT)); } mutex_lock(&com_phy_lock); @@ -5385,9 +5399,6 @@ static irqreturn_t handle_linkdown_irq(int irq, void *data) dev->link_status = MSM_PCIE_LINK_DISABLED; dev->shadow_en = false; - pcie_phy_dump(dev); - pcie_parf_dump(dev); - if (dev->linkdown_panic) panic("User has chosen to panic on linkdown\n"); @@ -5420,7 +5431,7 @@ static irqreturn_t handle_msi_irq(int irq, void *data) struct msm_pcie_dev_t *dev = data; void __iomem *ctrl_status; - PCIE_DBG(dev, "irq=%d\n", irq); + PCIE_DUMP(dev, "irq: %d\n", irq); /* check for set bits, clear it by setting that bit and trigger corresponding irq */ @@ -5696,7 +5707,7 @@ static int arch_setup_msi_irq_qgic(struct pci_dev *pdev, irq_set_msi_desc(firstirq, desc); msg.address_hi = 0; msg.address_lo = dev->msi_gicm_addr; - msg.data = dev->msi_gicm_base; + msg.data = dev->msi_gicm_base + (firstirq - dev->msi[0].num); write_msi_msg(firstirq, &msg); return 0; @@ -6071,6 +6082,18 @@ static int msm_pcie_probe(struct platform_device *pdev) PCIE_DBG(&msm_pcie_dev[rc_idx], "RC%d: ep-latency: 0x%x.\n", rc_idx, msm_pcie_dev[rc_idx].ep_latency); + msm_pcie_dev[rc_idx].wr_halt_size = 0; + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,wr-halt-size", + &msm_pcie_dev[rc_idx].wr_halt_size); + if (ret) + PCIE_DBG(&msm_pcie_dev[rc_idx], + "RC%d: wr-halt-size not specified in dt. Use default value.\n", + rc_idx); + else + PCIE_DBG(&msm_pcie_dev[rc_idx], "RC%d: wr-halt-size: 0x%x.\n", + rc_idx, msm_pcie_dev[rc_idx].wr_halt_size); + msm_pcie_dev[rc_idx].cpl_timeout = 0; ret = of_property_read_u32((&pdev->dev)->of_node, "qcom,cpl-timeout", diff --git a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c index 45db409eb7c1..3678f952fe0f 100644 --- a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c +++ b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c @@ -354,6 +354,8 @@ enum msmfalcon_functions { msm_mux_blsp_i2c2, msm_mux_phase_flag31, msm_mux_blsp_spi3, + msm_mux_blsp_spi3_cs1, + msm_mux_blsp_spi3_cs2, msm_mux_wlan1_adc1, msm_mux_atest_usb13, msm_mux_tgu_ch1, @@ -380,7 +382,10 @@ enum msmfalcon_functions { msm_mux_blsp_spi4, msm_mux_pri_mi2s, msm_mux_phase_flag26, - msm_mux_qdss_cti, + msm_mux_qdss_cti0_a, + msm_mux_qdss_cti0_b, + msm_mux_qdss_cti1_a, + msm_mux_qdss_cti1_b, msm_mux_DP_HOT, msm_mux_pri_mi2s_ws, msm_mux_phase_flag27, @@ -402,7 +407,8 @@ enum msmfalcon_functions { msm_mux_phase_flag13, msm_mux_vsense_mode, msm_mux_blsp_spi7, - msm_mux_BLSP_UART, + msm_mux_blsp_uart6_a, + msm_mux_blsp_uart6_b, msm_mux_sec_mi2s, msm_mux_sndwire_clk, msm_mux_phase_flag17, @@ -415,13 +421,15 @@ enum msmfalcon_functions { msm_mux_vfr_1, msm_mux_phase_flag20, msm_mux_NFC_INT, - msm_mux_blsp_spi, + msm_mux_blsp_spi8_cs1, + msm_mux_blsp_spi8_cs2, 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_blsp_i2c8_a, + msm_mux_blsp_i2c8_b, msm_mux_phase_flag23, msm_mux_NFC_ESE, msm_mux_pwr_modem, @@ -519,10 +527,15 @@ enum msmfalcon_functions { msm_mux_atest_char0, msm_mux_US_EURO, msm_mux_LCD_BACKLIGHT, - msm_mux_blsp_spi8, + msm_mux_blsp_spi8_a, + msm_mux_blsp_spi8_b, msm_mux_sp_cmu, - msm_mux_NAV_PPS, - msm_mux_GPS_TX, + msm_mux_nav_pps_a, + msm_mux_nav_pps_b, + msm_mux_nav_pps_c, + msm_mux_gps_tx_a, + msm_mux_gps_tx_b, + msm_mux_gps_tx_c, msm_mux_adsp_ext, msm_mux_TS_RESET, msm_mux_ssc_irq, @@ -560,16 +573,23 @@ static const char * const blsp_spi1_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio46", }; static const char * const gpio_groups[] = { - "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", + "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", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", "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", + "gpio111", "gpio112", "gpio113", }; static const char * const blsp_uim1_groups[] = { "gpio0", "gpio1", @@ -599,7 +619,13 @@ static const char * const phase_flag31_groups[] = { "gpio6", }; static const char * const blsp_spi3_groups[] = { - "gpio8", "gpio9", "gpio10", "gpio11", "gpio30", "gpio65", + "gpio8", "gpio9", "gpio10", "gpio11", +}; +static const char * const blsp_spi3_cs1_groups[] = { + "gpio30", +}; +static const char * const blsp_spi3_cs2_groups[] = { + "gpio65", }; static const char * const wlan1_adc1_groups[] = { "gpio8", @@ -679,9 +705,17 @@ static const char * const pri_mi2s_groups[] = { static const char * const phase_flag26_groups[] = { "gpio12", }; -static const char * const qdss_cti_groups[] = { - "gpio12", "gpio13", "gpio21", "gpio49", "gpio50", "gpio53", "gpio55", - "gpio66", +static const char * const qdss_cti0_a_groups[] = { + "gpio49", "gpio50", +}; +static const char * const qdss_cti0_b_groups[] = { + "gpio13", "gpio21", +}; +static const char * const qdss_cti1_a_groups[] = { + "gpio53", "gpio55", +}; +static const char * const qdss_cti1_b_groups[] = { + "gpio12", "gpio66", }; static const char * const DP_HOT_groups[] = { "gpio13", @@ -746,9 +780,11 @@ static const char * const vsense_mode_groups[] = { static const char * const blsp_spi7_groups[] = { "gpio24", "gpio25", "gpio26", "gpio27", }; -static const char * const BLSP_UART_groups[] = { - "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", - "gpio31", +static const char * const blsp_uart6_a_groups[] = { + "gpio24", "gpio25", "gpio26", "gpio27", +}; +static const char * const blsp_uart6_b_groups[] = { + "gpio28", "gpio29", "gpio30", "gpio31", }; static const char * const sec_mi2s_groups[] = { "gpio24", "gpio25", "gpio26", "gpio27", "gpio62", @@ -786,9 +822,11 @@ static const char * const phase_flag20_groups[] = { static const char * const NFC_INT_groups[] = { "gpio28", }; -static const char * const blsp_spi_groups[] = { - "gpio28", "gpio29", "gpio30", "gpio31", "gpio40", "gpio41", "gpio44", - "gpio52", +static const char * const blsp_spi8_a_groups[] = { + "gpio28", "gpio29", "gpio30", "gpio31", +}; +static const char * const blsp_spi8_b_groups[] = { + "gpio40", "gpio41", "gpio44", "gpio52", }; static const char * const m_voc_groups[] = { "gpio28", @@ -805,8 +843,11 @@ static const char * const phase_flag22_groups[] = { static const char * const NFC_DWL_groups[] = { "gpio30", }; -static const char * const BLSP_I2C_groups[] = { - "gpio30", "gpio31", "gpio44", "gpio52", +static const char * const blsp_i2c8_a_groups[] = { + "gpio30", "gpio31", +}; +static const char * const blsp_i2c8_b_groups[] = { + "gpio44", "gpio52", }; static const char * const phase_flag23_groups[] = { "gpio30", @@ -1099,17 +1140,32 @@ static const char * const US_EURO_groups[] = { static const char * const LCD_BACKLIGHT_groups[] = { "gpio64", }; -static const char * const blsp_spi8_groups[] = { - "gpio64", "gpio76", +static const char * const blsp_spi8_cs1_groups[] = { + "gpio64", +}; +static const char * const blsp_spi8_cs2_groups[] = { + "gpio76", }; static const char * const sp_cmu_groups[] = { "gpio64", }; -static const char * const NAV_PPS_groups[] = { - "gpio65", "gpio65", "gpio80", "gpio80", "gpio98", "gpio98", +static const char * const nav_pps_a_groups[] = { + "gpio65", }; -static const char * const GPS_TX_groups[] = { - "gpio65", "gpio80", "gpio98", +static const char * const nav_pps_b_groups[] = { + "gpio98", +}; +static const char * const nav_pps_c_groups[] = { + "gpio80", +}; +static const char * const gps_tx_a_groups[] = { + "gpio65", +}; +static const char * const gps_tx_b_groups[] = { + "gpio98", +}; +static const char * const gps_tx_c_groups[] = { + "gpio80", }; static const char * const adsp_ext_groups[] = { "gpio65", @@ -1216,6 +1272,8 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(blsp_i2c2), FUNCTION(phase_flag31), FUNCTION(blsp_spi3), + FUNCTION(blsp_spi3_cs1), + FUNCTION(blsp_spi3_cs2), FUNCTION(wlan1_adc1), FUNCTION(atest_usb13), FUNCTION(tgu_ch1), @@ -1242,7 +1300,10 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(blsp_spi4), FUNCTION(pri_mi2s), FUNCTION(phase_flag26), - FUNCTION(qdss_cti), + FUNCTION(qdss_cti0_a), + FUNCTION(qdss_cti0_b), + FUNCTION(qdss_cti1_a), + FUNCTION(qdss_cti1_b), FUNCTION(DP_HOT), FUNCTION(pri_mi2s_ws), FUNCTION(phase_flag27), @@ -1264,7 +1325,8 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(phase_flag13), FUNCTION(vsense_mode), FUNCTION(blsp_spi7), - FUNCTION(BLSP_UART), + FUNCTION(blsp_uart6_a), + FUNCTION(blsp_uart6_b), FUNCTION(sec_mi2s), FUNCTION(sndwire_clk), FUNCTION(phase_flag17), @@ -1277,13 +1339,15 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(vfr_1), FUNCTION(phase_flag20), FUNCTION(NFC_INT), - FUNCTION(blsp_spi), + FUNCTION(blsp_spi8_cs1), + FUNCTION(blsp_spi8_cs2), FUNCTION(m_voc), FUNCTION(phase_flag21), FUNCTION(NFC_EN), FUNCTION(phase_flag22), FUNCTION(NFC_DWL), - FUNCTION(BLSP_I2C), + FUNCTION(blsp_i2c8_a), + FUNCTION(blsp_i2c8_b), FUNCTION(phase_flag23), FUNCTION(NFC_ESE), FUNCTION(pwr_modem), @@ -1381,10 +1445,15 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(atest_char0), FUNCTION(US_EURO), FUNCTION(LCD_BACKLIGHT), - FUNCTION(blsp_spi8), + FUNCTION(blsp_spi8_a), + FUNCTION(blsp_spi8_b), FUNCTION(sp_cmu), - FUNCTION(NAV_PPS), - FUNCTION(GPS_TX), + FUNCTION(nav_pps_a), + FUNCTION(nav_pps_b), + FUNCTION(nav_pps_c), + FUNCTION(gps_tx_a), + FUNCTION(gps_tx_b), + FUNCTION(gps_tx_c), FUNCTION(adsp_ext), FUNCTION(TS_RESET), FUNCTION(ssc_irq), @@ -1441,10 +1510,10 @@ static const struct msm_pingroup msmfalcon_groups[] = { 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, + PINGROUP(12, NORTH, blsp_spi4, pri_mi2s, NA, phase_flag26, qdss_cti1_b, NA, NA, NA, NA), PINGROUP(13, NORTH, blsp_spi4, DP_HOT, pri_mi2s_ws, NA, NA, - phase_flag27, qdss_cti, NA, NA), + phase_flag27, qdss_cti0_b, NA, NA), PINGROUP(14, NORTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, phase_flag28, NA, NA, NA, NA), PINGROUP(15, NORTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, NA, NA, NA, NA, @@ -1460,27 +1529,27 @@ static const struct msm_pingroup msmfalcon_groups[] = { 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), + qdss_cti0_b, vsense_data0, NA, NA), PINGROUP(22, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA, phase_flag12, vsense_data1, NA, NA, NA), PINGROUP(23, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA, phase_flag13, vsense_mode, NA, NA, NA), - PINGROUP(24, NORTH, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_clk, NA, + PINGROUP(24, NORTH, blsp_spi7, blsp_uart6_a, sec_mi2s, sndwire_clk, NA, NA, phase_flag17, vsense_clkout, NA), - PINGROUP(25, NORTH, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_data, NA, + PINGROUP(25, NORTH, blsp_spi7, blsp_uart6_a, sec_mi2s, sndwire_data, NA, NA, phase_flag18, NA, NA), - PINGROUP(26, NORTH, blsp_spi7, BLSP_UART, blsp_i2c7, sec_mi2s, NA, + PINGROUP(26, NORTH, blsp_spi7, blsp_uart6_a, blsp_i2c7, sec_mi2s, NA, phase_flag19, NA, NA, NA), - PINGROUP(27, NORTH, blsp_spi7, BLSP_UART, blsp_i2c7, vfr_1, sec_mi2s, + PINGROUP(27, NORTH, blsp_spi7, blsp_uart6_a, 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, CENTER, blsp_spi, BLSP_UART, NA, NA, phase_flag22, 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(28, CENTER, blsp_spi8_a, blsp_uart6_b, m_voc, NA, phase_flag21, + NA, NA, NA, NA), + PINGROUP(29, CENTER, blsp_spi8_a, blsp_uart6_b, NA, NA, phase_flag22, + NA, NA, NA, NA), + PINGROUP(30, CENTER, blsp_spi8_a, blsp_uart6_b, blsp_i2c8_a, + blsp_spi3_cs1, NA, phase_flag23, NA, NA, NA), + PINGROUP(31, CENTER, blsp_spi8_a, blsp_uart6_b, blsp_i2c8_a, 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, NA, @@ -1495,30 +1564,35 @@ static const struct msm_pingroup msmfalcon_groups[] = { 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(40, SOUTH, CCI_TIMER0, NA, blsp_spi8_b, NA, NA, NA, NA, NA, + NA), + PINGROUP(41, SOUTH, CCI_TIMER1, NA, blsp_spi8_b, NA, NA, NA, NA, NA, + NA), PINGROUP(42, SOUTH, mdss_vsync0, mdss_vsync1, mdss_vsync2, mdss_vsync3, 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(44, SOUTH, CCI_TIMER4, CCI_ASYNC, blsp_spi8_b, blsp_i2c8_b, 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(48, SOUTH, NA, phase_flag1, qdss_gpio15, NA, NA, 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, + PINGROUP(49, SOUTH, NA, phase_flag2, qdss_cti0_a, NA, NA, NA, NA, NA, NA), + PINGROUP(50, SOUTH, qspi_cs, NA, phase_flag9, qdss_cti0_a, NA, NA, NA, + NA, 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(52, SOUTH, CCI_TIMER2, blsp_spi8_b, blsp_i2c8_b, NA, + phase_flag16, qdss_gpio, NA, NA, NA), + PINGROUP(53, NORTH, NA, phase_flag6, qdss_cti1_a, 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(55, SOUTH, NA, phase_flag25, qdss_cti1_a, NA, NA, NA, NA, NA, + NA), PINGROUP(56, SOUTH, NA, phase_flag10, qdss_gpio3, NA, atest_usb20, NA, NA, NA, NA), PINGROUP(57, SOUTH, gcc_gp1, NA, phase_flag4, atest_usb22, NA, NA, NA, @@ -1533,11 +1607,11 @@ static const struct msm_pingroup msmfalcon_groups[] = { 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, NORTH, NA, NA, qdss_cti, NA, NA, NA, NA, NA, NA), + PINGROUP(64, SOUTH, blsp_spi8_cs1, sp_cmu, NA, NA, qdss_gpio2, NA, NA, + NA, NA), + PINGROUP(65, SOUTH, NA, nav_pps_a, nav_pps_a, gps_tx_a, blsp_spi3_cs2, + adsp_ext, NA, NA, NA), + PINGROUP(66, NORTH, NA, NA, qdss_cti1_b, 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), @@ -1550,12 +1624,13 @@ static const struct msm_pingroup msmfalcon_groups[] = { 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(76, NORTH, blsp_spi8_cs2, 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(80, SOUTH, nav_pps_b, nav_pps_b, gps_tx_c, 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), @@ -1573,8 +1648,8 @@ static const struct msm_pingroup msmfalcon_groups[] = { 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, 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(98, SOUTH, NA, nav_pps_c, nav_pps_c, gps_tx_b, 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), diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index 804c89dc9533..73add50cf224 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -4907,20 +4907,16 @@ int ipa_iommu_map(struct iommu_domain *domain, IPADBG("domain =0x%p iova 0x%lx\n", domain, iova); IPADBG("paddr =0x%pa size 0x%x\n", &paddr, (u32)size); - /* make sure no overlapping */ + /* Checking the address overlapping */ if (domain == ipa2_get_smmu_domain()) { if (iova >= ap_cb->va_start && iova < ap_cb->va_end) { IPAERR("iommu AP overlap addr 0x%lx\n", iova); - ipa_assert(); - return -EFAULT; } } else if (domain == ipa2_get_wlan_smmu_domain()) { /* wlan is one time map */ } else if (domain == ipa2_get_uc_smmu_domain()) { if (iova >= uc_cb->va_start && iova < uc_cb->va_end) { IPAERR("iommu uC overlap addr 0x%lx\n", iova); - ipa_assert(); - return -EFAULT; } } else { IPAERR("Unexpected domain 0x%p\n", domain); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c index 7e15bcfc84ff..d51e9ac97fe0 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c @@ -18,6 +18,7 @@ #include "ipa_i.h" #include "ipa_trace.h" +#define IPA_WAN_AGGR_PKT_CNT 5 #define IPA_LAST_DESC_CNT 0xFFFF #define POLLING_INACTIVITY_RX 40 #define POLLING_INACTIVITY_TX 40 @@ -1099,16 +1100,18 @@ int ipa2_rx_poll(u32 clnt_hdl, int weight) break; ipa_wq_rx_common(ep->sys, iov.size); - cnt += 5; + cnt += IPA_WAN_AGGR_PKT_CNT; }; - if (cnt == 0) { + if (cnt == 0 || cnt < weight) { ep->inactive_cycles++; ep->client_notify(ep->priv, IPA_CLIENT_COMP_NAPI, 0); if (ep->inactive_cycles > 3 || ep->sys->len == 0) { ep->switch_to_intr = true; delay = 0; + } else if (cnt < weight) { + delay = 0; } queue_delayed_work(ep->sys->wq, &ep->sys->switch_to_intr_work, msecs_to_jiffies(delay)); @@ -3168,14 +3171,9 @@ static int ipa_assign_policy_v2(struct ipa_sys_connect_params *in, sys->repl_hdlr = ipa_replenish_rx_cache; } - if (in->napi_enabled) { - sys->rx_pool_sz = - IPA_WAN_NAPI_CONS_RX_POOL_SZ; - if (in->recycle_enabled) { - sys->repl_hdlr = - ipa_replenish_rx_cache_recycle; - } - } + if (in->napi_enabled && in->recycle_enabled) + sys->repl_hdlr = + ipa_replenish_rx_cache_recycle; sys->ep->wakelock_client = IPA_WAKELOCK_REF_CLIENT_WAN_RX; in->ipa_ep_cfg.aggr.aggr_sw_eof_active diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index 73206abf9cfd..866170d3324d 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -51,8 +51,6 @@ #define IPA_UC_FINISH_MAX 6 #define IPA_UC_WAIT_MIN_SLEEP 1000 #define IPA_UC_WAII_MAX_SLEEP 1200 -#define IPA_WAN_NAPI_CONS_RX_POOL_SZ (IPA_GENERIC_RX_POOL_SZ*3) -#define IPA_WAN_CONS_DESC_FIFO_SZ (IPA_SYS_DESC_FIFO_SZ*3) #define IPA_MAX_STATUS_STAT_NUM 30 diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c index 520f139ee38a..c2e43a62ab69 100644 --- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c @@ -62,6 +62,7 @@ #define IPA_UEVENT_NUM_EVNP 4 /* number of event pointers */ #define NAPI_WEIGHT 60 +#define IPA_WWAN_CONS_DESC_FIFO_SZ 1024 static struct net_device *ipa_netdevs[IPA_WWAN_DEVICE_COUNT]; static struct ipa_sys_connect_params apps_to_ipa_ep_cfg, ipa_to_apps_ep_cfg; @@ -100,6 +101,7 @@ struct ipa_rmnet_plat_drv_res { bool ipa_loaduC; bool ipa_advertise_sg_support; bool ipa_napi_enable; + u32 wan_rx_desc_size; }; static struct ipa_rmnet_plat_drv_res ipa_rmnet_res; @@ -1291,10 +1293,8 @@ static int handle_ingress_format(struct net_device *dev, ipa_to_apps_ep_cfg.priv = dev; ipa_to_apps_ep_cfg.napi_enabled = ipa_rmnet_res.ipa_napi_enable; - if (ipa_to_apps_ep_cfg.napi_enabled) - ipa_to_apps_ep_cfg.desc_fifo_sz = IPA_WAN_CONS_DESC_FIFO_SZ; - else - ipa_to_apps_ep_cfg.desc_fifo_sz = IPA_SYS_DESC_FIFO_SZ; + ipa_to_apps_ep_cfg.desc_fifo_sz = + ipa_rmnet_res.wan_rx_desc_size * sizeof(struct sps_iovec); mutex_lock(&ipa_to_apps_pipe_handle_guard); if (atomic_read(&is_ssr)) { @@ -1925,6 +1925,9 @@ static struct notifier_block ssr_notifier = { static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev, struct ipa_rmnet_plat_drv_res *ipa_rmnet_drv_res) { + int result; + + ipa_rmnet_drv_res->wan_rx_desc_size = IPA_WWAN_CONS_DESC_FIFO_SZ; ipa_rmnet_drv_res->ipa_rmnet_ssr = of_property_read_bool(pdev->dev.of_node, "qcom,rmnet-ipa-ssr"); @@ -1947,6 +1950,18 @@ static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev, "qcom,ipa-napi-enable"); pr_info("IPA Napi Enable = %s\n", ipa_rmnet_drv_res->ipa_napi_enable ? "True" : "False"); + + /* Get IPA WAN RX desc fifo size */ + result = of_property_read_u32(pdev->dev.of_node, + "qcom,wan-rx-desc-size", + &ipa_rmnet_drv_res->wan_rx_desc_size); + if (result) + pr_info("using default for wan-rx-desc-size = %u\n", + ipa_rmnet_drv_res->wan_rx_desc_size); + else + IPAWANDBG(": found ipa_drv_res->wan-rx-desc-size = %u\n", + ipa_rmnet_drv_res->wan_rx_desc_size); + return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index cc1cb456ab8a..4b0cd46082a3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -21,6 +21,7 @@ #include "ipahal/ipahal.h" #include "ipahal/ipahal_fltrt.h" +#define IPA_WAN_AGGR_PKT_CNT 5 #define IPA_LAST_DESC_CNT 0xFFFF #define POLLING_INACTIVITY_RX 40 #define POLLING_MIN_SLEEP_RX 1010 @@ -60,7 +61,6 @@ #define IPA_ODU_RX_POOL_SZ 64 #define IPA_SIZE_DL_CSUM_META_TRAILER 8 -#define IPA_GSI_EVT_RING_LEN 4096 #define IPA_GSI_MAX_CH_LOW_WEIGHT 15 #define IPA_GSI_EVT_RING_INT_MODT 3200 /* 0.1s under 32KHz clock */ @@ -3298,9 +3298,6 @@ static int ipa3_assign_policy(struct ipa_sys_connect_params *in, sys->repl_hdlr = ipa3_replenish_rx_cache; } - if (in->napi_enabled) - sys->rx_pool_sz = - IPA_WAN_NAPI_CONS_RX_POOL_SZ; if (in->napi_enabled && in->recycle_enabled) sys->repl_hdlr = ipa3_replenish_rx_cache_recycle; @@ -3965,13 +3962,19 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in, gsi_evt_ring_props.re_size = GSI_EVT_RING_RE_SIZE_16B; - gsi_evt_ring_props.ring_len = IPA_GSI_EVT_RING_LEN; + /* + * GSI ring length is calculated based on the desc_fifo_sz + * which was meant to define the BAM desc fifo. GSI descriptors + * are 16B as opposed to 8B for BAM. + */ + gsi_evt_ring_props.ring_len = 2 * in->desc_fifo_sz; + gsi_evt_ring_props.ring_base_vaddr = - dma_alloc_coherent(ipa3_ctx->pdev, IPA_GSI_EVT_RING_LEN, - &evt_dma_addr, GFP_KERNEL); + dma_alloc_coherent(ipa3_ctx->pdev, + gsi_evt_ring_props.ring_len, &evt_dma_addr, GFP_KERNEL); if (!gsi_evt_ring_props.ring_base_vaddr) { IPAERR("fail to dma alloc %u bytes\n", - IPA_GSI_EVT_RING_LEN); + gsi_evt_ring_props.ring_len); return -ENOMEM; } gsi_evt_ring_props.ring_base_addr = evt_dma_addr; @@ -4098,7 +4101,7 @@ fail_get_gsi_ep_info: } fail_alloc_evt_ring: if (gsi_evt_ring_props.ring_base_vaddr) - dma_free_coherent(ipa3_ctx->pdev, IPA_GSI_EVT_RING_LEN, + dma_free_coherent(ipa3_ctx->pdev, gsi_evt_ring_props.ring_len, gsi_evt_ring_props.ring_base_vaddr, evt_dma_addr); IPAERR("Return with err: %d\n", result); return result; @@ -4280,16 +4283,18 @@ int ipa3_rx_poll(u32 clnt_hdl, int weight) break; ipa3_wq_rx_common(ep->sys, mem_info.size); - cnt += 5; + cnt += IPA_WAN_AGGR_PKT_CNT; }; - if (cnt == 0) { + if (cnt == 0 || cnt < weight) { ep->inactive_cycles++; ep->client_notify(ep->priv, IPA_CLIENT_COMP_NAPI, 0); if (ep->inactive_cycles > 3 || ep->sys->len == 0) { ep->switch_to_intr = true; delay = 0; + } else if (cnt < weight) { + delay = 0; } queue_delayed_work(ep->sys->wq, &ep->sys->switch_to_intr_work, msecs_to_jiffies(delay)); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 40f1e93653f9..1b78835cda6b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -53,8 +53,6 @@ #define IPA_UC_FINISH_MAX 6 #define IPA_UC_WAIT_MIN_SLEEP 1000 #define IPA_UC_WAII_MAX_SLEEP 1200 -#define IPA_WAN_NAPI_CONS_RX_POOL_SZ (IPA_GENERIC_RX_POOL_SZ*3) -#define IPA_WAN_CONS_DESC_FIFO_SZ (IPA_SYS_DESC_FIFO_SZ*3) #define IPA_MAX_STATUS_STAT_NUM 30 diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c index cb47773e8a39..21ce28204069 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c @@ -585,7 +585,9 @@ send_cmd: if (ipa3_ctx->uc_ctx.uc_status != expected_status) { if (ipa3_ctx->uc_ctx.uc_status == - IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE) { + IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE || + ipa3_ctx->uc_ctx.uc_status == + IPA_HW_CONS_DISABLE_CMD_GSI_STOP_FAILURE) { retries++; if (retries == IPA_GSI_CHANNEL_STOP_MAX_RETRY) { IPAERR("Failed after %d tries\n", retries); @@ -594,7 +596,9 @@ send_cmd: return -EFAULT; } IPA3_UC_UNLOCK(flags); - ipa3_inject_dma_task_for_gsi(); + if (ipa3_ctx->uc_ctx.uc_status == + IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE) + ipa3_inject_dma_task_for_gsi(); /* sleep for short period to flush IPA */ usleep_range(IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC, IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC); diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 8f6c303d2867..0419249890e9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -65,6 +65,7 @@ ((rmnet_ipa3_ctx && rmnet_ipa3_ctx->wwan_priv) ? \ rmnet_ipa3_ctx->wwan_priv->net : NULL) +#define IPA_WWAN_CONS_DESC_FIFO_SZ 256 static int ipa3_wwan_add_ul_flt_rule_to_ipa(void); static int ipa3_wwan_del_ul_flt_rule_to_ipa(void); @@ -89,6 +90,7 @@ struct ipa3_rmnet_plat_drv_res { bool ipa_loaduC; bool ipa_advertise_sg_support; bool ipa_napi_enable; + u32 wan_rx_desc_size; }; /** @@ -1275,7 +1277,7 @@ static int handle3_ingress_format(struct net_device *dev, ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_pkt_limit = in->u.ingress_format.agg_count; - if (ipa_wan_ep_cfg->napi_enabled) { + if (ipa3_rmnet_res.ipa_napi_enable) { ipa_wan_ep_cfg->recycle_enabled = true; ep_cfg = (struct rmnet_phys_ep_conf_s *) rcu_dereference(dev->rx_handler_data); @@ -1303,10 +1305,8 @@ static int handle3_ingress_format(struct net_device *dev, ipa_wan_ep_cfg->priv = dev; ipa_wan_ep_cfg->napi_enabled = ipa3_rmnet_res.ipa_napi_enable; - if (ipa_wan_ep_cfg->napi_enabled) - ipa_wan_ep_cfg->desc_fifo_sz = IPA_WAN_CONS_DESC_FIFO_SZ; - else - ipa_wan_ep_cfg->desc_fifo_sz = IPA_SYS_DESC_FIFO_SZ; + ipa_wan_ep_cfg->desc_fifo_sz = + ipa3_rmnet_res.wan_rx_desc_size * sizeof(struct sps_iovec); mutex_lock(&rmnet_ipa3_ctx->ipa_to_apps_pipe_handle_guard); @@ -1957,6 +1957,9 @@ static struct notifier_block ipa3_ssr_notifier = { static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev, struct ipa3_rmnet_plat_drv_res *ipa_rmnet_drv_res) { + int result; + + ipa_rmnet_drv_res->wan_rx_desc_size = IPA_WWAN_CONS_DESC_FIFO_SZ; ipa_rmnet_drv_res->ipa_rmnet_ssr = of_property_read_bool(pdev->dev.of_node, "qcom,rmnet-ipa-ssr"); @@ -1979,6 +1982,18 @@ static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev, "qcom,ipa-napi-enable"); pr_info("IPA Napi Enable = %s\n", ipa_rmnet_drv_res->ipa_napi_enable ? "True" : "False"); + + /* Get IPA WAN RX desc fifo size */ + result = of_property_read_u32(pdev->dev.of_node, + "qcom,wan-rx-desc-size", + &ipa_rmnet_drv_res->wan_rx_desc_size); + if (result) + pr_info("using default for wan-rx-desc-size = %u\n", + ipa_rmnet_drv_res->wan_rx_desc_size); + else + IPAWANDBG(": found ipa_drv_res->wan-rx-desc-size = %u\n", + ipa_rmnet_drv_res->wan_rx_desc_size); + return 0; } diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c index 45fedfa72bda..5810f7bf7f2f 100644 --- a/drivers/platform/msm/msm_11ad/msm_11ad.c +++ b/drivers/platform/msm/msm_11ad/msm_11ad.c @@ -51,6 +51,9 @@ #define VDDIO_MAX_UV 2040000 #define VDDIO_MAX_UA 70300 +#define DISABLE_PCIE_L1_MASK 0xFFFFFFFD +#define PCIE20_CAP_LINKCTRLSTATUS 0x80 + struct device; static const char * const gpio_en_name = "qcom,wigig-en"; @@ -505,6 +508,7 @@ static int ops_resume(void *handle) int rc; struct msm11ad_ctx *ctx = handle; struct pci_dev *pcidev; + u32 val; pr_info("%s(%p)\n", __func__, handle); if (!ctx) { @@ -548,6 +552,27 @@ static int ops_resume(void *handle) goto err_suspend_rc; } + /* Disable L1 */ + rc = pci_read_config_dword(ctx->pcidev, + PCIE20_CAP_LINKCTRLSTATUS, &val); + if (rc) { + dev_err(ctx->dev, + "reading PCIE20_CAP_LINKCTRLSTATUS failed:%d\n", + rc); + goto err_suspend_rc; + } + val &= DISABLE_PCIE_L1_MASK; /* disable bit 1 */ + dev_dbg(ctx->dev, "writing PCIE20_CAP_LINKCTRLSTATUS (val 0x%x)\n", + val); + rc = pci_write_config_dword(ctx->pcidev, + PCIE20_CAP_LINKCTRLSTATUS, val); + if (rc) { + dev_err(ctx->dev, + "writing PCIE20_CAP_LINKCTRLSTATUS (val 0x%x) failed:%d\n", + val, rc); + goto err_suspend_rc; + } + return 0; err_suspend_rc: @@ -792,6 +817,7 @@ static int msm_11ad_probe(struct platform_device *pdev) struct device_node *rc_node; struct pci_dev *pcidev = NULL; int rc; + u32 val; ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -907,6 +933,28 @@ static int msm_11ad_probe(struct platform_device *pdev) goto out_rc; } ctx->pcidev = pcidev; + + /* Disable L1 */ + rc = pci_read_config_dword(ctx->pcidev, + PCIE20_CAP_LINKCTRLSTATUS, &val); + if (rc) { + dev_err(ctx->dev, + "reading PCIE20_CAP_LINKCTRLSTATUS failed:%d\n", + rc); + goto out_rc; + } + val &= DISABLE_PCIE_L1_MASK; /* disable bit 1 */ + dev_dbg(ctx->dev, "writing PCIE20_CAP_LINKCTRLSTATUS (val 0x%x)\n", + val); + rc = pci_write_config_dword(ctx->pcidev, + PCIE20_CAP_LINKCTRLSTATUS, val); + if (rc) { + dev_err(ctx->dev, + "writing PCIE20_CAP_LINKCTRLSTATUS (val 0x%x) failed:%d\n", + val, rc); + goto out_rc; + } + rc = pci_save_state(pcidev); if (rc) { dev_err(ctx->dev, "pci_save_state failed :%d\n", rc); diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index cb5880189fbf..d612016b1b79 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -74,6 +74,7 @@ enum fg_debug_flag { FG_BUS_WRITE = BIT(5), /* Show REGMAP writes */ FG_BUS_READ = BIT(6), /* Show REGMAP reads */ FG_CAP_LEARN = BIT(7), /* Show capacity learning */ + FG_TTF = BIT(8), /* Show time to full */ }; /* SRAM access */ @@ -128,6 +129,7 @@ enum { */ enum fg_sram_param_id { FG_SRAM_BATT_SOC = 0, + FG_SRAM_FULL_SOC, FG_SRAM_VOLTAGE_PRED, FG_SRAM_OCV, FG_SRAM_RSLOW, @@ -250,6 +252,29 @@ struct fg_irq_info { int irq; }; +struct fg_circ_buf { + int arr[20]; + int size; + int head; +}; + +struct fg_pt { + s32 x; + s32 y; +}; + +static const struct fg_pt fg_ln_table[] = { + { 1000, 0 }, + { 2000, 693 }, + { 4000, 1386 }, + { 6000, 1792 }, + { 8000, 2079 }, + { 16000, 2773 }, + { 32000, 3466 }, + { 64000, 4159 }, + { 128000, 4852 }, +}; + struct fg_chip { struct device *dev; struct pmic_revid_data *pmic_rev_id; @@ -259,6 +284,7 @@ struct fg_chip { struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *dc_psy; + struct power_supply *parallel_psy; struct iio_channel *batt_id_chan; struct fg_memif *sram; struct fg_irq_info *irqs; @@ -274,12 +300,15 @@ struct fg_chip { struct fg_cap_learning cl; struct mutex bus_lock; struct mutex sram_rw_lock; + struct mutex batt_avg_lock; u32 batt_soc_base; u32 batt_info_base; u32 mem_if_base; int batt_id_kohms; - int status; + int charge_status; + int prev_charge_status; int charge_done; + int charge_type; int last_soc; int last_batt_temp; int health; @@ -290,11 +319,15 @@ struct fg_chip { bool charge_full; bool recharge_soc_adjusted; bool ki_coeff_dischg_en; + bool esr_fcc_ctrl_en; struct completion soc_update; struct completion soc_ready; struct delayed_work profile_load_work; struct work_struct status_change_work; struct work_struct cycle_count_work; + struct delayed_work batt_avg_work; + struct fg_circ_buf ibatt_circ_buf; + struct fg_circ_buf vbatt_circ_buf; }; /* Debugfs data structures are below */ @@ -339,9 +372,15 @@ extern int fg_read(struct fg_chip *chip, int addr, u8 *val, int len); extern int fg_write(struct fg_chip *chip, int addr, u8 *val, int len); extern int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val); extern int fg_ima_init(struct fg_chip *chip); +extern int fg_clear_ima_errors_if_any(struct fg_chip *chip, bool check_hw_sts); +extern int fg_clear_dma_errors_if_any(struct fg_chip *chip); extern int fg_debugfs_create(struct fg_chip *chip); extern void fill_string(char *str, size_t str_len, u8 *buf, int buf_len); extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos); extern s64 fg_float_decode(u16 val); extern bool is_input_present(struct fg_chip *chip); +extern void fg_circ_buf_add(struct fg_circ_buf *, int); +extern void fg_circ_buf_clr(struct fg_circ_buf *); +extern int fg_circ_buf_avg(struct fg_circ_buf *, int *); +extern int fg_lerp(const struct fg_pt *, size_t, s32, s32 *); #endif diff --git a/drivers/power/qcom-charger/fg-memif.c b/drivers/power/qcom-charger/fg-memif.c index c271b24adfc4..a98ff7d765e3 100644 --- a/drivers/power/qcom-charger/fg-memif.c +++ b/drivers/power/qcom-charger/fg-memif.c @@ -64,44 +64,90 @@ static int fg_config_access_mode(struct fg_chip *chip, bool access, bool burst) static int fg_run_iacs_clear_sequence(struct fg_chip *chip) { - u8 tmp; - int rc; + u8 val, hw_sts, exp_sts; + int rc, tries = 250; /* * Values to write for running IACS clear sequence comes from * hardware documentation. */ - rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), IACS_CLR_BIT, - IACS_CLR_BIT); + rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), + IACS_CLR_BIT | STATIC_CLK_EN_BIT, + IACS_CLR_BIT | STATIC_CLK_EN_BIT); if (rc < 0) { pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_IMA_CFG(chip), rc); return rc; } - tmp = 0x4; - rc = fg_write(chip, MEM_IF_ADDR_MSB(chip), &tmp, 1); + rc = fg_config_access_mode(chip, FG_READ, false); if (rc < 0) { - pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_ADDR_LSB(chip), - rc); + pr_err("failed to write to 0x%04x, rc=%d\n", + MEM_IF_IMA_CTL(chip), rc); return rc; } - tmp = 0x0; - rc = fg_write(chip, MEM_IF_WR_DATA3(chip), &tmp, 1); + rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip), + MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, + MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT); if (rc < 0) { - pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_WR_DATA3(chip), - rc); + pr_err("failed to set ima_req_access bit rc=%d\n", rc); return rc; } - rc = fg_read(chip, MEM_IF_RD_DATA3(chip), &tmp, 1); - if (rc < 0) { - pr_err("failed to read 0x%04x, rc=%d\n", MEM_IF_RD_DATA3(chip), - rc); - return rc; + /* Delay for the clock to reach FG */ + usleep_range(35, 40); + + while (1) { + val = 0; + rc = fg_write(chip, MEM_IF_ADDR_MSB(chip), &val, 1); + if (rc < 0) { + pr_err("failed to write 0x%04x, rc=%d\n", + MEM_IF_ADDR_MSB(chip), rc); + return rc; + } + + val = 0; + rc = fg_write(chip, MEM_IF_WR_DATA3(chip), &val, 1); + if (rc < 0) { + pr_err("failed to write 0x%04x, rc=%d\n", + MEM_IF_WR_DATA3(chip), rc); + return rc; + } + + rc = fg_read(chip, MEM_IF_RD_DATA3(chip), &val, 1); + if (rc < 0) { + pr_err("failed to read 0x%04x, rc=%d\n", + MEM_IF_RD_DATA3(chip), rc); + return rc; + } + + /* Delay for IMA hardware to clear */ + usleep_range(35, 40); + + rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1); + if (rc < 0) { + pr_err("failed to read ima_hw_sts rc=%d\n", rc); + return rc; + } + + if (hw_sts != 0) + continue; + + rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1); + if (rc < 0) { + pr_err("failed to read ima_exp_sts rc=%d\n", rc); + return rc; + } + + if (exp_sts == 0 || !(--tries)) + break; } + if (!tries) + pr_err("Failed to clear the error? hw_sts: %x exp_sts: %d\n", + hw_sts, exp_sts); + rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), IACS_CLR_BIT, 0); if (rc < 0) { pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_IMA_CFG(chip), @@ -109,14 +155,65 @@ static int fg_run_iacs_clear_sequence(struct fg_chip *chip) return rc; } + udelay(5); + + rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip), + MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0); + if (rc < 0) { + pr_err("failed to write to 0x%04x, rc=%d\n", + MEM_IF_MEM_INTF_CFG(chip), rc); + return rc; + } + + /* Delay before next transaction is attempted */ + usleep_range(35, 40); fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "IACS clear sequence complete\n"); return rc; } -static int fg_check_for_ima_errors(struct fg_chip *chip) +int fg_clear_dma_errors_if_any(struct fg_chip *chip) +{ + int rc; + u8 dma_sts; + + rc = fg_read(chip, MEM_IF_DMA_STS(chip), &dma_sts, 1); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + MEM_IF_DMA_STS(chip), rc); + return rc; + } + fg_dbg(chip, FG_STATUS, "dma_sts: %x\n", dma_sts); + + if (dma_sts & (DMA_WRITE_ERROR_BIT | DMA_READ_ERROR_BIT)) { + rc = fg_masked_write(chip, MEM_IF_DMA_CTL(chip), + DMA_CLEAR_LOG_BIT, DMA_CLEAR_LOG_BIT); + if (rc < 0) { + pr_err("failed to write addr=0x%04x, rc=%d\n", + MEM_IF_DMA_CTL(chip), rc); + return rc; + } + } + + return 0; +} + +int fg_clear_ima_errors_if_any(struct fg_chip *chip, bool check_hw_sts) { int rc = 0; u8 err_sts, exp_sts = 0, hw_sts = 0; + bool run_err_clr_seq = false; + + rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1); + if (rc < 0) { + pr_err("failed to read ima_exp_sts rc=%d\n", rc); + return rc; + } + + rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1); + if (rc < 0) { + pr_err("failed to read ima_hw_sts rc=%d\n", rc); + return rc; + } rc = fg_read(chip, MEM_IF_IMA_ERR_STS(chip), &err_sts, 1); if (rc < 0) { @@ -124,22 +221,30 @@ static int fg_check_for_ima_errors(struct fg_chip *chip) return rc; } - if (err_sts & (ADDR_STBL_ERR_BIT | WR_ACS_ERR_BIT | RD_ACS_ERR_BIT)) { - rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1); - if (rc < 0) { - pr_err("failed to read ima_exp_sts rc=%d\n", rc); - return rc; - } + fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n", + err_sts, exp_sts, hw_sts); - rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1); - if (rc < 0) { - pr_err("failed to read ima_hw_sts rc=%d\n", rc); - return rc; + if (check_hw_sts) { + /* + * Lower nibble should be equal to upper nibble before SRAM + * transactions begins from SW side. If they are unequal, then + * the error clear sequence should be run irrespective of IMA + * exception errors. + */ + if ((hw_sts & 0x0F) != hw_sts >> 4) { + pr_err("IMA HW not in correct state, hw_sts=%x\n", + hw_sts); + run_err_clr_seq = true; } + } - pr_err("ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n", - err_sts, exp_sts, hw_sts); + if (exp_sts & (IACS_ERR_BIT | XCT_TYPE_ERR_BIT | DATA_RD_ERR_BIT | + DATA_WR_ERR_BIT | ADDR_BURST_WRAP_BIT | ADDR_STABLE_ERR_BIT)) { + pr_err("IMA exception bit set, exp_sts=%x\n", exp_sts); + run_err_clr_seq = true; + } + if (run_err_clr_seq) { /* clear the error */ rc = fg_run_iacs_clear_sequence(chip); if (rc < 0) { @@ -156,7 +261,7 @@ static int fg_check_for_ima_errors(struct fg_chip *chip) static int fg_check_iacs_ready(struct fg_chip *chip) { - int rc = 0, timeout = 250; + int rc = 0, tries = 250; u8 ima_opr_sts = 0; /* @@ -176,17 +281,17 @@ static int fg_check_iacs_ready(struct fg_chip *chip) if (ima_opr_sts & IACS_RDY_BIT) break; - if (!(--timeout)) + if (!(--tries)) break; /* delay for iacs_ready to be asserted */ usleep_range(5000, 7000); } - if (!timeout) { + if (!tries) { pr_err("IACS_RDY not set\n"); - - rc = fg_check_for_ima_errors(chip); + /* check for error condition */ + rc = fg_clear_ima_errors_if_any(chip, false); if (rc < 0) { pr_err("Failed to check for ima errors rc=%d\n", rc); return rc; @@ -250,7 +355,7 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u16 address, } /* check for error condition */ - rc = fg_check_for_ima_errors(chip); + rc = fg_clear_ima_errors_if_any(chip, false); if (rc < 0) { pr_err("Failed to check for ima errors rc=%d\n", rc); return rc; @@ -296,7 +401,7 @@ static int __fg_interleaved_mem_read(struct fg_chip *chip, u16 address, offset = 0; /* check for error condition */ - rc = fg_check_for_ima_errors(chip); + rc = fg_clear_ima_errors_if_any(chip, false); if (rc < 0) { pr_err("Failed to check for ima errors rc=%d\n", rc); return rc; @@ -581,5 +686,19 @@ int fg_ima_init(struct fg_chip *chip) return rc; } + /* Clear DMA errors if any before clearing IMA errors */ + rc = fg_clear_dma_errors_if_any(chip); + if (rc < 0) { + pr_err("Error in checking DMA errors rc:%d\n", rc); + return rc; + } + + /* Clear IMA errors if any before SRAM transactions can begin */ + rc = fg_clear_ima_errors_if_any(chip, true); + if (rc < 0 && rc != -EAGAIN) { + pr_err("Error in checking IMA errors rc:%d\n", rc); + return rc; + } + return 0; } diff --git a/drivers/power/qcom-charger/fg-reg.h b/drivers/power/qcom-charger/fg-reg.h index 431e28a7eb1f..ffc46f328f91 100644 --- a/drivers/power/qcom-charger/fg-reg.h +++ b/drivers/power/qcom-charger/fg-reg.h @@ -26,6 +26,9 @@ #define BATT_SOC_LOW_PWR_CFG(chip) (chip->batt_soc_base + 0x52) #define BATT_SOC_LOW_PWR_STS(chip) (chip->batt_soc_base + 0x56) +/* BATT_SOC_INT_RT_STS */ +#define MSOC_EMPTY_BIT BIT(5) + /* BATT_SOC_EN_CTL */ #define FG_ALGORITHM_EN_BIT BIT(7) @@ -258,6 +261,7 @@ #define ESR_REQ_CTL_EN_BIT BIT(0) /* FG_MEM_IF register and bit definitions */ +#define MEM_IF_INT_RT_STS(chip) ((chip->mem_if_base) + 0x10) #define MEM_IF_MEM_INTF_CFG(chip) ((chip->mem_if_base) + 0x50) #define MEM_IF_IMA_CTL(chip) ((chip->mem_if_base) + 0x51) #define MEM_IF_IMA_CFG(chip) ((chip->mem_if_base) + 0x52) @@ -273,6 +277,11 @@ #define MEM_IF_WR_DATA3(chip) ((chip->mem_if_base) + 0x66) #define MEM_IF_RD_DATA0(chip) ((chip->mem_if_base) + 0x67) #define MEM_IF_RD_DATA3(chip) ((chip->mem_if_base) + 0x6A) +#define MEM_IF_DMA_STS(chip) ((chip->mem_if_base) + 0x70) +#define MEM_IF_DMA_CTL(chip) ((chip->mem_if_base) + 0x71) + +/* MEM_IF_INT_RT_STS */ +#define MEM_XCP_BIT BIT(1) /* MEM_IF_MEM_INTF_CFG */ #define MEM_ACCESS_REQ_BIT BIT(7) @@ -286,10 +295,19 @@ /* MEM_IF_IMA_CFG */ #define IACS_CLR_BIT BIT(2) #define IACS_INTR_SRC_SLCT_BIT BIT(3) +#define STATIC_CLK_EN_BIT BIT(4) /* MEM_IF_IMA_OPR_STS */ #define IACS_RDY_BIT BIT(1) +/* MEM_IF_IMA_EXP_STS */ +#define IACS_ERR_BIT BIT(0) +#define XCT_TYPE_ERR_BIT BIT(1) +#define DATA_RD_ERR_BIT BIT(3) +#define DATA_WR_ERR_BIT BIT(4) +#define ADDR_BURST_WRAP_BIT BIT(5) +#define ADDR_STABLE_ERR_BIT BIT(7) + /* MEM_IF_IMA_ERR_STS */ #define ADDR_STBL_ERR_BIT BIT(7) #define WR_ACS_ERR_BIT BIT(6) @@ -297,4 +315,11 @@ /* MEM_IF_FG_BEAT_COUNT */ #define BEAT_COUNT_MASK GENMASK(3, 0) + +/* MEM_IF_DMA_STS */ +#define DMA_WRITE_ERROR_BIT BIT(1) +#define DMA_READ_ERROR_BIT BIT(2) + +/* MEM_IF_DMA_CTL */ +#define DMA_CLEAR_LOG_BIT BIT(0) #endif diff --git a/drivers/power/qcom-charger/fg-util.c b/drivers/power/qcom-charger/fg-util.c index 0e3c7dbb5731..405d875ea7df 100644 --- a/drivers/power/qcom-charger/fg-util.c +++ b/drivers/power/qcom-charger/fg-util.c @@ -14,6 +14,82 @@ #include "fg-core.h" +void fg_circ_buf_add(struct fg_circ_buf *buf, int val) +{ + buf->arr[buf->head] = val; + buf->head = (buf->head + 1) % ARRAY_SIZE(buf->arr); + buf->size = min(++buf->size, (int)ARRAY_SIZE(buf->arr)); +} + +void fg_circ_buf_clr(struct fg_circ_buf *buf) +{ + memset(buf, 0, sizeof(*buf)); +} + +int fg_circ_buf_avg(struct fg_circ_buf *buf, int *avg) +{ + s64 result = 0; + int i; + + if (buf->size == 0) + return -ENODATA; + + for (i = 0; i < buf->size; i++) + result += buf->arr[i]; + + *avg = div_s64(result, buf->size); + return 0; +} + +int fg_lerp(const struct fg_pt *pts, size_t tablesize, s32 input, s32 *output) +{ + int i; + s64 temp; + + if (pts == NULL) { + pr_err("Table is NULL\n"); + return -EINVAL; + } + + if (tablesize < 1) { + pr_err("Table has no entries\n"); + return -ENOENT; + } + + if (tablesize == 1) { + *output = pts[0].y; + return 0; + } + + if (pts[0].x > pts[1].x) { + pr_err("Table is not in acending order\n"); + return -EINVAL; + } + + if (input <= pts[0].x) { + *output = pts[0].y; + return 0; + } + + if (input >= pts[tablesize - 1].x) { + *output = pts[tablesize - 1].y; + return 0; + } + + for (i = 1; i < tablesize; i++) { + if (input >= pts[i].x) + continue; + + temp = (s64)(pts[i].y - pts[i - 1].y) * + (s64)(input - pts[i - 1].x); + temp = div_s64(temp, pts[i].x - pts[i - 1].x); + *output = temp + pts[i - 1].y; + return 0; + } + + return -EINVAL; +} + static struct fg_dbgfs dbgfs_data = { .help_msg = { .data = diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index c9edc667f35d..100153280d9e 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -146,6 +146,8 @@ static void fg_encode_default(struct fg_sram_param *sp, static struct fg_sram_param pmicobalt_v1_sram_params[] = { PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL, fg_decode_default), + PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL, + fg_decode_default), PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141, 1000, 0, NULL, fg_decode_voltage_15b), PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL, @@ -198,6 +200,8 @@ static struct fg_sram_param pmicobalt_v1_sram_params[] = { static struct fg_sram_param pmicobalt_v2_sram_params[] = { PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL, fg_decode_default), + PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL, + fg_decode_default), PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141, 1000, 0, NULL, fg_decode_voltage_15b), PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL, @@ -655,6 +659,35 @@ static int fg_get_msoc_raw(struct fg_chip *chip, int *val) return 0; } +static bool is_batt_empty(struct fg_chip *chip) +{ + u8 status; + int rc, vbatt_uv, msoc; + + rc = fg_read(chip, BATT_SOC_INT_RT_STS(chip), &status, 1); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + BATT_SOC_INT_RT_STS(chip), rc); + return false; + } + + if (!(status & MSOC_EMPTY_BIT)) + return false; + + rc = fg_get_battery_voltage(chip, &vbatt_uv); + if (rc < 0) { + pr_err("failed to get battery voltage, rc=%d\n", rc); + return false; + } + + rc = fg_get_msoc_raw(chip, &msoc); + if (!rc) + pr_warn("batt_soc_rt_sts: %x vbatt: %d uV msoc:%d\n", status, + vbatt_uv, msoc); + + return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false); +} + #define DEBUG_BATT_ID_KOHMS 7 static bool is_debug_batt_id(struct fg_chip *chip) { @@ -676,6 +709,7 @@ static bool is_debug_batt_id(struct fg_chip *chip) #define FULL_CAPACITY 100 #define FULL_SOC_RAW 255 #define DEBUG_BATT_SOC 67 +#define EMPTY_SOC 0 static int fg_get_prop_capacity(struct fg_chip *chip, int *val) { int rc, msoc; @@ -685,6 +719,11 @@ static int fg_get_prop_capacity(struct fg_chip *chip, int *val) return 0; } + if (is_batt_empty(chip)) { + *val = EMPTY_SOC; + return 0; + } + if (chip->charge_full) { *val = FULL_CAPACITY; return 0; @@ -903,6 +942,17 @@ static bool is_charger_available(struct fg_chip *chip) return true; } +static bool is_parallel_charger_available(struct fg_chip *chip) +{ + if (!chip->parallel_psy) + chip->parallel_psy = power_supply_get_by_name("parallel"); + + if (!chip->parallel_psy) + return false; + + return true; +} + static int fg_save_learned_cap_to_sram(struct fg_chip *chip) { int16_t cc_mah; @@ -1150,11 +1200,11 @@ static void fg_cap_learning_update(struct fg_chip *chip) batt_soc = (u32)batt_soc >> 24; fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n", - chip->status, chip->cl.active, batt_soc); + chip->charge_status, chip->cl.active, batt_soc); /* Initialize the starting point of learning capacity */ if (!chip->cl.active) { - if (chip->status == POWER_SUPPLY_STATUS_CHARGING) { + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) { rc = fg_cap_learning_begin(chip, batt_soc); chip->cl.active = (rc == 0); } @@ -1170,7 +1220,7 @@ static void fg_cap_learning_update(struct fg_chip *chip) chip->cl.init_cc_uah = 0; } - if (chip->status == POWER_SUPPLY_STATUS_NOT_CHARGING) { + if (chip->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) { fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n", batt_soc); chip->cl.active = false; @@ -1200,7 +1250,7 @@ static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip) return rc; } - if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) { + if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) { for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) { if (msoc < chip->dt.ki_coeff_soc[i]) { ki_coeff_med = chip->dt.ki_coeff_med_dischg[i]; @@ -1274,7 +1324,7 @@ static int fg_charge_full_update(struct fg_chip *chip) } fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc, - chip->health, chip->status); + chip->health, chip->charge_status); if (chip->charge_done) { if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD) chip->charge_full = true; @@ -1375,6 +1425,88 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip) return 0; } +static int fg_esr_fcc_config(struct fg_chip *chip) +{ + union power_supply_propval prop = {0, }; + int rc; + bool parallel_en = false; + + if (is_parallel_charger_available(chip)) { + rc = power_supply_get_property(chip->parallel_psy, + POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop); + if (rc < 0) { + pr_err("Error in reading charging_enabled from parallel_psy, rc=%d\n", + rc); + return rc; + } + parallel_en = prop.intval; + } + + fg_dbg(chip, FG_POWER_SUPPLY, "charge_status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n", + chip->charge_status, parallel_en, chip->esr_fcc_ctrl_en); + + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING && + parallel_en) { + if (chip->esr_fcc_ctrl_en) + return 0; + + /* + * When parallel charging is enabled, configure ESR FCC to + * 300mA to trigger an ESR pulse. Without this, FG can ask + * the main charger to increase FCC when it is supposed to + * decrease it. + */ + rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip), + ESR_FAST_CRG_IVAL_MASK | + ESR_FAST_CRG_CTL_EN_BIT, + ESR_FCC_300MA | ESR_FAST_CRG_CTL_EN_BIT); + if (rc < 0) { + pr_err("Error in writing to %04x, rc=%d\n", + BATT_INFO_ESR_FAST_CRG_CFG(chip), rc); + return rc; + } + + chip->esr_fcc_ctrl_en = true; + } else { + if (!chip->esr_fcc_ctrl_en) + return 0; + + /* + * If we're here, then it means either the device is not in + * charging state or parallel charging is disabled. Disable + * ESR fast charge current control in SW. + */ + rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip), + ESR_FAST_CRG_CTL_EN_BIT, 0); + if (rc < 0) { + pr_err("Error in writing to %04x, rc=%d\n", + BATT_INFO_ESR_FAST_CRG_CFG(chip), rc); + return rc; + } + + chip->esr_fcc_ctrl_en = false; + } + + fg_dbg(chip, FG_STATUS, "esr_fcc_ctrl_en set to %d\n", + chip->esr_fcc_ctrl_en); + return 0; +} + +static void fg_batt_avg_update(struct fg_chip *chip) +{ + if (chip->charge_status == chip->prev_charge_status) + return; + + cancel_delayed_work_sync(&chip->batt_avg_work); + fg_circ_buf_clr(&chip->ibatt_circ_buf); + fg_circ_buf_clr(&chip->vbatt_circ_buf); + + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING || + chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) + schedule_delayed_work(&chip->batt_avg_work, + msecs_to_jiffies(2000)); +} + static void status_change_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, @@ -1394,7 +1526,16 @@ static void status_change_work(struct work_struct *work) goto out; } - chip->status = prop.intval; + chip->prev_charge_status = chip->charge_status; + chip->charge_status = prop.intval; + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_CHARGE_TYPE, &prop); + if (rc < 0) { + pr_err("Error in getting charge type, rc=%d\n", rc); + goto out; + } + + chip->charge_type = prop.intval; rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CHARGE_DONE, &prop); if (rc < 0) { @@ -1403,9 +1544,6 @@ static void status_change_work(struct work_struct *work) } chip->charge_done = prop.intval; - fg_dbg(chip, FG_POWER_SUPPLY, "curr_status:%d charge_done: %d\n", - chip->status, chip->charge_done); - if (chip->cyc_ctr.en) schedule_work(&chip->cycle_count_work); @@ -1422,7 +1560,16 @@ static void status_change_work(struct work_struct *work) rc = fg_adjust_ki_coeff_dischg(chip); if (rc < 0) pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc); + + rc = fg_esr_fcc_config(chip); + if (rc < 0) + pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc); + + fg_batt_avg_update(chip); + out: + fg_dbg(chip, FG_POWER_SUPPLY, "charge_status:%d charge_type:%d charge_done:%d\n", + chip->charge_status, chip->charge_type, chip->charge_done); pm_relax(chip->dev); } @@ -1509,7 +1656,7 @@ static void cycle_count_work(struct work_struct *work) /* We need only the most significant byte here */ batt_soc = (u32)batt_soc >> 24; - if (chip->status == POWER_SUPPLY_STATUS_CHARGING) { + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) { /* Find out which bucket the SOC falls in */ bucket = batt_soc / BUCKET_SOC_PCT; pr_debug("batt_soc: %d bucket: %d\n", batt_soc, bucket); @@ -1826,6 +1973,229 @@ static struct kernel_param_ops fg_restart_ops = { module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644); +#define BATT_AVG_POLL_PERIOD_MS 10000 +static void batt_avg_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, struct fg_chip, + batt_avg_work.work); + int rc, ibatt_now, vbatt_now; + + mutex_lock(&chip->batt_avg_lock); + rc = fg_get_battery_current(chip, &ibatt_now); + if (rc < 0) { + pr_err("failed to get battery current, rc=%d\n", rc); + goto reschedule; + } + + rc = fg_get_battery_voltage(chip, &vbatt_now); + if (rc < 0) { + pr_err("failed to get battery voltage, rc=%d\n", rc); + goto reschedule; + } + + fg_circ_buf_add(&chip->ibatt_circ_buf, ibatt_now); + fg_circ_buf_add(&chip->vbatt_circ_buf, vbatt_now); + +reschedule: + mutex_unlock(&chip->batt_avg_lock); + schedule_delayed_work(&chip->batt_avg_work, + msecs_to_jiffies(BATT_AVG_POLL_PERIOD_MS)); +} + +#define DECI_TAU_SCALE 13 +#define HOURS_TO_SECONDS 3600 +#define OCV_SLOPE_UV 10869 +#define MILLI_UNIT 1000 +#define MICRO_UNIT 1000000 +static int fg_get_time_to_full(struct fg_chip *chip, int *val) +{ + int rc, ibatt_avg, vbatt_avg, rbatt, msoc, ocv_cc2cv, full_soc, + act_cap_uah; + s32 i_cc2cv, soc_cc2cv, ln_val; + s64 t_predicted_cc = 0, t_predicted_cv = 0; + + if (chip->bp.float_volt_uv <= 0) { + pr_err("battery profile is not loaded\n"); + return -ENODATA; + } + + if (!is_charger_available(chip)) { + fg_dbg(chip, FG_TTF, "charger is not available\n"); + return -ENODATA; + } + + if (chip->charge_status == POWER_SUPPLY_STATUS_FULL) { + *val = 0; + return 0; + } + + mutex_lock(&chip->batt_avg_lock); + rc = fg_circ_buf_avg(&chip->ibatt_circ_buf, &ibatt_avg); + if (rc < 0) { + /* try to get instantaneous current */ + rc = fg_get_battery_current(chip, &ibatt_avg); + if (rc < 0) { + mutex_unlock(&chip->batt_avg_lock); + pr_err("failed to get battery current, rc=%d\n", rc); + return rc; + } + } + + rc = fg_circ_buf_avg(&chip->vbatt_circ_buf, &vbatt_avg); + if (rc < 0) { + /* try to get instantaneous voltage */ + rc = fg_get_battery_voltage(chip, &vbatt_avg); + if (rc < 0) { + mutex_unlock(&chip->batt_avg_lock); + pr_err("failed to get battery voltage, rc=%d\n", rc); + return rc; + } + } + + mutex_unlock(&chip->batt_avg_lock); + fg_dbg(chip, FG_TTF, "vbatt_avg=%d\n", vbatt_avg); + + /* clamp ibatt_avg to -150mA */ + if (ibatt_avg > -150000) + ibatt_avg = -150000; + fg_dbg(chip, FG_TTF, "ibatt_avg=%d\n", ibatt_avg); + + /* reverse polarity to be consistent with unsigned current settings */ + ibatt_avg = abs(ibatt_avg); + + /* estimated battery current at the CC to CV transition */ + i_cc2cv = div_s64((s64)ibatt_avg * vbatt_avg, chip->bp.float_volt_uv); + fg_dbg(chip, FG_TTF, "i_cc2cv=%d\n", i_cc2cv); + + rc = fg_get_battery_resistance(chip, &rbatt); + if (rc < 0) { + pr_err("failed to get battery resistance rc=%d\n", rc); + return rc; + } + + /* clamp rbatt to 50mOhms */ + if (rbatt < 50000) + rbatt = 50000; + + fg_dbg(chip, FG_TTF, "rbatt=%d\n", rbatt); + + rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_uah); + if (rc < 0) { + pr_err("failed to get ACT_BATT_CAP rc=%d\n", rc); + return rc; + } + act_cap_uah *= MILLI_UNIT; + fg_dbg(chip, FG_TTF, "actual_capacity_uah=%d\n", act_cap_uah); + + rc = fg_get_prop_capacity(chip, &msoc); + if (rc < 0) { + pr_err("failed to get msoc rc=%d\n", rc); + return rc; + } + fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc); + + rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc); + if (rc < 0) { + pr_err("failed to get full soc rc=%d\n", rc); + return rc; + } + full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY, + FULL_SOC_RAW); + fg_dbg(chip, FG_TTF, "full_soc=%d\n", full_soc); + + /* if we are already in CV state then we can skip estimating CC */ + if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) + goto skip_cc_estimate; + + /* if the charger is current limited then use power approximation */ + if (ibatt_avg > chip->bp.fastchg_curr_ma * MILLI_UNIT - 50000) + ocv_cc2cv = div_s64((s64)rbatt * ibatt_avg, MICRO_UNIT); + else + ocv_cc2cv = div_s64((s64)rbatt * i_cc2cv, MICRO_UNIT); + ocv_cc2cv = chip->bp.float_volt_uv - ocv_cc2cv; + fg_dbg(chip, FG_TTF, "ocv_cc2cv=%d\n", ocv_cc2cv); + + soc_cc2cv = div_s64(chip->bp.float_volt_uv - ocv_cc2cv, OCV_SLOPE_UV); + /* estimated SOC at the CC to CV transition */ + soc_cc2cv = 100 - soc_cc2cv; + fg_dbg(chip, FG_TTF, "soc_cc2cv=%d\n", soc_cc2cv); + + /* the esimated SOC may be lower than the current SOC */ + if (soc_cc2cv - msoc <= 0) + goto skip_cc_estimate; + + t_predicted_cc = div_s64((s64)full_soc * act_cap_uah, 100); + t_predicted_cc = div_s64(t_predicted_cc * (soc_cc2cv - msoc), 100); + t_predicted_cc *= HOURS_TO_SECONDS; + t_predicted_cc = div_s64(t_predicted_cc, (ibatt_avg + i_cc2cv) / 2); + +skip_cc_estimate: + fg_dbg(chip, FG_TTF, "t_predicted_cc=%lld\n", t_predicted_cc); + + /* CV estimate starts here */ + if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) + ln_val = ibatt_avg / abs(chip->dt.sys_term_curr_ma); + else + ln_val = i_cc2cv / abs(chip->dt.sys_term_curr_ma); + + fg_dbg(chip, FG_TTF, "ln_in=%d\n", ln_val); + rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), ln_val, &ln_val); + fg_dbg(chip, FG_TTF, "ln_out=%d\n", ln_val); + t_predicted_cv = div_s64((s64)act_cap_uah * rbatt, MICRO_UNIT); + t_predicted_cv = div_s64(t_predicted_cv * DECI_TAU_SCALE, 10); + t_predicted_cv = div_s64(t_predicted_cv * ln_val, MILLI_UNIT); + t_predicted_cv = div_s64(t_predicted_cv * HOURS_TO_SECONDS, MICRO_UNIT); + fg_dbg(chip, FG_TTF, "t_predicted_cv=%lld\n", t_predicted_cv); + *val = t_predicted_cc + t_predicted_cv; + return 0; +} + +#define CENTI_ICORRECT_C0 105 +#define CENTI_ICORRECT_C1 20 +static int fg_get_time_to_empty(struct fg_chip *chip, int *val) +{ + int rc, ibatt_avg, msoc, act_cap_uah; + s32 divisor; + s64 t_predicted; + + rc = fg_circ_buf_avg(&chip->ibatt_circ_buf, &ibatt_avg); + if (rc < 0) { + /* try to get instantaneous current */ + rc = fg_get_battery_current(chip, &ibatt_avg); + if (rc < 0) { + pr_err("failed to get battery current, rc=%d\n", rc); + return rc; + } + } + + /* clamp ibatt_avg to 150mA */ + if (ibatt_avg < 150000) + ibatt_avg = 150000; + + rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_uah); + if (rc < 0) { + pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc); + return rc; + } + act_cap_uah *= MILLI_UNIT; + + rc = fg_get_prop_capacity(chip, &msoc); + if (rc < 0) { + pr_err("Error in getting capacity, rc=%d\n", rc); + return rc; + } + + t_predicted = div_s64((s64)msoc * act_cap_uah, 100); + t_predicted *= HOURS_TO_SECONDS; + divisor = CENTI_ICORRECT_C0 * 100 + CENTI_ICORRECT_C1 * msoc; + divisor = div_s64((s64)divisor * ibatt_avg, 10000); + if (divisor > 0) + t_predicted = div_s64(t_predicted, divisor); + + *val = t_predicted; + return 0; +} + /* PSY CALLBACKS STAY HERE */ static int fg_psy_get_property(struct power_supply *psy, @@ -1887,11 +2257,22 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGE_COUNTER: rc = fg_get_cc_soc_sw(chip, &pval->intval); break; + case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: + rc = fg_get_time_to_full(chip, &pval->intval); + break; + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: + rc = fg_get_time_to_empty(chip, &pval->intval); + break; default: + pr_err("unsupported property %d\n", psp); + rc = -EINVAL; break; } - return rc; + if (rc < 0) + return -ENODATA; + + return 0; } static int fg_psy_set_property(struct power_supply *psy, @@ -1974,6 +2355,8 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, + POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, }; static const struct power_supply_desc fg_psy_desc = { @@ -2180,6 +2563,37 @@ static int fg_memif_init(struct fg_chip *chip) /* INTERRUPT HANDLERS STAY HERE */ +static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data) +{ + struct fg_chip *chip = data; + u8 status; + int rc; + + rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &status, 1); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + MEM_IF_INT_RT_STS(chip), rc); + return IRQ_HANDLED; + } + + fg_dbg(chip, FG_IRQ, "irq %d triggered, status:%d\n", irq, status); + if (status & MEM_XCP_BIT) { + rc = fg_clear_dma_errors_if_any(chip); + if (rc < 0) { + pr_err("Error in clearing DMA error, rc=%d\n", rc); + return IRQ_HANDLED; + } + + mutex_lock(&chip->sram_rw_lock); + rc = fg_clear_ima_errors_if_any(chip, true); + if (rc < 0 && rc != -EAGAIN) + pr_err("Error in checking IMA errors rc:%d\n", rc); + mutex_unlock(&chip->sram_rw_lock); + } + + return IRQ_HANDLED; +} + static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data) { struct fg_chip *chip = data; @@ -2276,14 +2690,10 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data) struct fg_chip *chip = data; int rc; + fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); if (chip->cyc_ctr.en) schedule_work(&chip->cycle_count_work); - if (is_charger_available(chip)) - power_supply_changed(chip->batt_psy); - - fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); - if (chip->cl.active) fg_cap_learning_update(chip); @@ -2295,6 +2705,9 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data) if (rc < 0) pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc); + if (is_charger_available(chip)) + power_supply_changed(chip->batt_psy); + return IRQ_HANDLED; } @@ -2302,10 +2715,10 @@ static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data) { struct fg_chip *chip = data; + fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); if (is_charger_available(chip)) power_supply_changed(chip->batt_psy); - fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); return IRQ_HANDLED; } @@ -2319,9 +2732,7 @@ static irqreturn_t fg_soc_irq_handler(int irq, void *data) static irqreturn_t fg_dummy_irq_handler(int irq, void *data) { - struct fg_chip *chip = data; - - fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); + pr_debug("irq %d triggered\n", irq); return IRQ_HANDLED; } @@ -2395,7 +2806,7 @@ static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = { }, [MEM_XCP_IRQ] = { .name = "mem-xcp", - .handler = fg_dummy_irq_handler, + .handler = fg_mem_xcp_irq_handler, }, [IMA_RDY_IRQ] = { .name = "ima-rdy", @@ -2523,7 +2934,7 @@ static int fg_parse_ki_coefficients(struct fg_chip *chip) } #define DEFAULT_CUTOFF_VOLT_MV 3200 -#define DEFAULT_EMPTY_VOLT_MV 3100 +#define DEFAULT_EMPTY_VOLT_MV 2800 #define DEFAULT_CHG_TERM_CURR_MA 100 #define DEFAULT_SYS_TERM_CURR_MA -125 #define DEFAULT_DELTA_SOC_THR 1 @@ -2811,7 +3222,7 @@ static int fg_gen3_probe(struct platform_device *pdev) { struct fg_chip *chip; struct power_supply_config fg_psy_cfg; - int rc; + int rc, msoc, volt_uv, batt_temp; chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); if (!chip) @@ -2820,6 +3231,8 @@ static int fg_gen3_probe(struct platform_device *pdev) chip->dev = &pdev->dev; chip->debug_mask = &fg_gen3_debug_mask; chip->irqs = fg_irqs; + chip->charge_status = -EINVAL; + chip->prev_charge_status = -EINVAL; chip->regmap = dev_get_regmap(chip->dev->parent, NULL); if (!chip->regmap) { dev_err(chip->dev, "Parent regmap is unavailable\n"); @@ -2844,11 +3257,13 @@ static int fg_gen3_probe(struct platform_device *pdev) mutex_init(&chip->sram_rw_lock); mutex_init(&chip->cyc_ctr.lock); mutex_init(&chip->cl.lock); + mutex_init(&chip->batt_avg_lock); init_completion(&chip->soc_update); init_completion(&chip->soc_ready); INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work); INIT_WORK(&chip->status_change_work, status_change_work); INIT_WORK(&chip->cycle_count_work, cycle_count_work); + INIT_DELAYED_WORK(&chip->batt_avg_work, batt_avg_work); rc = fg_memif_init(chip); if (rc < 0) { @@ -2904,11 +3319,22 @@ static int fg_gen3_probe(struct platform_device *pdev) goto exit; } + rc = fg_get_battery_voltage(chip, &volt_uv); + if (!rc) + rc = fg_get_prop_capacity(chip, &msoc); + + if (!rc) + rc = fg_get_battery_temp(chip, &batt_temp); + + if (!rc) + pr_info("battery SOC:%d voltage: %duV temp: %d id: %dKOhms\n", + msoc, volt_uv, batt_temp, chip->batt_id_kohms); + + device_init_wakeup(chip->dev, true); if (chip->profile_available) schedule_delayed_work(&chip->profile_load_work, 0); - device_init_wakeup(chip->dev, true); - pr_debug("FG GEN3 driver successfully probed\n"); + pr_debug("FG GEN3 driver probed successfully\n"); return 0; exit: fg_cleanup(chip); @@ -2930,6 +3356,7 @@ static int fg_gen3_suspend(struct device *dev) } } + cancel_delayed_work_sync(&chip->batt_avg_work); return 0; } @@ -2948,6 +3375,9 @@ static int fg_gen3_resume(struct device *dev) } } + fg_circ_buf_clr(&chip->ibatt_circ_buf); + fg_circ_buf_clr(&chip->vbatt_circ_buf); + schedule_delayed_work(&chip->batt_avg_work, 0); return 0; } diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index f9d76c56aa2e..6968ab2ab11c 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -225,6 +225,7 @@ struct smb_dt_props { s32 step_cc_delta[STEP_CHARGING_MAX_STEPS]; struct device_node *revid_dev_node; int float_option; + int chg_inhibit_thr_mv; bool hvdcp_disable; }; @@ -335,6 +336,14 @@ static int smb2_parse_dt(struct smb2 *chip) chip->dt.hvdcp_disable = of_property_read_bool(node, "qcom,hvdcp-disable"); + of_property_read_u32(node, "qcom,chg-inhibit-threshold-mv", + &chip->dt.chg_inhibit_thr_mv); + if ((chip->dt.chg_inhibit_thr_mv < 0 || + chip->dt.chg_inhibit_thr_mv > 300)) { + pr_err("qcom,chg-inhibit-threshold-mv is incorrect\n"); + return -EINVAL; + } + return 0; } @@ -1040,6 +1049,7 @@ static int smb2_init_hw(struct smb2 *chip) { struct smb_charger *chg = &chip->chg; int rc; + u8 stat; if (chip->dt.no_battery) chg->fake_capacity = 50; @@ -1060,6 +1070,21 @@ static int smb2_init_hw(struct smb2 *chip) chg->otg_cl_ua = chip->dt.otg_cl_ua; + rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); + if (rc < 0) { + pr_err("Couldn't read APSD_RESULT_STATUS rc=%d\n", rc); + return rc; + } + + /* clear the ICL override if it is set */ + if (stat & ICL_OVERRIDE_LATCH_BIT) { + rc = smblib_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT); + if (rc < 0) { + pr_err("Couldn't disable ICL override rc=%d\n", rc); + return rc; + } + } + /* votes must be cast before configuring software control */ vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); @@ -1152,6 +1177,15 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } + /* increase VCONN softstart */ + rc = smblib_masked_write(chg, TYPE_C_CFG_2_REG, + VCONN_SOFTSTART_CFG_MASK, VCONN_SOFTSTART_CFG_MASK); + if (rc < 0) { + dev_err(chg->dev, "Couldn't increase VCONN softstart rc=%d\n", + rc); + return rc; + } + rc = smblib_masked_write(chg, QNOVO_PT_ENABLE_CMD_REG, QNOVO_PT_ENABLE_CMD_BIT, QNOVO_PT_ENABLE_CMD_BIT); if (rc < 0) { @@ -1174,13 +1208,12 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } - /* configure PMI stat output to enable and disable parallel charging */ + /* disable SW STAT override */ rc = smblib_masked_write(chg, STAT_CFG_REG, - STAT_PARALLEL_CFG_BIT | STAT_SW_OVERRIDE_CFG_BIT, - STAT_PARALLEL_CFG_BIT); + STAT_SW_OVERRIDE_CFG_BIT, 0); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure signal for parallel rc=%d\n", rc); + dev_err(chg->dev, "Couldn't disable SW STAT override rc=%d\n", + rc); return rc; } @@ -1213,6 +1246,40 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } + switch (chip->dt.chg_inhibit_thr_mv) { + case 50: + rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, + CHARGE_INHIBIT_THRESHOLD_MASK, + CHARGE_INHIBIT_THRESHOLD_50MV); + break; + case 100: + rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, + CHARGE_INHIBIT_THRESHOLD_MASK, + CHARGE_INHIBIT_THRESHOLD_100MV); + break; + case 200: + rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, + CHARGE_INHIBIT_THRESHOLD_MASK, + CHARGE_INHIBIT_THRESHOLD_200MV); + break; + case 300: + rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG, + CHARGE_INHIBIT_THRESHOLD_MASK, + CHARGE_INHIBIT_THRESHOLD_300MV); + break; + case 0: + rc = smblib_masked_write(chg, CHGR_CFG2_REG, + CHARGER_INHIBIT_BIT, 0); + default: + break; + } + + if (rc < 0) { + dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n", + rc); + return rc; + } + return rc; } @@ -1241,8 +1308,11 @@ static int smb2_setup_wa_flags(struct smb2 *chip) switch (pmic_rev_id->pmic_subtype) { case PMICOBALT_SUBTYPE: + chip->chg.wa_flags |= BOOST_BACK_WA; if (pmic_rev_id->rev4 == PMICOBALT_V1P1_REV4) /* PMI rev 1.1 */ chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT; + if (pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4) /* PMI rev 2.0 */ + chg->wa_flags |= TYPEC_CC2_REMOVAL_WA_BIT; break; default: pr_err("PMIC subtype %d not supported\n", @@ -1451,7 +1521,8 @@ static struct smb2_irq_info smb2_irqs[] = { }, { .name = "switcher-power-ok", - .handler = smblib_handle_debug, + .handler = smblib_handle_switcher_power_ok, + .storm_data = {true, 1000, 3}, }, }; @@ -1746,6 +1817,16 @@ static int smb2_remove(struct platform_device *pdev) return 0; } +static void smb2_shutdown(struct platform_device *pdev) +{ + struct smb2 *chip = platform_get_drvdata(pdev); + struct smb_charger *chg = &chip->chg; + + smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG, + HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0); + smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT); +} + static const struct of_device_id match_table[] = { { .compatible = "qcom,qpnp-smb2", }, { }, @@ -1759,6 +1840,7 @@ static struct platform_driver smb2_driver = { }, .probe = smb2_probe, .remove = smb2_remove, + .shutdown = smb2_shutdown, }; module_platform_driver(smb2_driver); diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 198e77469bbe..6aae7d49271f 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -490,7 +490,7 @@ static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg) /* ensure hvdcp is enabled */ if (!get_effective_result(chg->hvdcp_disable_votable)) { apsd_result = smblib_get_apsd_result(chg); - if (apsd_result->pst == POWER_SUPPLY_TYPE_USB_HVDCP) { + if (apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT)) { /* rerun APSD */ smblib_dbg(chg, PR_MISC, "rerun APSD\n"); smblib_masked_write(chg, CMD_APSD_REG, @@ -596,7 +596,11 @@ static int smblib_usb_suspend_vote_callback(struct votable *votable, void *data, { struct smb_charger *chg = data; - return smblib_set_usb_suspend(chg, suspend); + /* resume input if suspend is invalid */ + if (suspend < 0) + suspend = 0; + + return smblib_set_usb_suspend(chg, (bool)suspend); } static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data, @@ -604,10 +608,11 @@ static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data, { struct smb_charger *chg = data; + /* resume input if suspend is invalid */ if (suspend < 0) - suspend = false; + suspend = 0; - return smblib_set_dc_suspend(chg, suspend); + return smblib_set_dc_suspend(chg, (bool)suspend); } static int smblib_fcc_max_vote_callback(struct votable *votable, void *data, @@ -956,12 +961,13 @@ static int smblib_apsd_disable_vote_callback(struct votable *votable, * OTG REGULATOR * *****************/ -#define OTG_SOFT_START_DELAY_MS 20 +#define MAX_SOFTSTART_TRIES 2 int smblib_vbus_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); u8 stat; int rc = 0; + int tries = MAX_SOFTSTART_TRIES; rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, @@ -978,14 +984,25 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev) return rc; } - msleep(OTG_SOFT_START_DELAY_MS); - rc = smblib_read(chg, OTG_STATUS_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read OTG_STATUS_REG rc=%d\n", rc); - return rc; - } - if (stat & BOOST_SOFTSTART_DONE_BIT) - smblib_otg_cl_config(chg, chg->otg_cl_ua); + /* waiting for boost readiness, usually ~1ms, 2ms in worst case */ + do { + usleep_range(1000, 1100); + + rc = smblib_read(chg, OTG_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read OTG_STATUS_REG rc=%d\n", + rc); + return rc; + } + if (stat & BOOST_SOFTSTART_DONE_BIT) { + smblib_otg_cl_config(chg, chg->otg_cl_ua); + break; + } + } while (--tries); + + if (tries == 0) + smblib_err(chg, "Timeout waiting for boost softstart rc=%d\n", + rc); return rc; } @@ -1447,21 +1464,17 @@ int smblib_set_prop_system_temp_level(struct smb_charger *chg, int smblib_get_prop_dc_present(struct smb_charger *chg, union power_supply_propval *val) { - int rc = 0; + int rc; u8 stat; - rc = smblib_read(chg, DC_INT_RT_STS_REG, &stat); + rc = smblib_read(chg, DCIN_BASE + INT_RT_STS_OFFSET, &stat); if (rc < 0) { - smblib_err(chg, "Couldn't read DC_INT_RT_STS_REG rc=%d\n", - rc); + smblib_err(chg, "Couldn't read DCIN_RT_STS rc=%d\n", rc); return rc; } - smblib_dbg(chg, PR_REGISTER, "DC_INT_RT_STS_REG = 0x%02x\n", - stat); val->intval = (bool)(stat & DCIN_PLUGIN_RT_STS_BIT); - - return rc; + return 0; } int smblib_get_prop_dc_online(struct smb_charger *chg, @@ -1517,20 +1530,17 @@ int smblib_set_prop_dc_current_max(struct smb_charger *chg, int smblib_get_prop_usb_present(struct smb_charger *chg, union power_supply_propval *val) { - int rc = 0; + int rc; u8 stat; - rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); + rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat); if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); + smblib_err(chg, "Couldn't read USBIN_RT_STS rc=%d\n", rc); return rc; } - smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", - stat); - - val->intval = (bool)(stat & CC_ATTACHED_BIT); - return rc; + val->intval = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT); + return 0; } int smblib_get_prop_usb_online(struct smb_charger *chg, @@ -1997,6 +2007,45 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, "Couldn't enable vconn on CC line rc=%d\n", rc); return rc; } + + rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA); + if (rc < 0) { + smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n", + rc); + return rc; + } + + rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, + USBIN_MODE_CHG_BIT, USBIN_MODE_CHG_BIT); + if (rc < 0) { + smblib_err(chg, + "Couldn't change USB mode rc=%d\n", rc); + return rc; + } + + rc = smblib_masked_write(chg, CMD_APSD_REG, + ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT); + if (rc < 0) { + smblib_err(chg, + "Couldn't override APSD rc=%d\n", rc); + return rc; + } + } else { + rc = smblib_masked_write(chg, CMD_APSD_REG, + ICL_OVERRIDE_BIT, 0); + if (rc < 0) { + smblib_err(chg, + "Couldn't override APSD rc=%d\n", rc); + return rc; + } + + rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG, + USBIN_MODE_CHG_BIT, 0); + if (rc < 0) { + smblib_err(chg, + "Couldn't change USB mode rc=%d\n", rc); + return rc; + } } /* CC pin selection s/w override in PD session; h/w otherwise. */ @@ -2027,6 +2076,146 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, return rc; } +int smblib_reg_block_update(struct smb_charger *chg, + struct reg_info *entry) +{ + int rc = 0; + + while (entry && entry->reg) { + rc = smblib_read(chg, entry->reg, &entry->bak); + if (rc < 0) { + dev_err(chg->dev, "Error in reading %s rc=%d\n", + entry->desc, rc); + break; + } + entry->bak &= entry->mask; + + rc = smblib_masked_write(chg, entry->reg, + entry->mask, entry->val); + if (rc < 0) { + dev_err(chg->dev, "Error in writing %s rc=%d\n", + entry->desc, rc); + break; + } + entry++; + } + + return rc; +} + +int smblib_reg_block_restore(struct smb_charger *chg, + struct reg_info *entry) +{ + int rc = 0; + + while (entry && entry->reg) { + rc = smblib_masked_write(chg, entry->reg, + entry->mask, entry->bak); + if (rc < 0) { + dev_err(chg->dev, "Error in writing %s rc=%d\n", + entry->desc, rc); + break; + } + entry++; + } + + return rc; +} + +static struct reg_info cc2_detach_settings[] = { + { + .reg = TYPE_C_CFG_2_REG, + .mask = TYPE_C_UFP_MODE_BIT | EN_TRY_SOURCE_MODE_BIT, + .val = TYPE_C_UFP_MODE_BIT, + .desc = "TYPE_C_CFG_2_REG", + }, + { + .reg = TYPE_C_CFG_3_REG, + .mask = EN_TRYSINK_MODE_BIT, + .val = 0, + .desc = "TYPE_C_CFG_3_REG", + }, + { + .reg = TAPER_TIMER_SEL_CFG_REG, + .mask = TYPEC_SPARE_CFG_BIT, + .val = TYPEC_SPARE_CFG_BIT, + .desc = "TAPER_TIMER_SEL_CFG_REG", + }, + { + .reg = TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + .mask = VCONN_EN_ORIENTATION_BIT, + .val = 0, + .desc = "TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG", + }, + { + .reg = MISC_CFG_REG, + .mask = TCC_DEBOUNCE_20MS_BIT, + .val = TCC_DEBOUNCE_20MS_BIT, + .desc = "Tccdebounce time" + }, + { + }, +}; + +static int smblib_cc2_sink_removal_enter(struct smb_charger *chg) +{ + int rc = 0; + union power_supply_propval cc2_val = {0, }; + + if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0) + return rc; + + if (chg->cc2_sink_detach_flag != CC2_SINK_NONE) + return rc; + + rc = smblib_get_prop_typec_cc_orientation(chg, &cc2_val); + if (rc < 0) { + smblib_err(chg, "Couldn't get cc orientation rc=%d\n", rc); + return rc; + } + if (cc2_val.intval == 1) + return rc; + + rc = smblib_get_prop_typec_mode(chg, &cc2_val); + if (rc < 0) { + smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc); + return rc; + } + + switch (cc2_val.intval) { + case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT: + smblib_reg_block_update(chg, cc2_detach_settings); + chg->cc2_sink_detach_flag = CC2_SINK_STD; + schedule_work(&chg->rdstd_cc2_detach_work); + break; + case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM: + case POWER_SUPPLY_TYPEC_SOURCE_HIGH: + chg->cc2_sink_detach_flag = CC2_SINK_MEDIUM_HIGH; + break; + default: + break; + } + + return rc; +} + +static int smblib_cc2_sink_removal_exit(struct smb_charger *chg) +{ + int rc = 0; + + if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0) + return rc; + + if (chg->cc2_sink_detach_flag == CC2_SINK_STD) { + cancel_work_sync(&chg->rdstd_cc2_detach_work); + smblib_reg_block_restore(chg, cc2_detach_settings); + } + + chg->cc2_sink_detach_flag = CC2_SINK_NONE; + + return rc; +} + int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, const union power_supply_propval *val) { @@ -2035,9 +2224,24 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, EXIT_SNK_BASED_ON_CC_BIT, (val->intval) ? EXIT_SNK_BASED_ON_CC_BIT : 0); + if (rc < 0) { + smblib_err(chg, "Could not set EXIT_SNK_BASED_ON_CC rc=%d\n", + rc); + return rc; + } vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, val->intval, 0); + if (val->intval) + rc = smblib_cc2_sink_removal_enter(chg); + else + rc = smblib_cc2_sink_removal_exit(chg); + + if (rc < 0) { + smblib_err(chg, "Could not detect cc2 removal rc=%d\n", rc); + return rc; + } + return rc; } @@ -2208,6 +2412,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) struct smb_charger *chg = irq_data->parent_data; int rc; u8 stat; + bool vbus_rising; rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat); if (rc < 0) { @@ -2215,9 +2420,9 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) return IRQ_HANDLED; } - chg->vbus_present = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT); + vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT); smblib_set_opt_freq_buck(chg, - chg->vbus_present ? FSW_600HZ_FOR_5V : FSW_1MHZ_FOR_REMOVAL); + vbus_rising ? FSW_600HZ_FOR_5V : FSW_1MHZ_FOR_REMOVAL); /* fetch the DPDM regulator */ if (!chg->dpdm_reg && of_get_property(chg->dev->of_node, @@ -2230,11 +2435,8 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) } } - if (!chg->dpdm_reg) - goto skip_dpdm_float; - - if (chg->vbus_present) { - if (!regulator_is_enabled(chg->dpdm_reg)) { + if (vbus_rising) { + if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) { smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n"); rc = regulator_enable(chg->dpdm_reg); if (rc < 0) @@ -2242,7 +2444,14 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) rc); } } else { - if (regulator_is_enabled(chg->dpdm_reg)) { + if (chg->wa_flags & BOOST_BACK_WA) { + vote(chg->usb_suspend_votable, + BOOST_BACK_VOTER, false, 0); + vote(chg->dc_suspend_votable, + BOOST_BACK_VOTER, false, 0); + } + + if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) { smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n"); rc = regulator_disable(chg->dpdm_reg); if (rc < 0) @@ -2251,10 +2460,9 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) } } -skip_dpdm_float: power_supply_changed(chg->usb_psy); smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n", - irq_data->name, chg->vbus_present ? "attached" : "detached"); + irq_data->name, vbus_rising ? "attached" : "detached"); return IRQ_HANDLED; } @@ -2621,6 +2829,24 @@ static void smblib_handle_typec_debounce_done(struct smb_charger *chg, if (rc < 0) smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc); + /* + * HW BUG - after cable is removed, medium or high rd reading + * falls to std. Use it for signal of typec cc detachment in + * software WA. + */ + if (chg->cc2_sink_detach_flag == CC2_SINK_MEDIUM_HIGH + && pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) { + + chg->cc2_sink_detach_flag = CC2_SINK_WA_DONE; + + rc = smblib_masked_write(chg, + TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + EXIT_SNK_BASED_ON_CC_BIT, 0); + if (rc < 0) + smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", + rc); + } + smblib_dbg(chg, PR_INTERRUPT, "IRQ: debounce-done %s; Type-C %s detected\n", rising ? "rising" : "falling", smblib_typec_mode_name[pval.intval]); @@ -2634,6 +2860,10 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) u8 stat; bool debounce_done, sink_attached, legacy_cable; + /* WA - not when PD hard_reset WIP on cc2 in sink mode */ + if (chg->cc2_sink_detach_flag == CC2_SINK_STD) + return IRQ_HANDLED; + rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); if (rc < 0) { smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); @@ -2683,6 +2913,39 @@ irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data) return IRQ_HANDLED; } +irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + struct smb_charger *chg = irq_data->parent_data; + int rc; + u8 stat; + + if (!(chg->wa_flags & BOOST_BACK_WA)) + return IRQ_HANDLED; + + rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", rc); + return IRQ_HANDLED; + } + + if ((stat & USE_USBIN_BIT) && + get_effective_result(chg->usb_suspend_votable)) + return IRQ_HANDLED; + + if ((stat & USE_DCIN_BIT) && + get_effective_result(chg->dc_suspend_votable)) + return IRQ_HANDLED; + + if (is_storming(&irq_data->storm_data)) { + smblib_dbg(chg, PR_MISC, "reverse boost detected; suspending input\n"); + vote(chg->usb_suspend_votable, BOOST_BACK_VOTER, true, 0); + vote(chg->dc_suspend_votable, BOOST_BACK_VOTER, true, 0); + } + + return IRQ_HANDLED; +} + /*************** * Work Queues * ***************/ @@ -2743,7 +3006,9 @@ static void smblib_pl_taper_work(struct work_struct *work) union power_supply_propval pval = {0, }; int rc; + smblib_dbg(chg, PR_PARALLEL, "starting parallel taper work\n"); if (chg->pl.slave_fcc_ua < MINIMUM_PARALLEL_FCC_UA) { + smblib_dbg(chg, PR_PARALLEL, "parallel taper is done\n"); vote(chg->pl_disable_votable, TAPER_END_VOTER, true, 0); goto done; } @@ -2755,6 +3020,7 @@ static void smblib_pl_taper_work(struct work_struct *work) } if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { + smblib_dbg(chg, PR_PARALLEL, "master is taper charging; reducing slave FCC\n"); vote(chg->awake_votable, PL_TAPER_WORK_RUNNING_VOTER, true, 0); /* Reduce the taper percent by 25 percent */ chg->pl.taper_pct = chg->pl.taper_pct @@ -2768,6 +3034,8 @@ static void smblib_pl_taper_work(struct work_struct *work) /* * Master back to Fast Charge, get out of this round of taper reduction */ + smblib_dbg(chg, PR_PARALLEL, "master is fast charging; waiting for next taper\n"); + done: vote(chg->awake_votable, PL_TAPER_WORK_RUNNING_VOTER, false, 0); } @@ -2780,6 +3048,74 @@ static void clear_hdc_work(struct work_struct *work) chg->is_hdc = 0; } +static void rdstd_cc2_detach_work(struct work_struct *work) +{ + int rc; + u8 stat; + struct smb_irq_data irq_data = {NULL, "cc2-removal-workaround"}; + struct smb_charger *chg = container_of(work, struct smb_charger, + rdstd_cc2_detach_work); + + /* + * WA steps - + * 1. Enable both UFP and DFP, wait for 10ms. + * 2. Disable DFP, wait for 30ms. + * 3. Removal detected if both TYPEC_DEBOUNCE_DONE_STATUS + * and TIMER_STAGE bits are gone, otherwise repeat all by + * work rescheduling. + * Note, work will be cancelled when pd_hard_reset is 0. + */ + + rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + UFP_EN_CMD_BIT | DFP_EN_CMD_BIT, + UFP_EN_CMD_BIT | DFP_EN_CMD_BIT); + if (rc < 0) { + smblib_err(chg, "Couldn't write TYPE_C_CTRL_REG rc=%d\n", rc); + return; + } + + usleep_range(10000, 11000); + + rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + UFP_EN_CMD_BIT | DFP_EN_CMD_BIT, + UFP_EN_CMD_BIT); + if (rc < 0) { + smblib_err(chg, "Couldn't write TYPE_C_CTRL_REG rc=%d\n", rc); + return; + } + + usleep_range(30000, 31000); + + rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", + rc); + return; + } + if (stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT) + goto rerun; + + rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat); + if (rc < 0) { + smblib_err(chg, + "Couldn't read TYPE_C_STATUS_5_REG rc=%d\n", rc); + return; + } + if (stat & TIMER_STAGE_2_BIT) + goto rerun; + + /* Bingo, cc2 removal detected */ + smblib_reg_block_restore(chg, cc2_detach_settings); + chg->cc2_sink_detach_flag = CC2_SINK_WA_DONE; + irq_data.parent_data = chg; + smblib_handle_usb_typec_change(0, &irq_data); + + return; + +rerun: + schedule_work(&chg->rdstd_cc2_detach_work); +} + static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; @@ -2962,6 +3298,7 @@ int smblib_init(struct smb_charger *chg) mutex_init(&chg->write_lock); INIT_WORK(&chg->bms_update_work, bms_update_work); INIT_WORK(&chg->pl_detect_work, smblib_pl_detect_work); + INIT_WORK(&chg->rdstd_cc2_detach_work, rdstd_cc2_detach_work); INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work); INIT_DELAYED_WORK(&chg->pl_taper_work, smblib_pl_taper_work); INIT_DELAYED_WORK(&chg->step_soc_req_work, step_soc_req_work); diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index 4be06ffcfb25..a0237412ee8b 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -46,6 +46,7 @@ enum print_reason { #define VBUS_CC_SHORT_VOTER "VBUS_CC_SHORT_VOTER" #define LEGACY_CABLE_VOTER "LEGACY_CABLE_VOTER" #define PD_INACTIVE_VOTER "PD_INACTIVE_VOTER" +#define BOOST_BACK_VOTER "BOOST_BACK_VOTER" enum smb_mode { PARALLEL_MASTER = 0, @@ -53,8 +54,17 @@ enum smb_mode { NUM_MODES, }; +enum cc2_sink_type { + CC2_SINK_NONE = 0, + CC2_SINK_STD, + CC2_SINK_MEDIUM_HIGH, + CC2_SINK_WA_DONE, +}; + enum { - QC_CHARGER_DETECTION_WA_BIT = BIT(0), + QC_CHARGER_DETECTION_WA_BIT = BIT(0), + BOOST_BACK_WA = BIT(1), + TYPEC_CC2_REMOVAL_WA_BIT = BIT(2), }; struct smb_regulator { @@ -116,6 +126,14 @@ struct smb_iio { struct iio_channel *batt_i_chan; }; +struct reg_info { + u16 reg; + u8 mask; + u8 val; + u8 bak; + const char *desc; +}; + struct smb_charger { struct device *dev; char *name; @@ -167,6 +185,7 @@ struct smb_charger { /* work */ struct work_struct bms_update_work; struct work_struct pl_detect_work; + struct work_struct rdstd_cc2_detach_work; struct delayed_work hvdcp_detect_work; struct delayed_work ps_change_timeout_work; struct delayed_work pl_taper_work; @@ -177,7 +196,6 @@ struct smb_charger { int voltage_min_uv; int voltage_max_uv; int pd_active; - bool vbus_present; bool system_suspend_supported; int system_temp_level; @@ -195,6 +213,7 @@ struct smb_charger { /* workaround flag */ u32 wa_flags; + enum cc2_sink_type cc2_sink_detach_flag; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); @@ -240,6 +259,7 @@ irqreturn_t smblib_handle_icl_change(int irq, void *data); irqreturn_t smblib_handle_usb_typec_change(int irq, void *data); irqreturn_t smblib_handle_dc_plugin(int irq, void *data); irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data); +irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data); int smblib_get_prop_input_suspend(struct smb_charger *chg, union power_supply_propval *val); diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index a74fcf730a8c..c2a2b0c86d73 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -184,6 +184,10 @@ enum { #define CHARGE_INHIBIT_THRESHOLD_CFG_REG (CHGR_BASE + 0x72) #define CHARGE_INHIBIT_THRESHOLD_MASK GENMASK(1, 0) +#define CHARGE_INHIBIT_THRESHOLD_50MV 0 +#define CHARGE_INHIBIT_THRESHOLD_100MV 1 +#define CHARGE_INHIBIT_THRESHOLD_200MV 2 +#define CHARGE_INHIBIT_THRESHOLD_300MV 3 #define RECHARGE_THRESHOLD_CFG_REG (CHGR_BASE + 0x73) #define RECHARGE_THRESHOLD_MASK GENMASK(1, 0) @@ -701,9 +705,6 @@ enum { #define WIPWR_RANGE_STATUS_REG (DCIN_BASE + 0x08) #define WIPWR_RANGE_STATUS_MASK GENMASK(4, 0) -#define DC_INT_RT_STS_REG (DCIN_BASE + 0x10) -#define DCIN_PLUGIN_RT_STS_BIT BIT(4) - /* DCIN Interrupt Bits */ #define WIPWR_VOLTAGE_RANGE_RT_STS_BIT BIT(7) #define DCIN_ICL_CHANGE_RT_STS_BIT BIT(6) @@ -901,6 +902,7 @@ enum { #define MISC_CFG_REG (MISC_BASE + 0x52) #define GSM_PA_ON_ADJ_SEL_BIT BIT(0) +#define TCC_DEBOUNCE_20MS_BIT BIT(5) #define SNARL_BARK_BITE_WD_CFG_REG (MISC_BASE + 0x53) #define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7) diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c index 9a87ff5fb081..9dc528a6bb45 100644 --- a/drivers/power/qcom-charger/smb138x-charger.c +++ b/drivers/power/qcom-charger/smb138x-charger.c @@ -397,6 +397,7 @@ static int smb138x_init_batt_psy(struct smb138x *chip) *****************************/ static enum power_supply_property smb138x_parallel_props[] = { + POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_CHARGING_ENABLED, POWER_SUPPLY_PROP_PIN_ENABLED, POWER_SUPPLY_PROP_INPUT_SUSPEND, @@ -417,6 +418,9 @@ static int smb138x_parallel_get_prop(struct power_supply *psy, u8 temp; switch (prop) { + case POWER_SUPPLY_PROP_CHARGE_TYPE: + rc = smblib_get_prop_batt_charge_type(chg, val); + break; case POWER_SUPPLY_PROP_CHARGING_ENABLED: rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG, &temp); diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c index 2e41401f8580..3d0be1f8a5b5 100644 --- a/drivers/regulator/qpnp-labibb-regulator.c +++ b/drivers/regulator/qpnp-labibb-regulator.c @@ -32,6 +32,7 @@ #define QPNP_LABIBB_REGULATOR_DRIVER_NAME "qcom,qpnp-labibb-regulator" +#define REG_REVISION_2 0x01 #define REG_PERPH_TYPE 0x04 #define QPNP_LAB_TYPE 0x24 @@ -60,6 +61,7 @@ #define REG_LAB_PRECHARGE_CTL 0x5E #define REG_LAB_SOFT_START_CTL 0x5F #define REG_LAB_SPARE_CTL 0x60 +#define REG_LAB_PFM_CTL 0x62 /* LAB register bits definitions */ @@ -91,9 +93,9 @@ #define LAB_IBB_EN_RDY_EN BIT(7) /* REG_LAB_CURRENT_LIMIT */ -#define LAB_CURRENT_LIMIT_BITS 3 -#define LAB_CURRENT_LIMIT_MASK ((1 << LAB_CURRENT_LIMIT_BITS) - 1) -#define LAB_CURRENT_LIMIT_EN BIT(7) +#define LAB_CURRENT_LIMIT_MASK GENMASK(2, 0) +#define LAB_CURRENT_LIMIT_EN_BIT BIT(7) +#define LAB_OVERRIDE_CURRENT_MAX_BIT BIT(3) /* REG_LAB_CURRENT_SENSE */ #define LAB_CURRENT_SENSE_GAIN_BITS 2 @@ -129,6 +131,9 @@ #define LAB_SPARE_TOUCH_WAKE_BIT BIT(3) #define LAB_SPARE_DISABLE_SCP_BIT BIT(0) +/* REG_LAB_PFM_CTL */ +#define LAB_PFM_EN_BIT BIT(7) + /* IBB register offset definitions */ #define REG_IBB_REVISION4 0x03 #define REG_IBB_STATUS1 0x08 @@ -253,12 +258,6 @@ #define SWIRE_DEFAULT_2ND_CMD_DLY_MS 20 #define SWIRE_DEFAULT_IBB_PS_ENABLE_DLY_MS 200 -enum pmic_subtype { - PMI8994 = 10, - PMI8950 = 17, - PMI8996 = 19, -}; - /** * enum qpnp_labibb_mode - working mode of LAB/IBB regulators * %QPNP_LABIBB_LCD_MODE: configure LAB and IBB regulators @@ -350,6 +349,10 @@ static const int lab_current_limit_plan[] = { 400, 600, 800, + 1000, + 1200, + 1400, + 1600, }; static const char * const lab_current_sense_plan[] = { @@ -477,6 +480,8 @@ struct qpnp_labibb { struct pmic_revid_data *pmic_rev_id; u16 lab_base; u16 ibb_base; + u8 lab_dig_major; + u8 ibb_dig_major; struct lab_regulator lab_vreg; struct ibb_regulator ibb_vreg; enum qpnp_labibb_mode mode; @@ -487,6 +492,7 @@ struct qpnp_labibb { bool swire_control; bool ttw_force_lab_on; bool skip_2nd_swire_cmd; + bool pfm_enable; u32 swire_2nd_cmd_delay; u32 swire_ibb_ps_enable_delay; }; @@ -539,60 +545,58 @@ static struct settings lab_settings[LAB_SETTINGS_MAX] = { SETTING(LAB_RDSON_MNGMNT, false), }; -static int -qpnp_labibb_read(struct qpnp_labibb *labibb, u8 *val, - u16 base, int count) +static int qpnp_labibb_read(struct qpnp_labibb *labibb, u8 *val, u16 address, + int count) { int rc = 0; struct platform_device *pdev = labibb->pdev; - if (base == 0) { - pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n", - base, to_spmi_device(pdev->dev.parent)->usid, rc); + if (address == 0) { + pr_err("address cannot be zero address=0x%02x sid=0x%02x rc=%d\n", + address, to_spmi_device(pdev->dev.parent)->usid, rc); return -EINVAL; } - rc = regmap_bulk_read(labibb->regmap, base, val, count); + rc = regmap_bulk_read(labibb->regmap, address, val, count); if (rc) { - pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base, - to_spmi_device(pdev->dev.parent)->usid, rc); + pr_err("SPMI read failed address=0x%02x sid=0x%02x rc=%d\n", + address, to_spmi_device(pdev->dev.parent)->usid, rc); return rc; } + return 0; } -static int -qpnp_labibb_write(struct qpnp_labibb *labibb, u16 base, - u8 *val, int count) +static int qpnp_labibb_write(struct qpnp_labibb *labibb, u16 address, u8 *val, + int count) { int rc = 0; struct platform_device *pdev = labibb->pdev; - if (base == 0) { - pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n", - base, to_spmi_device(pdev->dev.parent)->usid, rc); + if (address == 0) { + pr_err("address cannot be zero address=0x%02x sid=0x%02x rc=%d\n", + address, to_spmi_device(pdev->dev.parent)->usid, rc); return -EINVAL; } - rc = regmap_bulk_write(labibb->regmap, base, val, count); + rc = regmap_bulk_write(labibb->regmap, address, val, count); if (rc) { - pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n", - base, to_spmi_device(pdev->dev.parent)->usid, rc); + pr_err("write failed address=0x%02x sid=0x%02x rc=%d\n", + address, to_spmi_device(pdev->dev.parent)->usid, rc); return rc; } return 0; } -static int -qpnp_labibb_masked_write(struct qpnp_labibb *labibb, u16 base, - u8 mask, u8 val) +static int qpnp_labibb_masked_write(struct qpnp_labibb *labibb, u16 address, + u8 mask, u8 val) { int rc; - rc = regmap_update_bits(labibb->regmap, base, mask, val); + rc = regmap_update_bits(labibb->regmap, address, mask, val); if (rc) { - pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc); + pr_err("spmi write failed: addr=%03X, rc=%d\n", address, rc); return rc; } @@ -709,18 +713,24 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb, u8 i, val; u32 tmp; - if (labibb->mode == QPNP_LABIBB_LCD_MODE) - val = REG_LAB_IBB_LCD_MODE; - else - val = REG_LAB_IBB_AMOLED_MODE; + /* + * Do not configure LCD_AMOLED_SEL for pmicobalt as it will be done by + * GPIO selector. + */ + if (labibb->pmic_rev_id->pmic_subtype != PMICOBALT_SUBTYPE) { + if (labibb->mode == QPNP_LABIBB_LCD_MODE) + val = REG_LAB_IBB_LCD_MODE; + else + val = REG_LAB_IBB_AMOLED_MODE; - rc = qpnp_labibb_sec_write(labibb, labibb->lab_base, - REG_LAB_LCD_AMOLED_SEL, &val, 1); + rc = qpnp_labibb_sec_write(labibb, labibb->lab_base, + REG_LAB_LCD_AMOLED_SEL, &val, 1); - if (rc) { - pr_err("qpnp_lab_sec_write register %x failed rc = %d\n", - REG_LAB_LCD_AMOLED_SEL, rc); - return rc; + if (rc) { + pr_err("qpnp_lab_sec_write register %x failed rc = %d\n", + REG_LAB_LCD_AMOLED_SEL, rc); + return rc; + } } val = 0; @@ -785,7 +795,7 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb, if (of_property_read_bool(of_node, "qcom,qpnp-lab-limit-max-current-enable")) - val |= LAB_CURRENT_LIMIT_EN; + val |= LAB_CURRENT_LIMIT_EN_BIT; rc = qpnp_labibb_write(labibb, labibb->lab_base + REG_LAB_CURRENT_LIMIT, &val, 1); @@ -938,6 +948,88 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb, return rc; } +#define LAB_CURRENT_MAX_1600MA 0x7 +#define LAB_CURRENT_MAX_400MA 0x1 +static int qpnp_lab_pfm_disable(struct qpnp_labibb *labibb) +{ + int rc = 0; + u8 val, mask; + + mutex_lock(&(labibb->lab_vreg.lab_mutex)); + if (!labibb->pfm_enable) { + pr_debug("PFM already disabled\n"); + goto out; + } + + val = 0; + mask = LAB_PFM_EN_BIT; + rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + + REG_LAB_PFM_CTL, mask, val); + if (rc < 0) { + pr_err("Write register %x failed rc = %d\n", + REG_LAB_PFM_CTL, rc); + goto out; + } + + val = LAB_CURRENT_MAX_1600MA; + mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK; + rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + + REG_LAB_CURRENT_LIMIT, mask, val); + if (rc < 0) { + pr_err("Write register %x failed rc = %d\n", + REG_LAB_CURRENT_LIMIT, rc); + goto out; + } + + labibb->pfm_enable = false; +out: + mutex_unlock(&(labibb->lab_vreg.lab_mutex)); + return rc; +} + +static int qpnp_lab_pfm_enable(struct qpnp_labibb *labibb) +{ + int rc = 0; + u8 val, mask; + + mutex_lock(&(labibb->lab_vreg.lab_mutex)); + if (labibb->pfm_enable) { + pr_debug("PFM already enabled\n"); + goto out; + } + + /* Wait for ~100uS */ + usleep_range(100, 105); + + val = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_MAX_400MA; + mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK; + rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + + REG_LAB_CURRENT_LIMIT, mask, val); + if (rc < 0) { + pr_err("Write register %x failed rc = %d\n", + REG_LAB_CURRENT_LIMIT, rc); + goto out; + } + + /* Wait for ~100uS */ + usleep_range(100, 105); + + val = LAB_PFM_EN_BIT; + mask = LAB_PFM_EN_BIT; + rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + + REG_LAB_PFM_CTL, mask, val); + if (rc < 0) { + pr_err("Write register %x failed rc = %d\n", + REG_LAB_PFM_CTL, rc); + goto out; + } + + labibb->pfm_enable = true; +out: + mutex_unlock(&(labibb->lab_vreg.lab_mutex)); + return rc; +} + static int qpnp_labibb_restore_settings(struct qpnp_labibb *labibb) { int rc, i; @@ -1172,7 +1264,7 @@ static int qpnp_labibb_regulator_ttw_mode_enter(struct qpnp_labibb *labibb) } val = LAB_SPARE_DISABLE_SCP_BIT; - if (labibb->pmic_rev_id->pmic_subtype != PMI8950) + if (labibb->pmic_rev_id->pmic_subtype != PMI8950_SUBTYPE) val |= LAB_SPARE_TOUCH_WAKE_BIT; rc = qpnp_labibb_write(labibb, labibb->lab_base + REG_LAB_SPARE_CTL, &val, 1); @@ -1199,10 +1291,10 @@ static int qpnp_labibb_regulator_ttw_mode_enter(struct qpnp_labibb *labibb) } switch (labibb->pmic_rev_id->pmic_subtype) { - case PMI8996: + case PMI8996_SUBTYPE: rc = qpnp_labibb_ttw_enter_ibb_pmi8996(labibb); break; - case PMI8950: + case PMI8950_SUBTYPE: rc = qpnp_labibb_ttw_enter_ibb_pmi8950(labibb); break; } @@ -1282,9 +1374,9 @@ static int qpnp_labibb_regulator_ttw_mode_exit(struct qpnp_labibb *labibb) } switch (labibb->pmic_rev_id->pmic_subtype) { - case PMI8996: - case PMI8994: - case PMI8950: + case PMI8996_SUBTYPE: + case PMI8994_SUBTYPE: + case PMI8950_SUBTYPE: rc = qpnp_labibb_ttw_exit_ibb_common(labibb); break; } @@ -1437,6 +1529,15 @@ static int qpnp_labibb_regulator_disable(struct qpnp_labibb *labibb) return -EINVAL; } + if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && + labibb->mode == QPNP_LABIBB_LCD_MODE) { + rc = qpnp_lab_pfm_disable(labibb); + if (rc < 0) { + pr_err("Error in disabling PFM, rc=%d\n", rc); + return rc; + } + } + labibb->lab_vreg.vreg_enabled = 0; labibb->ibb_vreg.vreg_enabled = 0; @@ -1646,9 +1747,17 @@ static irqreturn_t lab_vreg_ok_handler(int irq, void *_labibb) struct qpnp_labibb *labibb = _labibb; int rc; - rc = qpnp_skip_swire_command(labibb); - if (rc) - pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n", rc); + if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2) { + rc = qpnp_skip_swire_command(labibb); + if (rc < 0) + pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n", + rc); + } else if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && + labibb->mode == QPNP_LABIBB_LCD_MODE) { + rc = qpnp_lab_pfm_enable(labibb); + if (rc < 0) + pr_err("Failed to config PFM, rc=%d\n", rc); + } return IRQ_HANDLED; } @@ -1663,6 +1772,23 @@ static int qpnp_lab_regulator_get_voltage(struct regulator_dev *rdev) return labibb->lab_vreg.curr_volt; } +static bool is_lab_vreg_ok_irq_available(struct qpnp_labibb *labibb) +{ + /* + * LAB VREG_OK interrupt is used only to skip 2nd SWIRE command in + * dig_major < 2 targets. For pmicobalt, it is used to enable PFM in + * LCD mode. + */ + if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2) + return true; + + if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && + labibb->mode == QPNP_LABIBB_LCD_MODE) + return true; + + return false; +} + static struct regulator_ops qpnp_lab_ops = { .enable = qpnp_lab_regulator_enable, .disable = qpnp_lab_regulator_disable, @@ -1784,16 +1910,16 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, } if (of_find_property(of_node, - "qpnp,qpnp-lab-current-sense", NULL)) { + "qcom,qpnp-lab-current-sense", NULL)) { config_current_sense = true; rc = of_property_read_string(of_node, - "qpnp,qpnp-lab-current-sense", + "qcom,qpnp-lab-current-sense", ¤t_sense_str); if (!rc) { val = qpnp_labibb_get_matching_idx( current_sense_str); } else { - pr_err("qpnp,qpnp-lab-current-sense configured incorrectly rc = %d\n", + pr_err("qcom,qpnp-lab-current-sense configured incorrectly rc = %d\n", rc); return rc; } @@ -1811,19 +1937,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, } } - if (labibb->skip_2nd_swire_cmd) { - rc = devm_request_threaded_irq(labibb->dev, - labibb->lab_vreg.lab_vreg_ok_irq, NULL, - lab_vreg_ok_handler, - IRQF_ONESHOT | IRQF_TRIGGER_RISING, - "lab-vreg-ok", labibb); - if (rc) { - pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n", - rc); - return rc; - } - } - val = (labibb->standalone) ? 0 : LAB_IBB_EN_RDY_EN; rc = qpnp_labibb_sec_write(labibb, labibb->lab_base, REG_LAB_IBB_EN_RDY, &val, 1); @@ -1901,6 +2014,19 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, labibb->lab_vreg.vreg_enabled = 1; } + if (is_lab_vreg_ok_irq_available(labibb)) { + rc = devm_request_threaded_irq(labibb->dev, + labibb->lab_vreg.lab_vreg_ok_irq, NULL, + lab_vreg_ok_handler, + IRQF_ONESHOT | IRQF_TRIGGER_RISING, + "lab-vreg-ok", labibb); + if (rc) { + pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n", + rc); + return rc; + } + } + rc = qpnp_labibb_read(labibb, &val, labibb->lab_base + REG_LAB_MODULE_RDY, 1); if (rc) { @@ -1955,7 +2081,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, return -EINVAL; } - mutex_init(&(labibb->lab_vreg.lab_mutex)); return 0; } @@ -1966,18 +2091,37 @@ static int qpnp_ibb_dt_init(struct qpnp_labibb *labibb, u32 i, tmp; u8 val; - if (labibb->mode == QPNP_LABIBB_LCD_MODE) - val = REG_LAB_IBB_LCD_MODE; - else - val = REG_LAB_IBB_AMOLED_MODE; + /* + * Do not configure LCD_AMOLED_SEL for pmicobalt as it will be done by + * GPIO selector. Override the labibb->mode with what was configured + * by the bootloader. + */ + if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE) { + rc = qpnp_labibb_read(labibb, &val, + labibb->ibb_base + REG_IBB_LCD_AMOLED_SEL, 1); + if (rc) { + pr_err("qpnp_labibb_read register %x failed rc = %d\n", + REG_IBB_LCD_AMOLED_SEL, rc); + return rc; + } - rc = qpnp_labibb_sec_write(labibb, labibb->ibb_base, - REG_LAB_LCD_AMOLED_SEL, &val, 1); + if (val == REG_LAB_IBB_AMOLED_MODE) + labibb->mode = QPNP_LABIBB_AMOLED_MODE; + else + labibb->mode = QPNP_LABIBB_LCD_MODE; + } else { + if (labibb->mode == QPNP_LABIBB_LCD_MODE) + val = REG_LAB_IBB_LCD_MODE; + else + val = REG_LAB_IBB_AMOLED_MODE; - if (rc) { - pr_err("qpnp_labibb_sec_write register %x failed rc = %d\n", - REG_IBB_LCD_AMOLED_SEL, rc); - return rc; + rc = qpnp_labibb_sec_write(labibb, labibb->ibb_base, + REG_LAB_LCD_AMOLED_SEL, &val, 1); + if (rc) { + pr_err("qpnp_labibb_sec_write register %x failed rc = %d\n", + REG_IBB_LCD_AMOLED_SEL, rc); + return rc; + } } rc = of_property_read_u32(of_node, "qcom,qpnp-ibb-lab-pwrdn-delay", @@ -2482,6 +2626,13 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb, return rc; } + /* + * For pmicobalt, override swire_control with what was configured + * before by the bootloader. + */ + if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE) + labibb->swire_control = val & IBB_ENABLE_CTL_SWIRE_RDY; + if (ibb_enable_ctl & (IBB_ENABLE_CTL_SWIRE_RDY | IBB_ENABLE_CTL_MODULE_EN)) { /* SWIRE_RDY or IBB_MODULE_EN enabled */ @@ -2659,14 +2810,13 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb, return -EINVAL; } - mutex_init(&(labibb->ibb_vreg.ibb_mutex)); return 0; } static int qpnp_lab_register_irq(struct device_node *child, struct qpnp_labibb *labibb) { - if (labibb->skip_2nd_swire_cmd) { + if (is_lab_vreg_ok_irq_available(labibb)) { labibb->lab_vreg.lab_vreg_ok_irq = of_irq_get_byname(child, "lab-vreg-ok"); if (labibb->lab_vreg.lab_vreg_ok_irq < 0) { @@ -2684,7 +2834,7 @@ static int qpnp_labibb_check_ttw_supported(struct qpnp_labibb *labibb) u8 val; switch (labibb->pmic_rev_id->pmic_subtype) { - case PMI8996: + case PMI8996_SUBTYPE: rc = qpnp_labibb_read(labibb, &val, labibb->ibb_base + REG_IBB_REVISION4, 1); if (rc) { @@ -2702,7 +2852,7 @@ static int qpnp_labibb_check_ttw_supported(struct qpnp_labibb *labibb) /* FORCE_LAB_ON in TTW is not required for PMI8996 */ labibb->ttw_force_lab_on = false; break; - case PMI8950: + case PMI8950_SUBTYPE: /* TTW supported for all revisions */ break; default: @@ -2721,7 +2871,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) unsigned int base; struct device_node *child, *revid_dev_node; const char *mode_name; - u8 type; + u8 type, revision; int rc = 0; labibb = devm_kzalloc(&pdev->dev, @@ -2739,6 +2889,9 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) labibb->dev = &(pdev->dev); labibb->pdev = pdev; + mutex_init(&(labibb->lab_vreg.lab_mutex)); + mutex_init(&(labibb->ibb_vreg.ibb_mutex)); + revid_dev_node = of_parse_phandle(labibb->dev->of_node, "qcom,pmic-revid", 0); if (!revid_dev_node) { @@ -2753,19 +2906,19 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) } rc = of_property_read_string(labibb->dev->of_node, - "qpnp,qpnp-labibb-mode", &mode_name); + "qcom,qpnp-labibb-mode", &mode_name); if (!rc) { if (strcmp("lcd", mode_name) == 0) { labibb->mode = QPNP_LABIBB_LCD_MODE; } else if (strcmp("amoled", mode_name) == 0) { labibb->mode = QPNP_LABIBB_AMOLED_MODE; } else { - pr_err("Invalid device property in qpnp,qpnp-labibb-mode: %s\n", + pr_err("Invalid device property in qcom,qpnp-labibb-mode: %s\n", mode_name); return -EINVAL; } } else { - pr_err("qpnp_labibb: qpnp,qpnp-labibb-mode is missing.\n"); + pr_err("qpnp_labibb: qcom,qpnp-labibb-mode is missing.\n"); return rc; } @@ -2783,15 +2936,17 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) labibb->dev->of_node, "qcom,labibb-ttw-force-lab-on"); labibb->swire_control = of_property_read_bool(labibb->dev->of_node, - "qpnp,swire-control"); + "qcom,swire-control"); if (labibb->swire_control && labibb->mode != QPNP_LABIBB_AMOLED_MODE) { pr_err("Invalid mode for SWIRE control\n"); return -EINVAL; } + if (labibb->swire_control) { labibb->skip_2nd_swire_cmd = of_property_read_bool(labibb->dev->of_node, "qcom,skip-2nd-swire-cmd"); + rc = of_property_read_u32(labibb->dev->of_node, "qcom,swire-2nd-cmd-delay", &labibb->swire_2nd_cmd_delay); @@ -2811,6 +2966,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) pr_err("no child nodes\n"); return -ENXIO; } + for_each_available_child_of_node(pdev->dev.of_node, child) { rc = of_property_read_u32(child, "reg", &base); if (rc < 0) { @@ -2820,6 +2976,13 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) return rc; } + rc = qpnp_labibb_read(labibb, &revision, base + REG_REVISION_2, + 1); + if (rc) { + pr_err("Reading REVISION_2 failed rc=%d\n", rc); + goto fail_registration; + } + rc = qpnp_labibb_read(labibb, &type, base + REG_PERPH_TYPE, 1); if (rc) { @@ -2830,6 +2993,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) switch (type) { case QPNP_LAB_TYPE: labibb->lab_base = base; + labibb->lab_dig_major = revision; rc = qpnp_lab_register_irq(child, labibb); if (rc) { pr_err("Failed to register LAB IRQ rc=%d\n", @@ -2843,6 +3007,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) case QPNP_IBB_TYPE: labibb->ibb_base = base; + labibb->ibb_dig_major = revision; rc = register_qpnp_ibb_regulator(labibb, child); if (rc) goto fail_registration; diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index 9cfca014c8ad..382245eb90b6 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -3948,7 +3948,6 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr, xprt_ptr->edge, xprt_ptr->name); if (IS_ERR_OR_NULL(xprt_ptr->tx_task)) { GLINK_ERR("%s: unable to run thread\n", __func__); - glink_core_deinit_xprt_qos_cfg(xprt_ptr); kfree(xprt_ptr); return -ENOMEM; } diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c index 00cc5e12709b..dcca82fc25c6 100644 --- a/drivers/soc/qcom/memshare/msm_memshare.c +++ b/drivers/soc/qcom/memshare/msm_memshare.c @@ -39,6 +39,7 @@ static DECLARE_DELAYED_WORK(work_recv_msg, mem_share_svc_recv_msg); static struct workqueue_struct *mem_share_svc_workqueue; static uint64_t bootup_request; static void *memshare_ramdump_dev[MAX_CLIENTS]; +static struct device *memshare_dev[MAX_CLIENTS]; /* Memshare Driver Structure */ struct memshare_driver { @@ -145,9 +146,14 @@ static int mem_share_configure_ramdump(void) } snprintf(client_name, 18, "memshare_%s", clnt); - - memshare_ramdump_dev[num_clients] = create_ramdump_device(client_name, - NULL); + if (memshare_dev[num_clients]) { + memshare_ramdump_dev[num_clients] = + create_ramdump_device(client_name, + memshare_dev[num_clients]); + } else { + pr_err("memshare:%s: invalid memshare device\n", __func__); + return -ENODEV; + } if (IS_ERR_OR_NULL(memshare_ramdump_dev[num_clients])) { pr_err("memshare: %s: Unable to create memshare ramdump device.\n", __func__); @@ -957,6 +963,8 @@ static int memshare_child_probe(struct platform_device *pdev) * memshare clients */ + memshare_dev[num_clients] = &pdev->dev; + if (!memblock[num_clients].file_created) { rc = mem_share_configure_ramdump(); if (rc) diff --git a/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c b/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c index e4c8f1f446df..a876484859eb 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.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 Mree software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -133,7 +133,7 @@ static ssize_t bus_floor_vote_store_api(struct device *dev, return 0; } - if (sscanf(buf, "%s %llu", name, &vote_khz) != 2) { + if (sscanf(buf, "%9s %llu", name, &vote_khz) != 2) { pr_err("%s:return error", __func__); return -EINVAL; } diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c index afe6b2309e27..95d50fe01ee1 100644 --- a/drivers/soc/qcom/secure_buffer.c +++ b/drivers/soc/qcom/secure_buffer.c @@ -260,7 +260,7 @@ int hyp_assign_table(struct sg_table *table, int *dest_vmids, int *dest_perms, int dest_nelems) { - int ret; + int ret = 0; struct scm_desc desc = {0}; u32 *source_vm_copy; size_t source_vm_copy_size; diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c index 24018c544b06..2b708732760f 100644 --- a/drivers/soc/qcom/service-locator.c +++ b/drivers/soc/qcom/service-locator.c @@ -149,7 +149,7 @@ static void service_locator_recv_msg(struct work_struct *work) do { pr_debug("Notified about a Receive event\n"); ret = qmi_recv_msg(service_locator.clnt_handle); - if (ret != -ENOMSG) + if (ret < 0) pr_err("Error receiving message rc:%d. Retrying...\n", ret); } while (ret == 0); diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c index 8cba88742cb8..a244bc168136 100644 --- a/drivers/soc/qcom/service-notifier.c +++ b/drivers/soc/qcom/service-notifier.c @@ -162,7 +162,7 @@ static void root_service_clnt_recv_msg(struct work_struct *work) data->instance_id); } while ((ret = qmi_recv_msg(data->clnt_handle)) == 0); - pr_info("Notified about a Receive event (instance-id: %d)\n", + pr_debug("Notified about a Receive event (instance-id: %d)\n", data->instance_id); } @@ -227,7 +227,8 @@ static void root_service_service_ind_cb(struct qmi_handle *handle, struct qmi_client_info *data = (struct qmi_client_info *)ind_cb_priv; struct service_notif_info *service_notif; struct msg_desc ind_desc; - struct qmi_servreg_notif_state_updated_ind_msg_v01 ind_msg; + struct qmi_servreg_notif_state_updated_ind_msg_v01 ind_msg = { + QMI_STATE_MIN_VAL, "", 0xFFFF }; int rc; ind_desc.msg_id = SERVREG_NOTIF_STATE_UPDATED_IND_MSG; diff --git a/drivers/soc/qcom/sysmon.c b/drivers/soc/qcom/sysmon.c index 8a12341a6f91..f8d0f10b1173 100644 --- a/drivers/soc/qcom/sysmon.c +++ b/drivers/soc/qcom/sysmon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-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 @@ -206,7 +206,7 @@ int sysmon_send_shutdown_no_qmi(struct subsys_desc *dest_desc) return -ENODEV; mutex_lock(&ss->lock); - ret = sysmon_send_msg(ss, tx_buf, ARRAY_SIZE(tx_buf)); + ret = sysmon_send_msg(ss, tx_buf, strlen(tx_buf)); if (ret) { pr_err("Message sending failed %d\n", ret); goto out; @@ -257,7 +257,7 @@ int sysmon_get_reason_no_qmi(struct subsys_desc *dest_desc, return -ENODEV; mutex_lock(&ss->lock); - ret = sysmon_send_msg(ss, tx_buf, ARRAY_SIZE(tx_buf)); + ret = sysmon_send_msg(ss, tx_buf, strlen(tx_buf)); if (ret) { pr_err("Message sending failed %d\n", ret); goto out; diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index c0b936d802ef..0ae654a921f8 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -24,6 +24,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/spmi.h> +#include <linux/syscore_ops.h> /* PMIC Arbiter configuration registers */ #define PMIC_ARB_VERSION 0x0000 @@ -159,6 +160,7 @@ struct spmi_pmic_arb { u16 last_apid; struct apid_data apid_data[PMIC_ARB_MAX_PERIPHS]; }; +static struct spmi_pmic_arb *the_pa; /** * pmic_arb_ver: version dependent functionality. @@ -525,7 +527,7 @@ static void cleanup_irq(struct spmi_pmic_arb *pa, u16 apid, int id) irq_mask, ppid); } -static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid) +static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid, bool show) { unsigned int irq; u32 status; @@ -542,22 +544,32 @@ static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid) cleanup_irq(pa, apid, id); continue; } - generic_handle_irq(irq); + if (show) { + struct irq_desc *desc; + const char *name = "null"; + + desc = irq_to_desc(irq); + if (desc == NULL) + name = "stray irq"; + else if (desc->action && desc->action->name) + name = desc->action->name; + + pr_warn("spmi_show_resume_irq: %d triggered [0x%01x, 0x%02x, 0x%01x] %s\n", + irq, sid, per, id, name); + } else { + generic_handle_irq(irq); + } } } -static void pmic_arb_chained_irq(struct irq_desc *desc) +static void __pmic_arb_chained_irq(struct spmi_pmic_arb *pa, bool show) { - struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); void __iomem *intr = pa->intr; int first = pa->min_apid >> 5; int last = pa->max_apid >> 5; u32 status, enable; int i, id, apid; - chained_irq_enter(chip, desc); - for (i = first; i <= last; ++i) { status = readl_relaxed(intr + pa->ver_ops->owner_acc_status(pa->ee, i)); @@ -568,10 +580,18 @@ static void pmic_arb_chained_irq(struct irq_desc *desc) enable = readl_relaxed(intr + pa->ver_ops->acc_enable(apid)); if (enable & SPMI_PIC_ACC_ENABLE_BIT) - periph_interrupt(pa, apid); + periph_interrupt(pa, apid, show); } } +} + +static void pmic_arb_chained_irq(struct irq_desc *desc) +{ + struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + chained_irq_enter(chip, desc); + __pmic_arb_chained_irq(pa, false); chained_irq_exit(chip, desc); } @@ -988,6 +1008,16 @@ static const struct irq_domain_ops pmic_arb_irq_domain_ops = { .xlate = qpnpint_irq_domain_dt_translate, }; +static void spmi_pmic_arb_resume(void) +{ + if (spmi_show_resume_irq()) + __pmic_arb_chained_irq(the_pa, true); +} + +static struct syscore_ops spmi_pmic_arb_syscore_ops = { + .resume = spmi_pmic_arb_resume, +}; + static int spmi_pmic_arb_probe(struct platform_device *pdev) { struct spmi_pmic_arb *pa; @@ -1153,6 +1183,8 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) if (err) goto err_domain_remove; + the_pa = pa; + register_syscore_ops(&spmi_pmic_arb_syscore_ops); return 0; err_domain_remove: @@ -1167,8 +1199,11 @@ static int spmi_pmic_arb_remove(struct platform_device *pdev) { struct spmi_controller *ctrl = platform_get_drvdata(pdev); struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl); + spmi_controller_remove(ctrl); irq_set_chained_handler_and_data(pa->irq, NULL, NULL); + unregister_syscore_ops(&spmi_pmic_arb_syscore_ops); + the_pa = NULL; irq_domain_remove(pa->domain); spmi_controller_put(ctrl); return 0; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 269c1ee2da44..5839111ab4e0 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -48,6 +48,11 @@ static void hub_event(struct work_struct *work); /* synchronize hub-port add/remove and peering operations */ DEFINE_MUTEX(usb_port_peer_mutex); +static bool skip_extended_resume_delay = 1; +module_param(skip_extended_resume_delay, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(skip_extended_resume_delay, + "removes extra delay added to finish bus resume"); + /* cycle leds on hubs that aren't blinking for attention */ static bool blinkenlights = 0; module_param(blinkenlights, bool, S_IRUGO); @@ -3434,7 +3439,9 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) /* drive resume for USB_RESUME_TIMEOUT msec */ dev_dbg(&udev->dev, "usb %sresume\n", (PMSG_IS_AUTO(msg) ? "auto-" : "")); - msleep(USB_RESUME_TIMEOUT); + if (!skip_extended_resume_delay) + usleep_range(USB_RESUME_TIMEOUT * 1000, + (USB_RESUME_TIMEOUT + 1) * 1000); /* Virtual root hubs can trigger on GET_PORT_STATUS to * stop resume signaling. Then finish the resume @@ -3443,7 +3450,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) status = hub_port_status(hub, port1, &portstatus, &portchange); /* TRSMRCY = 10 msec */ - msleep(10); + usleep_range(10000, 10500); } SuspendCleared: diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 5db4fe9e3cdf..be29dc4bef89 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1528,7 +1528,14 @@ static int android_setup(struct usb_gadget *gadget, static void android_disconnect(struct usb_gadget *gadget) { struct usb_composite_dev *cdev = get_gadget_data(gadget); - struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); + struct gadget_info *gi; + + if (!cdev) { + pr_err("%s: gadget is not connected\n", __func__); + return; + } + + gi = container_of(cdev, struct gadget_info, cdev); /* accessory HID support can be active while the accessory function is not actually enabled, diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index 5e50fe245a59..33f7304eac84 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -43,6 +43,7 @@ #include "configfs.h" #define MTP_RX_BUFFER_INIT_SIZE 1048576 +#define MTP_TX_BUFFER_INIT_SIZE 1048576 #define MTP_BULK_BUFFER_SIZE 16384 #define INTR_BUFFER_SIZE 28 #define MAX_INST_NAME_LEN 40 @@ -81,7 +82,7 @@ unsigned int mtp_rx_req_len = MTP_RX_BUFFER_INIT_SIZE; module_param(mtp_rx_req_len, uint, S_IRUGO | S_IWUSR); -unsigned int mtp_tx_req_len = MTP_BULK_BUFFER_SIZE; +unsigned int mtp_tx_req_len = MTP_TX_BUFFER_INIT_SIZE; module_param(mtp_tx_req_len, uint, S_IRUGO | S_IWUSR); unsigned int mtp_tx_reqs = MTP_TX_REQ_MAX; @@ -551,9 +552,6 @@ static int mtp_create_bulk_endpoints(struct mtp_dev *dev, dev->ep_intr = ep; retry_tx_alloc: - if (mtp_tx_req_len > MTP_BULK_BUFFER_SIZE) - mtp_tx_reqs = 4; - /* now allocate requests for our endpoints */ for (i = 0; i < mtp_tx_reqs; i++) { req = mtp_request_new(dev->ep_in, mtp_tx_req_len); @@ -753,8 +751,8 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf, break; } - if (count > MTP_BULK_BUFFER_SIZE) - xfer = MTP_BULK_BUFFER_SIZE; + if (count > mtp_tx_req_len) + xfer = mtp_tx_req_len; else xfer = count; if (xfer && copy_from_user(req->buf, buf, xfer)) { @@ -850,8 +848,8 @@ static void send_file_work(struct work_struct *data) break; } - if (count > MTP_BULK_BUFFER_SIZE) - xfer = MTP_BULK_BUFFER_SIZE; + if (count > mtp_tx_req_len) + xfer = mtp_tx_req_len; else xfer = count; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 0f51d078416e..a7b055bc279a 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1165,7 +1165,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_set_link_state(xhci, port_array, wIndex, XDEV_RESUME); spin_unlock_irqrestore(&xhci->lock, flags); - msleep(20); + usleep_range(21000, 21500); spin_lock_irqsave(&xhci->lock, flags); xhci_set_link_state(xhci, port_array, wIndex, XDEV_U0); @@ -1409,7 +1409,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) if (need_usb2_u3_exit) { spin_unlock_irqrestore(&xhci->lock, flags); - msleep(20); + usleep_range(21000, 21500); spin_lock_irqsave(&xhci->lock, flags); } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index ac298e632d73..29dc6ab252b1 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1789,6 +1789,8 @@ void xhci_free_command(struct xhci_hcd *xhci, int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned intr_num) { int size; + u32 iman_reg; + u64 erdp_reg; struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct device *dev = xhci_to_hcd(xhci)->self.controller; @@ -1800,14 +1802,38 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned intr_num) size = sizeof(struct xhci_erst_entry)*(xhci->sec_erst[intr_num].num_entries); - if (xhci->sec_erst[intr_num].entries) + if (xhci->sec_erst[intr_num].entries) { + /* + * disable irq, ack pending interrupt and clear EHB for xHC to + * generate interrupt again when new event ring is setup + */ + iman_reg = + readl_relaxed(&xhci->sec_ir_set[intr_num]->irq_pending); + iman_reg &= ~IMAN_IE; + writel_relaxed(iman_reg, + &xhci->sec_ir_set[intr_num]->irq_pending); + iman_reg = + readl_relaxed(&xhci->sec_ir_set[intr_num]->irq_pending); + if (iman_reg & IMAN_IP) + writel_relaxed(iman_reg, + &xhci->sec_ir_set[intr_num]->irq_pending); + /* make sure IP gets cleared before clearing EHB */ + mb(); + + erdp_reg = xhci_read_64(xhci, + &xhci->sec_ir_set[intr_num]->erst_dequeue); + xhci_write_64(xhci, erdp_reg | ERST_EHB, + &xhci->sec_ir_set[intr_num]->erst_dequeue); + dma_free_coherent(dev, size, xhci->sec_erst[intr_num].entries, xhci->sec_erst[intr_num].erst_dma_addr); - xhci->sec_erst[intr_num].entries = NULL; + xhci->sec_erst[intr_num].entries = NULL; + } xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed SEC ERST#%d", intr_num); if (xhci->sec_event_ring[intr_num]) xhci_ring_free(xhci, xhci->sec_event_ring[intr_num]); + xhci->sec_event_ring[intr_num] = NULL; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed sec event ring"); diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 084dbbc81a6d..c025dccdd8f1 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -332,7 +332,7 @@ static int xhci_plat_runtime_suspend(struct device *dev) dev_dbg(dev, "xhci-plat runtime suspend\n"); - return xhci_suspend(xhci, true); + return 0; } static int xhci_plat_runtime_resume(struct device *dev) @@ -346,7 +346,7 @@ static int xhci_plat_runtime_resume(struct device *dev) dev_dbg(dev, "xhci-plat runtime resume\n"); - ret = xhci_resume(xhci, false); + ret = 0; pm_runtime_mark_last_busy(dev); return ret; diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 1e93a5b2e9ba..5a24a1995af9 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -178,6 +178,7 @@ enum mdss_hw_capabilities { MDSS_CAPS_CWB_SUPPORTED, MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED, MDSS_CAPS_AVR_SUPPORTED, + MDSS_CAPS_SEC_DETACH_SMMU, MDSS_CAPS_MAX, }; @@ -221,6 +222,7 @@ struct mdss_smmu_client { bool domain_attached; bool handoff_pending; void __iomem *mmu_base; + int domain; }; struct mdss_mdp_qseed3_lut_tbl { @@ -327,6 +329,7 @@ struct mdss_data_type { u32 wfd_mode; u32 has_no_lut_read; atomic_t sd_client_count; + atomic_t sc_client_count; u8 has_wb_ad; u8 has_non_scalar_rgb; bool has_src_split; @@ -519,6 +522,8 @@ struct mdss_data_type { u32 max_dest_scaler_input_width; u32 max_dest_scaler_output_width; struct mdss_mdp_destination_scaler *ds; + u32 sec_disp_en; + u32 sec_cam_en; }; extern struct mdss_data_type *mdss_res; @@ -579,6 +584,14 @@ static inline int mdss_get_sd_client_cnt(void) return atomic_read(&mdss_res->sd_client_count); } +static inline int mdss_get_sc_client_cnt(void) +{ + if (!mdss_res) + return 0; + else + return atomic_read(&mdss_res->sc_client_count); +} + static inline void mdss_set_quirk(struct mdss_data_type *mdata, enum mdss_hw_quirk bit) { diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 75e42ca8cd88..29fc4e6fd65b 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -45,6 +45,11 @@ #define VDDA_UA_ON_LOAD 100000 /* uA units */ #define VDDA_UA_OFF_LOAD 100 /* uA units */ +struct mdss_dp_attention_node { + u32 vdo; + struct list_head list; +}; + #define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3 static u32 supported_modes[] = { HDMI_VFRMT_640x480p60_4_3, @@ -60,6 +65,7 @@ static u32 supported_modes[] = { static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv); static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata); static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp); +static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp_drv); static void mdss_dp_put_dt_clk_data(struct device *dev, struct dss_module_power *module_power) @@ -1133,7 +1139,7 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp, mdss_dp_fill_link_cfg(dp); mdss_dp_mainlink_ctrl(&dp->ctrl_io, true); mdss_dp_config_ctrl(dp); - mdss_dp_sw_mvid_nvid(&dp->ctrl_io); + mdss_dp_sw_config_msa(&dp->ctrl_io, dp->link_rate, &dp->dp_cc_io); mdss_dp_timing_cfg(&dp->ctrl_io, &dp->panel_data.panel_info); } @@ -1290,7 +1296,6 @@ link_training: dp_drv->cont_splash = 0; dp_drv->power_on = true; - mdss_dp_ack_state(dp_drv, true); pr_debug("End-\n"); exit: @@ -1559,6 +1564,7 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata) goto edid_error; } + mdss_dp_update_cable_status(dp_drv, true); mdss_dp_notify_clients(dp_drv, true); dp_drv->dp_initialized = true; @@ -1883,8 +1889,13 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp) } /* update internal data about hdcp */ - dp->hdcp.data = fd; - dp->hdcp.ops = ops; + if (dp->hdcp.hdcp2_present || dp->hdcp.hdcp1_present) { + dp->hdcp.data = fd; + dp->hdcp.ops = ops; + } else { + dp->hdcp.data = NULL; + dp->hdcp.ops = NULL; + } } static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv) @@ -1920,6 +1931,8 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata, if (dp->hdcp.ops && dp->hdcp.ops->authenticate) rc = dp->hdcp.ops->authenticate(dp->hdcp.data); + + mdss_dp_ack_state(dp, true); break; case MDSS_EVENT_PANEL_OFF: rc = mdss_dp_off(pdata); @@ -2041,6 +2054,12 @@ static int mdss_retrieve_dp_ctrl_resources(struct platform_device *pdev, return rc; } + if (msm_dss_ioremap_byname(pdev, &dp_drv->dp_cc_io, "dp_mmss_cc")) { + pr_err("%d unable to remap dp MMSS_CC resources\n", + __LINE__); + return rc; + } + if (msm_dss_ioremap_byname(pdev, &dp_drv->qfprom_io, "qfprom_physical")) pr_warn("unable to remap dp qfprom resources\n"); @@ -2117,6 +2136,9 @@ static void mdss_dp_event_work(struct work_struct *work) case EV_IDLE_PATTERNS_SENT: mdss_dp_idle_patterns_sent(dp); break; + case EV_USBPD_ATTENTION: + mdss_dp_handle_attention(dp); + break; case EV_USBPD_DISCOVER_MODES: usbpd_send_svdm(dp->pd, USB_C_DP_SID, USBPD_SVDM_DISCOVER_MODES, SVDM_CMD_TYPE_INITIATOR, 0x0, 0x0, 0x0); @@ -2225,6 +2247,7 @@ static int mdss_dp_event_setup(struct mdss_dp_drv_pdata *dp) INIT_WORK(&dp->work, mdss_dp_event_work); INIT_DELAYED_WORK(&dp->hdcp_cb_work, mdss_dp_hdcp_cb_work); + INIT_LIST_HEAD(&dp->attention_head); return 0; } @@ -2508,6 +2531,7 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, const u32 *vdos, int num_vdos) { struct mdss_dp_drv_pdata *dp_drv; + struct mdss_dp_attention_node *node; dp_drv = container_of(hdlr, struct mdss_dp_drv_pdata, svid_handler); if (!dp_drv->pd) { @@ -2535,45 +2559,14 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, dp_send_events(dp_drv, EV_USBPD_DP_STATUS); break; case USBPD_SVDM_ATTENTION: - dp_drv->alt_mode.dp_status.response = *vdos; - mdss_dp_usbpd_ext_dp_status(&dp_drv->alt_mode.dp_status); - - dp_drv->hpd_irq_toggled = dp_drv->hpd_irq_on != - dp_drv->alt_mode.dp_status.hpd_irq; + node = kzalloc(sizeof(*node), GFP_KERNEL); + node->vdo = *vdos; - if (dp_drv->alt_mode.dp_status.hpd_irq) { - pr_debug("Attention: hpd_irq high\n"); - - if (dp_drv->power_on && dp_drv->hdcp.ops && - dp_drv->hdcp.ops->cp_irq) - dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data); - - if (!mdss_dp_process_hpd_irq_high(dp_drv)) - break; - } else if (dp_drv->hpd_irq_toggled) { - if (!mdss_dp_process_hpd_irq_low(dp_drv)) - break; - } - - if (!dp_drv->alt_mode.dp_status.hpd_high) { - pr_debug("Attention: HPD low\n"); - mdss_dp_update_cable_status(dp_drv, false); - mdss_dp_notify_clients(dp_drv, false); - pr_debug("Attention: Notified clients\n"); - break; - } - - pr_debug("Attention: HPD high\n"); - - mdss_dp_update_cable_status(dp_drv, true); - - dp_drv->alt_mode.current_state |= DP_STATUS_DONE; - - if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE) - mdss_dp_host_init(&dp_drv->panel_data); - else - dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE); + mutex_lock(&dp_drv->attention_lock); + list_add_tail(&node->list, &dp_drv->attention_head); + mutex_unlock(&dp_drv->attention_lock); + dp_send_events(dp_drv, EV_USBPD_ATTENTION); break; case DP_VDM_STATUS: dp_drv->alt_mode.dp_status.response = *vdos; @@ -2597,6 +2590,74 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, } } +static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv) +{ + dp_drv->hpd_irq_toggled = dp_drv->hpd_irq_on != + dp_drv->alt_mode.dp_status.hpd_irq; + + if (dp_drv->alt_mode.dp_status.hpd_irq) { + pr_debug("Attention: hpd_irq high\n"); + + if (dp_drv->power_on && dp_drv->hdcp.ops && + dp_drv->hdcp.ops->cp_irq) + dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data); + + if (!mdss_dp_process_hpd_irq_high(dp_drv)) + return; + } else if (dp_drv->hpd_irq_toggled) { + if (!mdss_dp_process_hpd_irq_low(dp_drv)) + return; + } + + if (!dp_drv->alt_mode.dp_status.hpd_high) { + pr_debug("Attention: HPD low\n"); + mdss_dp_update_cable_status(dp_drv, false); + mdss_dp_notify_clients(dp_drv, false); + pr_debug("Attention: Notified clients\n"); + return; + } + + pr_debug("Attention: HPD high\n"); + + mdss_dp_update_cable_status(dp_drv, true); + + dp_drv->alt_mode.current_state |= DP_STATUS_DONE; + + if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE) + mdss_dp_host_init(&dp_drv->panel_data); + else + dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE); + + pr_debug("exit\n"); +} + +static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp) +{ + int i = 0; + + while (!list_empty_careful(&dp->attention_head)) { + struct mdss_dp_attention_node *node; + u32 vdo; + + pr_debug("processing item %d in the list\n", ++i); + + mutex_lock(&dp->attention_lock); + node = list_first_entry(&dp->attention_head, + struct mdss_dp_attention_node, list); + + vdo = node->vdo; + list_del(&node->list); + mutex_unlock(&dp->attention_lock); + + kzfree(node); + + dp->alt_mode.dp_status.response = vdo; + mdss_dp_usbpd_ext_dp_status(&dp->alt_mode.dp_status); + mdss_dp_process_attention(dp); + }; + +} + static int mdss_dp_usbpd_setup(struct mdss_dp_drv_pdata *dp_drv) { int ret = 0; @@ -2670,6 +2731,7 @@ static int mdss_dp_probe(struct platform_device *pdev) dp_drv->mask2 = EDP_INTR_MASK2; mutex_init(&dp_drv->emutex); mutex_init(&dp_drv->pd_msg_mutex); + mutex_init(&dp_drv->attention_lock); mutex_init(&dp_drv->hdcp_mutex); spin_lock_init(&dp_drv->lock); diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index e801eceeef1b..04abe9221acc 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -205,6 +205,7 @@ struct dp_alt_mode { #define EV_USBPD_DP_CONFIGURE BIT(10) #define EV_USBPD_CC_PIN_POLARITY BIT(11) #define EV_USBPD_EXIT_MODE BIT(12) +#define EV_USBPD_ATTENTION BIT(13) /* dp state ctrl */ #define ST_TRAIN_PATTERN_1 BIT(0) @@ -406,6 +407,7 @@ struct mdss_dp_drv_pdata { struct dss_io_data ctrl_io; struct dss_io_data phy_io; struct dss_io_data tcsr_reg_io; + struct dss_io_data dp_cc_io; struct dss_io_data qfprom_io; struct dss_io_data hdcp_io; int base_size; @@ -454,6 +456,7 @@ struct mdss_dp_drv_pdata { struct mutex aux_mutex; struct mutex train_mutex; struct mutex pd_msg_mutex; + struct mutex attention_lock; struct mutex hdcp_mutex; bool cable_connected; u32 s3d_mode; @@ -497,6 +500,8 @@ struct mdss_dp_drv_pdata { struct dpcd_test_request test_data; struct dpcd_sink_count sink_count; + + struct list_head attention_head; }; enum dp_lane_count { diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index 9014e3a02d21..b64518194926 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -514,7 +514,7 @@ char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt) { const u32 encoding_factx10 = 8; const u32 ln_to_link_ratio = 10; - u32 min_link_rate; + u32 min_link_rate, reminder = 0; char calc_link_rate = 0; pr_debug("clk_rate=%llu, bpp= %d, lane_cnt=%d\n", @@ -527,13 +527,19 @@ char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt) * Any changes in the section of code should * consider this limitation. */ - min_link_rate = pinfo->clk_rate - / (lane_cnt * encoding_factx10); + min_link_rate = (u32)div_u64(pinfo->clk_rate, + (lane_cnt * encoding_factx10)); min_link_rate /= ln_to_link_ratio; min_link_rate = (min_link_rate * pinfo->bpp); - min_link_rate = (u32)div_u64(min_link_rate * 10, - DP_LINK_RATE_MULTIPLIER); + min_link_rate = (u32)div_u64_rem(min_link_rate * 10, + DP_LINK_RATE_MULTIPLIER, &reminder); + /* + * To avoid any fractional values, + * increment the min_link_rate + */ + if (reminder) + min_link_rate += 1; pr_debug("min_link_rate = %d\n", min_link_rate); if (min_link_rate <= DP_LINK_RATE_162) @@ -1647,6 +1653,8 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp) clear: dp_clear_training_pattern(dp); if (ret != -EINVAL) { + mdss_dp_config_misc_settings(&dp->ctrl_io, + &dp->panel_data.panel_info); mdss_dp_setup_tr_unit(&dp->ctrl_io, dp->link_rate, dp->lane_cnt, dp->vic); mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO); diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c index 2d24d8499105..86edc4492599 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.c +++ b/drivers/video/fbdev/msm/mdss_dp_util.c @@ -253,10 +253,48 @@ void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io, writel_relaxed(data, ctrl_io->base + DP_ACTIVE_HOR_VER); } -void mdss_dp_sw_mvid_nvid(struct dss_io_data *ctrl_io) +void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io, + char lrate, struct dss_io_data *dp_cc_io) { - writel_relaxed(0x37, ctrl_io->base + DP_SOFTWARE_MVID); - writel_relaxed(0x3c, ctrl_io->base + DP_SOFTWARE_NVID); + u32 pixel_m, pixel_n; + u32 mvid, nvid; + + pixel_m = readl_relaxed(dp_cc_io->base + MMSS_DP_PIXEL_M); + pixel_n = readl_relaxed(dp_cc_io->base + MMSS_DP_PIXEL_N); + pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", + pixel_m, pixel_n); + + mvid = (pixel_m & 0xFFFF) * 5; + nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); + if (lrate == DP_LINK_RATE_540) + nvid = nvid * 2; + pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); + writel_relaxed(mvid, ctrl_io->base + DP_SOFTWARE_MVID); + writel_relaxed(nvid, ctrl_io->base + DP_SOFTWARE_NVID); +} + +void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io, + struct mdss_panel_info *pinfo) +{ + u32 bpp = pinfo->bpp; + u32 misc_val = 0x0; + + switch (bpp) { + case 18: + misc_val |= (0x0 << 5); + break; + case 30: + misc_val |= (0x2 << 5); + break; + case 24: + default: + misc_val |= (0x1 << 5); + } + + misc_val |= BIT(0); /* Configure clock to synchronous mode */ + + pr_debug("Misc settings = 0x%x\n", misc_val); + writel_relaxed(misc_val, ctrl_io->base + DP_MISC1_MISC0); } void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, @@ -267,8 +305,6 @@ void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, u32 valid_boundary2 = 0x0; struct dp_vc_tu_mapping_table const *tu_entry = tu_table; - writel_relaxed(0x21, ctrl_io->base + DP_MISC1_MISC0); - for (; tu_entry != tu_table + ARRAY_SIZE(tu_table); ++tu_entry) { if ((tu_entry->vic == res) && (tu_entry->lanes == ln_cnt) && @@ -454,8 +490,14 @@ u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp) pin_cfg = dp->alt_mode.dp_cap.dlink_pin_config; for (pin = PIN_ASSIGNMENT_A; pin < PIN_ASSIGNMENT_MAX; pin++) { - if (pin_cfg & BIT(pin)) - break; + if (pin_cfg & BIT(pin)) { + if (dp->alt_mode.dp_status.multi_func) { + if (pin == PIN_ASSIGNMENT_D) + break; + } else { + break; + } + } } if (pin == PIN_ASSIGNMENT_MAX) diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h index 334c0071050d..4b28d98177be 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.h +++ b/drivers/video/fbdev/msm/mdss_dp_util.h @@ -164,6 +164,12 @@ #define TCSR_USB3_DP_PHYMODE 0x48 #define EDID_START_ADDRESS 0x50 +/* DP MMSS_CC registers */ +#define MMSS_DP_LINK_CMD_RCGR 0x0000 +#define MMSS_DP_LINK_CFG_RCGR 0x0004 +#define MMSS_DP_PIXEL_M 0x0048 +#define MMSS_DP_PIXEL_N 0x004C + /* DP HDCP 1.3 registers */ #define DP_HDCP_CTRL (0x0A0) #define DP_HDCP_STATUS (0x0A4) @@ -271,6 +277,8 @@ void mdss_dp_switch_usb3_phy_to_dp_mode(struct dss_io_data *tcsr_reg_io); void mdss_dp_assert_phy_reset(struct dss_io_data *ctrl_io, bool assert); void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, u8 ln_cnt, u32 res); +void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io, + struct mdss_panel_info *pinfo); void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io); void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable); void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable); @@ -285,7 +293,8 @@ void mdss_dp_state_ctrl(struct dss_io_data *ctrl_io, u32 data); int mdss_dp_irq_setup(struct mdss_dp_drv_pdata *dp_drv); void mdss_dp_irq_enable(struct mdss_dp_drv_pdata *dp_drv); void mdss_dp_irq_disable(struct mdss_dp_drv_pdata *dp_drv); -void mdss_dp_sw_mvid_nvid(struct dss_io_data *ctrl_io); +void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io, + char lrate, struct dss_io_data *dp_cc_io); void mdss_dp_usbpd_ext_capabilities(struct usbpd_dp_capabilities *dp_cap); void mdss_dp_usbpd_ext_dp_status(struct usbpd_dp_status *dp_status); u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp); diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 7091dc2f38b9..3536cb2d294d 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -468,6 +468,7 @@ struct mdss_dsi_ctrl_pdata { bool cmd_sync_wait_trigger; struct mdss_rect roi; + struct mdss_dsi_dual_pu_roi dual_roi; struct pwm_device *pwm_bl; u32 pclk_rate; u32 byte_clk_rate; diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index bd0c2ad32c05..7c36bb627043 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -447,28 +447,82 @@ static int mdss_dsi_roi_merge(struct mdss_dsi_ctrl_pdata *ctrl, static char caset[] = {0x2a, 0x00, 0x00, 0x03, 0x00}; /* DTYPE_DCS_LWRITE */ static char paset[] = {0x2b, 0x00, 0x00, 0x05, 0x00}; /* DTYPE_DCS_LWRITE */ +/* + * Some panels can support multiple ROIs as part of the below commands + */ +static char caset_dual[] = {0x2a, 0x00, 0x00, 0x03, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00};/* DTYPE_DCS_LWRITE */ +static char paset_dual[] = {0x2b, 0x00, 0x00, 0x05, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00};/* DTYPE_DCS_LWRITE */ + /* pack into one frame before sent */ static struct dsi_cmd_desc set_col_page_addr_cmd[] = { {{DTYPE_DCS_LWRITE, 0, 0, 0, 1, sizeof(caset)}, caset}, /* packed */ {{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset)}, paset}, }; +/* pack into one frame before sent */ +static struct dsi_cmd_desc set_dual_col_page_addr_cmd[] = { /*packed*/ + {{DTYPE_DCS_LWRITE, 0, 0, 0, 1, sizeof(caset_dual)}, caset_dual}, + {{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset_dual)}, paset_dual}, +}; + + +static void __mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl, + struct mdss_rect *roi, bool dual_roi) +{ + if (dual_roi) { + struct mdss_rect *first, *second; + + first = &ctrl->panel_data.panel_info.dual_roi.first_roi; + second = &ctrl->panel_data.panel_info.dual_roi.second_roi; + + caset_dual[1] = (((first->x) & 0xFF00) >> 8); + caset_dual[2] = (((first->x) & 0xFF)); + caset_dual[3] = (((first->x - 1 + first->w) & 0xFF00) >> 8); + caset_dual[4] = (((first->x - 1 + first->w) & 0xFF)); + /* skip the MPU setting byte*/ + caset_dual[6] = (((second->x) & 0xFF00) >> 8); + caset_dual[7] = (((second->x) & 0xFF)); + caset_dual[8] = (((second->x - 1 + second->w) & 0xFF00) >> 8); + caset_dual[9] = (((second->x - 1 + second->w) & 0xFF)); + set_dual_col_page_addr_cmd[0].payload = caset_dual; + + paset_dual[1] = (((first->y) & 0xFF00) >> 8); + paset_dual[2] = (((first->y) & 0xFF)); + paset_dual[3] = (((first->y - 1 + first->h) & 0xFF00) >> 8); + paset_dual[4] = (((first->y - 1 + first->h) & 0xFF)); + /* skip the MPU setting byte */ + paset_dual[6] = (((second->y) & 0xFF00) >> 8); + paset_dual[7] = (((second->y) & 0xFF)); + paset_dual[8] = (((second->y - 1 + second->h) & 0xFF00) >> 8); + paset_dual[9] = (((second->y - 1 + second->h) & 0xFF)); + set_dual_col_page_addr_cmd[1].payload = paset_dual; + } else { + caset[1] = (((roi->x) & 0xFF00) >> 8); + caset[2] = (((roi->x) & 0xFF)); + caset[3] = (((roi->x - 1 + roi->w) & 0xFF00) >> 8); + caset[4] = (((roi->x - 1 + roi->w) & 0xFF)); + set_col_page_addr_cmd[0].payload = caset; + + paset[1] = (((roi->y) & 0xFF00) >> 8); + paset[2] = (((roi->y) & 0xFF)); + paset[3] = (((roi->y - 1 + roi->h) & 0xFF00) >> 8); + paset[4] = (((roi->y - 1 + roi->h) & 0xFF)); + set_col_page_addr_cmd[1].payload = paset; + } + pr_debug("%s Sending 2A 2B cmnd with dual_roi=%d\n", __func__, + dual_roi); + +} static void mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl, struct mdss_rect *roi, int unicast) { struct dcs_cmd_req cmdreq; + struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info; + bool dual_roi = pinfo->dual_roi.enabled; - caset[1] = (((roi->x) & 0xFF00) >> 8); - caset[2] = (((roi->x) & 0xFF)); - caset[3] = (((roi->x - 1 + roi->w) & 0xFF00) >> 8); - caset[4] = (((roi->x - 1 + roi->w) & 0xFF)); - set_col_page_addr_cmd[0].payload = caset; - - paset[1] = (((roi->y) & 0xFF00) >> 8); - paset[2] = (((roi->y) & 0xFF)); - paset[3] = (((roi->y - 1 + roi->h) & 0xFF00) >> 8); - paset[4] = (((roi->y - 1 + roi->h) & 0xFF)); - set_col_page_addr_cmd[1].payload = paset; + __mdss_dsi_send_col_page_addr(ctrl, roi, dual_roi); memset(&cmdreq, 0, sizeof(cmdreq)); cmdreq.cmds_cnt = 2; @@ -478,7 +532,9 @@ static void mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl, cmdreq.rlen = 0; cmdreq.cb = NULL; - cmdreq.cmds = set_col_page_addr_cmd; + /* Send default or dual roi 2A/2B cmd */ + cmdreq.cmds = dual_roi ? set_dual_col_page_addr_cmd : + set_col_page_addr_cmd; mdss_dsi_cmdlist_put(ctrl, &cmdreq); } @@ -1837,20 +1893,28 @@ error: pinfo->esd_check_enabled = false; } -static int mdss_dsi_parse_panel_features(struct device_node *np, - struct mdss_dsi_ctrl_pdata *ctrl) +static void mdss_dsi_parse_partial_update_caps(struct device_node *np, + struct mdss_dsi_ctrl_pdata *ctrl) { struct mdss_panel_info *pinfo; - - if (!np || !ctrl) { - pr_err("%s: Invalid arguments\n", __func__); - return -ENODEV; - } + const char *data; pinfo = &ctrl->panel_data.panel_info; - pinfo->partial_update_supported = of_property_read_bool(np, - "qcom,partial-update-enabled"); + data = of_get_property(np, "qcom,partial-update-enabled", NULL); + if (data && !strcmp(data, "single_roi")) + pinfo->partial_update_supported = + PU_SINGLE_ROI; + else if (data && !strcmp(data, "dual_roi")) + pinfo->partial_update_supported = + PU_DUAL_ROI; + else if (data && !strcmp(data, "none")) + pinfo->partial_update_supported = + PU_NOT_SUPPORTED; + else + pinfo->partial_update_supported = + PU_NOT_SUPPORTED; + if (pinfo->mipi.mode == DSI_CMD_MODE) { pinfo->partial_update_enabled = pinfo->partial_update_supported; pr_info("%s: partial_update_enabled=%d\n", __func__, @@ -1862,6 +1926,21 @@ static int mdss_dsi_parse_panel_features(struct device_node *np, "qcom,partial-update-roi-merge"); } } +} + +static int mdss_dsi_parse_panel_features(struct device_node *np, + struct mdss_dsi_ctrl_pdata *ctrl) +{ + struct mdss_panel_info *pinfo; + + if (!np || !ctrl) { + pr_err("%s: Invalid arguments\n", __func__); + return -ENODEV; + } + + pinfo = &ctrl->panel_data.panel_info; + + mdss_dsi_parse_partial_update_caps(np, ctrl); pinfo->dcs_cmd_by_left = of_property_read_bool(np, "qcom,dcs-cmd-by-left"); diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index bcd23d3c19f2..08e06c75522a 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -564,7 +564,7 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev, "min_fps=%d\nmax_fps=%d\npanel_name=%s\n" "primary_panel=%d\nis_pluggable=%d\ndisplay_id=%s\n" "is_cec_supported=%d\nis_pingpong_split=%d\n" - "dfps_porch_mode=%d\n", + "dfps_porch_mode=%d\npu_roi_cnt=%d\ndual_dsi=%d", pinfo->partial_update_enabled, pinfo->roi_alignment.xstart_pix_align, pinfo->roi_alignment.width_pix_align, @@ -577,7 +577,8 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev, pinfo->panel_name, pinfo->is_prim_panel, pinfo->is_pluggable, pinfo->display_id, pinfo->is_cec_supported, is_pingpong_split(mfd), - dfps_porch_mode); + dfps_porch_mode, pinfo->partial_update_enabled, + is_panel_split(mfd)); return ret; } @@ -3282,6 +3283,7 @@ int mdss_fb_atomic_commit(struct fb_info *info, mfd->msm_fb_backup.atomic_commit = true; mfd->msm_fb_backup.disp_commit.l_roi = commit_v1->left_roi; mfd->msm_fb_backup.disp_commit.r_roi = commit_v1->right_roi; + mfd->msm_fb_backup.disp_commit.flags = commit_v1->flags; mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt); diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 04e8fa4ba576..1dae41391795 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -47,6 +47,8 @@ #include <linux/msm-bus-board.h> #include <soc/qcom/scm.h> #include <soc/qcom/rpm-smd.h> +#include "soc/qcom/secure_buffer.h" +#include <asm/cacheflush.h> #include "mdss.h" #include "mdss_fb.h" @@ -64,6 +66,8 @@ #define RES_1080p (1088*1920) #define RES_UHD (3840*2160) +#define MDP_DEVICE_ID 0x1A + struct mdss_data_type *mdss_res; static u32 mem_protect_sd_ctrl_id; @@ -87,6 +91,7 @@ struct msm_mdp_interface mdp5 = { #define MEM_PROTECT_SD_CTRL 0xF #define MEM_PROTECT_SD_CTRL_FLAT 0x14 +#define MEM_PROTECT_SD_CTRL_SWITCH 0x18 static DEFINE_SPINLOCK(mdp_lock); static DEFINE_SPINLOCK(mdss_mdp_intr_lock); @@ -1329,7 +1334,9 @@ int mdss_iommu_ctrl(int enable) if (mdata->iommu_ref_cnt == 0) { rc = mdss_smmu_detach(mdata); if (mdss_has_quirk(mdata, - MDSS_QUIRK_MIN_BUS_VOTE)) + MDSS_QUIRK_MIN_BUS_VOTE) && + (!mdata->sec_disp_en || + !mdata->sec_cam_en)) mdss_bus_scale_set_quota(MDSS_HW_RT, 0, 0); } @@ -1985,6 +1992,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdata->pixel_ram_size = 50 * 1024; mdata->rects_per_sspp[MDSS_MDP_PIPE_TYPE_DMA] = 2; + mem_protect_sd_ctrl_id = MEM_PROTECT_SD_CTRL_SWITCH; set_bit(MDSS_QOS_PER_PIPE_IB, mdata->mdss_qos_map); set_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map); set_bit(MDSS_QOS_TS_PREFILL, mdata->mdss_qos_map); @@ -2015,6 +2023,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdata->has_wb_ubwc = true; set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map); set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map); + set_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map); break; default: mdata->max_target_zorder = 4; /* excluding base layer */ @@ -4939,29 +4948,115 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) } } -int mdss_mdp_secure_display_ctrl(unsigned int enable) +int mdss_mdp_secure_session_ctrl(unsigned int enable, u64 flags) { + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); struct sd_ctrl_req { unsigned int enable; } __attribute__ ((__packed__)) request; unsigned int resp = -1; int ret = 0; + uint32_t sid_info; struct scm_desc desc; - desc.args[0] = request.enable = enable; - desc.arginfo = SCM_ARGS(1); + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map)) { + /* + * Prepare syscall to hypervisor to switch the secure_vmid + * between secure and non-secure contexts + */ + /* MDP secure SID */ + sid_info = 0x1; + desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL); + desc.args[0] = MDP_DEVICE_ID; + desc.args[1] = SCM_BUFFER_PHYS(&sid_info); + desc.args[2] = sizeof(uint32_t); + - if (!is_scm_armv8()) { - ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL, - &request, sizeof(request), &resp, sizeof(resp)); - } else { - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + pr_debug("Enable/Disable: %d, Flags %llx\n", enable, flags); + if (enable) { + if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + desc.args[3] = VMID_CP_SEC_DISPLAY; + mdata->sec_disp_en = 1; + } else if (flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) { + desc.args[3] = VMID_CP_CAMERA_PREVIEW; + mdata->sec_cam_en = 1; + } else { + return 0; + } + + /* detach smmu contexts */ + ret = mdss_smmu_detach(mdata); + if (ret) { + pr_err("Error while detaching smmu contexts ret = %d\n", + ret); + return -EINVAL; + } + + /* let the driver think smmu is still attached */ + mdata->iommu_attached = true; + + dmac_flush_range(&sid_info, &sid_info + 1); + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, mem_protect_sd_ctrl_id), &desc); - resp = desc.ret[0]; - } + if (ret) { + pr_err("Error scm_call MEM_PROTECT_SD_CTRL(%u) ret=%dm resp=%x\n", + enable, ret, resp); + return -EINVAL; + } + resp = desc.ret[0]; - pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x", + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", + enable, ret, resp); + } else { + desc.args[3] = VMID_CP_PIXEL; + if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) + mdata->sec_disp_en = 0; + else if (flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) + mdata->sec_cam_en = 0; + + dmac_flush_range(&sid_info, &sid_info + 1); + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + mem_protect_sd_ctrl_id), &desc); + if (ret) + MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", + "dsi0_phy", "dsi1_ctrl", + "dsi1_phy", "vbif", "vbif_nrt", + "dbg_bus", "vbif_dbg_bus", + "panic"); + resp = desc.ret[0]; + + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", + enable, ret, resp); + + /* re-attach smmu contexts */ + mdata->iommu_attached = false; + ret = mdss_smmu_attach(mdata); + if (ret) { + pr_err("Error while attaching smmu contexts ret = %d\n", + ret); + return -EINVAL; + } + } + MDSS_XLOG(enable); + } else { + desc.args[0] = request.enable = enable; + desc.arginfo = SCM_ARGS(1); + + if (!is_scm_armv8()) { + ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL, + &request, + sizeof(request), + &resp, + sizeof(resp)); + } else { + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + mem_protect_sd_ctrl_id), &desc); + resp = desc.ret[0]; + } + + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", enable, ret, resp); + } if (ret) return ret; diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 93f5f9a51a63..e1c3841c82de 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -92,6 +92,8 @@ */ #define ENABLE_PIXEL_EXT_ONLY 0x80000000 +/* Pipe flag to indicate this pipe contains secure camera buffer */ +#define MDP_SECURE_CAMERA_OVERLAY_SESSION 0x100000000 /** * Destination Scaler control flags setting * @@ -562,6 +564,8 @@ struct mdss_mdp_mixer { bool valid_roi; bool roi_changed; struct mdss_rect roi; + bool dsc_enabled; + bool dsc_merge_enabled; u8 cursor_enabled; u16 cursor_hotx; @@ -627,7 +631,7 @@ struct mdss_mdp_img_data { dma_addr_t addr; unsigned long len; u32 offset; - u32 flags; + u64 flags; u32 dir; u32 domain; bool mapped; @@ -811,7 +815,7 @@ struct mdss_mdp_pipe { struct file *file; bool is_handed_off; - u32 flags; + u64 flags; u32 bwc_mode; /* valid only when pipe's output is crossing both layer mixers */ @@ -827,6 +831,9 @@ struct mdss_mdp_pipe { struct mdss_mdp_format_params *src_fmt; struct mdss_mdp_plane_sizes src_planes; + /* flag to re-store roi in case of pu dual-roi validation error */ + bool restore_roi; + /* compression ratio from the source format */ struct mult_factor comp_ratio; @@ -916,6 +923,7 @@ struct mdss_overlay_private { u32 splash_mem_addr; u32 splash_mem_size; u32 sd_enabled; + u32 sc_enabled; struct sw_sync_timeline *vsync_timeline; struct mdss_mdp_vsync_handler vsync_retire_handler; @@ -1289,6 +1297,15 @@ static inline void mdss_update_sd_client(struct mdss_data_type *mdata, atomic_add_unless(&mdss_res->sd_client_count, -1, 0); } +static inline void mdss_update_sc_client(struct mdss_data_type *mdata, + bool status) +{ + if (status) + atomic_inc(&mdata->sc_client_count); + else + atomic_add_unless(&mdss_res->sc_client_count, -1, 0); +} + static inline int mdss_mdp_get_wb_ctl_support(struct mdss_data_type *mdata, bool rotator_session) { @@ -1506,6 +1523,7 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata, struct mdss_mdp_img_data *data) { u32 is_secure_ui = data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION; + u64 is_secure_camera = data->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION; /* * For ULT Targets we need SMMU Map, to issue map call for secure Display. @@ -1513,6 +1531,10 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata, if (is_secure_ui && !mdss_has_quirk(mdata, MDSS_QUIRK_NEED_SECURE_MAP)) return false; + if (is_secure_camera && test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map)) + return false; + return true; } @@ -1569,7 +1591,7 @@ unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked); int mdss_mdp_vsync_clk_enable(int enable, bool locked); void mdss_mdp_clk_ctrl(int enable); struct mdss_data_type *mdss_mdp_get_mdata(void); -int mdss_mdp_secure_display_ctrl(unsigned int enable); +int mdss_mdp_secure_session_ctrl(unsigned int enable, u64 flags); int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd); int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd, @@ -1603,7 +1625,7 @@ int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd); void mdss_mdp_overlay_set_chroma_sample( struct mdss_mdp_pipe *pipe); int mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe, - u32 flags); + u64 flags); int mdss_mdp_overlay_setup_scaling(struct mdss_mdp_pipe *pipe); struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata, struct mdss_mdp_mixer *mixer, u32 ndx, @@ -1836,7 +1858,7 @@ struct mult_factor *mdss_mdp_get_comp_factor(u32 format, int mdss_mdp_data_map(struct mdss_mdp_data *data, bool rotator, int dir); void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir); int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir, struct mdp_layer_buffer *buffer); u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd); @@ -1847,7 +1869,7 @@ void mdss_mdp_intersect_rect(struct mdss_rect *res_rect, const struct mdss_rect *sci_rect); void mdss_mdp_crop_rect(struct mdss_rect *src_rect, struct mdss_rect *dst_rect, - const struct mdss_rect *sci_rect); + const struct mdss_rect *sci_rect, bool normalize); void rect_copy_mdss_to_mdp(struct mdp_rect *user, struct mdss_rect *kernel); void rect_copy_mdp_to_mdss(struct mdp_rect *user, struct mdss_rect *kernel); bool mdss_rect_overlap_check(struct mdss_rect *rect1, struct mdss_rect *rect2); diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 1d61653b76bb..9ed44937efe6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -728,7 +728,7 @@ int mdss_mdp_get_pipe_overlap_bw(struct mdss_mdp_pipe *pipe, /* crop rectangles */ if (roi && !mixer->ctl->is_video_mode && !pipe->src_split_req) - mdss_mdp_crop_rect(&src, &dst, roi); + mdss_mdp_crop_rect(&src, &dst, roi, true); /* * when doing vertical decimation lines will be skipped, hence there is @@ -1108,7 +1108,7 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, /* crop rectangles */ if (roi && !mixer->ctl->is_video_mode && !pipe->src_split_req) - mdss_mdp_crop_rect(&src, &dst, roi); + mdss_mdp_crop_rect(&src, &dst, roi, true); pr_debug("v_total=%d, xres=%d fps=%d\n", v_total, xres, fps); pr_debug("src(w,h)(%d,%d) dst(w,h)(%d,%d) dst_y=%d bpp=%d yuv=%d\n", @@ -2743,6 +2743,7 @@ static inline void __dsc_enable(struct mdss_mdp_mixer *mixer) { mdss_mdp_pingpong_write(mixer->pingpong_base, MDSS_MDP_REG_PP_DSC_MODE, 1); + mixer->dsc_enabled = true; } static inline void __dsc_disable(struct mdss_mdp_mixer *mixer) @@ -2762,6 +2763,13 @@ static inline void __dsc_disable(struct mdss_mdp_mixer *mixer) return; } writel_relaxed(0, offset + MDSS_MDP_REG_DSC_COMMON_MODE); + mixer->dsc_enabled = false; + mixer->dsc_merge_enabled = false; +} + +static bool __is_dsc_merge_enabled(u32 common_mode) +{ + return common_mode & BIT(1); } static void __dsc_config(struct mdss_mdp_mixer *mixer, @@ -2774,6 +2782,7 @@ static void __dsc_config(struct mdss_mdp_mixer *mixer, u32 initial_lines = dsc->initial_lines; bool is_cmd_mode = !(mode & BIT(2)); + mixer->dsc_merge_enabled = __is_dsc_merge_enabled(mode); data = mdss_mdp_pingpong_read(mixer->pingpong_base, MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP); data |= BIT(18); /* endian flip */ @@ -2928,11 +2937,6 @@ static void __dsc_config_thresh(struct mdss_mdp_mixer *mixer, } } -static bool __is_dsc_merge_enabled(u32 common_mode) -{ - return common_mode & BIT(1); -} - static bool __dsc_is_3d_mux_enabled(struct mdss_mdp_ctl *ctl, struct mdss_panel_info *pinfo) { @@ -3291,8 +3295,19 @@ void mdss_mdp_ctl_dsc_setup(struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl; struct mdss_panel_info *spinfo; - if (!is_dsc_compression(pinfo)) + /* + * Check for dynamic resolution switch from DSC On to DSC Off + * and disable DSC + */ + if ((ctl->pending_mode_switch == SWITCH_RESOLUTION) && + ctl->is_master && + (!is_dsc_compression(pinfo))) { + if (ctl->mixer_left && ctl->mixer_left->dsc_enabled) + __dsc_disable(ctl->mixer_left); + if (ctl->mixer_right && ctl->mixer_right->dsc_enabled) + __dsc_disable(ctl->mixer_right); return; + } if (!ctl->is_master) { pr_debug("skip slave ctl because master will program for both\n"); @@ -3703,6 +3718,30 @@ skip_intf_reconfig: ctl->mixer_right->width = ctl->width / 2; ctl->mixer_right->height = ctl->height; } + + /* + * If we are transitioning from DSC On + DSC Merge to DSC Off + * the 3D mux needs to be enabled + */ + if (!is_dsc_compression(&pdata->panel_info) && + ctl->mixer_left && + ctl->mixer_left->dsc_enabled && + ctl->mixer_left->dsc_merge_enabled) { + ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE | + MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT; + } + + /* + * If we are transitioning from DSC Off to DSC On + DSC Merge + * the 3D mux needs to be disabled + */ + if (is_dsc_compression(&pdata->panel_info) && + ctl->mixer_left && + !ctl->mixer_left->dsc_enabled && + pdata->panel_info.dsc_enc_total != 1) { + ctl->opmode &= ~(MDSS_MDP_CTL_OP_PACK_3D_ENABLE | + MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT); + } } else { /* * Handles MDP_SPLIT_MODE_NONE, MDP_DUAL_LM_DUAL_DISPLAY and @@ -3717,7 +3756,6 @@ skip_intf_reconfig: ctl->border_x_off = pdata->panel_info.lcdc.border_left; ctl->border_y_off = pdata->panel_info.lcdc.border_top; - return ret; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c index 4c4fa9ea98d0..711d2d222c7d 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_debug.c +++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c @@ -1868,7 +1868,7 @@ static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe) int smps[4]; int i; - seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%08x play_cnt=%u xin_id=%d\n", + seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%16llx play_cnt=%u xin_id=%d\n", pipe->num, mdss_mdp_pipetype2str(pipe->type), pipe->ndx, pipe->flags, pipe->play_cnt, pipe->xin_id); seq_printf(s, "\tstage=%d alpha=0x%x transp=0x%x blend_op=%d\n", diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index 4eb121f01aca..f08af5d6edd3 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -2029,8 +2029,22 @@ static void mdss_mdp_cmd_dsc_reconfig(struct mdss_mdp_ctl *ctl) return; pinfo = &ctl->panel_data->panel_info; - if (pinfo->compression_mode != COMPRESSION_DSC) - return; + if (pinfo->compression_mode != COMPRESSION_DSC) { + /* + * Check for a dynamic resolution switch from DSC On to + * DSC Off and call mdss_mdp_ctl_dsc_setup to disable DSC + */ + if (ctl->pending_mode_switch == SWITCH_RESOLUTION) { + if (ctl->mixer_left && ctl->mixer_left->dsc_enabled) + changed = true; + if (is_split_lm(ctl->mfd) && + ctl->mixer_right && + ctl->mixer_right->dsc_enabled) + changed = true; + } else { + return; + } + } changed = ctl->mixer_left->roi_changed; if (is_split_lm(ctl->mfd)) diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index 353d07ad64ac..036e4e39efda 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -522,6 +522,56 @@ static void __update_avr_info(struct mdss_mdp_ctl *ctl, } /* + * __validate_dual_partial_update() - validation function for + * dual partial update ROIs + * + * - This function uses the commit structs "left_roi" and "right_roi" + * to pass the first and second ROI information for the multiple + * partial update feature. + * - Supports only SINGLE DSI with a max of 2 PU ROIs. + * - Not supported along with destination scalar. + * - Not supported when source-split is disabled. + * - Not supported with ping-pong split enabled. + */ +static int __validate_dual_partial_update( + struct mdss_mdp_ctl *ctl, struct mdp_layer_commit_v1 *commit) +{ + struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info; + struct mdss_data_type *mdata = ctl->mdata; + struct mdss_rect first_roi, second_roi; + int ret = 0; + struct mdp_destination_scaler_data *ds_data = commit->dest_scaler; + + if (!mdata->has_src_split + || (is_panel_split(ctl->mfd)) + || (is_pingpong_split(ctl->mfd)) + || (ds_data && commit->dest_scaler_cnt && + ds_data->flags & MDP_DESTSCALER_ENABLE)) { + pr_err("Invalid mode multi pu src_split:%d, split_mode:%d, ds_cnt:%d\n", + mdata->has_src_split, ctl->mfd->split_mode, + commit->dest_scaler_cnt); + ret = -EINVAL; + goto end; + } + + rect_copy_mdp_to_mdss(&commit->left_roi, &first_roi); + rect_copy_mdp_to_mdss(&commit->right_roi, &second_roi); + + if (!is_valid_pu_dual_roi(pinfo, &first_roi, &second_roi)) + ret = -EINVAL; + + MDSS_XLOG(ctl->num, first_roi.x, first_roi.y, first_roi.w, first_roi.h, + second_roi.x, second_roi.y, second_roi.w, second_roi.h, + ret); + pr_debug("Multiple PU ROIs - roi0:{%d,%d,%d,%d}, roi1{%d,%d,%d,%d}, ret:%d\n", + first_roi.x, first_roi.y, first_roi.w, first_roi.h, + second_roi.x, second_roi.y, second_roi.w, + second_roi.h, ret); +end: + return ret; +} + +/* * __layer_needs_src_split() - check needs source split configuration * @layer: input layer * @@ -936,7 +986,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, { int ret = 0; u32 left_lm_w = left_lm_w_from_mfd(mfd); - u32 flags; + u64 flags; struct mdss_mdp_mixer *mixer = NULL; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); @@ -978,6 +1028,8 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, pipe->flags |= MDP_BWC_EN; if (layer->flags & MDP_LAYER_PP) pipe->flags |= MDP_OVERLAY_PP_CFG_EN; + if (layer->flags & MDP_LAYER_SECURE_CAMERA_SESSION) + pipe->flags |= MDP_SECURE_CAMERA_OVERLAY_SESSION; pipe->scaler.enable = (layer->flags & SCALER_ENABLED); pipe->is_fg = layer->flags & MDP_LAYER_FORGROUND; @@ -1000,6 +1052,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, pipe->is_handed_off = false; pipe->async_update = (layer->flags & MDP_LAYER_ASYNC) ? true : false; pipe->csc_coeff_set = layer->color_space; + pipe->restore_roi = false; if (mixer->ctl) { pipe->dst.x += mixer->ctl->border_x_off; @@ -1007,7 +1060,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, pr_debug("border{%d,%d}\n", mixer->ctl->border_x_off, mixer->ctl->border_y_off); } - pr_debug("src{%d,%d,%d,%d}, dst{%d,%d,%d,%d}\n", + pr_debug("pipe:%d src{%d,%d,%d,%d}, dst{%d,%d,%d,%d}\n", pipe->num, pipe->src.x, pipe->src.y, pipe->src.w, pipe->src.h, pipe->dst.x, pipe->dst.y, pipe->dst.w, pipe->dst.h); @@ -1348,7 +1401,7 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd, struct mdp_layer_buffer *buffer; struct msmfb_data image; int i, ret; - u32 flags; + u64 flags; struct mdss_mdp_validate_info_t *vitem; for (i = 0; i < layer_count; i++) { @@ -1374,7 +1427,8 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd, } flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | - MDP_SECURE_DISPLAY_OVERLAY_SESSION)); + MDP_SECURE_DISPLAY_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)); if (buffer->planes[0].fd < 0) { pr_err("invalid file descriptor for layer buffer\n"); @@ -1585,34 +1639,48 @@ end: } /* - * __validate_secure_display() - validate secure display + * __validate_secure_session() - validate various secure sessions * * This function travers through used pipe list and checks if any pipe - * is with secure display enabled flag. It fails if client tries to stage - * unsecure content with secure display session. + * is with secure display, secure video and secure camera enabled flag. + * It fails if client tries to stage unsecure content with + * secure display session and secure camera with secure video sessions. * */ -static int __validate_secure_display(struct mdss_overlay_private *mdp5_data) +static int __validate_secure_session(struct mdss_overlay_private *mdp5_data) { struct mdss_mdp_pipe *pipe, *tmp; uint32_t sd_pipes = 0, nonsd_pipes = 0; + uint32_t secure_vid_pipes = 0, secure_cam_pipes = 0; mutex_lock(&mdp5_data->list_lock); list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) { if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) sd_pipes++; + else if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) + secure_vid_pipes++; + else if (pipe->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) + secure_cam_pipes++; else nonsd_pipes++; } mutex_unlock(&mdp5_data->list_lock); - pr_debug("pipe count:: secure display:%d non-secure:%d\n", - sd_pipes, nonsd_pipes); + pr_debug("pipe count:: secure display:%d non-secure:%d secure-vid:%d,secure-cam:%d\n", + sd_pipes, nonsd_pipes, secure_vid_pipes, secure_cam_pipes); - if ((sd_pipes || mdss_get_sd_client_cnt()) && nonsd_pipes) { + if ((sd_pipes || mdss_get_sd_client_cnt()) && + (nonsd_pipes || secure_vid_pipes || + secure_cam_pipes)) { pr_err("non-secure layer validation request during secure display session\n"); - pr_err(" secure client cnt:%d secure pipe cnt:%d non-secure pipe cnt:%d\n", - mdss_get_sd_client_cnt(), sd_pipes, nonsd_pipes); + pr_err(" secure client cnt:%d secure pipe:%d non-secure pipe:%d, secure-vid:%d, secure-cam:%d\n", + mdss_get_sd_client_cnt(), sd_pipes, nonsd_pipes, + secure_vid_pipes, secure_cam_pipes); + return -EINVAL; + } else if (secure_cam_pipes && (secure_vid_pipes || sd_pipes)) { + pr_err(" incompatible layers during secure camera session\n"); + pr_err("secure-camera cnt:%d secure video:%d secure display:%d\n", + secure_cam_pipes, secure_vid_pipes, sd_pipes); return -EINVAL; } else { return 0; @@ -2388,7 +2456,7 @@ static int __validate_layers(struct msm_fb_data_type *mfd, validate_skip: __handle_free_list(mdp5_data, validate_info_list, layer_count); - ret = __validate_secure_display(mdp5_data); + ret = __validate_secure_session(mdp5_data); validate_exit: pr_debug("err=%d total_layer:%d left:%d right:%d rec0_rel_ndx=0x%x rec1_rel_ndx=0x%x rec0_destroy_ndx=0x%x rec1_destroy_ndx=0x%x processed=%d\n", @@ -2402,16 +2470,20 @@ validate_exit: mutex_lock(&mdp5_data->list_lock); list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) { if (IS_ERR_VALUE(ret)) { - if ((pipe->ndx & rec_release_ndx[0]) || - (pipe->ndx & rec_release_ndx[1])) { + if (((pipe->ndx & rec_release_ndx[0]) && + (pipe->multirect.num == 0)) || + ((pipe->ndx & rec_release_ndx[1]) && + (pipe->multirect.num == 1))) { mdss_mdp_smp_unreserve(pipe); pipe->params_changed = 0; pipe->dirty = true; if (!list_empty(&pipe->list)) list_del_init(&pipe->list); mdss_mdp_pipe_destroy(pipe); - } else if ((pipe->ndx & rec_destroy_ndx[0]) || - (pipe->ndx & rec_destroy_ndx[1])) { + } else if (((pipe->ndx & rec_destroy_ndx[0]) && + (pipe->multirect.num == 0)) || + ((pipe->ndx & rec_destroy_ndx[1]) && + (pipe->multirect.num == 1))) { /* * cleanup/destroy list pipes should move back * to destroy list. Next/current kickoff cycle @@ -2625,6 +2697,7 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd, { struct mdss_overlay_private *mdp5_data; struct mdp_destination_scaler_data *ds_data; + struct mdss_panel_info *pinfo; int rc = 0; if (!mfd || !commit) { @@ -2658,6 +2731,23 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd, } } + pinfo = mfd->panel_info; + if (pinfo->partial_update_enabled == PU_DUAL_ROI) { + if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) { + rc = __validate_dual_partial_update(mdp5_data->ctl, + commit); + if (IS_ERR_VALUE(rc)) { + pr_err("Multiple pu pre-validate fail\n"); + return rc; + } + } + } else { + if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) { + pr_err("Multiple partial update not supported!\n"); + return -EINVAL; + } + } + ds_data = commit->dest_scaler; if (ds_data && commit->dest_scaler_cnt && (ds_data->flags & MDP_DESTSCALER_ENABLE)) { diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 9bdc66232dd5..946e33033ab7 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -396,7 +396,7 @@ int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd, } int mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe, - u32 flags) + u64 flags) { struct mdss_data_type *mdata = pipe->mixer_left->ctl->mdata; struct mdss_mdp_perf_params perf; @@ -1188,11 +1188,10 @@ static void __overlay_pipe_cleanup(struct msm_fb_data_type *mfd, list_move(&buf->buf_list, &mdp5_data->bufs_freelist); /* - * in case of secure UI, the buffer needs to be released as - * soon as session is closed. + * free the buffers on the same cycle instead of waiting for + * next kickoff */ - if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) - mdss_mdp_overlay_buf_free(mfd, buf); + mdss_mdp_overlay_buf_free(mfd, buf); } mdss_mdp_pipe_destroy(pipe); @@ -1477,7 +1476,7 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd) */ if (mdss_get_sd_client_cnt() && !(pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)) { - pr_warn("Non secure pipe during secure display: %u: %08X, skip\n", + pr_warn("Non secure pipe during secure display: %u: %16llx, skip\n", pipe->num, pipe->flags); continue; } @@ -1861,12 +1860,109 @@ int mdss_mode_switch_post(struct msm_fb_data_type *mfd, u32 mode) return rc; } +static void __restore_pipe(struct mdss_mdp_pipe *pipe) +{ + + if (!pipe->restore_roi) + return; + + pr_debug("restoring pipe:%d dst from:{%d,%d,%d,%d} to:{%d,%d,%d,%d}\n", + pipe->num, pipe->dst.x, pipe->dst.y, + pipe->dst.w, pipe->dst.h, pipe->layer.dst_rect.x, + pipe->layer.dst_rect.y, pipe->layer.dst_rect.w, + pipe->layer.dst_rect.h); + pr_debug("restoring pipe:%d src from:{%d,%d,%d,%d} to:{%d,%d,%d,%d}\n", + pipe->num, pipe->src.x, pipe->src.y, + pipe->src.w, pipe->src.h, pipe->layer.src_rect.x, + pipe->layer.src_rect.y, pipe->layer.src_rect.w, + pipe->layer.src_rect.h); + + pipe->src.x = pipe->layer.src_rect.x; + pipe->src.y = pipe->layer.src_rect.y; + pipe->src.w = pipe->layer.src_rect.w; + pipe->src.h = pipe->layer.src_rect.h; + + pipe->dst.x = pipe->layer.dst_rect.x; + pipe->dst.y = pipe->layer.dst_rect.y; + pipe->dst.w = pipe->layer.dst_rect.w; + pipe->dst.h = pipe->layer.dst_rect.h; +} + + /** + * __crop_adjust_pipe_rect() - Adjust pipe roi for dual partial + * update feature. + * @pipe: pipe to check against. + * @dual_roi: roi's for the dual partial roi. + * + * For dual PU ROI case, the layer mixer is configured + * by merging the two width aligned ROIs (first_roi and + * second_roi) vertically. So, the y-offset of all the + * pipes belonging to the second_roi needs to adjusted + * accordingly. Also the cropping of the pipe's src/dst + * rect has to be done with respect to the ROI the pipe + * is intersecting with, before the adjustment. + */ +static int __crop_adjust_pipe_rect(struct mdss_mdp_pipe *pipe, + struct mdss_dsi_dual_pu_roi *dual_roi) +{ + u32 adjust_h; + u32 roi_y_pos; + int ret = 0; + + pipe->restore_roi = false; + if (mdss_rect_overlap_check(&pipe->dst, &dual_roi->first_roi)) { + mdss_mdp_crop_rect(&pipe->src, &pipe->dst, + &dual_roi->first_roi, false); + pipe->restore_roi = true; + + } else if (mdss_rect_overlap_check(&pipe->dst, &dual_roi->second_roi)) { + mdss_mdp_crop_rect(&pipe->src, &pipe->dst, + &dual_roi->second_roi, false); + adjust_h = dual_roi->second_roi.y; + roi_y_pos = dual_roi->first_roi.y + dual_roi->first_roi.h; + + if (adjust_h > roi_y_pos) { + adjust_h = adjust_h - roi_y_pos; + pipe->dst.y -= adjust_h; + } else { + pr_err("wrong y-pos adjust_y:%d roi_y_pos:%d\n", + adjust_h, roi_y_pos); + ret = -EINVAL; + } + pipe->restore_roi = true; + + } else { + ret = -EINVAL; + } + + pr_debug("crop/adjusted p:%d src:{%d,%d,%d,%d} dst:{%d,%d,%d,%d} r:%d\n", + pipe->num, pipe->src.x, pipe->src.y, + pipe->src.w, pipe->src.h, pipe->dst.x, + pipe->dst.y, pipe->dst.w, pipe->dst.h, + pipe->restore_roi); + + if (ret) { + pr_err("dual roi error p%d dst{%d,%d,%d,%d}", + pipe->num, pipe->dst.x, pipe->dst.y, pipe->dst.w, + pipe->dst.h); + pr_err(" roi1{%d,%d,%d,%d} roi2{%d,%d,%d,%d}\n", + dual_roi->first_roi.x, dual_roi->first_roi.y, + dual_roi->first_roi.w, dual_roi->first_roi.h, + dual_roi->second_roi.x, dual_roi->second_roi.y, + dual_roi->second_roi.w, dual_roi->second_roi.h); + } + + return ret; +} + static void __validate_and_set_roi(struct msm_fb_data_type *mfd, struct mdp_display_commit *commit) { struct mdss_mdp_pipe *pipe; struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); + struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info; + struct mdss_dsi_dual_pu_roi *dual_roi = &pinfo->dual_roi; struct mdss_rect l_roi = {0}, r_roi = {0}; struct mdp_rect tmp_roi = {0}; bool skip_partial_update = true; @@ -1881,6 +1977,39 @@ static void __validate_and_set_roi(struct msm_fb_data_type *mfd, rect_copy_mdp_to_mdss(&commit->l_roi, &l_roi); rect_copy_mdp_to_mdss(&commit->r_roi, &r_roi); + /* + * In case of dual partial update ROI, update the two ROIs to dual_roi + * struct and combine both the ROIs and assign it as a merged ROI in + * l_roi, as MDP would need only the merged ROI information for all + * LM settings. + */ + if (pinfo->partial_update_enabled == PU_DUAL_ROI) { + if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) { + + if (!is_valid_pu_dual_roi(pinfo, &l_roi, &r_roi)) { + pr_err("Invalid dual roi - fall back to full screen update\n"); + goto set_roi; + } + + dual_roi->first_roi = (struct mdss_rect) + {l_roi.x, l_roi.y, l_roi.w, l_roi.h}; + dual_roi->second_roi = (struct mdss_rect) + {r_roi.x, r_roi.y, r_roi.w, r_roi.h}; + dual_roi->enabled = true; + + l_roi.h += r_roi.h; + memset(&r_roi, 0, sizeof(struct mdss_rect)); + + pr_debug("Dual ROI - first_roi:{%d,%d,%d,%d}, second_roi:{%d,%d,%d,%d}\n", + dual_roi->first_roi.x, dual_roi->first_roi.y, + dual_roi->first_roi.w, dual_roi->first_roi.h, + dual_roi->second_roi.x, dual_roi->second_roi.y, + dual_roi->second_roi.w, dual_roi->second_roi.h); + } else { + dual_roi->enabled = false; + } + } + pr_debug("input: l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d\n", l_roi.x, l_roi.y, l_roi.w, l_roi.h, r_roi.x, r_roi.y, r_roi.w, r_roi.h); @@ -1926,12 +2055,24 @@ static void __validate_and_set_roi(struct msm_fb_data_type *mfd, } list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { + pr_debug("pipe:%d src:{%d,%d,%d,%d} dst:{%d,%d,%d,%d}\n", + pipe->num, pipe->src.x, pipe->src.y, + pipe->src.w, pipe->src.h, pipe->dst.x, + pipe->dst.y, pipe->dst.w, pipe->dst.h); + + if (dual_roi->enabled) { + if (__crop_adjust_pipe_rect(pipe, dual_roi)) { + skip_partial_update = true; + break; + } + } + if (!__is_roi_valid(pipe, &l_roi, &r_roi)) { skip_partial_update = true; - pr_err("error. invalid pu config for pipe%d: %d,%d,%d,%d\n", - pipe->num, - pipe->dst.x, pipe->dst.y, - pipe->dst.w, pipe->dst.h); + pr_err("error. invalid pu config for pipe%d: %d,%d,%d,%d, dual_pu_roi:%d\n", + pipe->num, pipe->dst.x, pipe->dst.y, + pipe->dst.w, pipe->dst.h, + dual_roi->enabled); break; } } @@ -1946,17 +2087,143 @@ set_roi: ctl->mixer_right->width, ctl->mixer_right->height}; } + + if (pinfo->partial_update_enabled == PU_DUAL_ROI) { + if (dual_roi->enabled) { + /* we failed pu validation, restore pipes */ + list_for_each_entry(pipe, + &mdp5_data->pipes_used, list) + __restore_pipe(pipe); + } + dual_roi->enabled = false; + } } - pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d\n", + pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d, dual_pu_roi:%d\n", (l_roi.w && l_roi.h && r_roi.w && r_roi.h) ? "left+right" : ((l_roi.w && l_roi.h) ? "left-only" : "right-only"), l_roi.x, l_roi.y, l_roi.w, l_roi.h, - r_roi.x, r_roi.y, r_roi.w, r_roi.h); + r_roi.x, r_roi.y, r_roi.w, r_roi.h, + dual_roi->enabled); mdss_mdp_set_roi(ctl, &l_roi, &r_roi); } +/* + * Enables/disable secure (display or camera) sessions + */ +static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd) +{ + struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); + struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); + struct mdss_mdp_pipe *pipe; + int ret = 0; + int sd_in_pipe = 0; + int sc_in_pipe = 0; + u64 pipes_flags = 0; + + list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { + pipes_flags |= pipe->flags; + if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + sd_in_pipe = 1; + pr_debug("Secure pipe: %u : %16llx\n", + pipe->num, pipe->flags); + } else if (pipe->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) { + sc_in_pipe = 1; + pr_debug("Secure camera: %u: %16llx\n", + pipe->num, pipe->flags); + } + } + + MDSS_XLOG(sd_in_pipe, sc_in_pipe, pipes_flags, + mdp5_data->sc_enabled, mdp5_data->sd_enabled); + pr_debug("sd:%d sd_in_pipe:%d sc:%d sc_in_pipe:%d flags:0x%llx\n", + mdp5_data->sd_enabled, sd_in_pipe, + mdp5_data->sc_enabled, sc_in_pipe, pipes_flags); + + /* + * Return early in only two conditions: + * 1. All the features are already disabled and state remains + * disabled for the pipes. + * 2. One of the features is already enabled and state remains + * enabled for the pipes. + */ + if (!sd_in_pipe && !mdp5_data->sd_enabled && + !sc_in_pipe && !mdp5_data->sc_enabled) + return ret; + else if ((sd_in_pipe && mdp5_data->sd_enabled) || + (sc_in_pipe && mdp5_data->sc_enabled)) + return ret; + + /* Secure Display */ + if (!mdp5_data->sd_enabled && sd_in_pipe) { + if (!mdss_get_sd_client_cnt()) { + MDSS_XLOG(0x11); + /*wait for ping pong done */ + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(1, + MDP_SECURE_DISPLAY_OVERLAY_SESSION); + if (ret) { + pr_err("secure display enable fail:%d", ret); + return ret; + } + } + mdp5_data->sd_enabled = 1; + mdss_update_sd_client(mdp5_data->mdata, true); + } else if (mdp5_data->sd_enabled && !sd_in_pipe) { + /* disable the secure display on last client */ + if (mdss_get_sd_client_cnt() == 1) { + MDSS_XLOG(0x22); + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(0, + MDP_SECURE_DISPLAY_OVERLAY_SESSION); + if (ret) { + pr_err("secure display disable fail:%d\n", ret); + return ret; + } + } + mdss_update_sd_client(mdp5_data->mdata, false); + mdp5_data->sd_enabled = 0; + } + + /* Secure Camera */ + if (!mdp5_data->sc_enabled && sc_in_pipe) { + if (!mdss_get_sc_client_cnt()) { + MDSS_XLOG(0x33); + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(1, + MDP_SECURE_CAMERA_OVERLAY_SESSION); + if (ret) { + pr_err("secure camera enable fail:%d\n", ret); + return ret; + } + } + mdp5_data->sc_enabled = 1; + mdss_update_sc_client(mdp5_data->mdata, true); + } else if (mdp5_data->sc_enabled && !sc_in_pipe) { + /* disable the secure camera on last client */ + if (mdss_get_sc_client_cnt() == 1) { + MDSS_XLOG(0x44); + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(0, + MDP_SECURE_CAMERA_OVERLAY_SESSION); + if (ret) { + pr_err("secure camera disable fail:%d\n", ret); + return ret; + } + } + mdss_update_sc_client(mdp5_data->mdata, false); + mdp5_data->sc_enabled = 0; + } + + MDSS_XLOG(ret); + return ret; +} + int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, struct mdp_display_commit *data) { @@ -1964,7 +2231,6 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, struct mdss_mdp_pipe *pipe, *tmp; struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; - int sd_in_pipe = 0; struct mdss_mdp_commit_cb commit_cb; if (!ctl) @@ -1995,30 +2261,12 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, mutex_unlock(ctl->shared_lock); return ret; } - mutex_lock(&mdp5_data->list_lock); - - /* - * check if there is a secure display session - */ - list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { - if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { - sd_in_pipe = 1; - pr_debug("Secure pipe: %u : %08X\n", - pipe->num, pipe->flags); - } - } - /* - * start secure display session if there is secure display session and - * sd_enabled is not true. - */ - if (!mdp5_data->sd_enabled && sd_in_pipe) { - if (!mdss_get_sd_client_cnt()) - ret = mdss_mdp_secure_display_ctrl(1); - if (!ret) { - mdp5_data->sd_enabled = 1; - mdss_update_sd_client(mdp5_data->mdata, true); - } + mutex_lock(&mdp5_data->list_lock); + ret = __overlay_secure_ctrl(mfd); + if (IS_ERR_VALUE(ret)) { + pr_err("secure operation failed %d\n", ret); + goto commit_fail; } if (!ctl->shared_lock) @@ -2108,19 +2356,6 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, } mutex_lock(&mdp5_data->ov_lock); - /* - * If there is no secure display session and sd_enabled, disable the - * secure display session - */ - if (mdp5_data->sd_enabled && !sd_in_pipe && !ret) { - /* disable the secure display on last client */ - if (mdss_get_sd_client_cnt() == 1) - ret = mdss_mdp_secure_display_ctrl(0); - if (!ret) { - mdss_update_sd_client(mdp5_data->mdata, false); - mdp5_data->sd_enabled = 0; - } - } mdss_fb_update_notify_update(mfd); commit_fail: @@ -2272,7 +2507,7 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd, struct mdss_mdp_data *src_data; struct mdp_layer_buffer buffer; int ret; - u32 flags; + u64 flags; pipe = __overlay_find_pipe(mfd, req->id); if (!pipe) { @@ -2298,7 +2533,8 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd, pr_warn("Unexpected buffer queue to a solid fill pipe\n"); flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | - MDP_SECURE_DISPLAY_OVERLAY_SESSION)); + MDP_SECURE_DISPLAY_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)); mutex_lock(&mdp5_data->list_lock); src_data = mdss_mdp_overlay_buf_alloc(mfd, pipe); @@ -5223,6 +5459,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) mdss_mdp_overlay_kickoff(mfd, NULL); } +ctl_stop: /* * If retire fences are still active wait for a vsync time * for retire fence to be updated. @@ -5253,7 +5490,6 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) flush_work(&mdp5_data->retire_work); } -ctl_stop: mutex_lock(&mdp5_data->ov_lock); /* set the correct pipe_mapped before ctl_stop */ mdss_mdp_mixer_update_pipe_map(mdp5_data->ctl, diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c index 8f211a977aa4..bcf5309993b9 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c @@ -1340,10 +1340,11 @@ static struct mdss_mdp_pipe *__pipe_lookup(struct mdss_mdp_pipe *pipe_list, bool (*cmp)(struct mdss_mdp_pipe *, void *), void *data) { struct mdss_mdp_pipe *pipe; - int i, j; + int i, j, max_rects; for (i = 0, pipe = pipe_list; i < count; i++) { - for (j = 0; j < pipe->multirect.max_rects; j++, pipe++) + max_rects = pipe->multirect.max_rects; + for (j = 0; j < max_rects; j++, pipe++) if ((rect_num == pipe->multirect.num) && cmp(pipe, data)) return pipe; @@ -1878,7 +1879,8 @@ static void mdss_mdp_pipe_stride_update(struct mdss_mdp_pipe *pipe) if (pipe->multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE) { memcpy(&ystride, &pipe->src_planes.ystride, sizeof(u32) * MAX_PLANES); - if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure = 0xF; } else { if (pipe->multirect.num == MDSS_MDP_PIPE_RECT0) { @@ -1891,12 +1893,14 @@ static void mdss_mdp_pipe_stride_update(struct mdss_mdp_pipe *pipe) ystride[0] = rec0_pipe->src_planes.ystride[0]; ystride[2] = rec0_pipe->src_planes.ystride[2]; - if (rec0_pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (rec0_pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure |= 0x5; ystride[1] = rec1_pipe->src_planes.ystride[0]; ystride[3] = rec1_pipe->src_planes.ystride[2]; - if (rec1_pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (rec1_pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure |= 0xA; } @@ -1998,7 +2002,7 @@ static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe, dst.x -= left_lm_w_from_mfd(pipe->mfd); } - mdss_mdp_crop_rect(&src, &dst, &roi); + mdss_mdp_crop_rect(&src, &dst, &roi, true); if (mdata->has_src_split && is_right_mixer) { /* @@ -2320,11 +2324,13 @@ static int mdss_mdp_pipe_solidfill_setup(struct mdss_mdp_pipe *pipe) } format = MDSS_MDP_FMT_SOLID_FILL; - secure = (pipe->flags & MDP_SECURE_OVERLAY_SESSION ? 0xF : 0x0); + secure = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION) + ? 0xF : 0x0); /* support ARGB color format only */ unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) | - (C1_B_Cb << 8) | (C0_G_Y << 0); + (C0_G_Y << 8) | (C1_B_Cb << 0); if (pipe->scaler.enable) opmode |= (1 << 31); diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c index 8b0ebc3fdf05..199c2b66d90e 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_util.c +++ b/drivers/video/fbdev/msm/mdss_mdp_util.c @@ -241,7 +241,7 @@ void mdss_mdp_intersect_rect(struct mdss_rect *res_rect, void mdss_mdp_crop_rect(struct mdss_rect *src_rect, struct mdss_rect *dst_rect, - const struct mdss_rect *sci_rect) + const struct mdss_rect *sci_rect, bool normalize) { struct mdss_rect res; mdss_mdp_intersect_rect(&res, dst_rect, sci_rect); @@ -253,9 +253,17 @@ void mdss_mdp_crop_rect(struct mdss_rect *src_rect, src_rect->w = res.w; src_rect->h = res.h; } - *dst_rect = (struct mdss_rect) - {(res.x - sci_rect->x), (res.y - sci_rect->y), - res.w, res.h}; + + /* adjust dest rect based on the sci_rect starting */ + if (normalize) { + *dst_rect = (struct mdss_rect) {(res.x - sci_rect->x), + (res.y - sci_rect->y), res.w, res.h}; + + /* return the actual cropped intersecting rect */ + } else { + *dst_rect = (struct mdss_rect) {res.x, res.y, + res.w, res.h}; + } } } @@ -963,16 +971,17 @@ static int mdss_mdp_put_img(struct mdss_mdp_img_data *data, bool rotator, data->srcp_dma_buf = NULL; } } - } else if (data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + } else if ((data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) || + (data->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION)) { /* - * skip memory unmapping - secure display uses physical - * address which does not require buffer unmapping + * skip memory unmapping - secure display and camera uses + * physical address which does not require buffer unmapping * * For LT targets in secure display usecase, srcp_dma_buf will * be filled due to map call which will be unmapped above. * */ - pr_debug("skip memory unmapping for secure display content\n"); + pr_debug("skip memory unmapping for secure display/camera content\n"); } else { return -ENOMEM; } @@ -1188,7 +1197,7 @@ err_unmap: } static int mdss_mdp_data_get(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir) { int i, rc = 0; @@ -1201,7 +1210,7 @@ static int mdss_mdp_data_get(struct mdss_mdp_data *data, rc = mdss_mdp_get_img(&planes[i], &data->p[i], dev, rotator, dir); if (rc) { - pr_err("failed to get buf p=%d flags=%x\n", i, flags); + pr_err("failed to get buf p=%d flags=%llx\n", i, flags); while (i > 0) { i--; mdss_mdp_put_img(&data->p[i], rotator, dir); @@ -1251,7 +1260,7 @@ void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir) } int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir, struct mdp_layer_buffer *buffer) { diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 18a93f9d3c3e..0483e3d42873 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -137,6 +137,25 @@ enum { SIM_HW_TE_MODE, }; + +/* + * enum partial_update_mode - Different modes for partial update feature + * + * @PU_NOT_SUPPORTED: Feature is not supported on target. + * @PU_SINGLE_ROI: Default mode, only one ROI is triggered to the + * panel(one on each DSI in case of split dsi) + * @PU_DUAL_ROI: Support for sending two roi's that are clubbed + * together as one big single ROI. This is only + * supported on certain panels that have this + * capability in their DDIC. + * + */ +enum { + PU_NOT_SUPPORTED = 0, + PU_SINGLE_ROI, + PU_DUAL_ROI, +}; + struct mdss_rect { u16 x; u16 y; @@ -664,6 +683,50 @@ struct mdss_panel_roi_alignment { u32 min_height; }; + +/* + * Nomeclature used to represent partial ROI in case of + * dual roi when the panel supports it. Region marked (XXX) is + * the extended roi to align with the second roi since LM output + * has to be rectangle. + * + * For single ROI, only the first ROI will be used in the struct. + * DSI driver will merge it based on the partial_update_roi_merge + * property. + * + * ------------------------------- + * | DSI0 | DSI1 | + * ------------------------------- + * | | | + * | | | + * | =========|=======----+ | + * | | | |XXXX| | + * | | First| Roi |XXXX| | + * | | | |XXXX| | + * | =========|=======----+ | + * | | | + * | | | + * | | | + * | +----================= | + * | |XXXX| | | | + * | |XXXX| Second Roi | | + * | |XXXX| | | | + * | +----====|============ | + * | | | + * | | | + * | | | + * | | | + * | | | + * ------------------------------ + * + */ + +struct mdss_dsi_dual_pu_roi { + struct mdss_rect first_roi; + struct mdss_rect second_roi; + bool enabled; +}; + struct mdss_panel_info { u32 xres; u32 yres; @@ -689,6 +752,7 @@ struct mdss_panel_info { u32 vic; /* video identification code */ u32 deep_color; struct mdss_rect roi; + struct mdss_dsi_dual_pu_roi dual_roi; int pwm_pmic_gpio; int pwm_lpg_chan; int pwm_period; @@ -723,8 +787,8 @@ struct mdss_panel_info { u32 cont_splash_enabled; bool esd_rdy; - bool partial_update_supported; /* value from dts if pu is supported */ - bool partial_update_enabled; /* is pu currently allowed */ + u32 partial_update_supported; /* value from dts if pu is supported */ + u32 partial_update_enabled; /* is pu currently allowed */ u32 dcs_cmd_by_left; u32 partial_update_roi_merge; struct ion_handle *splash_ihdl; @@ -1000,6 +1064,27 @@ static inline bool is_lm_configs_dsc_compatible(struct mdss_panel_info *pinfo, return true; } +static inline bool is_valid_pu_dual_roi(struct mdss_panel_info *pinfo, + struct mdss_rect *first_roi, struct mdss_rect *second_roi) +{ + if ((first_roi->x != second_roi->x) || (first_roi->w != second_roi->w) + || (first_roi->y > second_roi->y) + || ((first_roi->y + first_roi->h) > second_roi->y) + || (is_dsc_compression(pinfo) && + !is_lm_configs_dsc_compatible(pinfo, + first_roi->w, first_roi->h) && + !is_lm_configs_dsc_compatible(pinfo, + second_roi->w, second_roi->h))) { + pr_err("Invalid multiple PU ROIs, roi0:{%d,%d,%d,%d}, roi1{%d,%d,%d,%d}\n", + first_roi->x, first_roi->y, first_roi->w, + first_roi->h, second_roi->x, second_roi->y, + second_roi->w, second_roi->h); + return false; + } + + return true; +} + int mdss_register_panel(struct platform_device *pdev, struct mdss_panel_data *pdata); diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c index eab7bcaaa156..2239791fdad0 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.c +++ b/drivers/video/fbdev/msm/mdss_smmu.c @@ -162,12 +162,15 @@ end: } /* - * mdss_smmu_v2_attach() + * mdss_smmu_attach_v2() * * Associates each configured VA range with the corresponding smmu context * bank device. Enables the clks as smmu_v2 requires voting it before the usage. * And iommu attach is done only once during the initial attach and it is never * detached as smmu v2 uses a feature called 'retention'. + * Only detach the secure and non-secure contexts in case of secure display + * case and secure contexts for secure camera use cases for the platforms + * which have caps MDSS_CAPS_SEC_DETACH_SMMU enabled */ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata) { @@ -191,7 +194,9 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata) } mdss_smmu->handoff_pending = false; - if (!mdss_smmu->domain_attached) { + if (!mdss_smmu->domain_attached && + mdss_smmu_is_valid_domain_condition(mdata, + i, true)) { rc = arm_iommu_attach_device(mdss_smmu->dev, mdss_smmu->mmu_mapping); if (rc) { @@ -229,10 +234,11 @@ err: } /* - * mdss_smmu_v2_detach() + * mdss_smmu_detach_v2() * - * Only disables the clks as it is not required to detach the iommu mapped - * VA range from the device in smmu_v2 as explained in the mdss_smmu_v2_attach + * Disables the clks only when it is not required to detach the iommu mapped + * VA range (as long as not in secure display use case) + * from the device in smmu_v2 as explained in the mdss_smmu_v2_attach */ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata) { @@ -245,8 +251,24 @@ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata) continue; mdss_smmu = mdss_smmu_get_cb(i); - if (mdss_smmu && mdss_smmu->dev && !mdss_smmu->handoff_pending) - mdss_smmu_enable_power(mdss_smmu, false); + if (mdss_smmu && mdss_smmu->dev) { + if (!mdss_smmu->handoff_pending && + mdss_smmu->domain_attached && + mdss_smmu_is_valid_domain_condition(mdata, + i, false)) { + /* + * if entering in secure display or + * secure camera use case(for secured contexts + * leave the smmu clocks on and only detach the + * smmu contexts + */ + arm_iommu_detach_device(mdss_smmu->dev); + mdss_smmu->domain_attached = false; + pr_debug("iommu v2 domain[%i] detached\n", i); + } else { + mdss_smmu_enable_power(mdss_smmu, false); + } + } } mutex_unlock(&mdp_iommu_lock); @@ -609,6 +631,7 @@ int mdss_smmu_probe(struct platform_device *pdev) } mdss_smmu = &mdata->mdss_smmu[smmu_domain.domain]; + mdss_smmu->domain = smmu_domain.domain; mp = &mdss_smmu->mp; memset(mp, 0, sizeof(struct dss_module_power)); diff --git a/drivers/video/fbdev/msm/mdss_smmu.h b/drivers/video/fbdev/msm/mdss_smmu.h index a987066cc773..f7e6e275c16a 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.h +++ b/drivers/video/fbdev/msm/mdss_smmu.h @@ -73,6 +73,38 @@ static inline bool mdss_smmu_is_valid_domain_type(struct mdss_data_type *mdata, return true; } +static inline bool mdss_smmu_is_valid_domain_condition( + struct mdss_data_type *mdata, + int domain_type, + bool is_attach) +{ + if (is_attach) { + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map) && + (mdata->sec_disp_en || + (mdata->sec_cam_en && + domain_type == MDSS_IOMMU_DOMAIN_SECURE))) { + pr_debug("SMMU attach not attempted, sd:%d, sc:%d\n", + mdata->sec_disp_en, mdata->sec_cam_en); + return false; + } else { + return true; + } + } else { + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map) && + (mdata->sec_disp_en || + (mdata->sec_cam_en && + domain_type == MDSS_IOMMU_DOMAIN_SECURE))) { + pr_debug("SMMU detach attempted, sd:%d, sc:%d\n", + mdata->sec_disp_en, mdata->sec_cam_en); + return true; + } else { + return false; + } + } +} + static inline struct mdss_smmu_client *mdss_smmu_get_cb(u32 domain) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); @@ -96,7 +128,7 @@ static inline int is_mdss_iommu_attached(void) return mdata ? mdata->iommu_attached : false; } -static inline int mdss_smmu_get_domain_type(u32 flags, bool rotator) +static inline int mdss_smmu_get_domain_type(u64 flags, bool rotator) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); int type; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index c34a68ce901a..d33e10784b23 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -133,6 +133,7 @@ enum iommu_attr { DOMAIN_ATTR_S1_BYPASS, DOMAIN_ATTR_FAST, DOMAIN_ATTR_PGTBL_INFO, + DOMAIN_ATTR_EARLY_MAP, DOMAIN_ATTR_MAX, }; diff --git a/include/linux/nfcinfo.h b/include/linux/nfcinfo.h new file mode 100644 index 000000000000..595544f92a37 --- /dev/null +++ b/include/linux/nfcinfo.h @@ -0,0 +1,6 @@ +#ifndef _NFCINFO_H +#define _NFCINFO_H + +#include <uapi/linux/nfc/nfcinfo.h> + +#endif diff --git a/include/linux/qdsp6v2/apr_tal.h b/include/linux/qdsp6v2/apr_tal.h index ee8b2f5a8b5b..c2c49dd748de 100644 --- a/include/linux/qdsp6v2/apr_tal.h +++ b/include/linux/qdsp6v2/apr_tal.h @@ -32,7 +32,7 @@ #if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \ defined(CONFIG_MSM_QDSP6_APRV3_GLINK) #define APR_MAX_BUF 512 -#define APR_NUM_OF_TX_BUF 20 +#define APR_NUM_OF_TX_BUF 30 #else #define APR_MAX_BUF 8092 #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index f8aa9992a694..4f6711f31939 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -446,6 +446,7 @@ extern unsigned int hardlockup_panic; void lockup_detector_init(void); extern void watchdog_enable(unsigned int cpu); extern void watchdog_disable(unsigned int cpu); +extern bool watchdog_configured(unsigned int cpu); #else static inline void touch_softlockup_watchdog_sched(void) { @@ -468,6 +469,14 @@ static inline void watchdog_enable(unsigned int cpu) static inline void watchdog_disable(unsigned int cpu) { } +static inline bool watchdog_configured(unsigned int cpu) +{ + /* + * Predend the watchdog is always configured. + * We will be waiting for the watchdog to be enabled in core isolation + */ + return true; +} #endif #ifdef CONFIG_DETECT_HUNG_TASK diff --git a/include/linux/spmi.h b/include/linux/spmi.h index 1396a255d2a2..319c52a298ef 100644 --- a/include/linux/spmi.h +++ b/include/linux/spmi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -171,6 +171,19 @@ static inline void spmi_driver_unregister(struct spmi_driver *sdrv) module_driver(__spmi_driver, spmi_driver_register, \ spmi_driver_unregister) +#ifdef CONFIG_QCOM_SHOW_RESUME_IRQ +extern int msm_show_resume_irq_mask; +static inline bool spmi_show_resume_irq(void) +{ + return msm_show_resume_irq_mask; +} +#else +static inline bool spmi_show_resume_irq(void) +{ + return false; +} +#endif + int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf); int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf, size_t len); diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h index b0a8d67f50fa..e33fd9fc1841 100644 --- a/include/soc/qcom/qseecomi.h +++ b/include/soc/qcom/qseecomi.h @@ -68,6 +68,7 @@ enum qseecom_qceos_cmd_id { QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST = 0x1C, QSEOS_TEE_OPEN_SESSION_WHITELIST = 0x1D, QSEOS_TEE_INVOKE_COMMAND_WHITELIST = 0x1E, + QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST = 0x1F, QSEOS_FSM_LTEOTA_REQ_CMD = 0x109, QSEOS_FSM_LTEOTA_REQ_RSP_CMD = 0x110, QSEOS_FSM_IKE_REQ_CMD = 0x203, @@ -217,6 +218,16 @@ __packed struct qseecom_client_listener_data_irsp { uint32_t qsee_cmd_id; uint32_t listener_id; uint32_t status; + uint32_t sglistinfo_ptr; + uint32_t sglistinfo_len; +}; + +__packed struct qseecom_client_listener_data_64bit_irsp { + uint32_t qsee_cmd_id; + uint32_t listener_id; + uint32_t status; + uint64_t sglistinfo_ptr; + uint32_t sglistinfo_len; }; /* @@ -703,4 +714,12 @@ __packed struct qseecom_continue_blocked_request_ireq { TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ TZ_SYSCALL_PARAM_TYPE_VAL) +#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x05) + +#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_4( \ + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \ + TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL) + #endif /* __QSEECOMI_H_ */ diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 06b72b262395..e713641cc3ec 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -914,6 +914,34 @@ struct adm_cmd_connect_afe_port_v5 { #define AFE_PORT_ID_SENARY_MI2S_RX 0x1018 /* ID of the senary MI2S Tx port. */ #define AFE_PORT_ID_SENARY_MI2S_TX 0x1019 +/* ID of the Internal 0 MI2S Rx port */ +#define AFE_PORT_ID_INT0_MI2S_RX 0x102E +/* ID of the Internal 0 MI2S Tx port */ +#define AFE_PORT_ID_INT0_MI2S_TX 0x102F +/* ID of the Internal 1 MI2S Rx port */ +#define AFE_PORT_ID_INT1_MI2S_RX 0x1030 +/* ID of the Internal 1 MI2S Tx port */ +#define AFE_PORT_ID_INT1_MI2S_TX 0x1031 +/* ID of the Internal 2 MI2S Rx port */ +#define AFE_PORT_ID_INT2_MI2S_RX 0x1032 +/* ID of the Internal 2 MI2S Tx port */ +#define AFE_PORT_ID_INT2_MI2S_TX 0x1033 +/* ID of the Internal 3 MI2S Rx port */ +#define AFE_PORT_ID_INT3_MI2S_RX 0x1034 +/* ID of the Internal 3 MI2S Tx port */ +#define AFE_PORT_ID_INT3_MI2S_TX 0x1035 +/* ID of the Internal 4 MI2S Rx port */ +#define AFE_PORT_ID_INT4_MI2S_RX 0x1036 +/* ID of the Internal 4 MI2S Tx port */ +#define AFE_PORT_ID_INT4_MI2S_TX 0x1037 +/* ID of the Internal 5 MI2S Rx port */ +#define AFE_PORT_ID_INT5_MI2S_RX 0x1038 +/* ID of the Internal 5 MI2S Tx port */ +#define AFE_PORT_ID_INT5_MI2S_TX 0x1039 +/* ID of the Internal 6 MI2S Rx port */ +#define AFE_PORT_ID_INT6_MI2S_RX 0x103A +/* ID of the Internal 6 MI2S Tx port */ +#define AFE_PORT_ID_INT6_MI2S_TX 0x103B #define AFE_PORT_ID_SPDIF_RX 0x5000 #define AFE_PORT_ID_RT_PROXY_PORT_001_RX 0x2000 #define AFE_PORT_ID_RT_PROXY_PORT_001_TX 0x2001 @@ -8858,6 +8886,20 @@ enum afe_lpass_clk_mode { #define Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT 0x10D /* Clock ID for SENARY I2S EBIT */ #define Q6AFE_LPASS_CLK_ID_SEN_MI2S_EBIT 0x10E +/* Clock ID for INT0 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT0_MI2S_IBIT 0x10F +/* Clock ID for INT1 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT1_MI2S_IBIT 0x110 +/* Clock ID for INT2 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT2_MI2S_IBIT 0x111 +/* Clock ID for INT3 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT3_MI2S_IBIT 0x112 +/* Clock ID for INT4 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT4_MI2S_IBIT 0x113 +/* Clock ID for INT5 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT5_MI2S_IBIT 0x114 +/* Clock ID for INT6 I2S IBIT */ +#define Q6AFE_LPASS_CLK_ID_INT6_MI2S_IBIT 0x115 /* Clock ID for Primary PCM IBIT */ #define Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT 0x200 @@ -8899,8 +8941,19 @@ enum afe_lpass_clk_mode { #define Q6AFE_LPASS_CLK_ID_MCLK_2 0x301 /* Clock ID for MCLK3 */ #define Q6AFE_LPASS_CLK_ID_MCLK_3 0x302 +/* Clock ID for MCLK4 */ +#define Q6AFE_LPASS_CLK_ID_MCLK_4 0x304 /* Clock ID for Internal Digital Codec Core */ #define Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE 0x303 +/* Clock ID for INT MCLK0 */ +#define Q6AFE_LPASS_CLK_ID_INT_MCLK_0 0x305 +/* Clock ID for INT MCLK1 */ +#define Q6AFE_LPASS_CLK_ID_INT_MCLK_1 0x306 +/* + * Clock ID for soundwire NPL. + * This is the clock to be used to enable NPL clock for internal Soundwire. + */ +#define AFE_CLOCK_SET_CLOCK_ID_SWR_NPL_CLK 0x307 /* Clock ID for AHB HDMI input */ #define Q6AFE_LPASS_CLK_ID_AHB_HDMI_INPUT 0x400 diff --git a/include/sound/msm-dai-q6-v2.h b/include/sound/msm-dai-q6-v2.h index c3c65a02a817..b1d76bf73f51 100644 --- a/include/sound/msm-dai-q6-v2.h +++ b/include/sound/msm-dai-q6-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,8 +28,15 @@ #define MSM_SEC_MI2S_SD1 4 #define MSM_QUIN_MI2S 5 #define MSM_SENARY_MI2S 6 +#define MSM_INT0_MI2S 7 +#define MSM_INT1_MI2S 8 +#define MSM_INT2_MI2S 9 +#define MSM_INT3_MI2S 10 +#define MSM_INT4_MI2S 11 +#define MSM_INT5_MI2S 12 +#define MSM_INT6_MI2S 13 #define MSM_MI2S_MIN MSM_PRIM_MI2S -#define MSM_MI2S_MAX MSM_SENARY_MI2S +#define MSM_MI2S_MAX MSM_INT6_MI2S struct msm_dai_auxpcm_config { u16 mode; diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h index 31f7c02b54b3..e0da428fa52f 100644 --- a/include/sound/q6afe-v2.h +++ b/include/sound/q6afe-v2.h @@ -183,10 +183,26 @@ enum { IDX_AFE_PORT_ID_USB_TX, /* IDX 124 */ IDX_DISPLAY_PORT_RX, + /* IDX 125-> 128 */ IDX_AFE_PORT_ID_TERTIARY_PCM_RX, IDX_AFE_PORT_ID_TERTIARY_PCM_TX, IDX_AFE_PORT_ID_QUATERNARY_PCM_RX, IDX_AFE_PORT_ID_QUATERNARY_PCM_TX, + /* IDX 129-> 142 */ + IDX_AFE_PORT_ID_INT0_MI2S_RX, + IDX_AFE_PORT_ID_INT0_MI2S_TX, + IDX_AFE_PORT_ID_INT1_MI2S_RX, + IDX_AFE_PORT_ID_INT1_MI2S_TX, + IDX_AFE_PORT_ID_INT2_MI2S_RX, + IDX_AFE_PORT_ID_INT2_MI2S_TX, + IDX_AFE_PORT_ID_INT3_MI2S_RX, + IDX_AFE_PORT_ID_INT3_MI2S_TX, + IDX_AFE_PORT_ID_INT4_MI2S_RX, + IDX_AFE_PORT_ID_INT4_MI2S_TX, + IDX_AFE_PORT_ID_INT5_MI2S_RX, + IDX_AFE_PORT_ID_INT5_MI2S_TX, + IDX_AFE_PORT_ID_INT6_MI2S_RX, + IDX_AFE_PORT_ID_INT6_MI2S_TX, AFE_MAX_PORTS }; diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index d6ff882ad6a7..14bd1e806ad7 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -23,6 +23,7 @@ header-y += netfilter_ipv6/ header-y += usb/ header-y += wimax/ header-y += mfd/ +header-y += nfc/ genhdr-y += version.h diff --git a/include/uapi/linux/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h index 811d8b4e1994..1a71e860ba48 100644 --- a/include/uapi/linux/msm_mdp_ext.h +++ b/include/uapi/linux/msm_mdp_ext.h @@ -96,6 +96,10 @@ LAYER FLAG CONFIGURATION */ #define MDP_LAYER_MULTIRECT_PARALLEL_MODE 0x2000 + +/* Flag indicates that layer is associated with secure camera session */ +#define MDP_LAYER_SECURE_CAMERA_SESSION 0x4000 + /********************************************************************** DESTINATION SCALER FLAG CONFIGURATION **********************************************************************/ @@ -147,6 +151,9 @@ VALIDATE/COMMIT FLAG CONFIGURATION */ #define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10 +/* Flag to indicate dual partial ROI update */ +#define MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI 0x20 + /* Flag to enable concurrent writeback for the frame */ #define MDP_COMMIT_CWB_EN 0x800 diff --git a/include/uapi/linux/nfc/Kbuild b/include/uapi/linux/nfc/Kbuild new file mode 100644 index 000000000000..90710153e462 --- /dev/null +++ b/include/uapi/linux/nfc/Kbuild @@ -0,0 +1,2 @@ +#UAPI export list +header-y += nfcinfo.h diff --git a/include/uapi/linux/nfc/nfcinfo.h b/include/uapi/linux/nfc/nfcinfo.h new file mode 100644 index 000000000000..df178e2bbae6 --- /dev/null +++ b/include/uapi/linux/nfc/nfcinfo.h @@ -0,0 +1,21 @@ +#ifndef _UAPI_NFCINFO_H_ +#define _UAPI_NFCINFO_H_ + +#include <linux/ioctl.h> + +#define NFCC_MAGIC 0xE9 +#define NFCC_GET_INFO _IOW(NFCC_MAGIC, 0x09, unsigned int) + +struct nqx_devinfo { + unsigned char chip_type; + unsigned char rom_version; + unsigned char fw_major; + unsigned char fw_minor; +}; + +union nqx_uinfo { + unsigned int i; + struct nqx_devinfo info; +}; + +#endif diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 643c68f4c449..8fdf57504ab6 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1199,6 +1199,15 @@ enum v4l2_cid_mpeg_vidc_video_full_range { #define V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS \ (V4L2_CID_MPEG_MSM_VIDC_BASE + 97) +#define V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE \ + (V4L2_CID_MPEG_MSM_VIDC_BASE + 98) +enum v4l2_mpeg_vidc_video_venc_iframesize_type { + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED, +}; + /* Camera class control IDs */ #define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) diff --git a/include/uapi/media/msm_sde_rotator.h b/include/uapi/media/msm_sde_rotator.h index 4487edf0c854..12976e3f14d7 100644 --- a/include/uapi/media/msm_sde_rotator.h +++ b/include/uapi/media/msm_sde_rotator.h @@ -86,4 +86,10 @@ struct msm_sde_rotator_fence { /* SDE Rotator private control ID's */ #define V4L2_CID_SDE_ROTATOR_SECURE (V4L2_CID_USER_BASE + 0x1000) +/* + * This control Id indicates this context is associated with the + * secure camera + */ +#define V4L2_CID_SDE_ROTATOR_SECURE_CAMERA (V4L2_CID_USER_BASE + 0x2000) + #endif /* __UAPI_MSM_SDE_ROTATOR_H__ */ diff --git a/include/uapi/media/msmb_ispif.h b/include/uapi/media/msmb_ispif.h index 7f4deaf12683..3720056aa28d 100644 --- a/include/uapi/media/msmb_ispif.h +++ b/include/uapi/media/msmb_ispif.h @@ -28,6 +28,7 @@ enum msm_ispif_intftype { }; #define MAX_PARAM_ENTRIES (INTF_MAX * 2) #define MAX_CID_CH 8 +#define MAX_CID_CH_PARAM_ENTRY 3 #define PIX0_MASK (1 << PIX0) #define PIX1_MASK (1 << PIX1) @@ -94,7 +95,7 @@ struct msm_ispif_params_entry { enum msm_ispif_vfe_intf vfe_intf; enum msm_ispif_intftype intftype; int num_cids; - enum msm_ispif_cid cids[3]; + enum msm_ispif_cid cids[MAX_CID_CH_PARAM_ENTRY]; enum msm_ispif_csid csid; int crop_enable; uint16_t crop_start_pixel; diff --git a/kernel/Documentation/firmware_updater/request_firmware.txt b/kernel/Documentation/firmware_updater/request_firmware.txt deleted file mode 100644 index 317f04ac5684..000000000000 --- a/kernel/Documentation/firmware_updater/request_firmware.txt +++ /dev/null @@ -1,22 +0,0 @@ -Firmware Update Function -======================== - -Call export function "synaptics_fw_updater" in rmi_fw_update.c to start -firmware updating process in the driver. - -The RMI4 driver uses the kernel's request_firmware() feature to obtain -firmware for the touch sensor. The firmware is expected to live in -the file firmware/<firmware_name>.img.ihex. - -To prepare Synaptics provided .img file for reflashing, convert it to .ihex -format using the following command: - - objcopy -I binary -O ihex <firmware_name>.img firmware/<firmware_name>.img.ihex - -Then make sure to add the image file name to the -CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_FW_UPDATE entry in firmware/Makefile. -If you don't do this, the image file won't be included, and -the firmware loader class will delay for 60 seconds waiting for a non-existent -userspace response to the firmware load request. - -Firmware updates for multichip solutions (aka LTS) are not supported. diff --git a/kernel/Documentation/firmware_updater/synaptics_fw_updater b/kernel/Documentation/firmware_updater/synaptics_fw_updater Binary files differdeleted file mode 100644 index b0c1b4d9e770..000000000000 --- a/kernel/Documentation/firmware_updater/synaptics_fw_updater +++ /dev/null diff --git a/kernel/Documentation/firmware_updater/synaptics_fw_updater.c b/kernel/Documentation/firmware_updater/synaptics_fw_updater.c deleted file mode 100644 index 7409dd424109..000000000000 --- a/kernel/Documentation/firmware_updater/synaptics_fw_updater.c +++ /dev/null @@ -1,753 +0,0 @@ -/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * - * Copyright © 2011, 2012 Synaptics Incorporated. All rights reserved. - * - * The information in this file is confidential under the terms - * of a non-disclosure agreement with Synaptics and is provided - * AS IS without warranties or guarantees of any kind. - * - * The information in this file shall remain the exclusive property - * of Synaptics and may be the subject of Synaptics patents, in - * whole or part. Synaptics intellectual property rights in the - * information in this file are not expressly or implicitly licensed - * or otherwise transferred to you as a result of such information - * being made available to you. - * - * File: synaptics_fw_updater.c - * - * Description: command line reflash implimentation using command - * line args. This file should not be OS dependant and should build and - * run under any Linux based OS that utilizes the Synaptice rmi driver - * built into the kernel (kernel/drivers/input/rmi4). - * - * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - */ -#include <errno.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/time.h> - -#define DEFAULT_SENSOR "/sys/class/input/input1" - -#define MAX_STRING_LEN 256 -#define MAX_INT_LEN 33 - -#define DATA_FILENAME "data" -#define IMAGESIZE_FILENAME "imagesize" -#define DOREFLASH_FILENAME "doreflash" -#define CONFIGAREA_FILENAME "configarea" -#define READCONFIG_FILENAME "readconfig" -#define WRITECONFIG_FILENAME "writeconfig" -#define BLOCKSIZE_FILENAME "blocksize" -#define IMAGEBLOCKCOUNT_FILENAME "fwblockcount" -#define CONFIGBLOCKCOUNT_FILENAME "configblockcount" -#define PMCONFIGBLOCKCOUNT_FILENAME "permconfigblockcount" -#define BUILDID_FILENAME "buildid" -#define FLASHPROG_FILENAME "flashprog" - -#define UI_CONFIG_AREA 0 -#define PERM_CONFIG_AREA 1 -#define BL_CONFIG_AREA 2 -#define DISP_CONFIG_AREA 3 - -#define IMAGE_FILE_CHECKSUM_SIZE 4 - -unsigned char *firmware = NULL; -int fileSize; -int firmwareBlockSize; -int firmwareBlockCount; -int firmwareImgSize; -int configBlockSize; -int configBlockCount; -int configImgSize; -int totalBlockCount; -int readConfig = 0; -int writeConfig = 0; -int uiConfig = 0; -int pmConfig = 0; -int blConfig = 0; -int dpConfig = 0; -int force = 0; -int verbose = 0; - -char mySensor[MAX_STRING_LEN]; -char imageFileName[MAX_STRING_LEN]; - -static void usage(char *name) -{ - printf("Usage: %s [-b {image_file}] [-d {sysfs_entry}] [-r] [-ui] [-pm] [-bl] [-dp] [-f] [-v]\n", name); - printf("\t[-b {image_file}] - Name of image file\n"); - printf("\t[-d {sysfs_entry}] - Path to sysfs entry of sensor\n"); - printf("\t[-r] - Read config area\n"); - printf("\t[-ui] - UI config area\n"); - printf("\t[-pm] - Permanent config area\n"); - printf("\t[-bl] - BL config area\n"); - printf("\t[-dp] - Display config area\n"); - printf("\t[-f] - Force reflash\n"); - printf("\t[-v] - Verbose output\n"); - - return; -} - -static void TimeSubtract(struct timeval *result, struct timeval *x, struct timeval *y) -{ - if (x->tv_usec < y->tv_usec) { - result->tv_sec = x->tv_sec - y->tv_sec - 1; - result->tv_usec = y->tv_usec - x->tv_usec; - } else { - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_usec = x->tv_usec - y->tv_usec; - } - - return; -} - -static int CheckSysfsEntry(char *sensorName) -{ - int retval; - struct stat st; - - retval = stat(sensorName, &st); - if (retval) - printf("ERROR: sensor sysfs entry %s not found\n", sensorName); - - return retval; -} - -static void WriteBinData(char *fname, unsigned char *buf, int len) -{ - int numBytesWritten; - FILE *fp; - - fp = fopen(fname, "wb"); - if (!fp) { - printf("ERROR: failed to open %s for writing data\n", fname); - exit(EIO); - } - - numBytesWritten = fwrite(buf, 1, len, fp); - - if (numBytesWritten != len) { - printf("ERROR: failed to write all data to bin file\n"); - fclose(fp); - exit(EIO); - } - - fclose(fp); - - return; -} - -static void ReadBinData(char *fname, unsigned char *buf, int len) -{ - int numBytesRead; - FILE *fp; - - fp = fopen(fname, "rb"); - if (!fp) { - printf("ERROR: failed to open %s for reading data\n", fname); - exit(EIO); - } - - numBytesRead = fread(buf, 1, len, fp); - - if (numBytesRead != len) { - printf("ERROR: failed to read all data from bin file\n"); - fclose(fp); - exit(EIO); - } - - fclose(fp); - - return; -} - -static void WriteValueToFp(FILE *fp, unsigned int value) -{ - int numBytesWritten; - char buf[MAX_INT_LEN]; - - snprintf(buf, MAX_INT_LEN, "%u", value); - - fseek(fp, 0, 0); - - numBytesWritten = fwrite(buf, 1, strlen(buf) + 1, fp); - if (numBytesWritten != ((int)(strlen(buf) + 1))) { - printf("ERROR: failed to write value to file pointer\n"); - fclose(fp); - exit(EIO); - } - - return; -} - -static void WriteValueToSysfsFile(char *fname, unsigned int value) -{ - FILE *fp; - - fp = fopen(fname, "w"); - if (!fp) { - printf("ERROR: failed to open %s for writing value\n", fname); - exit(EIO); - } - - WriteValueToFp(fp, value); - - fclose(fp); - - return; -} - -static void ReadValueFromFp(FILE *fp, unsigned int *value) -{ - int retVal; - char buf[MAX_INT_LEN]; - - fseek(fp, 0, 0); - - retVal = fread(buf, 1, sizeof(buf), fp); - if (retVal == -1) { - printf("ERROR: failed to read value from file pointer\n"); - exit(EIO); - } - - *value = strtoul(buf, NULL, 0); - - return; -} - -static void ReadValueFromSysfsFile(char *fname, unsigned int *value) -{ - FILE *fp; - - fp = fopen(fname, "r"); - if (!fp) { - printf("ERROR: failed to open %s for reading value\n", fname); - exit(EIO); - } - - ReadValueFromFp(fp, value); - - fclose(fp); - - return; -} - -static void WriteBlockData(char *buf, int len) -{ - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, DATA_FILENAME); - - WriteBinData(tmpfname, (unsigned char *)buf, len); - - return; -} - -static void ReadBlockData(char *buf, int len) -{ - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, DATA_FILENAME); - - ReadBinData(tmpfname, (unsigned char *)buf, len); - - return; -} - -static void SetImageSize(int value) -{ - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, IMAGESIZE_FILENAME); - - WriteValueToSysfsFile(tmpfname, value); - - return; -} - -static void StartReflash(int value) -{ - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, DOREFLASH_FILENAME); - - WriteValueToSysfsFile(tmpfname, value); - - return; -} - -static void SetConfigArea(int value) -{ - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, CONFIGAREA_FILENAME); - - WriteValueToSysfsFile(tmpfname, value); - - return; -} - -static void StartWriteConfig(int value) -{ - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, WRITECONFIG_FILENAME); - - WriteValueToSysfsFile(tmpfname, value); - - return; -} - -static void StartReadConfig(int value) -{ - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, READCONFIG_FILENAME); - - WriteValueToSysfsFile(tmpfname, value); - - return; -} - -static int ReadBlockSize(void) -{ - unsigned int blockSize; - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, BLOCKSIZE_FILENAME); - - ReadValueFromSysfsFile(tmpfname, &blockSize); - - return blockSize; -} - -static int ReadFirmwareBlockCount(void) -{ - unsigned int imageBlockCount; - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, IMAGEBLOCKCOUNT_FILENAME); - - ReadValueFromSysfsFile(tmpfname, &imageBlockCount); - - return imageBlockCount; -} - -static int ReadConfigBlockCount(void) -{ - unsigned int configBlockCount; - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, CONFIGBLOCKCOUNT_FILENAME); - - ReadValueFromSysfsFile(tmpfname, &configBlockCount); - - return configBlockCount; -} - -static int ReadPmConfigBlockCount(void) -{ - unsigned int configBlockCount; - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, PMCONFIGBLOCKCOUNT_FILENAME); - - ReadValueFromSysfsFile(tmpfname, &configBlockCount); - - return configBlockCount; -} - -static int ReadBuildID(void) -{ - unsigned int buildID; - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, BUILDID_FILENAME); - - ReadValueFromSysfsFile(tmpfname, &buildID); - - return buildID; -} - -static int ReadFlashProg(void) -{ - unsigned int flashProg; - char tmpfname[MAX_STRING_LEN]; - - snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, FLASHPROG_FILENAME); - - ReadValueFromSysfsFile(tmpfname, &flashProg); - - return flashProg; -} - -static void ReadFirmwareInfo(void) -{ - firmwareBlockSize = ReadBlockSize(); - firmwareBlockCount = ReadFirmwareBlockCount(); - firmwareImgSize = firmwareBlockCount * firmwareBlockSize; - - return; -} - -static void ReadConfigInfo(void) -{ - configBlockSize = ReadBlockSize(); - configBlockCount = ReadConfigBlockCount(); - configImgSize = configBlockSize * configBlockCount; - - return; -} - -static void CalculateChecksum(unsigned short *data, unsigned short len, unsigned long *result) -{ - unsigned long temp; - unsigned long sum1 = 0xffff; - unsigned long sum2 = 0xffff; - - *result = 0xffffffff; - - while (len--) { - temp = *data; - sum1 += temp; - sum2 += sum1; - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - data++; - } - - *result = sum2 << 16 | sum1; - - return; -} - -static int CompareChecksum(void) -{ - unsigned long headerChecksum; - unsigned long computedChecksum; - - headerChecksum = (unsigned long)firmware[0] + - (unsigned long)firmware[1] * 0x100 + - (unsigned long)firmware[2] * 0x10000 + - (unsigned long)firmware[3] * 0x1000000; - - CalculateChecksum((unsigned short *)&firmware[IMAGE_FILE_CHECKSUM_SIZE], - ((fileSize - IMAGE_FILE_CHECKSUM_SIZE) / 2), &computedChecksum); - - if (verbose) { - printf("Checksum in image file header = 0x%08x\n", (unsigned int)headerChecksum); - printf("Checksum computed from image file = 0x%08x\n", (unsigned int)computedChecksum); - } - - if (headerChecksum == computedChecksum) - return 1; - else - return 0; -} - -static int ProceedWithReflash(void) -{ - int index = 0; - int deviceBuildID; - int imageBuildID; - char imagePR[MAX_STRING_LEN]; - char *strptr; - - if (force) { - printf("Force reflash...\n"); - return 1; - } - - if (ReadFlashProg()) { - printf("Force reflash (device in flash prog mode)...\n"); - return 1; - } - - strptr = strstr(imageFileName, "PR"); - if (!strptr) { - printf("No valid PR number (PRxxxxxxx) found in image file name...\n"); - return 0; - } - - strptr += 2; - while (strptr[index] >= '0' && strptr[index] <= '9') { - imagePR[index] = strptr[index]; - index++; - } - imagePR[index] = 0; - - imageBuildID = strtoul(imagePR, NULL, 0); - deviceBuildID = ReadBuildID(); - printf("Image file PR = %d\n", imageBuildID); - printf("Device PR = %d\n", deviceBuildID); - - if (imageBuildID > deviceBuildID) { - printf("Proceed with reflash...\n"); - return 1; - } else { - printf("No need to do reflash...\n"); - return 0; - } -} - -static void DoReadConfig(void) -{ - int ii; - int jj; - int index = 0; - int configSize; - int blockCount; - unsigned char *buffer; - - if (uiConfig) { - SetConfigArea(UI_CONFIG_AREA); - StartReadConfig(1); - blockCount = configBlockCount; - configSize = configImgSize; - buffer = malloc(configSize); - if (!buffer) - exit(ENOMEM); - ReadBlockData((char *)&buffer[0], configSize); - } else if (pmConfig) { - SetConfigArea(PERM_CONFIG_AREA); - StartReadConfig(1); - blockCount = ReadPmConfigBlockCount(); - configSize = configBlockSize * blockCount; - buffer = malloc(configSize); - if (!buffer) - exit(ENOMEM); - ReadBlockData((char *)&buffer[0], configSize); - } else { - return; - } - - for (ii = 0; ii < blockCount; ii++) { - for (jj = 0; jj < configBlockSize; jj++) { - printf("0x%02x ", buffer[index]); - index++; - } - printf("\n"); - } - - free(buffer); - - return; -} - -static void DoWriteConfig(void) -{ - printf("Starting config programming...\n"); - - if (uiConfig) - SetConfigArea(UI_CONFIG_AREA); - else if (pmConfig) - SetConfigArea(PERM_CONFIG_AREA); - else if (blConfig) - SetConfigArea(BL_CONFIG_AREA); - else if (dpConfig) - SetConfigArea(DISP_CONFIG_AREA); - else - return; - - SetImageSize(fileSize); - WriteBlockData((char *)&firmware[0], fileSize); - StartWriteConfig(1); - - printf("Config programming completed...\n"); - - return; -} - -static void DoReflash(void) -{ - if (verbose) - printf("Blocks: %d (firmware: %d, config: %d)\n", totalBlockCount, firmwareBlockCount, configBlockCount); - - if (!ProceedWithReflash()) - return; - - printf("Starting reflash...\n"); - - SetImageSize(fileSize); - WriteBlockData((char *)&firmware[0], fileSize); - StartReflash(1); - - printf("Reflash completed...\n"); - - return; -} - -static int InitFirmwareImage(void) -{ - int numBytesRead; - FILE *fp; - - if (!readConfig) { - fp = fopen(imageFileName, "rb"); - - if (!fp) { - printf("ERROR: image file %s not found\n", imageFileName); - exit(ENODEV); - } - - fseek(fp, 0L, SEEK_END); - fileSize = ftell(fp); - if (fileSize == -1) { - printf("ERROR: failed to determine size of %s\n", imageFileName); - exit(EIO); - } - - fseek(fp, 0L, SEEK_SET); - - firmware = malloc(fileSize + 1); - if (!firmware) { - exit(ENOMEM); - } else { - numBytesRead = fread(firmware, 1, fileSize, fp); - if (numBytesRead != fileSize) { - printf("ERROR: failed to read entire content of image file\n"); - exit(EIO); - } - } - - fclose(fp); - - if (!(pmConfig || blConfig || dpConfig)) { - if (!CompareChecksum()) { - printf("ERROR: failed to validate checksum of image file\n"); - exit(EINVAL); - } - } - } - - return 0; -} - -int main(int argc, char* argv[]) -{ - int retVal; - int this_arg = 1; - struct stat st; - struct timeval start_time; - struct timeval end_time; - struct timeval elapsed_time; - - if (argc == 1) { - usage(argv[0]); - exit(EINVAL); - } - - while (this_arg < argc) { - if (!strcmp((const char *)argv[this_arg], "-b")) { - /* Image file */ - FILE *file; - - this_arg++; - if (this_arg >= argc) { - printf("ERROR: image file missing\n"); - exit(EINVAL); - } - - /* check for presence of image file */ - file = fopen(argv[this_arg], "rb"); - if (file == 0) { - printf("ERROR: image file %s not found\n", argv[this_arg]); - exit(EINVAL); - } - fclose(file); - - strncpy(imageFileName, argv[this_arg], MAX_STRING_LEN); - } else if (!strcmp((const char *)argv[this_arg], "-d")) { - /* path to sensor sysfs entry */ - this_arg++; - - if (stat(argv[this_arg], &st) == 0) { - strncpy(mySensor, argv[this_arg], MAX_STRING_LEN); - } else { - printf("ERROR: sensor sysfs entry %s not found\n", argv[this_arg]); - exit(EINVAL); - } - } else if (!strcmp((const char *)argv[this_arg], "-r")) { - readConfig = 1; - } else if (!strcmp((const char *)argv[this_arg], "-ui")) { - uiConfig = 1; - } else if (!strcmp((const char *)argv[this_arg], "-pm")) { - pmConfig = 1; - } else if (!strcmp((const char *)argv[this_arg], "-bl")) { - blConfig = 1; - } else if (!strcmp((const char *)argv[this_arg], "-dp")) { - dpConfig = 1; - } else if (!strcmp((const char *)argv[this_arg], "-f")) { - force = 1; - } else if (!strcmp((const char *)argv[this_arg], "-v")) { - verbose = 1; - } else { - usage(argv[0]); - printf("ERROR: invalid parameter %s supplied\n", argv[this_arg]); - exit(EINVAL); - } - this_arg++; - } - - if ((uiConfig + pmConfig + blConfig + dpConfig) > 1) { - printf("ERROR: too many parameters\n"); - exit(EINVAL); - } - - if (uiConfig || pmConfig || blConfig || dpConfig) - writeConfig = 1; - - if (!readConfig && !strlen(imageFileName)) { - printf("ERROR: no image file specified\n"); - exit(EINVAL); - } - - if (!strlen(mySensor)) - strncpy(mySensor, DEFAULT_SENSOR, MAX_STRING_LEN); - - if (CheckSysfsEntry(mySensor)) - exit(ENODEV); - - InitFirmwareImage(); - - ReadFirmwareInfo(); - ReadConfigInfo(); - totalBlockCount = configBlockCount + firmwareBlockCount; - - retVal = gettimeofday(&start_time, NULL); - if (retVal) - printf("WARNING: failed to get start time\n"); - - if (verbose) { - if (!readConfig) - printf("Image file: %s\n", imageFileName); - printf("Sensor sysfs entry: %s\n", mySensor); - } - - if (readConfig) - DoReadConfig(); - else if (writeConfig) - DoWriteConfig(); - else - DoReflash(); - - retVal = gettimeofday(&end_time, NULL); - if (retVal) - printf("WARNING: failed to get end time\n"); - - TimeSubtract(&elapsed_time, &end_time, &start_time); - - if (verbose) { - printf("Elapsed time = %ld.%06ld seconds\n", - (long)elapsed_time.tv_sec, - (long)elapsed_time.tv_usec); - } - - return 0; -} diff --git a/kernel/Documentation/firmware_updater/synaptics_fw_updater_readme.txt b/kernel/Documentation/firmware_updater/synaptics_fw_updater_readme.txt deleted file mode 100644 index 66f71922995a..000000000000 --- a/kernel/Documentation/firmware_updater/synaptics_fw_updater_readme.txt +++ /dev/null @@ -1,41 +0,0 @@ -Use ADB (Android Debug Bridge) to do command-line reflash -- Power on device. -- Connect device to host via USB. -- Open command prompt on host and go to directory where adb, synaptics_fw_updater, and FW image (e.g. PR1234567.img) reside. -- Run "adb devices" to ensure connection with device. -- Run "adb root" to have root privileges. -- Run "adb push synaptics_fw_updater /data" to copy synaptics_fw_updater to /data directory on device. -- Run "adb push firmware.img /data" to copy firmware.img to /data directory on device. -- Run "adb shell chmod 777 /data/synaptics_fw_updater" to make synaptics_fw_updater executable. -- Run "adb shell /data/synaptics_fw_updater -b /data/PR1234567.img -f -v" to start reflash process. - -Parameters -[-b {image_file}] - Name of image file -[-d {sysfs_entry}] - Path to sysfs entry of sensor -[-r] - Read config area -[-ui] - UI config area -[-pm] - Permanent config area -[-bl] - BL config area -[-dp] - Display config area -[-f] - Force reflash -[-v] - Verbose output - -Procedures for checking whether to proceed with reflash -- If [-f] flag is set, proceed with reflash -- If device is in flash prog (bootloader) mode, proceed with reflash -- If PR number contained in name of new FW image is greater than PR number of FW on device, proceed with reflash. -- Otherwise, no reflash is performed - -Usage examples -- Perform reflash using PR1234567.img regardless of PR number of FW on device - synaptics_fw_updater -b PR1234567.img -f -- Perform reflash using PR1234567.img only if 1234567 is greater than PR number of FW on device. - synaptics_fw_updater -b PR1234567.img -- Write UI config area from PR1234567.img (parsing UI config area from firmware image file) - synaptics_fw_updater -b PR1234567.img -ui -- Write permanent config area from pmconfig.img (binary file containing permanent config data) - synaptics_fw_updater -b pmconfig.img -pm -- Read UI config area - synaptics_fw_updater -r -ui -- Read permanent config area - synaptics_fw_updater -r -pm
\ No newline at end of file diff --git a/kernel/arch/arm/configs/omap3_beagle_android_defconfig b/kernel/arch/arm/configs/omap3_beagle_android_defconfig deleted file mode 100644 index 4fc62c4fa440..000000000000 --- a/kernel/arch/arm/configs/omap3_beagle_android_defconfig +++ /dev/null @@ -1,2419 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux/arm 2.6.37 Kernel Configuration -# Mon Apr 16 13:58:06 2012 -# -CONFIG_ARM=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y -# CONFIG_ARCH_USES_GETTIMEOFFSET is not set -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARCH_HAS_CPUFREQ=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_VECTORS_BASE=0xffff0000 -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_CONSTRUCTORS=y -CONFIG_HAVE_IRQ_WORK=y -CONFIG_IRQ_WORK=y - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_LZO is not set -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set -# CONFIG_TASKSTATS is not set -# CONFIG_AUDIT is not set -# CONFIG_HAVE_GENERIC_HARDIRQS is not set -# CONFIG_SPARSE_IRQ is not set - -# -# RCU Subsystem -# -CONFIG_TINY_RCU=y -# CONFIG_PREEMPT_RCU is not set -# CONFIG_TREE_RCU_TRACE is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_CGROUPS is not set -# CONFIG_NAMESPACES is not set -# CONFIG_SYSFS_DEPRECATED is not set -# CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -# CONFIG_RD_BZIP2 is not set -# CONFIG_RD_LZMA is not set -# CONFIG_RD_LZO is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_PANIC_TIMEOUT=0 -CONFIG_EMBEDDED=y -CONFIG_UID16=y -# CONFIG_SYSCTL_SYSCALL is not set -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_EXTRA_PASS=y -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_ASHMEM=y -CONFIG_AIO=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_PERF_USE_VMALLOC=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_COMPAT_BRK=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y -CONFIG_OPROFILE=y -CONFIG_HAVE_OPROFILE=y -CONFIG_KPROBES=y -CONFIG_KRETPROBES=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_HW_BREAKPOINT=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SRCVERSION_ALL=y -CONFIG_BLOCK=y -CONFIG_LBDAF=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_INTEGRITY is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# CONFIG_INLINE_SPIN_LOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -CONFIG_INLINE_SPIN_UNLOCK=y -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set -CONFIG_INLINE_SPIN_UNLOCK_IRQ=y -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -CONFIG_INLINE_READ_UNLOCK=y -# CONFIG_INLINE_READ_UNLOCK_BH is not set -CONFIG_INLINE_READ_UNLOCK_IRQ=y -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -CONFIG_INLINE_WRITE_UNLOCK=y -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -CONFIG_INLINE_WRITE_UNLOCK_IRQ=y -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set -CONFIG_FREEZER=y - -# -# System Type -# -CONFIG_MMU=y -# CONFIG_ARCH_AAEC2000 is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_VEXPRESS is not set -# CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_BCMRING is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CNS3XXX is not set -# CONFIG_ARCH_GEMINI is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_EP93XX is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_MXC is not set -# CONFIG_ARCH_STMP3XXX is not set -# CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IOP13XX is not set -# CONFIG_ARCH_IOP32X is not set -# CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_DOVE is not set -# CONFIG_ARCH_KIRKWOOD is not set -# CONFIG_ARCH_LOKI is not set -# CONFIG_ARCH_LPC32XX is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_MMP is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_NS9XXX is not set -# CONFIG_ARCH_W90X900 is not set -# CONFIG_ARCH_NUC93X is not set -# CONFIG_ARCH_TEGRA is not set -# CONFIG_ARCH_PNX4008 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MSM is not set -# CONFIG_ARCH_SHMOBILE is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_S3C64XX is not set -# CONFIG_ARCH_S5P64X0 is not set -# CONFIG_ARCH_S5P6442 is not set -# CONFIG_ARCH_S5PC100 is not set -# CONFIG_ARCH_S5PV210 is not set -# CONFIG_ARCH_S5PV310 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_TCC_926 is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_U300 is not set -# CONFIG_ARCH_U8500 is not set -# CONFIG_ARCH_NOMADIK is not set -# CONFIG_ARCH_DAVINCI is not set -CONFIG_ARCH_OMAP=y -# CONFIG_PLAT_SPEAR is not set - -# -# TI OMAP Common Features -# -CONFIG_ARCH_OMAP_OTG=y -# CONFIG_ARCH_OMAP1 is not set -CONFIG_ARCH_OMAP2PLUS=y - -# -# OMAP Feature Selections -# -CONFIG_OMAP_SMARTREFLEX=y -CONFIG_OMAP_SMARTREFLEX_CLASS3=y -CONFIG_OMAP_RESET_CLOCKS=y -CONFIG_OMAP_MUX=y -CONFIG_OMAP_MUX_DEBUG=y -CONFIG_OMAP_MUX_WARNINGS=y -CONFIG_OMAP_MCBSP=y -# CONFIG_OMAP_MBOX_FWK is not set -CONFIG_OMAP_IOMMU=y -# CONFIG_OMAP_IOMMU_DEBUG is not set -# CONFIG_OMAP_MPU_TIMER is not set -CONFIG_OMAP_32K_TIMER=y -# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set -CONFIG_OMAP_32K_TIMER_HZ=128 -CONFIG_OMAP_DM_TIMER=y -# CONFIG_OMAP_PM_NONE is not set -CONFIG_OMAP_PM_NOOP=y - -# -# TI OMAP2/3/4 Specific Features -# -CONFIG_ARCH_OMAP2PLUS_TYPICAL=y -# CONFIG_ARCH_OMAP2 is not set -CONFIG_ARCH_OMAP3=y -# CONFIG_ARCH_OMAP4 is not set -# CONFIG_ARCH_TI81XX is not set -CONFIG_ARCH_OMAP3430=y -CONFIG_OMAP_PACKAGE_CBB=y - -# -# OMAP Board Type -# -CONFIG_MACH_OMAP3_BEAGLE=y -# CONFIG_MACH_DEVKIT8000 is not set -# CONFIG_MACH_OMAP_LDP is not set -# CONFIG_MACH_OMAP3530_LV_SOM is not set -# CONFIG_MACH_OMAP3_TORPEDO is not set -# CONFIG_MACH_OVERO is not set -# CONFIG_MACH_OMAP3EVM is not set -# CONFIG_MACH_FLASHBOARD is not set -# CONFIG_MACH_OMAP3517EVM is not set -# CONFIG_MACH_CRANEBOARD is not set -# CONFIG_MACH_OMAP3_PANDORA is not set -# CONFIG_MACH_OMAP3_TOUCHBOOK is not set -# CONFIG_MACH_OMAP_3430SDP is not set -# CONFIG_MACH_NOKIA_RM680 is not set -# CONFIG_MACH_NOKIA_RX51 is not set -# CONFIG_MACH_OMAP_ZOOM2 is not set -# CONFIG_MACH_OMAP_ZOOM3 is not set -# CONFIG_MACH_CM_T35 is not set -# CONFIG_MACH_CM_T3517 is not set -# CONFIG_MACH_IGEP0020 is not set -# CONFIG_MACH_IGEP0030 is not set -# CONFIG_MACH_SBC3530 is not set -# CONFIG_MACH_OMAP_3630SDP is not set -# CONFIG_OMAP3_EMU is not set -CONFIG_OMAP3_PM_DISABLE_VT_SWITCH=y -# CONFIG_OMAP3_SDRC_AC_TIMING is not set - -# -# Processor Type -# -CONFIG_CPU_32v6K=y -CONFIG_CPU_V7=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y - -# -# Processor Features -# -CONFIG_ARM_THUMB=y -CONFIG_ARM_THUMBEE=y -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -# CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_ARM_ERRATA_743622 is not set -CONFIG_COMMON_CLKDEV=y -# CONFIG_FIQ_DEBUGGER is not set - -# -# Bus support -# -# CONFIG_PCI_SYSCALL is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_VMSPLIT_3G=y -# CONFIG_VMSPLIT_2G is not set -# CONFIG_VMSPLIT_1G is not set -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set -CONFIG_HZ=128 -# CONFIG_THUMB2_KERNEL is not set -CONFIG_AEABI=y -CONFIG_OABI_COMPAT=y -CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_HIGHMEM is not set -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -CONFIG_NEED_PER_CPU_KM=y -CONFIG_FORCE_MAX_ZONEORDER=11 -# CONFIG_LEDS is not set -CONFIG_ALIGNMENT_TRAP=y -# CONFIG_UACCESS_WITH_MEMCPY is not set -# CONFIG_SECCOMP is not set -# CONFIG_CC_STACKPROTECTOR is not set -# CONFIG_DEPRECATED_PARAM_STRUCT is not set - -# -# Boot options -# -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200" -# CONFIG_CMDLINE_FORCE is not set -# CONFIG_XIP_KERNEL is not set -CONFIG_KEXEC=y -CONFIG_ATAGS_PROC=y -# CONFIG_AUTO_ZRELADDR is not set - -# -# CPU Power Management -# -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_TABLE=y -# CONFIG_CPU_FREQ_DEBUG is not set -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_NEON=y - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_HAVE_AOUT=y -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_MISC=y - -# -# Power management options -# -CONFIG_PM=y -CONFIG_PM_DEBUG=y -# CONFIG_PM_ADVANCED_DEBUG is not set -# CONFIG_PM_VERBOSE is not set -CONFIG_CAN_PM_TRACE=y -CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_NVS=y -CONFIG_SUSPEND=y -# CONFIG_PM_TEST_SUSPEND is not set -CONFIG_SUSPEND_FREEZER=y -CONFIG_HAS_WAKELOCK=y -CONFIG_HAS_EARLYSUSPEND=y -CONFIG_WAKELOCK=y -CONFIG_WAKELOCK_STAT=y -CONFIG_USER_WAKELOCK=y -CONFIG_EARLYSUSPEND=y -# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set -# CONFIG_CONSOLE_EARLYSUSPEND is not set -CONFIG_FB_EARLYSUSPEND=y -# CONFIG_APM_EMULATION is not set -CONFIG_PM_RUNTIME=y -CONFIG_PM_OPS=y -CONFIG_ARCH_HAS_OPP=y -CONFIG_PM_OPP=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_XFRM_SUB_POLICY is not set -CONFIG_XFRM_MIGRATE=y -# CONFIG_XFRM_STATISTICS is not set -CONFIG_NET_KEY=y -CONFIG_NET_KEY_MIGRATE=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE_DEMUX is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=y -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -# CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=y -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=y -CONFIG_INET6_XFRM_MODE_TUNNEL=y -CONFIG_INET6_XFRM_MODE_BEET=y -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=y -# CONFIG_IPV6_SIT_6RD is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_NETLABEL is not set -CONFIG_ANDROID_PARANOID_NETWORK=y -CONFIG_NET_ACTIVITY_STATS=y -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETWORK_PHY_TIMESTAMPING is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_L2TP is not set -# CONFIG_BRIDGE is not set -# CONFIG_NET_DSA is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_PHONET is not set -# CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set -CONFIG_DNS_RESOLVER=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NET_TCPPROBE is not set -# CONFIG_NET_DROP_MONITOR is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set -CONFIG_WIRELESS=y -CONFIG_WIRELESS_EXT=y -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PROC=y -# CONFIG_CFG80211 is not set -CONFIG_WIRELESS_EXT_SYSFS=y -# CONFIG_LIB80211 is not set - -# -# CFG80211 needs to be enabled for MAC80211 -# - -# -# Some wireless drivers require a rate control algorithm -# -# CONFIG_WIMAX is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set -# CONFIG_CAIF is not set -# CONFIG_CEPH_LIB is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_DEVTMPFS is not set -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_CONNECTOR is not set -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_TESTS is not set -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set -# CONFIG_MTD_AR7_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLKDEVS=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set -# CONFIG_SM_FTL is not set -CONFIG_MTD_OOPS=y - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_DATAFLASH is not set -# CONFIG_MTD_M25P80 is not set -# CONFIG_MTD_SST25L is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -CONFIG_MTD_NAND_IDS=y -CONFIG_MTD_NAND_ECC=y -# CONFIG_MTD_NAND_ECC_SMC is not set -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_SM_COMMON is not set -# CONFIG_MTD_NAND_MUSEUM_IDS is not set -# CONFIG_MTD_NAND_GPIO is not set -CONFIG_MTD_NAND_OMAP2=y -# CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_NANDSIM is not set -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_ALAUDA is not set -CONFIG_MTD_ONENAND=y -CONFIG_MTD_ONENAND_VERIFY_WRITE=y -# CONFIG_MTD_ONENAND_GENERIC is not set -CONFIG_MTD_ONENAND_OMAP2=y -# CONFIG_MTD_ONENAND_OTP is not set -# CONFIG_MTD_ONENAND_2X_PROGRAM is not set -# CONFIG_MTD_ONENAND_SIM is not set - -# -# LPDDR flash memory drivers -# -# CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_UBI is not set -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set - -# -# DRBD disabled because PROC_FS, INET or CONNECTOR not selected -# -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=16384 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -# CONFIG_MG_DISK is not set -# CONFIG_BLK_DEV_RBD is not set -# CONFIG_MISC_DEVICES is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_NETLINK is not set -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set -# CONFIG_CHR_DEV_SCH is not set -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_WAIT_SCAN=m - -# -# SCSI Transports -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_ISCSI_TCP is not set -# CONFIG_ISCSI_BOOT_SYSFS is not set -# CONFIG_LIBFC is not set -# CONFIG_LIBFCOE is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_DH is not set -# CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_ATA is not set -CONFIG_MD=y -# CONFIG_BLK_DEV_MD is not set -CONFIG_BLK_DEV_DM=y -# CONFIG_DM_DEBUG is not set -CONFIG_DM_CRYPT=y -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_ZERO is not set -# CONFIG_DM_MULTIPATH is not set -# CONFIG_DM_DELAY is not set -CONFIG_DM_UEVENT=y -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set -CONFIG_MII=y -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -CONFIG_SMSC_PHY=y -# CONFIG_BROADCOM_PHY is not set -# CONFIG_BCM63XX_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set -# CONFIG_MDIO_BITBANG is not set -CONFIG_NET_ETHERNET=y -# CONFIG_AX88796 is not set -# CONFIG_SMC91X is not set -# CONFIG_DM9000 is not set -# CONFIG_ENC28J60 is not set -# CONFIG_ETHOC is not set -CONFIG_SMC911X=y -CONFIG_SMSC911X=y -# CONFIG_SMSC911X_ARCH_HOOKS is not set -# CONFIG_DNET is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set -# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set -# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set -# CONFIG_B44 is not set -# CONFIG_KS8851 is not set -# CONFIG_KS8851_MLL is not set -CONFIG_NETDEV_1000=y -CONFIG_TI_DAVINCI_EMAC=y -CONFIG_TI_DAVINCI_MDIO=y -CONFIG_TI_DAVINCI_CPDMA=y -# CONFIG_STMMAC_ETH is not set -CONFIG_NETDEV_10000=y -CONFIG_WLAN=y -# CONFIG_USB_ZD1201 is not set -# CONFIG_BCM4329 is not set -# CONFIG_HOSTAP is not set -CONFIG_WL12XX_PLATFORM_DATA=y - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -CONFIG_USB_USBNET=y -CONFIG_USB_NET_AX8817X=y -CONFIG_USB_NET_CDCETHER=y -# CONFIG_USB_NET_CDC_EEM is not set -# CONFIG_USB_NET_DM9601 is not set -# CONFIG_USB_NET_SMSC75XX is not set -CONFIG_USB_NET_SMSC95XX=y -# CONFIG_USB_NET_GL620A is not set -CONFIG_USB_NET_NET1080=y -# CONFIG_USB_NET_PLUSB is not set -# CONFIG_USB_NET_MCS7830 is not set -# CONFIG_USB_NET_RNDIS_HOST is not set -CONFIG_USB_NET_CDC_SUBSET=y -CONFIG_USB_ALI_M5632=y -CONFIG_USB_AN2720=y -CONFIG_USB_BELKIN=y -CONFIG_USB_ARMLINUX=y -CONFIG_USB_EPSON2888=y -CONFIG_USB_KC2190=y -CONFIG_USB_NET_ZAURUS=y -# CONFIG_USB_NET_CX82310_ETH is not set -# CONFIG_USB_NET_INT51X1 is not set -# CONFIG_USB_IPHETH is not set -# CONFIG_USB_SIERRA_NET is not set -# CONFIG_WAN is not set - -# -# CAIF transport drivers -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set -# CONFIG_INPUT_SPARSEKMAP is not set - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=y -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set -# CONFIG_INPUT_KEYRESET is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ADP5588 is not set -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_QT2160 is not set -# CONFIG_KEYBOARD_LKKBD is not set -CONFIG_KEYBOARD_GPIO=y -# CONFIG_KEYBOARD_GPIO_POLLED is not set -# CONFIG_KEYBOARD_TCA6416 is not set -# CONFIG_KEYBOARD_MATRIX is not set -# CONFIG_KEYBOARD_MAX7359 is not set -# CONFIG_KEYBOARD_MCS is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_OPENCORES is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_SUNKBD is not set -CONFIG_KEYBOARD_TWL4030=y -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -# CONFIG_MOUSE_PS2_SENTELIC is not set -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_APPLETOUCH is not set -# CONFIG_MOUSE_BCM5974 is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MOUSE_GPIO is not set -# CONFIG_MOUSE_SYNAPTICS_I2C is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_TOUCHSCREEN_ADS7846 is not set -# CONFIG_TOUCHSCREEN_AD7877 is not set -# CONFIG_TOUCHSCREEN_AD7879 is not set -# CONFIG_TOUCHSCREEN_BU21013 is not set -# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set -# CONFIG_TOUCHSCREEN_DYNAPRO is not set -# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set -# CONFIG_TOUCHSCREEN_EETI is not set -# CONFIG_TOUCHSCREEN_FUJITSU is not set -# CONFIG_TOUCHSCREEN_GUNZE is not set -# CONFIG_TOUCHSCREEN_ELO is not set -# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set -# CONFIG_TOUCHSCREEN_MCS5000 is not set -# CONFIG_TOUCHSCREEN_MTOUCH is not set -# CONFIG_TOUCHSCREEN_INEXIO is not set -# CONFIG_TOUCHSCREEN_MK712 is not set -# CONFIG_TOUCHSCREEN_PENMOUNT is not set -# CONFIG_TOUCHSCREEN_QT602240 is not set -CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y -CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y -CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y -# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set -# CONFIG_TOUCHSCREEN_TOUCHWIN is not set -# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set -# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set -# CONFIG_TOUCHSCREEN_TSC2007 is not set -# CONFIG_TOUCHSCREEN_TSC2004 is not set -# CONFIG_TOUCHSCREEN_W90X900 is not set -# CONFIG_TOUCHSCREEN_TPS6507X is not set -CONFIG_INPUT_MISC=y -# CONFIG_INPUT_AD714X is not set -# CONFIG_INPUT_ATI_REMOTE is not set -# CONFIG_INPUT_ATI_REMOTE2 is not set -# CONFIG_INPUT_KEYCHORD is not set -# CONFIG_INPUT_KEYSPAN_REMOTE is not set -# CONFIG_INPUT_POWERMATE is not set -# CONFIG_INPUT_YEALINK is not set -# CONFIG_INPUT_CM109 is not set -CONFIG_INPUT_TWL4030_PWRBUTTON=y -# CONFIG_INPUT_TWL4030_VIBRA is not set -# CONFIG_INPUT_UINPUT is not set -# CONFIG_INPUT_GPIO is not set -# CONFIG_INPUT_PCF8574 is not set -# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set -# CONFIG_INPUT_ADXL34X is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_ALTERA_PS2 is not set -# CONFIG_SERIO_PS2MULT is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_DEVMEM=y -CONFIG_DEVKMEM=y -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_N_GSM is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=32 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_MANY_PORTS=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -CONFIG_SERIAL_8250_DETECT_IRQ=y -CONFIG_SERIAL_8250_RSA=y - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_MAX3100 is not set -# CONFIG_SERIAL_MAX3107 is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_SERIAL_OMAP=y -CONFIG_SERIAL_OMAP_CONSOLE=y -# CONFIG_SERIAL_TIMBERDALE is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_TTY_PRINTK is not set -# CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=y -# CONFIG_HW_RANDOM_TIMERIOMEM is not set -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_TI81XX_HDMI is not set -# CONFIG_DCC_TTY is not set -# CONFIG_RAMOOPS is not set -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_CHARDEV=y -# CONFIG_I2C_MUX is not set -CONFIG_I2C_HELPER_AUTO=y - -# -# I2C Hardware Bus support -# - -# -# I2C system bus drivers (mostly embedded / system-on-chip) -# -# CONFIG_I2C_DESIGNWARE is not set -# CONFIG_I2C_GPIO is not set -# CONFIG_I2C_OCORES is not set -CONFIG_I2C_OMAP=y -# CONFIG_I2C_PCA_PLATFORM is not set -# CONFIG_I2C_SIMTEC is not set -# CONFIG_I2C_XILINX is not set - -# -# External I2C/SMBus adapter drivers -# -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_TINY_USB is not set - -# -# Other I2C/SMBus bus drivers -# -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -CONFIG_SPI=y -CONFIG_SPI_MASTER=y - -# -# SPI Master Controller Drivers -# -# CONFIG_SPI_BITBANG is not set -# CONFIG_SPI_GPIO is not set -CONFIG_SPI_OMAP24XX=y -# CONFIG_SPI_XILINX is not set -# CONFIG_SPI_DESIGNWARE is not set - -# -# SPI Protocol Masters -# -# CONFIG_SPI_SPIDEV is not set -# CONFIG_SPI_TLE62X0 is not set - -# -# PPS support -# -# CONFIG_PPS is not set -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -CONFIG_GPIO_SYSFS=y - -# -# Memory mapped GPIO expanders: -# -# CONFIG_GPIO_BASIC_MMIO is not set -# CONFIG_GPIO_IT8761E is not set -# CONFIG_GPIO_VX855 is not set - -# -# I2C GPIO expanders: -# -# CONFIG_GPIO_MAX7300 is not set -# CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCA953X is not set -# CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SX150X is not set -CONFIG_GPIO_TWL4030=y -# CONFIG_GPIO_ADP5588 is not set - -# -# PCI GPIO expanders: -# - -# -# SPI GPIO expanders: -# -# CONFIG_GPIO_MAX7301 is not set -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set - -# -# AC97 GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# -# CONFIG_W1 is not set -CONFIG_POWER_SUPPLY=y -# CONFIG_POWER_SUPPLY_DEBUG is not set -# CONFIG_PDA_POWER is not set -# CONFIG_TEST_POWER is not set -# CONFIG_BATTERY_DS2782 is not set -# CONFIG_BATTERY_BQ20Z75 is not set -# CONFIG_BATTERY_BQ27x00 is not set -# CONFIG_BATTERY_MAX17040 is not set -# CONFIG_CHARGER_ISP1704 is not set -# CONFIG_CHARGER_TWL4030 is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_HWMON_DEBUG_CHIP is not set - -# -# Native drivers -# -# CONFIG_SENSORS_AD7414 is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADT7411 is not set -# CONFIG_SENSORS_ADT7462 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7475 is not set -# CONFIG_SENSORS_ASC7621 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_G760A is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_GPIO_FAN is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_JC42 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM73 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_LTC4215 is not set -# CONFIG_SENSORS_LTC4245 is not set -# CONFIG_SENSORS_LTC4261 is not set -# CONFIG_SENSORS_LM95241 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_SHT15 is not set -# CONFIG_SENSORS_SMM665 is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_EMC1403 is not set -# CONFIG_SENSORS_EMC2103 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_ADS7828 is not set -# CONFIG_SENSORS_ADS7871 is not set -# CONFIG_SENSORS_AMC6821 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_TMP102 is not set -# CONFIG_SENSORS_TMP401 is not set -# CONFIG_SENSORS_TMP421 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83795 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83L786NG is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_SENSORS_LIS3_SPI is not set -# CONFIG_SENSORS_LIS3_I2C is not set -# CONFIG_THERMAL is not set -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -CONFIG_OMAP_WATCHDOG=y -CONFIG_TWL4030_WATCHDOG=y -# CONFIG_MAX63XX_WATCHDOG is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -# CONFIG_SSB is not set -CONFIG_MFD_SUPPORT=y -CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_ASIC3 is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_HTC_I2CPLD is not set -# CONFIG_TPS65010 is not set -# CONFIG_TPS6507X is not set -CONFIG_TWL4030_CORE=y -CONFIG_TWL4030_POWER=y -CONFIG_TWL4030_SCRIPT=y -CONFIG_TWL4030_CODEC=y -# CONFIG_TWL6030_PWM is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC35892 is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set -# CONFIG_PMIC_DA903X is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_MAX8925 is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_WM8400 is not set -# CONFIG_MFD_WM831X_I2C is not set -# CONFIG_MFD_WM831X_SPI is not set -# CONFIG_MFD_WM8350_I2C is not set -# CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_EZX_PCAP is not set -# CONFIG_MFD_TPS6586X is not set -CONFIG_REGULATOR=y -# CONFIG_REGULATOR_DEBUG is not set -CONFIG_REGULATOR_DUMMY=y -# CONFIG_REGULATOR_FIXED_VOLTAGE is not set -# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set -# CONFIG_REGULATOR_BQ24022 is not set -# CONFIG_REGULATOR_MAX1586 is not set -# CONFIG_REGULATOR_MAX8649 is not set -# CONFIG_REGULATOR_MAX8660 is not set -# CONFIG_REGULATOR_MAX8952 is not set -CONFIG_REGULATOR_TWL4030=y -# CONFIG_REGULATOR_LP3971 is not set -# CONFIG_REGULATOR_LP3972 is not set -# CONFIG_REGULATOR_TPS65023 is not set -# CONFIG_REGULATOR_TPS6507X is not set -# CONFIG_REGULATOR_ISL6271A is not set -# CONFIG_REGULATOR_AD5398 is not set -CONFIG_MEDIA_SUPPORT=y - -# -# Multimedia core support -# -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_COMMON=y -CONFIG_VIDEO_ALLOW_V4L1=y -CONFIG_VIDEO_V4L1_COMPAT=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y -# CONFIG_DVB_CORE is not set -CONFIG_VIDEO_MEDIA=y - -# -# Multimedia drivers -# -# CONFIG_IR_CORE is not set -# CONFIG_MEDIA_ATTACH is not set -CONFIG_MEDIA_TUNER=y -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_MEDIA_TUNER_SIMPLE=y -CONFIG_MEDIA_TUNER_TDA8290=y -CONFIG_MEDIA_TUNER_TDA827X=y -CONFIG_MEDIA_TUNER_TDA18271=y -CONFIG_MEDIA_TUNER_TDA9887=y -CONFIG_MEDIA_TUNER_TEA5761=y -CONFIG_MEDIA_TUNER_TEA5767=y -CONFIG_MEDIA_TUNER_MT20XX=y -CONFIG_MEDIA_TUNER_XC2028=y -CONFIG_MEDIA_TUNER_XC5000=y -CONFIG_MEDIA_TUNER_MC44S803=y -CONFIG_VIDEO_V4L2=y -CONFIG_VIDEO_V4L1=y -CONFIG_VIDEOBUF_GEN=y -CONFIG_VIDEOBUF_DMA_CONTIG=y -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set - -# -# Encoders/decoders and other helper chips -# - -# -# Audio decoders -# -# CONFIG_VIDEO_TVAUDIO is not set -# CONFIG_VIDEO_TDA7432 is not set -# CONFIG_VIDEO_TDA9840 is not set -# CONFIG_VIDEO_TDA9875 is not set -# CONFIG_VIDEO_TEA6415C is not set -# CONFIG_VIDEO_TEA6420 is not set -# CONFIG_VIDEO_MSP3400 is not set -# CONFIG_VIDEO_CS5345 is not set -# CONFIG_VIDEO_CS53L32A is not set -# CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_WM8775 is not set -# CONFIG_VIDEO_WM8739 is not set -# CONFIG_VIDEO_VP27SMPX is not set - -# -# RDS decoders -# -# CONFIG_VIDEO_SAA6588 is not set - -# -# Video decoders -# -# CONFIG_VIDEO_ADV7180 is not set -# CONFIG_VIDEO_BT819 is not set -# CONFIG_VIDEO_BT856 is not set -# CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_OV7670 is not set -# CONFIG_VIDEO_MT9T001 is not set -CONFIG_VIDEO_MT9V011=y -# CONFIG_VIDEO_MT9V032 is not set -CONFIG_VIDEO_MT9V113=y -# CONFIG_VIDEO_MT9T111 is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_VIDEO_SAA7110 is not set -# CONFIG_VIDEO_SAA711X is not set -# CONFIG_VIDEO_SAA717X is not set -# CONFIG_VIDEO_SAA7191 is not set -# CONFIG_VIDEO_TVP514X is not set -# CONFIG_VIDEO_TVP5150 is not set -# CONFIG_VIDEO_TVP7002 is not set -# CONFIG_VIDEO_VPX3220 is not set - -# -# Video and audio decoders -# -# CONFIG_VIDEO_CX25840 is not set - -# -# MPEG video encoders -# -# CONFIG_VIDEO_CX2341X is not set - -# -# Video encoders -# -# CONFIG_VIDEO_SAA7127 is not set -# CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_ADV7170 is not set -# CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_THS7303 is not set -# CONFIG_VIDEO_ADV7343 is not set -# CONFIG_VIDEO_AK881X is not set - -# -# Video improvement chips -# -# CONFIG_VIDEO_UPD64031A is not set -# CONFIG_VIDEO_UPD64083 is not set -# CONFIG_VIDEO_VPSS_SYSTEM is not set -# CONFIG_VIDEO_VPFE_CAPTURE is not set -CONFIG_VIDEO_OMAP2_VOUT=y -# CONFIG_VIDEO_CPIA2 is not set -# CONFIG_VIDEO_SR030PC30 is not set -CONFIG_VIDEO_OMAP3=y -CONFIG_VIDEO_OMAP3_DEBUG=y -# CONFIG_SOC_CAMERA is not set -CONFIG_V4L_USB_DRIVERS=y -CONFIG_USB_VIDEO_CLASS=y -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -# CONFIG_USB_GSPCA is not set -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_HDPVR is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_PWC is not set -# CONFIG_USB_ZR364XX is not set -# CONFIG_USB_STKWEBCAM is not set -# CONFIG_USB_S2255 is not set -# CONFIG_V4L_MEM2MEM_DRIVERS is not set -# CONFIG_RADIO_ADAPTERS is not set -# CONFIG_DAB is not set - -# -# Graphics support -# -# CONFIG_DRM is not set -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -CONFIG_FB=y -CONFIG_FIRMWARE_EDID=y -# CONFIG_FB_DDC is not set -# CONFIG_FB_BOOT_VESA_SUPPORT is not set -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_TILEBLITTING=y - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_TMIO is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_MB862XX is not set -# CONFIG_FB_BROADSHEET is not set -# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -CONFIG_OMAP2_VRAM=y -CONFIG_OMAP2_VRFB=y -CONFIG_OMAP2_DSS=y -CONFIG_OMAP2_VRAM_SIZE=4 -CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y -# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set -CONFIG_OMAP2_DSS_DPI=y -# CONFIG_OMAP2_DSS_RFBI is not set -CONFIG_OMAP2_DSS_VENC=y -CONFIG_OMAP2_VENC_OUT_TYPE_SVIDEO=y -# CONFIG_OMAP2_VENC_OUT_TYPE_COMPOSITE is not set -# CONFIG_OMAP2_DSS_SDI is not set -CONFIG_OMAP2_DSS_DSI=y -CONFIG_OMAP2_DSS_USE_DSI_PLL=y -# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set -CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1 -CONFIG_FB_OMAP2=y -CONFIG_FB_OMAP2_DEBUG_SUPPORT=y -CONFIG_FB_OMAP2_NUM_FBS=1 - -# -# OMAP2/3 Display Device Drivers -# -CONFIG_PANEL_GENERIC=y -# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set -# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set -CONFIG_PANEL_SHARP_LS037V7DW01=y -# CONFIG_PANEL_SHARP_LQ043T1DG01 is not set -# CONFIG_PANEL_SAMSUNG_LMS700KF23 is not set -# CONFIG_PANEL_TAAL is not set -# CONFIG_PANEL_TOPPOLY_TDO35S is not set -# CONFIG_PANEL_TPO_TD043MTEA1 is not set -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=y -# CONFIG_LCD_L4F00242T03 is not set -# CONFIG_LCD_LMS283GF05 is not set -# CONFIG_LCD_LTV350QV is not set -# CONFIG_LCD_TDO24M is not set -# CONFIG_LCD_VGG2432A4 is not set -CONFIG_LCD_PLATFORM=y -# CONFIG_LCD_S6E63M0 is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_GENERIC=m -# CONFIG_BACKLIGHT_ADP8860 is not set - -# -# Display device support -# -CONFIG_DISPLAY_SUPPORT=y - -# -# Display hardware drivers -# - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_SOUND=y -# CONFIG_SOUND_OSS_CORE is not set -CONFIG_SND=y -CONFIG_SND_TIMER=y -CONFIG_SND_PCM=y -CONFIG_SND_HWDEP=y -CONFIG_SND_RAWMIDI=y -CONFIG_SND_JACK=y -# CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_PCM_OSS is not set -# CONFIG_SND_HRTIMER is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -CONFIG_SND_SUPPORT_OLD_API=y -CONFIG_SND_VERBOSE_PROCFS=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -# CONFIG_SND_RAWMIDI_SEQ is not set -# CONFIG_SND_OPL3_LIB_SEQ is not set -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set -# CONFIG_SND_EMU10K1_SEQ is not set -CONFIG_SND_DRIVERS=y -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_ALOOP is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set -CONFIG_SND_ARM=y -CONFIG_SND_SPI=y -CONFIG_SND_USB=y -CONFIG_SND_USB_AUDIO=y -# CONFIG_SND_USB_UA101 is not set -# CONFIG_SND_USB_CAIAQ is not set -CONFIG_SND_SOC=y -CONFIG_SND_OMAP_SOC=y -CONFIG_SND_OMAP_SOC_MCBSP=y -CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y -CONFIG_SND_SOC_I2C_AND_SPI=y -# CONFIG_SND_SOC_ALL_CODECS is not set -CONFIG_SND_SOC_TWL4030=y -# CONFIG_SND_SOC_WL1271BT is not set -# CONFIG_SOUND_PRIME is not set -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HIDRAW is not set - -# -# USB Input Devices -# -CONFIG_USB_HID=y -# CONFIG_HID_PID is not set -# CONFIG_USB_HIDDEV is not set - -# -# Special HID drivers -# -# CONFIG_HID_3M_PCT is not set -# CONFIG_HID_A4TECH is not set -# CONFIG_HID_ACRUX_FF is not set -# CONFIG_HID_APPLE is not set -# CONFIG_HID_BELKIN is not set -# CONFIG_HID_CANDO is not set -# CONFIG_HID_CHERRY is not set -# CONFIG_HID_CHICONY is not set -# CONFIG_HID_PRODIKEYS is not set -# CONFIG_HID_CYPRESS is not set -# CONFIG_HID_DRAGONRISE is not set -# CONFIG_HID_EGALAX is not set -# CONFIG_HID_EZKEY is not set -# CONFIG_HID_KYE is not set -# CONFIG_HID_UCLOGIC is not set -# CONFIG_HID_WALTOP is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID_TWINHAN is not set -# CONFIG_HID_KENSINGTON is not set -# CONFIG_HID_LOGITECH is not set -# CONFIG_HID_MICROSOFT is not set -# CONFIG_HID_MOSART is not set -# CONFIG_HID_MONTEREY is not set -# CONFIG_HID_NTRIG is not set -# CONFIG_HID_ORTEK is not set -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PETALYNX is not set -# CONFIG_HID_PICOLCD is not set -# CONFIG_HID_QUANTA is not set -# CONFIG_HID_ROCCAT is not set -# CONFIG_HID_ROCCAT_KONE is not set -# CONFIG_HID_ROCCAT_PYRA is not set -# CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SONY is not set -# CONFIG_HID_STANTUM is not set -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_GREENASIA is not set -# CONFIG_HID_SMARTJOYPLUS is not set -# CONFIG_HID_TOPSEED is not set -# CONFIG_HID_THRUSTMASTER is not set -# CONFIG_HID_ZEROPLUS is not set -# CONFIG_HID_ZYDACRON is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - -# -# Miscellaneous USB options -# -# CONFIG_USB_DEVICEFS is not set -# CONFIG_USB_DEVICE_CLASS is not set -# CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y -CONFIG_USB_OTG=y -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -CONFIG_USB_MON=y -# CONFIG_USB_WUSB is not set -# CONFIG_USB_WUSB_CBAF is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_C67X00_HCD is not set -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -CONFIG_USB_EHCI_TT_NEWSCHED=y -# CONFIG_USB_OXU210HP_HCD is not set -# CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set -# CONFIG_USB_ISP1362_HCD is not set -# CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_R8A66597_HCD is not set -# CONFIG_USB_HWA_HCD is not set -CONFIG_USB_MUSB_HDRC=y - -# -# Platform Glue Layer -# -# CONFIG_USB_MUSB_TUSB6010_GLUE is not set -CONFIG_USB_MUSB_OMAP2PLUS_GLUE=y -# CONFIG_USB_MUSB_AM35X_GLUE is not set -# CONFIG_USB_MUSB_DAVINCI is not set -# CONFIG_USB_MUSB_DA8XX is not set -# CONFIG_USB_MUSB_TUSB6010 is not set -CONFIG_USB_MUSB_OMAP2PLUS=y -# CONFIG_USB_MUSB_AM35X is not set -# CONFIG_USB_MUSB_TI81XX is not set -# CONFIG_USB_MUSB_BLACKFIN is not set -# CONFIG_USB_MUSB_UX500 is not set -# CONFIG_USB_MUSB_HOST is not set -# CONFIG_USB_MUSB_PERIPHERAL is not set -CONFIG_USB_MUSB_OTG=y -CONFIG_USB_GADGET_MUSB_HDRC=y -CONFIG_USB_MUSB_HDRC_HCD=y -# CONFIG_MUSB_PIO_ONLY is not set -CONFIG_USB_INVENTRA_DMA_HW=y -# CONFIG_USB_TI_CPPI_DMA_HW is not set -# CONFIG_USB_TI_CPPI41_DMA_HW is not set -CONFIG_USB_INVENTRA_DMA=y -CONFIG_MUSB_USE_SYSTEM_DMA_WORKAROUND=y -# CONFIG_USB_TI_CPPI_DMA is not set -# CONFIG_USB_TI_CPPI41_DMA is not set -# CONFIG_USB_TUSB_OMAP_DMA is not set -# CONFIG_USB_MUSB_DEBUG is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set -# CONFIG_USB_TMC is not set - -# -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info -# -CONFIG_USB_STORAGE=y -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_USBAT is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_ALAUDA is not set -# CONFIG_USB_STORAGE_ONETOUCH is not set -# CONFIG_USB_STORAGE_KARMA is not set -# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set -# CONFIG_USB_UAS is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set - -# -# USB port drivers -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_ADUTUX is not set -# CONFIG_USB_SEVSEG is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_FTDI_ELAN is not set -# CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_IOWARRIOR is not set -# CONFIG_USB_TEST is not set -# CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_YUREX is not set -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_DEBUG_FILES is not set -# CONFIG_USB_GADGET_DEBUG_FS is not set -CONFIG_USB_GADGET_VBUS_DRAW=2 -CONFIG_USB_GADGET_SELECTED=y -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_USB_GADGET_R8A66597 is not set -# CONFIG_USB_GADGET_M66592 is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -CONFIG_USB_GADGET_DUALSPEED=y -# CONFIG_USB_ZERO is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FUNCTIONFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_MASS_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_G_PRINTER is not set -CONFIG_USB_ANDROID=y -# CONFIG_USB_ANDROID_ACM is not set -CONFIG_USB_ANDROID_ADB=y -CONFIG_USB_ANDROID_MASS_STORAGE=y -# CONFIG_USB_ANDROID_MTP is not set -# CONFIG_USB_ANDROID_RNDIS is not set -# CONFIG_USB_CDC_COMPOSITE is not set -# CONFIG_USB_G_MULTI is not set -# CONFIG_USB_G_HID is not set -# CONFIG_USB_G_DBGP is not set -# CONFIG_USB_G_WEBCAM is not set - -# -# OTG and related infrastructure -# -CONFIG_USB_OTG_UTILS=y -# CONFIG_USB_GPIO_VBUS is not set -# CONFIG_ISP1301_OMAP is not set -# CONFIG_USB_ULPI is not set -CONFIG_TWL4030_USB=y -# CONFIG_NOP_USB_XCEIV is not set -CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set -CONFIG_MMC_UNSAFE_RESUME=y -# CONFIG_MMC_EMBEDDED_SDIO is not set -# CONFIG_MMC_PARANOID_SD_INIT is not set - -# -# MMC/SD/SDIO Card Drivers -# -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_MMC_BLOCK_BOUNCE=y -# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set -CONFIG_SDIO_UART=y -# CONFIG_MMC_TEST is not set - -# -# MMC/SD/SDIO Host Controller Drivers -# -# CONFIG_MMC_SDHCI is not set -CONFIG_MMC_OMAP=y -CONFIG_MMC_OMAP_HS=y -# CONFIG_MMC_SPI is not set -# CONFIG_MMC_USHC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -CONFIG_SWITCH=y -# CONFIG_SWITCH_GPIO is not set -# CONFIG_ACCESSIBILITY is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set - -# -# RTC interfaces -# -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -CONFIG_RTC_INTF_ALARM=y -CONFIG_RTC_INTF_ALARM_DEV=y -# CONFIG_RTC_DRV_TEST is not set - -# -# I2C RTC drivers -# -# CONFIG_RTC_DRV_DS1307 is not set -# CONFIG_RTC_DRV_DS1374 is not set -# CONFIG_RTC_DRV_DS1672 is not set -# CONFIG_RTC_DRV_DS3232 is not set -# CONFIG_RTC_DRV_MAX6900 is not set -# CONFIG_RTC_DRV_RS5C372 is not set -# CONFIG_RTC_DRV_ISL1208 is not set -# CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_X1205 is not set -# CONFIG_RTC_DRV_PCF8563 is not set -# CONFIG_RTC_DRV_PCF8583 is not set -# CONFIG_RTC_DRV_M41T80 is not set -# CONFIG_RTC_DRV_BQ32K is not set -CONFIG_RTC_DRV_TWL4030=y -# CONFIG_RTC_DRV_S35390A is not set -# CONFIG_RTC_DRV_FM3130 is not set -# CONFIG_RTC_DRV_RX8581 is not set -# CONFIG_RTC_DRV_RX8025 is not set - -# -# SPI RTC drivers -# -# CONFIG_RTC_DRV_M41T94 is not set -# CONFIG_RTC_DRV_DS1305 is not set -# CONFIG_RTC_DRV_DS1390 is not set -# CONFIG_RTC_DRV_MAX6902 is not set -# CONFIG_RTC_DRV_R9701 is not set -# CONFIG_RTC_DRV_RS5C348 is not set -# CONFIG_RTC_DRV_DS3234 is not set -# CONFIG_RTC_DRV_PCF2123 is not set - -# -# Platform RTC drivers -# -# CONFIG_RTC_DRV_CMOS is not set -# CONFIG_RTC_DRV_DS1286 is not set -# CONFIG_RTC_DRV_DS1511 is not set -# CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_DS1742 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set -# CONFIG_RTC_DRV_M48T86 is not set -# CONFIG_RTC_DRV_M48T35 is not set -# CONFIG_RTC_DRV_M48T59 is not set -# CONFIG_RTC_DRV_MSM6242 is not set -# CONFIG_RTC_DRV_BQ4802 is not set -# CONFIG_RTC_DRV_RP5C01 is not set -# CONFIG_RTC_DRV_V3020 is not set - -# -# on-CPU RTC drivers -# -# CONFIG_DMADEVICES is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set -CONFIG_STAGING=y -# CONFIG_STAGING_EXCLUDE_BUILD is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_USB_IP_COMMON is not set -# CONFIG_ECHO is not set -# CONFIG_BRCM80211 is not set -# CONFIG_RT2870 is not set -# CONFIG_COMEDI is not set -# CONFIG_ASUS_OLED is not set -# CONFIG_R8712U is not set -# CONFIG_TRANZPORT is not set - -# -# Android -# -CONFIG_ANDROID=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_ANDROID_LOGGER=y -CONFIG_ANDROID_RAM_CONSOLE=y -CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y -CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y -CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE=128 -CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE=16 -CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE=8 -CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d -# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set -CONFIG_ANDROID_TIMED_OUTPUT=y -CONFIG_ANDROID_TIMED_GPIO=y -CONFIG_ANDROID_LOW_MEMORY_KILLER=y -# CONFIG_POHMELFS is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_LINE6_USB is not set -# CONFIG_VT6656 is not set -# CONFIG_FB_UDL is not set -# CONFIG_IIO is not set -# CONFIG_ZRAM is not set -# CONFIG_BATMAN_ADV is not set -# CONFIG_FB_SM7XX is not set - -# -# Texas Instruments shared transport line discipline -# -# CONFIG_ADIS16255 is not set -# CONFIG_SMB_FS is not set -# CONFIG_EASYCAP is not set -# CONFIG_TIDSPBRIDGE is not set -# CONFIG_WESTBRIDGE is not set -CONFIG_WESTBRIDGE_HAL_SELECTED=y -CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y -# CONFIG_MACH_NO_WESTBRIDGE is not set -# CONFIG_ATH6K_LEGACY is not set -# CONFIG_USB_ENESTORAGE is not set -# CONFIG_BCM_WIMAX is not set -# CONFIG_FT1000 is not set - -# -# Speakup console speech -# -# CONFIG_SPEAKUP is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_DEFAULTS_TO_ORDERED=y -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_XATTR=y -# CONFIG_EXT4_FS_POSIX_ACL is not set -# CONFIG_EXT4_FS_SECURITY is not set -# CONFIG_EXT4_DEBUG is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set -CONFIG_FILE_LOCKING=y -CONFIG_FSNOTIFY=y -CONFIG_DNOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_FANOTIFY is not set -CONFIG_QUOTA=y -# CONFIG_QUOTA_NETLINK_INTERFACE is not set -CONFIG_PRINT_QUOTA_WARNING=y -# CONFIG_QUOTA_DEBUG is not set -CONFIG_QUOTA_TREE=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -CONFIG_QUOTACTL=y -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set -CONFIG_MISC_FILESYSTEMS=y -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_ECRYPT_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_YAFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -CONFIG_JFFS2_SUMMARY=y -CONFIG_JFFS2_FS_XATTR=y -CONFIG_JFFS2_FS_POSIX_ACL=y -CONFIG_JFFS2_FS_SECURITY=y -CONFIG_JFFS2_COMPRESSION_OPTIONS=y -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_LZO=y -CONFIG_JFFS2_RTIME=y -CONFIG_JFFS2_RUBIN=y -# CONFIG_JFFS2_CMODE_NONE is not set -CONFIG_JFFS2_CMODE_PRIORITY=y -# CONFIG_JFFS2_CMODE_SIZE is not set -# CONFIG_JFFS2_CMODE_FAVOURLZO is not set -# CONFIG_LOGFS is not set -CONFIG_CRAMFS=y -# CONFIG_SQUASHFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_OMFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -# CONFIG_NFS_V4_1 is not set -CONFIG_ROOT_NFS=y -CONFIG_NFS_USE_LEGACY_DNS=y -# CONFIG_NFS_USE_NEW_IDMAPPER is not set -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_NFS_ACL_SUPPORT=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -CONFIG_SUNRPC_GSS=y -CONFIG_RPCSEC_GSS_KRB5=y -# CONFIG_CEPH_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -# CONFIG_EFI_PARTITION is not set -# CONFIG_SYSV68_PARTITION is not set -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set -# CONFIG_DLM is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_FRAME_WARN=1024 -CONFIG_MAGIC_SYSRQ=y -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_KERNEL is not set -# CONFIG_HARDLOCKUP_DETECTOR is not set -CONFIG_BKL=y -# CONFIG_SPARSE_RCU_POINTER is not set -CONFIG_STACKTRACE=y -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_MEMORY_INIT is not set -CONFIG_FRAME_POINTER=y -# CONFIG_LKDTM is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_NOP_TRACER=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y -CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y -CONFIG_TRACING_SUPPORT=y -CONFIG_FTRACE=y -# CONFIG_FUNCTION_TRACER is not set -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_ENABLE_DEFAULT_TRACERS is not set -CONFIG_BRANCH_PROFILE_NONE=y -# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set -# CONFIG_PROFILE_ALL_BRANCHES is not set -# CONFIG_STACK_TRACER is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -CONFIG_KPROBE_EVENT=y -# CONFIG_RING_BUFFER_BENCHMARK is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_STRICT_DEVMEM is not set -# CONFIG_ARM_UNWIND is not set -# CONFIG_DEBUG_USER is not set -# CONFIG_OC_ETM is not set - -# -# Security options -# -CONFIG_KEYS=y -# CONFIG_KEYS_DEBUG_PROC_KEYS is not set -# CONFIG_SECURITY_DMESG_RESTRICT is not set -CONFIG_SECURITY=y -# CONFIG_SECURITYFS is not set -# CONFIG_SECURITY_NETWORK is not set -# CONFIG_SECURITY_PATH is not set -# CONFIG_SECURITY_TOMOYO is not set -# CONFIG_SECURITY_APPARMOR is not set -# CONFIG_IMA is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ALGAPI2=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_PCOMP2=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set -CONFIG_CRYPTO_WORKQUEUE=y -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_XTS is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_VMAC is not set - -# -# Digest -# -CONFIG_CRYPTO_CRC32C=y -# CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=y -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set - -# -# Ciphers -# -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -CONFIG_CRYPTO_DES=y -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_TEA is not set -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_TWOFISH_COMMON=y - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set - -# -# Random Number Generation -# -# CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRYPTO_HW=y -# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set -# CONFIG_CRYPTO_DEV_OMAP_AES is not set -CONFIG_BINARY_PRINTF=y - -# -# Library routines -# -CONFIG_BITREVERSE=y -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_CRC_CCITT=y -# CONFIG_CRC16 is not set -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -CONFIG_LIBCRC32C=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_DECOMPRESS_GZIP=y -CONFIG_REED_SOLOMON=y -CONFIG_REED_SOLOMON_ENC8=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_NLATTR=y diff --git a/kernel/arch/arm/configs/panda_defconfig b/kernel/arch/arm/configs/panda_defconfig deleted file mode 100644 index 4c5e56c56cf6..000000000000 --- a/kernel/arch/arm/configs/panda_defconfig +++ /dev/null @@ -1,331 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_CGROUPS=y -CONFIG_CGROUP_DEBUG=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_SCHED=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_KALLSYMS_ALL=y -CONFIG_PANIC_TIMEOUT=5 -CONFIG_ASHMEM=y -# CONFIG_AIO is not set -CONFIG_EMBEDDED=y -# CONFIG_SLUB_DEBUG is not set -CONFIG_MODULES=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_ARCH_OMAP=y -CONFIG_OMAP_RESET_CLOCKS=y -# CONFIG_ARCH_OMAP2 is not set -# CONFIG_ARCH_OMAP3 is not set -# CONFIG_MACH_OMAP_4430SDP is not set -CONFIG_ARM_THUMBEE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_SMP=y -# CONFIG_SMP_ON_UP is not set -CONFIG_NR_CPUS=2 -CONFIG_PREEMPT=y -CONFIG_CMDLINE="console=ttyO2,115200n8 mem=1G androidboot.console=ttyO2" -CONFIG_CMDLINE_EXTEND=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_IDLE=y -CONFIG_OMAP_SMARTREFLEX=y -CONFIG_OMAP_SMARTREFLEX_CLASS1P5=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_BINFMT_MISC=y -CONFIG_WAKELOCK=y -CONFIG_PM_DEBUG=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_INET_ESP=y -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -CONFIG_INET6_AH=y -CONFIG_INET6_ESP=y -CONFIG_INET6_IPCOMP=y -CONFIG_IPV6_MIP6=y -CONFIG_IPV6_TUNNEL=y -CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_NETFILTER=y -CONFIG_NETFILTER_NETLINK_LOG=y -CONFIG_NETFILTER_TPROXY=y -CONFIG_NF_CONNTRACK=y -CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CT_PROTO_DCCP=y -CONFIG_NF_CT_PROTO_SCTP=y -CONFIG_NF_CT_PROTO_UDPLITE=y -CONFIG_NF_CONNTRACK_AMANDA=y -CONFIG_NF_CONNTRACK_FTP=y -CONFIG_NF_CONNTRACK_H323=y -CONFIG_NF_CONNTRACK_IRC=y -CONFIG_NF_CONNTRACK_NETBIOS_NS=y -CONFIG_NF_CONNTRACK_PPTP=y -CONFIG_NF_CONNTRACK_SANE=y -CONFIG_NF_CONNTRACK_TFTP=y -CONFIG_NF_CT_NETLINK=y -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y -CONFIG_NETFILTER_XT_TARGET_CONNMARK=y -CONFIG_NETFILTER_XT_TARGET_MARK=y -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -CONFIG_NETFILTER_XT_MATCH_COMMENT=y -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y -CONFIG_NETFILTER_XT_MATCH_CONNMARK=y -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -CONFIG_NETFILTER_XT_MATCH_HELPER=y -CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -CONFIG_NETFILTER_XT_MATCH_LENGTH=y -CONFIG_NETFILTER_XT_MATCH_LIMIT=y -CONFIG_NETFILTER_XT_MATCH_MAC=y -CONFIG_NETFILTER_XT_MATCH_MARK=y -CONFIG_NETFILTER_XT_MATCH_POLICY=y -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y -CONFIG_NETFILTER_XT_MATCH_QTAGUID=y -CONFIG_NETFILTER_XT_MATCH_QUOTA=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y -CONFIG_NETFILTER_XT_MATCH_SOCKET=y -CONFIG_NETFILTER_XT_MATCH_STATE=y -CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -CONFIG_NETFILTER_XT_MATCH_STRING=y -CONFIG_NETFILTER_XT_MATCH_TIME=y -CONFIG_NETFILTER_XT_MATCH_U32=y -CONFIG_NF_CONNTRACK_IPV4=y -CONFIG_NF_CONNTRACK_IPV6=y -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_AH=y -CONFIG_IP_NF_MATCH_ECN=y -CONFIG_IP_NF_MATCH_TTL=y -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_TARGET_REJECT_SKERR=y -CONFIG_IP_NF_TARGET_LOG=y -CONFIG_NF_NAT=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_NETMAP=y -CONFIG_IP_NF_TARGET_REDIRECT=y -CONFIG_IP_NF_RAW=y -CONFIG_IP_NF_ARPTABLES=y -CONFIG_IP_NF_ARPFILTER=y -CONFIG_IP_NF_ARP_MANGLE=y -CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_TARGET_LOG=y -CONFIG_IP6_NF_FILTER=y -CONFIG_IP6_NF_TARGET_REJECT=y -CONFIG_IP6_NF_TARGET_REJECT_SKERR=y -CONFIG_IP6_NF_MANGLE=y -CONFIG_IP6_NF_RAW=y -CONFIG_PHONET=y -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_HTB=y -CONFIG_NET_SCH_INGRESS=y -CONFIG_NET_CLS_U32=y -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_U32=y -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_POLICE=y -CONFIG_NET_ACT_GACT=y -CONFIG_NET_ACT_MIRRED=y -CONFIG_BT=y -CONFIG_BT_BNEP=y -CONFIG_BT_L2CAP=y -CONFIG_BT_SCO=y -CONFIG_BT_RFCOMM=y -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_HCIUART=y -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_WILINK=y -CONFIG_RFKILL=y -CONFIG_RFKILL_INPUT=y -CONFIG_MTD=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_NAND_IDS=y -CONFIG_MTD_ONENAND=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_MISC_DEVICES=y -# CONFIG_ANDROID_PMEM is not set -CONFIG_KERNEL_DEBUGGER_CORE=y -CONFIG_UID_STAT=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_SG=y -CONFIG_MD=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_DEBUG=y -CONFIG_DM_CRYPT=y -CONFIG_DM_UEVENT=y -CONFIG_NETDEVICES=y -CONFIG_IFB=y -CONFIG_USB_USBNET=y -CONFIG_USB_NET_SMSC95XX=y -CONFIG_PPP=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_MPPE=y -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_KEYRESET=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y -CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y -CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_KEYCHORD=y -CONFIG_INPUT_UINPUT=y -CONFIG_INPUT_GPIO=y -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_HW_RANDOM=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_GPIO=y -CONFIG_SPI=y -CONFIG_SPI_GPIO=y -CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_TWL4030=y -CONFIG_POWER_SUPPLY=y -# CONFIG_HWMON is not set -CONFIG_TWL6030_PWM=y -CONFIG_REGULATOR_TWL4030=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_PVR_SGX=y -CONFIG_PVR_NEED_PVR_DPF=y -CONFIG_PVR_NEED_PVR_ASSERT=y -CONFIG_PVR_USSE_EDM_STATUS_DEBUG=y -CONFIG_FB=y -CONFIG_OMAP2_DSS=y -# CONFIG_OMAP2_DSS_VENC is not set -CONFIG_FB_OMAP2=y -CONFIG_FB_OMAP2_NUM_FBS=2 -CONFIG_OMAP2_VRAM_SIZE=16 -CONFIG_PANEL_GENERIC_DPI=y -CONFIG_DISPLAY_SUPPORT=y -CONFIG_USB=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_DEVICEFS=y -CONFIG_USB_SUSPEND=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_MUSB_HDRC=y -CONFIG_USB_MUSB_OMAP2PLUS=y -CONFIG_USB_MUSB_PERIPHERAL=y -CONFIG_USB_GADGET_MUSB_HDRC=y -CONFIG_USB_ACM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_SERIAL=y -CONFIG_USB_SERIAL_KEYSPAN=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA28=y -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -CONFIG_USB_SERIAL_KEYSPAN_USA19=y -CONFIG_USB_SERIAL_KEYSPAN_USA18X=y -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_VBUS_DRAW=500 -CONFIG_USB_G_ANDROID=y -CONFIG_MMC=y -CONFIG_MMC_UNSAFE_RESUME=y -CONFIG_MMC_EMBEDDED_SDIO=y -CONFIG_MMC_PARANOID_SD_INIT=y -CONFIG_MMC_OMAP=y -CONFIG_MMC_OMAP_HS=y -CONFIG_SWITCH=y -CONFIG_SWITCH_GPIO=y -CONFIG_RTC_CLASS=y -CONFIG_STAGING=y -CONFIG_ANDROID=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_ANDROID_LOGGER=y -CONFIG_ANDROID_RAM_CONSOLE=y -CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y -CONFIG_ANDROID_TIMED_GPIO=y -CONFIG_ANDROID_LOW_MEMORY_KILLER=y -CONFIG_EXT2_FS=y -CONFIG_EXT4_FS=y -# CONFIG_EXT4_FS_XATTR is not set -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_PARTITION_ADVANCED=y -CONFIG_EFI_PARTITION=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -CONFIG_PRINTK_TIME=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y -CONFIG_DETECT_HUNG_TASK=y -# CONFIG_DEBUG_PREEMPT is not set -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y -CONFIG_DEBUG_INFO=y -CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_ARM_UNWIND is not set -CONFIG_DEBUG_USER=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRC_CCITT=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_SOC=y -CONFIG_SND_OMAP_SOC=y -CONFIG_SND_OMAP_SOC_SDP4430=y -CONFIG_SND_OMAP_SOC_OMAP4_HDMI=y -CONFIG_OMAP_HSI=y -CONFIG_OMAP_HSI_DEVICE=y -CONFIG_CFG80211=y -CONFIG_NL80211_TESTMODE=y -CONFIG_LIB80211=y -CONFIG_MAC80211=y -CONFIG_MAC80211_LEDS=y -CONFIG_MAC80211_DEBUGFS=y -CONFIG_USB_ZD1201=y -CONFIG_WL12XX_MENU=y -CONFIG_WL12XX=y -CONFIG_WL12XX_SDIO=y -CONFIG_CRYPTO_PCBC=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_SHA256=y -CONFIG_OMAP_TEMP_SENSOR=y -CONFIG_OMAP_DIE_TEMP_SENSOR=y -CONFIG_TI_ST=y -CONFIG_KEYBOARD_GPIO=y diff --git a/kernel/arch/arm/mach-omap2/board-omap3beagle.c b/kernel/arch/arm/mach-omap2/board-omap3beagle.c deleted file mode 100644 index b3d1b81b2a2e..000000000000 --- a/kernel/arch/arm/mach-omap2/board-omap3beagle.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/board-omap3beagle.c - * - * Copyright (C) 2008 Texas Instruments - * - * Modified from mach-omap2/board-3430sdp.c - * - * Initial code: Syed Mohammed Khasim - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/leds.h> -#include <linux/gpio.h> -#include <linux/input.h> -#include <linux/gpio_keys.h> - -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/nand.h> -#include <linux/mmc/host.h> - -#include <linux/usb/android_composite.h> - -#include <linux/regulator/machine.h> -#include <linux/i2c/twl.h> - -#include <mach/hardware.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/flash.h> - -#include <plat/board.h> -#include <plat/common.h> -#include <plat/display.h> -#include <plat/gpmc.h> -#include <plat/nand.h> -#include <plat/usb.h> - -#include "mux.h" -#include "hsmmc.h" -#include "timer-gp.h" -#include "board-flash.h" - -#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 -#include <linux/input/synaptics_dsx.h> - -#define TM_SAMPLE1 (1) // 2D only -#define TM_SAMPLE2 (2) // 2D + 0D x 2 -#define TM_SAMPLE3 (3) // 2D + 0D x 4 -#define SYNAPTICS_MODULE TM_SAMPLE1 -#endif - -#define NAND_BLOCK_SIZE SZ_128K - -#ifdef CONFIG_USB_ANDROID -#define GOOGLE_VENDOR_ID 0x18d1 -#define GOOGLE_PRODUCT_ID 0x9018 -#define GOOGLE_ADB_PRODUCT_ID 0x9015 -#endif - -/* Synaptics Thin Driver */ -#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 -static int synaptics_gpio_setup(unsigned gpio, bool configure) -{ - int retval=0; - if (configure) - { - retval = gpio_request(gpio, "rmi4_attn"); - if (retval) { - pr_err("%s: Failed to get attn gpio %d. Code: %d.", - __func__, gpio, retval); - return retval; - } - omap_mux_init_signal("sdmmc2_clk.gpio_130", OMAP_PIN_INPUT_PULLUP); - - retval = gpio_direction_input(gpio); - if (retval) { - pr_err("%s: Failed to setup attn gpio %d. Code: %d.", - __func__, gpio, retval); - gpio_free(gpio); - } - } else { - pr_warn("%s: No way to deconfigure gpio %d.", - __func__, gpio); - } - - return retval; -} - - #if (SYNAPTICS_MODULE == TM_SAMPLE1) -#define TM_SAMPLE1_ADDR 0x20 -#define TM_SAMPLE1_ATTN 130 - -static unsigned char TM_SAMPLE1_f1a_button_codes[] = {}; - -static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE1_capacitance_button_map = { - .nbuttons = ARRAY_SIZE(TM_SAMPLE1_f1a_button_codes), - .map = TM_SAMPLE1_f1a_button_codes, -}; - -static struct synaptics_rmi4_platform_data rmi4_platformdata = { - .irq_flags = IRQF_TRIGGER_FALLING, - .irq_gpio = TM_SAMPLE1_ATTN, - .gpio_config = synaptics_gpio_setup, - .capacitance_button_map = &TM_SAMPLE1_capacitance_button_map, -}; - -static struct i2c_board_info bus2_i2c_devices[] = { - { - I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE1_ADDR), - .platform_data = &rmi4_platformdata, - }, -}; - -#elif (SYNAPTICS_MODULE == TM_SAMPLE2) -#define TM_SAMPLE2_ADDR 0x20 -#define TM_SAMPLE2_ATTN 130 - -static unsigned char TM_SAMPLE2_f1a_button_codes[] = {KEY_MENU, KEY_BACK}; - -static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE2_capacitance_button_map = { - .nbuttons = ARRAY_SIZE(TM_SAMPLE2_f1a_button_codes), - .map = TM_SAMPLE2_f1a_button_codes, -}; - -static struct synaptics_rmi4_platform_data rmi4_platformdata = { - .irq_flags = IRQF_TRIGGER_FALLING, - .irq_gpio = TM_SAMPLE2_ATTN, - .gpio_config = synaptics_gpio_setup, - .capacitance_button_map = &TM_SAMPLE2_capacitance_button_map, -}; - -static struct i2c_board_info bus2_i2c_devices[] = { - { - I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE2_ADDR), - .platform_data = &rmi4_platformdata, - }, -}; - -#elif (SYNAPTICS_MODULE == TM_SAMPLE3) -#define TM_SAMPLE3_ADDR 0x20 -#define TM_SAMPLE3_ATTN 130 - -static unsigned char TM_SAMPLE3_f1a_button_codes[] = {KEY_MENU, KEY_HOME,KEY_BACK,KEY_SEARCH}; - -static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE3_capacitance_button_map = { - .nbuttons = ARRAY_SIZE(TM_SAMPLE3_f1a_button_codes), - .map = TM_SAMPLE3_f1a_button_codes, -}; - -static struct synaptics_rmi4_platform_data rmi4_platformdata = { - .irq_flags = IRQF_TRIGGER_FALLING, - .irq_gpio = TM_SAMPLE3_ATTN, - .gpio_config = synaptics_gpio_setup, - .capacitance_button_map = &TM_SAMPLE3_capacitance_button_map, -}; - -static struct i2c_board_info bus2_i2c_devices[] = { - { - I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE3_ADDR), - .platform_data = &rmi4_platformdata, - }, -}; -#endif - -void __init i2c_device_setup(void) -{ - pr_info(">>>>I2C device setup."); - if (ARRAY_SIZE(bus2_i2c_devices)) { - i2c_register_board_info(2, bus2_i2c_devices, - ARRAY_SIZE(bus2_i2c_devices)); - } -} - -/* End of Synaptics change for beagle board */ - -static char *usb_functions_adb[] = { - "adb", -}; - -static char *usb_functions_mass_storage[] = { - "usb_mass_storage", -}; -static char *usb_functions_ums_adb[] = { - "usb_mass_storage", - "adb", -}; - -static char *usb_functions_all[] = { - "adb", "usb_mass_storage", -}; - -static struct android_usb_product usb_products[] = { - { - .product_id = GOOGLE_PRODUCT_ID, - .num_functions = ARRAY_SIZE(usb_functions_adb), - .functions = usb_functions_adb, - }, - { - .product_id = GOOGLE_PRODUCT_ID, - .num_functions = ARRAY_SIZE(usb_functions_mass_storage), - .functions = usb_functions_mass_storage, - }, - { - .product_id = GOOGLE_PRODUCT_ID, - .num_functions = ARRAY_SIZE(usb_functions_ums_adb), - .functions = usb_functions_ums_adb, - }, -}; - -static struct usb_mass_storage_platform_data mass_storage_pdata = { - .nluns = 1, - .vendor = "rowboat", - .product = "rowboat gadget", - .release = 0x100, -}; - -static struct platform_device usb_mass_storage_device = { - .name = "usb_mass_storage", - .id = -1, - .dev = { - .platform_data = &mass_storage_pdata, - }, -}; - -static struct android_usb_platform_data android_usb_pdata = { - .vendor_id = GOOGLE_VENDOR_ID, - .product_id = GOOGLE_PRODUCT_ID, - .functions = usb_functions_all, - .products = usb_products, - .num_products = ARRAY_SIZE(usb_products), - .version = 0x0100, - .product_name = "rowboat gadget", - .manufacturer_name = "rowboat", - .serial_number = "20100720", - .num_functions = ARRAY_SIZE(usb_functions_all), -}; - -static struct platform_device androidusb_device = { - .name = "android_usb", - .id = -1, - .dev = { - .platform_data = &android_usb_pdata, - }, -}; - -static void omap3beagle_android_gadget_init(void) -{ - platform_device_register(&androidusb_device); -} -#endif -/* - * OMAP3 Beagle revision - * Run time detection of Beagle revision is done by reading GPIO. - * GPIO ID - - * AXBX = GPIO173, GPIO172, GPIO171: 1 1 1 - * C1_3 = GPIO173, GPIO172, GPIO171: 1 1 0 - * C4 = GPIO173, GPIO172, GPIO171: 1 0 1 - * XM = GPIO173, GPIO172, GPIO171: 0 0 0 - */ -enum { - OMAP3BEAGLE_BOARD_UNKN = 0, - OMAP3BEAGLE_BOARD_AXBX, - OMAP3BEAGLE_BOARD_C1_3, - OMAP3BEAGLE_BOARD_C4, - OMAP3BEAGLE_BOARD_XM, - OMAP3BEAGLE_BOARD_XMC, -}; - -extern void omap_pm_sys_offmode_select(int); -extern void omap_pm_sys_offmode_pol(int); -extern void omap_pm_sys_clkreq_pol(int); -extern void omap_pm_auto_off(int); -extern void omap_pm_auto_ret(int); - -static u8 omap3_beagle_version; - -static u8 omap3_beagle_get_rev(void) -{ - return omap3_beagle_version; -} - -/** - * Board specific initialization of PM components - */ -static void __init omap3_beagle_pm_init(void) -{ - /* Use sys_offmode signal */ - omap_pm_sys_offmode_select(1); - - /* sys_clkreq - active high */ - omap_pm_sys_clkreq_pol(1); - - /* sys_offmode - active low */ - omap_pm_sys_offmode_pol(0); - - /* Automatically send OFF command */ - omap_pm_auto_off(1); - - /* Automatically send RET command */ - omap_pm_auto_ret(1); -} - -static void __init omap3_beagle_init_rev(void) -{ - int ret; - u16 beagle_rev = 0; - - omap_mux_init_gpio(171, OMAP_PIN_INPUT_PULLUP); - omap_mux_init_gpio(172, OMAP_PIN_INPUT_PULLUP); - omap_mux_init_gpio(173, OMAP_PIN_INPUT_PULLUP); - - ret = gpio_request(171, "rev_id_0"); - if (ret < 0) - goto fail0; - - ret = gpio_request(172, "rev_id_1"); - if (ret < 0) - goto fail1; - - ret = gpio_request(173, "rev_id_2"); - if (ret < 0) - goto fail2; - - gpio_direction_input(171); - gpio_direction_input(172); - gpio_direction_input(173); - - beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1) - | (gpio_get_value(173) << 2); - - switch (beagle_rev) { - case 7: - printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n"); - omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX; - break; - case 6: - printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n"); - omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3; - break; - case 5: - printk(KERN_INFO "OMAP3 Beagle Rev: C4\n"); - omap3_beagle_version = OMAP3BEAGLE_BOARD_C4; - break; - case 2: - printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n"); - omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC; - break; - case 0: - printk(KERN_INFO "OMAP3 Beagle Rev: xM\n"); - omap3_beagle_version = OMAP3BEAGLE_BOARD_XM; - break; - default: - printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev); - omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN; - } - - return; - -fail2: - gpio_free(172); -fail1: - gpio_free(171); -fail0: - printk(KERN_ERR "Unable to get revision detection GPIO pins\n"); - omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN; - - return; -} - -static struct mtd_partition omap3beagle_nand_partitions[] = { - /* All the partition sizes are listed in terms of NAND block size */ - { - .name = "X-Loader", - .offset = 0, - .size = 4 * NAND_BLOCK_SIZE, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { - .name = "U-Boot", - .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */ - .size = 15 * NAND_BLOCK_SIZE, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { - .name = "U-Boot Env", - .offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */ - .size = 1 * NAND_BLOCK_SIZE, - }, - { - .name = "Kernel", - .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */ - .size = 32 * NAND_BLOCK_SIZE, - }, - { - .name = "File System", - .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */ - .size = MTDPART_SIZ_FULL, - }, -}; - -/* DSS */ - -static int beagle_enable_dvi(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(dssdev->reset_gpio)) - gpio_set_value(dssdev->reset_gpio, 1); - - return 0; -} - -static void beagle_disable_dvi(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(dssdev->reset_gpio)) - gpio_set_value(dssdev->reset_gpio, 0); -} - -static struct omap_dss_device beagle_dvi_device = { - .type = OMAP_DISPLAY_TYPE_DPI, - .name = "dvi", - .driver_name = "generic_panel", - .phy.dpi.data_lines = 24, - .reset_gpio = -EINVAL, - .platform_enable = beagle_enable_dvi, - .platform_disable = beagle_disable_dvi, -}; - -static struct omap_dss_device beagle_tv_device = { - .name = "tv", - .driver_name = "venc", - .type = OMAP_DISPLAY_TYPE_VENC, - .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, -}; - -static struct omap_dss_device *beagle_dss_devices[] = { - &beagle_dvi_device, - &beagle_tv_device, -}; - -static struct omap_dss_board_info beagle_dss_data = { - .num_devices = ARRAY_SIZE(beagle_dss_devices), - .devices = beagle_dss_devices, - .default_device = &beagle_dvi_device, -}; - -static struct platform_device beagle_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &beagle_dss_data, - }, -}; - -static struct regulator_consumer_supply beagle_vdac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); - -static struct regulator_consumer_supply beagle_vdvi_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); - -static void __init beagle_display_init(void) -{ - int r; - - r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset"); - if (r < 0) { - printk(KERN_ERR "Unable to get DVI reset GPIO\n"); - return; - } - - gpio_direction_output(beagle_dvi_device.reset_gpio, 0); -} - -#include "sdram-micron-mt46h32m32lf-6.h" - -static struct omap2_hsmmc_info mmc[] = { - { - .mmc = 1, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, - .gpio_wp = 29, - }, - {} /* Terminator */ -}; - -static struct regulator_consumer_supply beagle_vmmc1_supply = { - .supply = "vmmc", -}; - -static struct regulator_consumer_supply beagle_vsim_supply = { - .supply = "vmmc_aux", -}; - -static struct regulator_consumer_supply beagle_vaux3_supply = { - .supply = "cam_1v8", -}; - -static struct regulator_consumer_supply beagle_vaux4_supply = { - .supply = "cam_2v8", -}; - -static struct gpio_led gpio_leds[]; - -static int beagle_twl_gpio_setup(struct device *dev, - unsigned gpio, unsigned ngpio) -{ - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) { - mmc[0].gpio_wp = -EINVAL; - } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) || - (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) { - omap_mux_init_gpio(23, OMAP_PIN_INPUT); - mmc[0].gpio_wp = 23; - } else { - omap_mux_init_gpio(29, OMAP_PIN_INPUT); - } - /* gpio + 0 is "mmc0_cd" (input/IRQ) */ - mmc[0].gpio_cd = gpio + 0; - omap2_hsmmc_init(mmc); - - /* link regulators to MMC adapters */ - beagle_vmmc1_supply.dev = mmc[0].dev; - beagle_vsim_supply.dev = mmc[0].dev; - - /* REVISIT: need ehci-omap hooks for external VBUS - * power switch and overcurrent detect - */ - if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) { - gpio_request(gpio + 1, "EHCI_nOC"); - gpio_direction_input(gpio + 1); - } - - /* - * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active - * high / others active low) - */ - gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); - gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) - gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1); - else - gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); - - /* DVI reset GPIO is different between beagle revisions */ - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) - beagle_dvi_device.reset_gpio = 129; - else - beagle_dvi_device.reset_gpio = 170; - - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) { - /* Power on camera interface */ - gpio_request(gpio + 2, "CAM_EN"); - gpio_direction_output(gpio + 2, 1); - - /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ - gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); - gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1); - } else { - gpio_request(gpio + 1, "EHCI_nOC"); - gpio_direction_input(gpio + 1); - - /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ - gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); - gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); - } - /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ - gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; - - /* - * gpio + 1 on Xm controls the TFP410's enable line (active low) - * gpio + 2 control varies depending on the board rev as follows: - * P7/P8 revisions(prototype): Camera EN - * A2+ revisions (production): LDO (supplies DVI, serial, led blocks) - */ - if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) { - gpio_request(gpio + 1, "nDVI_PWR_EN"); - gpio_direction_output(gpio + 1, 0); - gpio_request(gpio + 2, "DVI_LDO_EN"); - gpio_direction_output(gpio + 2, 1); - } - - return 0; -} - -static struct twl4030_gpio_platform_data beagle_gpio_data = { - .gpio_base = OMAP_MAX_GPIO_LINES, - .irq_base = TWL4030_GPIO_IRQ_BASE, - .irq_end = TWL4030_GPIO_IRQ_END, - .use_leds = true, - .pullups = BIT(1), - .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13) - | BIT(15) | BIT(16) | BIT(17), - .setup = beagle_twl_gpio_setup, -}; - -/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ -static struct regulator_init_data beagle_vmmc1 = { - .constraints = { - .min_uV = 1850000, - .max_uV = 3150000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vmmc1_supply, -}; - -/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */ -static struct regulator_init_data beagle_vsim = { - .constraints = { - .min_uV = 1800000, - .max_uV = 3000000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vsim_supply, -}; - -/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */ -static struct regulator_init_data beagle_vdac = { - .constraints = { - .min_uV = 1800000, - .max_uV = 1800000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vdac_supply, -}; - -/* VPLL2 for digital video outputs */ -static struct regulator_init_data beagle_vpll2 = { - .constraints = { - .name = "VDVI", - .min_uV = 1800000, - .max_uV = 1800000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vdvi_supply, -}; - -/* VAUX3 for CAM_1V8 */ -static struct regulator_init_data beagle_vaux3 = { - .constraints = { - .min_uV = 1800000, - .max_uV = 1800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vaux3_supply, -}; - - /* VAUX4 for CAM_2V8 */ -static struct regulator_init_data beagle_vaux4 = { - .constraints = { - .min_uV = 1800000, - .max_uV = 1800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vaux4_supply, -}; - -static struct twl4030_usb_data beagle_usb_data = { - .usb_mode = T2_USB_MODE_ULPI, -}; - -/** - * Macro to configure resources - */ -#define TWL4030_RESCONFIG(res,grp,typ1,typ2,state) \ - { \ - .resource = res, \ - .devgroup = grp, \ - .type = typ1, \ - .type2 = typ2, \ - .remap_sleep = state \ - } - -static struct twl4030_resconfig __initdata board_twl4030_rconfig[] = { - TWL4030_RESCONFIG(RES_VPLL1, DEV_GRP_P1, 3, 1, RES_STATE_OFF), /* ? */ - TWL4030_RESCONFIG(RES_VINTANA1, DEV_GRP_ALL, 1, 2, RES_STATE_SLEEP), - TWL4030_RESCONFIG(RES_VINTANA2, DEV_GRP_ALL, 0, 2, RES_STATE_SLEEP), - TWL4030_RESCONFIG(RES_VINTDIG, DEV_GRP_ALL, 1, 2, RES_STATE_SLEEP), - TWL4030_RESCONFIG(RES_VIO, DEV_GRP_ALL, 2, 2, RES_STATE_SLEEP), - TWL4030_RESCONFIG(RES_VDD1, DEV_GRP_P1, 4, 1, RES_STATE_OFF), /* ? */ - TWL4030_RESCONFIG(RES_VDD2, DEV_GRP_P1, 3, 1, RES_STATE_OFF), /* ? */ - TWL4030_RESCONFIG(RES_REGEN, DEV_GRP_ALL, 2, 1, RES_STATE_SLEEP), - TWL4030_RESCONFIG(RES_NRES_PWRON, DEV_GRP_ALL, 0, 1, RES_STATE_SLEEP), - TWL4030_RESCONFIG(RES_CLKEN, DEV_GRP_ALL, 3, 2, RES_STATE_SLEEP), - TWL4030_RESCONFIG(RES_SYSEN, DEV_GRP_ALL, 6, 1, RES_STATE_SLEEP), - TWL4030_RESCONFIG(RES_HFCLKOUT, DEV_GRP_P3, 0, 2, RES_STATE_SLEEP), /* ? */ - TWL4030_RESCONFIG(0, 0, 0, 0, 0), -}; - -/** - * Optimized 'Active to Sleep' sequence - */ -static struct twl4030_ins omap3beagle_sleep_seq[] __initdata = { - { MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 20}, - { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, RES_STATE_SLEEP), 2 }, - { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_SLEEP), 2 }, -}; - -static struct twl4030_script omap3beagle_sleep_script __initdata = { - .script = omap3beagle_sleep_seq, - .size = ARRAY_SIZE(omap3beagle_sleep_seq), - .flags = TWL4030_SLEEP_SCRIPT, -}; - -/** - * Optimized 'Sleep to Active (P12)' sequence - */ -static struct twl4030_ins omap3beagle_wake_p12_seq[] __initdata = { - { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, RES_STATE_ACTIVE), 2 } -}; - -static struct twl4030_script omap3beagle_wake_p12_script __initdata = { - .script = omap3beagle_wake_p12_seq, - .size = ARRAY_SIZE(omap3beagle_wake_p12_seq), - .flags = TWL4030_WAKEUP12_SCRIPT, -}; - -/** - * Optimized 'Sleep to Active' (P3) sequence - */ -static struct twl4030_ins omap3beagle_wake_p3_seq[] __initdata = { - { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_ACTIVE), 2 } -}; - -static struct twl4030_script omap3beagle_wake_p3_script __initdata = { - .script = omap3beagle_wake_p3_seq, - .size = ARRAY_SIZE(omap3beagle_wake_p3_seq), - .flags = TWL4030_WAKEUP3_SCRIPT, -}; - -/** - * Optimized warm reset sequence (for less power surge) - */ -static struct twl4030_ins omap3beagle_wrst_seq[] __initdata = { - { MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 0x2 }, - { MSG_SINGULAR(DEV_GRP_NULL, RES_MAIN_REF, RES_STATE_WRST), 2 }, - { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_WRST), 0x2}, - { MSG_SINGULAR(DEV_GRP_NULL, RES_VUSB_3V1, RES_STATE_WRST), 0x2 }, - { MSG_SINGULAR(DEV_GRP_NULL, RES_VPLL1, RES_STATE_WRST), 0x2 }, - { MSG_SINGULAR(DEV_GRP_NULL, RES_VDD2, RES_STATE_WRST), 0x7 }, - { MSG_SINGULAR(DEV_GRP_NULL, RES_VDD1, RES_STATE_WRST), 0x25 }, - { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0, RES_STATE_WRST), 0x2 }, - { MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 0x2 }, - -}; - -static struct twl4030_script omap3beagle_wrst_script __initdata = { - .script = omap3beagle_wrst_seq, - .size = ARRAY_SIZE(omap3beagle_wrst_seq), - .flags = TWL4030_WRST_SCRIPT, -}; - -static struct twl4030_script __initdata *board_twl4030_scripts[] = { - &omap3beagle_wake_p12_script, - &omap3beagle_wake_p3_script, - &omap3beagle_sleep_script, - &omap3beagle_wrst_script -}; - -static struct twl4030_power_data __initdata omap3beagle_script_data = { - .scripts = board_twl4030_scripts, - .num = ARRAY_SIZE(board_twl4030_scripts), - .resource_config = board_twl4030_rconfig, -}; - -static struct twl4030_codec_audio_data beagle_audio_data = { - .audio_mclk = 26000000, - .digimic_delay = 1, - .ramp_delay_value = 1, - .offset_cncl_path = 1, - .check_defaults = false, - .reset_registers = false, - .reset_registers = false, -}; - -static struct twl4030_codec_data beagle_codec_data = { - .audio_mclk = 26000000, - .audio = &beagle_audio_data, -}; - -static struct twl4030_platform_data beagle_twldata = { - .irq_base = TWL4030_IRQ_BASE, - .irq_end = TWL4030_IRQ_END, - - /* platform_data for children goes here */ - .usb = &beagle_usb_data, - .gpio = &beagle_gpio_data, - .codec = &beagle_codec_data, - .vmmc1 = &beagle_vmmc1, - .vsim = &beagle_vsim, - .vdac = &beagle_vdac, - .vpll2 = &beagle_vpll2, - .vaux3 = &beagle_vaux3, - .vaux4 = &beagle_vaux4, - .power = &omap3beagle_script_data, -}; - -static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = { - { - I2C_BOARD_INFO("twl4030", 0x48), - .flags = I2C_CLIENT_WAKE, - .irq = INT_34XX_SYS_NIRQ, - .platform_data = &beagle_twldata, - }, -}; - -static struct i2c_board_info __initdata beagle_i2c_eeprom[] = { - { - I2C_BOARD_INFO("eeprom", 0x50), - }, -}; - -static int __init omap3_beagle_i2c_init(void) -{ - omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo, - ARRAY_SIZE(beagle_i2c_boardinfo)); - - /* Bus 2 is used for Camera/Sensor interface */ - if (ARRAY_SIZE(bus2_i2c_devices)) - omap_register_i2c_bus(2, 400, bus2_i2c_devices, - ARRAY_SIZE(bus2_i2c_devices)); - else - omap_register_i2c_bus(2, 400, NULL, 0); - - /* Bus 3 is attached to the DVI port where devices like the pico DLP - * projector don't work reliably with 400kHz */ - omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom)); - - return 0; -} - -static struct gpio_led gpio_leds[] = { - { - .name = "beagleboard::usr0", - .default_trigger = "heartbeat", - .gpio = 150, - }, - { - .name = "beagleboard::usr1", - .default_trigger = "mmc0", - .gpio = 149, - }, - { - .name = "beagleboard::pmu_stat", - .gpio = -EINVAL, /* gets replaced */ - .active_low = true, - }, -}; - -static struct gpio_led_platform_data gpio_led_info = { - .leds = gpio_leds, - .num_leds = ARRAY_SIZE(gpio_leds), -}; - -static struct platform_device leds_gpio = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = &gpio_led_info, - }, -}; - -static struct gpio_keys_button gpio_buttons[] = { - { - .code = KEY_POWER, - .gpio = 4, - .desc = "user", - .wakeup = 1, - }, -}; - -static struct gpio_keys_platform_data gpio_key_info = { - .buttons = gpio_buttons, - .nbuttons = ARRAY_SIZE(gpio_buttons), -}; - -static struct platform_device keys_gpio = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &gpio_key_info, - }, -}; - -static void __init omap3_beagle_init_irq(void) -{ - omap2_init_common_infrastructure(); - omap2_init_common_devices(mt46h32m32lf6_sdrc_params, - mt46h32m32lf6_sdrc_params); - omap_init_irq(); - gpmc_init(); -#ifdef CONFIG_OMAP_32K_TIMER - if (omap3_beagle_version == OMAP3BEAGLE_BOARD_AXBX) - omap2_gp_clockevent_set_gptimer(12); - else - omap2_gp_clockevent_set_gptimer(1); -#endif -} - -static struct platform_device *omap3_beagle_devices[] __initdata = { - &leds_gpio, - &keys_gpio, - &beagle_dss_device, - &usb_mass_storage_device, -}; - -static void __init omap3beagle_flash_init(void) -{ - u8 cs = 0; - u8 nandcs = GPMC_CS_NUM + 1; - - /* find out the chip-select on which NAND exists */ - while (cs < GPMC_CS_NUM) { - u32 ret = 0; - ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); - - if ((ret & 0xC00) == 0x800) { - printk(KERN_INFO "Found NAND on CS%d\n", cs); - if (nandcs > GPMC_CS_NUM) - nandcs = cs; - } - cs++; - } - - if (nandcs > GPMC_CS_NUM) { - printk(KERN_INFO "NAND: Unable to find configuration " - "in GPMC\n "); - return; - } - - if (nandcs < GPMC_CS_NUM) { - printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - board_nand_init(omap3beagle_nand_partitions, - ARRAY_SIZE(omap3beagle_nand_partitions), - nandcs, NAND_BUSWIDTH_16); - } -} - -static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { - - .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, - .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, - .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, - - .phy_reset = true, - .reset_gpio_port[0] = -EINVAL, - .reset_gpio_port[1] = 147, - .reset_gpio_port[2] = -EINVAL -}; - -#ifdef CONFIG_OMAP_MUX -static struct omap_board_mux board_mux[] __initdata = { - OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP | - OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW | - OMAP_PIN_OFF_WAKEUPENABLE), - { .reg_offset = OMAP_MUX_TERMINATOR }, -}; -#endif - -static struct omap_musb_board_data musb_board_data = { - .interface_type = MUSB_INTERFACE_ULPI, - .mode = MUSB_OTG, - .power = 100, -}; - -static void __init omap3_beagle_init(void) -{ - omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); - omap3_beagle_init_rev(); - omap3_beagle_i2c_init(); - platform_add_devices(omap3_beagle_devices, - ARRAY_SIZE(omap3_beagle_devices)); - omap_serial_init(); - - omap_mux_init_gpio(170, OMAP_PIN_INPUT); - gpio_request(170, "DVI_nPD"); - /* REVISIT leave DVI powered down until it's needed ... */ - gpio_direction_output(170, true); - - usb_musb_init(&musb_board_data); - usb_ehci_init(&ehci_pdata); - omap3beagle_flash_init(); - - /* Ensure SDRC pins are mux'd for self-refresh */ - omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); - omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); - - beagle_display_init(); -#ifdef CONFIG_USB_ANDROID - omap3beagle_android_gadget_init(); -#endif - omap3_beagle_pm_init(); -} - -MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") - /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */ - .boot_params = 0x80000100, - .map_io = omap3_map_io, - .reserve = omap_reserve, - .init_irq = omap3_beagle_init_irq, - .init_machine = omap3_beagle_init, - .timer = &omap_timer, -MACHINE_END diff --git a/kernel/arch/arm/mach-omap2/board-omap4panda.c b/kernel/arch/arm/mach-omap2/board-omap4panda.c deleted file mode 100644 index 4f8c79ddd650..000000000000 --- a/kernel/arch/arm/mach-omap2/board-omap4panda.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * Board support file for OMAP4430 based PandaBoard. - * - * Copyright (C) 2010 Texas Instruments - * - * Author: David Anders <x0132446@ti.com> - * - * Based on mach-omap2/board-4430sdp.c - * - * Author: Santosh Shilimkar <santosh.shilimkar@ti.com> - * - * Based on mach-omap2/board-3430sdp.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/input.h> -#include <linux/io.h> -#include <linux/leds.h> -#include <linux/gpio.h> -#include <linux/gpio_keys.h> -#include <linux/omapfb.h> -#include <linux/reboot.h> -#include <linux/usb/otg.h> -#include <linux/i2c/twl.h> -#include <linux/regulator/machine.h> -#include <linux/regulator/fixed.h> -#include <linux/wl12xx.h> -#include <linux/memblock.h> -#include <linux/skbuff.h> -#include <linux/ti_wilink_st.h> -#include <linux/platform_data/ram_console.h> - -#include <mach/hardware.h> -#include <mach/omap4-common.h> -#include <mach/emif.h> -#include <mach/lpddr2-elpida.h> -#include <mach/dmm.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <video/omapdss.h> - -#include <plat/board.h> -#include <plat/common.h> -#include <plat/usb.h> -#include <plat/mmc.h> -#include <plat/remoteproc.h> -#include <plat/vram.h> -#include <video/omap-panel-generic-dpi.h> -#include "timer-gp.h" - -#include "hsmmc.h" -#include "control.h" -#include "mux.h" -#include "common-board-devices.h" -#include "prm-regbits-44xx.h" -#include "prm44xx.h" -#include "pm.h" -#include "resetreason.h" - -#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 -#include <linux/input/synaptics_dsx.h> -#define TM_SAMPLE1 (1) // 2D only -#define TM_SAMPLE2 (2) // 2D + 0D x 2 -#define TM_SAMPLE3 (3) // 2D + 0D x 4 -#define SYNAPTICS_MODULE TM_SAMPLE1 -#endif - -#define PANDA_RAMCONSOLE_START (PLAT_PHYS_OFFSET + SZ_512M) -#define PANDA_RAMCONSOLE_SIZE SZ_2M - -#define GPIO_HUB_POWER 1 -#define GPIO_HUB_NRESET 62 -#define GPIO_WIFI_PMENA 43 -#define GPIO_WIFI_IRQ 53 -#define HDMI_GPIO_CT_CP_HPD 60 -#define HDMI_GPIO_HPD 63 /* Hot plug pin for HDMI */ -#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ -#define TPS62361_GPIO 7 /* VCORE1 power control */ -#define PANDA_BT_GPIO 46 - - -#define PHYS_ADDR_SMC_SIZE (SZ_1M * 3) -#define PHYS_ADDR_SMC_MEM (0x80000000 + SZ_1G - PHYS_ADDR_SMC_SIZE) -#define OMAP_ION_HEAP_SECURE_INPUT_SIZE (SZ_1M * 90) -#define PHYS_ADDR_DUCATI_SIZE (SZ_1M * 105) -#define PHYS_ADDR_DUCATI_MEM (PHYS_ADDR_SMC_MEM - PHYS_ADDR_DUCATI_SIZE - \ - OMAP_ION_HEAP_SECURE_INPUT_SIZE) - -#define WILINK_UART_DEV_NAME "/dev/ttyO1" - - -/* Synaptics changes for PandaBoard */ -#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 -static int synaptics_gpio_setup(unsigned gpio, bool configure) -{ - int retval = 0; - - if (configure) { - retval = gpio_request(gpio, "rmi4_attn"); - if (retval) { - pr_err("%s: Failed to get attn gpio %d (code: %d)", - __func__, gpio, retval); - return retval; - } - omap_mux_init_signal("gpmc_ad15.gpio_39", OMAP_PIN_INPUT_PULLUP); - - retval = gpio_direction_input(gpio); - if (retval) { - pr_err("%s: Failed to setup attn gpio %d (code: %d)", - __func__, gpio, retval); - gpio_free(gpio); - } - } else { - pr_warn("%s: No way to deconfigure gpio %d", - __func__, gpio); - } - - return retval; -} - - #if (SYNAPTICS_MODULE == TM_SAMPLE1) -#define TM_SAMPLE1_ADDR 0x20 -#define TM_SAMPLE1_ATTN 130 - -static unsigned char TM_SAMPLE1_f1a_button_codes[] = {}; - -static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE1_capacitance_button_map = { - .nbuttons = ARRAY_SIZE(TM_SAMPLE1_f1a_button_codes), - .map = TM_SAMPLE1_f1a_button_codes, -}; - -static struct synaptics_rmi4_platform_data rmi4_platformdata = { - .irq_flags = IRQF_TRIGGER_FALLING, - .irq_gpio = TM_SAMPLE1_ATTN, - .gpio_config = synaptics_gpio_setup, - .capacitance_button_map = &TM_SAMPLE1_capacitance_button_map, -}; - -static struct i2c_board_info bus4_i2c_devices[] = { - { - I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE1_ADDR), - .platform_data = &rmi4_platformdata, - }, -}; - -#elif (SYNAPTICS_MODULE == TM_SAMPLE2) -#define TM_SAMPLE2_ADDR 0x20 -#define TM_SAMPLE2_ATTN 130 - -static unsigned char TM_SAMPLE2_f1a_button_codes[] = {KEY_MENU, KEY_BACK}; - -static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE2_capacitance_button_map = { - .nbuttons = ARRAY_SIZE(TM_SAMPLE2_f1a_button_codes), - .map = TM_SAMPLE2_f1a_button_codes, -}; - -static struct synaptics_rmi4_platform_data rmi4_platformdata = { - .irq_flags = IRQF_TRIGGER_FALLING, - .irq_gpio = TM_SAMPLE2_ATTN, - .gpio_config = synaptics_gpio_setup, - .capacitance_button_map = &TM_SAMPLE2_capacitance_button_map, -}; - -static struct i2c_board_info bus4_i2c_devices[] = { - { - I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE2_ADDR), - .platform_data = &rmi4_platformdata, - }, -}; -}; - -#elif (SYNAPTICS_MODULE == TM_SAMPLE3) -#define TM_SAMPLE3_ADDR 0x20 -#define TM_SAMPLE3_ATTN 130 - -static unsigned char TM_SAMPLE3_f1a_button_codes[] = {KEY_MENU, KEY_HOME,KEY_BACK,KEY_SEARCH}; - -static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE3_capacitance_button_map = { - .nbuttons = ARRAY_SIZE(TM_SAMPLE3_f1a_button_codes), - .map = TM_SAMPLE3_f1a_button_codes, -}; - -static struct synaptics_rmi4_platform_data rmi4_platformdata = { - .irq_flags = IRQF_TRIGGER_FALLING, - .irq_gpio = TM_SAMPLE3_ATTN, - .gpio_config = synaptics_gpio_setup, - .capacitance_button_map = &TM_SAMPLE3_capacitance_button_map, -}; - -static struct i2c_board_info bus4_i2c_devices[] = { - { - I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE3_ADDR), - .platform_data = &rmi4_platformdata, - }, -}; -#endif - -void __init i2c_device_setup(void) -{ - pr_info(">>>>I2C device setup"); - if (ARRAY_SIZE(bus4_i2c_devices)) { - i2c_register_board_info(4, bus4_i2c_devices, - ARRAY_SIZE(bus4_i2c_devices)); - } -} -#endif -/* End of Synaptics changes for PandaBoard */ - -static struct gpio_led gpio_leds[] = { - { - .name = "pandaboard::status1", - .default_trigger = "heartbeat", - .gpio = 7, - }, - { - .name = "pandaboard::status2", - .default_trigger = "mmc0", - .gpio = 8, - }, -}; - -static struct gpio_led_platform_data gpio_led_info = { - .leds = gpio_leds, - .num_leds = ARRAY_SIZE(gpio_leds), -}; - -static struct platform_device leds_gpio = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = &gpio_led_info, - }, -}; - -/* GPIO_KEY for the panda */ -static struct gpio_keys_button panda_gpio_keys_buttons[] = { - [0] = { - .code = KEY_HOME, - .gpio = 113, - .desc = "user_button", - .active_low = 1, - .debounce_interval = 5, - }, -}; - -static struct gpio_keys_platform_data panda_gpio_keys = { - .buttons = panda_gpio_keys_buttons, - .nbuttons = ARRAY_SIZE(panda_gpio_keys_buttons), - .rep = 0, -}; - -static struct platform_device panda_gpio_keys_device = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &panda_gpio_keys, - }, -}; - -/* TODO: handle suspend/resume here. - * Upon every suspend, make sure the wilink chip is - * capable enough to wake-up the OMAP host. - */ -static int plat_wlink_kim_suspend(struct platform_device *pdev, pm_message_t - state) -{ - return 0; -} - -static int plat_wlink_kim_resume(struct platform_device *pdev) -{ - return 0; -} - -/* wl128x BT, FM, GPS connectivity chip */ -static struct ti_st_plat_data wilink_pdata = { - .nshutdown_gpio = PANDA_BT_GPIO, - .dev_name = WILINK_UART_DEV_NAME, - .flow_cntrl = 1, - .baud_rate = 3686400, - .suspend = plat_wlink_kim_suspend, - .resume = plat_wlink_kim_resume, -}; - -static struct platform_device btwilink_device = { - .name = "btwilink", - .id = -1, -}; - -/* wl127x BT, FM, GPS connectivity chip */ -static struct platform_device wl1271_device = { - .name = "kim", - .id = -1, - .dev.platform_data = &wilink_pdata, -}; - - -static struct platform_device *panda_devices[] __initdata = { - &leds_gpio, - &wl1271_device, - &btwilink_device, - &panda_gpio_keys_device, -}; - -static void __init omap4_panda_init_early(void) -{ - omap2_init_common_infrastructure(); - omap2_init_common_devices(NULL, NULL); -} - -static const struct usbhs_omap_board_data usbhs_bdata __initconst = { - .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, - .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED, - .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED, - .phy_reset = false, - .reset_gpio_port[0] = -EINVAL, - .reset_gpio_port[1] = -EINVAL, - .reset_gpio_port[2] = -EINVAL -}; - -static struct gpio panda_ehci_gpios[] __initdata = { - { GPIO_HUB_POWER, GPIOF_OUT_INIT_LOW, "hub_power" }, - { GPIO_HUB_NRESET, GPIOF_OUT_INIT_LOW, "hub_nreset" }, -}; - -static void __init omap4_ehci_init(void) -{ - int ret; - struct clk *phy_ref_clk; - - /* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */ - phy_ref_clk = clk_get(NULL, "auxclk3_ck"); - if (IS_ERR(phy_ref_clk)) { - pr_err("Cannot request auxclk3\n"); - return; - } - clk_set_rate(phy_ref_clk, 19200000); - clk_enable(phy_ref_clk); - - /* disable the power to the usb hub prior to init and reset phy+hub */ - ret = gpio_request_array(panda_ehci_gpios, - ARRAY_SIZE(panda_ehci_gpios)); - if (ret) { - pr_err("Unable to initialize EHCI power/reset\n"); - return; - } - - gpio_export(GPIO_HUB_POWER, 0); - gpio_export(GPIO_HUB_NRESET, 0); - gpio_set_value(GPIO_HUB_NRESET, 1); - - usbhs_init(&usbhs_bdata); - - /* enable power to hub */ - gpio_set_value(GPIO_HUB_POWER, 1); -} - -static struct omap_musb_board_data musb_board_data = { - .interface_type = MUSB_INTERFACE_UTMI, -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - .mode = MUSB_PERIPHERAL, -#else - .mode = MUSB_OTG, -#endif - .power = 100, -}; - -static struct twl4030_usb_data omap4_usbphy_data = { - .phy_init = omap4430_phy_init, - .phy_exit = omap4430_phy_exit, - .phy_power = omap4430_phy_power, - .phy_set_clock = omap4430_phy_set_clk, - .phy_suspend = omap4430_phy_suspend, -}; - -static struct omap2_hsmmc_info mmc[] = { - { - .mmc = 1, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, - .gpio_wp = -EINVAL, - .gpio_cd = -EINVAL, - }, - { - .name = "wl1271", - .mmc = 5, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, - .gpio_wp = -EINVAL, - .gpio_cd = -EINVAL, - .ocr_mask = MMC_VDD_165_195, - .nonremovable = true, - }, - {} /* Terminator */ -}; - -static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = { - { - .supply = "vmmc", - .dev_name = "omap_hsmmc.0", - }, -}; - -static struct regulator_consumer_supply omap4_panda_vmmc5_supply = { - .supply = "vmmc", - .dev_name = "omap_hsmmc.4", -}; - -static struct regulator_init_data panda_vmmc5 = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &omap4_panda_vmmc5_supply, -}; - -static struct fixed_voltage_config panda_vwlan = { - .supply_name = "vwl1271", - .microvolts = 1800000, /* 1.8V */ - .gpio = GPIO_WIFI_PMENA, - .startup_delay = 70000, /* 70msec */ - .enable_high = 1, - .enabled_at_boot = 0, - .init_data = &panda_vmmc5, -}; - -static struct platform_device omap_vwlan_device = { - .name = "reg-fixed-voltage", - .id = 1, - .dev = { - .platform_data = &panda_vwlan, - }, -}; - -struct wl12xx_platform_data omap_panda_wlan_data __initdata = { - .irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ), - /* PANDA ref clock is 38.4 MHz */ - .board_ref_clock = 2, -}; - -static int omap4_twl6030_hsmmc_late_init(struct device *dev) -{ - int ret = 0; - struct platform_device *pdev = container_of(dev, - struct platform_device, dev); - struct omap_mmc_platform_data *pdata = dev->platform_data; - - if (!pdata) { - dev_err(dev, "%s: NULL platform data\n", __func__); - return -EINVAL; - } - /* Setting MMC1 Card detect Irq */ - if (pdev->id == 0) { - ret = twl6030_mmc_card_detect_config(); - if (ret) - dev_err(dev, "%s: Error card detect config(%d)\n", - __func__, ret); - else - pdata->slots[0].card_detect = twl6030_mmc_card_detect; - } - return ret; -} - -static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev) -{ - struct omap_mmc_platform_data *pdata; - - /* dev can be null if CONFIG_MMC_OMAP_HS is not set */ - if (!dev) { - pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n"); - return; - } - pdata = dev->platform_data; - - pdata->init = omap4_twl6030_hsmmc_late_init; -} - -static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers) -{ - struct omap2_hsmmc_info *c; - - omap2_hsmmc_init(controllers); - for (c = controllers; c->mmc; c++) - omap4_twl6030_hsmmc_set_late_init(c->dev); - - return 0; -} - -static struct regulator_init_data omap4_panda_vaux2 = { - .constraints = { - .min_uV = 1200000, - .max_uV = 2800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -static struct regulator_init_data omap4_panda_vaux3 = { - .constraints = { - .min_uV = 1000000, - .max_uV = 3000000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -/* VMMC1 for MMC1 card */ -static struct regulator_init_data omap4_panda_vmmc = { - .constraints = { - .min_uV = 1200000, - .max_uV = 3000000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = omap4_panda_vmmc_supply, -}; - -static struct regulator_init_data omap4_panda_vpp = { - .constraints = { - .min_uV = 1800000, - .max_uV = 2500000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -static struct regulator_init_data omap4_panda_vana = { - .constraints = { - .min_uV = 2100000, - .max_uV = 2100000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -static struct regulator_init_data omap4_panda_vcxio = { - .constraints = { - .min_uV = 1800000, - .max_uV = 1800000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -static struct regulator_consumer_supply panda_vdac_supply[] = { - { - .supply = "hdmi_vref", - }, -}; - -static struct regulator_init_data omap4_panda_vdac = { - .constraints = { - .min_uV = 1800000, - .max_uV = 1800000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(panda_vdac_supply), - .consumer_supplies = panda_vdac_supply, -}; - -static struct regulator_init_data omap4_panda_vusb = { - .constraints = { - .min_uV = 3300000, - .max_uV = 3300000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -static struct regulator_init_data omap4_panda_clk32kg = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - .always_on = true, - }, -}; - -static void omap4_audio_conf(void) -{ - /* twl6040 naudint */ - omap_mux_init_signal("sys_nirq2.sys_nirq2", \ - OMAP_PIN_INPUT_PULLUP); -} - -static struct twl4030_codec_audio_data twl6040_audio = { - /* single-step ramp for headset and handsfree */ - .hs_left_step = 0x0f, - .hs_right_step = 0x0f, - .hf_left_step = 0x1d, - .hf_right_step = 0x1d, - .hs_switch_dev = 0x1, - .hs_forced_hs_state = 0x1 -}; - -static struct twl4030_codec_data twl6040_codec = { - .audio = &twl6040_audio, - .audpwron_gpio = 127, - .naudint_irq = OMAP44XX_IRQ_SYS_2N, - .irq_base = TWL6040_CODEC_IRQ_BASE, -}; - -static struct twl4030_platform_data omap4_panda_twldata = { - .irq_base = TWL6030_IRQ_BASE, - .irq_end = TWL6030_IRQ_END, - - /* Regulators */ - .vmmc = &omap4_panda_vmmc, - .vpp = &omap4_panda_vpp, - .vana = &omap4_panda_vana, - .vcxio = &omap4_panda_vcxio, - .vdac = &omap4_panda_vdac, - .vusb = &omap4_panda_vusb, - .vaux2 = &omap4_panda_vaux2, - .vaux3 = &omap4_panda_vaux3, - .clk32kg = &omap4_panda_clk32kg, - .usb = &omap4_usbphy_data, - - /* children */ - .codec = &twl6040_codec, -}; - -/* - * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM - * is connected as I2C slave device, and can be accessed at address 0x50 - */ -static struct i2c_board_info __initdata panda_i2c_eeprom[] = { - { - I2C_BOARD_INFO("eeprom", 0x50), - }, -}; - -static int __init omap4_panda_i2c_init(void) -{ - omap4_pmic_init("twl6030", &omap4_panda_twldata); - omap_register_i2c_bus(2, 400, NULL, 0); - /* - * Bus 3 is attached to the DVI port where devices like the pico DLP - * projector don't work reliably with 400kHz - */ - omap_register_i2c_bus(3, 100, panda_i2c_eeprom, - ARRAY_SIZE(panda_i2c_eeprom)); - if(ARRAY_SIZE(bus4_i2c_devices)) - omap_register_i2c_bus(4, 400, bus4_i2c_devices, ARRAY_SIZE(bus4_i2c_devices)); - else - omap_register_i2c_bus(4, 400, NULL, 0); - return 0; -} - -#ifdef CONFIG_OMAP_MUX -static struct omap_board_mux board_mux[] __initdata = { - /* WLAN IRQ - GPIO 53 */ - OMAP4_MUX(GPMC_NCS3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), - /* WLAN POWER ENABLE - GPIO 43 */ - OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT), - /* WLAN SDIO: MMC5 CMD */ - OMAP4_MUX(SDMMC5_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), - /* WLAN SDIO: MMC5 CLK */ - OMAP4_MUX(SDMMC5_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), - /* WLAN SDIO: MMC5 DAT[0-3] */ - OMAP4_MUX(SDMMC5_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), - OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), - OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), - OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), - /* gpio 0 - TFP410 PD */ - OMAP4_MUX(KPD_COL1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3), - /* dispc2_data23 */ - OMAP4_MUX(USBB2_ULPITLL_STP, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data22 */ - OMAP4_MUX(USBB2_ULPITLL_DIR, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data21 */ - OMAP4_MUX(USBB2_ULPITLL_NXT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data20 */ - OMAP4_MUX(USBB2_ULPITLL_DAT0, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data19 */ - OMAP4_MUX(USBB2_ULPITLL_DAT1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data18 */ - OMAP4_MUX(USBB2_ULPITLL_DAT2, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data15 */ - OMAP4_MUX(USBB2_ULPITLL_DAT3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data14 */ - OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data13 */ - OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data12 */ - OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data11 */ - OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data10 */ - OMAP4_MUX(DPM_EMU3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data9 */ - OMAP4_MUX(DPM_EMU4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data16 */ - OMAP4_MUX(DPM_EMU5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data17 */ - OMAP4_MUX(DPM_EMU6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_hsync */ - OMAP4_MUX(DPM_EMU7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_pclk */ - OMAP4_MUX(DPM_EMU8, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_vsync */ - OMAP4_MUX(DPM_EMU9, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_de */ - OMAP4_MUX(DPM_EMU10, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data8 */ - OMAP4_MUX(DPM_EMU11, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data7 */ - OMAP4_MUX(DPM_EMU12, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data6 */ - OMAP4_MUX(DPM_EMU13, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data5 */ - OMAP4_MUX(DPM_EMU14, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data4 */ - OMAP4_MUX(DPM_EMU15, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data3 */ - OMAP4_MUX(DPM_EMU16, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data2 */ - OMAP4_MUX(DPM_EMU17, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data1 */ - OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - /* dispc2_data0 */ - OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), - { .reg_offset = OMAP_MUX_TERMINATOR }, -}; - -static inline void __init board_serial_init(void) -{ - omap_serial_init(); -} -#else -#define board_mux NULL - -static inline void __init board_serial_init(void) -{ - omap_serial_init(); -} -#endif - -/* Display DVI */ -#define PANDA_DVI_TFP410_POWER_DOWN_GPIO 0 - -static int omap4_panda_enable_dvi(struct omap_dss_device *dssdev) -{ - gpio_set_value(dssdev->reset_gpio, 1); - return 0; -} - -static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev) -{ - gpio_set_value(dssdev->reset_gpio, 0); -} - -/* Using generic display panel */ -static struct panel_generic_dpi_data omap4_dvi_panel = { - .name = "generic_720p", - .platform_enable = omap4_panda_enable_dvi, - .platform_disable = omap4_panda_disable_dvi, -}; - -struct omap_dss_device omap4_panda_dvi_device = { - .type = OMAP_DISPLAY_TYPE_DPI, - .name = "dvi", - .driver_name = "generic_dpi_panel", - .data = &omap4_dvi_panel, - .phy.dpi.data_lines = 24, - .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, - .channel = OMAP_DSS_CHANNEL_LCD2, -}; - -int __init omap4_panda_dvi_init(void) -{ - int r; - - /* Requesting TFP410 DVI GPIO and disabling it, at bootup */ - r = gpio_request_one(omap4_panda_dvi_device.reset_gpio, - GPIOF_OUT_INIT_LOW, "DVI PD"); - if (r) - pr_err("Failed to get DVI powerdown GPIO\n"); - - return r; -} - -static struct gpio panda_hdmi_gpios[] = { - { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, - { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, -}; - -static void omap4_panda_hdmi_mux_init(void) -{ - u32 r; - int status; - /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ - omap_mux_init_signal("hdmi_hpd.hdmi_hpd", - OMAP_PIN_INPUT_PULLUP); - omap_mux_init_signal("gpmc_wait2.gpio_100", - OMAP_PIN_INPUT_PULLDOWN); - omap_mux_init_signal("hdmi_cec.hdmi_cec", - OMAP_PIN_INPUT_PULLUP); - /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */ - omap_mux_init_signal("hdmi_ddc_scl.hdmi_ddc_scl", - OMAP_PIN_INPUT_PULLUP); - omap_mux_init_signal("hdmi_ddc_sda.hdmi_ddc_sda", - OMAP_PIN_INPUT_PULLUP); - - /* strong pullup on DDC lines using unpublished register */ - r = ((1 << 24) | (1 << 28)) ; - omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1); - - gpio_request(HDMI_GPIO_HPD, NULL); - omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT | OMAP_PULL_ENA); - gpio_direction_input(HDMI_GPIO_HPD); - - status = gpio_request_array(panda_hdmi_gpios, - ARRAY_SIZE(panda_hdmi_gpios)); - if (status) - pr_err("%s: Cannot request HDMI GPIOs %x \n", __func__, status); -} - -static struct omap_dss_device omap4_panda_hdmi_device = { - .name = "hdmi", - .driver_name = "hdmi_panel", - .type = OMAP_DISPLAY_TYPE_HDMI, - .clocks = { - .dispc = { - .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK, - }, - .hdmi = { - .regn = 15, - .regm2 = 1, - }, - }, - .hpd_gpio = HDMI_GPIO_HPD, - .channel = OMAP_DSS_CHANNEL_DIGIT, -}; - -static struct omap_dss_device *omap4_panda_dss_devices[] = { - &omap4_panda_dvi_device, - &omap4_panda_hdmi_device, -}; - -static struct omap_dss_board_info omap4_panda_dss_data = { - .num_devices = ARRAY_SIZE(omap4_panda_dss_devices), - .devices = omap4_panda_dss_devices, - .default_device = &omap4_panda_dvi_device, -}; - -/* - * LPDDR2 Configeration Data: - * The memory organisation is as below : - * EMIF1 - CS0 - 2 Gb - * CS1 - 2 Gb - * EMIF2 - CS0 - 2 Gb - * CS1 - 2 Gb - * -------------------- - * TOTAL - 8 Gb - * - * Same devices installed on EMIF1 and EMIF2 - */ -static __initdata struct emif_device_details emif_devices = { - .cs0_device = &lpddr2_elpida_2G_S4_dev, - .cs1_device = &lpddr2_elpida_2G_S4_dev -}; - -void omap4_panda_display_init(void) -{ - int r; - - r = omap4_panda_dvi_init(); - if (r) - pr_err("error initializing panda DVI\n"); - - omap4_panda_hdmi_mux_init(); - omap_display_init(&omap4_panda_dss_data); -} - -static int panda_notifier_call(struct notifier_block *this, - unsigned long code, void *cmd) -{ - void __iomem *sar_base; - u32 v = OMAP4430_RST_GLOBAL_COLD_SW_MASK; - - sar_base = omap4_get_sar_ram_base(); - - if (!sar_base) - return notifier_from_errno(-ENOMEM); - - if ((code == SYS_RESTART) && (cmd != NULL)) { - /* cmd != null; case: warm boot */ - if (!strcmp(cmd, "bootloader")) { - /* Save reboot mode in scratch memory */ - strcpy(sar_base + 0xA0C, cmd); - v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK; - } else if (!strcmp(cmd, "recovery")) { - /* Save reboot mode in scratch memory */ - strcpy(sar_base + 0xA0C, cmd); - v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK; - } else { - v |= OMAP4430_RST_GLOBAL_COLD_SW_MASK; - } - } - - omap4_prm_write_inst_reg(0xfff, OMAP4430_PRM_DEVICE_INST, - OMAP4_RM_RSTST); - omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST, OMAP4_RM_RSTCTRL); - v = omap4_prm_read_inst_reg(WKUP_MOD, OMAP4_RM_RSTCTRL); - - return NOTIFY_DONE; -} - -static struct notifier_block panda_reboot_notifier = { - .notifier_call = panda_notifier_call, -}; - -#define PANDA_FB_RAM_SIZE SZ_16M /* 1920?1080*4 * 2 */ -static struct omapfb_platform_data panda_fb_pdata = { - .mem_desc = { - .region_cnt = 1, - .region = { - [0] = { - .size = PANDA_FB_RAM_SIZE, - }, - }, - }, -}; - -static struct resource ramconsole_resources[] = { - { - .flags = IORESOURCE_MEM, - .start = PANDA_RAMCONSOLE_START, - .end = PANDA_RAMCONSOLE_START + PANDA_RAMCONSOLE_SIZE - 1, - }, -}; - -static struct ram_console_platform_data ramconsole_pdata; - -static struct platform_device ramconsole_device = { - .name = "ram_console", - .id = -1, - .num_resources = ARRAY_SIZE(ramconsole_resources), - .resource = ramconsole_resources, - .dev = { - .platform_data = &ramconsole_pdata, - }, -}; - -extern void __init omap4_panda_android_init(void); - -static void __init omap4_panda_init(void) -{ - int package = OMAP_PACKAGE_CBS; - int status; - - omap_emif_setup_device_details(&emif_devices, &emif_devices); - - if (omap_rev() == OMAP4430_REV_ES1_0) - package = OMAP_PACKAGE_CBL; - omap4_mux_init(board_mux, NULL, package); - - if (wl12xx_set_platform_data(&omap_panda_wlan_data)) - pr_err("error setting wl12xx data\n"); - - register_reboot_notifier(&panda_reboot_notifier); - ramconsole_pdata.bootinfo = omap4_get_resetreason(); - platform_device_register(&ramconsole_device); - omap4_panda_i2c_init(); - omap4_audio_conf(); - - if (cpu_is_omap4430()) - panda_gpio_keys_buttons[0].gpio = 121; - - platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices)); - platform_device_register(&omap_vwlan_device); - board_serial_init(); - omap4_twl6030_hsmmc_init(mmc); - omap4_ehci_init(); - usb_musb_init(&musb_board_data); - - omap_dmm_init(); - omap_vram_set_sdram_vram(PANDA_FB_RAM_SIZE, 0); - omapfb_set_platform_data(&panda_fb_pdata); - omap4_panda_display_init(); - - if (cpu_is_omap446x()) { - /* Vsel0 = gpio, vsel1 = gnd */ - status = omap_tps6236x_board_setup(true, TPS62361_GPIO, -1, - OMAP_PIN_OFF_OUTPUT_HIGH, -1); - if (status) - pr_err("TPS62361 initialization failed: %d\n", status); - } - omap_enable_smartreflex_on_init(); -} - -static void __init omap4_panda_map_io(void) -{ - omap2_set_globals_443x(); - omap44xx_map_common_io(); -} - -static void __init omap4_panda_reserve(void) -{ - /* do the static reservations first */ - memblock_remove(PANDA_RAMCONSOLE_START, PANDA_RAMCONSOLE_SIZE); - memblock_remove(PHYS_ADDR_SMC_MEM, PHYS_ADDR_SMC_SIZE); - memblock_remove(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE); - /* ipu needs to recognize secure input buffer area as well */ - omap_ipu_set_static_mempool(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE + - OMAP_ION_HEAP_SECURE_INPUT_SIZE); - - omap_reserve(); -} - -MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") - /* Maintainer: David Anders - Texas Instruments Inc */ - .boot_params = 0x80000100, - .reserve = omap4_panda_reserve, - .map_io = omap4_panda_map_io, - .init_early = omap4_panda_init_early, - .init_irq = gic_init_irq, - .init_machine = omap4_panda_init, - .timer = &omap_timer, -MACHINE_END diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e2e784ad9e0f..ae83d9602aa0 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -781,6 +781,8 @@ static void put_css_set_locked(struct css_set *cset) static void put_css_set(struct css_set *cset) { + unsigned long flags; + /* * Ensure that the refcount doesn't hit zero while any readers * can see it. Similar to atomic_dec_and_lock(), but for an @@ -789,9 +791,9 @@ static void put_css_set(struct css_set *cset) if (atomic_add_unless(&cset->refcount, -1, 1)) return; - spin_lock_bh(&css_set_lock); + spin_lock_irqsave(&css_set_lock, flags); put_css_set_locked(cset); - spin_unlock_bh(&css_set_lock); + spin_unlock_irqrestore(&css_set_lock, flags); } /* @@ -1014,11 +1016,11 @@ static struct css_set *find_css_set(struct css_set *old_cset, /* First see if we already have a cgroup group that matches * the desired set */ - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); cset = find_existing_css_set(old_cset, cgrp, template); if (cset) get_css_set(cset); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); if (cset) return cset; @@ -1046,7 +1048,7 @@ static struct css_set *find_css_set(struct css_set *old_cset, * find_existing_css_set() */ memcpy(cset->subsys, template, sizeof(cset->subsys)); - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); /* Add reference counts and links from the new css_set. */ list_for_each_entry(link, &old_cset->cgrp_links, cgrp_link) { struct cgroup *c = link->cgrp; @@ -1072,7 +1074,7 @@ static struct css_set *find_css_set(struct css_set *old_cset, css_get(css); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); return cset; } @@ -1136,7 +1138,7 @@ static void cgroup_destroy_root(struct cgroup_root *root) * Release all the links from cset_links to this hierarchy's * root cgroup */ - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_for_each_entry_safe(link, tmp_link, &cgrp->cset_links, cset_link) { list_del(&link->cset_link); @@ -1144,7 +1146,7 @@ static void cgroup_destroy_root(struct cgroup_root *root) kfree(link); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); if (!list_empty(&root->root_list)) { list_del(&root->root_list); @@ -1548,11 +1550,11 @@ static int rebind_subsystems(struct cgroup_root *dst_root, ss->root = dst_root; css->cgroup = dcgrp; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); hash_for_each(css_set_table, i, cset, hlist) list_move_tail(&cset->e_cset_node[ss->id], &dcgrp->e_csets[ss->id]); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); src_root->subsys_mask &= ~(1 << ssid); scgrp->subtree_control &= ~(1 << ssid); @@ -1829,7 +1831,7 @@ static void cgroup_enable_task_cg_lists(void) { struct task_struct *p, *g; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); if (use_task_css_set_links) goto out_unlock; @@ -1854,8 +1856,12 @@ static void cgroup_enable_task_cg_lists(void) * entry won't be deleted though the process has exited. * Do it while holding siglock so that we don't end up * racing against cgroup_exit(). + * + * Interrupts were already disabled while acquiring + * the css_set_lock, so we do not need to disable it + * again when acquiring the sighand->siglock here. */ - spin_lock_irq(&p->sighand->siglock); + spin_lock(&p->sighand->siglock); if (!(p->flags & PF_EXITING)) { struct css_set *cset = task_css_set(p); @@ -1864,11 +1870,11 @@ static void cgroup_enable_task_cg_lists(void) list_add_tail(&p->cg_list, &cset->tasks); get_css_set(cset); } - spin_unlock_irq(&p->sighand->siglock); + spin_unlock(&p->sighand->siglock); } while_each_thread(g, p); read_unlock(&tasklist_lock); out_unlock: - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); } static void init_cgroup_housekeeping(struct cgroup *cgrp) @@ -1973,13 +1979,13 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned long ss_mask) * Link the root cgroup in this hierarchy into all the css_set * objects. */ - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); hash_for_each(css_set_table, i, cset, hlist) { link_css_set(&tmp_links, cset, root_cgrp); if (css_set_populated(cset)) cgroup_update_populated(root_cgrp, true); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); BUG_ON(!list_empty(&root_cgrp->self.children)); BUG_ON(atomic_read(&root->nr_cgrps) != 1); @@ -2212,7 +2218,7 @@ char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen) char *path = NULL; mutex_lock(&cgroup_mutex); - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); root = idr_get_next(&cgroup_hierarchy_idr, &hierarchy_id); @@ -2225,7 +2231,7 @@ char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen) path = buf; } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); mutex_unlock(&cgroup_mutex); return path; } @@ -2400,7 +2406,7 @@ static int cgroup_taskset_migrate(struct cgroup_taskset *tset, * the new cgroup. There are no failure cases after here, so this * is the commit point. */ - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_for_each_entry(cset, &tset->src_csets, mg_node) { list_for_each_entry_safe(task, tmp_task, &cset->mg_tasks, cg_list) { struct css_set *from_cset = task_css_set(task); @@ -2411,7 +2417,7 @@ static int cgroup_taskset_migrate(struct cgroup_taskset *tset, put_css_set_locked(from_cset); } } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); /* * Migration is committed, all target tasks are now on dst_csets. @@ -2440,13 +2446,13 @@ out_cancel_attach: } } out_release_tset: - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_splice_init(&tset->dst_csets, &tset->src_csets); list_for_each_entry_safe(cset, tmp_cset, &tset->src_csets, mg_node) { list_splice_tail_init(&cset->mg_tasks, &cset->tasks); list_del_init(&cset->mg_node); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); return ret; } @@ -2463,14 +2469,14 @@ static void cgroup_migrate_finish(struct list_head *preloaded_csets) lockdep_assert_held(&cgroup_mutex); - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_for_each_entry_safe(cset, tmp_cset, preloaded_csets, mg_preload_node) { cset->mg_src_cgrp = NULL; cset->mg_dst_cset = NULL; list_del_init(&cset->mg_preload_node); put_css_set_locked(cset); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); } /** @@ -2620,7 +2626,7 @@ static int cgroup_migrate(struct task_struct *leader, bool threadgroup, * already PF_EXITING could be freed from underneath us unless we * take an rcu_read_lock. */ - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); rcu_read_lock(); task = leader; do { @@ -2629,7 +2635,7 @@ static int cgroup_migrate(struct task_struct *leader, bool threadgroup, break; } while_each_thread(leader, task); rcu_read_unlock(); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); return cgroup_taskset_migrate(&tset, cgrp); } @@ -2650,7 +2656,7 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp, int ret; /* look up all src csets */ - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); rcu_read_lock(); task = leader; do { @@ -2660,7 +2666,7 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp, break; } while_each_thread(leader, task); rcu_read_unlock(); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); /* prepare dst csets and commit */ ret = cgroup_migrate_prepare_dst(dst_cgrp, &preloaded_csets); @@ -2748,9 +2754,9 @@ static int cgroup_procs_write_permission(struct task_struct *task, struct cgroup *cgrp; struct inode *inode; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); cgrp = task_cgroup_from_root(task, &cgrp_dfl_root); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); while (!cgroup_is_descendant(dst_cgrp, cgrp)) cgrp = cgroup_parent(cgrp); @@ -2851,9 +2857,9 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk) if (root == &cgrp_dfl_root) continue; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); from_cgrp = task_cgroup_from_root(from, root); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); retval = cgroup_attach_task(from_cgrp, tsk, false); if (retval) @@ -2978,7 +2984,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp) percpu_down_write(&cgroup_threadgroup_rwsem); /* look up all csses currently attached to @cgrp's subtree */ - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); css_for_each_descendant_pre(css, cgroup_css(cgrp, NULL)) { struct cgrp_cset_link *link; @@ -2990,14 +2996,14 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp) cgroup_migrate_add_src(link->cset, cgrp, &preloaded_csets); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); /* NULL dst indicates self on default hierarchy */ ret = cgroup_migrate_prepare_dst(NULL, &preloaded_csets); if (ret) goto out_finish; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_for_each_entry(src_cset, &preloaded_csets, mg_preload_node) { struct task_struct *task, *ntask; @@ -3009,7 +3015,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp) list_for_each_entry_safe(task, ntask, &src_cset->tasks, cg_list) cgroup_taskset_add(task, &tset); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); ret = cgroup_taskset_migrate(&tset, cgrp); out_finish: @@ -3692,10 +3698,10 @@ static int cgroup_task_count(const struct cgroup *cgrp) int count = 0; struct cgrp_cset_link *link; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_for_each_entry(link, &cgrp->cset_links, cset_link) count += atomic_read(&link->cset->refcount); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); return count; } @@ -4033,7 +4039,7 @@ void css_task_iter_start(struct cgroup_subsys_state *css, memset(it, 0, sizeof(*it)); - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); it->ss = css->ss; @@ -4046,7 +4052,7 @@ void css_task_iter_start(struct cgroup_subsys_state *css, css_task_iter_advance_css_set(it); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); } /** @@ -4064,7 +4070,7 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it) it->cur_task = NULL; } - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); if (it->task_pos) { it->cur_task = list_entry(it->task_pos, struct task_struct, @@ -4073,7 +4079,7 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it) css_task_iter_advance(it); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); return it->cur_task; } @@ -4087,10 +4093,10 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it) void css_task_iter_end(struct css_task_iter *it) { if (it->cur_cset) { - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_del(&it->iters_node); put_css_set_locked(it->cur_cset); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); } if (it->cur_task) @@ -4119,10 +4125,10 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) mutex_lock(&cgroup_mutex); /* all tasks in @from are being moved, all csets are source */ - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_for_each_entry(link, &from->cset_links, cset_link) cgroup_migrate_add_src(link->cset, to, &preloaded_csets); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); ret = cgroup_migrate_prepare_dst(to, &preloaded_csets); if (ret) @@ -5226,10 +5232,10 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) */ cgrp->self.flags &= ~CSS_ONLINE; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_for_each_entry(link, &cgrp->cset_links, cset_link) link->cset->dead = true; - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); /* initiate massacre of all css's */ for_each_css(css, ssid, cgrp) @@ -5488,7 +5494,7 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns, goto out; mutex_lock(&cgroup_mutex); - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); for_each_root(root) { struct cgroup_subsys *ss; @@ -5540,7 +5546,7 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns, retval = 0; out_unlock: - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); mutex_unlock(&cgroup_mutex); kfree(buf); out: @@ -5701,13 +5707,13 @@ void cgroup_post_fork(struct task_struct *child, if (use_task_css_set_links) { struct css_set *cset; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); cset = task_css_set(current); if (list_empty(&child->cg_list)) { get_css_set(cset); css_set_move_task(child, NULL, cset, false); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); } /* @@ -5751,9 +5757,9 @@ void cgroup_exit(struct task_struct *tsk) cset = task_css_set(tsk); if (!list_empty(&tsk->cg_list)) { - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); css_set_move_task(tsk, cset, NULL, false); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); } else { get_css_set(cset); } @@ -5819,7 +5825,9 @@ static void cgroup_release_agent(struct work_struct *work) if (!pathbuf || !agentbuf) goto out; + spin_lock_irq(&css_set_lock); path = cgroup_path(cgrp, pathbuf, PATH_MAX); + spin_unlock_irq(&css_set_lock); if (!path) goto out; @@ -5966,7 +5974,7 @@ static int current_css_set_cg_links_read(struct seq_file *seq, void *v) if (!name_buf) return -ENOMEM; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); rcu_read_lock(); cset = rcu_dereference(current->cgroups); list_for_each_entry(link, &cset->cgrp_links, cgrp_link) { @@ -5977,7 +5985,7 @@ static int current_css_set_cg_links_read(struct seq_file *seq, void *v) c->root->hierarchy_id, name_buf); } rcu_read_unlock(); - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); kfree(name_buf); return 0; } @@ -5988,7 +5996,7 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v) struct cgroup_subsys_state *css = seq_css(seq); struct cgrp_cset_link *link; - spin_lock_bh(&css_set_lock); + spin_lock_irq(&css_set_lock); list_for_each_entry(link, &css->cgroup->cset_links, cset_link) { struct css_set *cset = link->cset; struct task_struct *task; @@ -6011,7 +6019,7 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v) overflow: seq_puts(seq, " ...\n"); } - spin_unlock_bh(&css_set_lock); + spin_unlock_irq(&css_set_lock); return 0; } diff --git a/kernel/drivers/input/touchscreen/Kconfig b/kernel/drivers/input/touchscreen/Kconfig deleted file mode 100644 index 18655c0b3997..000000000000 --- a/kernel/drivers/input/touchscreen/Kconfig +++ /dev/null @@ -1,721 +0,0 @@ -# -# Touchscreen driver configuration -# -menuconfig INPUT_TOUCHSCREEN - bool "Touchscreens" - help - Say Y here, and a list of supported touchscreens will be displayed. - This option doesn't affect the kernel. - - If unsure, say Y. - -if INPUT_TOUCHSCREEN - -config TOUCHSCREEN_88PM860X - tristate "Marvell 88PM860x touchscreen" - depends on MFD_88PM860X - help - Say Y here if you have a 88PM860x PMIC and want to enable - support for the built-in touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called 88pm860x-ts. - -config TOUCHSCREEN_ADS7846 - tristate "ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens" - depends on SPI_MASTER - depends on HWMON = n || HWMON - help - Say Y here if you have a touchscreen interface using the - ADS7846/TSC2046/AD7873 or ADS7843/AD7843 controller, - and your board-specific setup code includes that in its - table of SPI devices. - - If HWMON is selected, and the driver is told the reference voltage - on your board, you will also get hwmon interfaces for the voltage - (and on ads7846/tsc2046/ad7873, temperature) sensors of this chip. - - If unsure, say N (but it's safe to say "Y"). - - To compile this driver as a module, choose M here: the - module will be called ads7846. - -config TOUCHSCREEN_AD7877 - tristate "AD7877 based touchscreens" - depends on SPI_MASTER - help - Say Y here if you have a touchscreen interface using the - AD7877 controller, and your board-specific initialization - code includes that in its table of SPI devices. - - If unsure, say N (but it's safe to say "Y"). - - To compile this driver as a module, choose M here: the - module will be called ad7877. - -config TOUCHSCREEN_AD7879 - tristate "Analog Devices AD7879-1/AD7889-1 touchscreen interface" - help - Say Y here if you want to support a touchscreen interface using - the AD7879-1/AD7889-1 controller. - - You should select a bus connection too. - - To compile this driver as a module, choose M here: the - module will be called ad7879. - -config TOUCHSCREEN_AD7879_I2C - tristate "support I2C bus connection" - depends on TOUCHSCREEN_AD7879 && I2C - help - Say Y here if you have AD7879-1/AD7889-1 hooked to an I2C bus. - - To compile this driver as a module, choose M here: the - module will be called ad7879-i2c. - -config TOUCHSCREEN_AD7879_SPI - tristate "support SPI bus connection" - depends on TOUCHSCREEN_AD7879 && SPI_MASTER - help - Say Y here if you have AD7879-1/AD7889-1 hooked to a SPI bus. - - If unsure, say N (but it's safe to say "Y"). - - To compile this driver as a module, choose M here: the - module will be called ad7879-spi. - -config TOUCHSCREEN_BITSY - tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" - depends on SA1100_BITSY - select SERIO - help - Say Y here if you have the h3600 (Bitsy) touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called h3600_ts_input. - -config TOUCHSCREEN_BU21013 - tristate "BU21013 based touch panel controllers" - depends on I2C - help - Say Y here if you have a bu21013 touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called bu21013_ts. - -config TOUCHSCREEN_CY8CTMG110 - tristate "cy8ctmg110 touchscreen" - depends on I2C - depends on GPIOLIB - - help - Say Y here if you have a cy8ctmg110 capacitive touchscreen on - an AAVA device. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called cy8ctmg110_ts. - -config TOUCHSCREEN_DA9034 - tristate "Touchscreen support for Dialog Semiconductor DA9034" - depends on PMIC_DA903X - default y - help - Say Y here to enable the support for the touchscreen found - on Dialog Semiconductor DA9034 PMIC. - -config TOUCHSCREEN_DYNAPRO - tristate "Dynapro serial touchscreen" - select SERIO - help - Say Y here if you have a Dynapro serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called dynapro. - -config TOUCHSCREEN_HAMPSHIRE - tristate "Hampshire serial touchscreen" - select SERIO - help - Say Y here if you have a Hampshire serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called hampshire. - -config TOUCHSCREEN_EETI - tristate "EETI touchscreen panel support" - depends on I2C - help - Say Y here to enable support for I2C connected EETI touch panels. - - To compile this driver as a module, choose M here: the - module will be called eeti_ts. - -config TOUCHSCREEN_FUJITSU - tristate "Fujitsu serial touchscreen" - select SERIO - help - Say Y here if you have the Fujitsu touchscreen (such as one - installed in Lifebook P series laptop) connected to your - system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called fujitsu-ts. - -config TOUCHSCREEN_S3C2410 - tristate "Samsung S3C2410/generic touchscreen input driver" - depends on ARCH_S3C2410 || SAMSUNG_DEV_TS - select S3C_ADC - help - Say Y here if you have the s3c2410 touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called s3c2410_ts. - -config TOUCHSCREEN_GUNZE - tristate "Gunze AHL-51S touchscreen" - select SERIO - help - Say Y here if you have the Gunze AHL-51 touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called gunze. - -config TOUCHSCREEN_ELO - tristate "Elo serial touchscreens" - select SERIO - help - Say Y here if you have an Elo serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called elo. - -config TOUCHSCREEN_WACOM_W8001 - tristate "Wacom W8001 penabled serial touchscreen" - select SERIO - help - Say Y here if you have an Wacom W8001 penabled serial touchscreen - connected to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called wacom_w8001. - -config TOUCHSCREEN_LPC32XX - tristate "LPC32XX touchscreen controller" - depends on ARCH_LPC32XX - help - Say Y here if you have a LPC32XX device and want - to support the built-in touchscreen. - - To compile this driver as a module, choose M here: the - module will be called lpc32xx_ts. - -config TOUCHSCREEN_MCS5000 - tristate "MELFAS MCS-5000 touchscreen" - depends on I2C - help - Say Y here if you have the MELFAS MCS-5000 touchscreen controller - chip in your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mcs5000_ts. - -config TOUCHSCREEN_MTOUCH - tristate "MicroTouch serial touchscreens" - select SERIO - help - Say Y here if you have a MicroTouch (3M) serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mtouch. - -config TOUCHSCREEN_INEXIO - tristate "iNexio serial touchscreens" - select SERIO - help - Say Y here if you have an iNexio serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called inexio. - -config TOUCHSCREEN_INTEL_MID - tristate "Intel MID platform resistive touchscreen" - depends on INTEL_SCU_IPC - help - Say Y here if you have a Intel MID based touchscreen in - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called intel_mid_touch. - -config TOUCHSCREEN_MK712 - tristate "ICS MicroClock MK712 touchscreen" - help - Say Y here if you have the ICS MicroClock MK712 touchscreen - controller chip in your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mk712. - -config TOUCHSCREEN_HP600 - tristate "HP Jornada 6xx touchscreen" - depends on SH_HP6XX && SH_ADC - help - Say Y here if you have a HP Jornada 620/660/680/690 and want to - support the built-in touchscreen. - - To compile this driver as a module, choose M here: the - module will be called hp680_ts_input. - -config TOUCHSCREEN_HP7XX - tristate "HP Jornada 7xx touchscreen" - depends on SA1100_JORNADA720_SSP - help - Say Y here if you have a HP Jornada 710/720/728 and want - to support the built-in touchscreen. - - To compile this driver as a module, choose M here: the - module will be called jornada720_ts. - -config TOUCHSCREEN_HTCPEN - tristate "HTC Shift X9500 touchscreen" - depends on ISA - help - Say Y here if you have an HTC Shift UMPC also known as HTC X9500 - Clio / Shangrila and want to support the built-in touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called htcpen. - -config TOUCHSCREEN_PENMOUNT - tristate "Penmount serial touchscreen" - select SERIO - help - Say Y here if you have a Penmount serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called penmount. - -config TOUCHSCREEN_QT602240 - tristate "QT602240 I2C Touchscreen" - depends on I2C - help - Say Y here if you have the AT42QT602240/ATMXT224 I2C touchscreen - connected to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called qt602240_ts. - -config TOUCHSCREEN_MIGOR - tristate "Renesas MIGO-R touchscreen" - depends on SH_MIGOR && I2C - help - Say Y here to enable MIGO-R touchscreen support. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called migor_ts. - -config TOUCHSCREEN_TNETV107X - tristate "TI TNETV107X touchscreen support" - depends on ARCH_DAVINCI_TNETV107X - help - Say Y here if you want to use the TNETV107X touchscreen. - - To compile this driver as a module, choose M here: the - module will be called tnetv107x-ts. - -config TOUCHSCREEN_SYNAPTICS_I2C_RMI4 - tristate "Synaptics DSX I2C touchscreen" - depends on I2C - help - Say Y here if you have a Synaptics DSX I2C touchscreen - connected to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called synaptics_i2c_rmi4. - -config TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV - tristate "Synaptics I2C touchscreen rmi device" - depends on TOUCHSCREEN_SYNAPTICS_I2C_RMI4 - help - This enables support for character device channel for Synaptics RMI - touchscreens. - -config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE - tristate "Synaptics I2C touchscreen firmware update" - depends on TOUCHSCREEN_SYNAPTICS_I2C_RMI4 - help - This enables support for firmware update for Synaptics RMI - touchscreens. - -config TOUCHSCREEN_TOUCHRIGHT - tristate "Touchright serial touchscreen" - select SERIO - help - Say Y here if you have a Touchright serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called touchright. - -config TOUCHSCREEN_TOUCHWIN - tristate "Touchwin serial touchscreen" - select SERIO - help - Say Y here if you have a Touchwin serial touchscreen connected to - your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called touchwin. - -config TOUCHSCREEN_ATMEL_TSADCC - tristate "Atmel Touchscreen Interface" - depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 - help - Say Y here if you have a 4-wire touchscreen connected to the - ADC Controller on your Atmel SoC (such as the AT91SAM9RL). - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called atmel_tsadcc. - -config TOUCHSCREEN_UCB1400 - tristate "Philips UCB1400 touchscreen" - depends on AC97_BUS - depends on UCB1400_CORE - help - This enables support for the Philips UCB1400 touchscreen interface. - The UCB1400 is an AC97 audio codec. The touchscreen interface - will be initialized only after the ALSA subsystem has been - brought up and the UCB1400 detected. You therefore have to - configure ALSA support as well (either built-in or modular, - independently of whether this driver is itself built-in or - modular) for this driver to work. - - To compile this driver as a module, choose M here: the - module will be called ucb1400_ts. - -config TOUCHSCREEN_WM97XX - tristate "Support for WM97xx AC97 touchscreen controllers" - depends on AC97_BUS - help - Say Y here if you have a Wolfson Microelectronics WM97xx - touchscreen connected to your system. Note that this option - only enables core driver, you will also need to select - support for appropriate chip below. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called wm97xx-ts. - -config TOUCHSCREEN_WM9705 - bool "WM9705 Touchscreen interface support" - depends on TOUCHSCREEN_WM97XX - default y - help - Say Y here to enable support for the Wolfson Microelectronics - WM9705 touchscreen controller. - -config TOUCHSCREEN_WM9712 - bool "WM9712 Touchscreen interface support" - depends on TOUCHSCREEN_WM97XX - default y - help - Say Y here to enable support for the Wolfson Microelectronics - WM9712 touchscreen controller. - -config TOUCHSCREEN_WM9713 - bool "WM9713 Touchscreen interface support" - depends on TOUCHSCREEN_WM97XX - default y - help - Say Y here to enable support for the Wolfson Microelectronics - WM9713 touchscreen controller. - -config TOUCHSCREEN_WM97XX_ATMEL - tristate "WM97xx Atmel accelerated touch" - depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91) - help - Say Y here for support for streaming mode with WM97xx touchscreens - on Atmel AT91 or AVR32 systems with an AC97C module. - - Be aware that this will use channel B in the controller for - streaming data, this must not conflict with other AC97C drivers. - - If unsure, say N. - - To compile this driver as a module, choose M here: the module will - be called atmel-wm97xx. - -config TOUCHSCREEN_WM97XX_MAINSTONE - tristate "WM97xx Mainstone/Palm accelerated touch" - depends on TOUCHSCREEN_WM97XX && ARCH_PXA - help - Say Y here for support for streaming mode with WM97xx touchscreens - on Mainstone, Palm Tungsten T5, TX and LifeDrive systems. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mainstone-wm97xx. - -config TOUCHSCREEN_WM97XX_ZYLONITE - tristate "Zylonite accelerated touch" - depends on TOUCHSCREEN_WM97XX && MACH_ZYLONITE - select TOUCHSCREEN_WM9713 - help - Say Y here for support for streaming mode with the touchscreen - on Zylonite systems. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called zylonite-wm97xx. - -config TOUCHSCREEN_USB_COMPOSITE - tristate "USB Touchscreen Driver" - depends on USB_ARCH_HAS_HCD - select USB - help - USB Touchscreen driver for: - - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700) - - PanJit TouchSet USB - - 3M MicroTouch USB (EX II series) - - ITM - - some other eTurboTouch - - Gunze AHL61 - - DMC TSC-10/25 - - IRTOUCHSYSTEMS/UNITOP - - IdealTEK URTC1000 - - GoTop Super_Q2/GogoPen/PenPower tablets - - JASTEC USB Touch Controller/DigiTech DTR-02U - - Zytronic controllers - - Have a look at <http://linux.chapter7.ch/touchkit/> for - a usage description and the required user-space stuff. - - To compile this driver as a module, choose M here: the - module will be called usbtouchscreen. - -config TOUCHSCREEN_MC13783 - tristate "Freescale MC13783 touchscreen input driver" - depends on MFD_MC13783 - help - Say Y here if you have an Freescale MC13783 PMIC on your - board and want to use its touchscreen - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mc13783_ts. - -config TOUCHSCREEN_USB_EGALAX - default y - bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_PANJIT - default y - bool "PanJit device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_3M - default y - bool "3M/Microtouch EX II series device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_ITM - default y - bool "ITM device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_ETURBO - default y - bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_GUNZE - default y - bool "Gunze AHL61 device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_DMC_TSC10 - default y - bool "DMC TSC-10/25 device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_IRTOUCH - default y - bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_IDEALTEK - default y - bool "IdealTEK URTC1000 device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_GENERAL_TOUCH - default y - bool "GeneralTouch Touchscreen device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_GOTOP - default y - bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_JASTEC - default y - bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_E2I - default y - bool "e2i Touchscreen controller (e.g. from Mimo 740)" - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_ZYTRONIC - default y - bool "Zytronic controller" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_ETT_TC45USB - default y - bool "ET&T USB series TC4UM/TC5UH touchscreen controler support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_USB_NEXIO - default y - bool "NEXIO/iNexio device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -config TOUCHSCREEN_TOUCHIT213 - tristate "Sahara TouchIT-213 touchscreen" - select SERIO - help - Say Y here if you have a Sahara TouchIT-213 Tablet PC. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called touchit213. - -config TOUCHSCREEN_TSC2007 - tristate "TSC2007 based touchscreens" - depends on I2C - help - Say Y here if you have a TSC2007 based touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called tsc2007. - -config TOUCHSCREEN_TSC2004 - tristate "TSC2004 based touchscreens" - depends on I2C - help - Say Y here if you have a TSC2004 based touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called tsc2004. - -config TOUCHSCREEN_W90X900 - tristate "W90P910 touchscreen driver" - depends on HAVE_CLK - help - Say Y here if you have a W90P910 based touchscreen. - - To compile this driver as a module, choose M here: the - module will be called w90p910_ts. - -config TOUCHSCREEN_PCAP - tristate "Motorola PCAP touchscreen" - depends on EZX_PCAP - help - Say Y here if you have a Motorola EZX telephone and - want to enable support for the built-in touchscreen. - - To compile this driver as a module, choose M here: the - module will be called pcap_ts. - -config TOUCHSCREEN_TPS6507X - tristate "TPS6507x based touchscreens" - depends on I2C - help - Say Y here if you have a TPS6507x based touchscreen - controller. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called tps6507x_ts. - -config TOUCHSCREEN_STMPE - tristate "STMicroelectronics STMPE touchscreens" - depends on MFD_STMPE - help - Say Y here if you want support for STMicroelectronics - STMPE touchscreen controllers. - - To compile this driver as a module, choose M here: the - module will be called stmpe-ts. - -endif diff --git a/kernel/drivers/input/touchscreen/Makefile b/kernel/drivers/input/touchscreen/Makefile deleted file mode 100644 index a6c7d9f388a6..000000000000 --- a/kernel/drivers/input/touchscreen/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# -# Makefile for the touchscreen drivers. -# - -# Each configuration option enables a list of files. - -wm97xx-ts-y := wm97xx-core.o - -obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o -obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o -obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o -obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o -obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o -obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o -obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o -obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o -obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o -obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o -obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o -obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o -obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o -obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o -obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o -obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o -obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o -obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o -obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o -obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o -obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o -obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o -obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o -obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o -obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o -obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o -obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o -obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o -obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o -obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o -obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o -obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o -obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o -obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o -obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV) += synaptics_rmi_dev.o -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_fw_update.o -obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o -obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o -obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o -obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o -obj-$(CONFIG_TOUCHSCREEN_TSC2004) += tsc2004.o -obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o -obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o -obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o -wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o -wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o -wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o -obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o -obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o -obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o -obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o -obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o - -all: -make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules - -clean: -make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean diff --git a/kernel/drivers/input/touchscreen/synaptics_fw_update.c b/kernel/drivers/input/touchscreen/synaptics_fw_update.c deleted file mode 100644 index 8b6d7c7e368d..000000000000 --- a/kernel/drivers/input/touchscreen/synaptics_fw_update.c +++ /dev/null @@ -1,1698 +0,0 @@ -/* - * Synaptics RMI4 touchscreen driver - * - * Copyright (C) 2012 Synaptics Incorporated - * - * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> - * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> - * - * 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 - * (at your option) any later version. - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/input.h> -#include <linux/firmware.h> -#include <linux/input/synaptics_dsx.h> -#include "synaptics_i2c_rmi4.h" - -#define DEBUG_FW_UPDATE -#define SHOW_PROGRESS -#define FW_IMAGE_NAME "PR1063486-s7301_00000000.img" -#define MAX_FIRMWARE_ID_LEN 10 -#define FORCE_UPDATE false -#define INSIDE_FIRMWARE_UPDATE - -#define CHECKSUM_OFFSET 0x00 -#define BOOTLOADER_VERSION_OFFSET 0x07 -#define IMAGE_SIZE_OFFSET 0x08 -#define CONFIG_SIZE_OFFSET 0x0C -#define PRODUCT_ID_OFFSET 0x10 -#define PRODUCT_INFO_OFFSET 0x1E -#define FW_IMAGE_OFFSET 0x100 -#define PRODUCT_ID_SIZE 10 - -#define BOOTLOADER_ID_OFFSET 0 -#define FLASH_PROPERTIES_OFFSET 2 -#define BLOCK_SIZE_OFFSET 3 -#define FW_BLOCK_COUNT_OFFSET 5 - -#define REG_MAP (1 << 0) -#define UNLOCKED (1 << 1) -#define HAS_CONFIG_ID (1 << 2) -#define HAS_PERM_CONFIG (1 << 3) -#define HAS_BL_CONFIG (1 << 4) -#define HAS_DISP_CONFIG (1 << 5) -#define HAS_CTRL1 (1 << 6) - -#define BLOCK_NUMBER_OFFSET 0 -#define BLOCK_DATA_OFFSET 2 - -#define UI_CONFIG_AREA 0x00 -#define PERM_CONFIG_AREA 0x01 -#define BL_CONFIG_AREA 0x02 -#define DISP_CONFIG_AREA 0x03 - -enum flash_command { - CMD_WRITE_FW_BLOCK = 0x2, - CMD_ERASE_ALL = 0x3, - CMD_READ_CONFIG_BLOCK = 0x5, - CMD_WRITE_CONFIG_BLOCK = 0x6, - CMD_ERASE_CONFIG = 0x7, - CMD_ERASE_BL_CONFIG = 0x9, - CMD_ERASE_DISP_CONFIG = 0xA, - CMD_ENABLE_FLASH_PROG = 0xF, -}; - -enum flash_area { - NONE, - UI_FIRMWARE, - CONFIG_AREA -}; - -#define SLEEP_MODE_NORMAL (0x00) -#define SLEEP_MODE_SENSOR_SLEEP (0x01) -#define SLEEP_MODE_RESERVED0 (0x02) -#define SLEEP_MODE_RESERVED1 (0x03) - -#define ENABLE_WAIT_MS (1 * 1000) -#define WRITE_WAIT_MS (3 * 1000) -#define ERASE_WAIT_MS (5 * 1000) -#define RESET_WAIT_MS (500) - -#define SLEEP_TIME_US 50 - -static ssize_t fwu_sysfs_show_image(struct file *data_file, - struct kobject *kobj, struct bin_attribute *attributes, - char *buf, loff_t pos, size_t count); - -static ssize_t fwu_sysfs_store_image(struct file *data_file, - struct kobject *kobj, struct bin_attribute *attributes, - char *buf, loff_t pos, size_t count); - -static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t fwu_sysfs_write_config_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t fwu_sysfs_read_config_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t fwu_sysfs_config_area_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t fwu_sysfs_image_size_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t fwu_sysfs_block_size_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static int fwu_wait_for_idle(int timeout_ms); - -struct image_header { - unsigned int checksum; - unsigned int image_size; - unsigned int config_size; - unsigned char options; - unsigned char bootloader_version; - unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1]; - unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE]; -}; - -struct pdt_properties { - union { - struct { - unsigned char reserved_1:6; - unsigned char has_bsr:1; - unsigned char reserved_2:1; - } __packed; - unsigned char data[1]; - }; -}; - -struct f01_device_status { - union { - struct { - unsigned char status_code:4; - unsigned char reserved:2; - unsigned char flash_prog:1; - unsigned char unconfigured:1; - } __packed; - unsigned char data[1]; - }; -}; - -struct f01_device_control { - union { - struct { - unsigned char sleep_mode:2; - unsigned char nosleep:1; - unsigned char reserved:2; - unsigned char charger_connected:1; - unsigned char report_rate:1; - unsigned char configured:1; - } __packed; - unsigned char data[1]; - }; -}; - -struct f34_flash_control { - union { - struct { - unsigned char command:4; - unsigned char status:3; - unsigned char program_enabled:1; - } __packed; - unsigned char data[1]; - }; -}; - -struct f34_flash_properties { - union { - struct { - unsigned char regmap:1; - unsigned char unlocked:1; - unsigned char has_configid:1; - unsigned char has_perm_config:1; - unsigned char has_bl_config:1; - unsigned char has_display_config:1; - unsigned char has_blob_config:1; - unsigned char reserved:1; - } __packed; - unsigned char data[1]; - }; -}; - -struct synaptics_rmi4_fwu_handle { - bool initialized; - bool force_update; - char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1]; - unsigned int image_size; - unsigned int data_pos; - unsigned char intr_mask; - unsigned char bootloader_id[2]; - unsigned char productinfo1; - unsigned char productinfo2; - unsigned char *ext_data_source; - unsigned char *read_config_buf; - const unsigned char *firmware_data; - const unsigned char *config_data; - unsigned short block_size; - unsigned short fw_block_count; - unsigned short config_block_count; - unsigned short perm_config_block_count; - unsigned short bl_config_block_count; - unsigned short disp_config_block_count; - unsigned short config_size; - unsigned short config_area; - unsigned short addr_f34_flash_control; - unsigned short addr_f01_interrupt_register; - struct synaptics_rmi4_fn_desc f01_fd; - struct synaptics_rmi4_fn_desc f34_fd; - struct synaptics_rmi4_exp_fn_ptr *fn_ptr; - struct synaptics_rmi4_data *rmi4_data; - struct f34_flash_control flash_control; - struct f34_flash_properties flash_properties; - struct workqueue_struct *fwu_workqueue; - struct delayed_work fwu_work; -}; - -static struct bin_attribute dev_attr_data = { - .attr = { - .name = "data", - .mode = (S_IRUGO | S_IWUGO), - }, - .size = 0, - .read = fwu_sysfs_show_image, - .write = fwu_sysfs_store_image, -}; - -static struct device_attribute attrs[] = { - __ATTR(doreflash, S_IWUGO, - synaptics_rmi4_show_error, - fwu_sysfs_do_reflash_store), - __ATTR(writeconfig, S_IWUGO, - synaptics_rmi4_show_error, - fwu_sysfs_write_config_store), - __ATTR(readconfig, S_IWUGO, - synaptics_rmi4_show_error, - fwu_sysfs_read_config_store), - __ATTR(configarea, S_IWUGO, - synaptics_rmi4_show_error, - fwu_sysfs_config_area_store), - __ATTR(imagesize, S_IWUGO, - synaptics_rmi4_show_error, - fwu_sysfs_image_size_store), - __ATTR(blocksize, S_IRUGO, - fwu_sysfs_block_size_show, - synaptics_rmi4_store_error), - __ATTR(fwblockcount, S_IRUGO, - fwu_sysfs_firmware_block_count_show, - synaptics_rmi4_store_error), - __ATTR(configblockcount, S_IRUGO, - fwu_sysfs_configuration_block_count_show, - synaptics_rmi4_store_error), - __ATTR(permconfigblockcount, S_IRUGO, - fwu_sysfs_perm_config_block_count_show, - synaptics_rmi4_store_error), - __ATTR(blconfigblockcount, S_IRUGO, - fwu_sysfs_bl_config_block_count_show, - synaptics_rmi4_store_error), - __ATTR(dispconfigblockcount, S_IRUGO, - fwu_sysfs_disp_config_block_count_show, - synaptics_rmi4_store_error), -}; - -static struct synaptics_rmi4_fwu_handle *fwu; - -static struct completion remove_complete; - -static unsigned int extract_uint(const unsigned char *ptr) -{ - return (unsigned int)ptr[0] + - (unsigned int)ptr[1] * 0x100 + - (unsigned int)ptr[2] * 0x10000 + - (unsigned int)ptr[3] * 0x1000000; -} - -static void parse_header(struct image_header *header, - const unsigned char *fw_image) -{ - header->checksum = extract_uint(&fw_image[CHECKSUM_OFFSET]); - header->bootloader_version = fw_image[BOOTLOADER_VERSION_OFFSET]; - header->image_size = extract_uint(&fw_image[IMAGE_SIZE_OFFSET]); - header->config_size = extract_uint(&fw_image[CONFIG_SIZE_OFFSET]); - memcpy(header->product_id, &fw_image[PRODUCT_ID_OFFSET], - SYNAPTICS_RMI4_PRODUCT_ID_SIZE); - header->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0; - memcpy(header->product_info, &fw_image[PRODUCT_INFO_OFFSET], - SYNAPTICS_RMI4_PRODUCT_INFO_SIZE); - -#ifdef DEBUG_FW_UPDATE - dev_info(&fwu->rmi4_data->i2c_client->dev, - "Firwmare size %d, config size %d\n", - header->image_size, - header->config_size); -#endif - return; -} - -static int fwu_read_f01_device_status(struct f01_device_status *status) -{ - int retval; - - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f01_fd.data_base_addr, - status->data, - sizeof(status->data)); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to read F01 device status\n", - __func__); - return retval; - } - - return 0; -} - -static int fwu_read_f34_queries(void) -{ - int retval; - unsigned char count = 4; - unsigned char buf[10]; - struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client; - - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f34_fd.query_base_addr + BOOTLOADER_ID_OFFSET, - fwu->bootloader_id, - sizeof(fwu->bootloader_id)); - if (retval < 0) { - dev_err(&i2c_client->dev, - "%s: Failed to read bootloader ID\n", - __func__); - return retval; - } - - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f34_fd.query_base_addr + FLASH_PROPERTIES_OFFSET, - fwu->flash_properties.data, - sizeof(fwu->flash_properties.data)); - if (retval < 0) { - dev_err(&i2c_client->dev, - "%s: Failed to read flash properties\n", - __func__); - return retval; - } - - dev_info(&i2c_client->dev, "%s perm:%d, bl:%d, display:%d\n", - __func__, - fwu->flash_properties.has_perm_config, - fwu->flash_properties.has_bl_config, - fwu->flash_properties.has_display_config); - - if (fwu->flash_properties.has_perm_config) - count += 2; - - if (fwu->flash_properties.has_bl_config) - count += 2; - - if (fwu->flash_properties.has_display_config) - count += 2; - - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f34_fd.query_base_addr + BLOCK_SIZE_OFFSET, - buf, - 2); - if (retval < 0) { - dev_err(&i2c_client->dev, - "%s: Failed to read block size info\n", - __func__); - return retval; - } - - batohs(&fwu->block_size, &(buf[0])); - - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f34_fd.query_base_addr + FW_BLOCK_COUNT_OFFSET, - buf, - count); - if (retval < 0) { - dev_err(&i2c_client->dev, - "%s: Failed to read block count info\n", - __func__); - return retval; - } - - batohs(&fwu->fw_block_count, &(buf[0])); - batohs(&fwu->config_block_count, &(buf[2])); - - count = 4; - - if (fwu->flash_properties.has_perm_config) { - batohs(&fwu->perm_config_block_count, &(buf[count])); - count += 2; - } - - if (fwu->flash_properties.has_bl_config) { - batohs(&fwu->bl_config_block_count, &(buf[count])); - count += 2; - } - - if (fwu->flash_properties.has_display_config) - batohs(&fwu->disp_config_block_count, &(buf[count])); - - fwu->addr_f34_flash_control = fwu->f34_fd.data_base_addr + - BLOCK_DATA_OFFSET + - fwu->block_size; - return 0; -} - -static int fwu_read_interrupt_status(void) -{ - int retval; - unsigned char interrupt_status; - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->addr_f01_interrupt_register, - &interrupt_status, - sizeof(interrupt_status)); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to read flash status\n", - __func__); - return retval; - } - return interrupt_status; -} - -static int fwu_read_f34_flash_status(void) -{ - int retval; - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->addr_f34_flash_control, - fwu->flash_control.data, - sizeof(fwu->flash_control.data)); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to read flash status\n", - __func__); - return retval; - } - return 0; -} - -static int fwu_reset_device(void) -{ - int retval; - -#ifdef DEBUG_FW_UPDATE - dev_info(&fwu->rmi4_data->i2c_client->dev, - "%s: Reset device\n", - __func__); -#endif - - retval = fwu->rmi4_data->reset_device(fwu->rmi4_data); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to reset core driver after reflash\n", - __func__); - return retval; - } - return 0; -} - -static int fwu_write_f34_command(unsigned char cmd) -{ - int retval; - - fwu->flash_control.data[0] = cmd; - retval = fwu->fn_ptr->write(fwu->rmi4_data, - fwu->addr_f34_flash_control, - fwu->flash_control.data, - sizeof(fwu->flash_control.data)); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to write command 0x%02x\n", - __func__, fwu->flash_control.data[0]); - return retval; - } - return 0; -} - -static int fwu_wait_for_idle(int timeout_ms) -{ - int count = 0; - int timeout_count = ((timeout_ms * 1000) / SLEEP_TIME_US) + 1; - do { - if (fwu->flash_control.command == 0x00) - return 0; - - usleep_range(SLEEP_TIME_US, SLEEP_TIME_US + 100); - } while (count++ < timeout_count); - - fwu_read_f34_flash_status(); - if (fwu->flash_control.command == 0x00) - return 0; - - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Timed out waiting for idle status\n", - __func__); - - return -ETIMEDOUT; -} - -static enum flash_area fwu_go_nogo(void) -{ - int retval = 0; - int index = 0; - int deviceFirmwareID; - int imageConfigID; - int deviceConfigID; - unsigned long imageFirmwareID; - unsigned char firmware_id[4]; - unsigned char config_id[4]; - char *strptr; - char *imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL); - enum flash_area flash_area = NONE; - struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client; - struct f01_device_status f01_device_status; - - if (fwu->force_update) { - flash_area = UI_FIRMWARE; - goto exit; - } - - retval = fwu_read_f01_device_status(&f01_device_status); - if (retval < 0) { - flash_area = NONE; - goto exit; - } - - imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL); - - /* Force update firmware when device is in bootloader mode */ - if (f01_device_status.flash_prog) { - dev_info(&i2c_client->dev, - "%s: In flash prog mode\n", - __func__); - flash_area = UI_FIRMWARE; - goto exit; - } - - - /* device firmware id */ - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f01_fd.query_base_addr + 18, - firmware_id, - sizeof(firmware_id)); - if (retval < 0) { - dev_err(&i2c_client->dev, - "Failed to read firmware ID (code %d).\n", retval); - goto exit; - } - firmware_id[3] = 0; - deviceFirmwareID = extract_uint(firmware_id); - - /* .img firmware id */ - strptr = strstr(FW_IMAGE_NAME, "PR"); - if (!strptr) { - dev_err(&i2c_client->dev, - "No valid PR number (PRxxxxxxx)" \ - "found in image file name...\n"); - goto exit; - } - - strptr += 2; - while (strptr[index] >= '0' && strptr[index] <= '9') { - imagePR[index] = strptr[index]; - index++; - } - imagePR[index] = 0; - - retval = sstrtoul(imagePR, 10, &imageFirmwareID); - if (retval == -EINVAL) { - dev_err(&i2c_client->dev, - "invalid image firmware id...\n"); - goto exit; - } - - dev_info(&i2c_client->dev, - "Device firmware id %d, .img firmware id %d\n", - deviceFirmwareID, - (unsigned int)imageFirmwareID); - if (imageFirmwareID > deviceFirmwareID) { - flash_area = UI_FIRMWARE; - goto exit; - } - - /* device config id */ - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f34_fd.ctrl_base_addr, - config_id, - sizeof(config_id)); - if (retval < 0) { - dev_err(&i2c_client->dev, - "Failed to read config ID (code %d).\n", retval); - flash_area = NONE; - goto exit; - } - deviceConfigID = extract_uint(config_id); - - dev_info(&i2c_client->dev, - "Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", - config_id[0], config_id[1], config_id[2], config_id[3]); - - /* .img config id */ - dev_info(&i2c_client->dev, - ".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", - fwu->config_data[0], - fwu->config_data[1], - fwu->config_data[2], - fwu->config_data[3]); - imageConfigID = extract_uint(fwu->config_data); - - if (imageConfigID > deviceConfigID) { - flash_area = CONFIG_AREA; - goto exit; - } - -exit: - kfree(imagePR); - if (flash_area == NONE) - dev_info(&i2c_client->dev, - "Nothing needs to be updated\n"); - else - dev_info(&i2c_client->dev, - "Update %s block\n", - flash_area == UI_FIRMWARE ? "UI FW" : "CONFIG"); - return flash_area; -} - -static int fwu_scan_pdt(void) -{ - int retval; - unsigned char ii; - unsigned char intr_count = 0; - unsigned char intr_off; - unsigned char intr_src; - unsigned short addr; - bool f01found = false; - bool f34found = false; - struct synaptics_rmi4_fn_desc rmi_fd; - -#ifdef DEBUG_FW_UPDATE - dev_info(&fwu->rmi4_data->i2c_client->dev, "Scan PDT\n"); -#endif - - for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { - retval = fwu->fn_ptr->read(fwu->rmi4_data, - addr, - (unsigned char *)&rmi_fd, - sizeof(rmi_fd)); - if (retval < 0) - return retval; - - if (rmi_fd.fn_number) { - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Found F%02x\n", - __func__, rmi_fd.fn_number); - switch (rmi_fd.fn_number) { - case SYNAPTICS_RMI4_F01: - f01found = true; - fwu->f01_fd = rmi_fd; - fwu->addr_f01_interrupt_register = - fwu->f01_fd.data_base_addr + 1; - break; - case SYNAPTICS_RMI4_F34: - f34found = true; - fwu->f34_fd = rmi_fd; - fwu->intr_mask = 0; - intr_src = rmi_fd.intr_src_count; - intr_off = intr_count % 8; - for (ii = intr_off; - ii < ((intr_src & MASK_3BIT) + - intr_off); - ii++) - fwu->intr_mask |= 1 << ii; - break; - } - } else - break; - - intr_count += (rmi_fd.intr_src_count & MASK_3BIT); - } - - if (!f01found || !f34found) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to find both F01 and F34\n", - __func__); - return -EINVAL; - } - - fwu_read_interrupt_status(); - return 0; -} - -static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt, - unsigned char command) -{ - int retval; - unsigned char block_offset[] = {0, 0}; - unsigned short block_num; - struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client; -#ifdef SHOW_PROGRESS - unsigned int progress = (command == CMD_WRITE_CONFIG_BLOCK) ? - 10 : 100; -#endif - -#ifdef DEBUG_FW_UPDATE - dev_info(&i2c_client->dev, - "%s: Start to update %s blocks\n", - __func__, - command == CMD_WRITE_CONFIG_BLOCK ? - "config" : "firmware"); -#endif - retval = fwu->fn_ptr->write(fwu->rmi4_data, - fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET, - block_offset, - sizeof(block_offset)); - if (retval < 0) { - dev_err(&i2c_client->dev, - "%s: Failed to write to block number registers\n", - __func__); - return retval; - } - - for (block_num = 0; block_num < block_cnt; block_num++) { -#ifdef SHOW_PROGRESS - if (block_num % progress == 0) - dev_info(&i2c_client->dev, - "%s: update %s %3d / %3d\n", - __func__, - command == CMD_WRITE_CONFIG_BLOCK ? - "config" : "firmware", - block_num, block_cnt); -#endif - retval = fwu->fn_ptr->write(fwu->rmi4_data, - fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET, - block_ptr, - fwu->block_size); - if (retval < 0) { - dev_err(&i2c_client->dev, - "%s: Failed to write block data (block %d)\n", - __func__, block_num); - return retval; - } - - retval = fwu_write_f34_command(command); - if (retval < 0) { - dev_err(&i2c_client->dev, - "%s: Failed to write command for block %d\n", - __func__, block_num); - return retval; - } - - retval = fwu_wait_for_idle(WRITE_WAIT_MS); - if (retval < 0) { - dev_err(&i2c_client->dev, - "%s: Failed to wait for idle status (block %d)\n", - __func__, block_num); - return retval; - } - - if (fwu->flash_control.status != 0x00) { - dev_err(&i2c_client->dev, - "%s: Flash block %d failed, status 0x%02X\n", - __func__, block_num, retval); - return -1; - } - - block_ptr += fwu->block_size; - } -#ifdef SHOW_PROGRESS - dev_info(&i2c_client->dev, - "%s: update %s %3d / %3d\n", - __func__, - command == CMD_WRITE_CONFIG_BLOCK ? - "config" : "firmware", - block_cnt, block_cnt); -#endif - return 0; -} - -static int fwu_write_firmware(void) -{ - return fwu_write_blocks((unsigned char *)fwu->firmware_data, - fwu->fw_block_count, CMD_WRITE_FW_BLOCK); -} - -static int fwu_write_configuration(void) -{ - return fwu_write_blocks((unsigned char *)fwu->config_data, - fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK); -} - -static int fwu_write_bootloader_id(void) -{ - int retval; - -#ifdef DEBUG_FW_UPDATE - dev_info(&fwu->rmi4_data->i2c_client->dev, - "Write bootloader ID 0x%02X 0x%02X\n", - fwu->bootloader_id[0], - fwu->bootloader_id[1]); -#endif - retval = fwu->fn_ptr->write(fwu->rmi4_data, - fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET, - fwu->bootloader_id, - sizeof(fwu->bootloader_id)); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to write bootloader ID\n", - __func__); - return retval; - } - - return 0; -} - -static int fwu_enter_flash_prog(void) -{ - int retval; - struct f01_device_status f01_device_status; - struct f01_device_control f01_device_control; - -#ifdef DEBUG_FW_UPDATE - dev_info(&fwu->rmi4_data->i2c_client->dev, "Enter bootloader mode\n"); -#endif - retval = fwu_read_f01_device_status(&f01_device_status); - if (retval < 0) - return retval; - - if (f01_device_status.flash_prog) { - dev_info(&fwu->rmi4_data->i2c_client->dev, - "%s: Already in flash prog mode\n", - __func__); - return 0; - } - - retval = fwu_write_bootloader_id(); - if (retval < 0) - return retval; - - retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG); - if (retval < 0) - return retval; - - retval = fwu_wait_for_idle(ENABLE_WAIT_MS); - if (retval < 0) - return retval; - - retval = fwu_scan_pdt(); - if (retval < 0) - return retval; - - retval = fwu_read_f01_device_status(&f01_device_status); - if (retval < 0) - return retval; - - if (!f01_device_status.flash_prog) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Not in flash prog mode\n", - __func__); - return -EINVAL; - } - - retval = fwu_read_f34_queries(); - if (retval < 0) - return retval; - - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f01_fd.ctrl_base_addr, - f01_device_control.data, - sizeof(f01_device_control.data)); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to read F01 device control\n", - __func__); - return retval; - } - - f01_device_control.nosleep = true; - f01_device_control.sleep_mode = SLEEP_MODE_NORMAL; - - retval = fwu->fn_ptr->write(fwu->rmi4_data, - fwu->f01_fd.ctrl_base_addr, - f01_device_control.data, - sizeof(f01_device_control.data)); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to write F01 device control\n", - __func__); - return retval; - } - - return retval; -} - -static int fwu_do_reflash(void) -{ - int retval; - - retval = fwu_enter_flash_prog(); - if (retval < 0) - return retval; - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Entered flash prog mode\n", - __func__); - - retval = fwu_write_bootloader_id(); - if (retval < 0) - return retval; - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Bootloader ID written\n", - __func__); - - retval = fwu_write_f34_command(CMD_ERASE_ALL); - if (retval < 0) - return retval; - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Erase all command written\n", - __func__); - - retval = fwu_wait_for_idle(ERASE_WAIT_MS); - if (retval < 0) - return retval; - - if (fwu->flash_control.status != 0x00) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Erase all command failed, status 0x%02X\n", - __func__, retval); - return -1; - } - - if (fwu->firmware_data) { - retval = fwu_write_firmware(); - if (retval < 0) - return retval; - pr_notice("%s: Firmware programmed\n", __func__); - } - - if (fwu->config_data) { - retval = fwu_write_configuration(); - if (retval < 0) - return retval; - pr_notice("%s: Configuration programmed\n", __func__); - } - - return retval; -} - -static int fwu_do_write_config(void) -{ - int retval; - - retval = fwu_enter_flash_prog(); - if (retval < 0) - return retval; - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Entered flash prog mode\n", - __func__); - - if (fwu->config_area == PERM_CONFIG_AREA) { - fwu->config_block_count = fwu->perm_config_block_count; - goto write_config; - } - - retval = fwu_write_bootloader_id(); - if (retval < 0) - return retval; - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Bootloader ID written\n", - __func__); - - switch (fwu->config_area) { - case UI_CONFIG_AREA: - retval = fwu_write_f34_command(CMD_ERASE_CONFIG); - break; - case BL_CONFIG_AREA: - retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG); - fwu->config_block_count = fwu->bl_config_block_count; - break; - case DISP_CONFIG_AREA: - retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG); - fwu->config_block_count = fwu->disp_config_block_count; - break; - } - if (retval < 0) - return retval; - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Erase command written\n", - __func__); - - retval = fwu_wait_for_idle(ERASE_WAIT_MS); - if (retval < 0) - return retval; - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Idle status detected\n", - __func__); - -write_config: - retval = fwu_write_configuration(); - if (retval < 0) - return retval; - - pr_notice("%s: Config written\n", __func__); - - return retval; -} - -static int fwu_start_write_config(void) -{ - int retval; - struct image_header header; - - switch (fwu->config_area) { - case UI_CONFIG_AREA: - break; - case PERM_CONFIG_AREA: - if (!fwu->flash_properties.has_perm_config) - return -EINVAL; - break; - case BL_CONFIG_AREA: - if (!fwu->flash_properties.has_bl_config) - return -EINVAL; - break; - case DISP_CONFIG_AREA: - if (!fwu->flash_properties.has_display_config) - return -EINVAL; - break; - default: - return -EINVAL; - } - - if (fwu->ext_data_source) - fwu->config_data = fwu->ext_data_source; - else - return -EINVAL; - - if (fwu->config_area == UI_CONFIG_AREA) { - parse_header(&header, fwu->ext_data_source); - - if (header.config_size) { - fwu->config_data = fwu->ext_data_source + - FW_IMAGE_OFFSET + - header.image_size; - } else { - return -EINVAL; - } - } - - pr_notice("%s: Start of write config process\n", __func__); - - retval = fwu_do_write_config(); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to write config\n", - __func__); - } - - fwu->rmi4_data->reset_device(fwu->rmi4_data); - - pr_notice("%s: End of write config process\n", __func__); - - return retval; -} - -static int fwu_do_read_config(void) -{ - int retval; - unsigned char block_offset[] = {0, 0}; - unsigned short block_num; - unsigned short block_count; - unsigned short index = 0; - - retval = fwu_enter_flash_prog(); - if (retval < 0) - goto exit; - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Entered flash prog mode\n", - __func__); - - switch (fwu->config_area) { - case UI_CONFIG_AREA: - block_count = fwu->config_block_count; - break; - case PERM_CONFIG_AREA: - if (!fwu->flash_properties.has_perm_config) { - retval = -EINVAL; - goto exit; - } - block_count = fwu->perm_config_block_count; - break; - case BL_CONFIG_AREA: - if (!fwu->flash_properties.has_bl_config) { - retval = -EINVAL; - goto exit; - } - block_count = fwu->bl_config_block_count; - break; - case DISP_CONFIG_AREA: - if (!fwu->flash_properties.has_display_config) { - retval = -EINVAL; - goto exit; - } - block_count = fwu->disp_config_block_count; - break; - default: - retval = -EINVAL; - goto exit; - } - - fwu->config_size = fwu->block_size * block_count; - - kfree(fwu->read_config_buf); - fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL); - - block_offset[1] |= (fwu->config_area << 5); - - retval = fwu->fn_ptr->write(fwu->rmi4_data, - fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET, - block_offset, - sizeof(block_offset)); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to write to block number registers\n", - __func__); - goto exit; - } - - for (block_num = 0; block_num < block_count; block_num++) { - retval = fwu_write_f34_command(CMD_READ_CONFIG_BLOCK); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to write read config command\n", - __func__); - goto exit; - } - - retval = fwu_wait_for_idle(WRITE_WAIT_MS); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to wait for idle status\n", - __func__); - goto exit; - } - - retval = fwu->fn_ptr->read(fwu->rmi4_data, - fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET, - &fwu->read_config_buf[index], - fwu->block_size); - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to read block data (block %d)\n", - __func__, block_num); - goto exit; - } - - index += fwu->block_size; - } - -exit: - fwu->rmi4_data->reset_device(fwu->rmi4_data); - - return retval; -} - -static int fwu_start_reflash(void) -{ - int retval; - struct image_header header; - const unsigned char *fw_image; - const struct firmware *fw_entry = NULL; - struct f01_device_status f01_device_status; - enum flash_area flash_area; - - pr_notice("%s: Start of reflash process\n", __func__); - - if (fwu->ext_data_source) - fw_image = fwu->ext_data_source; - else { - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Requesting firmware image %s\n", - __func__, FW_IMAGE_NAME); - - retval = request_firmware(&fw_entry, FW_IMAGE_NAME, - &fwu->rmi4_data->i2c_client->dev); - if (retval != 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Firmware image %s not available\n", - __func__, FW_IMAGE_NAME); - retval = -EINVAL; - goto exit; - } - - dev_dbg(&fwu->rmi4_data->i2c_client->dev, - "%s: Firmware image size = %d\n", - __func__, fw_entry->size); - - fw_image = fw_entry->data; - } - - parse_header(&header, fw_image); - - if (header.image_size) - fwu->firmware_data = fw_image + FW_IMAGE_OFFSET; - if (header.config_size) { - fwu->config_data = fw_image + FW_IMAGE_OFFSET + - header.image_size; - } - - if (fwu->ext_data_source) - flash_area = UI_FIRMWARE; - else - flash_area = fwu_go_nogo(); - - switch (flash_area) { - case NONE: - dev_info(&fwu->rmi4_data->i2c_client->dev, - "%s: No need to do reflash.\n", - __func__); - goto exit; - case UI_FIRMWARE: - retval = fwu_do_reflash(); - break; - case CONFIG_AREA: - retval = fwu_do_write_config(); - break; - default: - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Unknown flash area\n", - __func__); - goto exit; - } - - if (retval < 0) { - dev_err(&fwu->rmi4_data->i2c_client->dev, - "%s: Failed to do reflash\n", - __func__); - } - - /* reset device */ - fwu_reset_device(); - - /* check device status */ - retval = fwu_read_f01_device_status(&f01_device_status); - if (retval < 0) - goto exit; - - dev_info(&fwu->rmi4_data->i2c_client->dev, "Device is in %s mode\n", - f01_device_status.flash_prog == 1 ? "bootloader" : "UI"); - if (f01_device_status.flash_prog) - dev_info(&fwu->rmi4_data->i2c_client->dev, "Flash status %d\n", - f01_device_status.status_code); - - if (f01_device_status.flash_prog) { - dev_info(&fwu->rmi4_data->i2c_client->dev, - "%s: Device is in flash prog mode 0x%02X\n", - __func__, f01_device_status.status_code); - retval = 0; - goto exit; - } - - if (fw_entry) - release_firmware(fw_entry); - - pr_notice("%s: End of reflash process\n", __func__); -exit: - return retval; -} - -int synaptics_fw_updater(unsigned char *fw_data) -{ - int retval; - - if (!fwu) - return -ENODEV; - - if (!fwu->initialized) - return -ENODEV; - - fwu->ext_data_source = fw_data; - fwu->config_area = UI_CONFIG_AREA; - - retval = fwu_start_reflash(); - - return retval; -} -EXPORT_SYMBOL(synaptics_fw_updater); - -static ssize_t fwu_sysfs_show_image(struct file *data_file, - struct kobject *kobj, struct bin_attribute *attributes, - char *buf, loff_t pos, size_t count) -{ - struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; - - if (count < fwu->config_size) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Not enough space (%d bytes) in buffer\n", - __func__, count); - return -EINVAL; - } - - memcpy(buf, fwu->read_config_buf, fwu->config_size); - - return fwu->config_size; -} - -static ssize_t fwu_sysfs_store_image(struct file *data_file, - struct kobject *kobj, struct bin_attribute *attributes, - char *buf, loff_t pos, size_t count) -{ - memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]), - (const void *)buf, - count); - - fwu->data_pos += count; - - return count; -} - -static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int retval; - unsigned int input; - struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; - - if (sscanf(buf, "%u", &input) != 1) { - retval = -EINVAL; - goto exit; - } - - if (input != 1) { - retval = -EINVAL; - goto exit; - } - - retval = synaptics_fw_updater(fwu->ext_data_source); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to do reflash\n", - __func__); - goto exit; - } - - retval = count; - -exit: - kfree(fwu->ext_data_source); - fwu->ext_data_source = NULL; - return retval; -} - -static ssize_t fwu_sysfs_write_config_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int retval; - unsigned int input; - struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; - - if (sscanf(buf, "%u", &input) != 1) { - retval = -EINVAL; - goto exit; - } - - if (input != 1) { - retval = -EINVAL; - goto exit; - } - - retval = fwu_start_write_config(); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to write config\n", - __func__); - goto exit; - } - - retval = count; - -exit: - kfree(fwu->ext_data_source); - fwu->ext_data_source = NULL; - return retval; -} - -static ssize_t fwu_sysfs_read_config_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int retval; - unsigned int input; - struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; - - if (sscanf(buf, "%u", &input) != 1) - return -EINVAL; - - if (input != 1) - return -EINVAL; - - retval = fwu_do_read_config(); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to read config\n", - __func__); - return retval; - } - - return count; -} - -static ssize_t fwu_sysfs_config_area_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int retval; - unsigned long config_area; - - retval = sstrtoul(buf, 10, &config_area); - if (retval) - return retval; - - fwu->config_area = config_area; - - return count; -} - -static ssize_t fwu_sysfs_image_size_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int retval; - unsigned long size; - struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; - - retval = sstrtoul(buf, 10, &size); - if (retval) - return retval; - - fwu->image_size = size; - fwu->data_pos = 0; - - kfree(fwu->ext_data_source); - fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL); - if (!fwu->ext_data_source) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for image data\n", - __func__); - return -ENOMEM; - } - - return count; -} - -static ssize_t fwu_sysfs_block_size_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size); -} - -static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", fwu->fw_block_count); -} - -static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", fwu->config_block_count); -} - -static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", fwu->perm_config_block_count); -} - -static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", fwu->bl_config_block_count); -} - -static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count); -} - -static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, - unsigned char intr_mask) -{ - if (fwu->intr_mask & intr_mask) - fwu_read_f34_flash_status(); - - return; -} - -static void synaptics_rmi4_fwu_work(struct work_struct *work) -{ - fwu_start_reflash(); -} - -static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - unsigned char attr_count; - struct pdt_properties pdt_props; - - fwu = kzalloc(sizeof(*fwu), GFP_KERNEL); - if (!fwu) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for fwu\n", - __func__); - goto exit; - } - - fwu->fn_ptr = kzalloc(sizeof(*(fwu->fn_ptr)), GFP_KERNEL); - if (!fwu->fn_ptr) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for fn_ptr\n", - __func__); - retval = -ENOMEM; - goto exit_free_fwu; - } - - fwu->rmi4_data = rmi4_data; - fwu->fn_ptr->read = rmi4_data->i2c_read; - fwu->fn_ptr->write = rmi4_data->i2c_write; - fwu->fn_ptr->enable = rmi4_data->irq_enable; - - retval = fwu->fn_ptr->read(rmi4_data, - PDT_PROPS, - pdt_props.data, - sizeof(pdt_props.data)); - if (retval < 0) { - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Failed to read PDT properties, assuming 0x00\n", - __func__); - } else if (pdt_props.has_bsr) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Reflash for LTS not currently supported\n", - __func__); - goto exit_free_mem; - } - - retval = fwu_scan_pdt(); - if (retval < 0) - goto exit_free_mem; - - fwu->productinfo1 = rmi4_data->rmi4_mod_info.product_info[0]; - fwu->productinfo2 = rmi4_data->rmi4_mod_info.product_info[1]; - - memcpy(fwu->product_id, rmi4_data->rmi4_mod_info.product_id_string, - SYNAPTICS_RMI4_PRODUCT_ID_SIZE); - fwu->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0; - - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: F01 product info: 0x%04x 0x%04x\n", - __func__, fwu->productinfo1, fwu->productinfo2); - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: F01 product ID: %s\n", - __func__, fwu->product_id); - - retval = fwu_read_f34_queries(); - if (retval < 0) - goto exit_free_mem; - - fwu->initialized = true; - fwu->force_update = FORCE_UPDATE; - - retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, - &dev_attr_data); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to create sysfs bin file\n", - __func__); - goto exit_free_mem; - } - - for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { - retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, - &attrs[attr_count].attr); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to create sysfs attributes\n", - __func__); - retval = -ENODEV; - goto exit_remove_attrs; - } - } - -#ifdef INSIDE_FIRMWARE_UPDATE - fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); - INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work); - queue_delayed_work(fwu->fwu_workqueue, - &fwu->fwu_work, - msecs_to_jiffies(1000)); -#endif - return 0; - -exit_remove_attrs: -for (attr_count--; attr_count >= 0; attr_count--) { - sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, - &attrs[attr_count].attr); -} - -sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); - -exit_free_mem: - kfree(fwu->fn_ptr); - -exit_free_fwu: - kfree(fwu); - -exit: - return 0; -} - -static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) -{ - unsigned char attr_count; - - sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); - - for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { - sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, - &attrs[attr_count].attr); - } - - kfree(fwu->fn_ptr); - kfree(fwu); - - complete(&remove_complete); - - return; -} - -static int __init rmi4_fw_update_module_init(void) -{ - synaptics_rmi4_new_function(RMI_FW_UPDATER, true, - synaptics_rmi4_fwu_init, - synaptics_rmi4_fwu_remove, - synaptics_rmi4_fwu_attn); - return 0; -} - -static void __exit rmi4_fw_update_module_exit(void) -{ - init_completion(&remove_complete); - synaptics_rmi4_new_function(RMI_FW_UPDATER, false, - synaptics_rmi4_fwu_init, - synaptics_rmi4_fwu_remove, - synaptics_rmi4_fwu_attn); - wait_for_completion(&remove_complete); - return; -} - -module_init(rmi4_fw_update_module_init); -module_exit(rmi4_fw_update_module_exit); - -MODULE_AUTHOR("Synaptics, Inc."); -MODULE_DESCRIPTION("RMI4 FW Update Module"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION); diff --git a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c deleted file mode 100644 index 76f9155bd49c..000000000000 --- a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c +++ /dev/null @@ -1,2162 +0,0 @@ -/* - * Synaptics RMI4 touchscreen driver - * - * Copyright (C) 2012 Synaptics Incorporated - * - * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> - * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> - * - * 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 - * (at your option) any later version. - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/input.h> -#include <linux/gpio.h> -#include <linux/regulator/consumer.h> -#include <linux/input/synaptics_dsx.h> -#include "synaptics_i2c_rmi4.h" -#ifdef KERNEL_ABOVE_2_6_38 -#include <linux/input/mt.h> -#endif - -#define DRIVER_NAME "synaptics_rmi4_i2c" -#define INPUT_PHYS_NAME "synaptics_rmi4_i2c/input0" - -#ifdef KERNEL_ABOVE_2_6_38 -#define TYPE_B_PROTOCOL -#endif - -#define NO_0D_WHILE_2D -/* -#define REPORT_2D_Z -*/ -#define REPORT_2D_W - -#define RPT_TYPE (1 << 0) -#define RPT_X_LSB (1 << 1) -#define RPT_X_MSB (1 << 2) -#define RPT_Y_LSB (1 << 3) -#define RPT_Y_MSB (1 << 4) -#define RPT_Z (1 << 5) -#define RPT_WX (1 << 6) -#define RPT_WY (1 << 7) -#define RPT_DEFAULT (RPT_TYPE | RPT_X_LSB | RPT_X_MSB | RPT_Y_LSB | RPT_Y_MSB) - -#define EXP_FN_DET_INTERVAL 1000 /* ms */ -#define POLLING_PERIOD 1 /* ms */ -#define SYN_I2C_RETRY_TIMES 10 -#define MAX_ABS_MT_TOUCH_MAJOR 15 - -#define F01_STD_QUERY_LEN 21 -#define F01_BUID_ID_OFFSET 18 -#define F11_STD_QUERY_LEN 9 -#define F11_STD_CTRL_LEN 10 -#define F11_STD_DATA_LEN 12 - -#define NORMAL_OPERATION (0 << 0) -#define SENSOR_SLEEP (1 << 0) -#define NO_SLEEP_OFF (0 << 3) -#define NO_SLEEP_ON (1 << 3) - -static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, - unsigned short addr, unsigned char *data, - unsigned short length); - -static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, - unsigned short addr, unsigned char *data, - unsigned short length); - -static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data); - -#ifdef CONFIG_HAS_EARLYSUSPEND -static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static void synaptics_rmi4_early_suspend(struct early_suspend *h); - -static void synaptics_rmi4_late_resume(struct early_suspend *h); - -static int synaptics_rmi4_suspend(struct device *dev); - -static int synaptics_rmi4_resume(struct device *dev); -#endif - -static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -struct synaptics_rmi4_f01_device_status { - union { - struct { - unsigned char status_code:4; - unsigned char reserved:2; - unsigned char flash_prog:1; - unsigned char unconfigured:1; - } __packed; - unsigned char data[1]; - }; -}; - -struct synaptics_rmi4_f1a_query { - union { - struct { - unsigned char max_button_count:3; - unsigned char reserved:5; - unsigned char has_general_control:1; - unsigned char has_interrupt_enable:1; - unsigned char has_multibutton_select:1; - unsigned char has_tx_rx_map:1; - unsigned char has_perbutton_threshold:1; - unsigned char has_release_threshold:1; - unsigned char has_strongestbtn_hysteresis:1; - unsigned char has_filter_strength:1; - } __packed; - unsigned char data[2]; - }; -}; - -struct synaptics_rmi4_f1a_control_0 { - union { - struct { - unsigned char multibutton_report:2; - unsigned char filter_mode:2; - unsigned char reserved:4; - } __packed; - unsigned char data[1]; - }; -}; - -struct synaptics_rmi4_f1a_control_3_4 { - unsigned char transmitterbutton; - unsigned char receiverbutton; -}; - -struct synaptics_rmi4_f1a_control { - struct synaptics_rmi4_f1a_control_0 general_control; - unsigned char *button_int_enable; - unsigned char *multi_button; - struct synaptics_rmi4_f1a_control_3_4 *electrode_map; - unsigned char *button_threshold; - unsigned char button_release_threshold; - unsigned char strongest_button_hysteresis; - unsigned char filter_strength; -}; - -struct synaptics_rmi4_f1a_handle { - int button_bitmask_size; - unsigned char button_count; - unsigned char valid_button_count; - unsigned char *button_data_buffer; - unsigned char *button_map; - struct synaptics_rmi4_f1a_query button_query; - struct synaptics_rmi4_f1a_control button_control; -}; - -struct synaptics_rmi4_exp_fn { - enum exp_fn fn_type; - bool inserted; - int (*func_init)(struct synaptics_rmi4_data *rmi4_data); - void (*func_remove)(struct synaptics_rmi4_data *rmi4_data); - void (*func_attn)(struct synaptics_rmi4_data *rmi4_data, - unsigned char intr_mask); - struct list_head link; -}; - -static struct device_attribute attrs[] = { -#ifdef CONFIG_HAS_EARLYSUSPEND - __ATTR(full_pm_cycle, (S_IRUGO | S_IWUGO), - synaptics_rmi4_full_pm_cycle_show, - synaptics_rmi4_full_pm_cycle_store), -#endif - __ATTR(reset, S_IWUGO, - synaptics_rmi4_show_error, - synaptics_rmi4_f01_reset_store), - __ATTR(productinfo, S_IRUGO, - synaptics_rmi4_f01_productinfo_show, - synaptics_rmi4_store_error), - __ATTR(buildid, S_IRUGO, - synaptics_rmi4_f01_buildid_show, - synaptics_rmi4_store_error), - __ATTR(flashprog, S_IRUGO, - synaptics_rmi4_f01_flashprog_show, - synaptics_rmi4_store_error), - __ATTR(0dbutton, (S_IRUGO | S_IWUGO), - synaptics_rmi4_0dbutton_show, - synaptics_rmi4_0dbutton_store), -}; - -static bool exp_fn_inited; -static struct mutex exp_fn_list_mutex; -static struct list_head exp_fn_list; - -#ifdef CONFIG_HAS_EARLYSUSPEND -static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%u\n", - rmi4_data->full_pm_cycle); -} - -static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned int input; - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - - if (sscanf(buf, "%u", &input) != 1) - return -EINVAL; - - rmi4_data->full_pm_cycle = input > 0 ? 1 : 0; - - return count; -} -#endif - -static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int retval; - unsigned int reset; - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - - if (sscanf(buf, "%u", &reset) != 1) - return -EINVAL; - - if (reset != 1) - return -EINVAL; - - retval = synaptics_rmi4_reset_device(rmi4_data); - if (retval < 0) { - dev_err(dev, - "%s: Failed to issue reset command, error = %d\n", - __func__, retval); - return retval; - } - - return count; -} - -static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n", - (rmi4_data->rmi4_mod_info.product_info[0]), - (rmi4_data->rmi4_mod_info.product_info[1])); -} - -static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - unsigned int build_id; - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - struct synaptics_rmi4_device_info *rmi; - - rmi = &(rmi4_data->rmi4_mod_info); - - build_id = (unsigned int)rmi->build_id[0] + - (unsigned int)rmi->build_id[1] * 0x100 + - (unsigned int)rmi->build_id[2] * 0x10000; - - return snprintf(buf, PAGE_SIZE, "%u\n", - build_id); -} - -static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int retval; - struct synaptics_rmi4_f01_device_status device_status; - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_data_base_addr, - device_status.data, - sizeof(device_status.data)); - if (retval < 0) { - dev_err(dev, - "%s: Failed to read device status, error = %d\n", - __func__, retval); - return retval; - } - - return snprintf(buf, PAGE_SIZE, "%u\n", - device_status.flash_prog); -} - -static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%u\n", - rmi4_data->button_0d_enabled); -} - -static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int retval; - unsigned int input; - unsigned char ii; - unsigned char intr_enable; - struct synaptics_rmi4_fn *fhandler; - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - struct synaptics_rmi4_device_info *rmi; - - rmi = &(rmi4_data->rmi4_mod_info); - - if (sscanf(buf, "%u", &input) != 1) - return -EINVAL; - - input = input > 0 ? 1 : 0; - - if (rmi4_data->button_0d_enabled == input) - return count; - - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, &rmi->support_fn_list, link) { - if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) { - ii = fhandler->intr_reg_num; - - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_ctrl_base_addr + - 1 + ii, - &intr_enable, - sizeof(intr_enable)); - if (retval < 0) - return retval; - - if (input == 1) - intr_enable |= fhandler->intr_mask; - else - intr_enable &= ~fhandler->intr_mask; - - retval = synaptics_rmi4_i2c_write(rmi4_data, - rmi4_data->f01_ctrl_base_addr + - 1 + ii, - &intr_enable, - sizeof(intr_enable)); - if (retval < 0) - return retval; - } - } - } - - rmi4_data->button_0d_enabled = input; - - return count; -} - - /** - * synaptics_rmi4_set_page() - * - * Called by synaptics_rmi4_i2c_read() and synaptics_rmi4_i2c_write(). - * - * This function writes to the page select register to switch to the - * assigned page. - */ -static int synaptics_rmi4_set_page(struct synaptics_rmi4_data *rmi4_data, - unsigned int address) -{ - int retval = 0; - unsigned char retry; - unsigned char buf[PAGE_SELECT_LEN]; - unsigned char page; - struct i2c_client *i2c = rmi4_data->i2c_client; - - page = ((address >> 8) & MASK_8BIT); - if (page != rmi4_data->current_page) { - buf[0] = MASK_8BIT; - buf[1] = page; - for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { - retval = i2c_master_send(i2c, buf, PAGE_SELECT_LEN); - if (retval != PAGE_SELECT_LEN) { - dev_err(&i2c->dev, - "%s: I2C retry %d\n", - __func__, retry + 1); - msleep(20); - } else { - rmi4_data->current_page = page; - break; - } - } - } else - return PAGE_SELECT_LEN; - return (retval == PAGE_SELECT_LEN) ? retval : -EIO; -} - - /** - * synaptics_rmi4_i2c_read() - * - * Called by various functions in this driver, and also exported to - * other expansion Function modules such as rmi_dev. - * - * This function reads data of an arbitrary length from the sensor, - * starting from an assigned register address of the sensor, via I2C - * with a retry mechanism. - */ -static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, - unsigned short addr, unsigned char *data, unsigned short length) -{ - int retval; - unsigned char retry; - unsigned char buf; - struct i2c_msg msg[] = { - { - .addr = rmi4_data->i2c_client->addr, - .flags = 0, - .len = 1, - .buf = &buf, - }, - { - .addr = rmi4_data->i2c_client->addr, - .flags = I2C_M_RD, - .len = length, - .buf = data, - }, - }; - - buf = addr & MASK_8BIT; - - mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex)); - - retval = synaptics_rmi4_set_page(rmi4_data, addr); - if (retval != PAGE_SELECT_LEN) - goto exit; - - for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { - if (i2c_transfer(rmi4_data->i2c_client->adapter, msg, 2) == 2) { - retval = length; - break; - } - dev_err(&rmi4_data->i2c_client->dev, - "%s: I2C retry %d\n", - __func__, retry + 1); - msleep(20); - } - - if (retry == SYN_I2C_RETRY_TIMES) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: I2C read over retry limit\n", - __func__); - retval = -EIO; - } - -exit: - mutex_unlock(&(rmi4_data->rmi4_io_ctrl_mutex)); - - return retval; -} - - /** - * synaptics_rmi4_i2c_write() - * - * Called by various functions in this driver, and also exported to - * other expansion Function modules such as rmi_dev. - * - * This function writes data of an arbitrary length to the sensor, - * starting from an assigned register address of the sensor, via I2C with - * a retry mechanism. - */ -static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, - unsigned short addr, unsigned char *data, unsigned short length) -{ - int retval; - unsigned char retry; - unsigned char buf[length + 1]; - struct i2c_msg msg[] = { - { - .addr = rmi4_data->i2c_client->addr, - .flags = 0, - .len = length + 1, - .buf = buf, - } - }; - - mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex)); - - retval = synaptics_rmi4_set_page(rmi4_data, addr); - if (retval != PAGE_SELECT_LEN) - goto exit; - - buf[0] = addr & MASK_8BIT; - memcpy(&buf[1], &data[0], length); - - for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { - if (i2c_transfer(rmi4_data->i2c_client->adapter, msg, 1) == 1) { - retval = length; - break; - } - dev_err(&rmi4_data->i2c_client->dev, - "%s: I2C retry %d\n", - __func__, retry + 1); - msleep(20); - } - - if (retry == SYN_I2C_RETRY_TIMES) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: I2C write over retry limit\n", - __func__); - retval = -EIO; - } - -exit: - mutex_unlock(&(rmi4_data->rmi4_io_ctrl_mutex)); - - return retval; -} - - /** - * synaptics_rmi4_f11_abs_report() - * - * Called by synaptics_rmi4_report_touch() when valid Function $11 - * finger data has been detected. - * - * This function reads the Function $11 data registers, determines the - * status of each finger supported by the Function, processes any - * necessary coordinate manipulation, reports the finger data to - * the input subsystem, and returns the number of fingers detected. - */ -static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data, - struct synaptics_rmi4_fn *fhandler) -{ - int retval; - unsigned char touch_count = 0; /* number of touch points */ - unsigned char reg_index; - unsigned char finger; - unsigned char fingers_supported; - unsigned char num_of_finger_status_regs; - unsigned char finger_shift; - unsigned char finger_status; - unsigned char data_reg_blk_size; - unsigned char finger_status_reg[3]; - unsigned char data[F11_STD_DATA_LEN]; - unsigned short data_addr; - unsigned short data_offset; - int x; - int y; - int wx; - int wy; - - /* - * The number of finger status registers is determined by the - * maximum number of fingers supported - 2 bits per finger. So - * the number of finger status registers to read is: - * register_count = ceil(max_num_of_fingers / 4) - */ - fingers_supported = fhandler->num_of_data_points; - num_of_finger_status_regs = (fingers_supported + 3) / 4; - data_addr = fhandler->full_addr.data_base; - data_reg_blk_size = fhandler->size_of_data_register_block; - - retval = synaptics_rmi4_i2c_read(rmi4_data, - data_addr, - finger_status_reg, - num_of_finger_status_regs); - if (retval < 0) - return 0; - - for (finger = 0; finger < fingers_supported; finger++) { - reg_index = finger / 4; - finger_shift = (finger % 4) * 2; - finger_status = (finger_status_reg[reg_index] >> finger_shift) - & MASK_2BIT; - - /* - * Each 2-bit finger status field represents the following: - * 00 = finger not present - * 01 = finger present and data accurate - * 10 = finger present but data may be inaccurate - * 11 = reserved - */ -#ifdef TYPE_B_PROTOCOL - input_mt_slot(rmi4_data->input_dev, finger); - input_mt_report_slot_state(rmi4_data->input_dev, - MT_TOOL_FINGER, finger_status != 0); -#endif - - if (finger_status) { - data_offset = data_addr + - num_of_finger_status_regs + - (finger * data_reg_blk_size); - retval = synaptics_rmi4_i2c_read(rmi4_data, - data_offset, - data, - data_reg_blk_size); - if (retval < 0) - return 0; - - x = (data[0] << 4) | (data[2] & MASK_4BIT); - y = (data[1] << 4) | ((data[2] >> 4) & MASK_4BIT); - wx = (data[3] & MASK_4BIT); - wy = (data[3] >> 4) & MASK_4BIT; - - if (rmi4_data->board->x_flip) - x = rmi4_data->sensor_max_x - x; - if (rmi4_data->board->y_flip) - y = rmi4_data->sensor_max_y - y; - - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Finger %d:\n" - "status = 0x%02x\n" - "x = %d\n" - "y = %d\n" - "wx = %d\n" - "wy = %d\n", - __func__, finger, - finger_status, - x, y, wx, wy); - - input_report_key(rmi4_data->input_dev, - BTN_TOUCH, 1); - input_report_key(rmi4_data->input_dev, - BTN_TOOL_FINGER, 1); - input_report_abs(rmi4_data->input_dev, - ABS_MT_POSITION_X, x); - input_report_abs(rmi4_data->input_dev, - ABS_MT_POSITION_Y, y); - -#ifdef REPORT_2D_W - input_report_abs(rmi4_data->input_dev, - ABS_MT_TOUCH_MAJOR, max(wx, wy)); - input_report_abs(rmi4_data->input_dev, - ABS_MT_TOUCH_MINOR, min(wx, wy)); -#endif -#ifndef TYPE_B_PROTOCOL - input_mt_sync(rmi4_data->input_dev); -#endif - touch_count++; - } - } - -#ifndef TYPE_B_PROTOCOL - if (!touch_count) - input_mt_sync(rmi4_data->input_dev); -#else - /* sync after groups of events */ - #ifdef KERNEL_ABOVE_3_7 - input_mt_sync_frame(rmi4_data->input_dev); - #endif -#endif - - input_sync(rmi4_data->input_dev); - - return touch_count; -} - -static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data, - struct synaptics_rmi4_fn *fhandler) -{ - int retval; - unsigned char button; - unsigned char index; - unsigned char shift; - unsigned char status; - unsigned char *data; - unsigned short data_addr = fhandler->full_addr.data_base; - struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; - static unsigned char do_once = 1; - static bool current_status[MAX_NUMBER_OF_BUTTONS]; -#ifdef NO_0D_WHILE_2D - static bool before_2d_status[MAX_NUMBER_OF_BUTTONS]; - static bool while_2d_status[MAX_NUMBER_OF_BUTTONS]; -#endif - - if (do_once) { - memset(current_status, 0, sizeof(current_status)); -#ifdef NO_0D_WHILE_2D - memset(before_2d_status, 0, sizeof(before_2d_status)); - memset(while_2d_status, 0, sizeof(while_2d_status)); -#endif - do_once = 0; - } - - retval = synaptics_rmi4_i2c_read(rmi4_data, - data_addr, - f1a->button_data_buffer, - f1a->button_bitmask_size); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to read button data registers\n", - __func__); - return; - } - - data = f1a->button_data_buffer; - - for (button = 0; button < f1a->valid_button_count; button++) { - index = button / 8; - shift = button % 8; - status = ((data[index] >> shift) & MASK_1BIT); - - if (current_status[button] == status) - continue; - else - current_status[button] = status; - - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Button %d (code %d) ->%d\n", - __func__, button, - f1a->button_map[button], - status); -#ifdef NO_0D_WHILE_2D - if (rmi4_data->fingers_on_2d == false) { - if (status == 1) { - before_2d_status[button] = 1; - } else { - if (while_2d_status[button] == 1) { - while_2d_status[button] = 0; - continue; - } else { - before_2d_status[button] = 0; - } - } - input_report_key(rmi4_data->input_dev, - f1a->button_map[button], - status); - } else { - if (before_2d_status[button] == 1) { - before_2d_status[button] = 0; - input_report_key(rmi4_data->input_dev, - f1a->button_map[button], - status); - } else { - if (status == 1) - while_2d_status[button] = 1; - else - while_2d_status[button] = 0; - } - } -#else - input_report_key(rmi4_data->input_dev, - f1a->button_map[button], - status); -#endif - } - - input_sync(rmi4_data->input_dev); - - return; -} - - /** - * synaptics_rmi4_report_touch() - * - * Called by synaptics_rmi4_sensor_report(). - * - * This function calls the appropriate finger data reporting function - * based on the function handler it receives and returns the number of - * fingers detected. - */ -static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data, - struct synaptics_rmi4_fn *fhandler, - unsigned char *touch_count) -{ - unsigned char touch_count_2d; - - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Function %02x reporting\n", - __func__, fhandler->fn_number); - - switch (fhandler->fn_number) { - case SYNAPTICS_RMI4_F11: - touch_count_2d = synaptics_rmi4_f11_abs_report(rmi4_data, - fhandler); - - *touch_count += touch_count_2d; - - if (touch_count_2d) - rmi4_data->fingers_on_2d = true; - else - rmi4_data->fingers_on_2d = false; - break; - - case SYNAPTICS_RMI4_F1A: - synaptics_rmi4_f1a_report(rmi4_data, fhandler); - break; - - default: - break; - } - - return; -} - - /** - * synaptics_rmi4_sensor_report() - * - * Called by synaptics_rmi4_irq(). - * - * This function determines the interrupt source(s) from the sensor - * and calls synaptics_rmi4_report_touch() with the appropriate - * function handler for each function with valid data inputs. - */ -static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - unsigned char touch_count = 0; - unsigned char intr[MAX_INTR_REGISTERS]; - struct synaptics_rmi4_fn *fhandler; - struct synaptics_rmi4_exp_fn *exp_fhandler; - struct synaptics_rmi4_device_info *rmi; - - rmi = &(rmi4_data->rmi4_mod_info); - - /* - * Get interrupt status information from F01 Data1 register to - * determine the source(s) that are flagging the interrupt. - */ - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_data_base_addr + 1, - intr, - rmi4_data->num_of_intr_regs); - if (retval < 0) - return retval; - - /* - * Traverse the function handler list and service the source(s) - * of the interrupt accordingly. - */ - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, &rmi->support_fn_list, link) { - if (fhandler->num_of_data_sources) { - if (fhandler->intr_mask & - intr[fhandler->intr_reg_num]) { - synaptics_rmi4_report_touch(rmi4_data, - fhandler, &touch_count); - } - } - } - } - - mutex_lock(&exp_fn_list_mutex); - if (!list_empty(&exp_fn_list)) { - list_for_each_entry(exp_fhandler, &exp_fn_list, link) { - if (exp_fhandler->inserted && - (exp_fhandler->func_attn != NULL)) - exp_fhandler->func_attn(rmi4_data, intr[0]); - } - } - mutex_unlock(&exp_fn_list_mutex); - - return touch_count; -} - - /** - * synaptics_rmi4_irq() - * - * Called by the kernel when an interrupt occurs (when the sensor - * asserts the attention irq). - * - * This function is the ISR thread and handles the acquisition - * and the reporting of finger data when the presence of fingers - * is detected. - */ -static irqreturn_t synaptics_rmi4_irq(int irq, void *data) -{ - struct synaptics_rmi4_data *rmi4_data = data; - - synaptics_rmi4_sensor_report(rmi4_data); - - return IRQ_HANDLED; -} - - /** - * synaptics_rmi4_irq_enable() - * - * Called by synaptics_rmi4_probe() and the power management functions - * in this driver and also exported to other expansion Function modules - * such as rmi_dev. - * - * This function handles the enabling and disabling of the attention - * irq including the setting up of the ISR thread. - */ -static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data, - bool enable) -{ - int retval = 0; - unsigned char intr_status; - const struct synaptics_rmi4_platform_data *platform_data = - rmi4_data->i2c_client->dev.platform_data; - - if (enable) { - if (rmi4_data->irq_enabled) - return retval; - - /* Clear interrupts first */ - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_data_base_addr + 1, - &intr_status, - rmi4_data->num_of_intr_regs); - if (retval < 0) - return retval; - - retval = request_threaded_irq(rmi4_data->irq, NULL, - synaptics_rmi4_irq, platform_data->irq_flags, - DRIVER_NAME, rmi4_data); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to create irq thread\n", - __func__); - return retval; - } - - rmi4_data->irq_enabled = true; - } else { - if (rmi4_data->irq_enabled) { - disable_irq(rmi4_data->irq); - free_irq(rmi4_data->irq, rmi4_data); - rmi4_data->irq_enabled = false; - } - } - - return retval; -} - - /** - * synaptics_rmi4_f11_init() - * - * Called by synaptics_rmi4_query_device(). - * - * This funtion parses information from the Function 11 registers - * and determines the number of fingers supported, x and y data ranges, - * offset to the associated interrupt status register, interrupt bit - * mask, and gathers finger data acquisition capabilities from the query - * registers. - */ -static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data, - struct synaptics_rmi4_fn *fhandler, - struct synaptics_rmi4_fn_desc *fd, - unsigned int intr_count) -{ - int retval; - unsigned char ii; - unsigned char intr_offset; - unsigned char abs_data_size; - unsigned char abs_data_blk_size; - unsigned char query[F11_STD_QUERY_LEN]; - unsigned char control[F11_STD_CTRL_LEN]; - - fhandler->fn_number = fd->fn_number; - fhandler->num_of_data_sources = fd->intr_src_count; - - retval = synaptics_rmi4_i2c_read(rmi4_data, - fhandler->full_addr.query_base, - query, - sizeof(query)); - if (retval < 0) - return retval; - - /* Maximum number of fingers supported */ - if ((query[1] & MASK_3BIT) <= 4) - fhandler->num_of_data_points = (query[1] & MASK_3BIT) + 1; - else if ((query[1] & MASK_3BIT) == 5) - fhandler->num_of_data_points = 10; - - rmi4_data->num_of_fingers = fhandler->num_of_data_points; - - retval = synaptics_rmi4_i2c_read(rmi4_data, - fhandler->full_addr.ctrl_base, - control, - sizeof(control)); - if (retval < 0) - return retval; - - /* Maximum x and y */ - rmi4_data->sensor_max_x = ((control[6] & MASK_8BIT) << 0) | - ((control[7] & MASK_4BIT) << 8); - rmi4_data->sensor_max_y = ((control[8] & MASK_8BIT) << 0) | - ((control[9] & MASK_4BIT) << 8); - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Function %02x max x = %d max y = %d\n", - __func__, fhandler->fn_number, - rmi4_data->sensor_max_x, - rmi4_data->sensor_max_y); - - fhandler->intr_reg_num = (intr_count + 7) / 8; - if (fhandler->intr_reg_num != 0) - fhandler->intr_reg_num -= 1; - - /* Set an enable bit for each data source */ - intr_offset = intr_count % 8; - fhandler->intr_mask = 0; - for (ii = intr_offset; - ii < ((fd->intr_src_count & MASK_3BIT) + - intr_offset); - ii++) - fhandler->intr_mask |= 1 << ii; - - abs_data_size = query[5] & MASK_2BIT; - abs_data_blk_size = 3 + (2 * (abs_data_size == 0 ? 1 : 0)); - fhandler->size_of_data_register_block = abs_data_blk_size; - - return retval; -} - -static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data, - struct synaptics_rmi4_fn *fhandler) -{ - int retval; - struct synaptics_rmi4_f1a_handle *f1a; - - f1a = kzalloc(sizeof(*f1a), GFP_KERNEL); - if (!f1a) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for function handle\n", - __func__); - return -ENOMEM; - } - - fhandler->data = (void *)f1a; - - retval = synaptics_rmi4_i2c_read(rmi4_data, - fhandler->full_addr.query_base, - f1a->button_query.data, - sizeof(f1a->button_query.data)); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to read query registers\n", - __func__); - return retval; - } - - f1a->button_count = f1a->button_query.max_button_count + 1; - f1a->button_bitmask_size = (f1a->button_count + 7) / 8; - - f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size, - sizeof(*(f1a->button_data_buffer)), GFP_KERNEL); - if (!f1a->button_data_buffer) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for data buffer\n", - __func__); - return -ENOMEM; - } - - f1a->button_map = kcalloc(f1a->button_count, - sizeof(*(f1a->button_map)), GFP_KERNEL); - if (!f1a->button_map) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for button map\n", - __func__); - return -ENOMEM; - } - - return 0; -} - -static int synaptics_rmi4_capacitance_button_map( - struct synaptics_rmi4_data *rmi4_data, - struct synaptics_rmi4_fn *fhandler) -{ - unsigned char ii; - struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; - const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board; - - if (!pdata->capacitance_button_map) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: capacitance_button_map is" \ - "NULL in board file\n", - __func__); - return -ENODEV; - } else if (!pdata->capacitance_button_map->map) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Button map is missing in board file\n", - __func__); - return -ENODEV; - } else { - if (pdata->capacitance_button_map->nbuttons != - f1a->button_count) { - f1a->valid_button_count = min(f1a->button_count, - pdata->capacitance_button_map->nbuttons); - } else { - f1a->valid_button_count = f1a->button_count; - } - - for (ii = 0; ii < f1a->valid_button_count; ii++) - f1a->button_map[ii] = - pdata->capacitance_button_map->map[ii]; - } - - return 0; -} - -static void synaptics_rmi4_f1a_kfree(struct synaptics_rmi4_fn *fhandler) -{ - struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; - - if (f1a) { - kfree(f1a->button_data_buffer); - kfree(f1a->button_map); - kfree(f1a); - fhandler->data = NULL; - } - - return; -} - -static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data, - struct synaptics_rmi4_fn *fhandler, - struct synaptics_rmi4_fn_desc *fd, - unsigned int intr_count) -{ - int retval; - unsigned char ii; - unsigned short intr_offset; - - fhandler->fn_number = fd->fn_number; - fhandler->num_of_data_sources = fd->intr_src_count; - - fhandler->intr_reg_num = (intr_count + 7) / 8; - if (fhandler->intr_reg_num != 0) - fhandler->intr_reg_num -= 1; - - /* Set an enable bit for each data source */ - intr_offset = intr_count % 8; - fhandler->intr_mask = 0; - for (ii = intr_offset; - ii < ((fd->intr_src_count & MASK_3BIT) + - intr_offset); - ii++) - fhandler->intr_mask |= 1 << ii; - - retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler); - if (retval < 0) - goto error_exit; - - retval = synaptics_rmi4_capacitance_button_map(rmi4_data, fhandler); - if (retval < 0) - goto error_exit; - - rmi4_data->button_0d_enabled = 1; - - return 0; - -error_exit: - synaptics_rmi4_f1a_kfree(fhandler); - - return retval; -} - -static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler, - struct synaptics_rmi4_fn_desc *rmi_fd, int page_number) -{ - *fhandler = kmalloc(sizeof(**fhandler), GFP_KERNEL); - if (!(*fhandler)) - return -ENOMEM; - - (*fhandler)->full_addr.data_base = - (rmi_fd->data_base_addr | - (page_number << 8)); - (*fhandler)->full_addr.ctrl_base = - (rmi_fd->ctrl_base_addr | - (page_number << 8)); - (*fhandler)->full_addr.cmd_base = - (rmi_fd->cmd_base_addr | - (page_number << 8)); - (*fhandler)->full_addr.query_base = - (rmi_fd->query_base_addr | - (page_number << 8)); - - return 0; -} - - - /** - * synaptics_rmi4_query_device_info() - * - * Called by synaptics_rmi4_query_device(). - * - */ -static int synaptics_rmi4_query_device_info( - struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - unsigned char f01_query[F01_STD_QUERY_LEN]; - struct synaptics_rmi4_device_info *rmi = &(rmi4_data->rmi4_mod_info); - - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_query_base_addr, - f01_query, - sizeof(f01_query)); - if (retval < 0) - return retval; - - /* RMI Version 4.0 currently supported */ - rmi->version_major = 4; - rmi->version_minor = 0; - - rmi->manufacturer_id = f01_query[0]; - rmi->product_props = f01_query[1]; - rmi->product_info[0] = f01_query[2] & MASK_7BIT; - rmi->product_info[1] = f01_query[3] & MASK_7BIT; - rmi->date_code[0] = f01_query[4] & MASK_5BIT; - rmi->date_code[1] = f01_query[5] & MASK_4BIT; - rmi->date_code[2] = f01_query[6] & MASK_5BIT; - rmi->tester_id = ((f01_query[7] & MASK_7BIT) << 8) | - (f01_query[8] & MASK_7BIT); - rmi->serial_number = ((f01_query[9] & MASK_7BIT) << 8) | - (f01_query[10] & MASK_7BIT); - memcpy(rmi->product_id_string, &f01_query[11], 10); - - if (rmi->manufacturer_id != 1) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Non-Synaptics device found, manufacturer ID = %d\n", - __func__, rmi->manufacturer_id); - } - - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET, - rmi->build_id, - sizeof(rmi->build_id)); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to read firmware build id (code %d)\n", - __func__, retval); - return retval; - } - return retval; -} - - /** - * synaptics_rmi4_query_device() - * - * Called by synaptics_rmi4_probe(). - * - * This funtion scans the page description table, records the offsets - * to the register types of Function $01, sets up the function handlers - * for Function $11 and Function $12, determines the number of interrupt - * sources from the sensor, adds valid Functions with data inputs to the - * Function linked list, parses information from the query registers of - * Function $01, and enables the interrupt sources from the valid Functions - * with data inputs. - */ -static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - unsigned char ii; - unsigned char page_number; - unsigned char intr_count = 0; - unsigned char data_sources = 0; - unsigned short pdt_entry_addr; - unsigned short intr_addr; - struct synaptics_rmi4_f01_device_status status; - struct synaptics_rmi4_fn_desc rmi_fd; - struct synaptics_rmi4_fn *fhandler; - struct synaptics_rmi4_device_info *rmi; - - rmi = &(rmi4_data->rmi4_mod_info); - - INIT_LIST_HEAD(&rmi->support_fn_list); - - /* Scan the page description tables of the pages to service */ - for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) { - for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END; - pdt_entry_addr -= PDT_ENTRY_SIZE) { - pdt_entry_addr |= (page_number << 8); - - retval = synaptics_rmi4_i2c_read(rmi4_data, - pdt_entry_addr, - (unsigned char *)&rmi_fd, - sizeof(rmi_fd)); - if (retval < 0) - return retval; - - fhandler = NULL; - - if (rmi_fd.fn_number == 0) { - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Reached end of PDT\n", - __func__); - break; - } - - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: F%02x found (page %d)\n", - __func__, rmi_fd.fn_number, - page_number); - - switch (rmi_fd.fn_number) { - case SYNAPTICS_RMI4_F01: - rmi4_data->f01_query_base_addr = - rmi_fd.query_base_addr; - rmi4_data->f01_ctrl_base_addr = - rmi_fd.ctrl_base_addr; - rmi4_data->f01_data_base_addr = - rmi_fd.data_base_addr; - rmi4_data->f01_cmd_base_addr = - rmi_fd.cmd_base_addr; - - retval = - synaptics_rmi4_query_device_info(rmi4_data); - if (retval < 0) - return retval; - - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_data_base_addr, - status.data, - sizeof(status.data)); - if (retval < 0) - return retval; - - if (status.flash_prog == 1) { - pr_notice("%s: In flash prog mode, status = 0x%02x\n", - __func__, - status.status_code); - goto flash_prog_mode; - } - break; - - case SYNAPTICS_RMI4_F34: - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi_fd.ctrl_base_addr, - rmi->config_id, - sizeof(rmi->config_id)); - if (retval < 0) - return retval; - break; - - case SYNAPTICS_RMI4_F11: - if (rmi_fd.intr_src_count == 0) - break; - - retval = synaptics_rmi4_alloc_fh(&fhandler, - &rmi_fd, page_number); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc for F%d\n", - __func__, - rmi_fd.fn_number); - return retval; - } - - retval = synaptics_rmi4_f11_init(rmi4_data, - fhandler, &rmi_fd, intr_count); - if (retval < 0) - return retval; - break; - - case SYNAPTICS_RMI4_F1A: - if (rmi_fd.intr_src_count == 0) - break; - - retval = synaptics_rmi4_alloc_fh(&fhandler, - &rmi_fd, page_number); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc for F%d\n", - __func__, - rmi_fd.fn_number); - return retval; - } - - retval = synaptics_rmi4_f1a_init(rmi4_data, - fhandler, &rmi_fd, intr_count); - if (retval < 0) - return retval; - break; - } - - /* Accumulate the interrupt count */ - intr_count += (rmi_fd.intr_src_count & MASK_3BIT); - - if (fhandler && rmi_fd.intr_src_count) { - list_add_tail(&fhandler->link, - &rmi->support_fn_list); - } - } - } - -flash_prog_mode: - rmi4_data->num_of_intr_regs = (intr_count + 7) / 8; - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Number of interrupt registers = %d\n", - __func__, rmi4_data->num_of_intr_regs); - - memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask)); - - /* - * Map out the interrupt bit masks for the interrupt sources - * from the registered function handlers. - */ - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, &rmi->support_fn_list, link) - data_sources += fhandler->num_of_data_sources; - } - if (data_sources) { - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, - &rmi->support_fn_list, link) { - if (fhandler->num_of_data_sources) { - rmi4_data->intr_mask[fhandler->intr_reg_num] |= - fhandler->intr_mask; - } - } - } - } - - /* Enable the interrupt sources */ - for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) { - if (rmi4_data->intr_mask[ii] != 0x00) { - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Interrupt enable mask %d = 0x%02x\n", - __func__, ii, rmi4_data->intr_mask[ii]); - intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii; - retval = synaptics_rmi4_i2c_write(rmi4_data, - intr_addr, - &(rmi4_data->intr_mask[ii]), - sizeof(rmi4_data->intr_mask[ii])); - if (retval < 0) - return retval; - } - } - - return 0; -} - -static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - unsigned char command = 0x01; - struct synaptics_rmi4_fn *fhandler; - struct synaptics_rmi4_device_info *rmi; - - rmi = &(rmi4_data->rmi4_mod_info); - - retval = synaptics_rmi4_i2c_write(rmi4_data, - rmi4_data->f01_cmd_base_addr, - &command, - sizeof(command)); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to issue reset command, error = %d\n", - __func__, retval); - return retval; - } - - msleep(100); - - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, &rmi->support_fn_list, link) { - if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) - synaptics_rmi4_f1a_kfree(fhandler); - else - kfree(fhandler->data); - kfree(fhandler); - } - } - - retval = synaptics_rmi4_query_device(rmi4_data); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to query device\n", - __func__); - return retval; - } - - return 0; -} - -/** -* synaptics_rmi4_detection_work() -* -* Called by the kernel at the scheduled time. -* -* This function is a self-rearming work thread that checks for the -* insertion and removal of other expansion Function modules such as -* rmi_dev and calls their initialization and removal callback functions -* accordingly. -*/ -static void synaptics_rmi4_detection_work(struct work_struct *work) -{ - struct synaptics_rmi4_exp_fn *exp_fhandler, *next_list_entry; - struct synaptics_rmi4_data *rmi4_data = - container_of(work, struct synaptics_rmi4_data, - det_work.work); - - queue_delayed_work(rmi4_data->det_workqueue, - &rmi4_data->det_work, - msecs_to_jiffies(EXP_FN_DET_INTERVAL)); - - mutex_lock(&exp_fn_list_mutex); - if (!list_empty(&exp_fn_list)) { - list_for_each_entry_safe(exp_fhandler, - next_list_entry, - &exp_fn_list, - link) { - if ((exp_fhandler->func_init != NULL) && - (exp_fhandler->inserted == false)) { - exp_fhandler->func_init(rmi4_data); - exp_fhandler->inserted = true; - } else if ((exp_fhandler->func_init == NULL) && - (exp_fhandler->inserted == true)) { - exp_fhandler->func_remove(rmi4_data); - list_del(&exp_fhandler->link); - kfree(exp_fhandler); - } - } - } - mutex_unlock(&exp_fn_list_mutex); - - return; -} - -/** -* synaptics_rmi4_new_function() -* -* Called by other expansion Function modules in their module init and -* module exit functions. -* -* This function is used by other expansion Function modules such as -* rmi_dev to register themselves with the driver by providing their -* initialization and removal callback function pointers so that they -* can be inserted or removed dynamically at module init and exit times, -* respectively. -*/ -void synaptics_rmi4_new_function(enum exp_fn fn_type, bool insert, - int (*func_init)(struct synaptics_rmi4_data *rmi4_data), - void (*func_remove)(struct synaptics_rmi4_data *rmi4_data), - void (*func_attn)(struct synaptics_rmi4_data *rmi4_data, - unsigned char intr_mask)) -{ - struct synaptics_rmi4_exp_fn *exp_fhandler; - - if (!exp_fn_inited) { - mutex_init(&exp_fn_list_mutex); - INIT_LIST_HEAD(&exp_fn_list); - exp_fn_inited = 1; - } - - mutex_lock(&exp_fn_list_mutex); - if (insert) { - exp_fhandler = kzalloc(sizeof(*exp_fhandler), GFP_KERNEL); - if (!exp_fhandler) { - pr_err("%s: Failed to alloc mem for expansion function\n", - __func__); - goto exit; - } - exp_fhandler->fn_type = fn_type; - exp_fhandler->func_init = func_init; - exp_fhandler->func_attn = func_attn; - exp_fhandler->func_remove = func_remove; - exp_fhandler->inserted = false; - list_add_tail(&exp_fhandler->link, &exp_fn_list); - } else { - if (!list_empty(&exp_fn_list)) { - list_for_each_entry(exp_fhandler, &exp_fn_list, link) { - if (exp_fhandler->func_init == func_init) { - exp_fhandler->inserted = false; - exp_fhandler->func_init = NULL; - exp_fhandler->func_attn = NULL; - goto exit; - } - } - } - } - -exit: - mutex_unlock(&exp_fn_list_mutex); - - return; -} -EXPORT_SYMBOL(synaptics_rmi4_new_function); - - /** - * synaptics_rmi4_probe() - * - * Called by the kernel when an association with an I2C device of the - * same name is made (after doing i2c_add_driver). - * - * This funtion allocates and initializes the resources for the driver - * as an input driver, turns on the power to the sensor, queries the - * sensor for its supported Functions and characteristics, registers - * the driver to the input subsystem, sets up the interrupt, handles - * the registration of the early_suspend and late_resume functions, - * and creates a work queue for detection of other expansion Function - * modules. - */ -static int __devinit synaptics_rmi4_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - int retval; - unsigned char ii; - unsigned char attr_count; - struct synaptics_rmi4_f1a_handle *f1a; - struct synaptics_rmi4_fn *fhandler; - struct synaptics_rmi4_data *rmi4_data; - struct synaptics_rmi4_device_info *rmi; - const struct synaptics_rmi4_platform_data *platform_data = - client->dev.platform_data; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, - "%s: SMBus byte data not supported\n", - __func__); - return -EIO; - } - - if (!platform_data) { - dev_err(&client->dev, - "%s: No platform data found\n", - __func__); - return -EINVAL; - } - - rmi4_data = kzalloc(sizeof(*rmi4_data) * 2, GFP_KERNEL); - if (!rmi4_data) { - dev_err(&client->dev, - "%s: Failed to alloc mem for rmi4_data\n", - __func__); - return -ENOMEM; - } - - rmi = &(rmi4_data->rmi4_mod_info); - - rmi4_data->input_dev = input_allocate_device(); - if (rmi4_data->input_dev == NULL) { - dev_err(&client->dev, - "%s: Failed to allocate input device\n", - __func__); - retval = -ENOMEM; - goto err_input_device; - } - - if (platform_data->regulator_en) { - rmi4_data->regulator = regulator_get(&client->dev, "vdd"); - if (IS_ERR(rmi4_data->regulator)) { - dev_err(&client->dev, - "%s: Failed to get regulator\n", - __func__); - retval = PTR_ERR(rmi4_data->regulator); - goto err_regulator; - } - regulator_enable(rmi4_data->regulator); - } - - rmi4_data->i2c_client = client; - rmi4_data->current_page = MASK_8BIT; - rmi4_data->board = platform_data; - rmi4_data->touch_stopped = false; - rmi4_data->sensor_sleep = false; - rmi4_data->irq_enabled = false; - - rmi4_data->i2c_read = synaptics_rmi4_i2c_read; - rmi4_data->i2c_write = synaptics_rmi4_i2c_write; - rmi4_data->irq_enable = synaptics_rmi4_irq_enable; - rmi4_data->reset_device = synaptics_rmi4_reset_device; - - init_waitqueue_head(&rmi4_data->wait); - mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex)); - - retval = synaptics_rmi4_query_device(rmi4_data); - if (retval < 0) { - dev_err(&client->dev, - "%s: Failed to query device\n", - __func__); - goto err_query_device; - } - - i2c_set_clientdata(client, rmi4_data); - - rmi4_data->input_dev->name = DRIVER_NAME; - rmi4_data->input_dev->phys = INPUT_PHYS_NAME; - rmi4_data->input_dev->id.bustype = BUS_I2C; - rmi4_data->input_dev->id.product = SYNAPTICS_RMI4_DRIVER_PRODUCT; - rmi4_data->input_dev->id.version = SYNAPTICS_RMI4_DRIVER_VERSION; - rmi4_data->input_dev->dev.parent = &client->dev; - input_set_drvdata(rmi4_data->input_dev, rmi4_data); - - set_bit(EV_SYN, rmi4_data->input_dev->evbit); - set_bit(EV_KEY, rmi4_data->input_dev->evbit); - set_bit(EV_ABS, rmi4_data->input_dev->evbit); - set_bit(BTN_TOUCH, rmi4_data->input_dev->keybit); - set_bit(BTN_TOOL_FINGER, rmi4_data->input_dev->keybit); - -#ifdef INPUT_PROP_DIRECT - set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit); -#endif - - input_set_abs_params(rmi4_data->input_dev, - ABS_MT_POSITION_X, 0, - rmi4_data->sensor_max_x, 0, 0); - input_set_abs_params(rmi4_data->input_dev, - ABS_MT_POSITION_Y, 0, - rmi4_data->sensor_max_y, 0, 0); -#ifdef REPORT_2D_W - input_set_abs_params(rmi4_data->input_dev, - ABS_MT_TOUCH_MAJOR, 0, - MAX_ABS_MT_TOUCH_MAJOR, 0, 0); -#endif - -#ifdef TYPE_B_PROTOCOL - input_mt_init_slots(rmi4_data->input_dev, - rmi4_data->num_of_fingers); -#endif - - f1a = NULL; - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, &rmi->support_fn_list, link) { - if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) - f1a = fhandler->data; - } - } - - if (f1a) { - for (ii = 0; ii < f1a->valid_button_count; ii++) { - set_bit(f1a->button_map[ii], - rmi4_data->input_dev->keybit); - input_set_capability(rmi4_data->input_dev, - EV_KEY, f1a->button_map[ii]); - } - } - - retval = input_register_device(rmi4_data->input_dev); - if (retval) { - dev_err(&client->dev, - "%s: Failed to register input device\n", - __func__); - goto err_register_input; - } - -#ifdef CONFIG_HAS_EARLYSUSPEND - rmi4_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - rmi4_data->early_suspend.suspend = synaptics_rmi4_early_suspend; - rmi4_data->early_suspend.resume = synaptics_rmi4_late_resume; - register_early_suspend(&rmi4_data->early_suspend); -#endif - - if (!exp_fn_inited) { - mutex_init(&exp_fn_list_mutex); - INIT_LIST_HEAD(&exp_fn_list); - exp_fn_inited = 1; - } - - rmi4_data->det_workqueue = - create_singlethread_workqueue("rmi_det_workqueue"); - INIT_DELAYED_WORK(&rmi4_data->det_work, - synaptics_rmi4_detection_work); - queue_delayed_work(rmi4_data->det_workqueue, - &rmi4_data->det_work, - msecs_to_jiffies(EXP_FN_DET_INTERVAL)); - - if (platform_data->gpio_config) { - retval = platform_data->gpio_config(platform_data->irq_gpio, - true); - if (retval < 0) { - dev_err(&client->dev, - "%s: Failed to configure GPIO\n", - __func__); - goto err_gpio; - } - } - - rmi4_data->irq = gpio_to_irq(platform_data->irq_gpio); - - retval = synaptics_rmi4_irq_enable(rmi4_data, true); - if (retval < 0) { - dev_err(&client->dev, - "%s: Failed to enable attention interrupt\n", - __func__); - goto err_enable_irq; - } - - for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { - retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, - &attrs[attr_count].attr); - if (retval < 0) { - dev_err(&client->dev, - "%s: Failed to create sysfs attributes\n", - __func__); - goto err_sysfs; - } - } - - return retval; - -err_sysfs: - for (attr_count--; attr_count >= 0; attr_count--) { - sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, - &attrs[attr_count].attr); - } - -err_enable_irq: -err_gpio: - input_unregister_device(rmi4_data->input_dev); - -err_register_input: -err_query_device: - if (platform_data->regulator_en) { - regulator_disable(rmi4_data->regulator); - regulator_put(rmi4_data->regulator); - } - - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, &rmi->support_fn_list, link) { - if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) - synaptics_rmi4_f1a_kfree(fhandler); - else - kfree(fhandler->data); - kfree(fhandler); - } - } - -err_regulator: - input_free_device(rmi4_data->input_dev); - rmi4_data->input_dev = NULL; - -err_input_device: - kfree(rmi4_data); - - return retval; -} - - /** - * synaptics_rmi4_remove() - * - * Called by the kernel when the association with an I2C device of the - * same name is broken (when the driver is unloaded). - * - * This funtion terminates the work queue, stops sensor data acquisition, - * frees the interrupt, unregisters the driver from the input subsystem, - * turns off the power to the sensor, and frees other allocated resources. - */ -static int __devexit synaptics_rmi4_remove(struct i2c_client *client) -{ - unsigned char attr_count; - struct synaptics_rmi4_fn *fhandler; - struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client); - struct synaptics_rmi4_device_info *rmi; - const struct synaptics_rmi4_platform_data *platform_data = - rmi4_data->board; - - rmi = &(rmi4_data->rmi4_mod_info); - - cancel_delayed_work_sync(&rmi4_data->det_work); - flush_workqueue(rmi4_data->det_workqueue); - destroy_workqueue(rmi4_data->det_workqueue); - - rmi4_data->touch_stopped = true; - wake_up(&rmi4_data->wait); - - synaptics_rmi4_irq_enable(rmi4_data, false); - - for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { - sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, - &attrs[attr_count].attr); - } - - input_unregister_device(rmi4_data->input_dev); - - if (platform_data->regulator_en) { - regulator_disable(rmi4_data->regulator); - regulator_put(rmi4_data->regulator); - } - - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, &rmi->support_fn_list, link) { - if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) - synaptics_rmi4_f1a_kfree(fhandler); - else - kfree(fhandler->data); - kfree(fhandler); - } - } - input_free_device(rmi4_data->input_dev); - - kfree(rmi4_data); - - return 0; -} - -#ifdef CONFIG_PM - /** - * synaptics_rmi4_sensor_sleep() - * - * Called by synaptics_rmi4_early_suspend() and synaptics_rmi4_suspend(). - * - * This function stops finger data acquisition and puts the sensor to sleep. - */ -static void synaptics_rmi4_sensor_sleep(struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - unsigned char device_ctrl; - - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_ctrl_base_addr, - &device_ctrl, - sizeof(device_ctrl)); - if (retval < 0) { - dev_err(&(rmi4_data->input_dev->dev), - "%s: Failed to enter sleep mode\n", - __func__); - rmi4_data->sensor_sleep = false; - return; - } - - device_ctrl = (device_ctrl & ~MASK_3BIT); - device_ctrl = (device_ctrl | NO_SLEEP_OFF | SENSOR_SLEEP); - - retval = synaptics_rmi4_i2c_write(rmi4_data, - rmi4_data->f01_ctrl_base_addr, - &device_ctrl, - sizeof(device_ctrl)); - if (retval < 0) { - dev_err(&(rmi4_data->input_dev->dev), - "%s: Failed to enter sleep mode\n", - __func__); - rmi4_data->sensor_sleep = false; - return; - } else { - rmi4_data->sensor_sleep = true; - } - - return; -} - - /** - * synaptics_rmi4_sensor_wake() - * - * Called by synaptics_rmi4_resume() and synaptics_rmi4_late_resume(). - * - * This function wakes the sensor from sleep. - */ -static void synaptics_rmi4_sensor_wake(struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - unsigned char device_ctrl; - - retval = synaptics_rmi4_i2c_read(rmi4_data, - rmi4_data->f01_ctrl_base_addr, - &device_ctrl, - sizeof(device_ctrl)); - if (retval < 0) { - dev_err(&(rmi4_data->input_dev->dev), - "%s: Failed to wake from sleep mode\n", - __func__); - rmi4_data->sensor_sleep = true; - return; - } - - device_ctrl = (device_ctrl & ~MASK_3BIT); - device_ctrl = (device_ctrl | NO_SLEEP_OFF | NORMAL_OPERATION); - - retval = synaptics_rmi4_i2c_write(rmi4_data, - rmi4_data->f01_ctrl_base_addr, - &device_ctrl, - sizeof(device_ctrl)); - if (retval < 0) { - dev_err(&(rmi4_data->input_dev->dev), - "%s: Failed to wake from sleep mode\n", - __func__); - rmi4_data->sensor_sleep = true; - return; - } else { - rmi4_data->sensor_sleep = false; - } - - return; -} - -#ifdef CONFIG_HAS_EARLYSUSPEND - /** - * synaptics_rmi4_early_suspend() - * - * Called by the kernel during the early suspend phase when the system - * enters suspend. - * - * This function calls synaptics_rmi4_sensor_sleep() to stop finger - * data acquisition and put the sensor to sleep. - */ -static void synaptics_rmi4_early_suspend(struct early_suspend *h) -{ - struct synaptics_rmi4_data *rmi4_data = - container_of(h, struct synaptics_rmi4_data, - early_suspend); - - rmi4_data->touch_stopped = true; - wake_up(&rmi4_data->wait); - synaptics_rmi4_irq_enable(rmi4_data, false); - synaptics_rmi4_sensor_sleep(rmi4_data); - - if (rmi4_data->full_pm_cycle) - synaptics_rmi4_suspend(&(rmi4_data->input_dev->dev)); - - return; -} - - /** - * synaptics_rmi4_late_resume() - * - * Called by the kernel during the late resume phase when the system - * wakes up from suspend. - * - * This function goes through the sensor wake process if the system wakes - * up from early suspend (without going into suspend). - */ -static void synaptics_rmi4_late_resume(struct early_suspend *h) -{ - struct synaptics_rmi4_data *rmi4_data = - container_of(h, struct synaptics_rmi4_data, - early_suspend); - - if (rmi4_data->full_pm_cycle) - synaptics_rmi4_resume(&(rmi4_data->input_dev->dev)); - - if (rmi4_data->sensor_sleep == true) { - synaptics_rmi4_sensor_wake(rmi4_data); - rmi4_data->touch_stopped = false; - synaptics_rmi4_irq_enable(rmi4_data, true); - } - - return; -} -#endif - - /** - * synaptics_rmi4_suspend() - * - * Called by the kernel during the suspend phase when the system - * enters suspend. - * - * This function stops finger data acquisition and puts the sensor to - * sleep (if not already done so during the early suspend phase), - * disables the interrupt, and turns off the power to the sensor. - */ -static int synaptics_rmi4_suspend(struct device *dev) -{ - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - const struct synaptics_rmi4_platform_data *platform_data = - rmi4_data->board; - - if (!rmi4_data->sensor_sleep) { - rmi4_data->touch_stopped = true; - wake_up(&rmi4_data->wait); - synaptics_rmi4_irq_enable(rmi4_data, false); - synaptics_rmi4_sensor_sleep(rmi4_data); - } - - if (platform_data->regulator_en) - regulator_disable(rmi4_data->regulator); - - return 0; -} - - /** - * synaptics_rmi4_resume() - * - * Called by the kernel during the resume phase when the system - * wakes up from suspend. - * - * This function turns on the power to the sensor, wakes the sensor - * from sleep, enables the interrupt, and starts finger data - * acquisition. - */ -static int synaptics_rmi4_resume(struct device *dev) -{ - struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); - const struct synaptics_rmi4_platform_data *platform_data = - rmi4_data->board; - - if (platform_data->regulator_en) - regulator_enable(rmi4_data->regulator); - - synaptics_rmi4_sensor_wake(rmi4_data); - rmi4_data->touch_stopped = false; - synaptics_rmi4_irq_enable(rmi4_data, true); - - return 0; -} - -static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = { - .suspend = synaptics_rmi4_suspend, - .resume = synaptics_rmi4_resume, -}; -#endif - -static const struct i2c_device_id synaptics_rmi4_id_table[] = { - {DRIVER_NAME, 0}, - {}, -}; -MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table); - -static struct i2c_driver synaptics_rmi4_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, -#ifdef CONFIG_PM - .pm = &synaptics_rmi4_dev_pm_ops, -#endif - }, - .probe = synaptics_rmi4_probe, - .remove = __devexit_p(synaptics_rmi4_remove), - .id_table = synaptics_rmi4_id_table, -}; - - /** - * synaptics_rmi4_init() - * - * Called by the kernel during do_initcalls (if built-in) - * or when the driver is loaded (if a module). - * - * This function registers the driver to the I2C subsystem. - * - */ -static int __init synaptics_rmi4_init(void) -{ - return i2c_add_driver(&synaptics_rmi4_driver); -} - - /** - * synaptics_rmi4_exit() - * - * Called by the kernel when the driver is unloaded. - * - * This funtion unregisters the driver from the I2C subsystem. - * - */ -static void __exit synaptics_rmi4_exit(void) -{ - i2c_del_driver(&synaptics_rmi4_driver); -} - -module_init(synaptics_rmi4_init); -module_exit(synaptics_rmi4_exit); - -MODULE_AUTHOR("Synaptics, Inc."); -MODULE_DESCRIPTION("Synaptics RMI4 I2C Touch Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION); diff --git a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h deleted file mode 100644 index ecb9b9415e8a..000000000000 --- a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Synaptics RMI4 touchscreen driver - * - * Copyright (C) 2012 Synaptics Incorporated - * - * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> - * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> - * - * 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 - * (at your option) any later version. - * - * 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 _SYNAPTICS_DSX_RMI4_H_ -#define _SYNAPTICS_DSX_RMI4_H_ - -#define SYNAPTICS_RMI4_DS4 0x0001 -#define SYNAPTICS_RMI4_DS5 0x0002 -#define SYNAPTICS_RMI4_DRIVER_PRODUCT SYNAPTICS_RMI4_DS4 -#define SYNAPTICS_RMI4_DRIVER_VERSION 0x1001 - -#include <linux/version.h> -#ifdef CONFIG_HAS_EARLYSUSPEND -#include <linux/earlysuspend.h> -#endif - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)) -#define KERNEL_ABOVE_2_6_38 -#endif - -#ifdef KERNEL_ABOVE_2_6_38 -#define sstrtoul(...) kstrtoul(__VA_ARGS__) -#else -#define sstrtoul(...) strict_strtoul(__VA_ARGS__) -#endif - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)) -#define KERNEL_ABOVE_3_7 -#endif - -#define PDT_PROPS (0x00EF) -#define PDT_START (0x00E9) -#define PDT_END (0x000A) -#define PDT_ENTRY_SIZE (0x0006) -#define PAGES_TO_SERVICE (10) -#define PAGE_SELECT_LEN (2) - -#define SYNAPTICS_RMI4_F01 (0x01) -#define SYNAPTICS_RMI4_F11 (0x11) -#define SYNAPTICS_RMI4_F1A (0x1a) -#define SYNAPTICS_RMI4_F34 (0x34) -#define SYNAPTICS_RMI4_F54 (0x54) -#define SYNAPTICS_RMI4_F55 (0x55) - -#define SYNAPTICS_RMI4_PRODUCT_INFO_SIZE 2 -#define SYNAPTICS_RMI4_DATE_CODE_SIZE 3 -#define SYNAPTICS_RMI4_PRODUCT_ID_SIZE 10 -#define SYNAPTICS_RMI4_BUILD_ID_SIZE 3 - -#define MAX_NUMBER_OF_FINGERS 10 -#define MAX_NUMBER_OF_BUTTONS 4 -#define MAX_INTR_REGISTERS 4 - -#define MASK_16BIT 0xFFFF -#define MASK_8BIT 0xFF -#define MASK_7BIT 0x7F -#define MASK_6BIT 0x3F -#define MASK_5BIT 0x1F -#define MASK_4BIT 0x0F -#define MASK_3BIT 0x07 -#define MASK_2BIT 0x03 -#define MASK_1BIT 0x01 - -/* - * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT - * @query_base_addr: base address for query registers - * @cmd_base_addr: base address for command registers - * @ctrl_base_addr: base address for control registers - * @data_base_addr: base address for data registers - * @intr_src_count: number of interrupt sources - * @fn_number: function number - */ -struct synaptics_rmi4_fn_desc { - unsigned char query_base_addr; - unsigned char cmd_base_addr; - unsigned char ctrl_base_addr; - unsigned char data_base_addr; - unsigned char intr_src_count; - unsigned char fn_number; -}; - -/* - * synaptics_rmi4_fn_full_addr - full 16-bit base addresses - * @query_base: 16-bit base address for query registers - * @cmd_base: 16-bit base address for data registers - * @ctrl_base: 16-bit base address for command registers - * @data_base: 16-bit base address for control registers - */ -struct synaptics_rmi4_fn_full_addr { - unsigned short query_base; - unsigned short cmd_base; - unsigned short ctrl_base; - unsigned short data_base; -}; - -/* - * struct synaptics_rmi4_fn - function handler data structure - * @fn_number: function number - * @num_of_data_sources: number of data sources - * @num_of_data_points: maximum number of fingers supported - * @size_of_data_register_block: data register block size - * @data1_offset: offset to data1 register from data base address - * @intr_reg_num: index to associated interrupt register - * @intr_mask: interrupt mask - * @full_addr: full 16-bit base addresses of function registers - * @link: linked list for function handlers - * @data_size: size of private data - * @data: pointer to private data - */ -struct synaptics_rmi4_fn { - unsigned char fn_number; - unsigned char num_of_data_sources; - unsigned char num_of_data_points; - unsigned char size_of_data_register_block; - unsigned char data1_offset; - unsigned char intr_reg_num; - unsigned char intr_mask; - struct synaptics_rmi4_fn_full_addr full_addr; - struct list_head link; - int data_size; - void *data; -}; - -/* - * struct synaptics_rmi4_device_info - device information - * @version_major: rmi protocol major version number - * @version_minor: rmi protocol minor version number - * @manufacturer_id: manufacturer id - * @product_props: product properties information - * @product_info: product info array - * @date_code: device manufacture date - * @tester_id: tester id array - * @serial_number: device serial number - * @product_id_string: device product id - * @support_fn_list: linked list for function handlers - */ -struct synaptics_rmi4_device_info { - unsigned int version_major; - unsigned int version_minor; - unsigned char manufacturer_id; - unsigned char product_props; - unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE]; - unsigned char date_code[SYNAPTICS_RMI4_DATE_CODE_SIZE]; - unsigned short tester_id; - unsigned short serial_number; - unsigned char product_id_string[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1]; - unsigned char build_id[SYNAPTICS_RMI4_BUILD_ID_SIZE]; - unsigned char config_id[3]; - struct list_head support_fn_list; -}; - -/* - * struct synaptics_rmi4_data - rmi4 device instance data - * @i2c_client: pointer to associated i2c client - * @input_dev: pointer to associated input device - * @board: constant pointer to platform data - * @rmi4_mod_info: device information - * @regulator: pointer to associated regulator - * @rmi4_io_ctrl_mutex: mutex for i2c i/o control - * @det_work: work thread instance for expansion function detection - * @det_workqueue: pointer to work queue for work thread instance - * @early_suspend: instance to support early suspend power management - * @current_page: current page in sensor to acess - * @button_0d_enabled: flag for 0d button support - * @full_pm_cycle: flag for full power management cycle in early suspend stage - * @num_of_intr_regs: number of interrupt registers - * @f01_query_base_addr: query base address for f01 - * @f01_cmd_base_addr: command base address for f01 - * @f01_ctrl_base_addr: control base address for f01 - * @f01_data_base_addr: data base address for f01 - * @irq: attention interrupt - * @sensor_max_x: sensor maximum x value - * @sensor_max_y: sensor maximum y value - * @irq_enabled: flag for indicating interrupt enable status - * @touch_stopped: flag to stop interrupt thread processing - * @fingers_on_2d: flag to indicate presence of fingers in 2d area - * @sensor_sleep: flag to indicate sleep state of sensor - * @wait: wait queue for touch data polling in interrupt thread - * @i2c_read: pointer to i2c read function - * @i2c_write: pointer to i2c write function - * @irq_enable: pointer to irq enable function - */ -struct synaptics_rmi4_data { - struct i2c_client *i2c_client; - struct input_dev *input_dev; - const struct synaptics_rmi4_platform_data *board; - struct synaptics_rmi4_device_info rmi4_mod_info; - struct regulator *regulator; - struct mutex rmi4_io_ctrl_mutex; - struct delayed_work det_work; - struct workqueue_struct *det_workqueue; - struct early_suspend early_suspend; - unsigned char current_page; - unsigned char button_0d_enabled; - unsigned char full_pm_cycle; - unsigned char num_of_rx; - unsigned char num_of_tx; - unsigned char num_of_fingers; - unsigned char intr_mask[MAX_INTR_REGISTERS]; - unsigned short num_of_intr_regs; - unsigned short f01_query_base_addr; - unsigned short f01_cmd_base_addr; - unsigned short f01_ctrl_base_addr; - unsigned short f01_data_base_addr; - int irq; - int sensor_max_x; - int sensor_max_y; - bool irq_enabled; - bool touch_stopped; - bool fingers_on_2d; - bool sensor_sleep; - wait_queue_head_t wait; - int (*i2c_read)(struct synaptics_rmi4_data *pdata, unsigned short addr, - unsigned char *data, unsigned short length); - int (*i2c_write)(struct synaptics_rmi4_data *pdata, unsigned short addr, - unsigned char *data, unsigned short length); - int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable); - int (*reset_device)(struct synaptics_rmi4_data *rmi4_data); -}; - -enum exp_fn { - RMI_DEV = 0, - RMI_F34, - RMI_F54, - RMI_FW_UPDATER, - RMI_LAST, -}; - -struct synaptics_rmi4_exp_fn_ptr { - int (*read)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, - unsigned char *data, unsigned short length); - int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, - unsigned char *data, unsigned short length); - int (*enable)(struct synaptics_rmi4_data *rmi4_data, bool enable); -}; - -void synaptics_rmi4_new_function(enum exp_fn fn_type, bool insert, - int (*func_init)(struct synaptics_rmi4_data *rmi4_data), - void (*func_remove)(struct synaptics_rmi4_data *rmi4_data), - void (*func_attn)(struct synaptics_rmi4_data *rmi4_data, - unsigned char intr_mask)); - -static inline ssize_t synaptics_rmi4_show_error(struct device *dev, - struct device_attribute *attr, char *buf) -{ - dev_warn(dev, "%s Attempted to read from write-only attribute %s\n", - __func__, attr->attr.name); - return -EPERM; -} - -static inline ssize_t synaptics_rmi4_store_error(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - dev_warn(dev, "%s Attempted to write to read-only attribute %s\n", - __func__, attr->attr.name); - return -EPERM; -} - -static inline void batohs(unsigned short *dest, unsigned char *src) -{ - *dest = src[1] * 0x100 + src[0]; -} - -static inline void hstoba(unsigned char *dest, unsigned short src) -{ - dest[0] = src % 0x100; - dest[1] = src / 0x100; -} - -#endif diff --git a/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c b/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c deleted file mode 100644 index 75857802c97a..000000000000 --- a/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Synaptics RMI4 touchscreen driver - * - * Copyright (C) 2012 Synaptics Incorporated - * - * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> - * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> - * - * 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 - * (at your option) any later version. - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/input.h> -#include <linux/gpio.h> -#include <linux/uaccess.h> -#include <linux/cdev.h> -#include <linux/input/synaptics_dsx.h> -#include "synaptics_i2c_rmi4.h" - -#define CHAR_DEVICE_NAME "rmi" -#define DEVICE_CLASS_NAME "rmidev" -#define DEV_NUMBER 1 -#define REG_ADDR_LIMIT 0xFFFF - -static ssize_t rmidev_sysfs_open_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t rmidev_sysfs_release_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t rmidev_sysfs_address_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t rmidev_sysfs_length_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -static ssize_t rmidev_sysfs_data_show(struct device *dev, - struct device_attribute *attr, char *buf); - -static ssize_t rmidev_sysfs_data_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count); - -struct rmidev_handle { - dev_t dev_no; - unsigned short address; - unsigned int length; - struct device dev; - struct synaptics_rmi4_data *rmi4_data; - struct synaptics_rmi4_exp_fn_ptr *fn_ptr; - struct kobject *sysfs_dir; - void *data; -}; - -struct rmidev_data { - int ref_count; - struct cdev main_dev; - struct class *device_class; - struct mutex file_mutex; - struct rmidev_handle *rmi_dev; -}; - -static struct device_attribute attrs[] = { - __ATTR(open, S_IWUGO, - synaptics_rmi4_show_error, - rmidev_sysfs_open_store), - __ATTR(release, S_IWUGO, - synaptics_rmi4_show_error, - rmidev_sysfs_release_store), - __ATTR(address, S_IWUGO, - synaptics_rmi4_show_error, - rmidev_sysfs_address_store), - __ATTR(length, S_IWUGO, - synaptics_rmi4_show_error, - rmidev_sysfs_length_store), - __ATTR(data, (S_IRUGO | S_IWUGO), - rmidev_sysfs_data_show, - rmidev_sysfs_data_store), -}; - -static int rmidev_major_num; - -static struct class *rmidev_device_class; - -static struct rmidev_handle *rmidev; - -static struct completion remove_complete; - -static ssize_t rmidev_sysfs_open_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned int input; - - if (sscanf(buf, "%u", &input) != 1) - return -EINVAL; - - if (input != 1) - return -EINVAL; - - rmidev->fn_ptr->enable(rmidev->rmi4_data, false); - dev_dbg(&rmidev->rmi4_data->i2c_client->dev, - "%s: Attention interrupt disabled\n", - __func__); - - return count; -} - -static ssize_t rmidev_sysfs_release_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned int input; - - if (sscanf(buf, "%u", &input) != 1) - return -EINVAL; - - if (input != 1) - return -EINVAL; - - rmidev->fn_ptr->enable(rmidev->rmi4_data, true); - dev_dbg(&rmidev->rmi4_data->i2c_client->dev, - "%s: Attention interrupt enabled\n", - __func__); - - return count; -} - -static ssize_t rmidev_sysfs_address_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned int input; - - if (sscanf(buf, "%u", &input) != 1) - return -EINVAL; - - if (input > REG_ADDR_LIMIT) - return -EINVAL; - - rmidev->address = (unsigned short)input; - - return count; -} - -static ssize_t rmidev_sysfs_length_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned int input; - - if (sscanf(buf, "%u", &input) != 1) - return -EINVAL; - - if (input > REG_ADDR_LIMIT) - return -EINVAL; - - rmidev->length = input; - - return count; -} - -static ssize_t rmidev_sysfs_data_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int retval; - unsigned int data_length = rmidev->length; - - if (data_length > (REG_ADDR_LIMIT - rmidev->address)) - data_length = REG_ADDR_LIMIT - rmidev->address; - - if (data_length) { - retval = rmidev->fn_ptr->read(rmidev->rmi4_data, - rmidev->address, - (unsigned char *)buf, - data_length); - if (retval < 0) { - dev_err(&rmidev->rmi4_data->i2c_client->dev, - "%s: Failed to read data\n", - __func__); - return retval; - } - } else { - return -EINVAL; - } - - return data_length; -} - -static ssize_t rmidev_sysfs_data_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int retval; - unsigned int data_length = rmidev->length; - - if (data_length > (REG_ADDR_LIMIT - rmidev->address)) - data_length = REG_ADDR_LIMIT - rmidev->address; - - if (data_length) { - retval = rmidev->fn_ptr->write(rmidev->rmi4_data, - rmidev->address, - (unsigned char *)buf, - data_length); - if (retval < 0) { - dev_err(&rmidev->rmi4_data->i2c_client->dev, - "%s: Failed to write data\n", - __func__); - return retval; - } - } else { - return -EINVAL; - } - - return data_length; -} - -/* - * rmidev_llseek - used to set up register address - * - * @filp: file structure for seek - * @off: offset - * if whence == SEEK_SET, - * high 16 bits: page address - * low 16 bits: register address - * if whence == SEEK_CUR, - * offset from current position - * if whence == SEEK_END, - * offset from end position (0xFFFF) - * @whence: SEEK_SET, SEEK_CUR, or SEEK_END - */ -static loff_t rmidev_llseek(struct file *filp, loff_t off, int whence) -{ - loff_t newpos; - struct rmidev_data *dev_data = filp->private_data; - - if (IS_ERR(dev_data)) { - pr_err("%s: Pointer of char device data is invalid", __func__); - return -EBADF; - } - - mutex_lock(&(dev_data->file_mutex)); - - switch (whence) { - case SEEK_SET: - newpos = off; - break; - case SEEK_CUR: - newpos = filp->f_pos + off; - break; - case SEEK_END: - newpos = REG_ADDR_LIMIT + off; - break; - default: - newpos = -EINVAL; - goto clean_up; - } - - if (newpos < 0 || newpos > REG_ADDR_LIMIT) { - dev_err(&rmidev->rmi4_data->i2c_client->dev, - "%s: New position 0x%04x is invalid\n", - __func__, (unsigned int)newpos); - newpos = -EINVAL; - goto clean_up; - } - - filp->f_pos = newpos; - -clean_up: - mutex_unlock(&(dev_data->file_mutex)); - - return newpos; -} - -/* - * rmidev_read: - use to read data from rmi device - * - * @filp: file structure for read - * @buf: user space buffer pointer - * @count: number of bytes to read - * @f_pos: offset (starting register address) - */ -static ssize_t rmidev_read(struct file *filp, char __user *buf, - size_t count, loff_t *f_pos) -{ - ssize_t retval; - unsigned char tmpbuf[count + 1]; - struct rmidev_data *dev_data = filp->private_data; - - if (IS_ERR(dev_data)) { - pr_err("%s: Pointer of char device data is invalid", __func__); - return -EBADF; - } - - if (count == 0) - return 0; - - if (count > (REG_ADDR_LIMIT - *f_pos)) - count = REG_ADDR_LIMIT - *f_pos; - - mutex_lock(&(dev_data->file_mutex)); - - retval = rmidev->fn_ptr->read(rmidev->rmi4_data, - *f_pos, - tmpbuf, - count); - if (retval < 0) - goto clean_up; - - if (copy_to_user(buf, tmpbuf, count)) - retval = -EFAULT; - else - *f_pos += retval; - -clean_up: - mutex_unlock(&(dev_data->file_mutex)); - - return retval; -} - -/* - * rmidev_write: - used to write data to rmi device - * - * @filep: file structure for write - * @buf: user space buffer pointer - * @count: number of bytes to write - * @f_pos: offset (starting register address) - */ -static ssize_t rmidev_write(struct file *filp, const char __user *buf, - size_t count, loff_t *f_pos) -{ - ssize_t retval; - unsigned char tmpbuf[count + 1]; - struct rmidev_data *dev_data = filp->private_data; - - if (IS_ERR(dev_data)) { - pr_err("%s: Pointer of char device data is invalid", __func__); - return -EBADF; - } - - if (count == 0) - return 0; - - if (count > (REG_ADDR_LIMIT - *f_pos)) - count = REG_ADDR_LIMIT - *f_pos; - - if (copy_from_user(tmpbuf, buf, count)) - return -EFAULT; - - mutex_lock(&(dev_data->file_mutex)); - - retval = rmidev->fn_ptr->write(rmidev->rmi4_data, - *f_pos, - tmpbuf, - count); - if (retval >= 0) - *f_pos += retval; - - mutex_unlock(&(dev_data->file_mutex)); - - return retval; -} - -/* - * rmidev_open: enable access to rmi device - * @inp: inode struture - * @filp: file structure - */ -static int rmidev_open(struct inode *inp, struct file *filp) -{ - int retval = 0; - struct rmidev_data *dev_data = - container_of(inp->i_cdev, struct rmidev_data, main_dev); - - if (!dev_data) - return -EACCES; - - filp->private_data = dev_data; - - mutex_lock(&(dev_data->file_mutex)); - - rmidev->fn_ptr->enable(rmidev->rmi4_data, false); - dev_dbg(&rmidev->rmi4_data->i2c_client->dev, - "%s: Attention interrupt disabled\n", - __func__); - - if (dev_data->ref_count < 1) - dev_data->ref_count++; - else - retval = -EACCES; - - mutex_unlock(&(dev_data->file_mutex)); - - return retval; -} - -/* - * rmidev_release: - release access to rmi device - * @inp: inode structure - * @filp: file structure - */ -static int rmidev_release(struct inode *inp, struct file *filp) -{ - struct rmidev_data *dev_data = - container_of(inp->i_cdev, struct rmidev_data, main_dev); - - if (!dev_data) - return -EACCES; - - mutex_lock(&(dev_data->file_mutex)); - - dev_data->ref_count--; - if (dev_data->ref_count < 0) - dev_data->ref_count = 0; - - rmidev->fn_ptr->enable(rmidev->rmi4_data, true); - dev_dbg(&rmidev->rmi4_data->i2c_client->dev, - "%s: Attention interrupt enabled\n", - __func__); - - mutex_unlock(&(dev_data->file_mutex)); - - return 0; -} - -static const struct file_operations rmidev_fops = { - .owner = THIS_MODULE, - .llseek = rmidev_llseek, - .read = rmidev_read, - .write = rmidev_write, - .open = rmidev_open, - .release = rmidev_release, -}; - -static void rmidev_device_cleanup(struct rmidev_data *dev_data) -{ - dev_t devno; - - if (dev_data) { - devno = dev_data->main_dev.dev; - - if (dev_data->device_class) - device_destroy(dev_data->device_class, devno); - - cdev_del(&dev_data->main_dev); - - unregister_chrdev_region(devno, 1); - - dev_dbg(&rmidev->rmi4_data->i2c_client->dev, - "%s: rmidev device removed\n", - __func__); - } - - return; -} - -static char *rmi_char_devnode(struct device *dev, mode_t *mode) -{ - if (!mode) - return NULL; - - *mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - - return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev)); -} - -static int rmidev_create_device_class(void) -{ - rmidev_device_class = class_create(THIS_MODULE, DEVICE_CLASS_NAME); - - if (IS_ERR(rmidev_device_class)) { - pr_err("%s: Failed to create /dev/%s\n", - __func__, CHAR_DEVICE_NAME); - return -ENODEV; - } - - rmidev_device_class->devnode = rmi_char_devnode; - - return 0; -} - -static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - dev_t dev_no; - unsigned char attr_count; - struct rmidev_data *dev_data; - struct device *device_ptr; - - rmidev = kzalloc(sizeof(*rmidev), GFP_KERNEL); - if (!rmidev) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for rmidev\n", - __func__); - retval = -ENOMEM; - goto err_rmidev; - } - - rmidev->fn_ptr = kzalloc(sizeof(*(rmidev->fn_ptr)), GFP_KERNEL); - if (!rmidev) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for fn_ptr\n", - __func__); - retval = -ENOMEM; - goto err_fn_ptr; - } - - rmidev->fn_ptr->read = rmi4_data->i2c_read; - rmidev->fn_ptr->write = rmi4_data->i2c_write; - rmidev->fn_ptr->enable = rmi4_data->irq_enable; - rmidev->rmi4_data = rmi4_data; - - retval = rmidev_create_device_class(); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to create device class\n", - __func__); - goto err_device_class; - } - - if (rmidev_major_num) { - dev_no = MKDEV(rmidev_major_num, DEV_NUMBER); - retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME); - } else { - retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to allocate char device region\n", - __func__); - goto err_device_region; - } - - rmidev_major_num = MAJOR(dev_no); - dev_dbg(&rmi4_data->i2c_client->dev, - "%s: Major number of rmidev = %d\n", - __func__, rmidev_major_num); - } - - dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); - if (!dev_data) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to alloc mem for dev_data\n", - __func__); - retval = -ENOMEM; - goto err_dev_data; - } - - mutex_init(&dev_data->file_mutex); - dev_data->rmi_dev = rmidev; - rmidev->data = dev_data; - - cdev_init(&dev_data->main_dev, &rmidev_fops); - - retval = cdev_add(&dev_data->main_dev, dev_no, 1); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to add rmi char device\n", - __func__); - goto err_char_device; - } - - dev_set_name(&rmidev->dev, "rmidev%d", MINOR(dev_no)); - dev_data->device_class = rmidev_device_class; - - device_ptr = device_create(dev_data->device_class, NULL, dev_no, - NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no)); - if (IS_ERR(device_ptr)) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to create rmi char device\n", - __func__); - retval = -ENODEV; - goto err_char_device; - } - - retval = gpio_export(rmi4_data->board->irq_gpio, false); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to export attention gpio\n", - __func__); - } else { - retval = gpio_export_link(&(rmi4_data->input_dev->dev), - "attn", rmi4_data->board->irq_gpio); - if (retval < 0) { - dev_err(&rmi4_data->input_dev->dev, - "%s Failed to create gpio symlink\n", - __func__); - } else { - dev_dbg(&rmi4_data->input_dev->dev, - "%s: Exported attention gpio %d\n", - __func__, rmi4_data->board->irq_gpio); - } - } - - rmidev->sysfs_dir = kobject_create_and_add("rmidev", - &rmi4_data->input_dev->dev.kobj); - if (!rmidev->sysfs_dir) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to create sysfs directory\n", - __func__); - goto err_sysfs_dir; - } - - for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { - retval = sysfs_create_file(rmidev->sysfs_dir, - &attrs[attr_count].attr); - if (retval < 0) { - dev_err(&rmi4_data->input_dev->dev, - "%s: Failed to create sysfs attributes\n", - __func__); - retval = -ENODEV; - goto err_sysfs_attrs; - } - } - - return 0; - -err_sysfs_attrs: - for (attr_count--; attr_count >= 0; attr_count--) { - sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, - &attrs[attr_count].attr); - } - - kobject_put(rmidev->sysfs_dir); - -err_sysfs_dir: -err_char_device: - rmidev_device_cleanup(dev_data); - kfree(dev_data); - -err_dev_data: - unregister_chrdev_region(dev_no, 1); - -err_device_region: - class_destroy(rmidev_device_class); - -err_device_class: - kfree(rmidev->fn_ptr); - -err_fn_ptr: - kfree(rmidev); - -err_rmidev: - return retval; -} - -static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data) -{ - unsigned char attr_count; - struct rmidev_data *dev_data; - - if (!rmidev) - return; - - for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) - sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr); - - kobject_put(rmidev->sysfs_dir); - - dev_data = rmidev->data; - if (dev_data) { - rmidev_device_cleanup(dev_data); - kfree(dev_data); - } - - unregister_chrdev_region(rmidev->dev_no, 1); - - class_destroy(rmidev_device_class); - - kfree(rmidev->fn_ptr); - kfree(rmidev); - - complete(&remove_complete); - - return; -} - -static int __init rmidev_module_init(void) -{ - synaptics_rmi4_new_function(RMI_DEV, true, - rmidev_init_device, - rmidev_remove_device, - NULL); - return 0; -} - -static void __exit rmidev_module_exit(void) -{ - init_completion(&remove_complete); - synaptics_rmi4_new_function(RMI_DEV, false, - rmidev_init_device, - rmidev_remove_device, - NULL); - wait_for_completion(&remove_complete); - return; -} - -module_init(rmidev_module_init); -module_exit(rmidev_module_exit); - -MODULE_AUTHOR("Synaptics, Inc."); -MODULE_DESCRIPTION("RMI4 RMI_Dev Module"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION); diff --git a/kernel/include/linux/input/synaptics_dsx.h b/kernel/include/linux/input/synaptics_dsx.h deleted file mode 100644 index b779e42a9bac..000000000000 --- a/kernel/include/linux/input/synaptics_dsx.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Synaptics RMI4 touchscreen driver - * - * Copyright (C) 2012 Synaptics Incorporated - * - * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com> - * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com> - * - * 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 - * (at your option) any later version. - * - * 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 _SYNAPTICS_DSX_H_ -#define _SYNAPTICS_DSX_H_ - -/* - * struct synaptics_rmi4_capacitance_button_map - 0d button map - * @nbuttons: number of buttons - * @map: button map - */ -struct synaptics_rmi4_capacitance_button_map { - unsigned char nbuttons; - unsigned char *map; -}; - -/* - * struct synaptics_rmi4_platform_data - rmi4 platform data - * @x_flip: x flip flag - * @y_flip: y flip flag - * @regulator_en: regulator enable flag - * @irq_gpio: attention interrupt gpio - * @irq_flags: flags used by the irq - * @reset_gpio: reset gpio - * @panel_x: panel maximum values on the x - * @panel_y: panel maximum values on the y - * @gpio_config: pointer to gpio configuration function - * @capacitance_button_map: pointer to 0d button map - */ -struct synaptics_rmi4_platform_data { - bool x_flip; - bool y_flip; - bool regulator_en; - unsigned irq_gpio; - unsigned long irq_flags; - unsigned reset_gpio; - unsigned panel_x; - unsigned panel_y; - int (*gpio_config)(unsigned gpio, bool configure); - struct synaptics_rmi4_capacitance_button_map *capacitance_button_map; -}; - -#endif diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 6e39de2836ea..84563da000cf 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1912,7 +1912,7 @@ void scheduler_ipi(void) /* * Check if someone kicked us for doing the nohz idle load balance. */ - if (unlikely(got_nohz_idle_kick())) { + if (unlikely(got_nohz_idle_kick()) && !cpu_isolated(cpu)) { this_rq()->idle_balance = 1; raise_softirq_irqoff(SCHED_SOFTIRQ); } @@ -5497,7 +5497,7 @@ static void migrate_tasks(struct rq *dead_rq, bool migrate_pinned_tasks) */ if ((migrate_pinned_tasks && rq->nr_running == 1) || (!migrate_pinned_tasks && - rq->nr_running == num_pinned_kthreads)) + rq->nr_running <= num_pinned_kthreads)) break; /* @@ -5533,8 +5533,12 @@ static void migrate_tasks(struct rq *dead_rq, bool migrate_pinned_tasks) * Since we're inside stop-machine, _nothing_ should have * changed the task, WARN if weird stuff happened, because in * that case the above rq->lock drop is a fail too. + * However, during cpu isolation the load balancer might have + * interferred since we don't stop all CPUs. Ignore warning for + * this case. */ - if (WARN_ON(task_rq(next) != rq || !task_on_rq_queued(next))) { + if (task_rq(next) != rq || !task_on_rq_queued(next)) { + WARN_ON(migrate_pinned_tasks); raw_spin_unlock(&next->pi_lock); continue; } @@ -5562,7 +5566,6 @@ static void set_rq_offline(struct rq *rq); int do_isolation_work_cpu_stop(void *data) { - unsigned long flags; unsigned int cpu = smp_processor_id(); struct rq *rq = cpu_rq(cpu); @@ -5570,23 +5573,35 @@ int do_isolation_work_cpu_stop(void *data) irq_migrate_all_off_this_cpu(); + local_irq_disable(); + sched_ttwu_pending(); - /* Update our root-domain */ - raw_spin_lock_irqsave(&rq->lock, flags); + raw_spin_lock(&rq->lock); + + /* + * Temporarily mark the rq as offline. This will allow us to + * move tasks off the CPU. + */ if (rq->rd) { BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); set_rq_offline(rq); } migrate_tasks(rq, false); - raw_spin_unlock_irqrestore(&rq->lock, flags); + + if (rq->rd) + set_rq_online(rq); + raw_spin_unlock(&rq->lock); /* * We might have been in tickless state. Clear NOHZ flags to avoid * us being kicked for helping out with balancing */ nohz_balance_clear_nohz_mask(cpu); + + clear_hmp_request(cpu); + local_irq_enable(); return 0; } @@ -5685,6 +5700,22 @@ int sched_isolate_cpu(int cpu) if (++cpu_isolation_vote[cpu] > 1) goto out; + /* + * There is a race between watchdog being enabled by hotplug and + * core isolation disabling the watchdog. When a CPU is hotplugged in + * and the hotplug lock has been released the watchdog thread might + * not have run yet to enable the watchdog. + * We have to wait for the watchdog to be enabled before proceeding. + */ + if (!watchdog_configured(cpu)) { + msleep(20); + if (!watchdog_configured(cpu)) { + --cpu_isolation_vote[cpu]; + ret_code = -EBUSY; + goto out; + } + } + set_cpu_isolated(cpu, true); cpumask_clear_cpu(cpu, &avail_cpus); @@ -5695,7 +5726,6 @@ int sched_isolate_cpu(int cpu) migrate_sync_cpu(cpu, cpumask_first(&avail_cpus)); stop_cpus(cpumask_of(cpu), do_isolation_work_cpu_stop, 0); - clear_hmp_request(cpu); calc_load_migrate(rq); update_max_interval(); sched_update_group_capacities(cpu); @@ -5737,10 +5767,6 @@ int sched_unisolate_cpu_unlocked(int cpu) raw_spin_lock_irqsave(&rq->lock, flags); rq->age_stamp = sched_clock_cpu(cpu); - if (rq->rd) { - BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); - set_rq_online(rq); - } raw_spin_unlock_irqrestore(&rq->lock, flags); } diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c index 0db85a4fa9c8..9b21a09ec4ba 100644 --- a/kernel/sched/core_ctl.c +++ b/kernel/sched/core_ctl.c @@ -687,6 +687,7 @@ int core_ctl_set_boost(bool boost) return ret; } +EXPORT_SYMBOL(core_ctl_set_boost); void core_ctl_check(u64 wallclock) { @@ -719,8 +720,18 @@ static void move_cpu_lru(struct cpu_data *cpu_data) static void try_to_isolate(struct cluster_data *cluster, unsigned int need) { struct cpu_data *c, *tmp; + unsigned long flags; + unsigned int num_cpus = cluster->num_cpus; + /* + * Protect against entry being removed (and added at tail) by other + * thread (hotplug). + */ + spin_lock_irqsave(&state_lock, flags); list_for_each_entry_safe(c, tmp, &cluster->lru, sib) { + if (!num_cpus--) + break; + if (!is_active(c)) continue; if (cluster->active_cpus == need) @@ -729,6 +740,8 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need) if (c->is_busy) continue; + spin_unlock_irqrestore(&state_lock, flags); + pr_debug("Trying to isolate CPU%u\n", c->cpu); if (!sched_isolate_cpu(c->cpu)) { c->isolated_by_us = true; @@ -738,7 +751,9 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need) pr_debug("Unable to isolate CPU%u\n", c->cpu); } cluster->active_cpus = get_active_cpu_count(cluster); + spin_lock_irqsave(&state_lock, flags); } + spin_unlock_irqrestore(&state_lock, flags); /* * If the number of active CPUs is within the limits, then @@ -747,12 +762,19 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need) if (cluster->active_cpus <= cluster->max_cpus) return; + num_cpus = cluster->num_cpus; + spin_lock_irqsave(&state_lock, flags); list_for_each_entry_safe(c, tmp, &cluster->lru, sib) { + if (!num_cpus--) + break; + if (!is_active(c)) continue; if (cluster->active_cpus <= cluster->max_cpus) break; + spin_unlock_irqrestore(&state_lock, flags); + pr_debug("Trying to isolate CPU%u\n", c->cpu); if (!sched_isolate_cpu(c->cpu)) { c->isolated_by_us = true; @@ -762,15 +784,28 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need) pr_debug("Unable to isolate CPU%u\n", c->cpu); } cluster->active_cpus = get_active_cpu_count(cluster); + spin_lock_irqsave(&state_lock, flags); } + spin_unlock_irqrestore(&state_lock, flags); + } static void __try_to_unisolate(struct cluster_data *cluster, unsigned int need, bool force) { struct cpu_data *c, *tmp; + unsigned long flags; + unsigned int num_cpus = cluster->num_cpus; + /* + * Protect against entry being removed (and added at tail) by other + * thread (hotplug). + */ + spin_lock_irqsave(&state_lock, flags); list_for_each_entry_safe(c, tmp, &cluster->lru, sib) { + if (!num_cpus--) + break; + if (!c->isolated_by_us) continue; if ((c->online && !cpu_isolated(c->cpu)) || @@ -779,6 +814,8 @@ static void __try_to_unisolate(struct cluster_data *cluster, if (cluster->active_cpus == need) break; + spin_unlock_irqrestore(&state_lock, flags); + pr_debug("Trying to unisolate CPU%u\n", c->cpu); if (!sched_unisolate_cpu(c->cpu)) { c->isolated_by_us = false; @@ -787,7 +824,9 @@ static void __try_to_unisolate(struct cluster_data *cluster, pr_debug("Unable to unisolate CPU%u\n", c->cpu); } cluster->active_cpus = get_active_cpu_count(cluster); + spin_lock_irqsave(&state_lock, flags); } + spin_unlock_irqrestore(&state_lock, flags); } static void try_to_unisolate(struct cluster_data *cluster, unsigned int need) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 21a60beb8288..1674b1054f83 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -8121,8 +8121,11 @@ static struct rq *find_busiest_queue_hmp(struct lb_env *env, int max_nr_big = 0, nr_big; bool find_big = !!(env->flags & LBF_BIG_TASK_ACTIVE_BALANCE); int i; + cpumask_t cpus; - for_each_cpu(i, sched_group_cpus(group)) { + cpumask_andnot(&cpus, sched_group_cpus(group), cpu_isolated_mask); + + for_each_cpu(i, &cpus) { struct rq *rq = cpu_rq(i); u64 cumulative_runnable_avg = rq->hmp_stats.cumulative_runnable_avg; @@ -8285,6 +8288,15 @@ static int need_active_balance(struct lb_env *env) sd->cache_nice_tries + NEED_ACTIVE_BALANCE_THRESHOLD); } +static int group_balance_cpu_not_isolated(struct sched_group *sg) +{ + cpumask_t cpus; + + cpumask_and(&cpus, sched_group_cpus(sg), sched_group_mask(sg)); + cpumask_andnot(&cpus, &cpus, cpu_isolated_mask); + return cpumask_first(&cpus); +} + static int should_we_balance(struct lb_env *env) { struct sched_group *sg = env->sd->groups; @@ -8302,7 +8314,8 @@ static int should_we_balance(struct lb_env *env) sg_mask = sched_group_mask(sg); /* Try to find first idle cpu */ for_each_cpu_and(cpu, sg_cpus, env->cpus) { - if (!cpumask_test_cpu(cpu, sg_mask) || !idle_cpu(cpu)) + if (!cpumask_test_cpu(cpu, sg_mask) || !idle_cpu(cpu) || + cpu_isolated(cpu)) continue; balance_cpu = cpu; @@ -8310,7 +8323,7 @@ static int should_we_balance(struct lb_env *env) } if (balance_cpu == -1) - balance_cpu = group_balance_cpu(sg); + balance_cpu = group_balance_cpu_not_isolated(sg); /* * First idle cpu or the first cpu(busiest) in this sched group @@ -8530,7 +8543,8 @@ no_move: * ->active_balance_work. Once set, it's cleared * only after active load balance is finished. */ - if (!busiest->active_balance) { + if (!busiest->active_balance && + !cpu_isolated(cpu_of(busiest))) { busiest->active_balance = 1; busiest->push_cpu = this_cpu; active_balance = 1; @@ -9198,12 +9212,15 @@ static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle) /* Earliest time when we have to do rebalance again */ unsigned long next_balance = jiffies + 60*HZ; int update_next_balance = 0; + cpumask_t cpus; if (idle != CPU_IDLE || !test_bit(NOHZ_BALANCE_KICK, nohz_flags(this_cpu))) goto end; - for_each_cpu(balance_cpu, nohz.idle_cpus_mask) { + cpumask_andnot(&cpus, nohz.idle_cpus_mask, cpu_isolated_mask); + + for_each_cpu(balance_cpu, &cpus) { if (balance_cpu == this_cpu || !idle_cpu(balance_cpu)) continue; diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 18d2fe271cf7..c3914e8f87b0 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -49,6 +49,7 @@ #include <linux/sched/deadline.h> #include <linux/timer.h> #include <linux/freezer.h> +#include <linux/delay.h> #include <asm/uaccess.h> @@ -1648,6 +1649,12 @@ static void migrate_hrtimer_list(struct hrtimer_cpu_base *old_base, raw_spin_unlock(&old_base->lock); raw_spin_unlock(&new_base->lock); cpu_relax(); + /* + * cpu_relax may just be a barrier. Grant the + * run_hrtimer_list code some time to obtain the + * spinlock. + */ + udelay(2); raw_spin_lock(&new_base->lock); raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 748eefb72a91..5ebefc7cfa4f 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1640,7 +1640,7 @@ static void migrate_timer_list(struct tvec_base *new_base, } } -static void __migrate_timers(int cpu, bool wait, bool remove_pinned) +static void __migrate_timers(int cpu, bool remove_pinned) { struct tvec_base *old_base; struct tvec_base *new_base; @@ -1656,18 +1656,14 @@ static void __migrate_timers(int cpu, bool wait, bool remove_pinned) spin_lock_irqsave(&new_base->lock, flags); spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); - if (wait) { - /* Ensure timers are done running before continuing */ - while (old_base->running_timer) { - spin_unlock(&old_base->lock); - spin_unlock_irqrestore(&new_base->lock, flags); - cpu_relax(); - spin_lock_irqsave(&new_base->lock, flags); - spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); - } - } else { + /* + * If we're in the hotplug path, kill the system if there's a running + * timer. It's ok to have a running timer in the isolation case - the + * currently running or just expired timers are off of the timer wheel + * and so everything else can be migrated off. + */ + if (!cpu_online(cpu)) BUG_ON(old_base->running_timer); - } for (i = 0; i < TVR_SIZE; i++) migrate_timer_list(new_base, old_base->tv1.vec + i, @@ -1692,12 +1688,12 @@ static void __migrate_timers(int cpu, bool wait, bool remove_pinned) static void migrate_timers(int cpu) { BUG_ON(cpu_online(cpu)); - __migrate_timers(cpu, false, true); + __migrate_timers(cpu, true); } void timer_quiesce_cpu(void *cpup) { - __migrate_timers(*(int *)cpup, true, false); + __migrate_timers(*(int *)cpup, false); } static int timer_cpu_notify(struct notifier_block *self, diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 7f21591c8ec5..f2813e137b23 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -588,17 +588,13 @@ static void watchdog_set_prio(unsigned int policy, unsigned int prio) sched_setscheduler(current, policy, ¶m); } -/* Must be called with hotplug lock (lock_device_hotplug()) held. */ void watchdog_enable(unsigned int cpu) { struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer); unsigned int *enabled = raw_cpu_ptr(&watchdog_en); - lock_device_hotplug_assert(); - if (*enabled) return; - *enabled = 1; /* kick off the timer for the hardlockup detector */ hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); @@ -614,24 +610,40 @@ void watchdog_enable(unsigned int cpu) /* initialize timestamp */ watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1); __touch_watchdog(); + + /* + * Need to ensure above operations are observed by other CPUs before + * indicating that timer is enabled. This is to synchronize core + * isolation and hotplug. Core isolation will wait for this flag to be + * set. + */ + mb(); + *enabled = 1; } -/* Must be called with hotplug lock (lock_device_hotplug()) held. */ void watchdog_disable(unsigned int cpu) { struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer); unsigned int *enabled = raw_cpu_ptr(&watchdog_en); - lock_device_hotplug_assert(); - if (!*enabled) return; - *enabled = 0; watchdog_set_prio(SCHED_NORMAL, 0); hrtimer_cancel(hrtimer); /* disable the perf event */ watchdog_nmi_disable(cpu); + + /* + * No need for barrier here since disabling the watchdog is + * synchronized with hotplug lock + */ + *enabled = 0; +} + +bool watchdog_configured(unsigned int cpu) +{ + return *per_cpu_ptr(&watchdog_en, cpu); } static void watchdog_cleanup(unsigned int cpu, bool online) diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c index e060c7cdf24c..100963091cc6 100644 --- a/mm/debug-pagealloc.c +++ b/mm/debug-pagealloc.c @@ -113,6 +113,7 @@ static void check_poison_mem(struct page *page, print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start, end - start + 1, 1); + BUG_ON(PANIC_CORRUPTION); dump_stack(); } diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index dda332d821e4..456a1dff692d 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c @@ -460,9 +460,9 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par) list_del(&info->timer->entry); del_timer_sync(&info->timer->timer); - cancel_work_sync(&info->timer->work); sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr); unregister_pm_notifier(&info->timer->pm_nb); + cancel_work_sync(&info->timer->work); kfree(info->timer->attr.attr.name); kfree(info->timer); } else { diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c index 4e3a205551e0..2999e2c15fdb 100644 --- a/net/rmnet_data/rmnet_data_vnd.c +++ b/net/rmnet_data/rmnet_data_vnd.c @@ -180,6 +180,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, rmnet_vnd_add_qos_header(skb, dev, dev_conf->qos_version); + skb_orphan(skb); rmnet_egress_handler(skb, &dev_conf->local_ep); } else { dev->stats.tx_dropped++; diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd.c b/sound/soc/codecs/msm8x16/msm8x16-wcd.c index 481e1efdf015..c73414681c5a 100644 --- a/sound/soc/codecs/msm8x16/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16/msm8x16-wcd.c @@ -40,9 +40,10 @@ #include <sound/tlv.h> #include <sound/q6core.h> #include <soc/qcom/subsystem_notif.h> -#include "msm8x16-wcd.h" +#include "../../msm/msmfalcon-common.h" #include "../wcd-mbhc-v2.h" #include "msm8916-wcd-irq.h" +#include "msm8x16-wcd.h" #define DRV_NAME "msm-codec" #define MSM89XX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ @@ -253,8 +254,6 @@ static struct wcd_mbhc_register 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", @@ -295,7 +294,7 @@ static int msm8x16_wcd_dt_parse_vreg_info(struct device *dev, 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, +static int msm8x16_wcd_enable_ext_mb_source(struct wcd_mbhc *mbhc, 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); @@ -335,35 +334,28 @@ static int get_codec_version(struct msm8x16_wcd_priv *msm8x16_wcd) static int msm_digcdc_clock_control(bool flag) { int ret = -EINVAL; - struct msm8916_asoc_mach_data *pdata = NULL; + struct msm_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); - } + mutex_lock(&pdata->cdc_int_mclk0_mutex); + if (atomic_read(&pdata->int_mclk0_enabled) == false) { + pdata->digital_cdc_core_clk.enable = 1; + ret = afe_set_lpass_clock_v2( + AFE_PORT_ID_INT0_MI2S_RX, + &pdata->digital_cdc_core_clk); if (ret < 0) { - pr_err("failed to enable the MCLK\n"); - goto err; + pr_err("failed to enable the INT_MCLK0\n"); + goto err_mclk; } pr_err("enabled digital codec core clk\n"); - atomic_set(&pdata->mclk_enabled, true); - schedule_delayed_work(&pdata->disable_mclk_work, 50); + atomic_set(&pdata->int_mclk0_enabled, true); + schedule_delayed_work(&pdata->disable_int_mclk0_work, + 50); } -err: - mutex_unlock(&pdata->cdc_mclk_mutex); +err_mclk: + mutex_unlock(&pdata->cdc_int_mclk0_mutex); return ret; } return 0; @@ -617,11 +609,12 @@ static void msm8x16_wcd_compute_impedance(struct snd_soc_codec *codec, s16 l, } static struct firmware_cal *msm8x16_wcd_get_hwdep_fw_cal( - struct snd_soc_codec *codec, + struct wcd_mbhc *mbhc, enum wcd_cal_type type) { struct msm8x16_wcd_priv *msm8x16_wcd; struct firmware_cal *hwdep_cal; + struct snd_soc_codec *codec = mbhc->codec; if (!codec) { pr_err("%s: NULL codec pointer\n", __func__); @@ -1063,10 +1056,11 @@ exit: pr_err("%s: Impedance detection completed\n", __func__); } -static int msm8x16_register_notifier(struct snd_soc_codec *codec, +static int msm8x16_register_notifier(struct wcd_mbhc *mbhc, struct notifier_block *nblock, bool enable) { + struct snd_soc_codec *codec = mbhc->codec; struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); @@ -1624,7 +1618,7 @@ out: static int msm8x16_wcd_codec_enable_clock_block(struct snd_soc_codec *codec, int enable) { - struct msm8916_asoc_mach_data *pdata = NULL; + struct msm_asoc_mach_data *pdata = NULL; pdata = snd_soc_card_get_drvdata(codec->component.card); if (enable) { @@ -1776,7 +1770,7 @@ 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; + struct msm_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", @@ -1789,7 +1783,7 @@ 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; + struct msm_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", @@ -3061,7 +3055,7 @@ static int msm8x16_wcd_codec_enable_dig_clk(struct snd_soc_dapm_widget *w, { 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; + struct msm_asoc_mach_data *pdata = NULL; pdata = snd_soc_card_get_drvdata(codec->component.card); @@ -3202,11 +3196,12 @@ static void msm8x16_trim_btn_reg(struct snd_soc_codec *codec) pr_err("%s: This device is trimmed at ATE\n", __func__); } } -static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec, +static int msm8x16_wcd_enable_ext_mb_source(struct wcd_mbhc *mbhc, bool turn_on) { int ret = 0; static int count; + struct snd_soc_codec *codec = mbhc->codec; 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, @@ -3405,7 +3400,7 @@ 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; + struct msm_asoc_mach_data *pdata = NULL; unsigned int decimator; struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); char *dec_name = NULL; @@ -4328,14 +4323,14 @@ int msm8x16_wcd_mclk_enable(struct snd_soc_codec *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->int_mclk0_enabled = true; msm8x16_wcd_codec_enable_clock_block(codec, 1); } else { - if (!msm8x16_wcd->mclk_enabled) { + if (!msm8x16_wcd->int_mclk0_enabled) { dev_err(codec->dev, "Error, MCLK already diabled\n"); return -EINVAL; } - msm8x16_wcd->mclk_enabled = false; + msm8x16_wcd->int_mclk0_enabled = false; msm8x16_wcd_codec_enable_clock_block(codec, 0); } return 0; @@ -5178,7 +5173,7 @@ static struct regulator *wcd8x16_wcd_codec_find_regulator( static int msm8x16_wcd_device_down(struct snd_soc_codec *codec) { - struct msm8916_asoc_mach_data *pdata = NULL; + struct msm_asoc_mach_data *pdata = NULL; struct msm8x16_wcd_priv *msm8x16_wcd_priv = snd_soc_codec_get_drvdata(codec); int i; @@ -5250,7 +5245,7 @@ static int msm8x16_wcd_device_down(struct snd_soc_codec *codec) MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x93); msm8x16_wcd_bringup(codec); - atomic_set(&pdata->mclk_enabled, false); + atomic_set(&pdata->int_mclk0_enabled, false); set_bit(BUS_DOWN, &msm8x16_wcd_priv->status_mask); snd_soc_card_change_online_state(codec->component.card, 0); return 0; @@ -5399,7 +5394,7 @@ static void msm8x16_wcd_configure_cap(struct snd_soc_codec *codec, bool micbias1, bool micbias2) { - struct msm8916_asoc_mach_data *pdata = NULL; + struct msm_asoc_mach_data *pdata = NULL; pdata = snd_soc_card_get_drvdata(codec->component.card); @@ -5553,7 +5548,7 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec) 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->int_mclk0_enabled = false; msm8x16_wcd_priv->clock_active = false; msm8x16_wcd_priv->config_mode_active = false; @@ -5654,33 +5649,23 @@ static int msm8x16_wcd_disable_static_supplies_to_optimum( int msm8x16_wcd_suspend(struct snd_soc_codec *codec) { - struct msm8916_asoc_mach_data *pdata = NULL; + struct msm_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) { + __func__, atomic_read(&pdata->int_mclk0_rsc_ref), + atomic_read(&pdata->int_mclk0_enabled)); + if (atomic_read(&pdata->int_mclk0_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); + &pdata->disable_int_mclk0_work); + mutex_lock(&pdata->cdc_int_mclk0_mutex); + pdata->digital_cdc_core_clk.enable = 0; + afe_set_lpass_clock_v2(AFE_PORT_ID_INT0_MI2S_RX, + &pdata->digital_cdc_core_clk); + atomic_set(&pdata->int_mclk0_enabled, false); + mutex_unlock(&pdata->cdc_int_mclk0_mutex); } msm8x16_wcd_disable_static_supplies_to_optimum(msm8x16, msm8x16_pdata); return 0; @@ -5688,7 +5673,7 @@ int msm8x16_wcd_suspend(struct snd_soc_codec *codec) int msm8x16_wcd_resume(struct snd_soc_codec *codec) { - struct msm8916_asoc_mach_data *pdata = NULL; + struct msm_asoc_mach_data *pdata = NULL; struct msm8x16_wcd *msm8x16 = codec->control_data; struct msm8x16_wcd_pdata *msm8x16_pdata = msm8x16->dev->platform_data; diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd.h b/sound/soc/codecs/msm8x16/msm8x16-wcd.h index d2e782b07cb2..776090258119 100644 --- a/sound/soc/codecs/msm8x16/msm8x16-wcd.h +++ b/sound/soc/codecs/msm8x16/msm8x16-wcd.h @@ -221,31 +221,6 @@ struct wcd_imped_i_ref { 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; @@ -291,7 +266,7 @@ struct msm8x16_wcd_priv { u32 rx_bias_count; s32 dmic_1_2_clk_cnt; u32 mute_mask; - bool mclk_enabled; + bool int_mclk0_enabled; bool clock_active; bool config_mode_active; u16 boost_option; diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 281db1d07f57..06e00fdfe6a1 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -714,6 +714,16 @@ struct hpf_work { struct delayed_work dwork; }; +#define WCD9335_SPK_ANC_EN_DELAY_MS 350 +static int spk_anc_en_delay = WCD9335_SPK_ANC_EN_DELAY_MS; +module_param(spk_anc_en_delay, int, S_IRUGO | S_IWUSR | S_IWGRP); +MODULE_PARM_DESC(spk_anc_en_delay, "delay to enable anc in speaker path"); + +struct spk_anc_work { + struct tasha_priv *tasha; + struct delayed_work dwork; +}; + struct tx_mute_work { struct tasha_priv *tasha; u8 decimator; @@ -836,6 +846,7 @@ struct tasha_priv { int ear_spkr_gain; struct hpf_work tx_hpf_work[TASHA_NUM_DECIMATORS]; struct tx_mute_work tx_mute_dwork[TASHA_NUM_DECIMATORS]; + struct spk_anc_work spk_anc_dwork; struct mutex codec_mutex; int hph_l_gain; int hph_r_gain; @@ -4278,6 +4289,21 @@ static int tasha_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w, return ret; } +static void tasha_spk_anc_update_callback(struct work_struct *work) +{ + struct spk_anc_work *spk_anc_dwork; + struct tasha_priv *tasha; + struct delayed_work *delayed_work; + struct snd_soc_codec *codec; + + delayed_work = to_delayed_work(work); + spk_anc_dwork = container_of(delayed_work, struct spk_anc_work, dwork); + tasha = spk_anc_dwork->tasha; + codec = tasha->codec; + + snd_soc_update_bits(codec, WCD9335_CDC_RX7_RX_PATH_CFG0, 0x10, 0x10); +} + static int tasha_codec_enable_spk_anc(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -4295,10 +4321,11 @@ static int tasha_codec_enable_spk_anc(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: ret = tasha_codec_enable_anc(w, kcontrol, event); - snd_soc_update_bits(codec, WCD9335_CDC_RX7_RX_PATH_CFG0, - 0x10, 0x10); + schedule_delayed_work(&tasha->spk_anc_dwork.dwork, + msecs_to_jiffies(spk_anc_en_delay)); break; case SND_SOC_DAPM_POST_PMD: + cancel_delayed_work_sync(&tasha->spk_anc_dwork.dwork); snd_soc_update_bits(codec, WCD9335_CDC_RX7_RX_PATH_CFG0, 0x10, 0x00); ret = tasha_codec_enable_anc(w, kcontrol, event); @@ -11793,7 +11820,7 @@ static struct snd_soc_dai_driver tasha_dai[] = { .capture = { .stream_name = "AIF1 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 192000, .rate_min = 8000, .channels_min = 1, @@ -11821,7 +11848,7 @@ static struct snd_soc_dai_driver tasha_dai[] = { .capture = { .stream_name = "AIF2 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 192000, .rate_min = 8000, .channels_min = 1, @@ -11849,7 +11876,7 @@ static struct snd_soc_dai_driver tasha_dai[] = { .capture = { .stream_name = "AIF3 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 48000, .rate_min = 8000, .channels_min = 1, @@ -11950,7 +11977,7 @@ static struct snd_soc_dai_driver tasha_i2s_dai[] = { .capture = { .stream_name = "AIF1 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 192000, .rate_min = 8000, .channels_min = 1, @@ -11978,7 +12005,7 @@ static struct snd_soc_dai_driver tasha_i2s_dai[] = { .capture = { .stream_name = "AIF2 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 192000, .rate_min = 8000, .channels_min = 1, @@ -13687,6 +13714,10 @@ static int tasha_codec_probe(struct snd_soc_codec *codec) tasha_tx_mute_update_callback); } + tasha->spk_anc_dwork.tasha = tasha; + INIT_DELAYED_WORK(&tasha->spk_anc_dwork.dwork, + tasha_spk_anc_update_callback); + mutex_lock(&tasha->codec_mutex); snd_soc_dapm_disable_pin(dapm, "ANC LINEOUT1"); snd_soc_dapm_disable_pin(dapm, "ANC LINEOUT2"); diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index 6745aec41388..56882be12554 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -546,6 +546,16 @@ struct tx_mute_work { struct delayed_work dwork; }; +#define WCD934X_SPK_ANC_EN_DELAY_MS 350 +static int spk_anc_en_delay = WCD934X_SPK_ANC_EN_DELAY_MS; +module_param(spk_anc_en_delay, int, S_IRUGO | S_IWUSR | S_IWGRP); +MODULE_PARM_DESC(spk_anc_en_delay, "delay to enable anc in speaker path"); + +struct spk_anc_work { + struct tavil_priv *tavil; + struct delayed_work dwork; +}; + struct hpf_work { struct tavil_priv *tavil; u8 decimator; @@ -610,6 +620,7 @@ struct tavil_priv { struct work_struct tavil_add_child_devices_work; struct hpf_work tx_hpf_work[WCD934X_NUM_DECIMATORS]; struct tx_mute_work tx_mute_dwork[WCD934X_NUM_DECIMATORS]; + struct spk_anc_work spk_anc_dwork; unsigned int vi_feed_value; @@ -1775,6 +1786,21 @@ static int tavil_codec_enable_rx_bias(struct snd_soc_dapm_widget *w, return 0; } +static void tavil_spk_anc_update_callback(struct work_struct *work) +{ + struct spk_anc_work *spk_anc_dwork; + struct tavil_priv *tavil; + struct delayed_work *delayed_work; + struct snd_soc_codec *codec; + + delayed_work = to_delayed_work(work); + spk_anc_dwork = container_of(delayed_work, struct spk_anc_work, dwork); + tavil = spk_anc_dwork->tavil; + codec = tavil->codec; + + snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0, 0x10, 0x10); +} + static int tavil_codec_enable_spkr_anc(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -1792,10 +1818,11 @@ static int tavil_codec_enable_spkr_anc(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: ret = tavil_codec_enable_anc(w, kcontrol, event); - snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0, - 0x10, 0x10); + schedule_delayed_work(&tavil->spk_anc_dwork.dwork, + msecs_to_jiffies(spk_anc_en_delay)); break; case SND_SOC_DAPM_POST_PMD: + cancel_delayed_work_sync(&tavil->spk_anc_dwork.dwork); snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0, 0x10, 0x00); ret = tavil_codec_enable_anc(w, kcontrol, event); @@ -4182,7 +4209,7 @@ int tavil_micbias_control(struct snd_soc_codec *codec, post_dapm_on, &tavil->mbhc->wcd_mbhc); break; case MICB_DISABLE: - if (tavil->pullup_ref[micb_index] > 0) + if (tavil->micb_ref[micb_index] > 0) tavil->micb_ref[micb_index]--; if ((tavil->micb_ref[micb_index] == 0) && (tavil->pullup_ref[micb_index] > 0)) @@ -4362,6 +4389,9 @@ static const struct reg_sequence tavil_hph_reset_tbl[] = { { WCD934X_HPH_RDAC_LDO_CTL, 0x33 }, { WCD934X_HPH_RDAC_CHOP_CLK_LP_CTL, 0x00 }, { WCD934X_HPH_REFBUFF_UHQA_CTL, 0xA8 }, +}; + +static const struct reg_sequence tavil_hph_reset_tbl_1_0[] = { { WCD934X_HPH_REFBUFF_LP_CTL, 0x0A }, { WCD934X_HPH_L_DAC_CTL, 0x00 }, { WCD934X_HPH_R_DAC_CTL, 0x00 }, @@ -4383,6 +4413,28 @@ static const struct reg_sequence tavil_hph_reset_tbl[] = { { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 }, }; +static const struct reg_sequence tavil_hph_reset_tbl_1_1[] = { + { WCD934X_HPH_REFBUFF_LP_CTL, 0x0E }, + { WCD934X_HPH_L_DAC_CTL, 0x00 }, + { WCD934X_HPH_R_DAC_CTL, 0x00 }, + { WCD934X_HPH_NEW_ANA_HPH2, 0x00 }, + { WCD934X_HPH_NEW_ANA_HPH3, 0x00 }, + { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40 }, + { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL, 0x81 }, + { WCD934X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 }, + { WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 }, + { WCD934X_HPH_NEW_INT_RDAC_MISC1, 0x81 }, + { WCD934X_HPH_NEW_INT_PA_MISC1, 0x22 }, + { WCD934X_HPH_NEW_INT_PA_MISC2, 0x00 }, + { WCD934X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 }, + { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0xFE }, + { WCD934X_HPH_NEW_INT_HPH_TIMER2, 0x2 }, + { WCD934X_HPH_NEW_INT_HPH_TIMER3, 0x4e}, + { WCD934X_HPH_NEW_INT_HPH_TIMER4, 0x54 }, + { WCD934X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 }, + { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 }, +}; + static const struct tavil_reg_mask_val tavil_pa_disable[] = { { WCD934X_CDC_RX1_RX_PATH_CTL, 0x30, 0x10 }, /* RX1 mute enable */ { WCD934X_CDC_RX2_RX_PATH_CTL, 0x30, 0x10 }, /* RX2 mute enable */ @@ -4408,6 +4460,7 @@ static const struct tavil_reg_mask_val tavil_ocp_en_seq_1[] = { /* LO-HIFI */ static const struct tavil_reg_mask_val tavil_pre_pa_en_lohifi[] = { { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00 }, + { WCD934X_FLYBACK_VNEG_CTRL_4, 0xf0, 0x80 }, { WCD934X_HPH_NEW_INT_PA_MISC2, 0x20, 0x20 }, { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xf0, 0x40 }, { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 }, @@ -4449,6 +4502,7 @@ static void tavil_codec_hph_reg_recover(struct tavil_priv *tavil, struct regmap *map, int pa_status) { int i; + unsigned int reg; blocking_notifier_call_chain(&tavil->mbhc->notifier, WCD_EVENT_OCP_OFF, @@ -4470,6 +4524,12 @@ static void tavil_codec_hph_reg_recover(struct tavil_priv *tavil, /* Restore to HW defaults */ regmap_multi_reg_write(map, tavil_hph_reset_tbl, ARRAY_SIZE(tavil_hph_reset_tbl)); + if (TAVIL_IS_1_1(tavil->wcd9xxx)) + regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1, + ARRAY_SIZE(tavil_hph_reset_tbl_1_1)); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0, + ARRAY_SIZE(tavil_hph_reset_tbl_1_0)); for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq); i++) regmap_write_bits(map, tavil_ocp_en_seq[i].reg, @@ -4483,13 +4543,23 @@ pa_en_restore: __func__, pa_status); /* Disable PA and other registers before restoring */ - for (i = 0; i < ARRAY_SIZE(tavil_pa_disable); i++) + for (i = 0; i < ARRAY_SIZE(tavil_pa_disable); i++) { + if (TAVIL_IS_1_1(tavil->wcd9xxx) && + (tavil_pa_disable[i].reg == WCD934X_HPH_CNP_WG_CTL)) + continue; regmap_write_bits(map, tavil_pa_disable[i].reg, tavil_pa_disable[i].mask, tavil_pa_disable[i].val); + } regmap_multi_reg_write(map, tavil_hph_reset_tbl, ARRAY_SIZE(tavil_hph_reset_tbl)); + if (TAVIL_IS_1_1(tavil->wcd9xxx)) + regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1, + ARRAY_SIZE(tavil_hph_reset_tbl_1_1)); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0, + ARRAY_SIZE(tavil_hph_reset_tbl_1_0)); for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq_1); i++) regmap_write_bits(map, tavil_ocp_en_seq_1[i].reg, @@ -4497,17 +4567,37 @@ pa_en_restore: tavil_ocp_en_seq_1[i].val); if (tavil->hph_mode == CLS_H_LOHIFI) { - for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en_lohifi); i++) + for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en_lohifi); i++) { + reg = tavil_pre_pa_en_lohifi[i].reg; + if ((TAVIL_IS_1_1(tavil->wcd9xxx)) && + ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) || + (reg == WCD934X_HPH_CNP_WG_CTL) || + (reg == WCD934X_HPH_REFBUFF_LP_CTL))) + continue; regmap_write_bits(map, tavil_pre_pa_en_lohifi[i].reg, tavil_pre_pa_en_lohifi[i].mask, tavil_pre_pa_en_lohifi[i].val); + } } else { - for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en); i++) + for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en); i++) { + reg = tavil_pre_pa_en[i].reg; + if ((TAVIL_IS_1_1(tavil->wcd9xxx)) && + ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) || + (reg == WCD934X_HPH_CNP_WG_CTL) || + (reg == WCD934X_HPH_REFBUFF_LP_CTL))) + continue; regmap_write_bits(map, tavil_pre_pa_en[i].reg, tavil_pre_pa_en[i].mask, tavil_pre_pa_en[i].val); + } } + + if (TAVIL_IS_1_1(tavil->wcd9xxx)) { + regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x84); + regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x84); + } + regmap_write_bits(map, WCD934X_ANA_HPH, 0x0C, pa_status & 0x0C); regmap_write_bits(map, WCD934X_ANA_HPH, 0x30, 0x30); /* wait for 100usec after HPH DAC is enabled */ @@ -4516,10 +4606,14 @@ pa_en_restore: /* Sleep for 7msec after PA is enabled */ usleep_range(7000, 7100); - for (i = 0; i < ARRAY_SIZE(tavil_post_pa_en); i++) + for (i = 0; i < ARRAY_SIZE(tavil_post_pa_en); i++) { + if ((TAVIL_IS_1_1(tavil->wcd9xxx)) && + (tavil_post_pa_en[i].reg == WCD934X_HPH_CNP_WG_CTL)) + continue; regmap_write_bits(map, tavil_post_pa_en[i].reg, tavil_post_pa_en[i].mask, tavil_post_pa_en[i].val); + } end: tavil->mbhc->is_hph_recover = true; @@ -5049,14 +5143,18 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol, u32 adc, i, mic_bias_found = 0; int ret = 0; char *mad_input; + bool is_adc2_input = false; tavil_mad_input = ucontrol->value.integer.value[0]; if (strnstr(tavil_conn_mad_text[tavil_mad_input], "NOTUSED", sizeof("NOTUSED"))) { - dev_err(codec->dev, + dev_dbg(codec->dev, "%s: Unsupported tavil_mad_input = %s\n", __func__, tavil_conn_mad_text[tavil_mad_input]); + /* Make sure the MAD register is updated */ + snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP, + 0x88, 0x00); return -EINVAL; } @@ -5085,14 +5183,16 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol, snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc); mad_input_widget = mad_amic_input_widget; + if (adc == 2) + is_adc2_input = true; } else { /* DMIC type input widget*/ mad_input_widget = tavil_conn_mad_text[tavil_mad_input]; } dev_dbg(codec->dev, - "%s: tavil input widget = %s\n", __func__, - mad_input_widget); + "%s: tavil input widget = %s, adc_input = %s\n", __func__, + mad_input_widget, is_adc2_input ? "true" : "false"); for (i = 0; i < card->num_of_dapm_routes; i++) { if (!strcmp(card->of_dapm_routes[i].sink, mad_input_widget)) { @@ -5137,7 +5237,13 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol, 0x0F, tavil_mad_input); snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP, 0x07, mic_bias_found); - + /* for adc2 input, mad should be in micbias mode with BG enabled */ + if (is_adc2_input) + snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP, + 0x88, 0x88); + else + snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP, + 0x88, 0x00); return 0; } @@ -8492,21 +8598,6 @@ done: return rc; } -static void tavil_enable_sido_buck(struct snd_soc_codec *codec) -{ - struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); - - snd_soc_update_bits(codec, WCD934X_ANA_RCO, 0x80, 0x80); - usleep_range(100, 110); - snd_soc_update_bits(codec, WCD934X_ANA_BUCK_CTL, 0x02, 0x02); - usleep_range(100, 110); - snd_soc_update_bits(codec, WCD934X_ANA_BUCK_CTL, 0x01, 0x01); - usleep_range(100, 110); - snd_soc_update_bits(codec, WCD934X_ANA_BUCK_CTL, 0x04, 0x04); - usleep_range(100, 110); - tavil->resmgr->sido_input_src = SIDO_SOURCE_RCO_BG; -} - static void tavil_cdc_vote_svs(struct snd_soc_codec *codec, bool vote) { struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); @@ -8609,7 +8700,8 @@ static int tavil_device_down(struct wcd9xxx *wcd9xxx) for (count = 0; count < NUM_CODEC_DAIS; count++) priv->dai[count].bus_down_in_recovery = true; wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT); - priv->resmgr->sido_input_src = SIDO_SOURCE_INTERNAL; + wcd_resmgr_set_sido_input_src_locked(priv->resmgr, + SIDO_SOURCE_INTERNAL); return 0; } @@ -8781,7 +8873,6 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec) tavil->comp_enabled[i] = 0; tavil_codec_init_reg(tavil); - tavil_enable_sido_buck(codec); pdata = dev_get_platdata(codec->dev->parent); ret = tavil_handle_pdata(tavil, pdata); @@ -8837,6 +8928,10 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec) tavil_tx_mute_update_callback); } + tavil->spk_anc_dwork.tavil = tavil; + INIT_DELAYED_WORK(&tavil->spk_anc_dwork.dwork, + tavil_spk_anc_update_callback); + tavil_mclk2_reg_defaults(tavil); /* DSD initialization */ @@ -9352,7 +9447,6 @@ err_mem: static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil) { int val, rc; - struct snd_soc_codec *codec; __tavil_cdc_mclk_enable(tavil, true); @@ -9372,14 +9466,6 @@ static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil) WARN(1, "%s: Efuse sense is not complete val=%x, ret=%d\n", __func__, val, rc); - codec = tavil->codec; - if (!codec) { - pr_debug("%s: codec is not yet registered\n", __func__); - goto done; - } - tavil_enable_sido_buck(codec); - -done: __tavil_cdc_mclk_enable(tavil, false); return rc; diff --git a/sound/soc/codecs/wcd9xxx-resmgr-v2.c b/sound/soc/codecs/wcd9xxx-resmgr-v2.c index 39ca965e791e..84754b8d09b0 100644 --- a/sound/soc/codecs/wcd9xxx-resmgr-v2.c +++ b/sound/soc/codecs/wcd9xxx-resmgr-v2.c @@ -25,6 +25,8 @@ #define WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL 0x0d41 #define WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL 0x0d42 +static void wcd_resmgr_set_sido_input_src(struct wcd9xxx_resmgr_v2 *resmgr, + int sido_src); static const char *wcd_resmgr_clk_type_to_str(enum wcd_clock_type clk_type) { if (clk_type == WCD_CLK_OFF) @@ -262,6 +264,8 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) 0x01, 0x01); wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_CODEC_RPM_CLK_GATE, 0x03, 0x00); + wcd_resmgr_set_sido_input_src(resmgr, + SIDO_SOURCE_RCO_BG); } else { wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, @@ -315,6 +319,10 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) 0x80, 0x00); } + if ((resmgr->codec_type == WCD934X) && + (resmgr->clk_type == WCD_CLK_OFF)) + wcd_resmgr_set_sido_input_src(resmgr, SIDO_SOURCE_INTERNAL); + pr_debug("%s: mclk_users: %d, clk_type: %s\n", __func__, resmgr->clk_mclk_users, wcd_resmgr_clk_type_to_str(resmgr->clk_type)); @@ -444,6 +452,9 @@ static int wcd_resmgr_disable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO, 0x80, 0x00); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD934X_CLK_SYS_MCLK_PRG, + 0x01, 0x00); resmgr->clk_type = WCD_CLK_OFF; } else if ((resmgr->clk_rco_users == 0) && (resmgr->clk_mclk_users)) { @@ -455,6 +466,11 @@ static int wcd_resmgr_disable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr) WCD9335_ANA_RCO, 0x80, 0x00); } + + if ((resmgr->codec_type == WCD934X) && + (resmgr->clk_type == WCD_CLK_OFF)) + wcd_resmgr_set_sido_input_src(resmgr, SIDO_SOURCE_INTERNAL); + pr_debug("%s: rco clk users: %d, clk_type: %s\n", __func__, resmgr->clk_rco_users, wcd_resmgr_clk_type_to_str(resmgr->clk_type)); @@ -493,6 +509,64 @@ int wcd_resmgr_enable_clk_block(struct wcd9xxx_resmgr_v2 *resmgr, return ret; } +static void wcd_resmgr_set_sido_input_src(struct wcd9xxx_resmgr_v2 *resmgr, + int sido_src) +{ + if (!resmgr) + return; + + if (sido_src == resmgr->sido_input_src) + return; + + if (sido_src == SIDO_SOURCE_INTERNAL) { + wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, + 0x04, 0x00); + usleep_range(100, 110); + wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, + 0x03, 0x00); + usleep_range(100, 110); + wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_RCO, + 0x80, 0x00); + usleep_range(100, 110); + resmgr->sido_input_src = SIDO_SOURCE_INTERNAL; + pr_debug("%s: sido input src to internal\n", __func__); + } else if (sido_src == SIDO_SOURCE_RCO_BG) { + wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_RCO, + 0x80, 0x80); + usleep_range(100, 110); + wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, + 0x02, 0x02); + usleep_range(100, 110); + wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, + 0x01, 0x01); + usleep_range(100, 110); + wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL, + 0x04, 0x04); + usleep_range(100, 110); + resmgr->sido_input_src = SIDO_SOURCE_RCO_BG; + pr_debug("%s: sido input src to external\n", __func__); + } +} + +/* + * wcd_resmgr_set_sido_input_src_locked: + * Set SIDO input in BG_CLK locked context + * + * @resmgr: handle to struct wcd9xxx_resmgr_v2 + * @sido_src: Select the SIDO input source + */ +void wcd_resmgr_set_sido_input_src_locked(struct wcd9xxx_resmgr_v2 *resmgr, + int sido_src) +{ + if (!resmgr) + return; + + WCD9XXX_V2_BG_CLK_LOCK(resmgr); + wcd_resmgr_set_sido_input_src(resmgr, sido_src); + WCD9XXX_V2_BG_CLK_UNLOCK(resmgr); +} +EXPORT_SYMBOL(wcd_resmgr_set_sido_input_src_locked); + /* * wcd_resmgr_disable_clk_block: disable MCLK or RCO * @resmgr: handle to struct wcd9xxx_resmgr_v2 diff --git a/sound/soc/codecs/wcd9xxx-resmgr-v2.h b/sound/soc/codecs/wcd9xxx-resmgr-v2.h index c1955d31889f..f605a249a620 100644 --- a/sound/soc/codecs/wcd9xxx-resmgr-v2.h +++ b/sound/soc/codecs/wcd9xxx-resmgr-v2.h @@ -85,4 +85,6 @@ int wcd_resmgr_disable_clk_block(struct wcd9xxx_resmgr_v2 *resmgr, enum wcd_clock_type type); int wcd_resmgr_get_clk_type(struct wcd9xxx_resmgr_v2 *resmgr); void wcd_resmgr_post_ssr_v2(struct wcd9xxx_resmgr_v2 *resmgr); +void wcd_resmgr_set_sido_input_src_locked(struct wcd9xxx_resmgr_v2 *resmgr, + int sido_src); #endif diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig index 64a1fa76604d..9cf69eca0028 100644 --- a/sound/soc/msm/Kconfig +++ b/sound/soc/msm/Kconfig @@ -98,6 +98,70 @@ config SND_SOC_CPE The configuration includes the cpe lsm driver to enable listen on codec. +config SND_SOC_INT_CODEC + tristate "SoC Machine driver for MSMFALCON_INT" + depends on ARCH_QCOM + select SND_SOC_QDSP6V2 + select SND_SOC_MSM_STUB + select SND_SOC_MSM_HOSTLESS_PCM + select SND_DYNAMIC_MINORS + select MSM_QDSP6_APRV2_GLINK + select MSM_QDSP6_SSR + select MSM_QDSP6_PDR + select MSM_QDSP6_NOTIFIER + select MSM_QDSP6V2_CODECS + select SND_SOC_MSM_SWR + select SND_SOC_MSM8X16_WCD + select QTI_PP + select DTS_SRS_TM + select DOLBY_DAP + select DOLBY_DS2 + select SND_HWDEP + select MSM_ULTRASOUND + select DTS_EAGLE + select SND_SOC_MSMFALCON_COMMON + select SND_SOC_COMPRESS + help + To add support for SoC audio on MSM_INT. + This will enable sound soc drivers which + interfaces with DSP, also it will enable + the machine driver and the corresponding + DAI-links + +config SND_SOC_EXT_CODEC + tristate "SoC Machine driver for MSMFALCON_EXT" + depends on ARCH_QCOM + select SND_SOC_QDSP6V2 + select SND_SOC_MSM_STUB + select SND_SOC_MSM_HOSTLESS_PCM + select SND_DYNAMIC_MINORS + select MSM_QDSP6_APRV2_GLINK + select MSM_QDSP6_SSR + select MSM_QDSP6_PDR + select MSM_QDSP6_NOTIFIER + select MSM_QDSP6V2_CODECS + select SND_SOC_WCD9335 + select SND_SOC_WCD934X + select SND_SOC_WSA881X + select MFD_CORE + select QTI_PP + select DTS_SRS_TM + select DOLBY_DAP + select DOLBY_DS2 + select SND_SOC_CPE + select SND_SOC_WCD_CPE + select SND_HWDEP + select MSM_ULTRASOUND + select DTS_EAGLE + select SND_SOC_MSMFALCON_COMMON + select SND_SOC_COMPRESS + help + To add support for SoC audio on MSM_EXT. + This will enable sound soc drivers which + interfaces with DSP, also it will enable + the machine driver and the corresponding + DAI-links + config SND_SOC_MSM8996 tristate "SoC Machine driver for MSM8996 boards" depends on ARCH_MSM8996 @@ -157,4 +221,16 @@ config SND_SOC_MSMCOBALT the machine driver and the corresponding DAI-links +config SND_SOC_FALCON + tristate "SoC Machine driver for MSMFALCON boards" + depends on ARCH_MSMFALCON + select SND_SOC_INT_CODEC + select SND_SOC_EXT_CODEC + help + To add support for SoC audio on MSMFALCON. + This will enable sound soc drivers which + interfaces with DSP, also it will enable + the machine driver and the corresponding + DAI-links + endmenu diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile index 3ad34be41578..799c9ee63d43 100644 --- a/sound/soc/msm/Makefile +++ b/sound/soc/msm/Makefile @@ -19,3 +19,18 @@ obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-msm8996.o # for MSMCOBALT sound card driver snd-soc-msmcobalt-objs := msmcobalt.o obj-$(CONFIG_SND_SOC_MSMCOBALT) += snd-soc-msmcobalt.o + +# for MSMFALCON sound card driver +snd-soc-msmfalcon-common-objs := msm-audio-pinctrl.o msmfalcon-common.o +obj-$(CONFIG_SND_SOC_MSMFALCON_COMMON) += snd-soc-msmfalcon-common.o + +# for MSMFALCON sound card driver +snd-soc-int-codec-objs := msmfalcon-internal.o +obj-$(CONFIG_SND_SOC_INT_CODEC) += snd-soc-msmfalcon-common.o +obj-$(CONFIG_SND_SOC_INT_CODEC) += snd-soc-int-codec.o + +# for MSMFALCON sound card driver +snd-soc-ext-codec-objs := msmfalcon-external.o msmfalcon-ext-dai-links.o +obj-$(CONFIG_SND_SOC_EXT_CODEC) += snd-soc-msmfalcon-common.o +obj-$(CONFIG_SND_SOC_EXT_CODEC) += snd-soc-ext-codec.o + diff --git a/sound/soc/msm/msm-audio-pinctrl.h b/sound/soc/msm/msm-audio-pinctrl.h index 0b5395520b1b..73eeaff39bfd 100644 --- a/sound/soc/msm/msm-audio-pinctrl.h +++ b/sound/soc/msm/msm-audio-pinctrl.h @@ -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 @@ -14,8 +14,7 @@ #define __MSM_AUDIO_PINCTRL_H enum pinctrl_client { - CLIENT_WCD_INT, - CLIENT_WCD_EXT, + CLIENT_WCD, CLIENT_WSA_BONGO_1, CLIENT_WSA_BONGO_2, MAX_PINCTRL_CLIENT, diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index ee9dcacdd5c9..aa036d352f40 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -870,6 +870,38 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .name = "QUAT_MI2S_RX_HOSTLESS", .probe = fe_dai_probe, }, + { + .playback = { + .stream_name = "INT0 MI2S_RX Hostless Playback", + .aif_name = "INT0_MI2S_DL_HL", + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_fe_dai_ops, + .name = "INT0_MI2S_RX_HOSTLESS", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "INT4 MI2S_RX Hostless Playback", + .aif_name = "INT4_MI2S_DL_HL", + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_fe_dai_ops, + .name = "INT4_MI2S_RX_HOSTLESS", + .probe = fe_dai_probe, + }, /* TDM Hostless */ { .capture = { diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c index c295c26a6fd7..9c392f3d4ddc 100644 --- a/sound/soc/msm/msmcobalt.c +++ b/sound/soc/msm/msmcobalt.c @@ -3258,20 +3258,23 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_ignore_suspend(dapm, "EAR"); snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1"); snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2"); - snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3"); - snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4"); snd_soc_dapm_ignore_suspend(dapm, "ANC EAR"); snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT"); snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT"); snd_soc_dapm_ignore_suspend(dapm, "HPHL"); snd_soc_dapm_ignore_suspend(dapm, "HPHR"); - snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL"); - snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR"); - snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1"); - snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2"); snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI"); snd_soc_dapm_ignore_suspend(dapm, "VIINPUT"); + if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) { + snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3"); + snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR"); + snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1"); + snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2"); + } + snd_soc_dapm_sync(dapm); snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch), diff --git a/sound/soc/msm/msmfalcon-common.c b/sound/soc/msm/msmfalcon-common.c new file mode 100644 index 000000000000..6c96a0778b52 --- /dev/null +++ b/sound/soc/msm/msmfalcon-common.c @@ -0,0 +1,1768 @@ +/* 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/input.h> +#include <linux/of_gpio.h> +#include <linux/mfd/msm-cdc-pinctrl.h> +#include <sound/pcm_params.h> +#include <sound/q6afe-v2.h> +#include "qdsp6v2/msm-pcm-routing-v2.h" +#include "msm-audio-pinctrl.h" +#include "msmfalcon-common.h" +#include "msmfalcon-internal.h" +#include "msmfalcon-external.h" +#include "../codecs/msm8x16/msm8x16-wcd.h" +#include "../codecs/wsa881x.h" + +#define DRV_NAME "msmfalcon-asoc-snd" + +#define DEV_NAME_STR_LEN 32 +#define DEFAULT_MCLK_RATE 9600000 + +enum { + PRIM_MI2S = 0, + SEC_MI2S, + TERT_MI2S, + QUAT_MI2S, + MI2S_MAX, +}; + +enum { + PRIM_AUX_PCM = 0, + SEC_AUX_PCM, + TERT_AUX_PCM, + QUAT_AUX_PCM, + AUX_PCM_MAX, +}; + +enum { + PCM_I2S_SEL_PRIM = 0, + PCM_I2S_SEL_SEC, + PCM_I2S_SEL_TERT, + PCM_I2S_SEL_QUAT, + PCM_I2S_SEL_MAX, +}; + +struct mi2s_aux_pcm_common_conf { + struct mutex lock; + void *pcm_i2s_sel_vt_addr; +}; + +struct mi2s_conf { + struct mutex lock; + u32 ref_cnt; + u32 msm_is_mi2s_master; +}; + +struct auxpcm_conf { + struct mutex lock; + u32 ref_cnt; +}; + +struct dev_config { + u32 sample_rate; + u32 bit_format; + u32 channels; +}; + +struct msm_wsa881x_dev_info { + struct device_node *of_node; + u32 index; +}; +static struct snd_soc_aux_dev *msm_aux_dev; +static struct snd_soc_codec_conf *msm_codec_conf; + +static bool msm_swap_gnd_mic(struct snd_soc_codec *codec); + +static struct wcd_mbhc_config mbhc_cfg = { + .read_fw_bin = false, + .calibration = NULL, + .detect_extn_cable = true, + .mono_stero_detection = false, + .swap_gnd_mic = NULL, + .hs_ext_micbias = false, + .key_code[0] = KEY_MEDIA, + .key_code[1] = KEY_VOICECOMMAND, + .key_code[2] = KEY_VOLUMEUP, + .key_code[3] = KEY_VOLUMEDOWN, + .key_code[4] = 0, + .key_code[5] = 0, + .key_code[6] = 0, + .key_code[7] = 0, + .linein_th = 5000, + .moisture_en = false, + .mbhc_micbias = 0, + .anc_micbias = 0, + .enable_anc_mic_detect = false, +}; + +static struct dev_config proxy_rx_cfg = { + .sample_rate = SAMPLING_RATE_48KHZ, + .bit_format = SNDRV_PCM_FORMAT_S16_LE, + .channels = 2, +}; + +static struct dev_config btsco_cfg = { + .sample_rate = SAMPLING_RATE_8KHZ, + .bit_format = SNDRV_PCM_FORMAT_S16_LE, + .channels = 1, +}; + +/* Default configuration of MI2S channels */ +static struct dev_config mi2s_rx_cfg[] = { + [PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, + [SEC_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, + [TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, + [QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, +}; + +static struct dev_config mi2s_tx_cfg[] = { + [PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SEC_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, +}; + +static struct dev_config aux_pcm_rx_cfg[] = { + [PRIM_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SEC_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, +}; + +static struct dev_config aux_pcm_tx_cfg[] = { + [PRIM_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SEC_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, +}; + +static char const *ch_text[] = {"Two", "Three", "Four", "Five", + "Six", "Seven", "Eight"}; +static const char *const auxpcm_rate_text[] = {"KHZ_8", "KHZ_16"}; +static char const *mi2s_rate_text[] = {"KHZ_8", "KHZ_16", + "KHZ_32", "KHZ_44P1", "KHZ_48", + "KHZ_96", "KHZ_192"}; +static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four", + "Five", "Six", "Seven", + "Eight"}; + +static SOC_ENUM_SINGLE_EXT_DECL(btsco_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_rx_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_rx_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_rx_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_rx_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_tx_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_tx_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_tx_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_tx_sample_rate, auxpcm_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_chs, mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_chs, mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_chs, mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_chs, mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_chs, mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_chs, mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_chs, mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_chs, mi2s_ch_text); + +static struct afe_clk_set mi2s_clk[MI2S_MAX] = { + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + } +}; + +static struct mi2s_aux_pcm_common_conf mi2s_auxpcm_conf[PCM_I2S_SEL_MAX]; +static struct mi2s_conf mi2s_intf_conf[MI2S_MAX]; +static struct auxpcm_conf auxpcm_intf_conf[AUX_PCM_MAX]; + +static int proxy_rx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: proxy_rx channels = %d\n", + __func__, proxy_rx_cfg.channels); + ucontrol->value.integer.value[0] = proxy_rx_cfg.channels - 2; + + return 0; +} + +static int proxy_rx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + proxy_rx_cfg.channels = ucontrol->value.integer.value[0] + 2; + pr_debug("%s: proxy_rx channels = %d\n", + __func__, proxy_rx_cfg.channels); + + return 1; +} + +static int aux_pcm_get_sample_rate(int value) +{ + int sample_rate; + + switch (value) { + case 1: + sample_rate = SAMPLING_RATE_16KHZ; + break; + case 0: + default: + sample_rate = SAMPLING_RATE_8KHZ; + break; + } + return sample_rate; +} + +static int aux_pcm_get_sample_rate_val(int sample_rate) +{ + int sample_rate_val; + + switch (sample_rate) { + case SAMPLING_RATE_16KHZ: + sample_rate_val = 1; + break; + case SAMPLING_RATE_8KHZ: + default: + sample_rate_val = 0; + break; + } + return sample_rate_val; +} + +static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol) +{ + int idx; + + if (strnstr(kcontrol->id.name, "PRIM_AUX_PCM", + sizeof("PRIM_AUX_PCM"))) + idx = PRIM_AUX_PCM; + else if (strnstr(kcontrol->id.name, "SEC_AUX_PCM", + sizeof("SEC_AUX_PCM"))) + idx = SEC_AUX_PCM; + else if (strnstr(kcontrol->id.name, "TERT_AUX_PCM", + sizeof("TERT_AUX_PCM"))) + idx = TERT_AUX_PCM; + else if (strnstr(kcontrol->id.name, "QUAT_AUX_PCM", + sizeof("QUAT_AUX_PCM"))) + idx = QUAT_AUX_PCM; + else { + pr_err("%s: unsupported port: %s", + __func__, kcontrol->id.name); + idx = -EINVAL; + } + + return idx; +} + +static int btsco_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + btsco_cfg.sample_rate = + aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: btsco_sample_rate = %d, item = %d\n", __func__, + btsco_cfg.sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int btsco_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.enumerated.item[0] = + aux_pcm_get_sample_rate_val(btsco_cfg.sample_rate); + + pr_debug("%s: btsco_sample_rate = %d, item = %d\n", __func__, + btsco_cfg.sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int aux_pcm_rx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = aux_pcm_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + aux_pcm_rx_cfg[idx].sample_rate = + aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__, + idx, aux_pcm_rx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int aux_pcm_rx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = aux_pcm_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + aux_pcm_get_sample_rate_val(aux_pcm_rx_cfg[idx].sample_rate); + + pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__, + idx, aux_pcm_rx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int aux_pcm_tx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = aux_pcm_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + aux_pcm_tx_cfg[idx].sample_rate = + aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__, + idx, aux_pcm_tx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int aux_pcm_tx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = aux_pcm_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + aux_pcm_get_sample_rate_val(aux_pcm_tx_cfg[idx].sample_rate); + + pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__, + idx, aux_pcm_tx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int mi2s_get_port_idx(struct snd_kcontrol *kcontrol) +{ + int idx; + + if (strnstr(kcontrol->id.name, "PRIM_MI2S_RX", + sizeof("PRIM_MI2S_RX"))) + idx = PRIM_MI2S; + else if (strnstr(kcontrol->id.name, "SEC_MI2S_RX", + sizeof("SEC_MI2S_RX"))) + idx = SEC_MI2S; + else if (strnstr(kcontrol->id.name, "TERT_MI2S_RX", + sizeof("TERT_MI2S_RX"))) + idx = TERT_MI2S; + else if (strnstr(kcontrol->id.name, "QUAT_MI2S_RX", + sizeof("QUAT_MI2S_RX"))) + idx = QUAT_MI2S; + else if (strnstr(kcontrol->id.name, "PRIM_MI2S_TX", + sizeof("PRIM_MI2S_TX"))) + idx = PRIM_MI2S; + else if (strnstr(kcontrol->id.name, "SEC_MI2S_TX", + sizeof("SEC_MI2S_TX"))) + idx = SEC_MI2S; + else if (strnstr(kcontrol->id.name, "TERT_MI2S_TX", + sizeof("TERT_MI2S_TX"))) + idx = TERT_MI2S; + else if (strnstr(kcontrol->id.name, "QUAT_MI2S_TX", + sizeof("QUAT_MI2S_TX"))) + idx = QUAT_MI2S; + else { + pr_err("%s: unsupported channel: %s", + __func__, kcontrol->id.name); + idx = -EINVAL; + } + + return idx; +} + +static int mi2s_get_sample_rate_val(int sample_rate) +{ + int sample_rate_val; + + switch (sample_rate) { + case SAMPLING_RATE_8KHZ: + sample_rate_val = 0; + break; + case SAMPLING_RATE_16KHZ: + sample_rate_val = 1; + break; + case SAMPLING_RATE_32KHZ: + sample_rate_val = 2; + break; + case SAMPLING_RATE_44P1KHZ: + sample_rate_val = 3; + break; + case SAMPLING_RATE_48KHZ: + sample_rate_val = 4; + break; + case SAMPLING_RATE_96KHZ: + sample_rate_val = 5; + break; + case SAMPLING_RATE_192KHZ: + sample_rate_val = 6; + break; + default: + sample_rate_val = 4; + break; + } + return sample_rate_val; +} + +static int mi2s_get_sample_rate(int value) +{ + int sample_rate; + + switch (value) { + case 0: + sample_rate = SAMPLING_RATE_8KHZ; + break; + case 1: + sample_rate = SAMPLING_RATE_16KHZ; + break; + case 2: + sample_rate = SAMPLING_RATE_32KHZ; + break; + case 3: + sample_rate = SAMPLING_RATE_44P1KHZ; + break; + case 4: + sample_rate = SAMPLING_RATE_48KHZ; + break; + case 5: + sample_rate = SAMPLING_RATE_96KHZ; + break; + case 6: + sample_rate = SAMPLING_RATE_192KHZ; + break; + default: + sample_rate = SAMPLING_RATE_48KHZ; + break; + } + return sample_rate; +} + +static int mi2s_rx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + mi2s_rx_cfg[idx].sample_rate = + mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__, + idx, mi2s_rx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int mi2s_rx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + mi2s_get_sample_rate_val(mi2s_rx_cfg[idx].sample_rate); + + pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__, + idx, mi2s_rx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int mi2s_tx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + mi2s_tx_cfg[idx].sample_rate = + mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__, + idx, mi2s_tx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int mi2s_tx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + mi2s_get_sample_rate_val(mi2s_tx_cfg[idx].sample_rate); + + pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__, + idx, mi2s_tx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int msm_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + pr_debug("%s: msm_mi2s_[%d]_rx_ch = %d\n", __func__, + idx, mi2s_rx_cfg[idx].channels); + ucontrol->value.enumerated.item[0] = mi2s_rx_cfg[idx].channels - 1; + + return 0; +} + +static int msm_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + mi2s_rx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1; + pr_debug("%s: msm_mi2s_[%d]_rx_ch = %d\n", __func__, + idx, mi2s_rx_cfg[idx].channels); + + return 1; +} + +static int msm_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + pr_debug("%s: msm_mi2s_[%d]_tx_ch = %d\n", __func__, + idx, mi2s_tx_cfg[idx].channels); + ucontrol->value.enumerated.item[0] = mi2s_tx_cfg[idx].channels - 1; + + return 0; +} + +static int msm_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + mi2s_tx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1; + pr_debug("%s: msm_mi2s_[%d]_tx_ch = %d\n", __func__, + idx, mi2s_tx_cfg[idx].channels); + + return 1; +} + +const struct snd_kcontrol_new msm_common_snd_controls[] = { + SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs, + proxy_rx_ch_get, proxy_rx_ch_put), + SOC_ENUM_EXT("BTSCO SampleRate", btsco_sample_rate, + btsco_sample_rate_get, + btsco_sample_rate_put), + SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate, + aux_pcm_rx_sample_rate_get, + aux_pcm_rx_sample_rate_put), + SOC_ENUM_EXT("SEC_AUX_PCM_RX SampleRate", sec_aux_pcm_rx_sample_rate, + aux_pcm_rx_sample_rate_get, + aux_pcm_rx_sample_rate_put), + SOC_ENUM_EXT("TERT_AUX_PCM_RX SampleRate", tert_aux_pcm_rx_sample_rate, + aux_pcm_rx_sample_rate_get, + aux_pcm_rx_sample_rate_put), + SOC_ENUM_EXT("QUAT_AUX_PCM_RX SampleRate", quat_aux_pcm_rx_sample_rate, + aux_pcm_rx_sample_rate_get, + aux_pcm_rx_sample_rate_put), + SOC_ENUM_EXT("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate, + aux_pcm_tx_sample_rate_get, + aux_pcm_tx_sample_rate_put), + SOC_ENUM_EXT("SEC_AUX_PCM_TX SampleRate", sec_aux_pcm_tx_sample_rate, + aux_pcm_tx_sample_rate_get, + aux_pcm_tx_sample_rate_put), + SOC_ENUM_EXT("TERT_AUX_PCM_TX SampleRate", tert_aux_pcm_tx_sample_rate, + aux_pcm_tx_sample_rate_get, + aux_pcm_tx_sample_rate_put), + SOC_ENUM_EXT("QUAT_AUX_PCM_TX SampleRate", quat_aux_pcm_tx_sample_rate, + aux_pcm_tx_sample_rate_get, + aux_pcm_tx_sample_rate_put), + SOC_ENUM_EXT("PRIM_MI2S_RX SampleRate", prim_mi2s_rx_sample_rate, + mi2s_rx_sample_rate_get, + mi2s_rx_sample_rate_put), + SOC_ENUM_EXT("SEC_MI2S_RX SampleRate", sec_mi2s_rx_sample_rate, + mi2s_rx_sample_rate_get, + mi2s_rx_sample_rate_put), + SOC_ENUM_EXT("TERT_MI2S_RX SampleRate", tert_mi2s_rx_sample_rate, + mi2s_rx_sample_rate_get, + mi2s_rx_sample_rate_put), + SOC_ENUM_EXT("QUAT_MI2S_RX SampleRate", quat_mi2s_rx_sample_rate, + mi2s_rx_sample_rate_get, + mi2s_rx_sample_rate_put), + SOC_ENUM_EXT("PRIM_MI2S_TX SampleRate", prim_mi2s_tx_sample_rate, + mi2s_tx_sample_rate_get, + mi2s_tx_sample_rate_put), + SOC_ENUM_EXT("SEC_MI2S_TX SampleRate", sec_mi2s_tx_sample_rate, + mi2s_tx_sample_rate_get, + mi2s_tx_sample_rate_put), + SOC_ENUM_EXT("TERT_MI2S_TX SampleRate", tert_mi2s_tx_sample_rate, + mi2s_tx_sample_rate_get, + mi2s_tx_sample_rate_put), + SOC_ENUM_EXT("QUAT_MI2S_TX SampleRate", quat_mi2s_tx_sample_rate, + mi2s_tx_sample_rate_get, + mi2s_tx_sample_rate_put), + SOC_ENUM_EXT("PRIM_MI2S_RX Channels", prim_mi2s_rx_chs, + msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put), + SOC_ENUM_EXT("PRIM_MI2S_TX Channels", prim_mi2s_tx_chs, + msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put), + SOC_ENUM_EXT("SEC_MI2S_RX Channels", sec_mi2s_rx_chs, + msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put), + SOC_ENUM_EXT("SEC_MI2S_TX Channels", sec_mi2s_tx_chs, + msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put), + SOC_ENUM_EXT("TERT_MI2S_RX Channels", tert_mi2s_rx_chs, + msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put), + SOC_ENUM_EXT("TERT_MI2S_TX Channels", tert_mi2s_tx_chs, + msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put), + SOC_ENUM_EXT("QUAT_MI2S_RX Channels", quat_mi2s_rx_chs, + msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put), + SOC_ENUM_EXT("QUAT_MI2S_TX Channels", quat_mi2s_tx_chs, + msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put), +}; + +/** + * msm_common_be_hw_params_fixup - updates settings of ALSA BE hw params. + * + * @rtd: runtime dailink instance + * @params: HW params of associated backend dailink. + * + * Returns 0. + */ +int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_dai_link *dai_link = rtd->dai_link; + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + int rc = 0; + + pr_debug("%s: format = %d, rate = %d\n", + __func__, params_format(params), params_rate(params)); + + switch (dai_link->be_id) { + case MSM_BACKEND_DAI_INT_BT_SCO_RX: + case MSM_BACKEND_DAI_INT_BT_SCO_TX: + channels->min = channels->max = btsco_cfg.channels; + rate->min = rate->max = 1; + break; + + case MSM_BACKEND_DAI_AFE_PCM_RX: + channels->min = channels->max = proxy_rx_cfg.channels; + rate->min = rate->max = SAMPLING_RATE_48KHZ; + break; + + case MSM_BACKEND_DAI_AUXPCM_RX: + rate->min = rate->max = + aux_pcm_rx_cfg[PRIM_AUX_PCM].sample_rate; + channels->min = channels->max = + aux_pcm_rx_cfg[PRIM_AUX_PCM].channels; + break; + + case MSM_BACKEND_DAI_AUXPCM_TX: + rate->min = rate->max = + aux_pcm_tx_cfg[PRIM_AUX_PCM].sample_rate; + channels->min = channels->max = + aux_pcm_tx_cfg[PRIM_AUX_PCM].channels; + break; + + case MSM_BACKEND_DAI_SEC_AUXPCM_RX: + rate->min = rate->max = + aux_pcm_rx_cfg[SEC_AUX_PCM].sample_rate; + channels->min = channels->max = + aux_pcm_rx_cfg[SEC_AUX_PCM].channels; + break; + + case MSM_BACKEND_DAI_SEC_AUXPCM_TX: + rate->min = rate->max = + aux_pcm_tx_cfg[SEC_AUX_PCM].sample_rate; + channels->min = channels->max = + aux_pcm_tx_cfg[SEC_AUX_PCM].channels; + break; + + case MSM_BACKEND_DAI_TERT_AUXPCM_RX: + rate->min = rate->max = + aux_pcm_rx_cfg[TERT_AUX_PCM].sample_rate; + channels->min = channels->max = + aux_pcm_rx_cfg[TERT_AUX_PCM].channels; + break; + + case MSM_BACKEND_DAI_TERT_AUXPCM_TX: + rate->min = rate->max = + aux_pcm_tx_cfg[TERT_AUX_PCM].sample_rate; + channels->min = channels->max = + aux_pcm_tx_cfg[TERT_AUX_PCM].channels; + break; + + case MSM_BACKEND_DAI_QUAT_AUXPCM_RX: + rate->min = rate->max = + aux_pcm_rx_cfg[QUAT_AUX_PCM].sample_rate; + channels->min = channels->max = + aux_pcm_rx_cfg[QUAT_AUX_PCM].channels; + break; + + case MSM_BACKEND_DAI_QUAT_AUXPCM_TX: + rate->min = rate->max = + aux_pcm_tx_cfg[QUAT_AUX_PCM].sample_rate; + channels->min = channels->max = + aux_pcm_tx_cfg[QUAT_AUX_PCM].channels; + break; + + case MSM_BACKEND_DAI_PRI_MI2S_RX: + rate->min = rate->max = mi2s_rx_cfg[PRIM_MI2S].sample_rate; + channels->min = channels->max = + mi2s_rx_cfg[PRIM_MI2S].channels; + break; + + case MSM_BACKEND_DAI_PRI_MI2S_TX: + rate->min = rate->max = mi2s_tx_cfg[PRIM_MI2S].sample_rate; + channels->min = channels->max = + mi2s_tx_cfg[PRIM_MI2S].channels; + break; + + case MSM_BACKEND_DAI_SECONDARY_MI2S_RX: + rate->min = rate->max = mi2s_rx_cfg[SEC_MI2S].sample_rate; + channels->min = channels->max = + mi2s_rx_cfg[SEC_MI2S].channels; + break; + + case MSM_BACKEND_DAI_SECONDARY_MI2S_TX: + rate->min = rate->max = mi2s_tx_cfg[SEC_MI2S].sample_rate; + channels->min = channels->max = + mi2s_tx_cfg[SEC_MI2S].channels; + break; + + case MSM_BACKEND_DAI_TERTIARY_MI2S_RX: + rate->min = rate->max = mi2s_rx_cfg[TERT_MI2S].sample_rate; + channels->min = channels->max = + mi2s_rx_cfg[TERT_MI2S].channels; + break; + + case MSM_BACKEND_DAI_TERTIARY_MI2S_TX: + rate->min = rate->max = mi2s_tx_cfg[TERT_MI2S].sample_rate; + channels->min = channels->max = + mi2s_tx_cfg[TERT_MI2S].channels; + break; + + case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX: + rate->min = rate->max = mi2s_rx_cfg[QUAT_MI2S].sample_rate; + channels->min = channels->max = + mi2s_rx_cfg[QUAT_MI2S].channels; + break; + + case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX: + rate->min = rate->max = mi2s_tx_cfg[QUAT_MI2S].sample_rate; + channels->min = channels->max = + mi2s_tx_cfg[QUAT_MI2S].channels; + break; + + default: + rate->min = rate->max = SAMPLING_RATE_48KHZ; + break; + } + return rc; +} +EXPORT_SYMBOL(msm_common_be_hw_params_fixup); + +/** + * msm_aux_pcm_snd_startup - startup ops of auxpcm. + * + * @substream: PCM stream pointer of associated backend dailink + * + * Returns 0 on success or -EINVAL on error. + */ +int msm_aux_pcm_snd_startup(struct snd_pcm_substream *substream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int index = cpu_dai->id - 1; + return ret = 0; + + dev_dbg(rtd->card->dev, + "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", + __func__, substream->name, substream->stream, + cpu_dai->name, cpu_dai->id); + + if (index < PRIM_AUX_PCM || index > QUAT_AUX_PCM) { + ret = -EINVAL; + dev_err(rtd->card->dev, + "%s: CPU DAI id (%d) out of range\n", + __func__, cpu_dai->id); + goto done; + } + + mutex_lock(&auxpcm_intf_conf[index].lock); + if (++auxpcm_intf_conf[index].ref_cnt == 1) { + if (mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr != NULL) { + mutex_lock(&mi2s_auxpcm_conf[index].lock); + iowrite32(1, + mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr); + mutex_unlock(&mi2s_auxpcm_conf[index].lock); + } else { + dev_err(rtd->card->dev, + "%s lpaif_tert_muxsel_virt_addr is NULL\n", + __func__); + ret = -EINVAL; + } + } + if (IS_ERR_VALUE(ret)) + auxpcm_intf_conf[index].ref_cnt--; + + mutex_unlock(&auxpcm_intf_conf[index].lock); + +done: + return ret; +} +EXPORT_SYMBOL(msm_aux_pcm_snd_startup); + +/** + * msm_aux_pcm_snd_shutdown - shutdown ops of auxpcm. + * + * @substream: PCM stream pointer of associated backend dailink + */ +void msm_aux_pcm_snd_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int index = rtd->cpu_dai->id - 1; + + dev_dbg(rtd->card->dev, + "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", + __func__, + substream->name, substream->stream, + rtd->cpu_dai->name, rtd->cpu_dai->id); + + if (index < PRIM_AUX_PCM || index > QUAT_AUX_PCM) { + dev_err(rtd->card->dev, + "%s: CPU DAI id (%d) out of range\n", + __func__, rtd->cpu_dai->id); + return; + } + + mutex_lock(&auxpcm_intf_conf[index].lock); + if (--auxpcm_intf_conf[index].ref_cnt == 0) { + if (mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr != NULL) { + mutex_lock(&mi2s_auxpcm_conf[index].lock); + iowrite32(0, + mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr); + mutex_unlock(&mi2s_auxpcm_conf[index].lock); + } else { + dev_err(rtd->card->dev, + "%s lpaif_tert_muxsel_virt_addr is NULL\n", + __func__); + auxpcm_intf_conf[index].ref_cnt++; + } + } + mutex_unlock(&auxpcm_intf_conf[index].lock); +} +EXPORT_SYMBOL(msm_aux_pcm_snd_shutdown); + +static int msm_get_port_id(int be_id) +{ + int afe_port_id; + + switch (be_id) { + case MSM_BACKEND_DAI_PRI_MI2S_RX: + afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_RX; + break; + case MSM_BACKEND_DAI_PRI_MI2S_TX: + afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_TX; + break; + case MSM_BACKEND_DAI_SECONDARY_MI2S_RX: + afe_port_id = AFE_PORT_ID_SECONDARY_MI2S_RX; + break; + case MSM_BACKEND_DAI_SECONDARY_MI2S_TX: + afe_port_id = AFE_PORT_ID_SECONDARY_MI2S_TX; + break; + case MSM_BACKEND_DAI_TERTIARY_MI2S_RX: + afe_port_id = AFE_PORT_ID_TERTIARY_MI2S_RX; + break; + case MSM_BACKEND_DAI_TERTIARY_MI2S_TX: + afe_port_id = AFE_PORT_ID_TERTIARY_MI2S_TX; + break; + case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX: + afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_RX; + break; + case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX: + afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; + break; + default: + pr_err("%s: Invalid be_id: %d\n", __func__, be_id); + afe_port_id = -EINVAL; + } + + return afe_port_id; +} + +static u32 get_mi2s_bits_per_sample(u32 bit_format) +{ + u32 bit_per_sample; + + switch (bit_format) { + case SNDRV_PCM_FORMAT_S24_3LE: + case SNDRV_PCM_FORMAT_S24_LE: + bit_per_sample = 32; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + bit_per_sample = 16; + break; + } + + return bit_per_sample; +} + +static void update_mi2s_clk_val(int dai_id, int stream) +{ + u32 bit_per_sample; + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + bit_per_sample = + get_mi2s_bits_per_sample(mi2s_rx_cfg[dai_id].bit_format); + mi2s_clk[dai_id].clk_freq_in_hz = + mi2s_rx_cfg[dai_id].sample_rate * 2 * bit_per_sample; + } else { + bit_per_sample = + get_mi2s_bits_per_sample(mi2s_tx_cfg[dai_id].bit_format); + mi2s_clk[dai_id].clk_freq_in_hz = + mi2s_tx_cfg[dai_id].sample_rate * 2 * bit_per_sample; + } + + if (!mi2s_intf_conf[dai_id].msm_is_mi2s_master) + mi2s_clk[dai_id].clk_freq_in_hz = 0; +} + +static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int port_id = 0; + int index = cpu_dai->id; + + port_id = msm_get_port_id(rtd->dai_link->be_id); + if (IS_ERR_VALUE(port_id)) { + dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__); + ret = port_id; + goto done; + } + + if (enable) { + update_mi2s_clk_val(index, substream->stream); + dev_dbg(rtd->card->dev, "%s: clock rate %ul\n", __func__, + mi2s_clk[index].clk_freq_in_hz); + } + + mi2s_clk[index].enable = enable; + ret = afe_set_lpass_clock_v2(port_id, + &mi2s_clk[index]); + if (ret < 0) { + dev_err(rtd->card->dev, + "%s: afe lpass clock failed for port 0x%x , err:%d\n", + __func__, port_id, ret); + goto done; + } + +done: + return ret; +} + +/** + * msm_mi2s_snd_startup - startup ops of mi2s. + * + * @substream: PCM stream pointer of associated backend dailink + * + * Returns 0 on success or -EINVAL on error. + */ +int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int index = cpu_dai->id; + unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; + + dev_dbg(rtd->card->dev, + "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", + __func__, substream->name, substream->stream, + cpu_dai->name, cpu_dai->id); + + if (index < PRIM_MI2S || index > QUAT_MI2S) { + ret = -EINVAL; + dev_err(rtd->card->dev, + "%s: CPU DAI id (%d) out of range\n", + __func__, cpu_dai->id); + goto done; + } + /* + * Muxtex protection in case the same MI2S + * interface using for both TX and RX so + * that the same clock won't be enable twice. + */ + mutex_lock(&mi2s_intf_conf[index].lock); + if (++mi2s_intf_conf[index].ref_cnt == 1) { + ret = msm_mi2s_set_sclk(substream, true); + if (IS_ERR_VALUE(ret)) { + dev_err(rtd->card->dev, + "%s: afe lpass clock failed to enable MI2S clock, err:%d\n", + __func__, ret); + goto clean_up; + } + if (mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr != NULL) { + mutex_lock(&mi2s_auxpcm_conf[index].lock); + iowrite32(0, + mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr); + mutex_unlock(&mi2s_auxpcm_conf[index].lock); + } else { + dev_err(rtd->card->dev, + "%s lpaif_muxsel_virt_addr is NULL for dai %d\n", + __func__, index); + ret = -EINVAL; + goto clk_off; + } + /* Check if msm needs to provide the clock to the interface */ + if (!mi2s_intf_conf[index].msm_is_mi2s_master) + fmt = SND_SOC_DAIFMT_CBM_CFM; + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (IS_ERR_VALUE(ret)) { + dev_err(rtd->card->dev, + "%s: set fmt cpu dai failed for MI2S (%d), err:%d\n", + __func__, index, ret); + goto clk_off; + } + } +clk_off: + if (IS_ERR_VALUE(ret)) + msm_mi2s_set_sclk(substream, false); +clean_up: + if (IS_ERR_VALUE(ret)) + mi2s_intf_conf[index].ref_cnt--; + mutex_unlock(&mi2s_intf_conf[index].lock); +done: + return ret; +} +EXPORT_SYMBOL(msm_mi2s_snd_startup); + +/** + * msm_mi2s_snd_shutdown - shutdown ops of mi2s. + * + * @substream: PCM stream pointer of associated backend dailink + */ +void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) +{ + int ret; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int index = rtd->cpu_dai->id; + + pr_debug("%s(): substream = %s stream = %d\n", __func__, + substream->name, substream->stream); + if (index < PRIM_MI2S || index > QUAT_MI2S) { + pr_err("%s:invalid MI2S DAI(%d)\n", __func__, index); + return; + } + + mutex_lock(&mi2s_intf_conf[index].lock); + if (--mi2s_intf_conf[index].ref_cnt == 0) { + ret = msm_mi2s_set_sclk(substream, false); + if (ret < 0) { + pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n", + __func__, index, ret); + mi2s_intf_conf[index].ref_cnt++; + } + } + mutex_unlock(&mi2s_intf_conf[index].lock); +} +EXPORT_SYMBOL(msm_mi2s_snd_shutdown); + +/* Validate whether US EU switch is present or not */ +static int msm_prepare_us_euro(struct snd_soc_card *card) +{ + struct msm_asoc_mach_data *pdata = + snd_soc_card_get_drvdata(card); + int ret = 0; + + if (pdata->us_euro_gpio >= 0) { + dev_dbg(card->dev, "%s: us_euro gpio request %d", __func__, + pdata->us_euro_gpio); + ret = gpio_request(pdata->us_euro_gpio, "TASHA_CODEC_US_EURO"); + if (ret) { + dev_err(card->dev, + "%s: Failed to request codec US/EURO gpio %d error %d\n", + __func__, pdata->us_euro_gpio, ret); + } + } + + return ret; +} + +static bool msm_swap_gnd_mic(struct snd_soc_codec *codec) +{ + struct snd_soc_card *card = codec->component.card; + struct msm_asoc_mach_data *pdata = + snd_soc_card_get_drvdata(card); + int value = 0; + + if (pdata->us_euro_gpio_p) { + value = msm_cdc_pinctrl_get_state(pdata->us_euro_gpio_p); + if (value) + msm_cdc_pinctrl_select_sleep_state( + pdata->us_euro_gpio_p); + else + msm_cdc_pinctrl_select_active_state( + pdata->us_euro_gpio_p); + } else if (pdata->us_euro_gpio >= 0) { + value = gpio_get_value_cansleep(pdata->us_euro_gpio); + gpio_set_value_cansleep(pdata->us_euro_gpio, !value); + } + pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value); + return true; +} + +static int msm_populate_dai_link_component_of_node( + struct snd_soc_card *card) +{ + int i, index, ret = 0; + struct device *cdev = card->dev; + struct snd_soc_dai_link *dai_link = card->dai_link; + struct device_node *phandle; + + if (!cdev) { + pr_err("%s: Sound card device memory NULL\n", __func__); + return -ENODEV; + } + + for (i = 0; i < card->num_links; i++) { + if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node) + continue; + + /* populate platform_of_node for snd card dai links */ + if (dai_link[i].platform_name && + !dai_link[i].platform_of_node) { + index = of_property_match_string(cdev->of_node, + "asoc-platform-names", + dai_link[i].platform_name); + if (index < 0) { + pr_err("%s: No match found for platform name: %s\n", + __func__, dai_link[i].platform_name); + ret = index; + goto cpu_dai; + } + phandle = of_parse_phandle(cdev->of_node, + "asoc-platform", + index); + if (!phandle) { + pr_err("%s: retrieving phandle for platform %s, index %d failed\n", + __func__, dai_link[i].platform_name, + index); + ret = -ENODEV; + goto err; + } + dai_link[i].platform_of_node = phandle; + dai_link[i].platform_name = NULL; + } +cpu_dai: + /* populate cpu_of_node for snd card dai links */ + if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) { + index = of_property_match_string(cdev->of_node, + "asoc-cpu-names", + dai_link[i].cpu_dai_name); + if (index < 0) + goto codec_dai; + phandle = of_parse_phandle(cdev->of_node, "asoc-cpu", + index); + if (!phandle) { + pr_err("%s: retrieving phandle for cpu dai %s failed\n", + __func__, dai_link[i].cpu_dai_name); + ret = -ENODEV; + goto err; + } + dai_link[i].cpu_of_node = phandle; + dai_link[i].cpu_dai_name = NULL; + } +codec_dai: + /* populate codec_of_node for snd card dai links */ + if (dai_link[i].codec_name && !dai_link[i].codec_of_node) { + index = of_property_match_string(cdev->of_node, + "asoc-codec-names", + dai_link[i].codec_name); + if (index < 0) + continue; + phandle = of_parse_phandle(cdev->of_node, "asoc-codec", + index); + if (!phandle) { + pr_err("%s: retrieving phandle for codec dai %s failed\n", + __func__, dai_link[i].codec_name); + ret = -ENODEV; + goto err; + } + dai_link[i].codec_of_node = phandle; + dai_link[i].codec_name = NULL; + } + } +err: + return ret; +} + +static int msm_wsa881x_init(struct snd_soc_component *component) +{ + u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {100, 101, 102, 106}; + u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {103, 104, 105, 107}; + unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200}; + unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3}; + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + struct msm_asoc_mach_data *pdata; + struct snd_soc_dapm_context *dapm = + snd_soc_codec_get_dapm(codec); + + if (!codec) { + pr_err("%s codec is NULL\n", __func__); + return -EINVAL; + } + + if (!strcmp(component->name_prefix, "SpkrLeft")) { + dev_dbg(codec->dev, "%s: setting left ch map to codec %s\n", + __func__, codec->component.name); + wsa881x_set_channel_map(codec, &spkleft_ports[0], + WSA881X_MAX_SWR_PORTS, &ch_mask[0], + &ch_rate[0]); + if (dapm->component) { + snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN"); + snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR"); + } + } else if (!strcmp(component->name_prefix, "SpkrRight")) { + dev_dbg(codec->dev, "%s: setting right ch map to codec %s\n", + __func__, codec->component.name); + wsa881x_set_channel_map(codec, &spkright_ports[0], + WSA881X_MAX_SWR_PORTS, &ch_mask[0], + &ch_rate[0]); + if (dapm->component) { + snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN"); + snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR"); + } + } else { + dev_err(codec->dev, "%s: wrong codec name %s\n", __func__, + codec->component.name); + return -EINVAL; + } + + + pdata = snd_soc_card_get_drvdata(component->card); + if (pdata && pdata->codec_root) + wsa881x_codec_info_create_codec_entry(pdata->codec_root, + codec); + return 0; +} + + +static int msm_init_wsa_dev(struct platform_device *pdev, + struct snd_soc_card *card) +{ + struct device_node *wsa_of_node; + u32 wsa_max_devs; + u32 wsa_dev_cnt; + char *dev_name_str = NULL; + struct msm_wsa881x_dev_info *wsa881x_dev_info; + const char *wsa_auxdev_name_prefix[1]; + int found = 0; + int i; + int ret; + + /* Get maximum WSA device count for this platform */ + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,wsa-max-devs", &wsa_max_devs); + if (ret) { + dev_dbg(&pdev->dev, + "%s: wsa-max-devs property missing in DT %s, ret = %d\n", + __func__, pdev->dev.of_node->full_name, ret); + goto err_dt; + } + if (wsa_max_devs == 0) { + dev_warn(&pdev->dev, + "%s: Max WSA devices is 0 for this target?\n", + __func__); + goto err_dt; + } + + /* Get count of WSA device phandles for this platform */ + wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node, + "qcom,wsa-devs", NULL); + if (wsa_dev_cnt == -ENOENT) { + dev_warn(&pdev->dev, "%s: No wsa device defined in DT.\n", + __func__); + goto err_dt; + } else if (wsa_dev_cnt <= 0) { + dev_err(&pdev->dev, + "%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n", + __func__, wsa_dev_cnt); + ret = -EINVAL; + goto err_dt; + } + + /* + * Expect total phandles count to be NOT less than maximum possible + * WSA count. However, if it is less, then assign same value to + * max count as well. + */ + if (wsa_dev_cnt < wsa_max_devs) { + dev_dbg(&pdev->dev, + "%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n", + __func__, wsa_max_devs, wsa_dev_cnt); + wsa_max_devs = wsa_dev_cnt; + } + + /* Make sure prefix string passed for each WSA device */ + ret = of_property_count_strings(pdev->dev.of_node, + "qcom,wsa-aux-dev-prefix"); + if (ret != wsa_dev_cnt) { + dev_err(&pdev->dev, + "%s: expecting %d wsa prefix. Defined only %d in DT\n", + __func__, wsa_dev_cnt, ret); + ret = -EINVAL; + goto err_dt; + } + + /* + * Alloc mem to store phandle and index info of WSA device, if already + * registered with ALSA core + */ + wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs, + sizeof(struct msm_wsa881x_dev_info), + GFP_KERNEL); + if (!wsa881x_dev_info) { + ret = -ENOMEM; + goto err_mem; + } + + /* + * search and check whether all WSA devices are already + * registered with ALSA core or not. If found a node, store + * the node and the index in a local array of struct for later + * use. + */ + for (i = 0; i < wsa_dev_cnt; i++) { + wsa_of_node = of_parse_phandle(pdev->dev.of_node, + "qcom,wsa-devs", i); + if (unlikely(!wsa_of_node)) { + /* we should not be here */ + dev_err(&pdev->dev, + "%s: wsa dev node is not present\n", + __func__); + ret = -EINVAL; + goto err_dev_node; + } + if (soc_find_component(wsa_of_node, NULL)) { + /* WSA device registered with ALSA core */ + wsa881x_dev_info[found].of_node = wsa_of_node; + wsa881x_dev_info[found].index = i; + found++; + if (found == wsa_max_devs) + break; + } + } + + if (found < wsa_max_devs) { + dev_dbg(&pdev->dev, + "%s: failed to find %d components. Found only %d\n", + __func__, wsa_max_devs, found); + return -EPROBE_DEFER; + } + dev_info(&pdev->dev, + "%s: found %d wsa881x devices registered with ALSA core\n", + __func__, found); + + card->num_aux_devs = wsa_max_devs; + card->num_configs = wsa_max_devs; + + /* Alloc array of AUX devs struct */ + msm_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs, + sizeof(struct snd_soc_aux_dev), + GFP_KERNEL); + if (!msm_aux_dev) { + ret = -ENOMEM; + goto err_auxdev_mem; + } + + /* Alloc array of codec conf struct */ + msm_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs, + sizeof(struct snd_soc_codec_conf), + GFP_KERNEL); + if (!msm_codec_conf) { + ret = -ENOMEM; + goto err_codec_conf; + } + + for (i = 0; i < card->num_aux_devs; i++) { + dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN, + GFP_KERNEL); + if (!dev_name_str) { + ret = -ENOMEM; + goto err_dev_str; + } + + ret = of_property_read_string_index(pdev->dev.of_node, + "qcom,wsa-aux-dev-prefix", + wsa881x_dev_info[i].index, + wsa_auxdev_name_prefix); + if (ret) { + dev_err(&pdev->dev, + "%s: failed to read wsa aux dev prefix, ret = %d\n", + __func__, ret); + ret = -EINVAL; + goto err_dt_prop; + } + + snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i); + msm_aux_dev[i].name = dev_name_str; + msm_aux_dev[i].codec_name = NULL; + msm_aux_dev[i].codec_of_node = + wsa881x_dev_info[i].of_node; + msm_aux_dev[i].init = msm_wsa881x_init; + msm_codec_conf[i].dev_name = NULL; + msm_codec_conf[i].name_prefix = wsa_auxdev_name_prefix[0]; + msm_codec_conf[i].of_node = wsa881x_dev_info[i].of_node; + } + card->codec_conf = msm_codec_conf; + card->aux_dev = msm_aux_dev; + + return 0; + +err_dt_prop: + devm_kfree(&pdev->dev, dev_name_str); +err_dev_str: + devm_kfree(&pdev->dev, msm_codec_conf); +err_codec_conf: + devm_kfree(&pdev->dev, msm_aux_dev); +err_auxdev_mem: +err_dev_node: + devm_kfree(&pdev->dev, wsa881x_dev_info); +err_mem: +err_dt: + return ret; +} + +static void msm_free_auxdev_mem(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + int i; + + if (card->num_aux_devs > 0) { + for (i = 0; i < card->num_aux_devs; i++) { + kfree(msm_aux_dev[i].codec_name); + kfree(msm_codec_conf[i].dev_name); + kfree(msm_codec_conf[i].name_prefix); + } + } +} + +static void i2s_auxpcm_init(struct platform_device *pdev) +{ + struct resource *muxsel; + int count; + u32 mi2s_master_slave[MI2S_MAX]; + int ret; + char *str[PCM_I2S_SEL_MAX] = { + "lpaif_pri_mode_muxsel", + "lpaif_sec_mode_muxsel", + "lpaif_tert_mode_muxsel", + "lpaif_quat_mode_muxsel" + }; + + for (count = 0; count < MI2S_MAX; count++) { + mutex_init(&mi2s_intf_conf[count].lock); + mi2s_intf_conf[count].ref_cnt = 0; + } + + for (count = 0; count < AUX_PCM_MAX; count++) { + mutex_init(&auxpcm_intf_conf[count].lock); + auxpcm_intf_conf[count].ref_cnt = 0; + } + + for (count = 0; count < PCM_I2S_SEL_MAX; count++) { + mutex_init(&mi2s_auxpcm_conf[count].lock); + mi2s_auxpcm_conf[count].pcm_i2s_sel_vt_addr = NULL; + } + + for (count = 0; count < PCM_I2S_SEL_MAX; count++) { + muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM, + str[count]); + if (muxsel) { + mi2s_auxpcm_conf[count].pcm_i2s_sel_vt_addr + = ioremap(muxsel->start, resource_size(muxsel)); + } + } + + ret = of_property_read_u32_array(pdev->dev.of_node, + "qcom,msm-mi2s-master", + mi2s_master_slave, MI2S_MAX); + if (ret) { + dev_dbg(&pdev->dev, "%s: no qcom,msm-mi2s-master in DT node\n", + __func__); + } else { + for (count = 0; count < MI2S_MAX; count++) { + mi2s_intf_conf[count].msm_is_mi2s_master = + mi2s_master_slave[count]; + } + } +} + +static void i2s_auxpcm_deinit(void) +{ + int count; + + for (count = 0; count < PCM_I2S_SEL_MAX; count++) + if (mi2s_auxpcm_conf[count].pcm_i2s_sel_vt_addr != + NULL) + iounmap( + mi2s_auxpcm_conf[count].pcm_i2s_sel_vt_addr); +} + +static const struct of_device_id msmfalcon_asoc_machine_of_match[] = { + { .compatible = "qcom,msmfalcon-asoc-snd", + .data = "internal_codec"}, + { .compatible = "qcom,msmfalcon-asoc-snd-tasha", + .data = "tasha_codec"}, + { .compatible = "qcom,msmfalcon-asoc-snd-tavil", + .data = "tavil_codec"}, + {}, +}; + +static int msm_asoc_machine_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = NULL; + struct msm_asoc_mach_data *pdata = NULL; + const char *mclk = "qcom,msm-mclk-freq"; + int ret = -EINVAL, id; + const struct of_device_id *match; + + pdata = devm_kzalloc(&pdev->dev, + sizeof(struct msm_asoc_mach_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + match = of_match_node(msmfalcon_asoc_machine_of_match, + pdev->dev.of_node); + if (!match) + goto err; + + ret = of_property_read_u32(pdev->dev.of_node, mclk, &id); + if (ret) { + dev_err(&pdev->dev, + "%s: missing %s in dt node\n", __func__, mclk); + id = DEFAULT_MCLK_RATE; + } + pdata->mclk_freq = id; + + if (!strcmp(match->data, "tasha_codec") || + !strcmp(match->data, "tavil_codec")) { + ret = msm_ext_cdc_init(pdev, pdata, &card, &mbhc_cfg); + if (ret) + goto err; + } else if (!strcmp(match->data, "internal_codec")) { + pdata->int_codec = 1; + ret = msm_int_cdc_init(pdev, pdata, &card, &mbhc_cfg); + if (ret) + goto err; + } else { + dev_err(&pdev->dev, + "%s: Not a matching DT sound node\n", __func__); + goto err; + } + if (!card) + goto err; + + /*reading the gpio configurations from dtsi file*/ + ret = msm_gpioset_initialize(CLIENT_WCD, &pdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, + "%s: error reading dtsi files%d\n", __func__, ret); + goto err; + } + + /* + * Parse US-Euro gpio info from DT. Report no error if us-euro + * entry is not found in DT file as some targets do not support + * US-Euro detection + */ + pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node, + "qcom,us-euro-gpios", 0); + if (!gpio_is_valid(pdata->us_euro_gpio)) + pdata->us_euro_gpio_p = of_parse_phandle(pdev->dev.of_node, + "qcom,us-euro-gpios", 0); + if (!gpio_is_valid(pdata->us_euro_gpio) && (!pdata->us_euro_gpio_p)) { + dev_dbg(&pdev->dev, "property %s not detected in node %s", + "qcom,us-euro-gpios", pdev->dev.of_node->full_name); + } else { + dev_dbg(&pdev->dev, "%s detected", + "qcom,us-euro-gpios"); + mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic; + } + + ret = msm_prepare_us_euro(card); + if (ret) + dev_dbg(&pdev->dev, "msm_prepare_us_euro failed (%d)\n", + ret); + + i2s_auxpcm_init(pdev); + + ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing"); + if (ret) + goto err; + + ret = msm_populate_dai_link_component_of_node(card); + if (ret) { + ret = -EPROBE_DEFER; + goto err; + } + ret = msm_init_wsa_dev(pdev, card); + if (ret) + goto err; + + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); + goto err; + } + return 0; +err: + if (pdata->us_euro_gpio > 0) { + dev_dbg(&pdev->dev, "%s free us_euro gpio %d\n", + __func__, pdata->us_euro_gpio); + pdata->us_euro_gpio = 0; + } + if (pdata->hph_en1_gpio > 0) { + dev_dbg(&pdev->dev, "%s free hph_en1_gpio %d\n", + __func__, pdata->hph_en1_gpio); + gpio_free(pdata->hph_en1_gpio); + pdata->hph_en1_gpio = 0; + } + if (pdata->hph_en0_gpio > 0) { + dev_dbg(&pdev->dev, "%s free hph_en0_gpio %d\n", + __func__, pdata->hph_en0_gpio); + gpio_free(pdata->hph_en0_gpio); + pdata->hph_en0_gpio = 0; + } + devm_kfree(&pdev->dev, pdata); + return ret; +} + +static int msm_asoc_machine_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + + if (pdata->int_codec) + mutex_destroy(&pdata->cdc_int_mclk0_mutex); + msm_free_auxdev_mem(pdev); + + gpio_free(pdata->us_euro_gpio); + gpio_free(pdata->hph_en1_gpio); + gpio_free(pdata->hph_en0_gpio); + i2s_auxpcm_deinit(); + snd_soc_unregister_card(card); + return 0; +} + +static struct platform_driver msmfalcon_asoc_machine_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = msmfalcon_asoc_machine_of_match, + }, + .probe = msm_asoc_machine_probe, + .remove = msm_asoc_machine_remove, +}; +module_platform_driver(msmfalcon_asoc_machine_driver); + +MODULE_DESCRIPTION("ALSA SoC msm"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); +MODULE_DEVICE_TABLE(of, msmfalcon_asoc_machine_of_match); diff --git a/sound/soc/msm/msmfalcon-common.h b/sound/soc/msm/msmfalcon-common.h new file mode 100644 index 000000000000..ff8232d6fcbb --- /dev/null +++ b/sound/soc/msm/msmfalcon-common.h @@ -0,0 +1,69 @@ +/* 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 __MSM_COMMON +#define __MSM_COMMON + +#include <sound/soc.h> +#include <sound/q6afe-v2.h> +#include "../codecs/wcd-mbhc-v2.h" + +#define SAMPLING_RATE_8KHZ 8000 +#define SAMPLING_RATE_11P025KHZ 11025 +#define SAMPLING_RATE_16KHZ 16000 +#define SAMPLING_RATE_22P05KHZ 22050 +#define SAMPLING_RATE_32KHZ 32000 +#define SAMPLING_RATE_44P1KHZ 44100 +#define SAMPLING_RATE_48KHZ 48000 +#define SAMPLING_RATE_88P2KHZ 88200 +#define SAMPLING_RATE_96KHZ 96000 +#define SAMPLING_RATE_176P4KHZ 176400 +#define SAMPLING_RATE_192KHZ 192000 +#define SAMPLING_RATE_352P8KHZ 352800 +#define SAMPLING_RATE_384KHZ 384000 + +extern const struct snd_kcontrol_new msm_common_snd_controls[]; +struct msmfalcon_codec { + void* (*get_afe_config_fn)(struct snd_soc_codec *codec, + enum afe_config_type config_type); +}; + +struct msm_asoc_mach_data { + int us_euro_gpio; /* used by gpio driver API */ + int hph_en1_gpio; + int hph_en0_gpio; + struct device_node *us_euro_gpio_p; /* used by pinctrl API */ + struct device_node *hph_en1_gpio_p; /* used by pinctrl API */ + struct device_node *hph_en0_gpio_p; /* used by pinctrl API */ + struct snd_soc_codec *codec; + struct msmfalcon_codec msmfalcon_codec_fn; + struct snd_info_entry *codec_root; + int spk_ext_pa_gpio; + int mclk_freq; + int lb_mode; + u8 micbias1_cap_mode; + u8 micbias2_cap_mode; + atomic_t int_mclk0_rsc_ref; + atomic_t int_mclk0_enabled; + struct mutex cdc_int_mclk0_mutex; + struct delayed_work disable_int_mclk0_work; + struct afe_clk_set digital_cdc_core_clk; + bool int_codec; +}; + +int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); +int msm_aux_pcm_snd_startup(struct snd_pcm_substream *substream); +void msm_aux_pcm_snd_shutdown(struct snd_pcm_substream *substream); +int msm_mi2s_snd_startup(struct snd_pcm_substream *substream); +void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream); +#endif diff --git a/sound/soc/msm/msmfalcon-ext-dai-links.c b/sound/soc/msm/msmfalcon-ext-dai-links.c new file mode 100644 index 000000000000..4dca7908c108 --- /dev/null +++ b/sound/soc/msm/msmfalcon-ext-dai-links.c @@ -0,0 +1,1527 @@ +/* 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/mfd/wcd9xxx/core.h> +#include <linux/of.h> +#include <sound/core.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/pcm.h> +#include "qdsp6v2/msm-pcm-routing-v2.h" +#include "../codecs/wcd9335.h" +#include "msmfalcon-common.h" +#include "msmfalcon-external.h" + +#define DEV_NAME_STR_LEN 32 +#define __CHIPSET__ "MSMFALCON " +#define MSM_DAILINK_NAME(name) (__CHIPSET__#name) + +static struct snd_soc_card snd_soc_card_msm_card; + +static struct snd_soc_ops msm_ext_slimbus_be_ops = { + .hw_params = msm_snd_hw_params, +}; + +static struct snd_soc_ops msm_ext_cpe_ops = { + .hw_params = msm_snd_cpe_hw_params, +}; + +static struct snd_soc_ops msm_ext_slimbus_2_be_ops = { + .hw_params = msm_ext_slimbus_2_hw_params, +}; + +static struct snd_soc_ops msm_mi2s_be_ops = { + .startup = msm_mi2s_snd_startup, + .shutdown = msm_mi2s_snd_shutdown, +}; + +static struct snd_soc_ops msm_aux_pcm_be_ops = { + .startup = msm_aux_pcm_snd_startup, + .shutdown = msm_aux_pcm_snd_shutdown, +}; + +static struct snd_soc_dai_link msm_ext_tasha_fe_dai[] = { + /* tasha_vifeedback for speaker protection */ + { + .name = LPASS_BE_SLIMBUS_4_TX, + .stream_name = "Slimbus4 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16393", + .platform_name = "msm-pcm-hostless", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_vifeedback", + .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + }, + /* Ultrasound RX DAI Link */ + { + .name = "SLIMBUS_2 Hostless Playback", + .stream_name = "SLIMBUS_2 Hostless Playback", + .cpu_dai_name = "msm-dai-q6-dev.16388", + .platform_name = "msm-pcm-hostless", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_rx2", + .ignore_suspend = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ops = &msm_ext_slimbus_2_be_ops, + }, + /* Ultrasound TX DAI Link */ + { + .name = "SLIMBUS_2 Hostless Capture", + .stream_name = "SLIMBUS_2 Hostless Capture", + .cpu_dai_name = "msm-dai-q6-dev.16389", + .platform_name = "msm-pcm-hostless", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_tx2", + .ignore_suspend = 1, + .dpcm_capture = 1, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ops = &msm_ext_slimbus_2_be_ops, + }, + /* CPE LSM direct dai-link */ + { + .name = "CPE Listen service", + .stream_name = "CPE Listen Audio Service", + .cpu_dai_name = "msm-dai-slim", + .platform_name = "msm-cpe-lsm", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .dpcm_capture = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "tasha_mad1", + .codec_name = "tasha_codec", + .ops = &msm_ext_cpe_ops, + }, + { + .name = "SLIMBUS_6 Hostless Playback", + .stream_name = "SLIMBUS_6 Hostless", + .cpu_dai_name = "SLIMBUS6_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dailink has playback support */ + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + /* CPE LSM EC PP direct dai-link */ + { + .name = "CPE Listen service ECPP", + .stream_name = "CPE Listen Audio Service ECPP", + .cpu_dai_name = "CPE_LSM_NOHOST", + .platform_name = "msm-cpe-lsm.3", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "tasha_cpe", + .codec_name = "tasha_codec", + }, +}; + +static struct snd_soc_dai_link msm_ext_tavil_fe_dai[] = { + { + .name = LPASS_BE_SLIMBUS_4_TX, + .stream_name = "Slimbus4 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16393", + .platform_name = "msm-pcm-hostless", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_vifeedback", + .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + }, + /* Ultrasound RX DAI Link */ + { + .name = "SLIMBUS_2 Hostless Playback", + .stream_name = "SLIMBUS_2 Hostless Playback", + .cpu_dai_name = "msm-dai-q6-dev.16388", + .platform_name = "msm-pcm-hostless", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_rx2", + .ignore_suspend = 1, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ops = &msm_ext_slimbus_2_be_ops, + }, + /* Ultrasound TX DAI Link */ + { + .name = "SLIMBUS_2 Hostless Capture", + .stream_name = "SLIMBUS_2 Hostless Capture", + .cpu_dai_name = "msm-dai-q6-dev.16389", + .platform_name = "msm-pcm-hostless", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_tx2", + .ignore_suspend = 1, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ops = &msm_ext_slimbus_2_be_ops, + }, +}; + +static struct snd_soc_dai_link msm_ext_tasha_be_dai[] = { + /* Backend DAI Links */ + { + .name = LPASS_BE_SLIMBUS_0_RX, + .stream_name = "Slimbus Playback", + .cpu_dai_name = "msm-dai-q6-dev.16384", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_mix_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX, + .init = &msm_audrx_init, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_ext_slimbus_be_ops, + }, + { + .name = LPASS_BE_SLIMBUS_0_TX, + .stream_name = "Slimbus Capture", + .cpu_dai_name = "msm-dai-q6-dev.16385", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_tx1", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ignore_suspend = 1, + .ops = &msm_ext_slimbus_be_ops, + }, + { + .name = LPASS_BE_SLIMBUS_1_RX, + .stream_name = "Slimbus1 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16386", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_mix_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_1_TX, + .stream_name = "Slimbus1 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16387", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_tx3", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_3_RX, + .stream_name = "Slimbus3 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16390", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_mix_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_3_TX, + .stream_name = "Slimbus3 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16391", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_tx1", + .no_pcm = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_4_RX, + .stream_name = "Slimbus4 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16392", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_mix_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_5_RX, + .stream_name = "Slimbus5 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16394", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_rx3", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_5_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + /* MAD BE */ + { + .name = LPASS_BE_SLIMBUS_5_TX, + .stream_name = "Slimbus5 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16395", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_mad1", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_6_RX, + .stream_name = "Slimbus6 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16396", + .platform_name = "msm-pcm-routing", + .codec_name = "tasha_codec", + .codec_dai_name = "tasha_rx4", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_6_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, +}; + +static struct snd_soc_dai_link msm_ext_tavil_be_dai[] = { + { + .name = LPASS_BE_SLIMBUS_0_RX, + .stream_name = "Slimbus Playback", + .cpu_dai_name = "msm-dai-q6-dev.16384", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX, + .init = &msm_audrx_init, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_ext_slimbus_be_ops, + }, + { + .name = LPASS_BE_SLIMBUS_0_TX, + .stream_name = "Slimbus Capture", + .cpu_dai_name = "msm-dai-q6-dev.16385", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_tx1", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ignore_suspend = 1, + .ops = &msm_ext_slimbus_be_ops, + }, + { + .name = LPASS_BE_SLIMBUS_1_RX, + .stream_name = "Slimbus1 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16386", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_1_TX, + .stream_name = "Slimbus1 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16387", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_tx3", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_2_RX, + .stream_name = "Slimbus2 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16388", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_rx2", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_2_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_3_RX, + .stream_name = "Slimbus3 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16390", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_3_TX, + .stream_name = "Slimbus3 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16391", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_tx1", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_4_RX, + .stream_name = "Slimbus4 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16392", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_5_RX, + .stream_name = "Slimbus5 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16394", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_rx3", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_5_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + /* MAD BE */ + { + .name = LPASS_BE_SLIMBUS_5_TX, + .stream_name = "Slimbus5 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16395", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_mad1", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SLIMBUS_6_RX, + .stream_name = "Slimbus6 Playback", + .cpu_dai_name = "msm-dai-q6-dev.16396", + .platform_name = "msm-pcm-routing", + .codec_name = "tavil_codec", + .codec_dai_name = "tavil_rx4", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SLIMBUS_6_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ops = &msm_ext_slimbus_be_ops, + /* dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, +}; + +static struct snd_soc_dai_link msm_ext_common_fe_dai[] = { + /* FrontEnd DAI Links */ + {/* hw:x,0 */ + .name = MSM_DAILINK_NAME(Media1), + .stream_name = "MultiMedia1", + .cpu_dai_name = "MultiMedia1", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1 + }, + {/* hw:x,1 */ + .name = MSM_DAILINK_NAME(Media2), + .stream_name = "MultiMedia2", + .cpu_dai_name = "MultiMedia2", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2, + }, + {/* hw:x,2 */ + .name = "VoiceMMode1", + .stream_name = "VoiceMMode1", + .cpu_dai_name = "VoiceMMode1", + .platform_name = "msm-pcm-voice", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_VOICEMMODE1, + }, + {/* hw:x,3 */ + .name = "MSM VoIP", + .stream_name = "VoIP", + .cpu_dai_name = "VoIP", + .platform_name = "msm-voip-dsp", + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_VOIP, + }, + {/* hw:x,4 */ + .name = MSM_DAILINK_NAME(ULL), + .stream_name = "ULL", + .cpu_dai_name = "MultiMedia3", + .platform_name = "msm-pcm-dsp.2", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3, + }, + /* Hostless PCM purpose */ + {/* hw:x,5 */ + .name = "SLIMBUS_0 Hostless", + .stream_name = "SLIMBUS_0 Hostless", + .cpu_dai_name = "SLIMBUS0_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* This dai link has MI2S support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,6 */ + .name = "MSM AFE-PCM RX", + .stream_name = "AFE-PROXY RX", + .cpu_dai_name = "msm-dai-q6-dev.241", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .platform_name = "msm-pcm-afe", + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + }, + {/* hw:x,7 */ + .name = "MSM AFE-PCM TX", + .stream_name = "AFE-PROXY TX", + .cpu_dai_name = "msm-dai-q6-dev.240", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .platform_name = "msm-pcm-afe", + .ignore_suspend = 1, + }, + {/* hw:x,8 */ + .name = MSM_DAILINK_NAME(Compress1), + .stream_name = "Compress1", + .cpu_dai_name = "MultiMedia4", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4, + }, + {/* hw:x,9*/ + .name = "AUXPCM Hostless", + .stream_name = "AUXPCM Hostless", + .cpu_dai_name = "AUXPCM_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,10 */ + .name = "SLIMBUS_1 Hostless", + .stream_name = "SLIMBUS_1 Hostless", + .cpu_dai_name = "SLIMBUS1_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, /* dai link has playback support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,11 */ + .name = "SLIMBUS_3 Hostless", + .stream_name = "SLIMBUS_3 Hostless", + .cpu_dai_name = "SLIMBUS3_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, /* dai link has playback support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,12 */ + .name = "SLIMBUS_4 Hostless", + .stream_name = "SLIMBUS_4 Hostless", + .cpu_dai_name = "SLIMBUS4_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, /* dai link has playback support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,13 */ + .name = MSM_DAILINK_NAME(LowLatency), + .stream_name = "MultiMedia5", + .cpu_dai_name = "MultiMedia5", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5, + }, + /* LSM FE */ + {/* hw:x,14 */ + .name = "Listen 1 Audio Service", + .stream_name = "Listen 1 Audio Service", + .cpu_dai_name = "LSM1", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM1, + }, + {/* hw:x,15 */ + .name = MSM_DAILINK_NAME(Compress2), + .stream_name = "Compress2", + .cpu_dai_name = "MultiMedia7", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7, + }, + {/* hw:x,16 */ + .name = MSM_DAILINK_NAME(Compress3), + .stream_name = "Compress3", + .cpu_dai_name = "MultiMedia10", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA10, + }, + {/* hw:x,17 */ + .name = MSM_DAILINK_NAME(ULL_NOIRQ), + .stream_name = "MM_NOIRQ", + .cpu_dai_name = "MultiMedia8", + .platform_name = "msm-pcm-dsp-noirq", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8, + }, + {/* hw:x,18 */ + .name = "HDMI_RX_HOSTLESS", + .stream_name = "HDMI_RX_HOSTLESS", + .cpu_dai_name = "HDMI_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,19 */ + .name = "VoiceMMode2", + .stream_name = "VoiceMMode2", + .cpu_dai_name = "VoiceMMode2", + .platform_name = "msm-pcm-voice", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_VOICEMMODE2, + }, + {/* hw:x,20 */ + .name = "Listen 2 Audio Service", + .stream_name = "Listen 2 Audio Service", + .cpu_dai_name = "LSM2", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM2, + }, + {/* hw:x,21 */ + .name = "Listen 3 Audio Service", + .stream_name = "Listen 3 Audio Service", + .cpu_dai_name = "LSM3", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM3, + }, + {/* hw:x,22 */ + .name = "Listen 4 Audio Service", + .stream_name = "Listen 4 Audio Service", + .cpu_dai_name = "LSM4", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM4, + }, + {/* hw:x,23 */ + .name = "Listen 5 Audio Service", + .stream_name = "Listen 5 Audio Service", + .cpu_dai_name = "LSM5", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM5, + }, + {/* hw:x,24 */ + .name = "Listen 6 Audio Service", + .stream_name = "Listen 6 Audio Service", + .cpu_dai_name = "LSM6", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM6 + }, + {/* hw:x,25 */ + .name = "Listen 7 Audio Service", + .stream_name = "Listen 7 Audio Service", + .cpu_dai_name = "LSM7", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM7, + }, + {/* hw:x,26 */ + .name = "Listen 8 Audio Service", + .stream_name = "Listen 8 Audio Service", + .cpu_dai_name = "LSM8", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM8, + }, + {/* hw:x,27 */ + .name = MSM_DAILINK_NAME(Media9), + .stream_name = "MultiMedia9", + .cpu_dai_name = "MultiMedia9", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA9, + }, + {/* hw:x,28 */ + .name = MSM_DAILINK_NAME(Compress4), + .stream_name = "Compress4", + .cpu_dai_name = "MultiMedia11", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA11, + }, + {/* hw:x,29 */ + .name = MSM_DAILINK_NAME(Compress5), + .stream_name = "Compress5", + .cpu_dai_name = "MultiMedia12", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA12, + }, + {/* hw:x,30 */ + .name = MSM_DAILINK_NAME(Compress6), + .stream_name = "Compress6", + .cpu_dai_name = "MultiMedia13", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA13, + }, + {/* hw:x,31 */ + .name = MSM_DAILINK_NAME(Compress7), + .stream_name = "Compress7", + .cpu_dai_name = "MultiMedia14", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA14, + }, + {/* hw:x,32 */ + .name = MSM_DAILINK_NAME(Compress8), + .stream_name = "Compress8", + .cpu_dai_name = "MultiMedia15", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA15, + }, + {/* hw:x,33 */ + .name = MSM_DAILINK_NAME(Compress9), + .stream_name = "Compress9", + .cpu_dai_name = "MultiMedia16", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA16, + }, + {/* hw:x,34 */ + .name = "SLIMBUS_8 Hostless", + .stream_name = "SLIMBUS8_HOSTLESS Capture", + .cpu_dai_name = "SLIMBUS8_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, +}; + +static struct snd_soc_dai_link msm_ext_common_be_dai[] = { + { + .name = LPASS_BE_AFE_PCM_RX, + .stream_name = "AFE Playback", + .cpu_dai_name = "msm-dai-q6-dev.224", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_AFE_PCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_AFE_PCM_TX, + .stream_name = "AFE Capture", + .cpu_dai_name = "msm-dai-q6-dev.225", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_AFE_PCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_suspend = 1, + }, + /* Incall Record Uplink BACK END DAI Link */ + { + .name = LPASS_BE_INCALL_RECORD_TX, + .stream_name = "Voice Uplink Capture", + .cpu_dai_name = "msm-dai-q6-dev.32772", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ignore_suspend = 1, + }, + /* Incall Record Downlink BACK END DAI Link */ + { + .name = LPASS_BE_INCALL_RECORD_RX, + .stream_name = "Voice Downlink Capture", + .cpu_dai_name = "msm-dai-q6-dev.32771", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ignore_suspend = 1, + }, + /* Incall Music BACK END DAI Link */ + { + .name = LPASS_BE_VOICE_PLAYBACK_TX, + .stream_name = "Voice Farend Playback", + .cpu_dai_name = "msm-dai-q6-dev.32773", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ignore_suspend = 1, + }, + /* Incall Music 2 BACK END DAI Link */ + { + .name = LPASS_BE_VOICE2_PLAYBACK_TX, + .stream_name = "Voice2 Farend Playback", + .cpu_dai_name = "msm-dai-q6-dev.32770", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX, + .be_hw_params_fixup = msm_ext_be_hw_params_fixup, + .ignore_suspend = 1, + }, +}; + +static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = { + { + .name = LPASS_BE_PRI_MI2S_RX, + .stream_name = "Primary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.0", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_PRI_MI2S_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_PRI_MI2S_TX, + .stream_name = "Primary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.0", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_PRI_MI2S_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_RX, + .stream_name = "Secondary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_TX, + .stream_name = "Secondary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_RX, + .stream_name = "Tertiary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.2", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_TX, + .stream_name = "Tertiary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.2", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_RX, + .stream_name = "Quaternary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.3", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_TX, + .stream_name = "Quaternary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.3", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + }, +}; + +static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = { + /* Primary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_AUXPCM_RX, + .stream_name = "AUX PCM Playback", + .cpu_dai_name = "msm-dai-q6-auxpcm.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_AUXPCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + { + .name = LPASS_BE_AUXPCM_TX, + .stream_name = "AUX PCM Capture", + .cpu_dai_name = "msm-dai-q6-auxpcm.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_AUXPCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + /* Secondary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_SEC_AUXPCM_RX, + .stream_name = "Sec AUX PCM Playback", + .cpu_dai_name = "msm-dai-q6-auxpcm.2", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + { + .name = LPASS_BE_SEC_AUXPCM_TX, + .stream_name = "Sec AUX PCM Capture", + .cpu_dai_name = "msm-dai-q6-auxpcm.2", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .ops = &msm_aux_pcm_be_ops, + }, + /* Tertiary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_TERT_AUXPCM_RX, + .stream_name = "Tert AUX PCM Playback", + .cpu_dai_name = "msm-dai-q6-auxpcm.3", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_TERT_AUXPCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + { + .name = LPASS_BE_TERT_AUXPCM_TX, + .stream_name = "Tert AUX PCM Capture", + .cpu_dai_name = "msm-dai-q6-auxpcm.3", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_TERT_AUXPCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .ops = &msm_aux_pcm_be_ops, + }, + /* Quaternary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_QUAT_AUXPCM_RX, + .stream_name = "Quat AUX PCM Playback", + .cpu_dai_name = "msm-dai-q6-auxpcm.4", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUAT_AUXPCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + { + .name = LPASS_BE_QUAT_AUXPCM_TX, + .stream_name = "Quat AUX PCM Capture", + .cpu_dai_name = "msm-dai-q6-auxpcm.4", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUAT_AUXPCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .ops = &msm_aux_pcm_be_ops, + }, +}; + +static struct snd_soc_dai_link msm_ext_tasha_dai_links[ +ARRAY_SIZE(msm_ext_common_fe_dai) + +ARRAY_SIZE(msm_ext_tasha_fe_dai) + +ARRAY_SIZE(msm_ext_common_be_dai) + +ARRAY_SIZE(msm_ext_tasha_be_dai) + +ARRAY_SIZE(msm_mi2s_be_dai_links) + +ARRAY_SIZE(msm_auxpcm_be_dai_links)]; + +static struct snd_soc_dai_link msm_ext_tavil_dai_links[ +ARRAY_SIZE(msm_ext_common_fe_dai) + +ARRAY_SIZE(msm_ext_tavil_fe_dai) + +ARRAY_SIZE(msm_ext_common_be_dai) + +ARRAY_SIZE(msm_ext_tavil_be_dai) + +ARRAY_SIZE(msm_mi2s_be_dai_links) + +ARRAY_SIZE(msm_auxpcm_be_dai_links)]; + +/** + * populate_snd_card_dailinks - prepares dailink array and initializes card. + * + * @dev: device handle + * + * Returns card on success or NULL on failure. + */ +struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) +{ + struct snd_soc_card *card = &snd_soc_card_msm_card; + struct snd_soc_dai_link *msm_ext_dai_links = NULL; + int ret, len1, len2, len3, len4; + enum codec_variant codec_ver = 0; + + card->dev = dev; + ret = snd_soc_of_parse_card_name(card, "qcom,model"); + if (ret) { + dev_err(dev, "%s: parse card name failed, err:%d\n", + __func__, ret); + return NULL; + } + + if (strnstr(card->name, "tasha", strlen(card->name))) { + codec_ver = tasha_codec_ver(); + if (codec_ver == WCD9326) + card->name = "msmfalcon-tashalite-snd-card"; + + len1 = ARRAY_SIZE(msm_ext_common_fe_dai); + len2 = len1 + ARRAY_SIZE(msm_ext_tasha_fe_dai); + len3 = len2 + ARRAY_SIZE(msm_ext_common_be_dai); + memcpy(msm_ext_tasha_dai_links, msm_ext_common_fe_dai, + sizeof(msm_ext_common_fe_dai)); + memcpy(msm_ext_tasha_dai_links + len1, + msm_ext_tasha_fe_dai, sizeof(msm_ext_tasha_fe_dai)); + memcpy(msm_ext_tasha_dai_links + len2, + msm_ext_common_be_dai, sizeof(msm_ext_common_be_dai)); + memcpy(msm_ext_tasha_dai_links + len3, + msm_ext_tasha_be_dai, sizeof(msm_ext_tasha_be_dai)); + len4 = len3 + ARRAY_SIZE(msm_ext_tasha_be_dai); + if (of_property_read_bool(dev->of_node, + "qcom,mi2s-audio-intf")) { + memcpy(msm_ext_tasha_dai_links + len4, + msm_mi2s_be_dai_links, + sizeof(msm_mi2s_be_dai_links)); + len4 += ARRAY_SIZE(msm_mi2s_be_dai_links); + } + if (of_property_read_bool(dev->of_node, + "qcom,auxpcm-audio-intf")) { + memcpy(msm_ext_tasha_dai_links + len4, + msm_auxpcm_be_dai_links, + sizeof(msm_auxpcm_be_dai_links)); + len4 += ARRAY_SIZE(msm_auxpcm_be_dai_links); + } + msm_ext_dai_links = msm_ext_tasha_dai_links; + } else if (strnstr(card->name, "tavil", strlen(card->name))) { + len1 = ARRAY_SIZE(msm_ext_common_fe_dai); + len2 = len1 + ARRAY_SIZE(msm_ext_tavil_fe_dai); + len3 = len2 + ARRAY_SIZE(msm_ext_common_be_dai); + memcpy(msm_ext_tavil_dai_links, msm_ext_common_fe_dai, + sizeof(msm_ext_common_fe_dai)); + memcpy(msm_ext_tavil_dai_links + len1, + msm_ext_tavil_fe_dai, sizeof(msm_ext_tavil_fe_dai)); + memcpy(msm_ext_tavil_dai_links + len2, + msm_ext_common_be_dai, sizeof(msm_ext_common_be_dai)); + memcpy(msm_ext_tavil_dai_links + len3, + msm_ext_tavil_be_dai, sizeof(msm_ext_tavil_be_dai)); + len4 = len3 + ARRAY_SIZE(msm_ext_tavil_be_dai); + if (of_property_read_bool(dev->of_node, + "qcom,mi2s-audio-intf")) { + memcpy(msm_ext_tavil_dai_links + len4, + msm_mi2s_be_dai_links, + sizeof(msm_mi2s_be_dai_links)); + len4 += ARRAY_SIZE(msm_mi2s_be_dai_links); + } + if (of_property_read_bool(dev->of_node, + "qcom,auxpcm-audio-intf")) { + memcpy(msm_ext_tavil_dai_links + len4, + msm_auxpcm_be_dai_links, + sizeof(msm_auxpcm_be_dai_links)); + len4 += ARRAY_SIZE(msm_auxpcm_be_dai_links); + } + msm_ext_dai_links = msm_ext_tavil_dai_links; + } else { + dev_err(dev, "%s: failing as no matching card name\n", + __func__); + return NULL; + } + card->dai_link = msm_ext_dai_links; + card->num_links = len4; + card->dev = dev; + + return card; +} +EXPORT_SYMBOL(populate_snd_card_dailinks); diff --git a/sound/soc/msm/msmfalcon-external.c b/sound/soc/msm/msmfalcon-external.c new file mode 100644 index 000000000000..046c63bb73cf --- /dev/null +++ b/sound/soc/msm/msmfalcon-external.c @@ -0,0 +1,1700 @@ +/* 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/delay.h> +#include <linux/of_gpio.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <sound/soc.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/q6core.h> +#include <linux/qdsp6v2/audio_notifier.h> +#include "qdsp6v2/msm-pcm-routing-v2.h" +#include "msm-audio-pinctrl.h" +#include "msmfalcon-common.h" +#include "msmfalcon-external.h" +#include "../codecs/wcd9335.h" +#include "../codecs/wcd934x/wcd934x.h" +#include "../codecs/wcd934x/wcd934x-mbhc.h" + +#define MSMFALCON_SPK_ON 1 +#define MSMFALCON_SPK_OFF 0 + +#define WCD9XXX_MBHC_DEF_BUTTONS 8 +#define WCD9XXX_MBHC_DEF_RLOADS 5 +#define CODEC_EXT_CLK_RATE 9600000 +#define ADSP_STATE_READY_TIMEOUT_MS 3000 + +#define WSA8810_NAME_1 "wsa881x.20170211" +#define WSA8810_NAME_2 "wsa881x.20170212" + +static int msm_ext_spk_control = 1; +static struct wcd_mbhc_config *wcd_mbhc_cfg_ptr; + +struct msm_asoc_wcd93xx_codec { + void* (*get_afe_config_fn)(struct snd_soc_codec *codec, + enum afe_config_type config_type); + void (*mbhc_hs_detect_exit)(struct snd_soc_codec *codec); +}; + +static struct msm_asoc_wcd93xx_codec msm_codec_fn; +static struct platform_device *spdev; + +static bool is_initial_boot; + +static void *def_ext_mbhc_cal(void); + +enum { + SLIM_RX_0 = 0, + SLIM_RX_1, + SLIM_RX_2, + SLIM_RX_3, + SLIM_RX_4, + SLIM_RX_5, + SLIM_RX_6, + SLIM_RX_7, + SLIM_RX_MAX, +}; + +enum { + SLIM_TX_0 = 0, + SLIM_TX_1, + SLIM_TX_2, + SLIM_TX_3, + SLIM_TX_4, + SLIM_TX_5, + SLIM_TX_6, + SLIM_TX_7, + SLIM_TX_8, + SLIM_TX_MAX, +}; + +struct dev_config { + u32 sample_rate; + u32 bit_format; + u32 channels; +}; + +/* Default configuration of slimbus channels */ +static struct dev_config slim_rx_cfg[] = { + [SLIM_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_RX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_RX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_RX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_RX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_RX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_RX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_RX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, +}; + +static struct dev_config slim_tx_cfg[] = { + [SLIM_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_TX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_TX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_TX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_TX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_TX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_TX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_TX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, +}; + +static int msm_vi_feed_tx_ch = 2; +static const char *const slim_rx_ch_text[] = {"One", "Two"}; +static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four", + "Five", "Six", "Seven", + "Eight"}; +static const char *const vi_feed_ch_text[] = {"One", "Two"}; +static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE", + "S32_LE"}; +static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16", + "KHZ_32", "KHZ_44P1", "KHZ_48", + "KHZ_88P2", "KHZ_96", "KHZ_176P4", + "KHZ_192", "KHZ_352P8", "KHZ_384"}; +static const char *const spk_function_text[] = {"Off", "On"}; + +static SOC_ENUM_SINGLE_EXT_DECL(spk_func_en, spk_function_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_chs, slim_rx_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_chs, slim_tx_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_1_tx_chs, slim_tx_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_chs, slim_rx_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_chs, slim_rx_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(slim_2_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 int slim_get_sample_rate_val(int sample_rate) +{ + int sample_rate_val = 0; + + switch (sample_rate) { + case SAMPLING_RATE_8KHZ: + sample_rate_val = 0; + break; + case SAMPLING_RATE_16KHZ: + sample_rate_val = 1; + break; + case SAMPLING_RATE_32KHZ: + sample_rate_val = 2; + break; + case SAMPLING_RATE_44P1KHZ: + sample_rate_val = 3; + break; + case SAMPLING_RATE_48KHZ: + sample_rate_val = 4; + break; + case SAMPLING_RATE_88P2KHZ: + sample_rate_val = 5; + break; + case SAMPLING_RATE_96KHZ: + sample_rate_val = 6; + break; + case SAMPLING_RATE_176P4KHZ: + sample_rate_val = 7; + break; + case SAMPLING_RATE_192KHZ: + sample_rate_val = 8; + break; + case SAMPLING_RATE_352P8KHZ: + sample_rate_val = 9; + break; + case SAMPLING_RATE_384KHZ: + sample_rate_val = 10; + break; + default: + sample_rate_val = 4; + break; + } + return sample_rate_val; +} + +static int slim_get_sample_rate(int value) +{ + int sample_rate = 0; + + switch (value) { + case 0: + sample_rate = SAMPLING_RATE_8KHZ; + break; + case 1: + sample_rate = SAMPLING_RATE_16KHZ; + break; + case 2: + sample_rate = SAMPLING_RATE_32KHZ; + break; + case 3: + sample_rate = SAMPLING_RATE_44P1KHZ; + break; + case 4: + sample_rate = SAMPLING_RATE_48KHZ; + break; + case 5: + sample_rate = SAMPLING_RATE_88P2KHZ; + break; + case 6: + sample_rate = SAMPLING_RATE_96KHZ; + break; + case 7: + sample_rate = SAMPLING_RATE_176P4KHZ; + break; + case 8: + sample_rate = SAMPLING_RATE_192KHZ; + break; + case 9: + sample_rate = SAMPLING_RATE_352P8KHZ; + break; + case 10: + sample_rate = SAMPLING_RATE_384KHZ; + break; + default: + sample_rate = SAMPLING_RATE_48KHZ; + break; + } + return sample_rate; +} + +static int slim_get_bit_format_val(int bit_format) +{ + int val = 0; + + switch (bit_format) { + case SNDRV_PCM_FORMAT_S32_LE: + val = 3; + break; + case SNDRV_PCM_FORMAT_S24_3LE: + val = 2; + break; + case SNDRV_PCM_FORMAT_S24_LE: + val = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + val = 0; + break; + } + return val; +} + +static int slim_get_bit_format(int val) +{ + int bit_fmt = SNDRV_PCM_FORMAT_S16_LE; + + switch (val) { + case 0: + bit_fmt = SNDRV_PCM_FORMAT_S16_LE; + break; + case 1: + bit_fmt = SNDRV_PCM_FORMAT_S24_LE; + break; + case 2: + bit_fmt = SNDRV_PCM_FORMAT_S24_3LE; + break; + case 3: + bit_fmt = SNDRV_PCM_FORMAT_S32_LE; + break; + default: + bit_fmt = SNDRV_PCM_FORMAT_S16_LE; + break; + } + return bit_fmt; +} + +static int slim_get_port_idx(struct snd_kcontrol *kcontrol) +{ + int port_id = 0; + + if (strnstr(kcontrol->id.name, "SLIM_0_RX", sizeof("SLIM_0_RX"))) + port_id = SLIM_RX_0; + else if (strnstr(kcontrol->id.name, "SLIM_2_RX", sizeof("SLIM_2_RX"))) + port_id = SLIM_RX_2; + else if (strnstr(kcontrol->id.name, "SLIM_5_RX", sizeof("SLIM_5_RX"))) + port_id = SLIM_RX_5; + else if (strnstr(kcontrol->id.name, "SLIM_6_RX", sizeof("SLIM_6_RX"))) + port_id = SLIM_RX_6; + else if (strnstr(kcontrol->id.name, "SLIM_0_TX", sizeof("SLIM_0_TX"))) + port_id = SLIM_TX_0; + else if (strnstr(kcontrol->id.name, "SLIM_1_TX", sizeof("SLIM_1_TX"))) + port_id = SLIM_TX_1; + else { + pr_err("%s: unsupported channel: %s", + __func__, kcontrol->id.name); + return -EINVAL; + } + + return port_id; +} + +static int slim_rx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + ucontrol->value.enumerated.item[0] = + slim_get_sample_rate_val(slim_rx_cfg[ch_num].sample_rate); + + pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__, + ch_num, slim_rx_cfg[ch_num].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int slim_rx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + slim_rx_cfg[ch_num].sample_rate = + slim_get_sample_rate(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__, + ch_num, slim_rx_cfg[ch_num].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int slim_tx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + ucontrol->value.enumerated.item[0] = + slim_get_sample_rate_val(slim_tx_cfg[ch_num].sample_rate); + + pr_debug("%s: slim[%d]_tx_sample_rate = %d, item = %d\n", __func__, + ch_num, slim_tx_cfg[ch_num].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int slim_tx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int sample_rate = 0; + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + sample_rate = slim_get_sample_rate(ucontrol->value.enumerated.item[0]); + if (sample_rate == SAMPLING_RATE_44P1KHZ) { + pr_err("%s: Unsupported sample rate %d: for Tx path\n", + __func__, sample_rate); + return -EINVAL; + } + slim_tx_cfg[ch_num].sample_rate = sample_rate; + + pr_debug("%s: slim[%d]_tx_sample_rate = %d, value = %d\n", __func__, + ch_num, slim_tx_cfg[ch_num].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int slim_rx_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + ucontrol->value.enumerated.item[0] = + slim_get_bit_format_val(slim_rx_cfg[ch_num].bit_format); + + pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n", + __func__, ch_num, slim_rx_cfg[ch_num].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int slim_rx_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + slim_rx_cfg[ch_num].bit_format = + slim_get_bit_format(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n", + __func__, ch_num, slim_rx_cfg[ch_num].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int slim_tx_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + ucontrol->value.enumerated.item[0] = + slim_get_bit_format_val(slim_tx_cfg[ch_num].bit_format); + + pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n", + __func__, ch_num, slim_tx_cfg[ch_num].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int slim_tx_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + slim_tx_cfg[ch_num].bit_format = + slim_get_bit_format(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n", + __func__, ch_num, slim_tx_cfg[ch_num].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int msm_slim_rx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__, + ch_num, slim_rx_cfg[ch_num].channels); + ucontrol->value.enumerated.item[0] = slim_rx_cfg[ch_num].channels - 1; + + return 0; +} + +static int msm_slim_rx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + slim_rx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1; + pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__, + ch_num, slim_rx_cfg[ch_num].channels); + + return 1; +} + +static int msm_slim_tx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__, + ch_num, slim_tx_cfg[ch_num].channels); + ucontrol->value.enumerated.item[0] = slim_tx_cfg[ch_num].channels - 1; + + return 0; +} + +static int msm_slim_tx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = slim_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + slim_tx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1; + pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__, + ch_num, slim_tx_cfg[ch_num].channels); + + return 1; +} + +static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1; + pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__, + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1; + + pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch); + return 1; +} + +static void *def_ext_mbhc_cal(void) +{ + void *tavil_wcd_cal; + struct wcd_mbhc_btn_detect_cfg *btn_cfg; + u16 *btn_high; + + tavil_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS, + WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL); + if (!tavil_wcd_cal) + return NULL; + +#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(tavil_wcd_cal)->X) = (Y)) + S(v_hs_max, 1600); +#undef S +#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(tavil_wcd_cal)->X) = (Y)) + S(num_btn, WCD_MBHC_DEF_BUTTONS); +#undef S + + btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(tavil_wcd_cal); + btn_high = ((void *)&btn_cfg->_v_btn_low) + + (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn); + + btn_high[0] = 75; + btn_high[1] = 150; + btn_high[2] = 237; + btn_high[3] = 500; + btn_high[4] = 500; + btn_high[5] = 500; + btn_high[6] = 500; + btn_high[7] = 500; + + return tavil_wcd_cal; +} + +static inline int param_is_mask(int p) +{ + return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && + (p <= SNDRV_PCM_HW_PARAM_LAST_MASK); +} + +static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n) +{ + return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]); +} + + +static void msm_ext_control(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_codec_get_dapm(codec); + + pr_debug("%s: msm_ext_spk_control = %d", __func__, msm_ext_spk_control); + if (msm_ext_spk_control == MSMFALCON_SPK_ON) { + snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp"); + snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp"); + } else { + snd_soc_dapm_disable_pin(dapm, "Lineout_1 amp"); + snd_soc_dapm_disable_pin(dapm, "Lineout_3 amp"); + } + snd_soc_dapm_sync(dapm); +} + +static int msm_ext_get_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: msm_ext_spk_control = %d\n", + __func__, msm_ext_spk_control); + ucontrol->value.integer.value[0] = msm_ext_spk_control; + return 0; +} + +static int msm_ext_set_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + pr_debug("%s()\n", __func__); + if (msm_ext_spk_control == ucontrol->value.integer.value[0]) + return 0; + + msm_ext_spk_control = ucontrol->value.integer.value[0]; + msm_ext_control(codec); + return 1; +} + + +int msm_ext_enable_codec_mclk(struct snd_soc_codec *codec, int enable, + bool dapm) +{ + int ret; + + pr_debug("%s: enable = %d\n", __func__, enable); + + if (!strcmp(dev_name(codec->dev), "tasha_codec")) + ret = tasha_cdc_mclk_enable(codec, enable, dapm); + else if (!strcmp(dev_name(codec->dev), "tavil_codec")) + ret = tavil_cdc_mclk_enable(codec, enable); + else { + dev_err(codec->dev, "%s: unknown codec to enable ext clk\n", + __func__); + ret = -EINVAL; + } + return ret; +} + +static const struct snd_kcontrol_new msm_snd_controls[] = { + SOC_ENUM_EXT("Speaker Function", spk_func_en, msm_ext_get_spk, + msm_ext_set_spk), + SOC_ENUM_EXT("SLIM_0_RX Channels", slim_0_rx_chs, + msm_slim_rx_ch_get, msm_slim_rx_ch_put), + SOC_ENUM_EXT("SLIM_2_RX Channels", slim_2_rx_chs, + msm_slim_rx_ch_get, msm_slim_rx_ch_put), + SOC_ENUM_EXT("SLIM_0_TX Channels", slim_0_tx_chs, + msm_slim_tx_ch_get, msm_slim_tx_ch_put), + SOC_ENUM_EXT("SLIM_1_TX Channels", slim_1_tx_chs, + msm_slim_tx_ch_get, msm_slim_tx_ch_put), + SOC_ENUM_EXT("SLIM_5_RX Channels", slim_5_rx_chs, + msm_slim_rx_ch_get, msm_slim_rx_ch_put), + SOC_ENUM_EXT("SLIM_6_RX Channels", slim_6_rx_chs, + msm_slim_rx_ch_get, msm_slim_rx_ch_put), + SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs, + msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put), + SOC_ENUM_EXT("SLIM_0_RX Format", slim_0_rx_format, + slim_rx_bit_format_get, slim_rx_bit_format_put), + SOC_ENUM_EXT("SLIM_5_RX Format", slim_5_rx_format, + slim_rx_bit_format_get, slim_rx_bit_format_put), + SOC_ENUM_EXT("SLIM_6_RX Format", slim_6_rx_format, + slim_rx_bit_format_get, slim_rx_bit_format_put), + SOC_ENUM_EXT("SLIM_0_TX Format", slim_0_tx_format, + slim_tx_bit_format_get, slim_tx_bit_format_put), + SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate, + slim_rx_sample_rate_get, slim_rx_sample_rate_put), + SOC_ENUM_EXT("SLIM_2_RX SampleRate", slim_2_rx_sample_rate, + slim_rx_sample_rate_get, slim_rx_sample_rate_put), + SOC_ENUM_EXT("SLIM_0_TX SampleRate", slim_0_tx_sample_rate, + slim_tx_sample_rate_get, slim_tx_sample_rate_put), + SOC_ENUM_EXT("SLIM_5_RX SampleRate", slim_5_rx_sample_rate, + 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), +}; + +static int msm_slim_get_ch_from_beid(int32_t be_id) +{ + int ch_id = 0; + + switch (be_id) { + case MSM_BACKEND_DAI_SLIMBUS_0_RX: + ch_id = SLIM_RX_0; + break; + case MSM_BACKEND_DAI_SLIMBUS_1_RX: + ch_id = SLIM_RX_1; + break; + case MSM_BACKEND_DAI_SLIMBUS_2_RX: + ch_id = SLIM_RX_2; + break; + case MSM_BACKEND_DAI_SLIMBUS_3_RX: + ch_id = SLIM_RX_3; + break; + case MSM_BACKEND_DAI_SLIMBUS_4_RX: + ch_id = SLIM_RX_4; + break; + case MSM_BACKEND_DAI_SLIMBUS_6_RX: + ch_id = SLIM_RX_6; + break; + case MSM_BACKEND_DAI_SLIMBUS_0_TX: + ch_id = SLIM_TX_0; + break; + case MSM_BACKEND_DAI_SLIMBUS_3_TX: + ch_id = SLIM_TX_3; + break; + default: + ch_id = SLIM_RX_0; + break; + } + + return ch_id; +} + +static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit) +{ + if (bit >= SNDRV_MASK_MAX) + return; + if (param_is_mask(n)) { + struct snd_mask *m = param_to_mask(p, n); + + m->bits[0] = 0; + m->bits[1] = 0; + m->bits[bit >> 5] |= (1 << (bit & 31)); + } +} + +/** + * msm_ext_be_hw_params_fixup - updates settings of ALSA BE hw params. + * + * @rtd: runtime dailink instance + * @params: HW params of associated backend dailink. + * + * Returns 0 on success or rc on failure. + */ +int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_dai_link *dai_link = rtd->dai_link; + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + int rc = 0; + int idx; + void *config = NULL; + struct snd_soc_codec *codec = rtd->codec; + + pr_debug("%s: format = %d, rate = %d\n", + __func__, params_format(params), params_rate(params)); + + switch (dai_link->be_id) { + case MSM_BACKEND_DAI_SLIMBUS_0_RX: + case MSM_BACKEND_DAI_SLIMBUS_1_RX: + case MSM_BACKEND_DAI_SLIMBUS_2_RX: + case MSM_BACKEND_DAI_SLIMBUS_3_RX: + case MSM_BACKEND_DAI_SLIMBUS_4_RX: + case MSM_BACKEND_DAI_SLIMBUS_6_RX: + idx = msm_slim_get_ch_from_beid(dai_link->be_id); + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + slim_rx_cfg[idx].bit_format); + rate->min = rate->max = slim_rx_cfg[idx].sample_rate; + channels->min = channels->max = slim_rx_cfg[idx].channels; + break; + + case MSM_BACKEND_DAI_SLIMBUS_0_TX: + case MSM_BACKEND_DAI_SLIMBUS_3_TX: + idx = msm_slim_get_ch_from_beid(dai_link->be_id); + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + slim_tx_cfg[idx].bit_format); + rate->min = rate->max = slim_tx_cfg[idx].sample_rate; + channels->min = channels->max = slim_tx_cfg[idx].channels; + break; + + case MSM_BACKEND_DAI_SLIMBUS_1_TX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + slim_tx_cfg[1].bit_format); + rate->min = rate->max = slim_tx_cfg[1].sample_rate; + channels->min = channels->max = slim_tx_cfg[1].channels; + break; + + case MSM_BACKEND_DAI_SLIMBUS_4_TX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_FORMAT_S32_LE); + rate->min = rate->max = SAMPLING_RATE_8KHZ; + channels->min = channels->max = msm_vi_feed_tx_ch; + break; + + case MSM_BACKEND_DAI_SLIMBUS_5_RX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + slim_rx_cfg[5].bit_format); + rate->min = rate->max = slim_rx_cfg[5].sample_rate; + channels->min = channels->max = slim_rx_cfg[5].channels; + break; + + case MSM_BACKEND_DAI_SLIMBUS_5_TX: + rate->min = rate->max = SAMPLING_RATE_16KHZ; + channels->min = channels->max = 1; + + config = msm_codec_fn.get_afe_config_fn(codec, + AFE_SLIMBUS_SLAVE_PORT_CONFIG); + if (config) { + rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG, + config, SLIMBUS_5_TX); + if (rc) + pr_err("%s: Failed to set slimbus slave port config %d\n", + __func__, rc); + } + 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; + break; + + case MSM_BACKEND_DAI_SLIMBUS_7_TX: + rate->min = rate->max = slim_tx_cfg[SLIM_TX_7].sample_rate; + channels->min = channels->max = + slim_tx_cfg[SLIM_TX_7].channels; + break; + + case MSM_BACKEND_DAI_SLIMBUS_8_TX: + rate->min = rate->max = slim_tx_cfg[SLIM_TX_8].sample_rate; + channels->min = channels->max = + slim_tx_cfg[SLIM_TX_8].channels; + break; + + default: + rate->min = rate->max = SAMPLING_RATE_48KHZ; + break; + } + return rc; +} +EXPORT_SYMBOL(msm_ext_be_hw_params_fixup); + +/** + * msm_snd_hw_params - hw params ops of backend dailink. + * + * @substream: PCM stream of associated backend dailink. + * @params: HW params of associated backend dailink. + * + * Returns 0 on success or ret on failure. + */ +int msm_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai_link *dai_link = rtd->dai_link; + + int ret = 0; + u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; + u32 rx_ch_cnt = 0, tx_ch_cnt = 0; + u32 user_set_tx_ch = 0; + u32 rx_ch_count; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = snd_soc_dai_get_channel_map(codec_dai, + &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch); + if (ret < 0) { + pr_err("%s: failed to get codec chan map, err:%d\n", + __func__, ret); + goto err_ch_map; + } + if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_5_RX) { + pr_debug("%s: rx_5_ch=%d\n", __func__, + slim_rx_cfg[5].channels); + rx_ch_count = slim_rx_cfg[5].channels; + } else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_2_RX) { + pr_debug("%s: rx_2_ch=%d\n", __func__, + slim_rx_cfg[2].channels); + rx_ch_count = slim_rx_cfg[2].channels; + } else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_6_RX) { + pr_debug("%s: rx_6_ch=%d\n", __func__, + slim_rx_cfg[6].channels); + rx_ch_count = slim_rx_cfg[6].channels; + } else { + pr_debug("%s: rx_0_ch=%d\n", __func__, + slim_rx_cfg[0].channels); + rx_ch_count = slim_rx_cfg[0].channels; + } + ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, + rx_ch_count, rx_ch); + if (ret < 0) { + pr_err("%s: failed to set cpu chan map, err:%d\n", + __func__, ret); + goto err_ch_map; + } + } else { + pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__, + codec_dai->name, codec_dai->id, user_set_tx_ch); + ret = snd_soc_dai_get_channel_map(codec_dai, + &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch); + if (ret < 0) { + pr_err("%s: failed to get codec chan map\n, err:%d\n", + __func__, ret); + goto err_ch_map; + } + /* For <codec>_tx1 case */ + if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_0_TX) + user_set_tx_ch = slim_tx_cfg[0].channels; + /* For <codec>_tx3 case */ + else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_1_TX) + user_set_tx_ch = slim_tx_cfg[1].channels; + else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_4_TX) + user_set_tx_ch = msm_vi_feed_tx_ch; + else + user_set_tx_ch = tx_ch_cnt; + + pr_debug("%s: msm_slim_0_tx_ch(%d) user_set_tx_ch(%d) tx_ch_cnt(%d), be_id (%d)\n", + __func__, slim_tx_cfg[0].channels, user_set_tx_ch, + tx_ch_cnt, dai_link->be_id); + + ret = snd_soc_dai_set_channel_map(cpu_dai, + user_set_tx_ch, tx_ch, 0, 0); + if (ret < 0) + pr_err("%s: failed to set cpu chan map, err:%d\n", + __func__, ret); + } + +err_ch_map: + return ret; +} +EXPORT_SYMBOL(msm_snd_hw_params); + +/** + * msm_ext_slimbus_2_hw_params - hw params ops of slimbus_2 BE. + * + * @substream: PCM stream of associated backend dailink. + * @params: HW params of associated backend dailink. + * + * Returns 0 on success or ret on failure. + */ +int msm_ext_slimbus_2_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret = 0; + unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; + unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0; + unsigned int num_tx_ch = 0; + unsigned int num_rx_ch = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + num_rx_ch = params_channels(params); + pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__, + codec_dai->name, codec_dai->id, num_rx_ch); + ret = snd_soc_dai_get_channel_map(codec_dai, + &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch); + if (ret < 0) { + pr_err("%s: failed to get codec chan map, err:%d\n", + __func__, ret); + goto end; + } + ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, + num_rx_ch, rx_ch); + if (ret < 0) { + pr_err("%s: failed to set cpu chan map, err:%d\n", + __func__, ret); + goto end; + } + } else { + num_tx_ch = params_channels(params); + pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__, + codec_dai->name, codec_dai->id, num_tx_ch); + ret = snd_soc_dai_get_channel_map(codec_dai, + &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch); + if (ret < 0) { + pr_err("%s: failed to get codec chan map, err:%d\n", + __func__, ret); + goto end; + } + ret = snd_soc_dai_set_channel_map(cpu_dai, + num_tx_ch, tx_ch, 0, 0); + if (ret < 0) { + pr_err("%s: failed to set cpu chan map, err:%d\n", + __func__, ret); + goto end; + } + } +end: + return ret; +} +EXPORT_SYMBOL(msm_ext_slimbus_2_hw_params); + +/** + * msm_snd_cpe_hw_params - hw params ops of CPE backend. + * + * @substream: PCM stream of associated backend dailink. + * @params: HW params of associated backend dailink. + * + * Returns 0 on success or ret on failure. + */ +int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai_link *dai_link = rtd->dai_link; + int ret = 0; + u32 tx_ch[SLIM_MAX_TX_PORTS]; + u32 tx_ch_cnt = 0; + + if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) { + pr_err("%s: Invalid stream type %d\n", + __func__, substream->stream); + ret = -EINVAL; + goto end; + } + + pr_debug("%s: %s_tx_dai_id_%d\n", __func__, + codec_dai->name, codec_dai->id); + ret = snd_soc_dai_get_channel_map(codec_dai, + &tx_ch_cnt, tx_ch, NULL, NULL); + if (ret < 0) { + pr_err("%s: failed to get codec chan map\n, err:%d\n", + __func__, ret); + goto end; + } + + pr_debug("%s: tx_ch_cnt(%d) be_id %d\n", + __func__, tx_ch_cnt, dai_link->be_id); + + ret = snd_soc_dai_set_channel_map(cpu_dai, + tx_ch_cnt, tx_ch, 0, 0); + if (ret < 0) { + pr_err("%s: failed to set cpu chan map, err:%d\n", + __func__, ret); + goto end; + } +end: + return ret; +} +EXPORT_SYMBOL(msm_snd_cpe_hw_params); + +static int msm_afe_set_config(struct snd_soc_codec *codec) +{ + int rc; + void *config_data; + + pr_debug("%s: enter\n", __func__); + + if (!msm_codec_fn.get_afe_config_fn) { + dev_err(codec->dev, "%s: codec get afe config not init'ed\n", + __func__); + return -EINVAL; + } + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_CDC_REGISTERS_CONFIG); + if (config_data) { + rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0); + if (rc) { + pr_err("%s: Failed to set codec registers config %d\n", + __func__, rc); + return rc; + } + } + + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_CDC_REGISTER_PAGE_CONFIG); + if (config_data) { + rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data, + 0); + if (rc) + pr_err("%s: Failed to set cdc register page config\n", + __func__); + } + + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_SLIMBUS_SLAVE_CONFIG); + if (config_data) { + rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0); + if (rc) { + pr_err("%s: Failed to set slimbus slave config %d\n", + __func__, rc); + return rc; + } + } + + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_AANC_VERSION); + if (config_data) { + rc = afe_set_config(AFE_AANC_VERSION, config_data, 0); + if (rc) { + pr_err("%s: Failed to set AANC version %d\n", + __func__, rc); + return rc; + } + } + + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_CDC_CLIP_REGISTERS_CONFIG); + if (config_data) { + rc = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG, + config_data, 0); + if (rc) { + pr_err("%s: Failed to set clip registers %d\n", + __func__, rc); + return rc; + } + } + + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_CLIP_BANK_SEL); + if (config_data) { + rc = afe_set_config(AFE_CLIP_BANK_SEL, + config_data, 0); + if (rc) { + pr_err("%s: Failed to set AFE bank selection %d\n", + __func__, rc); + return rc; + } + } + + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_CDC_REGISTER_PAGE_CONFIG); + if (config_data) { + rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data, + 0); + if (rc) + pr_err("%s: Failed to set cdc register page config\n", + __func__); + } + + return 0; +} + +static void msm_afe_clear_config(void) +{ + afe_clear_config(AFE_CDC_REGISTERS_CONFIG); + afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG); +} + +static int msm_adsp_power_up_config(struct snd_soc_codec *codec) +{ + int ret = 0; + unsigned long timeout; + int adsp_ready = 0; + + timeout = jiffies + + msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS); + + do { + if (q6core_is_adsp_ready()) { + pr_debug("%s: ADSP Audio is ready\n", __func__); + adsp_ready = 1; + break; + } + /* + * ADSP will be coming up after subsystem restart and + * it might not be fully up when the control reaches + * here. So, wait for 50msec before checking ADSP state + */ + msleep(50); + } while (time_after(timeout, jiffies)); + + if (!adsp_ready) { + pr_err("%s: timed out waiting for ADSP Audio\n", __func__); + ret = -ETIMEDOUT; + goto err_fail; + } + + ret = msm_afe_set_config(codec); + if (ret) + pr_err("%s: Failed to set AFE config. err %d\n", + __func__, ret); + + return 0; + +err_fail: + return ret; +} + +static int msmfalcon_notifier_service_cb(struct notifier_block *this, + unsigned long opcode, void *ptr) +{ + int ret; + struct snd_soc_card *card = NULL; + const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_codec *codec; + + pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode); + + switch (opcode) { + case AUDIO_NOTIFIER_SERVICE_DOWN: + /* + * Use flag to ignore initial boot notifications + * On initial boot msm_adsp_power_up_config is + * called on init. There is no need to clear + * and set the config again on initial boot. + */ + if (is_initial_boot) + break; + msm_afe_clear_config(); + break; + case AUDIO_NOTIFIER_SERVICE_UP: + if (is_initial_boot) { + is_initial_boot = false; + break; + } + if (!spdev) + return -EINVAL; + + card = platform_get_drvdata(spdev); + rtd = snd_soc_get_pcm_runtime(card, be_dl_name); + if (!rtd) { + dev_err(card->dev, + "%s: snd_soc_get_pcm_runtime for %s failed!\n", + __func__, be_dl_name); + ret = -EINVAL; + goto done; + } + codec = rtd->codec; + + ret = msm_adsp_power_up_config(codec); + if (ret < 0) { + dev_err(card->dev, + "%s: msm_adsp_power_up_config failed ret = %d!\n", + __func__, ret); + goto done; + } + break; + default: + break; + } +done: + return NOTIFY_OK; +} + +static struct notifier_block service_nb = { + .notifier_call = msmfalcon_notifier_service_cb, + .priority = -INT_MAX, +}; + +static int msm_config_hph_en0_gpio(struct snd_soc_codec *codec, bool high) +{ + struct snd_soc_card *card = codec->component.card; + struct msm_asoc_mach_data *pdata; + int val; + + if (!card) + return 0; + + pdata = snd_soc_card_get_drvdata(card); + if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio)) + return 0; + + val = gpio_get_value_cansleep(pdata->hph_en0_gpio); + if ((!!val) == high) + return 0; + + gpio_direction_output(pdata->hph_en0_gpio, (int)high); + + return 1; +} + +static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec, + int enable, bool dapm) +{ + int ret = 0; + + if (!strcmp(dev_name(codec->dev), "tasha_codec")) + ret = tasha_cdc_mclk_tx_enable(codec, enable, dapm); + else { + dev_err(codec->dev, "%s: unknown codec to enable ext clk\n", + __func__); + ret = -EINVAL; + } + return ret; +} + +static int msm_ext_mclk_tx_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); + + pr_debug("%s: event = %d\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return msm_snd_enable_codec_ext_tx_clk(codec, 1, true); + case SND_SOC_DAPM_POST_PMD: + return msm_snd_enable_codec_ext_tx_clk(codec, 0, true); + } + return 0; +} + +static int msm_ext_mclk_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); + + pr_debug("%s: event = %d\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return msm_ext_enable_codec_mclk(codec, 1, true); + case SND_SOC_DAPM_POST_PMD: + return msm_ext_enable_codec_mclk(codec, 0, true); + } + return 0; +} + +static int msm_ext_prepare_hifi(struct msm_asoc_mach_data *pdata) +{ + int ret = 0; + + if (gpio_is_valid(pdata->hph_en1_gpio)) { + pr_debug("%s: hph_en1_gpio request %d\n", __func__, + pdata->hph_en1_gpio); + ret = gpio_request(pdata->hph_en1_gpio, "hph_en1_gpio"); + if (ret) { + pr_err("%s: hph_en1_gpio request failed, ret:%d\n", + __func__, ret); + goto err; + } + } + if (gpio_is_valid(pdata->hph_en0_gpio)) { + pr_debug("%s: hph_en0_gpio request %d\n", __func__, + pdata->hph_en0_gpio); + ret = gpio_request(pdata->hph_en0_gpio, "hph_en0_gpio"); + if (ret) + pr_err("%s: hph_en0_gpio request failed, ret:%d\n", + __func__, ret); + } + +err: + return ret; +} + +static const struct snd_soc_dapm_widget msm_dapm_widgets[] = { + + SND_SOC_DAPM_SUPPLY_S("MCLK", -1, SND_SOC_NOPM, 0, 0, + msm_ext_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("MCLK TX", -1, SND_SOC_NOPM, 0, 0, + msm_ext_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SPK("Lineout_1 amp", NULL), + SND_SOC_DAPM_SPK("Lineout_3 amp", NULL), + SND_SOC_DAPM_SPK("Lineout_2 amp", NULL), + SND_SOC_DAPM_SPK("Lineout_4 amp", NULL), + SND_SOC_DAPM_MIC("Handset Mic", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Secondary Mic", NULL), + SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL), + SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL), + SND_SOC_DAPM_MIC("Analog Mic4", NULL), + SND_SOC_DAPM_MIC("Analog Mic6", NULL), + SND_SOC_DAPM_MIC("Analog Mic7", NULL), + SND_SOC_DAPM_MIC("Analog Mic8", NULL), + + SND_SOC_DAPM_MIC("Digital Mic0", NULL), + SND_SOC_DAPM_MIC("Digital Mic1", NULL), + SND_SOC_DAPM_MIC("Digital Mic2", NULL), + SND_SOC_DAPM_MIC("Digital Mic3", NULL), + SND_SOC_DAPM_MIC("Digital Mic4", NULL), + SND_SOC_DAPM_MIC("Digital Mic5", NULL), + SND_SOC_DAPM_MIC("Digital Mic6", NULL), +}; + +static struct snd_soc_dapm_route wcd_audio_paths_tasha[] = { + {"MIC BIAS1", NULL, "MCLK TX"}, + {"MIC BIAS2", NULL, "MCLK TX"}, + {"MIC BIAS3", NULL, "MCLK TX"}, + {"MIC BIAS4", NULL, "MCLK TX"}, +}; + +static struct snd_soc_dapm_route wcd_audio_paths[] = { + {"MIC BIAS1", NULL, "MCLK"}, + {"MIC BIAS2", NULL, "MCLK"}, + {"MIC BIAS3", NULL, "MCLK"}, + {"MIC BIAS4", NULL, "MCLK"}, +}; + +/** + * msm_audrx_init - Audio init function of sound card instantiate. + * + * @rtd: runtime dailink instance + * + * Returns 0 on success or ret on failure. + */ +int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + void *config_data; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = + snd_soc_codec_get_dapm(codec); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_pcm_runtime *rtd_aux = rtd->card->rtd_aux; + struct snd_card *card; + struct snd_info_entry *entry; + struct msm_asoc_mach_data *pdata = + snd_soc_card_get_drvdata(rtd->card); + + /* Codec SLIMBUS configuration + * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13 + * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13 + * TX14, TX15, TX16 + */ + unsigned int rx_ch[TASHA_RX_MAX] = {144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156}; + unsigned int tx_ch[TASHA_TX_MAX] = {128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143}; + + pr_debug("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev)); + + rtd->pmdown_time = 0; + + ret = snd_soc_add_codec_controls(codec, msm_snd_controls, + ARRAY_SIZE(msm_snd_controls)); + if (ret < 0) { + pr_err("%s: add_codec_controls failed: %d\n", + __func__, ret); + return ret; + } + + snd_soc_dapm_new_controls(dapm, msm_dapm_widgets, + ARRAY_SIZE(msm_dapm_widgets)); + + if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) + snd_soc_dapm_add_routes(dapm, wcd_audio_paths_tasha, + ARRAY_SIZE(wcd_audio_paths_tasha)); + else + snd_soc_dapm_add_routes(dapm, wcd_audio_paths, + ARRAY_SIZE(wcd_audio_paths)); + + snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp"); + snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp"); + snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp"); + snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp"); + + snd_soc_dapm_ignore_suspend(dapm, "MADINPUT"); + snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT"); + snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); + snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); + snd_soc_dapm_ignore_suspend(dapm, "Secondary Mic"); + snd_soc_dapm_ignore_suspend(dapm, "Lineout_1 amp"); + snd_soc_dapm_ignore_suspend(dapm, "Lineout_3 amp"); + snd_soc_dapm_ignore_suspend(dapm, "Lineout_2 amp"); + snd_soc_dapm_ignore_suspend(dapm, "Lineout_4 amp"); + snd_soc_dapm_ignore_suspend(dapm, "ANCRight Headset Mic"); + snd_soc_dapm_ignore_suspend(dapm, "ANCLeft Headset Mic"); + snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0"); + snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1"); + snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2"); + snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3"); + snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4"); + snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5"); + snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4"); + snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6"); + snd_soc_dapm_ignore_suspend(dapm, "Analog Mic7"); + snd_soc_dapm_ignore_suspend(dapm, "Analog Mic8"); + + snd_soc_dapm_ignore_suspend(dapm, "EAR"); + snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1"); + snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2"); + snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3"); + snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC1"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC2"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC3"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC4"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC5"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC6"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC0"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC1"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC2"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC3"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC4"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC5"); + snd_soc_dapm_ignore_suspend(dapm, "ANC EAR"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HEADPHONE"); + snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT"); + snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT"); + snd_soc_dapm_ignore_suspend(dapm, "HPHL"); + snd_soc_dapm_ignore_suspend(dapm, "HPHR"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR"); + snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1"); + snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2"); + snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI"); + snd_soc_dapm_ignore_suspend(dapm, "VIINPUT"); + + snd_soc_dapm_sync(dapm); + snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch), + tx_ch, ARRAY_SIZE(rx_ch), rx_ch); + + if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) { + msm_codec_fn.get_afe_config_fn = tavil_get_afe_config; + } else { + msm_codec_fn.get_afe_config_fn = tasha_get_afe_config; + msm_codec_fn.mbhc_hs_detect_exit = tasha_mbhc_hs_detect_exit; + } + + ret = msm_adsp_power_up_config(codec); + if (ret) { + pr_err("%s: Failed to set AFE config %d\n", __func__, ret); + goto err_afe_cfg; + } + + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_AANC_VERSION); + if (config_data) { + ret = afe_set_config(AFE_AANC_VERSION, config_data, 0); + if (ret) { + pr_err("%s: Failed to set aanc version %d\n", + __func__, ret); + goto err_afe_cfg; + } + } + + if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) { + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_CDC_CLIP_REGISTERS_CONFIG); + if (config_data) { + ret = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG, + config_data, 0); + if (ret) { + pr_err("%s: Failed to set clip registers %d\n", + __func__, ret); + goto err_afe_cfg; + } + } + config_data = msm_codec_fn.get_afe_config_fn(codec, + AFE_CLIP_BANK_SEL); + if (config_data) { + ret = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0); + if (ret) { + pr_err("%s: Failed to set AFE bank selection %d\n", + __func__, ret); + goto err_afe_cfg; + } + } + } + + /* + * Send speaker configuration only for WSA8810. + * Defalut configuration is for WSA8815. + */ + if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) { + if (rtd_aux && rtd_aux->component) + if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) || + !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) { + tavil_set_spkr_mode(rtd->codec, SPKR_MODE_1); + tavil_set_spkr_gain_offset(rtd->codec, + RX_GAIN_OFFSET_M1P5_DB); + } + card = rtd->card->snd_card; + entry = snd_register_module_info(card->module, "codecs", + card->proc_root); + if (!entry) { + pr_debug("%s: Cannot create codecs module entry\n", + __func__); + pdata->codec_root = NULL; + goto done; + } + pdata->codec_root = entry; + tavil_codec_info_create_codec_entry(pdata->codec_root, codec); + } else { + if (rtd_aux && rtd_aux->component) + if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) || + !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) { + tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1); + tasha_set_spkr_gain_offset(rtd->codec, + RX_GAIN_OFFSET_M1P5_DB); + } + card = rtd->card->snd_card; + entry = snd_register_module_info(card->module, "codecs", + card->proc_root); + if (!entry) { + pr_debug("%s: Cannot create codecs module entry\n", + __func__); + ret = 0; + goto err_snd_module; + } + pdata->codec_root = entry; + tasha_codec_info_create_codec_entry(pdata->codec_root, codec); + tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, rtd->codec); + } + + wcd_mbhc_cfg_ptr->calibration = def_ext_mbhc_cal(); + if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) { + if (wcd_mbhc_cfg_ptr->calibration) { + pdata->codec = codec; + ret = tavil_mbhc_hs_detect(codec, wcd_mbhc_cfg_ptr); + if (ret < 0) + pr_err("%s: Failed to intialise mbhc %d\n", + __func__, ret); + } else { + pr_err("%s: wcd_mbhc_cfg calibration is NULL\n", + __func__); + ret = -ENOMEM; + goto err_mbhc_cal; + } + } else { + if (wcd_mbhc_cfg_ptr->calibration) { + pdata->codec = codec; + ret = tasha_mbhc_hs_detect(codec, wcd_mbhc_cfg_ptr); + if (ret < 0) + pr_err("%s: Failed to intialise mbhc %d\n", + __func__, ret); + } else { + pr_err("%s: wcd_mbhc_cfg calibration is NULL\n", + __func__); + ret = -ENOMEM; + goto err_mbhc_cal; + } + + } +done: + return 0; + +err_snd_module: +err_afe_cfg: +err_mbhc_cal: + return ret; +} +EXPORT_SYMBOL(msm_audrx_init); + +/** + * msm_ext_cdc_init - external codec machine specific init. + * + * @pdev: platform device handle + * @pdata: private data of machine driver + * @card: sound card pointer reference + * @mbhc_cfg: MBHC config reference + * + * Returns 0 on success or ret on failure. + */ +int msm_ext_cdc_init(struct platform_device *pdev, + struct msm_asoc_mach_data *pdata, + struct snd_soc_card **card, + struct wcd_mbhc_config *wcd_mbhc_cfg_ptr1) +{ + int ret = 0; + + wcd_mbhc_cfg_ptr = wcd_mbhc_cfg_ptr1; + pdev->id = 0; + wcd_mbhc_cfg_ptr->moisture_en = true; + wcd_mbhc_cfg_ptr->mbhc_micbias = MIC_BIAS_2; + wcd_mbhc_cfg_ptr->anc_micbias = MIC_BIAS_2; + wcd_mbhc_cfg_ptr->enable_anc_mic_detect = false; + + *card = populate_snd_card_dailinks(&pdev->dev); + if (!(*card)) { + dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__); + ret = -EPROBE_DEFER; + goto err; + } + (*card)->dev = &pdev->dev; + spdev = pdev; + platform_set_drvdata(pdev, *card); + snd_soc_card_set_drvdata(*card, pdata); + is_initial_boot = true; + ret = audio_notifier_register("msmfalcon", AUDIO_NOTIFIER_ADSP_DOMAIN, + &service_nb); + if (ret < 0) { + pr_err("%s: Audio notifier register failed ret = %d\n", + __func__, ret); + goto err; + } + pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node, + "qcom,hph-en1-gpio", 0); + if (!gpio_is_valid(pdata->hph_en1_gpio)) + pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node, + "qcom,hph-en1-gpio", 0); + if (!gpio_is_valid(pdata->hph_en1_gpio) && (!pdata->hph_en1_gpio_p)) { + dev_dbg(&pdev->dev, "property %s not detected in node %s", + "qcom,hph-en1-gpio", pdev->dev.of_node->full_name); + } + + pdata->hph_en0_gpio = of_get_named_gpio(pdev->dev.of_node, + "qcom,hph-en0-gpio", 0); + if (!gpio_is_valid(pdata->hph_en0_gpio)) + pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node, + "qcom,hph-en0-gpio", 0); + if (!gpio_is_valid(pdata->hph_en0_gpio) && (!pdata->hph_en0_gpio_p)) { + dev_dbg(&pdev->dev, "property %s not detected in node %s", + "qcom,hph-en0-gpio", pdev->dev.of_node->full_name); + } + + ret = msm_ext_prepare_hifi(pdata); + if (ret) { + dev_dbg(&pdev->dev, "msm_ext_prepare_hifi failed (%d)\n", + ret); + ret = 0; + } +err: + return ret; +} +EXPORT_SYMBOL(msm_ext_cdc_init); diff --git a/sound/soc/msm/msmfalcon-external.h b/sound/soc/msm/msmfalcon-external.h new file mode 100644 index 000000000000..24aa7ea53a09 --- /dev/null +++ b/sound/soc/msm/msmfalcon-external.h @@ -0,0 +1,44 @@ +/* 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 __MSMFALCON_EXTERNAL +#define __MSMFALCON_EXTERNAL + +int msm_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +int msm_ext_slimbus_2_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); +int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); +int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); +int msm_audrx_init(struct snd_soc_pcm_runtime *rtd); +int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +struct snd_soc_card *populate_snd_card_dailinks(struct device *dev); +int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); +#ifdef CONFIG_SND_SOC_EXT_CODEC +int msm_ext_cdc_init(struct platform_device *, struct msm_asoc_mach_data *, + struct snd_soc_card **, struct wcd_mbhc_config *); +#else +inline int msm_ext_cdc_init(struct platform_device *pdev, + struct msm_asoc_mach_data *pdata, + struct snd_soc_card **card, + struct wcd_mbhc_config *wcd_mbhc_cfg_ptr1) +{ + return 0; +} +#endif +#endif diff --git a/sound/soc/msm/msmfalcon-internal.c b/sound/soc/msm/msmfalcon-internal.c new file mode 100644 index 000000000000..3a8b88cdfb64 --- /dev/null +++ b/sound/soc/msm/msmfalcon-internal.c @@ -0,0 +1,2453 @@ +/* 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/of_gpio.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <sound/pcm_params.h> +#include "qdsp6v2/msm-pcm-routing-v2.h" +#include "msm-audio-pinctrl.h" +#include "msmfalcon-common.h" +#include "../codecs/msm8x16/msm8x16-wcd.h" + +#define __CHIPSET__ "MSMFALCON " +#define MSM_DAILINK_NAME(name) (__CHIPSET__#name) + +#define DEFAULT_MCLK_RATE 9600000 +#define NATIVE_MCLK_RATE 11289600 + +#define WCD_MBHC_DEF_RLOADS 5 + +enum { + INT0_MI2S = 0, + INT1_MI2S, + INT2_MI2S, + INT3_MI2S, + INT4_MI2S, + INT5_MI2S, + INT6_MI2S, + INT_MI2S_MAX, +}; + +static struct afe_clk_set int_mi2s_clk[INT_MI2S_MAX] = { + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_INT0_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_INT1_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_INT2_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_INT3_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_INT4_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_INT5_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, + { + AFE_API_VERSION_I2S_CONFIG, + Q6AFE_LPASS_CLK_ID_INT6_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, + }, +}; + +struct dev_config { + u32 sample_rate; + u32 bit_format; + u32 channels; +}; + +/* Default configuration of MI2S channels */ +static struct dev_config int_mi2s_cfg[] = { + [INT0_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, + [INT1_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [INT2_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [INT3_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [INT4_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, + [INT5_MI2S] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, + [INT6_MI2S] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, +}; + +static char const *int_mi2s_rate_text[] = {"KHZ_8", "KHZ_16", + "KHZ_32", "KHZ_44P1", "KHZ_48", + "KHZ_96", "KHZ_192"}; +static const char *const int_mi2s_ch_text[] = {"One", "Two"}; +static const char *const int_mi2s_tx_ch_text[] = {"One", "Two", + "Three", "Four"}; +static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"}; +static const char *const loopback_mclk_text[] = {"DISABLE", "ENABLE"}; + +static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_sample_rate, int_mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_chs, int_mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(int2_mi2s_tx_sample_rate, int_mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(int2_mi2s_tx_chs, int_mi2s_tx_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(int2_mi2s_tx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(int3_mi2s_tx_sample_rate, int_mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(int3_mi2s_tx_chs, int_mi2s_tx_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(int3_mi2s_tx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_sample_rate, int_mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_chs, int_mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(int5_mi2s_tx_chs, int_mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(loopback_mclk_en, loopback_mclk_text); + +static int msm_dmic_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +static int msm_int_enable_dig_cdc_clk(struct snd_soc_codec *codec, int enable, + bool dapm); +static int msm_int_mclk0_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); +static int msm_int_mi2s_snd_startup(struct snd_pcm_substream *substream); +static void msm_int_mi2s_snd_shutdown(struct snd_pcm_substream *substream); + +static struct wcd_mbhc_config *mbhc_cfg_ptr; + +static int int_mi2s_get_bit_format_val(int bit_format) +{ + int val = 0; + + switch (bit_format) { + case SNDRV_PCM_FORMAT_S24_3LE: + val = 2; + break; + case SNDRV_PCM_FORMAT_S24_LE: + val = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + val = 0; + break; + } + return val; +} + +static int int_mi2s_get_bit_format(int val) +{ + int bit_fmt = SNDRV_PCM_FORMAT_S16_LE; + + switch (val) { + case 0: + bit_fmt = SNDRV_PCM_FORMAT_S16_LE; + break; + case 1: + bit_fmt = SNDRV_PCM_FORMAT_S24_LE; + break; + case 2: + bit_fmt = SNDRV_PCM_FORMAT_S24_3LE; + break; + default: + bit_fmt = SNDRV_PCM_FORMAT_S16_LE; + break; + } + return bit_fmt; +} + +static int int_mi2s_get_port_idx(struct snd_kcontrol *kcontrol) +{ + int port_id = 0; + + if (strnstr(kcontrol->id.name, "INT0_MI2S", sizeof("INT0_MI2S"))) + port_id = INT0_MI2S; + else if (strnstr(kcontrol->id.name, "INT2_MI2S", sizeof("INT2_MI2S"))) + port_id = INT2_MI2S; + else if (strnstr(kcontrol->id.name, "INT3_MI2S", sizeof("INT3_MI2S"))) + port_id = INT3_MI2S; + else if (strnstr(kcontrol->id.name, "INT4_MI2S", sizeof("INT4_MI2S"))) + port_id = INT4_MI2S; + else { + pr_err("%s: unsupported channel: %s", + __func__, kcontrol->id.name); + return -EINVAL; + } + + return port_id; +} + +static int int_mi2s_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = int_mi2s_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + ucontrol->value.enumerated.item[0] = + int_mi2s_get_bit_format_val(int_mi2s_cfg[ch_num].bit_format); + + pr_debug("%s: int_mi2s[%d]_bit_format = %d, ucontrol value = %d\n", + __func__, ch_num, int_mi2s_cfg[ch_num].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int int_mi2s_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ch_num = int_mi2s_get_port_idx(kcontrol); + + if (ch_num < 0) + return ch_num; + + int_mi2s_cfg[ch_num].bit_format = + int_mi2s_get_bit_format(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: int_mi2s[%d]_rx_bit_format = %d, ucontrol value = %d\n", + __func__, ch_num, int_mi2s_cfg[ch_num].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static inline int param_is_mask(int p) +{ + return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && + (p <= SNDRV_PCM_HW_PARAM_LAST_MASK); +} + +static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, + int n) +{ + return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]); +} + +static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit) +{ + if (bit >= SNDRV_MASK_MAX) + return; + if (param_is_mask(n)) { + struct snd_mask *m = param_to_mask(p, n); + + m->bits[0] = 0; + m->bits[1] = 0; + m->bits[bit >> 5] |= (1 << (bit & 31)); + } +} + +static int int_mi2s_get_sample_rate_val(int sample_rate) +{ + int sample_rate_val; + + switch (sample_rate) { + case SAMPLING_RATE_8KHZ: + sample_rate_val = 0; + break; + case SAMPLING_RATE_16KHZ: + sample_rate_val = 1; + break; + case SAMPLING_RATE_32KHZ: + sample_rate_val = 2; + break; + case SAMPLING_RATE_44P1KHZ: + sample_rate_val = 3; + break; + case SAMPLING_RATE_48KHZ: + sample_rate_val = 4; + break; + case SAMPLING_RATE_96KHZ: + sample_rate_val = 5; + break; + case SAMPLING_RATE_192KHZ: + sample_rate_val = 6; + break; + default: + sample_rate_val = 4; + break; + } + return sample_rate_val; +} + +static int int_mi2s_get_sample_rate(int value) +{ + int sample_rate; + + switch (value) { + case 0: + sample_rate = SAMPLING_RATE_8KHZ; + break; + case 1: + sample_rate = SAMPLING_RATE_16KHZ; + break; + case 2: + sample_rate = SAMPLING_RATE_32KHZ; + break; + case 3: + sample_rate = SAMPLING_RATE_44P1KHZ; + break; + case 4: + sample_rate = SAMPLING_RATE_48KHZ; + break; + case 5: + sample_rate = SAMPLING_RATE_96KHZ; + break; + case 6: + sample_rate = SAMPLING_RATE_192KHZ; + break; + default: + sample_rate = SAMPLING_RATE_48KHZ; + break; + } + return sample_rate; +} + +static int int_mi2s_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = int_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + int_mi2s_cfg[idx].sample_rate = + int_mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_sample_rate = %d, item = %d\n", __func__, + idx, int_mi2s_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int int_mi2s_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = int_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + int_mi2s_get_sample_rate_val(int_mi2s_cfg[idx].sample_rate); + + pr_debug("%s: idx[%d]_sample_rate = %d, item = %d\n", __func__, + idx, int_mi2s_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int int_mi2s_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = int_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + pr_debug("%s: int_mi2s_[%d]_rx_ch = %d\n", __func__, + idx, int_mi2s_cfg[idx].channels); + ucontrol->value.enumerated.item[0] = int_mi2s_cfg[idx].channels - 1; + + return 0; +} + +static int int_mi2s_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = int_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + int_mi2s_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1; + pr_debug("%s: int_mi2s_[%d]_ch = %d\n", __func__, + idx, int_mi2s_cfg[idx].channels); + + return 1; +} + +static const struct snd_soc_dapm_widget msm_int_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY_S("INT_MCLK0", -1, SND_SOC_NOPM, 0, 0, + msm_int_mclk0_event, SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MIC("Handset Mic", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Secondary Mic", NULL), + SND_SOC_DAPM_MIC("Digital Mic1", msm_dmic_event), + SND_SOC_DAPM_MIC("Digital Mic2", msm_dmic_event), + SND_SOC_DAPM_MIC("Digital Mic3", msm_dmic_event), + SND_SOC_DAPM_MIC("Digital Mic4", msm_dmic_event), +}; + +static int msm_config_hph_compander_gpio(bool enable) +{ + int ret = 0; + + pr_debug("%s: %s HPH Compander\n", __func__, + enable ? "Enable" : "Disable"); + + if (enable) { + ret = msm_gpioset_activate(CLIENT_WCD, "comp_gpio"); + if (ret) { + pr_err("%s: gpio set cannot be activated %s\n", + __func__, "comp_gpio"); + goto done; + } + } else { + ret = msm_gpioset_suspend(CLIENT_WCD, "comp_gpio"); + if (ret) { + pr_err("%s: gpio set cannot be de-activated %s\n", + __func__, "comp_gpio"); + goto done; + } + } + +done: + return ret; +} + +static int is_ext_spk_gpio_support(struct platform_device *pdev, + struct msm_asoc_mach_data *pdata) +{ + const char *spk_ext_pa = "qcom,msm-spk-ext-pa"; + + pr_debug("%s:Enter\n", __func__); + + pdata->spk_ext_pa_gpio = of_get_named_gpio(pdev->dev.of_node, + spk_ext_pa, 0); + + if (pdata->spk_ext_pa_gpio < 0) { + dev_dbg(&pdev->dev, + "%s: missing %s in dt node\n", __func__, spk_ext_pa); + } else { + if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) { + pr_err("%s: Invalid external speaker gpio: %d", + __func__, pdata->spk_ext_pa_gpio); + return -EINVAL; + } + } + return 0; +} + +static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) +{ + struct snd_soc_card *card = codec->component.card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + int ret; + + if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) { + pr_err("%s: Invalid gpio: %d\n", __func__, + pdata->spk_ext_pa_gpio); + return false; + } + + pr_debug("%s: %s external speaker PA\n", __func__, + enable ? "Enable" : "Disable"); + + if (enable) { + ret = msm_gpioset_activate(CLIENT_WCD, "ext_spk_gpio"); + if (ret) { + pr_err("%s: gpio set cannot be de-activated %s\n", + __func__, "ext_spk_gpio"); + return ret; + } + gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable); + } else { + gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable); + ret = msm_gpioset_suspend(CLIENT_WCD, "ext_spk_gpio"); + if (ret) { + pr_err("%s: gpio set cannot be de-activated %s\n", + __func__, "ext_spk_gpio"); + return ret; + } + } + return 0; +} + +static int int_mi2s_get_idx_from_beid(int32_t be_id) +{ + int idx = 0; + + switch (be_id) { + case MSM_BACKEND_DAI_INT0_MI2S_RX: + idx = INT0_MI2S; + break; + case MSM_BACKEND_DAI_INT2_MI2S_TX: + idx = INT2_MI2S; + break; + case MSM_BACKEND_DAI_INT3_MI2S_TX: + idx = INT3_MI2S; + break; + case MSM_BACKEND_DAI_INT4_MI2S_RX: + idx = INT4_MI2S; + break; + case MSM_BACKEND_DAI_INT5_MI2S_TX: + idx = INT5_MI2S; + break; + default: + idx = INT0_MI2S; + break; + } + + return idx; +} + +static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + pr_debug("%s()\n", __func__); + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + return 0; +} + +int int_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_dai_link *dai_link = rtd->dai_link; + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + int idx; + + pr_debug("%s: format = %d, rate = %d\n", + __func__, params_format(params), params_rate(params)); + + switch (dai_link->be_id) { + case MSM_BACKEND_DAI_INT0_MI2S_RX: + case MSM_BACKEND_DAI_INT2_MI2S_TX: + case MSM_BACKEND_DAI_INT3_MI2S_TX: + case MSM_BACKEND_DAI_INT4_MI2S_RX: + case MSM_BACKEND_DAI_INT5_MI2S_TX: + idx = int_mi2s_get_idx_from_beid(dai_link->be_id); + rate->min = rate->max = int_mi2s_cfg[idx].sample_rate; + channels->min = channels->max = + int_mi2s_cfg[idx].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + int_mi2s_cfg[idx].bit_format); + break; + default: + rate->min = rate->max = SAMPLING_RATE_48KHZ; + break; + } + return 0; +} + +static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = + (int_mi2s_cfg[INT5_MI2S].channels/2 - 1); + pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__, + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int_mi2s_cfg[INT5_MI2S].channels = + roundup_pow_of_two(ucontrol->value.integer.value[0] + 2); + + pr_debug("%s: msm_vi_feed_tx_ch = %d\n", + __func__, int_mi2s_cfg[INT5_MI2S].channels); + return 1; +} + +static int msm_int_enable_dig_cdc_clk(struct snd_soc_codec *codec, + int enable, bool dapm) +{ + int ret = 0; + struct msm_asoc_mach_data *pdata = NULL; + int clk_freq_in_hz; + bool int_mclk0_freq_chg = false; + + pdata = snd_soc_card_get_drvdata(codec->component.card); + pr_debug("%s: enable %d mclk ref counter %d\n", + __func__, enable, + atomic_read(&pdata->int_mclk0_rsc_ref)); + if (enable) { + if (int_mi2s_cfg[INT0_MI2S].sample_rate == + SAMPLING_RATE_44P1KHZ) + clk_freq_in_hz = NATIVE_MCLK_RATE; + else + clk_freq_in_hz = pdata->mclk_freq; + + if (pdata->digital_cdc_core_clk.clk_freq_in_hz + != clk_freq_in_hz) + int_mclk0_freq_chg = true; + if (!atomic_read(&pdata->int_mclk0_rsc_ref) || + int_mclk0_freq_chg) { + cancel_delayed_work_sync( + &pdata->disable_int_mclk0_work); + mutex_lock(&pdata->cdc_int_mclk0_mutex); + if (atomic_read(&pdata->int_mclk0_enabled) == false || + int_mclk0_freq_chg) { + pdata->digital_cdc_core_clk.clk_freq_in_hz = + clk_freq_in_hz; + pdata->digital_cdc_core_clk.enable = 1; + ret = afe_set_lpass_clock_v2( + AFE_PORT_ID_INT0_MI2S_RX, + &pdata->digital_cdc_core_clk); + if (ret < 0) { + pr_err("%s: failed to enable CCLK\n", + __func__); + mutex_unlock( + &pdata->cdc_int_mclk0_mutex); + return ret; + } + pr_debug("enabled digital codec core clk\n"); + atomic_set(&pdata->int_mclk0_enabled, true); + } + mutex_unlock(&pdata->cdc_int_mclk0_mutex); + } + atomic_inc(&pdata->int_mclk0_rsc_ref); + } else { + cancel_delayed_work_sync(&pdata->disable_int_mclk0_work); + mutex_lock(&pdata->cdc_int_mclk0_mutex); + if (atomic_read(&pdata->int_mclk0_enabled) == true) { + pdata->digital_cdc_core_clk.enable = 0; + ret = afe_set_lpass_clock_v2( + AFE_PORT_ID_INT0_MI2S_RX, + &pdata->digital_cdc_core_clk); + if (ret < 0) + pr_err("%s: failed to disable CCLK\n", + __func__); + atomic_set(&pdata->int_mclk0_enabled, false); + } + mutex_unlock(&pdata->cdc_int_mclk0_mutex); + } + return ret; +} + +static int loopback_mclk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s\n", __func__); + return 0; +} + +static int loopback_mclk_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = -EINVAL; + struct msm_asoc_mach_data *pdata = NULL; + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + + pdata = snd_soc_card_get_drvdata(codec->component.card); + pr_debug("%s: mclk_rsc_ref %d enable %ld\n", + __func__, atomic_read(&pdata->int_mclk0_rsc_ref), + ucontrol->value.integer.value[0]); + switch (ucontrol->value.integer.value[0]) { + case 1: + ret = msm_gpioset_activate(CLIENT_WCD, "int_pdm"); + if (ret) { + pr_err("%s: failed to enable the pri gpios: %d\n", + __func__, ret); + break; + } + mutex_lock(&pdata->cdc_int_mclk0_mutex); + if ((!atomic_read(&pdata->int_mclk0_rsc_ref)) && + (!atomic_read(&pdata->int_mclk0_enabled))) { + pdata->digital_cdc_core_clk.enable = 1; + ret = afe_set_lpass_clock_v2( + AFE_PORT_ID_INT0_MI2S_RX, + &pdata->digital_cdc_core_clk); + if (ret < 0) { + pr_err("%s: failed to enable the MCLK: %d\n", + __func__, ret); + mutex_unlock(&pdata->cdc_int_mclk0_mutex); + ret = msm_gpioset_suspend(CLIENT_WCD, + "int_pdm"); + if (ret) + pr_err("%s: failed to disable the pri gpios: %d\n", + __func__, ret); + break; + } + atomic_set(&pdata->int_mclk0_enabled, true); + } + mutex_unlock(&pdata->cdc_int_mclk0_mutex); + atomic_inc(&pdata->int_mclk0_rsc_ref); + msm8x16_wcd_mclk_enable(codec, 1, true); + break; + case 0: + if (atomic_read(&pdata->int_mclk0_rsc_ref) <= 0) + break; + msm8x16_wcd_mclk_enable(codec, 0, true); + mutex_lock(&pdata->cdc_int_mclk0_mutex); + if ((!atomic_dec_return(&pdata->int_mclk0_rsc_ref)) && + (atomic_read(&pdata->int_mclk0_enabled))) { + pdata->digital_cdc_core_clk.enable = 0; + ret = afe_set_lpass_clock_v2( + AFE_PORT_ID_INT0_MI2S_RX, + &pdata->digital_cdc_core_clk); + if (ret < 0) { + pr_err("%s: failed to disable the CCLK: %d\n", + __func__, ret); + mutex_unlock(&pdata->cdc_int_mclk0_mutex); + break; + } + atomic_set(&pdata->int_mclk0_enabled, false); + } + mutex_unlock(&pdata->cdc_int_mclk0_mutex); + ret = msm_gpioset_suspend(CLIENT_WCD, "int_pdm"); + if (ret) + pr_err("%s: failed to disable the pri gpios: %d\n", + __func__, ret); + break; + default: + pr_err("%s: Unexpected input value\n", __func__); + break; + } + return ret; +} + +static const struct snd_kcontrol_new msm_snd_controls[] = { + SOC_ENUM_EXT("INT0_MI2S_RX Format", int0_mi2s_rx_format, + int_mi2s_bit_format_get, int_mi2s_bit_format_put), + SOC_ENUM_EXT("INT2_MI2S_TX Format", int2_mi2s_tx_format, + int_mi2s_bit_format_get, int_mi2s_bit_format_put), + SOC_ENUM_EXT("INT3_MI2S_TX Format", int3_mi2s_tx_format, + int_mi2s_bit_format_get, int_mi2s_bit_format_put), + SOC_ENUM_EXT("INT0_MI2S_RX SampleRate", int0_mi2s_rx_sample_rate, + int_mi2s_sample_rate_get, + int_mi2s_sample_rate_put), + SOC_ENUM_EXT("INT2_MI2S_TX SampleRate", int2_mi2s_tx_sample_rate, + int_mi2s_sample_rate_get, + int_mi2s_sample_rate_put), + SOC_ENUM_EXT("INT3_MI2S_TX SampleRate", int3_mi2s_tx_sample_rate, + int_mi2s_sample_rate_get, + int_mi2s_sample_rate_put), + SOC_ENUM_EXT("INT0_MI2S_RX SampleRate", int0_mi2s_rx_sample_rate, + int_mi2s_sample_rate_get, + int_mi2s_sample_rate_put), + SOC_ENUM_EXT("INT2_MI2S_TX SampleRate", int2_mi2s_tx_sample_rate, + int_mi2s_sample_rate_get, + int_mi2s_sample_rate_put), + SOC_ENUM_EXT("INT3_MI2S_TX SampleRate", int3_mi2s_tx_sample_rate, + int_mi2s_sample_rate_get, + int_mi2s_sample_rate_put), + SOC_ENUM_EXT("INT0_MI2S_RX Channels", int0_mi2s_rx_chs, + int_mi2s_ch_get, int_mi2s_ch_put), + SOC_ENUM_EXT("INT2_MI2S_TX Channels", int2_mi2s_tx_chs, + int_mi2s_ch_get, int_mi2s_ch_put), + SOC_ENUM_EXT("INT3_MI2S_TX Channels", int3_mi2s_tx_chs, + int_mi2s_ch_get, int_mi2s_ch_put), + SOC_ENUM_EXT("Loopback MCLK", loopback_mclk_en, + loopback_mclk_get, loopback_mclk_put), +}; + +static const struct snd_kcontrol_new msm_swr_controls[] = { + SOC_ENUM_EXT("INT4_MI2S_RX Format", int4_mi2s_rx_format, + int_mi2s_bit_format_get, int_mi2s_bit_format_put), + SOC_ENUM_EXT("INT4_MI2S_RX SampleRate", int4_mi2s_rx_sample_rate, + int_mi2s_sample_rate_get, + int_mi2s_sample_rate_put), + SOC_ENUM_EXT("INT4_MI2S_RX SampleRate", int4_mi2s_rx_sample_rate, + int_mi2s_sample_rate_get, + int_mi2s_sample_rate_put), + SOC_ENUM_EXT("INT4_MI2S_RX Channels", int4_mi2s_rx_chs, + int_mi2s_ch_get, int_mi2s_ch_put), + SOC_ENUM_EXT("VI_FEED_TX Channels", int5_mi2s_tx_chs, + msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put), +}; + +static int msm_dmic_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct msm_asoc_mach_data *pdata = NULL; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + int ret = 0; + + pdata = snd_soc_card_get_drvdata(codec->component.card); + pr_debug("%s: event = %d\n", __func__, event); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = msm_gpioset_activate(CLIENT_WCD, "dmic_gpio"); + if (ret < 0) { + pr_err("%s: gpio set cannot be activated %sd", + __func__, "dmic_gpio"); + return ret; + } + break; + case SND_SOC_DAPM_POST_PMD: + ret = msm_gpioset_suspend(CLIENT_WCD, "dmic_gpio"); + if (ret < 0) { + pr_err("%s: gpio set cannot be de-activated %sd", + __func__, "dmic_gpio"); + return ret; + } + break; + default: + pr_err("%s: invalid DAPM event %d\n", __func__, event); + return -EINVAL; + } + return 0; +} + +static int msm_int_mclk0_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct msm_asoc_mach_data *pdata = NULL; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + int ret = 0; + + pdata = snd_soc_card_get_drvdata(codec->component.card); + pr_debug("%s: event = %d\n", __func__, event); + switch (event) { + case SND_SOC_DAPM_POST_PMD: + pr_debug("%s: mclk_res_ref = %d\n", + __func__, atomic_read(&pdata->int_mclk0_rsc_ref)); + ret = msm_gpioset_suspend(CLIENT_WCD, "int_pdm"); + if (ret < 0) { + pr_err("%s: gpio set cannot be de-activated %sd", + __func__, "int_pdm"); + return ret; + } + if (atomic_read(&pdata->int_mclk0_rsc_ref) == 0) { + pr_debug("%s: disabling MCLK\n", __func__); + /* disable the codec mclk config*/ + msm8x16_wcd_mclk_enable(codec, 0, true); + msm_int_enable_dig_cdc_clk(codec, 0, true); + } + break; + default: + pr_err("%s: invalid DAPM event %d\n", __func__, event); + return -EINVAL; + } + return 0; +} + +static int int_mi2s_get_port_id(int be_id) +{ + int afe_port_id; + + switch (be_id) { + case MSM_BACKEND_DAI_INT0_MI2S_RX: + afe_port_id = AFE_PORT_ID_INT0_MI2S_RX; + break; + case MSM_BACKEND_DAI_INT2_MI2S_TX: + afe_port_id = AFE_PORT_ID_INT2_MI2S_TX; + break; + case MSM_BACKEND_DAI_INT3_MI2S_TX: + afe_port_id = AFE_PORT_ID_INT3_MI2S_TX; + break; + case MSM_BACKEND_DAI_INT4_MI2S_RX: + afe_port_id = AFE_PORT_ID_INT4_MI2S_RX; + break; + case MSM_BACKEND_DAI_INT5_MI2S_TX: + afe_port_id = AFE_PORT_ID_INT5_MI2S_TX; + break; + default: + pr_err("%s: Invalid be_id: %d\n", __func__, be_id); + afe_port_id = -EINVAL; + } + + return afe_port_id; +} + +static int int_mi2s_get_index(int port_id) +{ + int index; + + switch (port_id) { + case AFE_PORT_ID_INT0_MI2S_RX: + index = INT0_MI2S; + break; + case AFE_PORT_ID_INT2_MI2S_TX: + index = INT2_MI2S; + break; + case AFE_PORT_ID_INT3_MI2S_TX: + index = INT3_MI2S; + break; + case AFE_PORT_ID_INT4_MI2S_RX: + index = INT4_MI2S; + break; + case AFE_PORT_ID_INT5_MI2S_TX: + index = INT5_MI2S; + break; + default: + pr_err("%s: Invalid port_id: %d\n", __func__, port_id); + index = -EINVAL; + } + + return index; +} + +static u32 get_int_mi2s_bits_per_sample(u32 bit_format) +{ + u32 bit_per_sample; + + switch (bit_format) { + case SNDRV_PCM_FORMAT_S24_3LE: + case SNDRV_PCM_FORMAT_S24_LE: + bit_per_sample = 32; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + bit_per_sample = 16; + break; + } + + return bit_per_sample; +} + +static void update_int_mi2s_clk_val(int idx, int stream) +{ + u32 bit_per_sample; + + bit_per_sample = + get_int_mi2s_bits_per_sample(int_mi2s_cfg[idx].bit_format); + int_mi2s_clk[idx].clk_freq_in_hz = + (int_mi2s_cfg[idx].sample_rate * int_mi2s_cfg[idx].channels + * bit_per_sample); +} + +static int int_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int port_id = 0; + int index; + + port_id = int_mi2s_get_port_id(rtd->dai_link->be_id); + if (IS_ERR_VALUE(port_id)) { + dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__); + ret = port_id; + goto done; + } + index = int_mi2s_get_index(port_id); + if (index < 0) { + dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__); + ret = port_id; + goto done; + } + if (enable) { + update_int_mi2s_clk_val(index, substream->stream); + dev_dbg(rtd->card->dev, "%s: clock rate %ul\n", __func__, + int_mi2s_clk[index].clk_freq_in_hz); + } + + int_mi2s_clk[index].enable = enable; + ret = afe_set_lpass_clock_v2(port_id, + &int_mi2s_clk[index]); + if (ret < 0) { + dev_err(rtd->card->dev, + "%s: afe lpass clock failed for port 0x%x , err:%d\n", + __func__, port_id, ret); + goto done; + } + +done: + return ret; +} + +static int msm_swr_mi2s_snd_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret = 0; + + pr_debug("%s(): substream = %s stream = %d\n", __func__, + substream->name, substream->stream); + + ret = int_mi2s_set_sclk(substream, true); + if (ret < 0) { + pr_err("%s: failed to enable sclk %d\n", + __func__, ret); + return ret; + } + /* Enable the codec mclk config */ + ret = msm_gpioset_activate(CLIENT_WCD, "swr_pin"); + if (ret < 0) { + pr_err("%s: gpio set cannot be activated %sd", + __func__, "swr_pin"); + return ret; + } + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + pr_err("%s: set fmt cpu dai failed; ret=%d\n", __func__, ret); + + return ret; +} + +static void msm_swr_mi2s_snd_shutdown(struct snd_pcm_substream *substream) +{ + int ret; + + pr_debug("%s(): substream = %s stream = %d\n", __func__, + substream->name, substream->stream); + + ret = int_mi2s_set_sclk(substream, false); + if (ret < 0) + pr_err("%s:clock disable failed; ret=%d\n", __func__, + ret); +} + +static int msm_int_mi2s_snd_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_codec *codec = rtd->codec; + int ret = 0; + + pr_debug("%s(): substream = %s stream = %d\n", __func__, + substream->name, substream->stream); + + ret = int_mi2s_set_sclk(substream, true); + if (ret < 0) { + pr_err("%s: failed to enable sclk %d\n", + __func__, ret); + return ret; + } + ret = msm_int_enable_dig_cdc_clk(codec, 1, true); + if (ret < 0) { + pr_err("failed to enable mclk\n"); + return ret; + } + /* Enable the codec mclk config */ + ret = msm_gpioset_activate(CLIENT_WCD, "int_pdm"); + if (ret < 0) { + pr_err("%s: gpio set cannot be activated %s\n", + __func__, "int_pdm"); + return ret; + } + msm8x16_wcd_mclk_enable(codec, 1, true); + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + pr_err("%s: set fmt cpu dai failed; ret=%d\n", __func__, ret); + + return ret; +} + +static void msm_int_mi2s_snd_shutdown(struct snd_pcm_substream *substream) +{ + int ret; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + + pr_debug("%s(): substream = %s stream = %d\n", __func__, + substream->name, substream->stream); + + ret = int_mi2s_set_sclk(substream, false); + if (ret < 0) + pr_err("%s:clock disable failed; ret=%d\n", __func__, + ret); + if (atomic_read(&pdata->int_mclk0_rsc_ref) > 0) { + atomic_dec(&pdata->int_mclk0_rsc_ref); + pr_debug("%s: decrementing mclk_res_ref %d\n", + __func__, + atomic_read(&pdata->int_mclk0_rsc_ref)); + } +} + +static void *def_msm_int_wcd_mbhc_cal(void) +{ + void *msm_int_wcd_cal; + struct wcd_mbhc_btn_detect_cfg *btn_cfg; + u16 *btn_low, *btn_high; + + msm_int_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS, + WCD_MBHC_DEF_RLOADS), GFP_KERNEL); + if (!msm_int_wcd_cal) + return NULL; + +#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(msm_int_wcd_cal)->X) = (Y)) + S(v_hs_max, 1500); +#undef S +#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(msm_int_wcd_cal)->X) = (Y)) + S(num_btn, WCD_MBHC_DEF_BUTTONS); +#undef S + + + btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(msm_int_wcd_cal); + btn_low = btn_cfg->_v_btn_low; + btn_high = ((void *)&btn_cfg->_v_btn_low) + + (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn); + + /* + * In SW we are maintaining two sets of threshold register + * one for current source and another for Micbias. + * all btn_low corresponds to threshold for current source + * all bt_high corresponds to threshold for Micbias + * Below thresholds are based on following resistances + * 0-70 == Button 0 + * 110-180 == Button 1 + * 210-290 == Button 2 + * 360-680 == Button 3 + */ + btn_low[0] = 75; + btn_high[0] = 75; + btn_low[1] = 150; + btn_high[1] = 150; + btn_low[2] = 225; + btn_high[2] = 225; + btn_low[3] = 450; + btn_high[3] = 450; + btn_low[4] = 500; + btn_high[4] = 500; + + return msm_int_wcd_cal; +} + +static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = + snd_soc_codec_get_dapm(codec); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret = -ENOMEM; + + pr_debug("%s(),dev_name%s\n", __func__, dev_name(cpu_dai->dev)); + + snd_soc_add_codec_controls(codec, msm_snd_controls, + ARRAY_SIZE(msm_snd_controls)); + + snd_soc_add_codec_controls(codec, msm_common_snd_controls, + ARRAY_SIZE(msm_snd_controls)); + + snd_soc_dapm_new_controls(dapm, msm_int_dapm_widgets, + ARRAY_SIZE(msm_int_dapm_widgets)); + + snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); + snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); + snd_soc_dapm_ignore_suspend(dapm, "Secondary Mic"); + snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1"); + snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2"); + + snd_soc_dapm_ignore_suspend(dapm, "EAR"); + snd_soc_dapm_ignore_suspend(dapm, "HEADPHONE"); + snd_soc_dapm_ignore_suspend(dapm, "SPK_OUT"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC1"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC2"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC3"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC1"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC2"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC3"); + snd_soc_dapm_ignore_suspend(dapm, "DMIC4"); + + snd_soc_dapm_sync(dapm); + + msm8x16_wcd_spk_ext_pa_cb(enable_spk_ext_pa, codec); + msm8x16_wcd_hph_comp_cb(msm_config_hph_compander_gpio, codec); + + mbhc_cfg_ptr->calibration = def_msm_int_wcd_mbhc_cal(); + if (mbhc_cfg_ptr->calibration) { + ret = msm8x16_wcd_hs_detect(codec, mbhc_cfg_ptr); + if (ret) { + pr_err("%s: msm8x16_wcd_hs_detect failed\n", __func__); + kfree(mbhc_cfg_ptr->calibration); + return ret; + } + } + return 0; +} + +static int msm_swr_audrx_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = + snd_soc_codec_get_dapm(codec); + + snd_soc_add_codec_controls(codec, msm_swr_controls, + ARRAY_SIZE(msm_swr_controls)); + + snd_soc_dapm_ignore_suspend(dapm, "AIF1_SWR Playback"); + snd_soc_dapm_ignore_suspend(dapm, "VIfeed_SWR"); + snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT"); + snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT"); + snd_soc_dapm_ignore_suspend(dapm, "AIF1_SWR VI"); + snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_SWR"); + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static struct snd_soc_ops msm_mi2s_be_ops = { + .startup = msm_mi2s_snd_startup, + .shutdown = msm_mi2s_snd_shutdown, +}; + +static struct snd_soc_ops msm_aux_pcm_be_ops = { + .startup = msm_aux_pcm_snd_startup, + .shutdown = msm_aux_pcm_snd_shutdown, +}; + +static struct snd_soc_ops msm_int_mi2s_be_ops = { + .startup = msm_int_mi2s_snd_startup, + .shutdown = msm_int_mi2s_snd_shutdown, +}; + +static struct snd_soc_ops msm_swr_mi2s_be_ops = { + .startup = msm_swr_mi2s_snd_startup, + .shutdown = msm_swr_mi2s_snd_shutdown, +}; + +/* Digital audio interface glue - connects codec <---> CPU */ +static struct snd_soc_dai_link msm_int_dai[] = { + /* FrontEnd DAI Links */ + {/* hw:x,0 */ + .name = MSM_DAILINK_NAME(Media1), + .stream_name = "MultiMedia1", + .cpu_dai_name = "MultiMedia1", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1 + }, + {/* hw:x,1 */ + .name = MSM_DAILINK_NAME(Media2), + .stream_name = "MultiMedia2", + .cpu_dai_name = "MultiMedia2", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2, + }, + {/* hw:x,2 */ + .name = "VoiceMMode1", + .stream_name = "VoiceMMode1", + .cpu_dai_name = "VoiceMMode1", + .platform_name = "msm-pcm-voice", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_VOICEMMODE1, + }, + {/* hw:x,3 */ + .name = "MSM VoIP", + .stream_name = "VoIP", + .cpu_dai_name = "VoIP", + .platform_name = "msm-voip-dsp", + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_VOIP, + }, + {/* hw:x,4 */ + .name = MSM_DAILINK_NAME(ULL), + .stream_name = "ULL", + .cpu_dai_name = "MultiMedia3", + .platform_name = "msm-pcm-dsp.2", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3, + }, + /* Hostless PCM purpose */ + {/* hw:x,5 */ + .name = "INT4 MI2S_RX Hostless", + .stream_name = "INT4 MI2S_RX Hostless", + .cpu_dai_name = "INT4_MI2S_RX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dailink has playback support */ + .ignore_pmdown_time = 1, + /* This dainlink has MI2S support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,6 */ + .name = "MSM AFE-PCM RX", + .stream_name = "AFE-PROXY RX", + .cpu_dai_name = "msm-dai-q6-dev.241", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .platform_name = "msm-pcm-afe", + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + }, + {/* hw:x,7 */ + .name = "MSM AFE-PCM TX", + .stream_name = "AFE-PROXY TX", + .cpu_dai_name = "msm-dai-q6-dev.240", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .platform_name = "msm-pcm-afe", + .ignore_suspend = 1, + }, + {/* hw:x,8 */ + .name = MSM_DAILINK_NAME(Compress1), + .stream_name = "Compress1", + .cpu_dai_name = "MultiMedia4", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4, + }, + {/* hw:x,9*/ + .name = "AUXPCM Hostless", + .stream_name = "AUXPCM Hostless", + .cpu_dai_name = "AUXPCM_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,10 */ + .name = "SLIMBUS_1 Hostless", + .stream_name = "SLIMBUS_1 Hostless", + .cpu_dai_name = "SLIMBUS1_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, /* dai link has playback support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,11 */ + .name = "SLIMBUS_3 Hostless", + .stream_name = "SLIMBUS_3 Hostless", + .cpu_dai_name = "SLIMBUS3_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, /* dai link has playback support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,12 */ + .name = "SLIMBUS_4 Hostless", + .stream_name = "SLIMBUS_4 Hostless", + .cpu_dai_name = "SLIMBUS4_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, /* dai link has playback support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,13 */ + .name = MSM_DAILINK_NAME(LowLatency), + .stream_name = "MultiMedia5", + .cpu_dai_name = "MultiMedia5", + .platform_name = "msm-pcm-dsp.1", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dai link has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5, + }, + /* LSM FE */ + {/* hw:x,14 */ + .name = "Listen 1 Audio Service", + .stream_name = "Listen 1 Audio Service", + .cpu_dai_name = "LSM1", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM1, + }, + {/* hw:x,15 */ + .name = MSM_DAILINK_NAME(Compress2), + .stream_name = "Compress2", + .cpu_dai_name = "MultiMedia7", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7, + }, + {/* hw:x,16 */ + .name = MSM_DAILINK_NAME(Compress3), + .stream_name = "Compress3", + .cpu_dai_name = "MultiMedia10", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA10, + }, + {/* hw:x,17 */ + .name = MSM_DAILINK_NAME(ULL_NOIRQ), + .stream_name = "MM_NOIRQ", + .cpu_dai_name = "MultiMedia8", + .platform_name = "msm-pcm-dsp-noirq", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8, + }, + {/* hw:x,18 */ + .name = "HDMI_RX_HOSTLESS", + .stream_name = "HDMI_RX_HOSTLESS", + .cpu_dai_name = "HDMI_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,19 */ + .name = "VoiceMMode2", + .stream_name = "VoiceMMode2", + .cpu_dai_name = "VoiceMMode2", + .platform_name = "msm-pcm-voice", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_VOICEMMODE2, + }, + {/* hw:x,20 */ + .name = "Listen 2 Audio Service", + .stream_name = "Listen 2 Audio Service", + .cpu_dai_name = "LSM2", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM2, + }, + {/* hw:x,21 */ + .name = "Listen 3 Audio Service", + .stream_name = "Listen 3 Audio Service", + .cpu_dai_name = "LSM3", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM3, + }, + {/* hw:x,22 */ + .name = "Listen 4 Audio Service", + .stream_name = "Listen 4 Audio Service", + .cpu_dai_name = "LSM4", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM4, + }, + {/* hw:x,23 */ + .name = "Listen 5 Audio Service", + .stream_name = "Listen 5 Audio Service", + .cpu_dai_name = "LSM5", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM5, + }, + {/* hw:x,24 */ + .name = "Listen 6 Audio Service", + .stream_name = "Listen 6 Audio Service", + .cpu_dai_name = "LSM6", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM6 + }, + {/* hw:x,25 */ + .name = "Listen 7 Audio Service", + .stream_name = "Listen 7 Audio Service", + .cpu_dai_name = "LSM7", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM7, + }, + {/* hw:x,26 */ + .name = "Listen 8 Audio Service", + .stream_name = "Listen 8 Audio Service", + .cpu_dai_name = "LSM8", + .platform_name = "msm-lsm-client", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .be_id = MSM_FRONTEND_DAI_LSM8, + }, + {/* hw:x,27 */ + .name = MSM_DAILINK_NAME(Media9), + .stream_name = "MultiMedia9", + .cpu_dai_name = "MultiMedia9", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA9, + }, + {/* hw:x,28 */ + .name = MSM_DAILINK_NAME(Compress4), + .stream_name = "Compress4", + .cpu_dai_name = "MultiMedia11", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA11, + }, + {/* hw:x,29 */ + .name = MSM_DAILINK_NAME(Compress5), + .stream_name = "Compress5", + .cpu_dai_name = "MultiMedia12", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA12, + }, + {/* hw:x,30 */ + .name = MSM_DAILINK_NAME(Compress6), + .stream_name = "Compress6", + .cpu_dai_name = "MultiMedia13", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA13, + }, + {/* hw:x,31 */ + .name = MSM_DAILINK_NAME(Compress7), + .stream_name = "Compress7", + .cpu_dai_name = "MultiMedia14", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA14, + }, + {/* hw:x,32 */ + .name = MSM_DAILINK_NAME(Compress8), + .stream_name = "Compress8", + .cpu_dai_name = "MultiMedia15", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA15, + }, + {/* hw:x,33 */ + .name = MSM_DAILINK_NAME(Compress9), + .stream_name = "Compress9", + .cpu_dai_name = "MultiMedia16", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dai link has playback support */ + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA16, + }, + {/* hw:x,34 */ + .name = "SLIMBUS_8 Hostless", + .stream_name = "SLIMBUS8_HOSTLESS Capture", + .cpu_dai_name = "SLIMBUS8_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,35 */ + .name = LPASS_BE_INT5_MI2S_TX, + .stream_name = "INT5_mi2s Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.12", + .platform_name = "msm-pcm-hostless", + .codec_name = "msm_swr_codec", + .codec_dai_name = "msm_swr_vifeedback", + .be_id = MSM_BACKEND_DAI_INT5_MI2S_TX, + .be_hw_params_fixup = int_mi2s_be_hw_params_fixup, + .ops = &msm_swr_mi2s_be_ops, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .dpcm_capture = 1, + .ignore_pmdown_time = 1, + }, + {/* hw:x,36 */ + .name = "Primary MI2S_RX Hostless", + .stream_name = "Primary MI2S_RX Hostless", + .cpu_dai_name = "PRI_MI2S_RX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dailink has playback support */ + .ignore_pmdown_time = 1, + /* This dainlink has MI2S support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,37 */ + .name = "Secondary MI2S_RX Hostless", + .stream_name = "Secondary MI2S_RX Hostless", + .cpu_dai_name = "SEC_MI2S_RX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dailink has playback support */ + .ignore_pmdown_time = 1, + /* This dainlink has MI2S support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,38 */ + .name = "Tertiary MI2S_RX Hostless", + .stream_name = "Tertiary MI2S_RX Hostless", + .cpu_dai_name = "TERT_MI2S_RX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dailink has playback support */ + .ignore_pmdown_time = 1, + /* This dainlink has MI2S support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + {/* hw:x,39 */ + .name = "INT0 MI2S_RX Hostless", + .stream_name = "INT0 MI2S_RX Hostless", + .cpu_dai_name = "INT0_MI2S_RX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dailink has playback support */ + .ignore_pmdown_time = 1, + /* This dainlink has MI2S support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + /* Backend I2S DAI Links */ + { + .name = LPASS_BE_INT0_MI2S_RX, + .stream_name = "INT0 MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.7", + .platform_name = "msm-pcm-routing", + .codec_name = "cajon_codec", + .codec_dai_name = "msm8x16_wcd_i2s_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE | + ASYNC_DPCM_SND_SOC_HW_PARAMS, + .be_id = MSM_BACKEND_DAI_INT0_MI2S_RX, + .init = &msm_audrx_init, + .be_hw_params_fixup = int_mi2s_be_hw_params_fixup, + .ops = &msm_int_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_INT4_MI2S_RX, + .stream_name = "INT4 MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.11", + .platform_name = "msm-pcm-routing", + .codec_name = "msm_swr_codec", + .codec_dai_name = "msm_swr_i2s_rx1", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_INT4_MI2S_RX, + .init = &msm_swr_audrx_init, + .be_hw_params_fixup = int_mi2s_be_hw_params_fixup, + .ops = &msm_swr_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_INT2_MI2S_TX, + .stream_name = "INT2 MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.9", + .platform_name = "msm-pcm-routing", + .codec_name = "cajon_codec", + .codec_dai_name = "msm8x16_wcd_i2s_tx2", + .no_pcm = 1, + .dpcm_capture = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE | + ASYNC_DPCM_SND_SOC_HW_PARAMS, + .be_id = MSM_BACKEND_DAI_INT2_MI2S_TX, + .be_hw_params_fixup = int_mi2s_be_hw_params_fixup, + .ops = &msm_int_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_INT3_MI2S_TX, + .stream_name = "INT3 MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.10", + .platform_name = "msm-pcm-routing", + .codec_name = "cajon_codec", + .codec_dai_name = "msm8x16_wcd_i2s_tx1", + .no_pcm = 1, + .dpcm_capture = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE | + ASYNC_DPCM_SND_SOC_HW_PARAMS, + .be_id = MSM_BACKEND_DAI_INT3_MI2S_TX, + .be_hw_params_fixup = int_mi2s_be_hw_params_fixup, + .ops = &msm_int_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_AFE_PCM_RX, + .stream_name = "AFE Playback", + .cpu_dai_name = "msm-dai-q6-dev.224", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_AFE_PCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_AFE_PCM_TX, + .stream_name = "AFE Capture", + .cpu_dai_name = "msm-dai-q6-dev.225", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_AFE_PCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_suspend = 1, + }, + /* Incall Record Uplink BACK END DAI Link */ + { + .name = LPASS_BE_INCALL_RECORD_TX, + .stream_name = "Voice Uplink Capture", + .cpu_dai_name = "msm-dai-q6-dev.32772", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_suspend = 1, + }, + /* Incall Record Downlink BACK END DAI Link */ + { + .name = LPASS_BE_INCALL_RECORD_RX, + .stream_name = "Voice Downlink Capture", + .cpu_dai_name = "msm-dai-q6-dev.32771", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_suspend = 1, + }, + /* Incall Music BACK END DAI Link */ + { + .name = LPASS_BE_VOICE_PLAYBACK_TX, + .stream_name = "Voice Farend Playback", + .cpu_dai_name = "msm-dai-q6-dev.32773", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_suspend = 1, + }, + /* Incall Music 2 BACK END DAI Link */ + { + .name = LPASS_BE_VOICE2_PLAYBACK_TX, + .stream_name = "Voice2 Farend Playback", + .cpu_dai_name = "msm-dai-q6-dev.32770", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_suspend = 1, + }, +}; + +static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = { + { + .name = LPASS_BE_PRI_MI2S_RX, + .stream_name = "Primary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.0", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_PRI_MI2S_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_PRI_MI2S_TX, + .stream_name = "Primary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.0", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_PRI_MI2S_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_RX, + .stream_name = "Secondary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_TX, + .stream_name = "Secondary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_RX, + .stream_name = "Tertiary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.2", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_TX, + .stream_name = "Tertiary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.2", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_RX, + .stream_name = "Quaternary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.3", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_TX, + .stream_name = "Quaternary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.3", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ops = &msm_mi2s_be_ops, + .ignore_suspend = 1, + }, +}; + +static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = { + /* Primary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_AUXPCM_RX, + .stream_name = "AUX PCM Playback", + .cpu_dai_name = "msm-dai-q6-auxpcm.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_AUXPCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + { + .name = LPASS_BE_AUXPCM_TX, + .stream_name = "AUX PCM Capture", + .cpu_dai_name = "msm-dai-q6-auxpcm.1", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_AUXPCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + /* Secondary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_SEC_AUXPCM_RX, + .stream_name = "Sec AUX PCM Playback", + .cpu_dai_name = "msm-dai-q6-auxpcm.2", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + { + .name = LPASS_BE_SEC_AUXPCM_TX, + .stream_name = "Sec AUX PCM Capture", + .cpu_dai_name = "msm-dai-q6-auxpcm.2", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .ops = &msm_aux_pcm_be_ops, + }, + /* Tertiary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_TERT_AUXPCM_RX, + .stream_name = "Tert AUX PCM Playback", + .cpu_dai_name = "msm-dai-q6-auxpcm.3", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_TERT_AUXPCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + { + .name = LPASS_BE_TERT_AUXPCM_TX, + .stream_name = "Tert AUX PCM Capture", + .cpu_dai_name = "msm-dai-q6-auxpcm.3", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_TERT_AUXPCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .ops = &msm_aux_pcm_be_ops, + }, + /* Quaternary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_QUAT_AUXPCM_RX, + .stream_name = "Quat AUX PCM Playback", + .cpu_dai_name = "msm-dai-q6-auxpcm.4", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUAT_AUXPCM_RX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_aux_pcm_be_ops, + }, + { + .name = LPASS_BE_QUAT_AUXPCM_TX, + .stream_name = "Quat AUX PCM Capture", + .cpu_dai_name = "msm-dai-q6-auxpcm.4", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUAT_AUXPCM_TX, + .be_hw_params_fixup = msm_common_be_hw_params_fixup, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .ops = &msm_aux_pcm_be_ops, + }, +}; + +static struct snd_soc_dai_link msm_int_dai_links[ +ARRAY_SIZE(msm_int_dai) + +ARRAY_SIZE(msm_mi2s_be_dai_links) + +ARRAY_SIZE(msm_auxpcm_be_dai_links)]; + +static struct snd_soc_card msmfalcon_card = { + /* snd_soc_card_msmfalcon */ + .name = "msmfalcon-snd-card", + .dai_link = msm_int_dai, + .num_links = ARRAY_SIZE(msm_int_dai), +}; + +static void msm_disable_int_mclk0(struct work_struct *work) +{ + struct msm_asoc_mach_data *pdata = NULL; + struct delayed_work *dwork; + int ret = 0; + + dwork = to_delayed_work(work); + pdata = container_of(dwork, struct msm_asoc_mach_data, + disable_int_mclk0_work); + mutex_lock(&pdata->cdc_int_mclk0_mutex); + pr_debug("%s: mclk_enabled %d mclk_rsc_ref %d\n", __func__, + atomic_read(&pdata->int_mclk0_enabled), + atomic_read(&pdata->int_mclk0_rsc_ref)); + + if (atomic_read(&pdata->int_mclk0_enabled) == true + && atomic_read(&pdata->int_mclk0_rsc_ref) == 0) { + pr_debug("Disable the mclk\n"); + pdata->digital_cdc_core_clk.enable = 0; + ret = afe_set_lpass_clock_v2( + AFE_PORT_ID_INT0_MI2S_RX, + &pdata->digital_cdc_core_clk); + if (ret < 0) + pr_err("%s failed to disable the CCLK\n", __func__); + atomic_set(&pdata->int_mclk0_enabled, false); + } + mutex_unlock(&pdata->cdc_int_mclk0_mutex); +} + +static void msm_int_dt_parse_cap_info(struct platform_device *pdev, + struct msm_asoc_mach_data *pdata) +{ + const char *ext1_cap = "qcom,msm-micbias1-ext-cap"; + const char *ext2_cap = "qcom,msm-micbias2-ext-cap"; + + pdata->micbias1_cap_mode = + (of_property_read_bool(pdev->dev.of_node, ext1_cap) ? + MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP); + + pdata->micbias2_cap_mode = + (of_property_read_bool(pdev->dev.of_node, ext2_cap) ? + MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP); +} + +static struct snd_soc_card *msm_int_populate_sndcard_dailinks( + struct device *dev) +{ + struct snd_soc_card *card = &msmfalcon_card; + struct snd_soc_dai_link *dailink; + int len1; + + card->name = dev_name(dev); + len1 = ARRAY_SIZE(msm_int_dai); + memcpy(msm_int_dai_links, msm_int_dai, sizeof(msm_int_dai)); + dailink = msm_int_dai_links; + if (of_property_read_bool(dev->of_node, + "qcom,mi2s-audio-intf")) { + memcpy(dailink + len1, + msm_mi2s_be_dai_links, + sizeof(msm_mi2s_be_dai_links)); + len1 += ARRAY_SIZE(msm_mi2s_be_dai_links); + } + if (of_property_read_bool(dev->of_node, + "qcom,auxpcm-audio-intf")) { + memcpy(dailink + len1, + msm_auxpcm_be_dai_links, + sizeof(msm_auxpcm_be_dai_links)); + len1 += ARRAY_SIZE(msm_auxpcm_be_dai_links); + } + card->dai_link = dailink; + card->num_links = len1; + return card; +} + +static int msm_internal_init(struct platform_device *pdev, + struct msm_asoc_mach_data *pdata, + struct snd_soc_card *card) +{ + const char *type = NULL; + const char *hs_micbias_type = "qcom,msm-hs-micbias-type"; + int ret; + + ret = is_ext_spk_gpio_support(pdev, pdata); + if (ret < 0) + dev_dbg(&pdev->dev, + "%s: doesn't support external speaker pa\n", + __func__); + + ret = of_property_read_string(pdev->dev.of_node, + hs_micbias_type, &type); + if (ret) { + dev_err(&pdev->dev, "%s: missing %s in dt node\n", + __func__, hs_micbias_type); + goto err; + } + if (!strcmp(type, "external")) { + dev_dbg(&pdev->dev, "Headset is using external micbias\n"); + mbhc_cfg_ptr->hs_ext_micbias = true; + } else { + dev_dbg(&pdev->dev, "Headset is using internal micbias\n"); + mbhc_cfg_ptr->hs_ext_micbias = false; + } + + /* initialize the int_mclk0 */ + pdata->digital_cdc_core_clk.clk_set_minor_version = + AFE_API_VERSION_I2S_CONFIG; + pdata->digital_cdc_core_clk.clk_id = + Q6AFE_LPASS_CLK_ID_INT_MCLK_0; + pdata->digital_cdc_core_clk.clk_freq_in_hz = + pdata->mclk_freq; + pdata->digital_cdc_core_clk.clk_attri = + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO; + pdata->digital_cdc_core_clk.clk_root = + Q6AFE_LPASS_CLK_ROOT_DEFAULT; + pdata->digital_cdc_core_clk.enable = 1; + + /* Initialize loopback mode to false */ + pdata->lb_mode = false; + + msm_int_dt_parse_cap_info(pdev, pdata); + + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, pdata); + ret = snd_soc_of_parse_card_name(card, "qcom,model"); + if (ret) + goto err; + /* initialize timer */ + INIT_DELAYED_WORK(&pdata->disable_int_mclk0_work, + msm_disable_int_mclk0); + mutex_init(&pdata->cdc_int_mclk0_mutex); + atomic_set(&pdata->int_mclk0_rsc_ref, 0); + atomic_set(&pdata->int_mclk0_enabled, false); + + dev_info(&pdev->dev, "%s: default codec configured\n", __func__); + + return 0; +err: + return ret; +} + +/** + * msm_int_cdc_init - internal codec machine specific init. + * + * @pdev: platform device handle + * @pdata: private data of machine driver + * @card: sound card pointer reference + * @mbhc_cfg: MBHC config reference + * + * Returns 0. + */ +int msm_int_cdc_init(struct platform_device *pdev, + struct msm_asoc_mach_data *pdata, + struct snd_soc_card **card, + struct wcd_mbhc_config *mbhc_cfg) +{ + mbhc_cfg_ptr = mbhc_cfg; + + *card = msm_int_populate_sndcard_dailinks(&pdev->dev); + msm_internal_init(pdev, pdata, *card); + return 0; +} +EXPORT_SYMBOL(msm_int_cdc_init); diff --git a/sound/soc/msm/msmfalcon-internal.h b/sound/soc/msm/msmfalcon-internal.h new file mode 100644 index 000000000000..e5e3e7c66246 --- /dev/null +++ b/sound/soc/msm/msmfalcon-internal.h @@ -0,0 +1,32 @@ +/* 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 __MSMFALCON_INTERNAL +#define __MSMFALCON_INTERNAL + +#include <sound/soc.h> + +#ifdef CONFIG_SND_SOC_INT_CODEC +int msm_int_cdc_init(struct platform_device *pdev, + struct msm_asoc_mach_data *pdata, + struct snd_soc_card **card, + struct wcd_mbhc_config *mbhc_cfg); +#else +int msm_int_cdc_init(struct platform_device *pdev, + struct msm_asoc_mach_data *pdata, + struct snd_soc_card **card, + struct wcd_mbhc_config *mbhc_cfg) +{ + return 0; +} +#endif +#endif diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 770bd12eb501..a2cd6c6f98db 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -2779,10 +2779,10 @@ static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol, acdb_dev_id = ucontrol->value.integer.value[1]; if (0 != ucontrol->value.integer.value[2]) sample_rate = ucontrol->value.integer.value[2]; - pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d\n", - __func__, app_type, acdb_dev_id, sample_rate); + pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", + __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_RX); msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, - acdb_dev_id, sample_rate); + acdb_dev_id, sample_rate, SESSION_TYPE_RX); return 0; } @@ -2804,8 +2804,8 @@ static int msm_compr_app_type_cfg_get(struct snd_kcontrol *kcontrol, goto done; } - ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, &app_type, - &acdb_dev_id, &sample_rate); + ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_RX, + &app_type, &acdb_dev_id, &sample_rate); if (ret < 0) { pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", __func__, ret); @@ -2815,8 +2815,9 @@ static int msm_compr_app_type_cfg_get(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = app_type; ucontrol->value.integer.value[1] = acdb_dev_id; ucontrol->value.integer.value[2] = sample_rate; - pr_debug("%s: fedai_id %llu, app_type %d, acdb_dev_id %d, sample_rate %d\n", - __func__, fe_id, app_type, acdb_dev_id, sample_rate); + pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fe_id, SESSION_TYPE_RX, + app_type, acdb_dev_id, sample_rate); done: return ret; } diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index 7eb4a10b83c7..718f7017342b 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -3481,12 +3481,32 @@ static int msm_mi2s_get_port_id(u32 mi2s_id, int stream, u16 *port_id) case MSM_QUIN_MI2S: *port_id = AFE_PORT_ID_QUINARY_MI2S_RX; break; - break; + case MSM_INT0_MI2S: + *port_id = AFE_PORT_ID_INT0_MI2S_RX; + break; + case MSM_INT1_MI2S: + *port_id = AFE_PORT_ID_INT1_MI2S_RX; + break; + case MSM_INT2_MI2S: + *port_id = AFE_PORT_ID_INT2_MI2S_RX; + break; + case MSM_INT3_MI2S: + *port_id = AFE_PORT_ID_INT3_MI2S_RX; + break; + case MSM_INT4_MI2S: + *port_id = AFE_PORT_ID_INT4_MI2S_RX; + break; + case MSM_INT5_MI2S: + *port_id = AFE_PORT_ID_INT5_MI2S_RX; + break; + case MSM_INT6_MI2S: + *port_id = AFE_PORT_ID_INT6_MI2S_RX; + break; default: pr_err("%s: playback err id 0x%x\n", __func__, mi2s_id); ret = -1; - break; + break; } break; case SNDRV_PCM_STREAM_CAPTURE: @@ -3509,10 +3529,31 @@ static int msm_mi2s_get_port_id(u32 mi2s_id, int stream, u16 *port_id) case MSM_SENARY_MI2S: *port_id = AFE_PORT_ID_SENARY_MI2S_TX; break; + case MSM_INT0_MI2S: + *port_id = AFE_PORT_ID_INT0_MI2S_TX; + break; + case MSM_INT1_MI2S: + *port_id = AFE_PORT_ID_INT1_MI2S_TX; + break; + case MSM_INT2_MI2S: + *port_id = AFE_PORT_ID_INT2_MI2S_TX; + break; + case MSM_INT3_MI2S: + *port_id = AFE_PORT_ID_INT3_MI2S_TX; + break; + case MSM_INT4_MI2S: + *port_id = AFE_PORT_ID_INT4_MI2S_TX; + break; + case MSM_INT5_MI2S: + *port_id = AFE_PORT_ID_INT5_MI2S_TX; + break; + case MSM_INT6_MI2S: + *port_id = AFE_PORT_ID_INT6_MI2S_TX; + break; default: pr_err("%s: capture err id 0x%x\n", __func__, mi2s_id); ret = -1; - break; + break; } break; default: @@ -3968,6 +4009,188 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { .probe = msm_dai_q6_dai_mi2s_probe, .remove = msm_dai_q6_dai_mi2s_remove, }, + { + .playback = { + .stream_name = "INT0 MI2S Playback", + .aif_name = "INT0_MI2S_RX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_44100, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .capture = { + .stream_name = "INT0 MI2S Capture", + .aif_name = "INT0_MI2S_TX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_mi2s_ops, + .id = MSM_INT0_MI2S, + .probe = msm_dai_q6_dai_mi2s_probe, + .remove = msm_dai_q6_dai_mi2s_remove, + }, + { + .playback = { + .stream_name = "INT1 MI2S Playback", + .aif_name = "INT1_MI2S_RX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .capture = { + .stream_name = "INT1 MI2S Capture", + .aif_name = "INT1_MI2S_TX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_mi2s_ops, + .id = MSM_INT1_MI2S, + .probe = msm_dai_q6_dai_mi2s_probe, + .remove = msm_dai_q6_dai_mi2s_remove, + }, + { + .playback = { + .stream_name = "INT2 MI2S Playback", + .aif_name = "INT2_MI2S_RX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .capture = { + .stream_name = "INT2 MI2S Capture", + .aif_name = "INT2_MI2S_TX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_mi2s_ops, + .id = MSM_INT2_MI2S, + .probe = msm_dai_q6_dai_mi2s_probe, + .remove = msm_dai_q6_dai_mi2s_remove, + }, + { + .playback = { + .stream_name = "INT3 MI2S Playback", + .aif_name = "INT3_MI2S_RX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .capture = { + .stream_name = "INT3 MI2S Capture", + .aif_name = "INT3_MI2S_TX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_mi2s_ops, + .id = MSM_INT3_MI2S, + .probe = msm_dai_q6_dai_mi2s_probe, + .remove = msm_dai_q6_dai_mi2s_remove, + }, + { + .playback = { + .stream_name = "INT4 MI2S Playback", + .aif_name = "INT4_MI2S_RX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .capture = { + .stream_name = "INT4 MI2S Capture", + .aif_name = "INT4_MI2S_TX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_mi2s_ops, + .id = MSM_INT4_MI2S, + .probe = msm_dai_q6_dai_mi2s_probe, + .remove = msm_dai_q6_dai_mi2s_remove, + }, + { + .playback = { + .stream_name = "INT5 MI2S Playback", + .aif_name = "INT5_MI2S_RX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .capture = { + .stream_name = "INT5 MI2S Capture", + .aif_name = "INT5_MI2S_TX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_mi2s_ops, + .id = MSM_INT5_MI2S, + .probe = msm_dai_q6_dai_mi2s_probe, + .remove = msm_dai_q6_dai_mi2s_remove, + }, + { + .playback = { + .stream_name = "INT6 MI2S Playback", + .aif_name = "INT6_MI2S_RX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .capture = { + .stream_name = "INT6 MI2S Capture", + .aif_name = "INT6_MI2S_TX", + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_dai_q6_mi2s_ops, + .id = MSM_INT6_MI2S, + .probe = msm_dai_q6_dai_mi2s_probe, + .remove = msm_dai_q6_dai_mi2s_remove, + }, }; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c index ff7cf5812c0c..82458275b892 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c @@ -516,7 +516,7 @@ exit: return rc; } -static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) +static int msm_pcm_add_volume_controls(struct snd_soc_pcm_runtime *rtd) { struct snd_pcm *pcm = rtd->pcm->streams[0].pcm; struct snd_pcm_volume *volume_info; @@ -537,6 +537,192 @@ static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) return 0; } +static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int app_type; + int acdb_dev_id; + int sample_rate = 48000; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + return -EINVAL; + } + + app_type = ucontrol->value.integer.value[0]; + acdb_dev_id = ucontrol->value.integer.value[1]; + if (ucontrol->value.integer.value[2] != 0) + sample_rate = ucontrol->value.integer.value[2]; + pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", + __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_RX); + msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, + acdb_dev_id, sample_rate, SESSION_TYPE_RX); + + return 0; +} + +static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int ret = 0; + int app_type; + int acdb_dev_id; + int sample_rate; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + ret = -EINVAL; + goto done; + } + + ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_RX, + &app_type, &acdb_dev_id, &sample_rate); + if (ret < 0) { + pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", + __func__, ret); + goto done; + } + + ucontrol->value.integer.value[0] = app_type; + ucontrol->value.integer.value[1] = acdb_dev_id; + ucontrol->value.integer.value[2] = sample_rate; + pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fe_id, SESSION_TYPE_RX, + app_type, acdb_dev_id, sample_rate); +done: + return ret; +} + +static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int app_type; + int acdb_dev_id; + int sample_rate = 48000; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + return -EINVAL; + } + + app_type = ucontrol->value.integer.value[0]; + acdb_dev_id = ucontrol->value.integer.value[1]; + if (ucontrol->value.integer.value[2] != 0) + sample_rate = ucontrol->value.integer.value[2]; + pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", + __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX); + msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, + acdb_dev_id, sample_rate, SESSION_TYPE_TX); + + return 0; +} + +static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int ret = 0; + int app_type; + int acdb_dev_id; + int sample_rate; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + ret = -EINVAL; + goto done; + } + + ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX, + &app_type, &acdb_dev_id, &sample_rate); + if (ret < 0) { + pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", + __func__, ret); + goto done; + } + + ucontrol->value.integer.value[0] = app_type; + ucontrol->value.integer.value[1] = acdb_dev_id; + ucontrol->value.integer.value[2] = sample_rate; + pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fe_id, SESSION_TYPE_TX, + app_type, acdb_dev_id, sample_rate); +done: + return ret; +} + +static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm->streams[0].pcm; + struct snd_pcm_usr *app_type_info; + struct snd_kcontrol *kctl; + const char *playback_mixer_ctl_name = "Audio Stream"; + const char *capture_mixer_ctl_name = "Audio Stream Capture"; + const char *deviceNo = "NN"; + const char *suffix = "App Type Cfg"; + int ctl_len, ret = 0; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + ctl_len = strlen(playback_mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + pr_debug("%s: Playback app type cntrl add\n", __func__); + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &app_type_info); + if (ret < 0) + return ret; + kctl = app_type_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + playback_mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_pcm_playback_app_type_cfg_ctl_put; + kctl->get = msm_pcm_playback_app_type_cfg_ctl_get; + } + + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ctl_len = strlen(capture_mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + pr_debug("%s: Capture app type cntrl add\n", __func__); + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &app_type_info); + if (ret < 0) + return ret; + kctl = app_type_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + capture_mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_pcm_capture_app_type_cfg_ctl_put; + kctl->get = msm_pcm_capture_app_type_cfg_ctl_get; + } + + return 0; +} + +static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) +{ + int ret = 0; + + pr_debug("%s\n", __func__); + ret = msm_pcm_add_volume_controls(rtd); + if (ret) + pr_err("%s: pcm add volume controls failed:%d\n", + __func__, ret); + ret = msm_pcm_add_app_type_controls(rtd); + if (ret) + pr_err("%s: pcm add app type controls failed:%d\n", + __func__, ret); + return ret; +} + static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index c5baf0e63732..920e7324f14a 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -1178,7 +1178,7 @@ static int msm_pcm_add_chmap_controls(struct snd_soc_pcm_runtime *rtd) return 0; } -static int msm_pcm_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, +static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; @@ -1197,15 +1197,15 @@ static int msm_pcm_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, acdb_dev_id = ucontrol->value.integer.value[1]; if (0 != ucontrol->value.integer.value[2]) sample_rate = ucontrol->value.integer.value[2]; - pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d\n", - __func__, app_type, acdb_dev_id, sample_rate); + pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", + __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_RX); msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, - acdb_dev_id, sample_rate); + acdb_dev_id, sample_rate, SESSION_TYPE_RX); return 0; } -static int msm_pcm_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, +static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; @@ -1222,8 +1222,8 @@ static int msm_pcm_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, goto done; } - ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, &app_type, - &acdb_dev_id, &sample_rate); + ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_RX, + &app_type, &acdb_dev_id, &sample_rate); if (ret < 0) { pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", __func__, ret); @@ -1233,8 +1233,71 @@ static int msm_pcm_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = app_type; ucontrol->value.integer.value[1] = acdb_dev_id; ucontrol->value.integer.value[2] = sample_rate; - pr_debug("%s: fedai_id %llu, app_type %d, acdb_dev_id %d, sample_rate %d\n", - __func__, fe_id, app_type, acdb_dev_id, sample_rate); + pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fe_id, SESSION_TYPE_RX, + app_type, acdb_dev_id, sample_rate); +done: + return ret; +} + +static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int app_type; + int acdb_dev_id; + int sample_rate = 48000; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + return -EINVAL; + } + + app_type = ucontrol->value.integer.value[0]; + acdb_dev_id = ucontrol->value.integer.value[1]; + if (ucontrol->value.integer.value[2] != 0) + sample_rate = ucontrol->value.integer.value[2]; + pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", + __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX); + msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, + acdb_dev_id, sample_rate, SESSION_TYPE_TX); + + return 0; +} + +static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int ret = 0; + int app_type; + int acdb_dev_id; + int sample_rate; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + ret = -EINVAL; + goto done; + } + + ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX, + &app_type, &acdb_dev_id, &sample_rate); + if (ret < 0) { + pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", + __func__, ret); + goto done; + } + + ucontrol->value.integer.value[0] = app_type; + ucontrol->value.integer.value[1] = acdb_dev_id; + ucontrol->value.integer.value[2] = sample_rate; + pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fe_id, SESSION_TYPE_TX, + app_type, acdb_dev_id, sample_rate); done: return ret; } @@ -1244,27 +1307,49 @@ static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) struct snd_pcm *pcm = rtd->pcm; struct snd_pcm_usr *app_type_info; struct snd_kcontrol *kctl; - const char *mixer_ctl_name = "Audio Stream"; + const char *playback_mixer_ctl_name = "Audio Stream"; + const char *capture_mixer_ctl_name = "Audio Stream Capture"; const char *deviceNo = "NN"; const char *suffix = "App Type Cfg"; int ctl_len, ret = 0; - ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + - strlen(suffix) + 1; - pr_debug("%s, App type cntrl add\n", __func__); - ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, - NULL, 1, ctl_len, rtd->dai_link->be_id, - &app_type_info); - if (ret < 0) { - pr_err("%s, app type cntrl add failed:%d\n", __func__, ret); - return ret; + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + ctl_len = strlen(playback_mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + pr_debug("%s: Playback app type cntrl add\n", __func__); + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &app_type_info); + if (ret < 0) { + pr_err("%s: playback app type cntrl add failed: %d\n", + __func__, ret); + return ret; + } + kctl = app_type_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + playback_mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_pcm_playback_app_type_cfg_ctl_put; + kctl->get = msm_pcm_playback_app_type_cfg_ctl_get; + } + + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ctl_len = strlen(capture_mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + pr_debug("%s: Capture app type cntrl add\n", __func__); + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &app_type_info); + if (ret < 0) { + pr_err("%s: capture app type cntrl add failed: %d\n", + __func__, ret); + return ret; + } + kctl = app_type_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + capture_mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_pcm_capture_app_type_cfg_ctl_put; + kctl->get = msm_pcm_capture_app_type_cfg_ctl_get; } - kctl = app_type_info->kctl; - snprintf(kctl->id.name, ctl_len, "%s %d %s", mixer_ctl_name, - rtd->pcm->device, suffix); - kctl = app_type_info->kctl; - kctl->put = msm_pcm_app_type_cfg_ctl_put; - kctl->get = msm_pcm_app_type_cfg_ctl_get; return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 13d4ba27d990..9681330be33b 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -466,6 +466,34 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { LPASS_BE_QUAT_AUXPCM_RX}, { AFE_PORT_ID_QUATERNARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_AUXPCM_TX}, + { AFE_PORT_ID_INT0_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT0_MI2S_RX}, + { AFE_PORT_ID_INT0_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT0_MI2S_TX}, + { AFE_PORT_ID_INT1_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT1_MI2S_RX}, + { AFE_PORT_ID_INT1_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT1_MI2S_TX}, + { AFE_PORT_ID_INT2_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT2_MI2S_RX}, + { AFE_PORT_ID_INT2_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT2_MI2S_TX}, + { AFE_PORT_ID_INT3_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT3_MI2S_RX}, + { AFE_PORT_ID_INT3_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT3_MI2S_TX}, + { AFE_PORT_ID_INT4_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT4_MI2S_RX}, + { AFE_PORT_ID_INT4_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT4_MI2S_TX}, + { AFE_PORT_ID_INT5_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT5_MI2S_RX}, + { AFE_PORT_ID_INT5_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT5_MI2S_TX}, + { AFE_PORT_ID_INT6_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT6_MI2S_RX}, + { AFE_PORT_ID_INT6_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INT6_MI2S_TX}, }; /* Track ASM playback & capture sessions of DAI */ @@ -525,7 +553,7 @@ static unsigned long session_copp_map[MSM_FRONTEND_DAI_MM_SIZE][2] [MSM_BACKEND_DAI_MAX]; static struct msm_pcm_routing_app_type_data app_type_cfg[MAX_APP_TYPES]; static struct msm_pcm_stream_app_type_cfg - fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MM_SIZE]; + fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MM_SIZE][2]; /* The caller of this should aqcuire routing lock */ void msm_pcm_routing_get_bedai_info(int be_idx, @@ -569,34 +597,43 @@ static int msm_pcm_routing_get_app_type_idx(int app_type) } void msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int app_type, - int acdb_dev_id, int sample_rate) + int acdb_dev_id, int sample_rate, int session_type) { - pr_debug("%s: fedai_id %d, app_type %d, sample_rate %d\n", - __func__, fedai_id, app_type, sample_rate); + pr_debug("%s: fedai_id %d, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fedai_id, session_type, app_type, + acdb_dev_id, sample_rate); if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { pr_err("%s: Invalid machine driver ID %d\n", __func__, fedai_id); return; } - fe_dai_app_type_cfg[fedai_id].app_type = app_type; - fe_dai_app_type_cfg[fedai_id].acdb_dev_id = acdb_dev_id; - fe_dai_app_type_cfg[fedai_id].sample_rate = sample_rate; + if (session_type != SESSION_TYPE_RX && + session_type != SESSION_TYPE_TX) { + pr_err("%s: Invalid session type %d\n", + __func__, session_type); + return; + } + fe_dai_app_type_cfg[fedai_id][session_type].app_type = app_type; + fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id = acdb_dev_id; + fe_dai_app_type_cfg[fedai_id][session_type].sample_rate = sample_rate; } /** * msm_pcm_routing_get_stream_app_type_cfg * - * Receives fedai_id and populates app_type, acdb_dev_id, & + * Receives fedai_id, session_type and populates app_type, acdb_dev_id, & * sample rate. Returns 0 on success. On failure returns * -EINVAL and does not alter passed values. * * fedai_id - Passed value, front end ID for which app type config is wanted + * session_type - Passed value, session type for which app type config + * is wanted * app_type - Returned value, app type used by app type config * acdb_dev_id - Returned value, ACDB device ID used by app type config * sample_rate - Returned value, sample rate used by app type config */ -int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int *app_type, - int *acdb_dev_id, int *sample_rate) +int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int session_type, + int *app_type, int *acdb_dev_id, int *sample_rate) { int ret = 0; @@ -617,13 +654,20 @@ int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int *app_type, __func__, fedai_id); ret = -EINVAL; goto done; + } else if (session_type != SESSION_TYPE_RX && + session_type != SESSION_TYPE_TX) { + pr_err("%s: Invalid session type %d\n", + __func__, session_type); + ret = -EINVAL; + goto done; } - *app_type = fe_dai_app_type_cfg[fedai_id].app_type; - *acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id; - *sample_rate = fe_dai_app_type_cfg[fedai_id].sample_rate; + *app_type = fe_dai_app_type_cfg[fedai_id][session_type].app_type; + *acdb_dev_id = fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id; + *sample_rate = fe_dai_app_type_cfg[fedai_id][session_type].sample_rate; - pr_debug("%s: fedai_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", - __func__, fedai_id, *app_type, *acdb_dev_id, *sample_rate); + pr_debug("%s: fedai_id %d, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fedai_id, session_type, + *app_type, *acdb_dev_id, *sample_rate); done: return ret; } @@ -680,7 +724,8 @@ static struct cal_block_data *msm_routing_find_topology(int path, return msm_routing_find_topology_by_path(path); } -static int msm_routing_get_adm_topology(int path, int fedai_id) +static int msm_routing_get_adm_topology(int path, int fedai_id, + int session_type) { int topology = NULL_COPP_TOPOLOGY; struct cal_block_data *cal_block = NULL; @@ -693,11 +738,10 @@ static int msm_routing_get_adm_topology(int path, int fedai_id) mutex_lock(&cal_data->lock); - if (path == RX_DEVICE) { - app_type = fe_dai_app_type_cfg[fedai_id].app_type; - acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id; - sample_rate = fe_dai_app_type_cfg[fedai_id].sample_rate; - } + app_type = fe_dai_app_type_cfg[fedai_id][session_type].app_type; + acdb_dev_id = fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id; + sample_rate = fe_dai_app_type_cfg[fedai_id][session_type].sample_rate; + cal_block = msm_routing_find_topology(path, app_type, acdb_dev_id, sample_rate); if (cal_block == NULL) @@ -753,9 +797,12 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, if (num_copps) { payload.num_copps = num_copps; payload.session_id = fe_dai_map[fedai_id][sess_type].strm_id; - payload.app_type = fe_dai_app_type_cfg[fedai_id].app_type; - payload.acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id; - payload.sample_rate = fe_dai_app_type_cfg[fedai_id].sample_rate; + payload.app_type = + fe_dai_app_type_cfg[fedai_id][sess_type].app_type; + payload.acdb_dev_id = + fe_dai_app_type_cfg[fedai_id][sess_type].acdb_dev_id; + payload.sample_rate = + fe_dai_app_type_cfg[fedai_id][sess_type].sample_rate; adm_matrix_map(path_type, payload, perf_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } @@ -863,22 +910,23 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, bit_width = msm_routing_get_bit_width( msm_bedais[i].format); - app_type = (stream_type == SNDRV_PCM_STREAM_PLAYBACK) ? - fe_dai_app_type_cfg[fe_id].app_type : 0; + app_type = + fe_dai_app_type_cfg[fe_id][session_type].app_type; if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx( app_type); sample_rate = - fe_dai_app_type_cfg[fe_id].sample_rate; + fe_dai_app_type_cfg[fe_id][session_type].sample_rate; bit_width = app_type_cfg[app_type_idx].bit_width; } else { sample_rate = msm_bedais[i].sample_rate; } - acdb_dev_id = fe_dai_app_type_cfg[fe_id].acdb_dev_id; + acdb_dev_id = + fe_dai_app_type_cfg[fe_id][session_type].acdb_dev_id; topology = msm_routing_get_adm_topology(path_type, - fe_id); + fe_id, session_type); if (compr_passthr_mode == COMPRESSED_PASSTHROUGH_DSD) topology = COMPRESS_PASSTHROUGH_NONE_TOPOLOGY; pr_err("%s: Before adm open topology %d\n", __func__, @@ -928,8 +976,10 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, if (num_copps) { payload.num_copps = num_copps; payload.session_id = fe_dai_map[fe_id][session_type].strm_id; - payload.app_type = fe_dai_app_type_cfg[fe_id].app_type; - payload.acdb_dev_id = fe_dai_app_type_cfg[fe_id].acdb_dev_id; + payload.app_type = + fe_dai_app_type_cfg[fe_id][session_type].app_type; + payload.acdb_dev_id = + fe_dai_app_type_cfg[fe_id][session_type].acdb_dev_id; adm_matrix_map(path_type, payload, perf_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } @@ -1026,21 +1076,23 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, bits_per_sample = msm_routing_get_bit_width( msm_bedais[i].format); - app_type = (stream_type == SNDRV_PCM_STREAM_PLAYBACK) ? - fe_dai_app_type_cfg[fedai_id].app_type : 0; + app_type = + fe_dai_app_type_cfg[fedai_id][session_type].app_type; if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx(app_type); sample_rate = - fe_dai_app_type_cfg[fedai_id].sample_rate; + fe_dai_app_type_cfg[fedai_id][session_type]. + sample_rate; bits_per_sample = app_type_cfg[app_type_idx].bit_width; } else sample_rate = msm_bedais[i].sample_rate; - acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id; + acdb_dev_id = + fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id; topology = msm_routing_get_adm_topology(path_type, - fedai_id); + fedai_id, session_type); copp_idx = adm_open(msm_bedais[i].port_id, path_type, sample_rate, channels, topology, perf_mode, bits_per_sample, @@ -1085,9 +1137,12 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, if (num_copps) { payload.num_copps = num_copps; payload.session_id = fe_dai_map[fedai_id][session_type].strm_id; - payload.app_type = fe_dai_app_type_cfg[fedai_id].app_type; - payload.acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id; - payload.sample_rate = fe_dai_app_type_cfg[fedai_id].sample_rate; + payload.app_type = + fe_dai_app_type_cfg[fedai_id][session_type].app_type; + payload.acdb_dev_id = + fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id; + payload.sample_rate = + fe_dai_app_type_cfg[fedai_id][session_type].sample_rate; adm_matrix_map(path_type, payload, perf_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } @@ -1255,20 +1310,23 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) bits_per_sample = msm_routing_get_bit_width( msm_bedais[reg].format); - app_type = (session_type == SESSION_TYPE_RX) ? - fe_dai_app_type_cfg[val].app_type : 0; + app_type = + fe_dai_app_type_cfg[val][session_type].app_type; if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx(app_type); sample_rate = - fe_dai_app_type_cfg[val].sample_rate; + fe_dai_app_type_cfg[val][session_type]. + sample_rate; bits_per_sample = app_type_cfg[app_type_idx].bit_width; } else sample_rate = msm_bedais[reg].sample_rate; - topology = msm_routing_get_adm_topology(path_type, val); - acdb_dev_id = fe_dai_app_type_cfg[val].acdb_dev_id; + topology = msm_routing_get_adm_topology(path_type, val, + session_type); + acdb_dev_id = + fe_dai_app_type_cfg[val][session_type].acdb_dev_id; copp_idx = adm_open(msm_bedais[reg].port_id, path_type, sample_rate, channels, topology, fdai->perf_mode, bits_per_sample, @@ -2919,6 +2977,108 @@ static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new int0_mi2s_rx_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new int4_mi2s_rx_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + static const struct snd_kcontrol_new hdmi_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_HDMI_RX, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, @@ -4358,6 +4518,12 @@ static const struct snd_kcontrol_new mmul1_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -4451,6 +4617,12 @@ static const struct snd_kcontrol_new mmul2_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -4526,6 +4698,12 @@ static const struct snd_kcontrol_new mmul3_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -4604,6 +4782,12 @@ static const struct snd_kcontrol_new mmul4_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -4646,6 +4830,12 @@ static const struct snd_kcontrol_new mmul5_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -4703,6 +4893,12 @@ static const struct snd_kcontrol_new mmul6_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -4760,6 +4956,12 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -5113,6 +5315,42 @@ static const struct snd_kcontrol_new pri_mi2s_rx_voice_mixer_controls[] = { msm_routing_put_voice_mixer), }; +static const struct snd_kcontrol_new int0_mi2s_rx_voice_mixer_controls[] = { + SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("VoiceMMode1", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("VoiceMMode2", MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), +}; + +static const struct snd_kcontrol_new int4_mi2s_rx_voice_mixer_controls[] = { + SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("VoiceMMode1", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("VoiceMMode2", MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), +}; + static const struct snd_kcontrol_new tert_mi2s_rx_voice_mixer_controls[] = { SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_TERTIARY_MI2S_RX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer, @@ -5777,6 +6015,9 @@ static const struct snd_kcontrol_new tx_voicemmode1_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX_MMode1", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX_MMode1", + MSM_BACKEND_DAI_INT3_MI2S_TX, MSM_FRONTEND_DAI_VOICEMMODE1, + 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), SOC_SINGLE_EXT("SLIM_7_TX_MMode1", MSM_BACKEND_DAI_SLIMBUS_7_TX, MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), @@ -5822,6 +6063,9 @@ static const struct snd_kcontrol_new tx_voicemmode2_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX_MMode2", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX_MMode2", + MSM_BACKEND_DAI_INT3_MI2S_TX, MSM_FRONTEND_DAI_VOICEMMODE2, + 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), SOC_SINGLE_EXT("SLIM_7_TX_MMode2", MSM_BACKEND_DAI_SLIMBUS_7_TX, MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), @@ -5867,6 +6111,9 @@ static const struct snd_kcontrol_new tx_voip_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX_Voip", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX_Voip", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), SOC_SINGLE_EXT("SLIM_7_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_7_TX, MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), @@ -5900,6 +6147,9 @@ static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer, msm_routing_put_voice_stub_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer, + msm_routing_put_voice_stub_mixer), SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer, msm_routing_put_voice_stub_mixer), @@ -6056,6 +6306,9 @@ static const struct snd_kcontrol_new tx_qchat_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX_QCHAT", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("INT3_MI2S_TX_QCHAT", MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), SOC_SINGLE_EXT("SLIM_7_TX_QCHAT", MSM_BACKEND_DAI_SLIMBUS_7_TX, MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), @@ -7877,6 +8130,12 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_IN("HDMI_DL_HL", "HDMI_HOSTLESS Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SEC_I2S_DL_HL", "SEC_I2S_RX_HOSTLESS Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("INT0_MI2S_DL_HL", + "INT0 MI2S_RX Hostless Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("INT4_MI2S_DL_HL", + "INT4 MI2S_RX Hostless Playback", + 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("PRI_MI2S_DL_HL", "Primary MI2S_RX Hostless Playback", 0, 0, 0, 0), @@ -8150,6 +8409,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("INT0_MI2S_RX", "INT0 MI2S Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("INT4_MI2S_RX", "INT4 MI2S Playback", + 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("QUIN_MI2S_RX", "Quinary MI2S Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0), @@ -8160,6 +8423,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX", "Tertiary MI2S Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("INT2_MI2S_TX", "INT2 MI2S Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("INT3_MI2S_TX", "INT3 MI2S Capture", + 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0), @@ -8444,6 +8711,12 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("PRI_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, primary_mi2s_rx_mixer_controls, ARRAY_SIZE(primary_mi2s_rx_mixer_controls)), + SND_SOC_DAPM_MIXER("INT0_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, + int0_mi2s_rx_mixer_controls, + ARRAY_SIZE(int0_mi2s_rx_mixer_controls)), + SND_SOC_DAPM_MIXER("INT4_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, + int4_mi2s_rx_mixer_controls, + ARRAY_SIZE(int4_mi2s_rx_mixer_controls)), SND_SOC_DAPM_MIXER("QUIN_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, quinary_mi2s_rx_mixer_controls, ARRAY_SIZE(quinary_mi2s_rx_mixer_controls)), @@ -8581,6 +8854,14 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_NOPM, 0, 0, pri_mi2s_rx_voice_mixer_controls, ARRAY_SIZE(pri_mi2s_rx_voice_mixer_controls)), + SND_SOC_DAPM_MIXER("INT0_MI2S_RX_Voice Mixer", + SND_SOC_NOPM, 0, 0, + int0_mi2s_rx_voice_mixer_controls, + ARRAY_SIZE(int0_mi2s_rx_voice_mixer_controls)), + SND_SOC_DAPM_MIXER("INT4_MI2S_RX_Voice Mixer", + SND_SOC_NOPM, 0, 0, + int4_mi2s_rx_voice_mixer_controls, + ARRAY_SIZE(int4_mi2s_rx_voice_mixer_controls)), SND_SOC_DAPM_MIXER("TERT_MI2S_RX_Voice Mixer", SND_SOC_NOPM, 0, 0, tert_mi2s_rx_voice_mixer_controls, @@ -9082,6 +9363,42 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_MI2S_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, {"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Audio Mixer"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"INT0_MI2S_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"INT0_MI2S_RX", NULL, "INT0_MI2S_RX Audio Mixer"}, + + {"INT4_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"INT4_MI2S_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"INT4_MI2S_RX", NULL, "INT4_MI2S_RX Audio Mixer"}, + + {"QUIN_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"QUIN_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"QUIN_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"QUIN_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, {"QUIN_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, @@ -9363,6 +9680,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia2 Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX"}, {"MultiMedia1 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"MultiMedia2 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"MultiMedia1 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"}, + {"MultiMedia2 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"}, + {"MultiMedia1 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"}, + {"MultiMedia2 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"}, {"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"MultiMedia3 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"}, @@ -9384,6 +9705,12 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia6 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"MultiMedia3 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"MultiMedia5 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"MultiMedia6 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"}, + {"MultiMedia3 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"}, + {"MultiMedia5 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"}, + {"MultiMedia6 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"}, + {"MultiMedia3 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"}, + {"MultiMedia5 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"}, {"MultiMedia6 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"MultiMedia6 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"MultiMedia6 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, @@ -9821,6 +10148,20 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_MI2S_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"}, {"PRI_MI2S_RX", NULL, "PRI_MI2S_RX_Voice Mixer"}, + {"INT0_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"}, + {"INT0_MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"}, + {"INT0_MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"}, + {"INT0_MI2S_RX_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"}, + {"INT0_MI2S_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"}, + {"INT0_MI2S_RX", NULL, "INT0_MI2S_RX_Voice Mixer"}, + + {"INT4_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"}, + {"INT4_MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"}, + {"INT4_MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"}, + {"INT4_MI2S_RX_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"}, + {"INT4_MI2S_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"}, + {"INT4_MI2S_RX", NULL, "INT4_MI2S_RX_Voice Mixer"}, + {"TERT_MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"}, {"TERT_MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"}, {"TERT_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"}, @@ -9992,6 +10333,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"VoiceMMode1_Tx Mixer", "PRI_MI2S_TX_MMode1", "PRI_MI2S_TX"}, {"VoiceMMode1_Tx Mixer", "MI2S_TX_MMode1", "MI2S_TX"}, {"VoiceMMode1_Tx Mixer", "TERT_MI2S_TX_MMode1", "TERT_MI2S_TX"}, + {"VoiceMMode1_Tx Mixer", "INT3_MI2S_TX_MMode1", "INT3_MI2S_TX"}, {"VoiceMMode1_Tx Mixer", "SLIM_0_TX_MMode1", "SLIMBUS_0_TX"}, {"VoiceMMode1_Tx Mixer", "SLIM_7_TX_MMode1", "SLIMBUS_7_TX"}, {"VoiceMMode1_Tx Mixer", "SLIM_8_TX_MMode1", "SLIMBUS_8_TX"}, @@ -10008,6 +10350,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"VoiceMMode2_Tx Mixer", "PRI_MI2S_TX_MMode2", "PRI_MI2S_TX"}, {"VoiceMMode2_Tx Mixer", "MI2S_TX_MMode2", "MI2S_TX"}, {"VoiceMMode2_Tx Mixer", "TERT_MI2S_TX_MMode2", "TERT_MI2S_TX"}, + {"VoiceMMode2_Tx Mixer", "INT3_MI2S_TX_MMode2", "INT3_MI2S_TX"}, {"VoiceMMode2_Tx Mixer", "SLIM_0_TX_MMode2", "SLIMBUS_0_TX"}, {"VoiceMMode2_Tx Mixer", "SLIM_7_TX_MMode2", "SLIMBUS_7_TX"}, {"VoiceMMode2_Tx Mixer", "SLIM_8_TX_MMode2", "SLIMBUS_8_TX"}, @@ -10023,6 +10366,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"}, {"Voip_Tx Mixer", "MI2S_TX_Voip", "MI2S_TX"}, {"Voip_Tx Mixer", "TERT_MI2S_TX_Voip", "TERT_MI2S_TX"}, + {"Voip_Tx Mixer", "INT3_MI2S_TX_Voip", "INT3_MI2S_TX"}, {"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"}, {"Voip_Tx Mixer", "SLIM_7_TX_Voip", "SLIMBUS_7_TX"}, {"Voip_Tx Mixer", "SLIM_8_TX_Voip", "SLIMBUS_8_TX"}, @@ -10132,6 +10476,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"QCHAT_Tx Mixer", "MI2S_TX_QCHAT", "MI2S_TX"}, {"QCHAT_Tx Mixer", "PRI_MI2S_TX_QCHAT", "PRI_MI2S_TX"}, {"QCHAT_Tx Mixer", "TERT_MI2S_TX_QCHAT", "TERT_MI2S_TX"}, + {"QCHAT_Tx Mixer", "INT3_MI2S_TX_QCHAT", "INT3_MI2S_TX"}, {"QCHAT_Tx Mixer", "USB_AUDIO_TX_QCHAT", "USB_AUDIO_TX"}, {"QCHAT_UL", NULL, "QCHAT_Tx Mixer"}, @@ -10149,6 +10494,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"MI2S_UL_HL", NULL, "MI2S_TX"}, {"PCM_RX_DL_HL", "Switch", "SLIM0_DL_HL"}, {"PCM_RX", NULL, "PCM_RX_DL_HL"}, + {"INT0_MI2S_RX_DL_HL", "Switch", "INT0_MI2S_DL_HL"}, + {"INT0_MI2S_RX", NULL, "INT0_MI2S_RX_DL_HL"}, + {"INT4_MI2S_RX_DL_HL", "Switch", "INT4_MI2S_DL_HL"}, + {"INT4_MI2S_RX", NULL, "INT4_MI2S_RX_DL_HL"}, {"PRI_MI2S_RX_DL_HL", "Switch", "PRI_MI2S_DL_HL"}, {"PRI_MI2S_RX", NULL, "PRI_MI2S_RX_DL_HL"}, {"SEC_MI2S_RX_DL_HL", "Switch", "SEC_MI2S_DL_HL"}, @@ -10384,6 +10733,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"Voice Stub Tx Mixer", "MI2S_TX", "MI2S_TX"}, {"Voice Stub Tx Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"Voice Stub Tx Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"Voice Stub Tx Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"}, {"Voice Stub Tx Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, {"Voice Stub Tx Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"Voice Stub Tx Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"}, @@ -10561,6 +10911,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "SEC_MI2S_RX"}, {"BE_OUT", NULL, "SEC_MI2S_RX_SD1"}, {"BE_OUT", NULL, "PRI_MI2S_RX"}, + {"BE_OUT", NULL, "INT0_MI2S_RX"}, + {"BE_OUT", NULL, "INT4_MI2S_RX"}, {"BE_OUT", NULL, "INT_BT_SCO_RX"}, {"BE_OUT", NULL, "INT_BT_A2DP_RX"}, {"BE_OUT", NULL, "INT_FM_RX"}, @@ -10593,6 +10945,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUIN_MI2S_TX", NULL, "BE_IN"}, {"PRI_MI2S_TX", NULL, "BE_IN"}, {"TERT_MI2S_TX", NULL, "BE_IN"}, + {"INT2_MI2S_TX", NULL, "BE_IN"}, + {"INT3_MI2S_TX", NULL, "BE_IN"}, {"SEC_MI2S_TX", NULL, "BE_IN"}, {"SENARY_MI2S_TX", NULL, "BE_IN" }, {"SLIMBUS_0_TX", NULL, "BE_IN" }, @@ -10726,7 +11080,6 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) int i, path_type, session_type, topology; struct msm_pcm_routing_bdai_data *bedai; u32 channels, sample_rate; - bool playback, capture; uint16_t bits_per_sample = 16, voc_path_type; struct msm_pcm_routing_fdai_data *fdai; u32 session_id; @@ -10762,8 +11115,6 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) * is started. */ bedai->active = 1; - playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - capture = substream->stream == SNDRV_PCM_STREAM_CAPTURE; for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) { fdai = &fe_dai_map[i][session_type]; @@ -10785,13 +11136,14 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) bits_per_sample = msm_routing_get_bit_width( bedai->format); - app_type = playback ? - fe_dai_app_type_cfg[i].app_type : 0; + app_type = + fe_dai_app_type_cfg[i][session_type].app_type; if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx(app_type); sample_rate = - fe_dai_app_type_cfg[i].sample_rate; + fe_dai_app_type_cfg[i][session_type]. + sample_rate; bits_per_sample = app_type_cfg[app_type_idx].bit_width; } else @@ -10804,8 +11156,10 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) 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); + acdb_dev_id = + fe_dai_app_type_cfg[i][session_type].acdb_dev_id; + topology = msm_routing_get_adm_topology(path_type, i, + session_type); copp_idx = adm_open(bedai->port_id, path_type, sample_rate, channels, topology, fdai->perf_mode, bits_per_sample, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 8e3086849d92..8a62e900ff28 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -143,6 +143,21 @@ #define LPASS_BE_USB_AUDIO_RX "USB_AUDIO_RX" #define LPASS_BE_USB_AUDIO_TX "USB_AUDIO_TX" + +#define LPASS_BE_INT0_MI2S_RX "INT0_MI2S_RX" +#define LPASS_BE_INT0_MI2S_TX "INT0_MI2S_TX" +#define LPASS_BE_INT1_MI2S_RX "INT1_MI2S_RX" +#define LPASS_BE_INT1_MI2S_TX "INT1_MI2S_TX" +#define LPASS_BE_INT2_MI2S_RX "INT2_MI2S_RX" +#define LPASS_BE_INT2_MI2S_TX "INT2_MI2S_TX" +#define LPASS_BE_INT3_MI2S_RX "INT3_MI2S_RX" +#define LPASS_BE_INT3_MI2S_TX "INT3_MI2S_TX" +#define LPASS_BE_INT4_MI2S_RX "INT4_MI2S_RX" +#define LPASS_BE_INT4_MI2S_TX "INT4_MI2S_TX" +#define LPASS_BE_INT5_MI2S_RX "INT5_MI2S_RX" +#define LPASS_BE_INT5_MI2S_TX "INT5_MI2S_TX" +#define LPASS_BE_INT6_MI2S_RX "INT6_MI2S_RX" +#define LPASS_BE_INT6_MI2S_TX "INT6_MI2S_TX" /* For multimedia front-ends, asm session is allocated dynamically. * Hence, asm session/multimedia front-end mapping has to be maintained. * Due to this reason, additional multimedia front-end must be placed before @@ -321,6 +336,20 @@ enum { MSM_BACKEND_DAI_TERT_AUXPCM_TX, MSM_BACKEND_DAI_QUAT_AUXPCM_RX, MSM_BACKEND_DAI_QUAT_AUXPCM_TX, + MSM_BACKEND_DAI_INT0_MI2S_RX, + MSM_BACKEND_DAI_INT0_MI2S_TX, + MSM_BACKEND_DAI_INT1_MI2S_RX, + MSM_BACKEND_DAI_INT1_MI2S_TX, + MSM_BACKEND_DAI_INT2_MI2S_RX, + MSM_BACKEND_DAI_INT2_MI2S_TX, + MSM_BACKEND_DAI_INT3_MI2S_RX, + MSM_BACKEND_DAI_INT3_MI2S_TX, + MSM_BACKEND_DAI_INT4_MI2S_RX, + MSM_BACKEND_DAI_INT4_MI2S_TX, + MSM_BACKEND_DAI_INT5_MI2S_RX, + MSM_BACKEND_DAI_INT5_MI2S_TX, + MSM_BACKEND_DAI_INT6_MI2S_RX, + MSM_BACKEND_DAI_INT6_MI2S_TX, MSM_BACKEND_DAI_MAX, }; @@ -432,7 +461,7 @@ void msm_pcm_routing_acquire_lock(void); void msm_pcm_routing_release_lock(void); void msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int app_type, - int acdb_dev_id, int sample_rate); -int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int *app_type, - int *acdb_dev_id, int *sample_rate); + int acdb_dev_id, int sample_rate, int session_type); +int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int session_type, + int *app_type, int *acdb_dev_id, int *sample_rate); #endif /*_MSM_PCM_H*/ diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index 78546fef7b3b..c75f7214db1a 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -483,6 +483,13 @@ int afe_get_port_type(u16 port_id) case AFE_PORT_ID_QUATERNARY_TDM_RX_6: case AFE_PORT_ID_QUATERNARY_TDM_RX_7: case AFE_PORT_ID_USB_RX: + case AFE_PORT_ID_INT0_MI2S_RX: + case AFE_PORT_ID_INT1_MI2S_RX: + case AFE_PORT_ID_INT2_MI2S_RX: + case AFE_PORT_ID_INT3_MI2S_RX: + case AFE_PORT_ID_INT4_MI2S_RX: + case AFE_PORT_ID_INT5_MI2S_RX: + case AFE_PORT_ID_INT6_MI2S_RX: ret = MSM_AFE_PORT_TYPE_RX; break; @@ -547,6 +554,13 @@ int afe_get_port_type(u16 port_id) case AFE_PORT_ID_QUATERNARY_TDM_TX_6: case AFE_PORT_ID_QUATERNARY_TDM_TX_7: case AFE_PORT_ID_USB_TX: + case AFE_PORT_ID_INT0_MI2S_TX: + case AFE_PORT_ID_INT1_MI2S_TX: + case AFE_PORT_ID_INT2_MI2S_TX: + case AFE_PORT_ID_INT3_MI2S_TX: + case AFE_PORT_ID_INT4_MI2S_TX: + case AFE_PORT_ID_INT5_MI2S_TX: + case AFE_PORT_ID_INT6_MI2S_TX: ret = MSM_AFE_PORT_TYPE_TX; break; diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 2874a334dfdd..22e14f431bb3 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -3015,7 +3015,8 @@ int q6asm_set_shared_circ_buff(struct audio_client *ac, int dir) { struct audio_buffer *buf_circ; - int bytes_to_alloc, rc, len; + int bytes_to_alloc, rc; + size_t len; buf_circ = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL); @@ -3034,7 +3035,7 @@ int q6asm_set_shared_circ_buff(struct audio_client *ac, rc = msm_audio_ion_alloc("audio_client", &buf_circ->client, &buf_circ->handle, bytes_to_alloc, (ion_phys_addr_t *)&buf_circ->phys, - (size_t *)&len, &buf_circ->data); + &len, &buf_circ->data); if (rc) { pr_err("%s: Audio ION alloc is failed, rc = %d\n", __func__, @@ -3076,7 +3077,8 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac, int dir) { struct audio_buffer *buf_pos = &ac->shared_pos_buf; - int len, rc; + int rc; + size_t len; int bytes_to_alloc = sizeof(struct asm_shared_position_buffer); mutex_lock(&ac->cmd_lock); @@ -3085,7 +3087,7 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac, rc = msm_audio_ion_alloc("audio_client", &buf_pos->client, &buf_pos->handle, bytes_to_alloc, - (ion_phys_addr_t *)&buf_pos->phys, (size_t *)&len, + (ion_phys_addr_t *)&buf_pos->phys, &len, &buf_pos->data); if (rc) { @@ -5848,7 +5850,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, struct asm_buffer_node *buffer_node = NULL; int rc = 0; int i = 0; - int cmd_size = 0; + uint32_t cmd_size = 0; uint32_t bufcnt_t; uint32_t bufsz_t; @@ -5870,10 +5872,25 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, bufsz_t = PAGE_ALIGN(bufsz_t); } + if (bufcnt_t > (UINT_MAX + - sizeof(struct avs_cmd_shared_mem_map_regions)) + / sizeof(struct avs_shared_map_region_payload)) { + pr_err("%s: Unsigned Integer Overflow. bufcnt_t = %u\n", + __func__, bufcnt_t); + return -EINVAL; + } + cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions) + (sizeof(struct avs_shared_map_region_payload) * bufcnt_t); + + if (bufcnt > (UINT_MAX / sizeof(struct asm_buffer_node))) { + pr_err("%s: Unsigned Integer Overflow. bufcnt = %u\n", + __func__, bufcnt); + return -EINVAL; + } + buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt, GFP_KERNEL); if (!buffer_node) { diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c index 99f5f0e1a5a5..84e1178dc354 100644 --- a/sound/soc/msm/qdsp6v2/q6audio-v2.c +++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c @@ -233,6 +233,34 @@ int q6audio_get_port_index(u16 port_id) return IDX_AFE_PORT_ID_USB_RX; case AFE_PORT_ID_USB_TX: return IDX_AFE_PORT_ID_USB_TX; + case AFE_PORT_ID_INT0_MI2S_RX: + return IDX_AFE_PORT_ID_INT0_MI2S_RX; + case AFE_PORT_ID_INT0_MI2S_TX: + return IDX_AFE_PORT_ID_INT0_MI2S_TX; + case AFE_PORT_ID_INT1_MI2S_RX: + return IDX_AFE_PORT_ID_INT1_MI2S_RX; + case AFE_PORT_ID_INT1_MI2S_TX: + return IDX_AFE_PORT_ID_INT1_MI2S_TX; + case AFE_PORT_ID_INT2_MI2S_RX: + return IDX_AFE_PORT_ID_INT2_MI2S_RX; + case AFE_PORT_ID_INT2_MI2S_TX: + return IDX_AFE_PORT_ID_INT2_MI2S_TX; + case AFE_PORT_ID_INT3_MI2S_RX: + return IDX_AFE_PORT_ID_INT3_MI2S_RX; + case AFE_PORT_ID_INT3_MI2S_TX: + return IDX_AFE_PORT_ID_INT3_MI2S_TX; + case AFE_PORT_ID_INT4_MI2S_RX: + return IDX_AFE_PORT_ID_INT4_MI2S_RX; + case AFE_PORT_ID_INT4_MI2S_TX: + return IDX_AFE_PORT_ID_INT4_MI2S_TX; + case AFE_PORT_ID_INT5_MI2S_RX: + return IDX_AFE_PORT_ID_INT5_MI2S_RX; + case AFE_PORT_ID_INT5_MI2S_TX: + return IDX_AFE_PORT_ID_INT5_MI2S_TX; + case AFE_PORT_ID_INT6_MI2S_RX: + return IDX_AFE_PORT_ID_INT6_MI2S_RX; + case AFE_PORT_ID_INT6_MI2S_TX: + return IDX_AFE_PORT_ID_INT6_MI2S_TX; default: return -EINVAL; } } @@ -452,6 +480,34 @@ int q6audio_get_port_id(u16 port_id) return AFE_PORT_ID_USB_RX; case AFE_PORT_ID_USB_TX: return AFE_PORT_ID_USB_TX; + case AFE_PORT_ID_INT0_MI2S_RX: + return AFE_PORT_ID_INT0_MI2S_RX; + case AFE_PORT_ID_INT0_MI2S_TX: + return AFE_PORT_ID_INT0_MI2S_TX; + case AFE_PORT_ID_INT1_MI2S_RX: + return AFE_PORT_ID_INT1_MI2S_RX; + case AFE_PORT_ID_INT1_MI2S_TX: + return AFE_PORT_ID_INT1_MI2S_TX; + case AFE_PORT_ID_INT2_MI2S_RX: + return AFE_PORT_ID_INT2_MI2S_RX; + case AFE_PORT_ID_INT2_MI2S_TX: + return AFE_PORT_ID_INT2_MI2S_TX; + case AFE_PORT_ID_INT3_MI2S_RX: + return AFE_PORT_ID_INT3_MI2S_RX; + case AFE_PORT_ID_INT3_MI2S_TX: + return AFE_PORT_ID_INT3_MI2S_TX; + case AFE_PORT_ID_INT4_MI2S_RX: + return AFE_PORT_ID_INT4_MI2S_RX; + case AFE_PORT_ID_INT4_MI2S_TX: + return AFE_PORT_ID_INT4_MI2S_TX; + case AFE_PORT_ID_INT5_MI2S_RX: + return AFE_PORT_ID_INT5_MI2S_RX; + case AFE_PORT_ID_INT5_MI2S_TX: + return AFE_PORT_ID_INT5_MI2S_TX; + case AFE_PORT_ID_INT6_MI2S_RX: + return AFE_PORT_ID_INT6_MI2S_RX; + case AFE_PORT_ID_INT6_MI2S_TX: + return AFE_PORT_ID_INT6_MI2S_TX; default: pr_warn("%s: Invalid port_id %d\n", __func__, port_id); return -EINVAL; @@ -572,6 +628,20 @@ int q6audio_is_digital_pcm_interface(u16 port_id) case AFE_PORT_ID_QUATERNARY_TDM_RX_7: case AFE_PORT_ID_QUATERNARY_TDM_TX_7: case AFE_PORT_ID_SENARY_MI2S_TX: + case AFE_PORT_ID_INT0_MI2S_RX: + case AFE_PORT_ID_INT0_MI2S_TX: + case AFE_PORT_ID_INT1_MI2S_RX: + case AFE_PORT_ID_INT1_MI2S_TX: + case AFE_PORT_ID_INT2_MI2S_RX: + case AFE_PORT_ID_INT2_MI2S_TX: + case AFE_PORT_ID_INT3_MI2S_RX: + case AFE_PORT_ID_INT3_MI2S_TX: + case AFE_PORT_ID_INT4_MI2S_RX: + case AFE_PORT_ID_INT4_MI2S_TX: + case AFE_PORT_ID_INT5_MI2S_RX: + case AFE_PORT_ID_INT5_MI2S_TX: + case AFE_PORT_ID_INT6_MI2S_RX: + case AFE_PORT_ID_INT6_MI2S_TX: break; default: ret = -EINVAL; @@ -710,6 +780,20 @@ int q6audio_validate_port(u16 port_id) case AFE_PORT_ID_SENARY_MI2S_TX: case AFE_PORT_ID_USB_RX: case AFE_PORT_ID_USB_TX: + case AFE_PORT_ID_INT0_MI2S_RX: + case AFE_PORT_ID_INT0_MI2S_TX: + case AFE_PORT_ID_INT1_MI2S_RX: + case AFE_PORT_ID_INT1_MI2S_TX: + case AFE_PORT_ID_INT2_MI2S_RX: + case AFE_PORT_ID_INT2_MI2S_TX: + case AFE_PORT_ID_INT3_MI2S_RX: + case AFE_PORT_ID_INT3_MI2S_TX: + case AFE_PORT_ID_INT4_MI2S_RX: + case AFE_PORT_ID_INT4_MI2S_TX: + case AFE_PORT_ID_INT5_MI2S_RX: + case AFE_PORT_ID_INT5_MI2S_TX: + case AFE_PORT_ID_INT6_MI2S_RX: + case AFE_PORT_ID_INT6_MI2S_TX: { ret = 0; break; diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h index 3b3e728f88f2..834fe7c05306 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.h +++ b/sound/soc/msm/qdsp6v2/q6voice.h @@ -142,7 +142,7 @@ struct share_mem_buf { struct mem_map_table { dma_addr_t phys; void *data; - uint32_t size; /* size of buffer */ + size_t size; /* size of buffer */ struct ion_handle *handle; struct ion_client *client; }; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index c8f45b4efa21..eb894d073c07 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -68,7 +68,8 @@ out: static int soc_compr_open_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; + struct snd_pcm_substream *fe_substream = + fe->pcm->streams[cstream->direction].substream; struct snd_soc_platform *platform = fe->platform; struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; @@ -443,7 +444,8 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, struct snd_compr_params *params) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; + struct snd_pcm_substream *fe_substream = + fe->pcm->streams[cstream->direction].substream; struct snd_soc_platform *platform = fe->platform; struct snd_soc_pcm_runtime *be_list[DPCM_MAX_BE_USERS]; struct snd_soc_dpcm *dpcm; @@ -852,8 +854,8 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) } } - printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name, - cpu_dai->name); + dev_dbg(rtd->card->dev, "compress asoc: %s <-> %s mapping ok\n", + codec_dai->name, cpu_dai->name); return ret; compr_err: diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4ef20ba02cb4..13649f96b370 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -3017,7 +3017,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) pcm->private_free = platform->driver->pcm_free; out: - dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", + dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n", (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, cpu_dai->name); return ret; diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c index 9f7d4e2cb532..22468eee62db 100644 --- a/sound/usb/usb_audio_qmi_svc.c +++ b/sound/usb/usb_audio_qmi_svc.c @@ -68,6 +68,9 @@ struct intf_info { size_t xfer_buf_size; phys_addr_t xfer_buf_pa; u8 *xfer_buf; + u8 pcm_card_num; + u8 pcm_dev_num; + u8 direction; bool in_use; }; @@ -115,6 +118,7 @@ struct uaudio_qmi_svc { struct qmi_handle *uaudio_svc_hdl; void *curr_conn; struct work_struct recv_msg_work; + struct work_struct qmi_disconnect_work; struct workqueue_struct *uaudio_wq; ktime_t t_request_recvd; ktime_t t_resp_sent; @@ -385,7 +389,7 @@ static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va, static int prepare_qmi_response(struct snd_usb_substream *subs, struct qmi_uaudio_stream_resp_msg_v01 *resp, u32 xfer_buf_len, - int card_num) + int card_num, int pcm_dev_num) { int ret = -ENODEV; struct usb_interface *iface; @@ -411,6 +415,14 @@ static int prepare_qmi_response(struct snd_usb_substream *subs, goto err; } + if (uadev[card_num].info && + uadev[card_num].info[subs->interface].in_use) { + pr_err("%s interface# %d already in use card# %d\n", __func__, + subs->interface, card_num); + ret = -EBUSY; + goto err; + } + alts = &iface->altsetting[subs->altset_idx]; altsd = get_iface_desc(alts); protocol = altsd->bInterfaceProtocol; @@ -627,12 +639,6 @@ skip_sync: kref_get(&uadev[card_num].kref); } - if (uadev[card_num].info[subs->interface].in_use) { - pr_err("%s interface# %d already in use card# %d\n", __func__, - subs->interface, card_num); - goto unmap_xfer_buf; - } - uadev[card_num].card_num = card_num; /* cache intf specific info to use it for unmap and free xfer buf */ @@ -644,6 +650,9 @@ skip_sync: uadev[card_num].info[subs->interface].xfer_buf_pa = xfer_buf_pa; uadev[card_num].info[subs->interface].xfer_buf_size = len; uadev[card_num].info[subs->interface].xfer_buf = xfer_buf; + uadev[card_num].info[subs->interface].pcm_card_num = card_num; + uadev[card_num].info[subs->interface].pcm_dev_num = pcm_dev_num; + uadev[card_num].info[subs->interface].direction = subs->direction; uadev[card_num].info[subs->interface].in_use = true; set_bit(card_num, &uaudio_qdev->card_slot); @@ -665,9 +674,71 @@ err: return ret; } -void uaudio_disconnect_cb(struct snd_usb_audio *chip) +static void uaudio_dev_intf_cleanup(struct usb_device *udev, + struct intf_info *info) +{ + uaudio_iommu_unmap(MEM_XFER_RING, info->data_xfer_ring_va, + info->data_xfer_ring_size); + info->data_xfer_ring_va = 0; + info->data_xfer_ring_size = 0; + + uaudio_iommu_unmap(MEM_XFER_RING, info->sync_xfer_ring_va, + info->sync_xfer_ring_size); + info->sync_xfer_ring_va = 0; + info->sync_xfer_ring_size = 0; + + uaudio_iommu_unmap(MEM_XFER_BUF, info->xfer_buf_va, + info->xfer_buf_size); + info->xfer_buf_va = 0; + + usb_free_coherent(udev, info->xfer_buf_size, + info->xfer_buf, info->xfer_buf_pa); + info->xfer_buf_size = 0; + info->xfer_buf = NULL; + info->xfer_buf_pa = 0; + + info->in_use = false; +} + +static void uaudio_dev_cleanup(struct uaudio_dev *dev) { - int ret, if_idx; + int if_idx; + + /* free xfer buffer and unmap xfer ring and buf per interface */ + for (if_idx = 0; if_idx < dev->num_intf; if_idx++) { + if (!dev->info[if_idx].in_use) + continue; + uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]); + pr_debug("%s: release resources: intf# %d card# %d\n", __func__, + if_idx, dev->card_num); + } + + /* iommu_unmap dcba iova for a usb device */ + uaudio_iommu_unmap(MEM_DCBA, dev->dcba_iova, dev->dcba_size); + + dev->dcba_iova = 0; + dev->dcba_size = 0; + dev->num_intf = 0; + + /* free interface info */ + kfree(dev->info); + dev->info = NULL; + + clear_bit(dev->card_num, &uaudio_qdev->card_slot); + + /* all audio devices are disconnected */ + if (!uaudio_qdev->card_slot) { + uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE); + usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num); + pr_debug("%s: all audio devices disconnected\n", __func__); + } + + dev->udev = NULL; +} + +static void uaudio_disconnect_cb(struct snd_usb_audio *chip) +{ + int ret; struct uaudio_dev *dev; int card_num = chip->card_num; struct uaudio_qmi_svc *svc = uaudio_svc; @@ -713,57 +784,7 @@ void uaudio_disconnect_cb(struct snd_usb_audio *chip) mutex_lock(&chip->dev_lock); } - /* free xfer buffer and unmap xfer ring and buf per interface */ - for (if_idx = 0; if_idx < dev->num_intf; if_idx++) { - if (!dev->info[if_idx].in_use) - continue; - usb_free_coherent(dev->udev, - dev->info[if_idx].xfer_buf_size, - dev->info[if_idx].xfer_buf, - dev->info[if_idx].xfer_buf_pa); - - uaudio_iommu_unmap(MEM_XFER_RING, - dev->info[if_idx].data_xfer_ring_va, - dev->info[if_idx].data_xfer_ring_size); - dev->info[if_idx].data_xfer_ring_va = 0; - dev->info[if_idx].data_xfer_ring_size = 0; - - uaudio_iommu_unmap(MEM_XFER_RING, - dev->info[if_idx].sync_xfer_ring_va, - dev->info[if_idx].sync_xfer_ring_size); - dev->info[if_idx].sync_xfer_ring_va = 0; - dev->info[if_idx].sync_xfer_ring_size = 0; - - uaudio_iommu_unmap(MEM_XFER_BUF, - dev->info[if_idx].xfer_buf_va, - dev->info[if_idx].xfer_buf_size); - dev->info[if_idx].xfer_buf_va = 0; - dev->info[if_idx].xfer_buf_size = 0; - pr_debug("%s: release resources: intf# %d card# %d\n", __func__, - if_idx, card_num); - } - - /* iommu_unmap dcba iova for a usb device */ - uaudio_iommu_unmap(MEM_DCBA, dev->dcba_iova, dev->dcba_size); - - dev->dcba_iova = 0; - dev->dcba_size = 0; - dev->num_intf = 0; - - /* free interface info */ - kfree(dev->info); - dev->info = NULL; - - clear_bit(card_num, &uaudio_qdev->card_slot); - - /* all audio devices are disconnected */ - if (!uaudio_qdev->card_slot) { - uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE); - usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num); - pr_debug("%s: all audio devices disconnected\n", __func__); - } - - dev->udev = NULL; + uaudio_dev_cleanup(dev); done: mutex_unlock(&chip->dev_lock); } @@ -789,7 +810,7 @@ static void uaudio_dev_release(struct kref *kref) } /* maps audio format received over QMI to asound.h based pcm format */ -int map_pcm_format(unsigned int fmt_received) +static int map_pcm_format(unsigned int fmt_received) { switch (fmt_received) { case USB_QMI_PCM_FORMAT_S8: @@ -903,7 +924,7 @@ static int handle_uaudio_stream_req(void *req_h, void *req) if (!ret && req_msg->enable) ret = prepare_qmi_response(subs, &resp, req_msg->xfer_buff_size, - pcm_card_num); + pcm_card_num, pcm_dev_num); mutex_unlock(&chip->dev_lock); @@ -912,31 +933,7 @@ response: if (intf_num >= 0) { mutex_lock(&chip->dev_lock); info = &uadev[pcm_card_num].info[intf_num]; - uaudio_iommu_unmap(MEM_XFER_RING, - info->data_xfer_ring_va, - info->data_xfer_ring_size); - info->data_xfer_ring_va = 0; - info->data_xfer_ring_size = 0; - - uaudio_iommu_unmap(MEM_XFER_RING, - info->sync_xfer_ring_va, - info->sync_xfer_ring_size); - info->sync_xfer_ring_va = 0; - info->sync_xfer_ring_size = 0; - - uaudio_iommu_unmap(MEM_XFER_BUF, - info->xfer_buf_va, - info->xfer_buf_size); - info->xfer_buf_va = 0; - - usb_free_coherent(uadev[pcm_card_num].udev, - info->xfer_buf_size, - info->xfer_buf, - info->xfer_buf_pa); - info->xfer_buf_size = 0; - info->xfer_buf = NULL; - info->xfer_buf_pa = 0; - info->in_use = false; + uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info); pr_debug("%s:release resources: intf# %d card# %d\n", __func__, intf_num, pcm_card_num); mutex_unlock(&chip->dev_lock); @@ -980,6 +977,43 @@ static int uaudio_qmi_svc_connect_cb(struct qmi_handle *handle, return 0; } +static void uaudio_qmi_disconnect_work(struct work_struct *w) +{ + struct intf_info *info; + int idx, if_idx; + struct snd_usb_substream *subs; + struct snd_usb_audio *chip = NULL; + + /* find all active intf for set alt 0 and cleanup usb audio dev */ + for (idx = 0; idx < SNDRV_CARDS; idx++) { + if (!atomic_read(&uadev[idx].in_use)) + continue; + + for (if_idx = 0; if_idx < uadev[idx].num_intf; if_idx++) { + if (!uadev[idx].info || !uadev[idx].info[if_idx].in_use) + continue; + info = &uadev[idx].info[if_idx]; + subs = find_snd_usb_substream(info->pcm_card_num, + info->pcm_dev_num, + info->direction, + &chip, + uaudio_disconnect_cb); + if (!subs || !chip || atomic_read(&chip->shutdown)) { + pr_debug("%s:no subs for c#%u, dev#%u dir%u\n", + __func__, info->pcm_card_num, + info->pcm_dev_num, + info->direction); + continue; + } + snd_usb_enable_audio_stream(subs, 0); + } + atomic_set(&uadev[idx].in_use, 0); + mutex_lock(&chip->dev_lock); + uaudio_dev_cleanup(&uadev[idx]); + mutex_unlock(&chip->dev_lock); + } +} + static int uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle, void *conn_h) { @@ -991,6 +1025,8 @@ static int uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle, } svc->curr_conn = NULL; + queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work); + return 0; } @@ -1195,6 +1231,7 @@ static int uaudio_qmi_svc_init(void) } INIT_WORK(&svc->recv_msg_work, uaudio_qmi_svc_recv_msg); + INIT_WORK(&svc->qmi_disconnect_work, uaudio_qmi_disconnect_work); uaudio_svc = svc; |
