diff options
author | Steve Pfetsch <spfetsch@google.com> | 2016-05-03 12:49:49 -0700 |
---|---|---|
committer | Steve Pfetsch <spfetsch@google.com> | 2016-05-03 12:49:49 -0700 |
commit | 42408dde031eb14e0ebfa2a27993f01422f7de53 (patch) | |
tree | 99fa5fe0fee21d0edfbe44c9d31686e46299fb38 | |
parent | 703c92069d9571adfc77eb3646654d3333d2c434 (diff) | |
parent | 452dd7ba0b1179321d1bea5b5a800d956378c05b (diff) |
Merge AU_LINUX_ANDROID_LA.HB.1.3.9.06.00.01.213.156 into android-msm-marlin-3.18
Conflicts:
arch/arm/mm/mmap.c
drivers/gpu/msm/adreno_a5xx.c
drivers/video/msm/mdss/msm_mdss_io_8974.c
kernel/trace/trace_event_perf.c
sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
Change-Id: I66e83a530e2314ab43fc5a4ed205662853418f98
256 files changed, 6058 insertions, 2402 deletions
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index e6c12d4f9741..297a1835a921 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -210,6 +210,20 @@ nodes to be present and contain the properties described below. property identifying a 64-bit zero-initialised memory location. + - efficiency + Usage: optional. + Value type: <u32> + Definition: + # Specifies the CPU efficiency. The CPU efficiency is + a unit less number and it is intended to show relative + performance of CPUs when normalized for clock frequency + (instructions per cycle performance). + + The efficiency of a CPU can vary across SoCs depending + on the cache size, bus interconnect frequencies etc. + This value overrides the default efficiency value + defined for the corresponding CPU architecture. + - qcom,saw Usage: required for systems that have an "enable-method" property value of "qcom,kpss-acc-v1" or diff --git a/Documentation/devicetree/bindings/arm/msm/adv7481.txt b/Documentation/devicetree/bindings/arm/msm/adv7481.txt new file mode 100644 index 000000000000..ea5fc3025fe2 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/adv7481.txt @@ -0,0 +1,20 @@ +ADV7481 chip driver (VIDEO_ADV7481) + +VIDEO_ADV7481 is a kernel platform driver that is used for video decoder +and dual mode HDMI/MHL receiver. + +The devicetree representation of the VIDEO_ADV7481 block should be: + +Required properties + +- compatible: "qcom,adv7481" +- qcom,slave-addr: The i2c slave address of adv7481 driver. +- qcom,cci-master: The i2c master id to be used for adv7481 driver. + +Example: + + qcom,adv7481@0 { + compatible = "qcom,adv7481"; + qcom,cci-master = <0>; + qcom,slave-addr = <0x70>; + }; diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt index e6be8e7e25b7..f7af14b1343d 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt @@ -224,6 +224,12 @@ Optional child nodes qcom,mx-restriction-temp and qcom,mx-restriction-temp-hysteresis should also be present. Also, if this property is defined, will have to define vdd-cx-supply = <&phandle_of_regulator>. +- qcom,mx-restriction-sensor_id: sensor id, which needs to be monitored for requesting MX/CX + retention voltage. If this optional property is defined, msm_thermal + will monitor only this sensor, otherwise by default it will monitor + all TSENS for this feature. If this property exists, then the properties, + qcom,mx-restriction-temp, qcom,mx-restriction-temp-hysteresis and + qcom,mx-retention-min should also be defined to enable this feature. - qcom,therm-reset-temp: Degree above which the KTM will initiate a secure watchdog reset. When this property is defined, KTM will monitor all the tsens from boot time and will initiate a secure watchdog reset if any of the @@ -269,6 +275,7 @@ Example: qcom,mx-restriction-temp = <5>; qcom,mx-restriction-temp-hysteresis = <10>; qcom,mx-retention-min = <710000>; + qcom,mx-restriction-sensor_id = <2>; vdd-mx-supply = <&pma8084_s1>; qcom,cx-retention-min = <RPM_SMD_REGULATOR_LEVEL_RETENTION_PLUS>; vdd-cx-supply = <&pmd9635_s5_level>; diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt index b2c9a24aca7d..50402892a9b0 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt @@ -416,7 +416,11 @@ Optional properties: fields in the supply entry, refer to the qcom,ctrl-supply-entries binding above. - qcom,config-select: Optional property to select default configuration. - +- qcom,panel-allow-phy-poweroff: A boolean property indicates that panel allows to turn off the phy power + supply during idle screen. A panel should able to handle the dsi lanes + in floating state(not LP00 or LP11) to turn on this property. Software + turns off PHY pmic power supply, phy ldo and DSI Lane ldo during + idle screen (footswitch control off) when this property is enabled. [[Optional config sub-nodes]] These subnodes provide different configurations for a given same panel. Default configuration can be chosen by specifying phandle of the selected subnode in the qcom,config-select. @@ -602,6 +606,7 @@ Example: qcom,suspend-ulps-enabled; qcom,panel-roi-alignment = <4 4 2 2 20 20>; qcom,esd-check-enabled; + qcom,panel-allow-phy-poweroff; qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 02 0A 08]; qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode"; qcom,mdss-dsi-panel-status-check-mode = "reg_read"; diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt index 949ecc6bcea4..c6eae2af4067 100644 --- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt +++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt @@ -528,6 +528,10 @@ Fudge Factors: Fudge factors are used to boost demand for - qcom,mdss-rot-reg-bus: Property to provide Bus scaling for register access for Rotator Block. +- qcom,mdss-hw-rt: Optional Property to request min vote on the bus. + Few Low tier targets expect min vote on the bus during SMMU + and TZ operations. use this handle to request the vote needed. + Optional subnodes: - mdss_fb: Child nodes representing the frame buffer virtual devices. @@ -838,6 +842,16 @@ Example: <1 590 0 320000>; }; + qcom,mdss-hw-rt-bus { + /* hw-rt Bus Scale Settings */ + qcom,msm-bus,name = "mdss_hw_rt"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <22 512 0 0>, + <22 512 0 1000>; + }; + smmu_mdp_sec: qcom,smmu_mdp_sec_cb { compatible = "qcom,smmu_mdp_sec"; iommus = <&mdp_smmu 1>; diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt index e55e64eea1ea..216076c52526 100644 --- a/Documentation/devicetree/bindings/gpu/adreno.txt +++ b/Documentation/devicetree/bindings/gpu/adreno.txt @@ -130,6 +130,19 @@ Optional Properties: rendering thread is running on masked CPUs. Bit 0 is for CPU-0, bit 1 is for CPU-1... +- qcom,snapshot-size: + Specify the size of snapshot in bytes. This will override + snapshot size defined in the driver code. + +- qcom,enable-ca-jump: + Boolean. Enables use of context aware DCVS +- qcom,ca-busy-penalty: + This property represents the time in microseconds required to + initiate context aware power level jump. +- qcom,ca-target-pwrlevel: + This value indicates which qcom,gpu-pwrlevel to jump on in case + of context aware power level jump. + GPU Quirks: - qcom,gpu-quirk-two-pass-use-wfi: Signal the GPU to set Set TWOPASSUSEWFI bit in @@ -207,6 +220,15 @@ Example of A330 GPU in MSM8916: coresight-child-list = <&funnel_in0>; coresight-child-ports = <5>; + /* Enable context aware freq. scaling */ + qcom,enable-ca-jump; + + /* Context aware jump busy penalty in us */ + qcom,ca-busy-penalty = <12000>; + + /* Context aware jump target power level */ + qcom,ca-target-pwrlevel = <1>; + /* Power levels */ qcom,gpu-pwrlevels-bins { #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/pci/msm_pcie.txt b/Documentation/devicetree/bindings/pci/msm_pcie.txt index 34480b77670d..d4f566bcf3c0 100644 --- a/Documentation/devicetree/bindings/pci/msm_pcie.txt +++ b/Documentation/devicetree/bindings/pci/msm_pcie.txt @@ -91,6 +91,10 @@ Optional Properties: from the endpoint. - linux,pci-domain: For details of pci-domains properties, please refer to: "Documentation/devicetree/bindings/pci/pci.txt" + - qcom,perst-delay-us-min: The minimum allowed time (unit: us) to sleep after + asserting or de-asserting PERST GPIO. + - qcom,perst-delay-us-max: The maximum allowed time (unit: us) to sleep after + asserting or de-asserting PERST GPIO. - qcom,tlp-rd-size: The max TLP read size (Calculation: 128 times 2 to the tlp-rd-size power). - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for diff --git a/Documentation/devicetree/bindings/regulator/cpr3-regulator.txt b/Documentation/devicetree/bindings/regulator/cpr3-regulator.txt index 0a5ad543a2be..7d88e9fbd9c6 100644 --- a/Documentation/devicetree/bindings/regulator/cpr3-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/cpr3-regulator.txt @@ -183,6 +183,19 @@ Platform independent properties: This is the voltage that vdd-supply must be set to when performing an aging measurement. +- qcom,cpr-panic-reg-addr-list + Usage: optional + Value type: <prop-encoded-array> + Definition: Array of register addresses to be dumped when device resets. + +- qcom,cpr-panic-reg-name-list + Usage: optional, though only meaningful if + qcom,cpr-panic-reg-addr-list is specified + Value type: <prop-encoded-array> + Definition: Address names. Must be specified in the same order + as the corresponding addresses are specified in + the qcom,cpr-panic-reg-addr-list property. + ================================================= Second Level Nodes - CPR Threads for a Controller ================================================= diff --git a/Documentation/devicetree/bindings/regulator/cpr4-apss-regulator.txt b/Documentation/devicetree/bindings/regulator/cpr4-apss-regulator.txt index 454fa3a4c071..29bb2d32bf91 100644 --- a/Documentation/devicetree/bindings/regulator/cpr4-apss-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/cpr4-apss-regulator.txt @@ -407,6 +407,13 @@ apc_cpr: cpr4-ctrl@b018000 { qcom,cpr-step-quot-fixed = <16>; qcom,cpr-voltage-settling-time = <1600>; + qcom,cpr-panic-reg-addr-list = + <0xb1d2c18 0xb1d2900 0x0b1112b0 0xb018798>; + qcom,cpr-panic-reg-name-list = + "CCI_SAW4_PMIC_STS", "CCI_SAW4_VCTL", + "APCS_ALIAS0_APM_CTLER_STATUS", + "APCS0_CPR_CORE_ADJ_MODE_REG"; + thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <1>; diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt index 48cc084de720..e5304f8852f9 100644 --- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt +++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt @@ -47,12 +47,6 @@ Optional properties : - hsic,resume-gpio : if present then periperal connected to hsic controller cannot wakeup from XO shutdown using in-band hsic resume. Use resume gpio to wakeup peripheral -- hsic,ignore-cal-pad-config : If present then HSIC CAL PAD configuration - using TLMM is not performed. -- hsic,strobe-pad-offset : Offset of TLMM register for configuring HSIC - STROBE GPIO PAD. -- hsic,data-pad-offset : Offset of TLMM register for configuring HSIC - DATA GPIO PAD. - qcom,phy-sof-workaround : If present then HSIC PHY has h/w BUGs related to SOFs. All the relevant software workarounds are required for the same during suspend, reset and resume. diff --git a/Documentation/scheduler/sched-zone.txt b/Documentation/scheduler/sched-zone.txt index 253391be357c..6a8dc675bf47 100644 --- a/Documentation/scheduler/sched-zone.txt +++ b/Documentation/scheduler/sched-zone.txt @@ -1293,7 +1293,7 @@ categorized as small wakee tasks. Scheduler places small wakee tasks on the waker's cluster. -*** 7.26 sched_big_waker_task_load +*** 7.27 sched_big_waker_task_load Appears at: /proc/sys/kernel/sched_big_waker_task_load @@ -1303,6 +1303,23 @@ This tunable is a percentage. Configure the minimum demand of big sync waker task. Scheduler places small wakee tasks woken up by big sync waker on the waker's cluster. +*** 7.28 sched_prefer_sync_wakee_to_waker + +Appears at: /proc/sys/kernel/sched_prefer_sync_wakee_to_waker + +Default value: 0 + +The default sync wakee policy has a preference to select an idle CPU in the +waker cluster compared to the waker CPU running only 1 task. By selecting +an idle CPU, it eliminates the chance of waker migrating to a different CPU +after the wakee preempts it. This policy is also not susceptible to the +incorrect "sync" usage i.e the waker does not goto sleep after waking up +the wakee. + +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. + ========================= 8. HMP SCHEDULER TRACE POINTS ========================= diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 1a1a3b8a2f1d..b641a42c7f8a 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -154,7 +154,8 @@ dtb-$(CONFIG_ARCH_MSM8940) += msm8940-pmi8937-cdp.dtb \ msm8940-pmi8950-mtp.dtb \ msm8940-pmi8937-rcm.dtb \ msm8940-pmi8950-rcm.dtb \ - msm8940-pmi8950-qrd-sku6.dtb + msm8940-pmi8950-qrd-sku6.dtb \ + msm8940-pmi8950-ext-codec-cdp.dtb dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ msm8953-rumi.dtb \ diff --git a/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi b/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi index 3ab4b5714eee..fce4c0a2cb42 100644 --- a/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi +++ b/arch/arm/boot/dts/qcom/apq8096-sbc.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 @@ -330,8 +330,8 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,mdss-dsi-bl-pmic-pwm-frequency = <50>; qcom,mdss-dsi-bl-pmic-bank-select = <0>; - qcom,mdss-dsi-pwm-gpio = <&pm8994_gpios 6 0>; - qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,mdss-dsi-pwm-gpio = <&pm8994_gpios 5 0>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>; }; &mdss_mdp { @@ -363,12 +363,11 @@ }; &labibb { - status = "ok"; - qpnp,qpnp-labibb-mode = "lcd"; + status = "disabled"; }; &ibb_regulator { - qcom,qpnp-ibb-discharge-resistor = <32>; + status = "disabled"; }; &rpm_bus { diff --git a/arch/arm/boot/dts/qcom/apq8096-v3-pmi8996-mdm9x55-i2s-mtp.dts b/arch/arm/boot/dts/qcom/apq8096-v3-pmi8996-mdm9x55-i2s-mtp.dts index 3e4d11122e01..599115d6e4a0 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v3-pmi8996-mdm9x55-i2s-mtp.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v3-pmi8996-mdm9x55-i2s-mtp.dts @@ -111,3 +111,153 @@ status = "okay"; }; }; + +&soc { + sound { + status = "disabled"; + }; + + sound-9335 { + status = "disabled"; + }; + + slim_msm: slim@91c0000 { + status = "disabled"; + }; + + clock_audio: audio_ext_clk { + compatible = "qcom,audio-ref-clk"; + qcom,codec-mclk-clk-freq = <12288000>; + pinctrl-names = "sleep", "active"; + pinctrl-0 = <&spkr_i2s_clk_sleep &ap_mclk_sleep + &mdm_mclk_sleep>; + pinctrl-1 = <&spkr_i2s_clk_active &ap_mclk_active + &mdm_mclk_sleep>; + }; + + i2c_7: i2c@75b5000 { + wcd9xxx_codec@d { + compatible = "qcom,tasha-i2c-pgd"; + reg = <0x0d>; + + interrupt-parent = <&wcd9xxx_intc>; + interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 + 30>; + + qcom,cdc-reset-gpio = <&tlmm 64 0>; + + clock-names = "wcd_clk"; + clocks = <&clock_audio clk_audio_lpass_mclk2>; + + cdc-vdd-buck-supply = <&pm8994_s4>; + qcom,cdc-vdd-buck-voltage = <1800000 1800000>; + qcom,cdc-vdd-buck-current = <650000>; + + cdc-buck-sido-supply = <&pm8994_s4>; + qcom,cdc-buck-sido-voltage = <1800000 1800000>; + qcom,cdc-buck-sido-current = <250000>; + + cdc-vdd-tx-h-supply = <&pm8994_s4>; + qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>; + qcom,cdc-vdd-tx-h-current = <25000>; + + cdc-vdd-rx-h-supply = <&pm8994_s4>; + qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>; + qcom,cdc-vdd-rx-h-current = <25000>; + + cdc-vddpx-1-supply = <&pm8994_s4>; + qcom,cdc-vddpx-1-voltage = <1800000 1800000>; + qcom,cdc-vddpx-1-current = <10000>; + + qcom,cdc-static-supplies = "cdc-vdd-buck", + "cdc-buck-sido", + "cdc-vdd-tx-h", + "cdc-vdd-rx-h", + "cdc-vddpx-1"; + + qcom,cdc-micbias1-mv = <1800>; + qcom,cdc-micbias2-mv = <1800>; + qcom,cdc-micbias3-mv = <1800>; + qcom,cdc-micbias4-mv = <1800>; + + qcom,cdc-mclk-clk-rate = <12288000>; + qcom,cdc-dmic-sample-rate = <4800000>; + }; + }; + + sound-9335-i2c { + compatible = "qcom,apq8096-asoc-snd-tasha-i2c"; + qcom,model = "apq8096-tasha-i2c-snd-card"; + + qcom,audio-routing = + "AIF4 VI", "MCLK", + "RX_BIAS", "MCLK", + "MADINPUT", "MCLK", + "AMIC2", "MIC BIAS2", + "MIC BIAS2", "Headset Mic", + "AMIC3", "MIC BIAS2", + "MIC BIAS2", "ANCRight Headset Mic", + "AMIC4", "MIC BIAS2", + "MIC BIAS2", "ANCLeft Headset Mic", + "AMIC5", "MIC BIAS3", + "MIC BIAS3", "Handset Mic", + "AMIC6", "MIC BIAS4", + "MIC BIAS4", "Analog Mic6", + "DMIC0", "MIC BIAS1", + "MIC BIAS1", "Digital Mic0", + "DMIC1", "MIC BIAS1", + "MIC BIAS1", "Digital Mic1", + "DMIC2", "MIC BIAS3", + "MIC BIAS3", "Digital Mic2", + "DMIC3", "MIC BIAS3", + "MIC BIAS3", "Digital Mic3", + "DMIC4", "MIC BIAS4", + "MIC BIAS4", "Digital Mic4", + "DMIC5", "MIC BIAS4", + "MIC BIAS4", "Digital Mic5", + "SpkrLeft IN", "SPK1 OUT", + "SpkrRight IN", "SPK2 OUT"; + + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <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_pri_auxpcm>, <&dai_sec_auxpcm>, <&dai_hdmi>, + <&dai_mi2s>, <&dai_mi2s_quat>, + <&afe_pcm_rx>, <&afe_pcm_tx>, + <&afe_proxy_rx>, <&afe_proxy_tx>, + <&incall_record_rx>, <&incall_record_tx>, + <&incall_music_rx>, <&incall_music2_rx>; + asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2", + "msm-dai-q6-hdmi.8", + "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", + "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"; + qcom,tasha-mclk-clk-freq = <12288000>; + asoc-codec = <&stub_codec>; + asoc-codec-names = "msm-stub-codec.1"; + }; + + qcom,msm-dai-mi2s { + dai_mi2s_quat: qcom,msm-dai-q6-mi2s-quat { + compatible = "qcom,msm-dai-q6-mi2s"; + qcom,msm-dai-q6-mi2s-dev-id = <3>; + qcom,msm-mi2s-rx-lines = <2>; + qcom,msm-mi2s-tx-lines = <1>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&quat_mi2s_active &quat_mi2s_sd0_active>; + pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_sd0_sleep>; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/mdm9607.dtsi b/arch/arm/boot/dts/qcom/mdm9607.dtsi index c0fe6e033e13..d25bde94cc88 100644 --- a/arch/arm/boot/dts/qcom/mdm9607.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9607.dtsi @@ -614,7 +614,7 @@ vdd-supply = <&mdm9607_l9>; qcom,vdd-voltage-level = <0 1225000 1225000>; qcom,hsic-tlmm-init-seq = - <0x12008 0x5 0x12004 0x5 0x12000 0x1 0x8 0x400000>; + <0x12008 0x5 0x12004 0x5 0x12000 0x1>; qcom,hsic-disable-on-boot; clocks = <&clock_gcc clk_gcc_usb_hsic_ahb_clk>, @@ -640,6 +640,36 @@ status = "disabled"; }; + hsic_host: hsic_host@7c00000 { + compatible = "qcom,hsic-host"; + reg = <0x7c00000 0x352>, + <0x1100000 0x1200c>; + interrupts = <0 141 0>, <0 142 0>; + interrupt-names = "core_irq", "async_irq"; + hsic_vdd_dig-supply = <&mdm9607_l9>; + hsic,vdd-voltage-level = <0 1225000 1225000>; + qcom,hsic-tlmm-init-seq = + <0x12008 0x5 0x12004 0x5 0x12000 0x1>; + qcom,phy-susp-sof-workaround; + qcom,disable-internal-clk-gating; + + clocks = <&clock_gcc clk_gcc_usb_hsic_ahb_clk>, + <&clock_gcc clk_gcc_usb_hsic_system_clk>, + <&clock_gcc clk_gcc_usb_hsic_clk>, + <&clock_gcc clk_gcc_usb_hsic_io_cal_clk>, + <&clock_gcc clk_gcc_usb_hsic_io_cal_sleep_clk>; + clock-names = "iface_clk", "core_clk", "phy_clk", + "cal_clk", "inactivity_clk"; + + qcom,msm-bus,name = "hsic"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <85 512 0 0>, + <85 512 60000 800000>; + status = "disabled"; + }; + qnand_1: nand@7980000 { compatible = "qcom,msm-nand"; reg = <0x07980000 0x1000>, diff --git a/arch/arm/boot/dts/qcom/mdmcalifornium-nand-dualwifi-mtp.dts b/arch/arm/boot/dts/qcom/mdmcalifornium-nand-dualwifi-mtp.dts index 3482bd58970d..255a4ec37a3e 100644 --- a/arch/arm/boot/dts/qcom/mdmcalifornium-nand-dualwifi-mtp.dts +++ b/arch/arm/boot/dts/qcom/mdmcalifornium-nand-dualwifi-mtp.dts @@ -28,3 +28,34 @@ &cnss_sdio { status = "ok"; }; + +&sdhc_1 { + vdd-supply = <&sdc_vreg>; + vdd-io-supply = <&pmdcalifornium_l7>; + qcom,vdd-io-voltage-level = <1800000 1800000>; + qcom,vdd-io-always-on; + qcom,vdd-io-current-level = <200 10000>; + + qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 + 200000000>; + qcom,bus-width = <4>; + qcom,core_3_0v_support; + qcom,nonremovable; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on + &sdc1_wlan_gpio_active>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off + &sdc1_wlan_gpio_sleep>; + #address-cells = <0>; + interrupt-parent = <&sdhc_1>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 123 0 + 1 &intc 0 138 0 + 2 &tlmm_pinmux 93 0x4>; + interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq"; + + status = "ok"; +}; diff --git a/arch/arm/boot/dts/qcom/mdmcalifornium-pinctrl.dtsi b/arch/arm/boot/dts/qcom/mdmcalifornium-pinctrl.dtsi index 1afbd2f85f8c..80c57d7973d4 100644 --- a/arch/arm/boot/dts/qcom/mdmcalifornium-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/mdmcalifornium-pinctrl.dtsi @@ -356,13 +356,13 @@ pcie0_wake_default: pcie0_wake_default { mux { - pins = "gpio65"; + pins = "gpio61"; function = "gpio"; }; config { - pins = "gpio65"; + pins = "gpio61"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; }; diff --git a/arch/arm/boot/dts/qcom/mdmcalifornium.dtsi b/arch/arm/boot/dts/qcom/mdmcalifornium.dtsi index 5b06606e535a..72cdc2c3ae4a 100644 --- a/arch/arm/boot/dts/qcom/mdmcalifornium.dtsi +++ b/arch/arm/boot/dts/qcom/mdmcalifornium.dtsi @@ -361,7 +361,7 @@ &pcie0_wake_default>; perst-gpio = <&tlmm_pinmux 60 0>; - wake-gpio = <&tlmm_pinmux 65 0>; + wake-gpio = <&tlmm_pinmux 61 0>; gdsc-vdd-supply = <&gdsc_pcie>; vreg-1.8-supply = <&pmdcalifornium_l5>; @@ -830,7 +830,6 @@ #address-cells = <1>; #size-cells = <0>; cell-index = <0>; - qcom,not-wakeup; /* Needed until Full-boot-chain enabled */ }; tsens0: tsens@4a9000 { diff --git a/arch/arm/boot/dts/qcom/msm-pmi8937.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8937.dtsi index 49f07a3cd668..0c1f9ddf0efc 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8937.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8937.dtsi @@ -32,6 +32,12 @@ qcom,secondary-pon-reset; qcom,hard-reset-poweroff-type = <PON_POWER_OFF_SHUTDOWN>; + + pon_perph_reg: qcom,pon_perph_reg { + regulator-name = "pon_spare_reg"; + qcom,pon-spare-reg-addr = <0x8c>; + qcom,pon-spare-reg-bit = <1>; + }; }; pmi8937_vadc: vadc@3100 { @@ -419,6 +425,7 @@ qcom,en-phase-stag; qcom,led-strings-list = [00 01]; qcom,en-ext-pfet-sc-pro; + qcom,cons-sync-write-delay-us = <1000>; }; flash_led: qcom,leds@d300 { @@ -495,6 +502,9 @@ qcom,duration = <1280>; qcom,id = <2>; qcom,current = <625>; + reg0 { + regulator-name = "pon_spare_reg"; + }; }; }; @@ -504,6 +514,7 @@ interrupts = <0x3 0xc0 0x0>, <0x3 0xc0 0x1>; interrupt-names = "sc-irq", "play-irq"; + vcc_pon-supply = <&pon_perph_reg>; qcom,play-mode = "direct"; qcom,wave-play-rate-us = <5263>; qcom,actuator-type = "lra"; @@ -521,7 +532,7 @@ qcom,wave-samp-rep-cnt = <1>; qcom,lra-auto-res-mode="qwd"; qcom,lra-high-z="opt1"; - qcom,lra-res-cal-period = <0>; + qcom,lra-res-cal-period = <4>; qcom,correct-lra-drive-freq; qcom,misc-trim-error-rc19p2-clk-reg-present; }; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi index 239740e191bd..b58bb840e745 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi @@ -31,6 +31,12 @@ qcom,secondary-pon-reset; qcom,hard-reset-poweroff-type = <PON_POWER_OFF_SHUTDOWN>; + + pon_perph_reg: qcom,pon_perph_reg { + regulator-name = "pon_spare_reg"; + qcom,pon-spare-reg-addr = <0x8c>; + qcom,pon-spare-reg-bit = <1>; + }; }; pmi8950_vadc: vadc@3100 { @@ -523,9 +529,9 @@ qcom,sync-dly-us = <800>; qcom,fs-curr-ua = <20000>; qcom,en-phase-stag; - qcom,ibb-pwrup-dly = <8>; qcom,led-strings-list = [00 01]; qcom,en-ext-pfet-sc-pro; + qcom,cons-sync-write-delay-us = <1000>; }; flash_led: qcom,leds@d300 { @@ -602,6 +608,9 @@ qcom,duration = <1280>; qcom,id = <2>; qcom,current = <625>; + reg0 { + regulator-name = "pon_spare_reg"; + }; }; }; @@ -611,6 +620,7 @@ interrupts = <0x3 0xc0 0x0>, <0x3 0xc0 0x1>; interrupt-names = "sc-irq", "play-irq"; + vcc_pon-supply = <&pon_perph_reg>; qcom,play-mode = "direct"; qcom,wave-play-rate-us = <5263>; qcom,actuator-type = "erm"; diff --git a/arch/arm/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts b/arch/arm/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts index 3ff351b94497..d71efe085bba 100644 --- a/arch/arm/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts +++ b/arch/arm/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts @@ -24,5 +24,5 @@ }; &int_codec { - qcom,model = "msm8952-sku2-snd-card"; + qcom,model = "msm8917-sku5-snd-card"; }; diff --git a/arch/arm/boot/dts/qcom/msm8917-qgp-tmo.dtsi b/arch/arm/boot/dts/qcom/msm8917-qgp-tmo.dtsi index f02780542b17..48b5e4d71665 100644 --- a/arch/arm/boot/dts/qcom/msm8917-qgp-tmo.dtsi +++ b/arch/arm/boot/dts/qcom/msm8917-qgp-tmo.dtsi @@ -21,6 +21,39 @@ }; &soc { + + i2c@78b7000 { + status = "ok"; + goodix@5d{ + compatible = "goodix,gt9xx"; + reg = <0x5d>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x02>; + avdd-supply = <&pm8917_l17>; + vdd-supply = <&pm8917_l17>; + vcc_i2c-supply = <&pm8917_l6>; + reset-gpios = <&tlmm 64 0x00>; + interrupt-gpios = <&tlmm 65 0x2008>; + goodix,panel-coords = <0 0 720 1200>; + goodix,display-coords = <0 0 720 1080>; + goodix,button-map= <139 172 158>; + goodix,product-id = "5668"; + goodix,fw_name = "gtp_fw.bin"; + goodix,have-touch-key; + goodix,driver-send-cfg; + }; + }; + + gpio_keys { + vol_down { + label = "volume_down"; + gpios = <&tlmm 128 0x1>; + linux,input-type = <1>; + linux,code = <114>; + debounce-interval = <15>; + }; + }; + led_flash0: qcom,camera-flash { }; }; @@ -73,3 +106,7 @@ qcom,bad-battery-detection-enable; qcom,hold-soc-while-full; }; + +&int_codec { + qcom,model = "msm8917-tmo-snd-card"; +}; diff --git a/arch/arm/boot/dts/qcom/msm8917-regulator.dtsi b/arch/arm/boot/dts/qcom/msm8917-regulator.dtsi index 0dffb6d85459..27f4c2e09676 100644 --- a/arch/arm/boot/dts/qcom/msm8917-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msm8917-regulator.dtsi @@ -434,14 +434,18 @@ qcom,cpr-voltage-scaling-factor-max = <0 2000 2000>; qcom,cpr-scaled-init-voltage-as-ceiling; qcom,cpr-fuse-revision = <69 39 3 0>; + qcom,pvs-version-fuse-sel = <37 40 3 0>; /* foundry */ qcom,cpr-fuse-version-map = - <(-1) (-1) 1 (-1) (-1) (-1)>, + <(-1) 0 1 (-1) (-1) (-1)>, + <(-1) 5 1 (-1) (-1) (-1)>, <(-1) (-1) (-1) (-1) (-1) (-1)>; qcom,cpr-quotient-adjustment = <50 40 100>, + <0 0 40>, <0 0 0>; qcom,cpr-init-voltage-adjustment = <30000 5000 35000>, + <0 0 20000>, <0 0 0>; qcom,cpr-enable; }; diff --git a/arch/arm/boot/dts/qcom/msm8917.dtsi b/arch/arm/boot/dts/qcom/msm8917.dtsi index bb852830bb3e..809ce158d64b 100644 --- a/arch/arm/boot/dts/qcom/msm8917.dtsi +++ b/arch/arm/boot/dts/qcom/msm8917.dtsi @@ -245,6 +245,9 @@ qcom,sensors = <10>; qcom,slope = <3200 3200 3200 3200 3200 3200 3200 3200 3200 3200>; + qcom,temp1-offset = <1 (-6) (-6) (-2) (-7) (-5) (-2) (-8) (-10) + (-6)>; + qcom,temp2-offset = <(-3) 1 (-2) 7 (-9) (-18) (-7) (-2) 1 16>; qcom,valid-status-check; }; @@ -1261,9 +1264,9 @@ qcom,ce-opp-freq = <100000000>; }; - qcom_seecom: qseecom@85e00000 { + qcom_seecom: qseecom@85b00000 { compatible = "qcom,qseecom"; - reg = <0x85e00000 0x500000>; + reg = <0x85b00000 0x800000>; reg-names = "secapp-region"; qcom,hlos-num-ce-hw-instances = <1>; qcom,hlos-ce-hw-instance = <0>; diff --git a/arch/arm/boot/dts/qcom/msm8937-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8937-cdp.dtsi index 75ab92f5bacb..458b5d6d15e7 100644 --- a/arch/arm/boot/dts/qcom/msm8937-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8937-cdp.dtsi @@ -130,6 +130,11 @@ &pmi_haptic{ qcom,wave-play-rate-us = <4165>; qcom,actuator-type = "lra"; + qcom,lra-auto-res-mode="qwd"; + qcom,lra-high-z="opt1"; + qcom,lra-res-cal-period = <4>; + qcom,correct-lra-drive-freq; + qcom,misc-trim-error-rc19p2-clk-reg-present; }; &sdhc_1 { diff --git a/arch/arm/boot/dts/qcom/msm8937-coresight.dtsi b/arch/arm/boot/dts/qcom/msm8937-coresight.dtsi index 6a8a8bf09cc5..d82cc9557b52 100644 --- a/arch/arm/boot/dts/qcom/msm8937-coresight.dtsi +++ b/arch/arm/boot/dts/qcom/msm8937-coresight.dtsi @@ -887,7 +887,7 @@ qcom,inst-id = <5>; }; - modem_etm0 { + modem_etm0: modem_etm0 { compatible = "qcom,coresight-remote-etm"; coresight-id = <51>; diff --git a/arch/arm/boot/dts/qcom/msm8937-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8937-gpu.dtsi index cabb82e06a25..90b7a91e664b 100644 --- a/arch/arm/boot/dts/qcom/msm8937-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8937-gpu.dtsi @@ -36,15 +36,17 @@ < 4248 >, /* 6. DDR:556.80 MHz BIMC: 278.40 MHz */ < 5346 >, /* 7. DDR:662.40 MHz BIMC: 331.20 MHz */ < 5712 >, /* 8. DDR:748.80 MHz BIMC: 374.40 MHz */ - < 6152 >; /* 9. DDR:806.40 MHz BIMC: 403.20 MHz */ + < 6152 >, /* 9. DDR:806.40 MHz BIMC: 403.20 MHz */ + < 7031 >; /* 10. DDR:921.60 MHz BIMC: 460.80 MHz */ }; msm_gpu: qcom,kgsl-3d0@1c00000 { label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; status = "ok"; - reg = <0x1c00000 0x40000>; - reg-names = "kgsl_3d0_reg_memory"; + reg = <0x1c00000 0x40000 + 0xa0000 0x6fff>; + reg-names = "kgsl_3d0_reg_memory", "qfprom_memory"; interrupts = <0 33 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; @@ -57,6 +59,8 @@ qcom,highest-bank-bit = <14>; + qcom,snapshot-size = <1048576>; //bytes + clocks = <&clock_gcc clk_gcc_oxili_gfx3d_clk>, <&clock_gcc clk_gcc_oxili_ahb_clk>, <&clock_gcc clk_gcc_bimc_gfx_clk>, @@ -74,7 +78,7 @@ qcom,bus-control; qcom,bus-width = <16>; qcom,msm-bus,name = "grp3d"; - qcom,msm-bus,num-cases = <10>; + qcom,msm-bus,num-cases = <11>; qcom,msm-bus,num-paths = <1>; qcom,msm-bus,vectors-KBps = <26 512 0 0>, /* off */ @@ -86,7 +90,8 @@ <26 512 0 4454400>, /* 6. 556.80 MHz */ <26 512 0 5299200>, /* 7. 662.40 MHz */ <26 512 0 5990400>, /* 8. 748.80 MHz */ - <26 512 0 6451200>; /* 9. 806.40 MHz */ + <26 512 0 6451200>, /* 9. 806.40 MHz */ + <26 512 0 7372800>; /* 10. 921.60 MHz */ /* GDSC regulator names */ regulator-names = "vddcx", "vdd"; diff --git a/arch/arm/boot/dts/qcom/msm8937-mdss.dtsi b/arch/arm/boot/dts/qcom/msm8937-mdss.dtsi index 090f88a20c6c..4e341a1178af 100644 --- a/arch/arm/boot/dts/qcom/msm8937-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/msm8937-mdss.dtsi @@ -172,6 +172,16 @@ <1 590 0 320000>; }; + qcom,mdss-hw-rt-bus { + /* Bus Scale Settings */ + qcom,msm-bus,name = "mdss_hw_rt"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <22 512 0 0>, + <22 512 0 1000>; + }; + smmu_mdp_unsec: qcom,smmu_mdp_unsec_cb { compatible = "qcom,smmu_mdp_unsec"; }; diff --git a/arch/arm/boot/dts/qcom/msm8937-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8937-mtp.dtsi index b8c21d885b55..4ddd3a3d336c 100644 --- a/arch/arm/boot/dts/qcom/msm8937-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8937-mtp.dtsi @@ -78,6 +78,11 @@ &pmi_haptic{ qcom,wave-play-rate-us = <4165>; qcom,actuator-type = "lra"; + qcom,lra-auto-res-mode="qwd"; + qcom,lra-high-z="opt1"; + qcom,lra-res-cal-period = <4>; + qcom,correct-lra-drive-freq; + qcom,misc-trim-error-rc19p2-clk-reg-present; }; &spi_3 { /* BLSP1 QUP3 */ diff --git a/arch/arm/boot/dts/qcom/msm8937-regulator.dtsi b/arch/arm/boot/dts/qcom/msm8937-regulator.dtsi index 9f0b79d5b085..ad65f6354f5d 100644 --- a/arch/arm/boot/dts/qcom/msm8937-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msm8937-regulator.dtsi @@ -356,7 +356,7 @@ interrupts = <0 15 0>; regulator-name = "apc_corner"; regulator-min-microvolt = <1>; - regulator-max-microvolt = <6>; + regulator-max-microvolt = <7>; qcom,cpr-fuse-corners = <3>; qcom,cpr-voltage-ceiling = <1155000 1225000 1350000>; @@ -393,17 +393,19 @@ <70 54 7 0>; qcom,cpr-fuse-quot-offset-scale = <5 5 5>; qcom,cpr-init-voltage-step = <10000>; - qcom,cpr-corner-map = <1 2 3 3 3 3>; + qcom,cpr-corner-map = <1 2 3 3 3 3 3>; qcom,cpr-corner-frequency-map = <1 960000000>, <2 1094400000>, <3 1209600000>, <4 1248000000>, <5 1344000000>, - <6 1401000000>; + <6 1401000000>, + <7 1497600000>; qcom,speed-bin-fuse-sel = <37 34 3 0>; qcom,cpr-speed-bin-max-corners = <0 0 1 2 6>, + <1 0 1 2 7>, <2 0 1 2 3>; qcom,cpr-fuse-revision = <69 39 3 0>; qcom,cpr-quot-adjust-scaling-factor-max = <0 1400 1400>; diff --git a/arch/arm/boot/dts/qcom/msm8937.dtsi b/arch/arm/boot/dts/qcom/msm8937.dtsi index d7d2958790bd..4660fb59ccdb 100644 --- a/arch/arm/boot/dts/qcom/msm8937.dtsi +++ b/arch/arm/boot/dts/qcom/msm8937.dtsi @@ -692,12 +692,33 @@ < 1344000000 5>, < 1401000000 6>; - qcom,speed0-bin-v0-cci = < 0 0>, < 400000000 1>, < 533333333 3>; + qcom,speed1-bin-v0-c0 = + < 0 0>, + < 768000000 1>, + < 902400000 2>, + < 998400000 4>, + < 1094400000 6>, + < 1209600000 7>; + + qcom,speed1-bin-v0-c1 = + < 0 0>, + < 960000000 1>, + < 1094400000 2>, + < 1248000000 4>, + < 1344000000 5>, + < 1401000000 6>, + < 1497600000 7>; + + qcom,speed1-bin-v0-cci = + < 0 0>, + < 400000000 1>, + < 533333333 3>; + qcom,speed2-bin-v0-c0 = < 0 0>, < 768000000 1>, @@ -740,13 +761,15 @@ < 1209600 >, < 1248000 >, < 1344000 >, - < 1401000 >; + < 1401000 >, + < 1497600 >; qcom,cpufreq-table-4 = < 768000 >, < 902400 >, < 998400 >, - < 1094400 >; + < 1094400 >, + < 1209600 >; }; cci_cache: qcom,cci { @@ -812,12 +835,12 @@ < 1094400 5053 >, /* NOM */ < 1248000 5712 >, /* NOM+ */ < 1344000 7031 >, - < 1401000 7031 >; /* TURBO */ + < 1497600 7031 >; /* TURBO */ cpu-to-dev-map-4 = < 806400 2929 >, /* SVS */ < 902400 5053 >, /* NOM */ < 998400 6152 >, /* NOM+ */ - < 1094400 7031 >; /* TURBO */ + < 1209600 7031 >; /* TURBO */ }; cci-cpufreq { @@ -827,22 +850,22 @@ < 1094400 400000 >, /* NOM */ < 1248000 533333 >, /* NOM+ */ < 1344000 533333 >, - < 1401000 533333 >; /* TURBO */ + < 1497600 533333 >; /* TURBO */ cpu-to-dev-map-4 = < 806400 400000 >, /* SVS */ < 902400 400000 >, /* NOM */ < 998400 533333 >, /* NOM+ */ - < 1094400 533333 >; /* TURBO */ + < 1209600 533333 >; /* TURBO */ }; mincpubw-cpufreq { target-dev = <&mincpubw>; cpu-to-dev-map-0 = < 1094400 2929 >, - < 1401000 4248 >; + < 1497600 4248 >; cpu-to-dev-map-4 = < 998400 2929 >, - < 1094400 4248 >; + < 1209600 4248 >; }; }; @@ -1568,7 +1591,7 @@ }; }; - qcom,bam_dmux@4044000 { + bam_dmux: qcom,bam_dmux@4044000 { compatible = "qcom,bam_dmux"; reg = <0x4044000 0x19000>; interrupts = <0 162 1>; @@ -1988,3 +2011,151 @@ clocks = <&clock_gcc clk_gcc_oxili_gfx3d_clk>; status = "okay"; }; + +/* GPU overrides */ +&msm_gpu { + + qcom,gpu-speed-bin = <0x6018 0x80000000 31>; + + qcom,gpu-pwrlevel-bins { + #address-cells = <1>; + #size-cells = <0>; + + compatible="qcom,gpu-pwrlevel-bins"; + + qcom,gpu-pwrlevels-0 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <0>; + + qcom,initial-pwrlevel = <2>; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <450000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <9>; + qcom,bus-max = <9>; + }; + + /* NOM+ */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <400000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <375000000>; + qcom,bus-freq = <6>; + qcom,bus-min = <5>; + qcom,bus-max = <8>; + }; + + /* SVS+ */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <300000000>; + qcom,bus-freq = <5>; + qcom,bus-min = <4>; + qcom,bus-max = <7>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <216000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + + /* XO */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; + + qcom,gpu-pwrlevels-1 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <1>; + + qcom,initial-pwrlevel = <3>; + + /* Super TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <475000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <10>; + qcom,bus-max = <10>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <45000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <9>; + qcom,bus-max = <10>; + }; + + /* NOM+ */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <400000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <375000000>; + qcom,bus-freq = <6>; + qcom,bus-min = <5>; + qcom,bus-max = <8>; + }; + + /* SVS+ */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <300000000>; + qcom,bus-freq = <5>; + qcom,bus-min = <4>; + qcom,bus-max = <7>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <216000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + + /* XO */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8940-pmi8950-ext-codec-cdp.dts b/arch/arm/boot/dts/qcom/msm8940-pmi8950-ext-codec-cdp.dts new file mode 100644 index 000000000000..1089dc9259b2 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8940-pmi8950-ext-codec-cdp.dts @@ -0,0 +1,102 @@ +/* + * 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 "msm8940.dtsi" +#include "msm8940-pmi8950-cdp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8940 External Audio Codec CDP"; + compatible = "qcom,msm8940-cdp", "qcom,msm8940", "qcom,cdp"; + qcom,board-id= <1 1>; + qcom,pmic-id = <0x10019 0x010011 0x0 0x0>; +}; + +&pm8937_gpios { + gpio@c000 { + status = "ok"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <2>; + qcom,master-en = <1>; + qcom,out-strength = <2>; + }; + + gpio@c600 { + status = "ok"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <0>; + qcom,master-en = <1>; + qcom,out-strength = <2>; + }; +}; + +&slim_msm { + status = "okay"; +}; + +&dai_slim { + status = "okay"; +}; + +&wcd9xxx_intc { + status = "okay"; +}; + +&clock_audio { + status = "okay"; +}; + +&wcd9335 { + status = "okay"; +}; + +&ext_codec { + status = "okay"; +}; + +&wcd_rst_gpio { + status = "okay"; +}; + +&int_codec { + status = "disabled"; +}; + +&pm8937_cajon_dig { + status = "disabled"; +}; + +&pm8937_cajon_analog { + status = "disabled"; +}; + +&wsa881x_i2c_e { + status = "disabled"; +}; + +&wsa881x_i2c_44 { + status = "disabled"; +}; + +&wsa881x_i2c_f { + status = "disabled"; +}; + +&wsa881x_i2c_45 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/qcom/msm8940-pmi8950-qrd-sku6.dts b/arch/arm/boot/dts/qcom/msm8940-pmi8950-qrd-sku6.dts index b24c38c0a8ef..aa0960d8726f 100644 --- a/arch/arm/boot/dts/qcom/msm8940-pmi8950-qrd-sku6.dts +++ b/arch/arm/boot/dts/qcom/msm8940-pmi8950-qrd-sku6.dts @@ -51,7 +51,7 @@ &soc { sound { - qcom,model = "msm8952-sku1-snd-card"; + qcom,model = "msm8940-sku6-snd-card"; qcom,msm-hs-micbias-type = "internal"; qcom,audio-routing = "RX_BIAS", "MCLK", diff --git a/arch/arm/boot/dts/qcom/msm8940.dtsi b/arch/arm/boot/dts/qcom/msm8940.dtsi index a5265c3ae977..2ed34b351546 100644 --- a/arch/arm/boot/dts/qcom/msm8940.dtsi +++ b/arch/arm/boot/dts/qcom/msm8940.dtsi @@ -23,6 +23,58 @@ }; +&usb_otg { + qcom,usbbam@78c4000 { + qcom,enable-hsusb-bam-on-boot; + + /delete-node/ qcom,pipe0; + qcom,pipe0 { + label = "hsusb-ipa-out-0"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <0>; + qcom,pipe-num = <0>; + qcom,peer-bam = <1>; + qcom,src-bam-pipe-index = <1>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + qcom,pipe1 { + label = "hsusb-ipa-in-0"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <1>; + qcom,pipe-num = <0>; + qcom,peer-bam = <1>; + qcom,dst-bam-pipe-index = <0>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + qcom,pipe2 { + label = "hsusb-qdss-in-0"; + qcom,usb-bam-mem-type = <2>; + qcom,dir = <1>; + qcom,pipe-num = <0>; + qcom,peer-bam = <0>; + qcom,peer-bam-physical-address = <0x6044000>; + qcom,src-bam-pipe-index = <0>; + qcom,dst-bam-pipe-index = <2>; + qcom,data-fifo-offset = <0x0>; + qcom,data-fifo-size = <0xe00>; + qcom,descriptor-fifo-offset = <0xe00>; + qcom,descriptor-fifo-size = <0x200>; + }; + qcom,pipe3 { + label = "hsusb-dpl-ipa-in-1"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <1>; + qcom,pipe-num = <1>; + qcom,peer-bam = <1>; + qcom,dst-bam-pipe-index = <3>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + }; +}; + &ad_hoc_bus { mas_ipa: mas-ipa { cell-id = <MSM_BUS_MASTER_IPA>; @@ -39,3 +91,245 @@ qcom,mas-rpm-id = <ICBID_MASTER_IPA>; }; }; + +&clock_gcc { + compatible = "qcom,gcc-8940"; +}; + +&clock_debug { + compatible = "qcom,cc-debug-8940"; +}; + +&clock_gcc_mdss { + compatible = "qcom,gcc-mdss-8940"; +}; + +&bam_dmux { + status = "disabled"; +}; + +&soc { + ipa_hw: qcom,ipa@07900000 { + compatible = "qcom,ipa"; + reg = <0x07900000 0x4effc>, <0x07904000 0x26934>; + reg-names = "ipa-base", "bam-base"; + interrupts = <0 228 0>, + <0 230 0>; + interrupt-names = "ipa-irq", "bam-irq"; + qcom,ipa-hw-ver = <6>; /* IPA core version = IPAv2.6L */ + qcom,ipa-hw-mode = <0>; /* IPA hw type = Normal */ + clock-names = "core_clk"; + clocks = <&clock_gcc clk_ipa_clk>; + qcom,ee = <0>; + qcom,use-ipa-tethering-bridge; + qcom,modem-cfg-emb-pipe-flt; + qcom,msm-bus,name = "ipa"; + qcom,msm-bus,num-cases = <3>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <90 512 0 0>, /* No BIMC vote (ab=0 Mbps, ib=0 Mbps ~ 0MHZ) */ + <90 512 100000 800000>, /* SVS (ab=100, ib=800 ~ 50MHz) */ + <90 512 100000 1200000>; /* PERF (ab=100, ib=1200 ~ 75MHz) */ + qcom,bus-vector-names = "MIN", "SVS", "PERF"; + }; + + qcom,rmnet-ipa { + compatible = "qcom,rmnet-ipa"; + qcom,rmnet-ipa-ssr; + qcom,ipa-loaduC; + qcom,ipa-advertise-sg-support; + }; + + /* remove 8937 MEM ACC node */ + /delete-node/ regulator@01946004; + + mem_acc_vreg_corner: regulator@01946004 { + compatible = "qcom,mem-acc-regulator"; + regulator-name = "mem_acc_corner"; + regulator-min-microvolt = <1>; + regulator-max-microvolt = <3>; + + qcom,acc-reg-addr-list = + <0x01942138 0x01942130 0x01942120 + 0x01942124 0x01942128>; + + qcom,acc-init-reg-config = <1 0xfff>; + + qcom,num-acc-corners = <3>; + qcom,boot-acc-corner = <2>; + qcom,corner1-reg-config = + /* SVS+ => SVS+ */ + <(-1) (-1)>, <(-1) (-1)>, <(-1) (-1)>, + <(-1) (-1)>, <(-1) (-1)>, <(-1) (-1)>, + <(-1) (-1)>, + /* SVS+ => NOM */ + < 2 0x555555>, < 3 0x1041041>, < 4 0x1041041>, + < 5 0x0000041>, <(-1) (-1)>, <(-1) (-1)>, + <(-1) (-1)>, + /* SVS+ => TURBO/NOM+ */ + < 2 0x555555 >, < 3 0x1041041>, < 4 0x1041041>, + < 5 0x0000041>, < 3 0x0>, < 4 0x0>, + < 5 0x0>; + + qcom,corner2-reg-config = + /* NOM => SVS+ */ + < 2 0x555555>, < 3 0x30C30C3>, < 4 0x30C30C3>, + < 5 0x00000C3>, + /* NOM => NOM */ + <(-1) (-1)>, <(-1) (-1)>, <(-1) (-1)>, + <(-1) (-1)>, + /* NOM => TURBO/NOM+ */ + < 2 0x555555>, < 3 0x0>, < 4 0x0>, + < 5 0x0>; + + qcom,corner3-reg-config = + /* TURBO/NOM+ => SVS+ */ + < 2 0x555555>, < 3 0x1041041>, < 4 0x1041041>, + < 5 0x0000041>, < 3 0x30C30C3>, < 4 0x30C30C3>, + < 5 0x00000C3>, + /* TURBO/NOM+ => NOM */ + < 2 0x555555>, < 3 0x1041041>, < 4 0x1041041>, + < 5 0x0000041>, <(-1) (-1)>, <(-1) (-1)>, + <(-1) (-1)>, + /* TURBO/NOM+ => TURBO/NOM+ */ + <(-1) (-1)>, <(-1) (-1)>, <(-1) (-1)>, + <(-1) (-1)>, <(-1) (-1)>, <(-1) (-1)>, + <(-1) (-1)>; + }; +}; + +&apc_vreg_corner { + /delete-property/ qcom,cpr-fuse-version-map; + /delete-property/ qcom,cpr-quotient-adjustment; + /delete-property/ qcom,cpr-init-voltage-adjustment; + /delete-property/ qcom,cpr-enable; +}; + +/* GPU overrides */ +&msm_gpu { + + /delete-node/qcom,gpu-pwrlevels; + + /* Power levels */ + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qcom,gpu-pwrlevels"; + + /* SUPER TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <450000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <10>; + qcom,bus-max = <10>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <450000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <9>; + qcom,bus-max = <10>; + }; + + /* NOM+ */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <400000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <375000000>; + qcom,bus-freq = <6>; + qcom,bus-min = <5>; + qcom,bus-max = <8>; + }; + + /* SVS+ */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <300000000>; + qcom,bus-freq = <5>; + qcom,bus-min = <4>; + qcom,bus-max = <7>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <216000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + + /* XO */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; +}; + +&mdss_mdp { + qcom,vbif-settings = <0x0d0 0x00000020>; +}; + +&modem_mem { + reg = <0x0 0x86800000 0x0 0x6a00000>; +}; + +&reloc_mem { + reg = <0x0 0x8d200000 0x0 0x1800000>; +}; + +&funnel_apss { + coresight-child-ports = <3>; +}; + +/* MSS_SCL */ +&modem_etm0 { + coresight-child-ports = <2>; + qcom,inst-id = <11>; +}; + +&soc { + cti_modem_cpu1: cti@6128000{ + compatible = "arm,coresight-cti"; + reg = <0x6128000 0x1000>; + reg-names = "cti-base"; + + coresight-id = <59>; + coresight-name = "coresight-cti-modem-cpu1"; + coresight-nr-inports = <0>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + /* MSS_VEC */ + modem_etm1 { + compatible = "qcom,coresight-remote-etm"; + + coresight-id = <60>; + coresight-name = "coresight-modem-etm1"; + coresight-nr-inports = <0>; + coresight-outports = <0>; + coresight-child-list = <&funnel_right>; + coresight-child-ports = <1>; + + qcom,inst-id = <2>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8953-gpu.dtsi index a6cf0030cb53..99881a6f98d5 100644 --- a/arch/arm/boot/dts/qcom/msm8953-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-gpu.dtsi @@ -75,6 +75,8 @@ qcom,highest-bank-bit = <14>; + qcom,snapshot-size = <1048576>; //bytes + clocks = <&clock_gcc_gfx clk_gcc_oxili_gfx3d_clk>, <&clock_gcc_gfx clk_gcc_oxili_ahb_clk>, <&clock_gcc_gfx clk_gcc_bimc_gfx_clk>, @@ -127,6 +129,15 @@ coresight-child-list = <&funnel_mm>; coresight-child-ports = <6>; + /* Enable context aware freq. scaling */ + qcom,enable-ca-jump; + + /* Context aware jump busy penalty in us */ + qcom,ca-busy-penalty = <12000>; + + /* Context aware jump target power level */ + qcom,ca-target-pwrlevel = <3>; + /* Power levels */ qcom,gpu-pwrlevels { #address-cells = <1>; diff --git a/arch/arm/boot/dts/qcom/msm8953-mdss.dtsi b/arch/arm/boot/dts/qcom/msm8953-mdss.dtsi index a7542f648d7d..619809a72965 100644 --- a/arch/arm/boot/dts/qcom/msm8953-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-mdss.dtsi @@ -173,6 +173,16 @@ <1 590 0 320000>; }; + qcom,mdss-hw-rt-bus { + /* Bus Scale Settings */ + qcom,msm-bus,name = "mdss_hw_rt"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <22 512 0 0>, + <22 512 0 1000>; + }; + smmu_mdp_unsec: qcom,smmu_mdp_unsec_cb { compatible = "qcom,smmu_mdp_unsec"; }; diff --git a/arch/arm/boot/dts/qcom/msm8953-regulator.dtsi b/arch/arm/boot/dts/qcom/msm8953-regulator.dtsi index d2f47d0c180c..e0263f1c8248 100644 --- a/arch/arm/boot/dts/qcom/msm8953-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-regulator.dtsi @@ -371,6 +371,13 @@ qcom,cpr-enable; qcom,cpr-hw-closed-loop; + qcom,cpr-panic-reg-addr-list = + <0xb1d2c18 0xb1d2900 0x0b1112b0 0xb018798>; + qcom,cpr-panic-reg-name-list = + "CCI_SAW4_PMIC_STS", "CCI_SAW4_VCTL", + "APCS_ALIAS0_APM_CTLER_STATUS", + "APCS0_CPR_CORE_ADJ_MODE_REG"; + thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <0>; @@ -636,9 +643,9 @@ qcom,cpr-closed-loop-voltage-fuse-adjustment = /* Speed bin 0; CPR rev 0..7 */ < 0 0 0 0>, - < 25000 0 20000 50000>, - < 25000 0 20000 50000>, - < 25000 0 20000 50000>, + < 10000 (-15000) 0 25000>, + < 10000 (-15000) 0 25000>, + < 10000 (-15000) 0 25000>, < 0 0 0 0>, < 0 0 0 0>, < 0 0 0 0>, @@ -656,9 +663,9 @@ /* Speed bin 2; CPR rev 0..7 */ < 0 0 0 0>, - < 25000 0 20000 50000>, - < 25000 0 20000 50000>, - < 25000 0 20000 50000>, + < 10000 (-15000) 0 25000>, + < 10000 (-15000) 0 25000>, + < 10000 (-15000) 0 25000>, < 0 0 0 0>, < 0 0 0 0>, < 0 0 0 0>, @@ -706,9 +713,9 @@ /* Speed bin 7; CPR rev 0..7 */ < 0 0 0 0>, - < 25000 0 20000 50000>, - < 25000 0 20000 50000>, - < 25000 0 20000 50000>, + < 10000 (-15000) 0 25000>, + < 10000 (-15000) 0 25000>, + < 10000 (-15000) 0 25000>, < 0 0 0 0>, < 0 0 0 0>, < 0 0 0 0>, diff --git a/arch/arm/boot/dts/qcom/msm8996-camera.dtsi b/arch/arm/boot/dts/qcom/msm8996-camera.dtsi index 43ccbb123c12..e24d4b3c2c07 100644 --- a/arch/arm/boot/dts/qcom/msm8996-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-camera.dtsi @@ -692,9 +692,9 @@ "smmu_cpp_ahb_clk"; qcom,clock-rates = <0 0 0 400000000 400000000 0 0 0 0 0 0 0>, - <0 0 0 400000000 400000000 0 0 0 0 0 0 0>, + <0 0 0 100000000 100000000 0 0 0 0 0 0 0>, <0 0 0 200000000 200000000 0 0 0 0 0 0 0>, - <0 0 0 100000000 100000000 0 0 0 0 0 0 0>; + <0 0 0 400000000 400000000 0 0 0 0 0 0 0>; qcom,msm-bus,name = "msm_camera_fd"; qcom,msm-bus,num-cases = <4>; qcom,msm-bus,num-paths = <1>; diff --git a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi index 23a65ccd7fd6..57f5adc54610 100644 --- a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi @@ -410,6 +410,7 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; qcom,partial-update-enabled; qcom,panel-roi-alignment = <720 128 720 64 720 64>; + qcom,panel-allow-phy-poweroff; }; &dsi_nt35950_4k_dsc_cmd { @@ -448,6 +449,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,panel-allow-phy-poweroff; }; &dsi_dual_sharp_1080_120hz_cmd { diff --git a/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi index 81f4fa8dda73..25e0d99987db 100644 --- a/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi @@ -77,6 +77,8 @@ qcom,highest-bank-bit = <15>; + qcom,snapshot-size = <1048576>; //bytes + /* Trace bus */ coresight-id = <300>; coresight-name = "coresight-gfx"; diff --git a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi index c34efa60b766..9517f2378a78 100644 --- a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi @@ -400,6 +400,7 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; qcom,partial-update-enabled; qcom,panel-roi-alignment = <720 128 720 64 720 64>; + qcom,panel-allow-phy-poweroff; }; &dsi_nt35950_4k_dsc_cmd { @@ -438,6 +439,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + qcom,panel-allow-phy-poweroff; }; &dsi_dual_sharp_1080_120hz_cmd { diff --git a/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi index 0b7be6a056f3..1676090dd4ff 100644 --- a/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi @@ -1533,24 +1533,24 @@ tert_mi2s { tert_mi2s_sleep: tert_mi2s_sleep { mux { - pins = "gpio75", "gpio76"; + pins = "gpio75", "gpio76", "gpio78"; function = "ter_mi2s"; }; config { - pins = "gpio75", "gpio76"; + pins = "gpio75", "gpio76", "gpio78"; drive-strength = <2>; /* 2 mA */ bias-pull-down; /* PULL DOWN */ }; }; tert_mi2s_active: tert_mi2s_active { mux { - pins = "gpio75", "gpio76"; + pins = "gpio75", "gpio76", "gpio78"; function = "ter_mi2s"; }; config { - pins = "gpio75", "gpio76"; + pins = "gpio75", "gpio76", "gpio78"; drive-strength = <8>; /* 8 mA */ bias-disable; /* NO PULL */ output-high; @@ -1588,24 +1588,24 @@ quat_mi2s { quat_mi2s_sleep: quat_mi2s_sleep { mux { - pins = "gpio58", "gpio59"; + pins = "gpio58", "gpio59", "gpio61"; function = "qua_mi2s"; }; config { - pins = "gpio58", "gpio59"; + pins = "gpio58", "gpio59", "gpio61"; drive-strength = <2>; /* 2 mA */ bias-pull-down; /* PULL DOWN */ }; }; quat_mi2s_active: quat_mi2s_active { mux { - pins = "gpio58", "gpio59"; + pins = "gpio58", "gpio59", "gpio61"; function = "qua_mi2s"; }; config { - pins = "gpio58", "gpio59"; + pins = "gpio58", "gpio59", "gpio61"; drive-strength = <8>; /* 8 mA */ bias-disable; /* NO PULL */ output-high; @@ -1804,6 +1804,64 @@ }; }; + ap_mclk_en { + ap_mclk_active: ap_mclk_active { + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + ap_mclk_sleep: ap_mclk_sleep { + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + drive-strength = <2>; + bias-pull-down; + output-low; + }; + }; + }; + + mdm_mclk_en { + mdm_mclk_active: mdm_mclk_active { + mux { + pins = "gpio134"; + function = "gpio"; + }; + + config { + pins = "gpio134"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + mdm_mclk_sleep: mdm_mclk_sleep { + mux { + pins = "gpio134"; + function = "gpio"; + }; + + config { + pins = "gpio134"; + drive-strength = <2>; + bias-pull-down; + output-low; + }; + }; + }; + cci0_active: cci0_active { mux { /* CLK, DATA */ diff --git a/arch/arm/boot/dts/qcom/msm8996-pm.dtsi b/arch/arm/boot/dts/qcom/msm8996-pm.dtsi index 82ac7271e9a8..df7cd79a7002 100644 --- a/arch/arm/boot/dts/qcom/msm8996-pm.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-pm.dtsi @@ -161,7 +161,7 @@ qcom,psci-cpu-mode = <4>; qcom,latency-us = <80>; qcom,ss-power = <196>; - qcom,energy-overhead = <45300>; + qcom,energy-overhead = <62248>; qcom,time-overhead = <210>; qcom,reset-level = <LPM_RESET_LVL_PC>; @@ -250,7 +250,7 @@ qcom,psci-cpu-mode = <4>; qcom,latency-us = <80>; qcom,ss-power = <196>; - qcom,energy-overhead = <45300>; + qcom,energy-overhead = <62248>; qcom,time-overhead = <210>; qcom,reset-level = <LPM_RESET_LVL_PC>; diff --git a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts index ac4d78f2a97c..ad38744e4490 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts @@ -12,6 +12,7 @@ /dts-v1/; +#include <dt-bindings/gpio/gpio.h> #include "msm8996pro.dtsi" #include "msm8996-pm8994.dtsi" #include "msm8996-agave-adp.dtsi" @@ -40,6 +41,10 @@ }; }; +&slim_msm { + status = "disabled"; +}; + &pm8994_mpps { mpp@a500 { /* MPP 6 */ qcom,mode = <1>; /* Digital output */ @@ -59,6 +64,19 @@ status = "ok"; }; +&sdhc_2 { + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on_sbc>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off + &sdc2_cd_on_sbc>; +}; + +&i2c_7 { + silabs4705@11 { /* SiLabs FM chip, slave id 0x11*/ + status = "disabled"; + }; +}; + &gfx_cpr { vdd-supply = <&hl7509_vreg>; qcom,cpr-step-quot-init-min = <20>; diff --git a/arch/arm/boot/dts/qcom/msm8996pro.dtsi b/arch/arm/boot/dts/qcom/msm8996pro.dtsi index 514bddbbd557..797df2b5a458 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996pro.dtsi @@ -54,9 +54,23 @@ qcom,cpr-corner-fmax-map = /* Speed bin 0 */ <1 6 9 14 19>, + <1 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, /* Speed bin 1 */ - <1 6 9 14 19>; + <1 6 9 14 19>, + <1 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>, + <3 6 9 14 19>; qcom,cpr-voltage-ceiling = /* Speed bin 0 */ @@ -336,9 +350,23 @@ qcom,cpr-corner-fmax-map = /* Speed bin 0 */ <1 7 10 15 27>, + <1 7 10 15 27>, + <4 7 10 15 27>, + <4 7 10 15 27>, + <4 7 10 15 27>, + <4 7 10 15 27>, + <4 7 10 15 27>, + <4 7 10 15 27>, /* Speed bin 1 */ - <1 7 10 15 25>; + <1 7 10 15 25>, + <1 7 10 15 25>, + <4 7 10 15 25>, + <4 7 10 15 25>, + <4 7 10 15 25>, + <4 7 10 15 25>, + <4 7 10 15 25>, + <4 7 10 15 25>; qcom,cpr-voltage-ceiling = /* Speed bin 0 */ @@ -974,6 +1002,9 @@ &soc { qcom,msm-thermal { + qcom,poll-ms = <50>; + qcom,limit-temp = <80>; + qcom,core-limit-temp = <90>; qcom,vdd-gfx-rstr{ qcom,levels = <6 8 9>; /* Nominal, Turbo, Turbo_L1 */ }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi index f2850e4f968a..72c8801b2a3e 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi @@ -77,6 +77,8 @@ qcom,highest-bank-bit = <15>; + qcom,snapshot-size = <1048576>; //bytes + clocks = <&clock_gpu clk_gpucc_gfx3d_clk>, <&clock_gcc clk_gcc_gpu_cfg_ahb_clk>, <&clock_gpu clk_gpucc_rbbmtimer_clk>, diff --git a/arch/arm/configs/mdm-perf_defconfig b/arch/arm/configs/mdm-perf_defconfig index a5211c534acc..3230a239a1bb 100644 --- a/arch/arm/configs/mdm-perf_defconfig +++ b/arch/arm/configs/mdm-perf_defconfig @@ -207,7 +207,8 @@ CONFIG_USB_NET_SMSC95XX=y CONFIG_USBNET_IPA_BRIDGE=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y -CONFIG_CNSS_PCI=y +CONFIG_CNSS=y +CONFIG_CLD_HL_SDIO_CORE=y CONFIG_CLD_LL_CORE=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y diff --git a/arch/arm/configs/mdm9607-perf_defconfig b/arch/arm/configs/mdm9607-perf_defconfig index a71038991d14..2f81192af342 100644 --- a/arch/arm/configs/mdm9607-perf_defconfig +++ b/arch/arm/configs/mdm9607-perf_defconfig @@ -194,7 +194,7 @@ CONFIG_PPP=y CONFIG_PPP_ASYNC=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y -CONFIG_CNSS_SDIO=y +CONFIG_CNSS=y CONFIG_CLD_HL_SDIO_CORE=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y diff --git a/arch/arm/configs/mdm9607_defconfig b/arch/arm/configs/mdm9607_defconfig index 54f9a4b7df72..a26399501901 100644 --- a/arch/arm/configs/mdm9607_defconfig +++ b/arch/arm/configs/mdm9607_defconfig @@ -194,7 +194,7 @@ CONFIG_PPP=y CONFIG_PPP_ASYNC=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y -CONFIG_CNSS_SDIO=y +CONFIG_CNSS=y CONFIG_CLD_HL_SDIO_CORE=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y diff --git a/arch/arm/configs/mdm_defconfig b/arch/arm/configs/mdm_defconfig index fa0e179b99e2..0127b003fa53 100644 --- a/arch/arm/configs/mdm_defconfig +++ b/arch/arm/configs/mdm_defconfig @@ -206,7 +206,8 @@ CONFIG_USB_NET_SMSC95XX=y CONFIG_USBNET_IPA_BRIDGE=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y -CONFIG_CNSS_PCI=y +CONFIG_CNSS=y +CONFIG_CLD_HL_SDIO_CORE=y CONFIG_CLD_LL_CORE=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig index adc9cc2ab586..a5ea0da55455 100644 --- a/arch/arm/configs/msm8937-perf_defconfig +++ b/arch/arm/configs/msm8937-perf_defconfig @@ -232,6 +232,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_UID_STAT=y CONFIG_QSEECOM=y CONFIG_HDCP_QSEECOM=y +CONFIG_UID_CPUTIME=y CONFIG_USB_EXT_TYPE_C_PERICOM=y CONFIG_MSM_ULTRASOUND=y CONFIG_SCSI=y @@ -294,7 +295,11 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_TOUCHSCREEN_FT5X06=y CONFIG_FT_SECURE_TOUCH=y +CONFIG_TOUCHSCREEN_GT9XX=y CONFIG_TOUCHSCREEN_MAXIM_STI=y +CONFIG_GT9XX_TOUCHPANEL_DRIVER=y +CONFIG_GT9XX_TOUCHPANEL_UPDATE=y +CONFIG_GT9XX_TOUCHPANEL_DEBUG=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y CONFIG_INPUT_KEYCHORD=y diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig index c1f33e636b57..02cc623139aa 100644 --- a/arch/arm/configs/msm8937_defconfig +++ b/arch/arm/configs/msm8937_defconfig @@ -234,6 +234,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_UID_STAT=y CONFIG_QSEECOM=y CONFIG_HDCP_QSEECOM=y +CONFIG_UID_CPUTIME=y CONFIG_USB_EXT_TYPE_C_PERICOM=y CONFIG_MSM_ULTRASOUND=y CONFIG_SCSI=y @@ -296,7 +297,11 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_GEN_VKEYS=y CONFIG_TOUCHSCREEN_FT5X06=y CONFIG_FT_SECURE_TOUCH=y +CONFIG_TOUCHSCREEN_GT9XX=y CONFIG_TOUCHSCREEN_MAXIM_STI=y +CONFIG_GT9XX_TOUCHPANEL_DRIVER=y +CONFIG_GT9XX_TOUCHPANEL_UPDATE=y +CONFIG_GT9XX_TOUCHPANEL_DEBUG=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y CONFIG_INPUT_KEYCHORD=y diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 5206d5b29b72..d8c2de72e8af 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -190,6 +190,13 @@ static int __init parse_cluster(struct device_node *cluster, int depth) return 0; } +static DEFINE_PER_CPU(unsigned long, cpu_efficiency) = SCHED_CAPACITY_SCALE; + +unsigned long arch_get_cpu_efficiency(int cpu) +{ + return per_cpu(cpu_efficiency, cpu); +} + #ifdef CONFIG_OF struct cpu_efficiency { const char *compatible; @@ -266,6 +273,7 @@ static int __init parse_dt_topology(void) for_each_possible_cpu(cpu) { const u32 *rate; int len; + u32 efficiency; /* too early to use cpu->of_node */ cn = of_get_cpu_node(cpu, NULL); @@ -274,12 +282,26 @@ static int __init parse_dt_topology(void) continue; } - for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++) - if (of_device_is_compatible(cn, cpu_eff->compatible)) - break; + /* + * The CPU efficiency value passed from the device tree + * overrides the value defined in the table_efficiency[] + */ + if (of_property_read_u32(cn, "efficiency", &efficiency) < 0) { + + for (cpu_eff = table_efficiency; + cpu_eff->compatible; cpu_eff++) - if (cpu_eff->compatible == NULL) - continue; + if (of_device_is_compatible(cn, + cpu_eff->compatible)) + break; + + if (cpu_eff->compatible == NULL) + continue; + + efficiency = cpu_eff->efficiency; + } + + per_cpu(cpu_efficiency, cpu) = efficiency; rate = of_get_property(cn, "clock-frequency", &len); if (!rate || len != 4) { @@ -288,7 +310,7 @@ static int __init parse_dt_topology(void) continue; } - capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; + capacity = ((be32_to_cpup(rate)) >> 20) * efficiency; /* Save min capacity of the system */ if (capacity < min_capacity) diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index bbdbe2dcc87d..407dc786583a 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -183,9 +183,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm) { unsigned long random_factor = 0UL; - if ((current->flags & PF_RANDOMIZE) && - !(current->personality & ADDR_NO_RANDOMIZE)) - random_factor = (get_random_long() & ((1UL << mmap_rnd_bits) - 1)) << PAGE_SHIFT; + if (current->flags & PF_RANDOMIZE) + random_factor = arch_mmap_rnd(); if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig index 87f683dc143b..7ad6cc91c32d 100644 --- a/arch/arm64/configs/msm-auto-perf_defconfig +++ b/arch/arm64/configs/msm-auto-perf_defconfig @@ -275,7 +275,7 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m -CONFIG_CNSS_PCI=y +CONFIG_CNSS=y CONFIG_CLD_LL_CORE=y CONFIG_BUS_AUTO_SUSPEND=y CONFIG_INPUT_EVDEV=y diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig index 583337fc1f12..f018e4f8f1f3 100644 --- a/arch/arm64/configs/msm-auto_defconfig +++ b/arch/arm64/configs/msm-auto_defconfig @@ -276,7 +276,7 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m -CONFIG_CNSS_PCI=y +CONFIG_CNSS=y CONFIG_CLD_LL_CORE=y CONFIG_BUS_AUTO_SUSPEND=y CONFIG_INPUT_EVDEV=y diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index e410fe3d8509..975ac5a6bf9c 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -272,7 +272,7 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m -CONFIG_CNSS_PCI=y +CONFIG_CNSS=y CONFIG_CLD_LL_CORE=y CONFIG_BUS_AUTO_SUSPEND=y CONFIG_INPUT_EVDEV=y diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig index 324e94869e6b..1f240a622751 100644 --- a/arch/arm64/configs/msm8937-perf_defconfig +++ b/arch/arm64/configs/msm8937-perf_defconfig @@ -228,6 +228,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_UID_STAT=y CONFIG_QSEECOM=y CONFIG_HDCP_QSEECOM=y +CONFIG_UID_CPUTIME=y CONFIG_USB_EXT_TYPE_C_PERICOM=y CONFIG_MSM_ULTRASOUND=y CONFIG_SCSI=y @@ -271,7 +272,7 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m -CONFIG_CNSS_PCI=y +CONFIG_CNSS=y CONFIG_CLD_LL_CORE=y CONFIG_BUS_AUTO_SUSPEND=y CONFIG_INPUT_EVDEV=y diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig index 4860e0d79681..84302b3d2330 100644 --- a/arch/arm64/configs/msm8937_defconfig +++ b/arch/arm64/configs/msm8937_defconfig @@ -228,6 +228,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_UID_STAT=y CONFIG_QSEECOM=y CONFIG_HDCP_QSEECOM=y +CONFIG_UID_CPUTIME=y CONFIG_USB_EXT_TYPE_C_PERICOM=y CONFIG_MSM_ULTRASOUND=y CONFIG_SCSI=y @@ -271,7 +272,7 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m -CONFIG_CNSS_PCI=y +CONFIG_CNSS=y CONFIG_CLD_LL_CORE=y CONFIG_BUS_AUTO_SUSPEND=y CONFIG_INPUT_EVDEV=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index 6c16bc386054..7de6330cf672 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -273,7 +273,7 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CNSS_CRYPTO=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m -CONFIG_CNSS_PCI=y +CONFIG_CNSS=y CONFIG_CLD_LL_CORE=y CONFIG_BUS_AUTO_SUSPEND=y CONFIG_INPUT_EVDEV=y diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 09a7167070e2..2bb7a0a8eda5 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -478,7 +478,6 @@ CONFIG_SWITCH=y CONFIG_EDAC=y CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_CORTEX_ARM64=y -CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_CE=y CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_UE=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_QPNP=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index a52eba470c4e..932024425806 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -481,7 +481,6 @@ CONFIG_SWITCH=y CONFIG_EDAC=y CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_CORTEX_ARM64=y -CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_CE=y CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_UE=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_QPNP=y diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 6feb103b5075..e0204616f1bb 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -280,6 +280,7 @@ static void __init parse_dt_cpu_power(void) for_each_possible_cpu(cpu) { const u32 *rate; int len; + u32 efficiency; /* Too early to use cpu->of_node */ cn = of_get_cpu_node(cpu, NULL); @@ -288,16 +289,29 @@ static void __init parse_dt_cpu_power(void) continue; } - for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++) - if (of_device_is_compatible(cn, cpu_eff->compatible)) - break; + /* + * The CPU efficiency value passed from the device tree + * overrides the value defined in the table_efficiency[] + */ + if (of_property_read_u32(cn, "efficiency", &efficiency) < 0) { - if (cpu_eff->compatible == NULL) { - pr_warn("%s: Unknown CPU type\n", cn->full_name); - continue; + for (cpu_eff = table_efficiency; + cpu_eff->compatible; cpu_eff++) + + if (of_device_is_compatible(cn, + cpu_eff->compatible)) + break; + + if (cpu_eff->compatible == NULL) { + pr_warn("%s: Unknown CPU type\n", + cn->full_name); + continue; + } + + efficiency = cpu_eff->efficiency; } - per_cpu(cpu_efficiency, cpu) = cpu_eff->efficiency; + per_cpu(cpu_efficiency, cpu) = efficiency; rate = of_get_property(cn, "clock-frequency", &len); if (!rate || len != 4) { @@ -306,7 +320,7 @@ static void __init parse_dt_cpu_power(void) continue; } - capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; + capacity = ((be32_to_cpup(rate)) >> 20) * efficiency; /* Save min capacity of the system */ if (capacity < min_capacity) diff --git a/drivers/base/dma-removed.c b/drivers/base/dma-removed.c index 6a75a16e2fae..ecb069a46f38 100644 --- a/drivers/base/dma-removed.c +++ b/drivers/base/dma-removed.c @@ -181,15 +181,16 @@ static void removed_region_fixup(struct removed_region *dma_mem, int index) { unsigned long fixup_size; unsigned long base_pfn; + unsigned long flags; if (index > dma_mem->nr_pages) return; /* carve-out */ - memblock_region_resize_late_begin(); + flags = memblock_region_resize_late_begin(); memblock_free(dma_mem->base, dma_mem->nr_pages * PAGE_SIZE); memblock_remove(dma_mem->base, index * PAGE_SIZE); - memblock_region_resize_late_end(); + memblock_region_resize_late_end(flags); /* clear page-mappings */ base_pfn = dma_mem->base >> PAGE_SHIFT; diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c index 6bcd6a77c631..3f2d53fa5a90 100644 --- a/drivers/bluetooth/bluetooth-power.c +++ b/drivers/bluetooth/bluetooth-power.c @@ -295,7 +295,7 @@ static const struct rfkill_ops bluetooth_power_rfkill_ops = { .set_block = bluetooth_toggle_radio, }; -#ifdef CONFIG_CNSS_PCI +#if defined(CONFIG_CNSS) && defined(CONFIG_CLD_LL_CORE) static ssize_t enable_extldo(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 406454ae0ee7..9af276fff273 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -424,6 +424,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map) if (!map) return; + fl = map->fl; if (map->flags == ADSP_MMAP_HEAP_ADDR) { spin_lock(&me->hlock); map->refs--; @@ -431,18 +432,6 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map) hlist_del_init(&map->hn); spin_unlock(&me->hlock); } else { - int destVM[1] = {VMID_HLOS}; - int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - - fl = map->fl; - vmid = fl->apps->channel[fl->cid].vmid; - if (vmid) { - int srcVM[2] = {VMID_HLOS, vmid}; - - hyp_assign_phys(map->phys, buf_page_size(map->size), - srcVM, 2, destVM, destVMperm, 1); - } - spin_lock(&fl->hlock); map->refs--; if (!map->refs) @@ -465,6 +454,9 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map) &(map->va), map->phys, &attrs); } } else { + int destVM[1] = {VMID_HLOS}; + int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; + if (!IS_ERR_OR_NULL(map->handle)) ion_free(fl->apps->client, map->handle); if (fl->sctx->smmu.enabled) { @@ -474,6 +466,14 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map) map->table->nents, DMA_BIDIRECTIONAL, map->buf); } + vmid = fl->apps->channel[fl->cid].vmid; + if (vmid && map->phys) { + int srcVM[2] = {VMID_HLOS, vmid}; + + hyp_assign_phys(map->phys, buf_page_size(map->size), + srcVM, 2, destVM, destVMperm, 1); + } + if (!IS_ERR_OR_NULL(map->table)) dma_buf_unmap_attachment(map->attach, map->table, DMA_BIDIRECTIONAL); @@ -552,9 +552,12 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, uintptr_t va, goto bail; map->uncached = !ION_IS_CACHED(flags); map->phys = sg_dma_address(map->table->sgl); - map->size = sg_dma_len(map->table->sgl); - if (sess->smmu.cb) + if (sess->smmu.cb) { map->phys += ((uint64_t)sess->smmu.cb << 32); + map->size = sg_dma_len(map->table->sgl); + } else { + map->size = buf_page_size(len); + } vmid = fl->apps->channel[fl->cid].vmid; if (vmid) { int srcVM[1] = {VMID_HLOS}; diff --git a/drivers/clk/msm/clock-gcc-8996.c b/drivers/clk/msm/clock-gcc-8996.c index 5cd45a4eadc1..a0f43c3cf908 100644 --- a/drivers/clk/msm/clock-gcc-8996.c +++ b/drivers/clk/msm/clock-gcc-8996.c @@ -1339,9 +1339,11 @@ static struct rcg_clk pdm2_clk_src = { }, }; -/* Frequency table might change later */ static struct clk_freq_tbl ftbl_qspi_ser_clk_src[] = { - F( 192000000, gpll4_out_main, 2, 0, 0), + F( 75000000, gpll0_out_main, 8, 0, 0), + F( 150000000, gpll0_out_main, 4, 0, 0), + F( 256000000, gpll4_out_main, 1.5, 0, 0), + F( 300000000, gpll0_out_main, 2, 0, 0), F_END }; diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c index f4ae70ac9315..750511a43b54 100644 --- a/drivers/cpuidle/lpm-levels-of.c +++ b/drivers/cpuidle/lpm-levels-of.c @@ -38,25 +38,87 @@ static const struct lpm_type_str lpm_types[] = { {SUSPEND, "suspend_enabled"}, }; +static DEFINE_PER_CPU(uint32_t *, max_residency); static struct lpm_level_avail *cpu_level_available[NR_CPUS]; static struct platform_device *lpm_pdev; -static void *get_avail_val(struct kobject *kobj, struct kobj_attribute *attr) +static void *get_enabled_ptr(struct kobj_attribute *attr, + struct lpm_level_avail *avail) { void *arg = NULL; + + if (!strcmp(attr->attr.name, lpm_types[IDLE].str)) + arg = (void *) &avail->idle_enabled; + else if (!strcmp(attr->attr.name, lpm_types[SUSPEND].str)) + arg = (void *) &avail->suspend_enabled; + + return arg; +} + +static struct lpm_level_avail *get_avail_ptr(struct kobject *kobj, + struct kobj_attribute *attr) +{ struct lpm_level_avail *avail = NULL; - if (!strcmp(attr->attr.name, lpm_types[IDLE].str)) { + if (!strcmp(attr->attr.name, lpm_types[IDLE].str)) avail = container_of(attr, struct lpm_level_avail, idle_enabled_attr); - arg = (void *) &avail->idle_enabled; - } else if (!strcmp(attr->attr.name, lpm_types[SUSPEND].str)) { + else if (!strcmp(attr->attr.name, lpm_types[SUSPEND].str)) avail = container_of(attr, struct lpm_level_avail, suspend_enabled_attr); - arg = (void *) &avail->suspend_enabled; + + return avail; +} + +static void set_optimum_cpu_residency(struct lpm_cpu *cpu, int cpu_id, + bool probe_time) +{ + int i, j; + bool mode_avail; + uint32_t *residency = per_cpu(max_residency, cpu_id); + + for (i = 0; i < cpu->nlevels; i++) { + struct power_params *pwr = &cpu->levels[i].pwr; + + residency[i] = ~0; + for (j = i + 1; j < cpu->nlevels; j++) { + mode_avail = probe_time || + lpm_cpu_mode_allow(cpu_id, j, true); + + if (mode_avail && + (residency[i] > pwr->residencies[j]) && + (pwr->residencies[j] != 0)) + residency[i] = pwr->residencies[j]; + } } +} - return arg; +static void set_optimum_cluster_residency(struct lpm_cluster *cluster, + bool probe_time) +{ + int i, j; + bool mode_avail; + + for (i = 0; i < cluster->nlevels; i++) { + struct power_params *pwr = &cluster->levels[i].pwr; + + pwr->max_residency = ~0; + for (j = 0; j < cluster->nlevels; j++) { + if (i >= j) + mode_avail = probe_time || + lpm_cluster_mode_allow(cluster, i, + true); + if (mode_avail && + (pwr->max_residency > pwr->residencies[j]) && + (pwr->residencies[j] != 0)) + pwr->max_residency = pwr->residencies[j]; + } + } +} + +uint32_t *get_per_cpu_max_residency(int cpu) +{ + return per_cpu(max_residency, cpu); } ssize_t lpm_enable_show(struct kobject *kobj, struct kobj_attribute *attr, @@ -65,7 +127,7 @@ ssize_t lpm_enable_show(struct kobject *kobj, struct kobj_attribute *attr, int ret = 0; struct kernel_param kp; - kp.arg = get_avail_val(kobj, attr); + kp.arg = get_enabled_ptr(attr, get_avail_ptr(kobj, attr)); ret = param_get_bool(buf, &kp); if (ret > 0) { strlcat(buf, "\n", PAGE_SIZE); @@ -80,15 +142,23 @@ ssize_t lpm_enable_store(struct kobject *kobj, struct kobj_attribute *attr, { int ret = 0; struct kernel_param kp; + struct lpm_level_avail *avail; - kp.arg = get_avail_val(kobj, attr); + avail = get_avail_ptr(kobj, attr); + kp.arg = get_enabled_ptr(attr, avail); ret = param_set_bool(buf, &kp); + if (avail->cpu_node) + set_optimum_cpu_residency(avail->data, avail->idx, false); + else + set_optimum_cluster_residency(avail->data, false); + return ret ? ret : len; } static int create_lvl_avail_nodes(const char *name, - struct kobject *parent, struct lpm_level_avail *avail) + struct kobject *parent, struct lpm_level_avail *avail, + void *data, int index, bool cpu_node) { struct attribute_group *attr_group = NULL; struct attribute **attr = NULL; @@ -139,6 +209,9 @@ static int create_lvl_avail_nodes(const char *name, avail->idle_enabled = true; avail->suspend_enabled = true; avail->kobj = kobj; + avail->data = data; + avail->idx = index; + avail->cpu_node = cpu_node; return ret; @@ -181,7 +254,8 @@ static int create_cpu_lvl_nodes(struct lpm_cluster *p, struct kobject *parent) for (i = 0; i < p->cpu->nlevels; i++) { ret = create_lvl_avail_nodes(p->cpu->levels[i].name, - cpu_kobj[cpu_idx], &level_list[i]); + cpu_kobj[cpu_idx], &level_list[i], + (void *)p->cpu, cpu, true); if (ret) goto release_kobj; } @@ -215,7 +289,8 @@ int create_cluster_lvl_nodes(struct lpm_cluster *p, struct kobject *kobj) for (i = 0; i < p->nlevels; i++) { ret = create_lvl_avail_nodes(p->levels[i].level_name, - cluster_kobj, &p->levels[i].available); + cluster_kobj, &p->levels[i].available, + (void *)p, 0, false); if (ret) return ret; } @@ -421,6 +496,9 @@ static int parse_power_params(struct device_node *node, key = "qcom,time-overhead"; ret = of_property_read_u32(node, key, &pwr->time_overhead_us); + if (ret) + goto fail; + fail: if (ret) pr_err("%s(): %s Error reading %s\n", __func__, node->name, @@ -615,11 +693,31 @@ static int get_cpumask_for_node(struct device_node *node, struct cpumask *mask) return 0; } +static int calculate_residency(struct power_params *base_pwr, + struct power_params *next_pwr) +{ + int32_t residency = (int32_t)(next_pwr->energy_overhead - + base_pwr->energy_overhead) - + ((int32_t)(next_pwr->ss_power * next_pwr->time_overhead_us) + - (int32_t)(base_pwr->ss_power * base_pwr->time_overhead_us)); + + residency /= (int32_t)(base_pwr->ss_power - next_pwr->ss_power); + + if (residency < 0) { + __WARN_printf("%s: Incorrect power attributes for LPM\n", + __func__); + return next_pwr->time_overhead_us; + } + + return residency < next_pwr->time_overhead_us ? + next_pwr->time_overhead_us : residency; +} + static int parse_cpu_levels(struct device_node *node, struct lpm_cluster *c) { struct device_node *n; int ret = -ENOMEM; - int i; + int i, j; char *key; c->cpu = devm_kzalloc(&lpm_pdev->dev, sizeof(*c->cpu), GFP_KERNEL); @@ -676,6 +774,22 @@ static int parse_cpu_levels(struct device_node *node, struct lpm_cluster *c) else if (ret) goto failed; } + for (i = 0; i < c->cpu->nlevels; i++) { + for (j = 0; j < c->cpu->nlevels; j++) { + if (i >= j) { + c->cpu->levels[i].pwr.residencies[j] = 0; + continue; + } + + c->cpu->levels[i].pwr.residencies[j] = + calculate_residency(&c->cpu->levels[i].pwr, + &c->cpu->levels[j].pwr); + + pr_err("%s: idx %d %u\n", __func__, j, + c->cpu->levels[i].pwr.residencies[j]); + } + } + return 0; failed: for (i = 0; i < c->cpu->nlevels; i++) { @@ -732,6 +846,7 @@ struct lpm_cluster *parse_cluster(struct device_node *node, struct device_node *n; char *key; int ret = 0; + int i, j; c = devm_kzalloc(&lpm_pdev->dev, sizeof(*c), GFP_KERNEL); if (!c) @@ -789,6 +904,16 @@ struct lpm_cluster *parse_cluster(struct device_node *node, goto failed_parse_cluster; c->aff_level = 1; + + for_each_cpu(i, &c->child_cpus) { + per_cpu(max_residency, i) = devm_kzalloc( + &lpm_pdev->dev, + sizeof(uint32_t) * c->cpu->nlevels, + GFP_KERNEL); + if (!per_cpu(max_residency, i)) + return ERR_PTR(-ENOMEM); + set_optimum_cpu_residency(c->cpu, i, true); + } } } @@ -797,6 +922,17 @@ struct lpm_cluster *parse_cluster(struct device_node *node, else c->last_level = c->nlevels-1; + for (i = 0; i < c->nlevels; i++) { + for (j = 0; j < c->nlevels; j++) { + if (i >= j) { + c->levels[i].pwr.residencies[j] = 0; + continue; + } + c->levels[i].pwr.residencies[j] = calculate_residency( + &c->levels[i].pwr, &c->levels[j].pwr); + } + } + set_optimum_cluster_residency(c, true); return c; failed_parse_cluster: diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 35ed569c21a5..3eeafdfbee43 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -453,18 +453,15 @@ static int cpu_power_select(struct cpuidle_device *dev, struct lpm_cpu *cpu) { int best_level = -1; - uint32_t best_level_pwr = ~0U; uint32_t latency_us = pm_qos_request_for_cpu(PM_QOS_CPU_DMA_LATENCY, dev->cpu); uint32_t sleep_us = (uint32_t)(ktime_to_us(tick_nohz_get_sleep_length())); uint32_t modified_time_us = 0; uint32_t next_event_us = 0; - uint32_t pwr; int i; uint32_t lvl_latency_us = 0; - uint32_t lvl_overhead_us = 0; - uint32_t lvl_overhead_energy = 0; + uint32_t *residency = get_per_cpu_max_residency(dev->cpu); if (!cpu) return -EINVAL; @@ -488,12 +485,8 @@ static int cpu_power_select(struct cpuidle_device *dev, lvl_latency_us = pwr_params->latency_us; - lvl_overhead_us = pwr_params->time_overhead_us; - - lvl_overhead_energy = pwr_params->energy_overhead; - if (latency_us < lvl_latency_us) - continue; + break; if (next_event_us) { if (next_event_us < lvl_latency_us) @@ -504,32 +497,15 @@ static int cpu_power_select(struct cpuidle_device *dev, next_wakeup_us = next_event_us - lvl_latency_us; } - if (next_wakeup_us <= pwr_params->time_overhead_us) - continue; - - /* - * If wakeup time greater than overhead by a factor of 1000 - * assume that core steady state power dominates the power - * equation - */ - if ((next_wakeup_us >> 10) > lvl_overhead_us) { - pwr = pwr_params->ss_power; - } else { - pwr = pwr_params->ss_power; - pwr -= (lvl_overhead_us * pwr_params->ss_power) / - next_wakeup_us; - pwr += pwr_params->energy_overhead / next_wakeup_us; - } - - if (best_level_pwr >= pwr) { + if (next_wakeup_us <= residency[i]) { best_level = i; - best_level_pwr = pwr; if (next_event_us && next_event_us < sleep_us && (mode != MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)) modified_time_us = next_event_us - lvl_latency_us; else modified_time_us = 0; + break; } } @@ -587,8 +563,6 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle) { int best_level = -1; int i; - uint32_t best_level_pwr = ~0U; - uint32_t pwr; struct cpumask mask; uint32_t latency_us = ~0U; uint32_t sleep_us; @@ -640,18 +614,9 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle) if (level->notify_rpm && msm_rpm_waiting_for_ack()) continue; - if ((sleep_us >> 10) > pwr_params->time_overhead_us) { - pwr = pwr_params->ss_power; - } else { - pwr = pwr_params->ss_power; - pwr -= (pwr_params->time_overhead_us * - pwr_params->ss_power) / sleep_us; - pwr += pwr_params->energy_overhead / sleep_us; - } - - if (best_level_pwr >= pwr) { + if (sleep_us <= pwr_params->max_residency) { best_level = i; - best_level_pwr = pwr; + break; } } diff --git a/drivers/cpuidle/lpm-levels.h b/drivers/cpuidle/lpm-levels.h index 8e05336be21a..f6979c4d4d9f 100644 --- a/drivers/cpuidle/lpm-levels.h +++ b/drivers/cpuidle/lpm-levels.h @@ -27,6 +27,8 @@ struct power_params { uint32_t ss_power; /* Steady state power */ uint32_t energy_overhead; /* Enter + exit over head */ uint32_t time_overhead_us; /* Enter + exit overhead */ + uint32_t residencies[NR_LPM_LEVELS]; + uint32_t max_residency; }; struct lpm_cpu_level { @@ -55,6 +57,9 @@ struct lpm_level_avail { struct kobject *kobj; struct kobj_attribute idle_enabled_attr; struct kobj_attribute suspend_enabled_attr; + void *data; + int idx; + bool cpu_node; }; struct lpm_cluster_level { @@ -119,7 +124,7 @@ bool lpm_cpu_mode_allow(unsigned int cpu, unsigned int mode, bool from_idle); bool lpm_cluster_mode_allow(struct lpm_cluster *cluster, unsigned int mode, bool from_idle); - +uint32_t *get_per_cpu_max_residency(int cpu); extern struct lpm_cluster *lpm_root_node; #ifdef CONFIG_SMP diff --git a/drivers/devfreq/governor_spdm_bw_hyp.c b/drivers/devfreq/governor_spdm_bw_hyp.c index e5e179931811..640af17144df 100644 --- a/drivers/devfreq/governor_spdm_bw_hyp.c +++ b/drivers/devfreq/governor_spdm_bw_hyp.c @@ -1,5 +1,5 @@ /* -*Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +*Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * *This program is free software; you can redistribute it and/or modify *it under the terms of the GNU General Public License version 2 and @@ -84,6 +84,10 @@ static irqreturn_t threaded_isr(int irq, void *dev_id) (int)desc.arg[0], ext_status); mutex_lock(&devfreqs_lock); list_for_each_entry(data, &devfreqs, list) { + if (data == NULL || data->devfreq == NULL) { + pr_err("Spurious interrupts\n"); + break; + } if (data->spdm_client == desc.ret[0]) { devfreq_monitor_suspend(data->devfreq); mutex_lock(&data->devfreq->lock); diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index 27884ff645d8..47e5078292c4 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -411,6 +411,8 @@ void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, * to used in the time period calculation * then calc the number of jiffies that represents */ + if (!msec) + msec = 1000; edac_dev->poll_msec = msec; edac_dev->delay = msecs_to_jiffies(msec); @@ -530,7 +532,7 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev) * enable workq processing on this instance, * default = 1000 msec */ - edac_device_workq_setup(edac_dev, 1000); + edac_device_workq_setup(edac_dev, edac_dev->poll_msec); } else { edac_dev->op_state = OP_RUNNING_INTERRUPT; } diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 2a3fbd5d08c7..7e36816ee2db 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -177,6 +177,7 @@ static const struct { { adreno_is_a530, a530_efuse_speed_bin }, { adreno_is_a530, a540_efuse_firmware_name }, { adreno_is_a540v1, a540_efuse_firmware_name }, + { adreno_is_a505, a530_efuse_speed_bin }, }; static void a5xx_check_features(struct adreno_device *adreno_dev) diff --git a/drivers/gpu/msm/kgsl_cmdbatch.c b/drivers/gpu/msm/kgsl_cmdbatch.c index f0d674161036..ceca8b1e1522 100644 --- a/drivers/gpu/msm/kgsl_cmdbatch.c +++ b/drivers/gpu/msm/kgsl_cmdbatch.c @@ -539,42 +539,41 @@ static void add_profiling_buffer(struct kgsl_device *device, int kgsl_cmdbatch_add_ibdesc(struct kgsl_device *device, struct kgsl_cmdbatch *cmdbatch, struct kgsl_ibdesc *ibdesc) { + uint64_t gpuaddr = (uint64_t) ibdesc->gpuaddr; + uint64_t size = (uint64_t) ibdesc->sizedwords << 2; struct kgsl_memobj_node *mem; + /* sanitize the ibdesc ctrl flags */ + ibdesc->ctrl &= KGSL_IBDESC_MEMLIST | KGSL_IBDESC_PROFILING_BUFFER; + + if (cmdbatch->flags & KGSL_CMDBATCH_MEMLIST && + ibdesc->ctrl & KGSL_IBDESC_MEMLIST) { + if (ibdesc->ctrl & KGSL_IBDESC_PROFILING_BUFFER) { + add_profiling_buffer(device, cmdbatch, + gpuaddr, size, 0, 0); + return 0; + } + } + + if (cmdbatch->flags & (KGSL_CMDBATCH_SYNC | KGSL_CMDBATCH_MARKER)) + return 0; + mem = kmem_cache_alloc(memobjs_cache, GFP_KERNEL); if (mem == NULL) return -ENOMEM; - mem->gpuaddr = (uint64_t) ibdesc->gpuaddr; - mem->size = (uint64_t) ibdesc->sizedwords << 2; + mem->gpuaddr = gpuaddr; + mem->size = size; mem->priv = 0; mem->id = 0; mem->offset = 0; mem->flags = 0; - /* sanitize the ibdesc ctrl flags */ - ibdesc->ctrl &= KGSL_IBDESC_MEMLIST | KGSL_IBDESC_PROFILING_BUFFER; - if (cmdbatch->flags & KGSL_CMDBATCH_MEMLIST && ibdesc->ctrl & KGSL_IBDESC_MEMLIST) { - if (ibdesc->ctrl & KGSL_IBDESC_PROFILING_BUFFER) { - add_profiling_buffer(device, cmdbatch, mem->gpuaddr, - mem->size, 0, 0); - return 0; - } - /* add to the memlist */ list_add_tail(&mem->node, &cmdbatch->memlist); - - if (ibdesc->ctrl & KGSL_IBDESC_PROFILING_BUFFER) - add_profiling_buffer(device, cmdbatch, mem->gpuaddr, - mem->size, 0, 0); } else { - /* Ignore if SYNC or MARKER is specified */ - if (cmdbatch->flags & - (KGSL_CMDBATCH_SYNC | KGSL_CMDBATCH_MARKER)) - return 0; - /* set the preamble flag if directed to */ if (cmdbatch->context->flags & KGSL_CONTEXT_PREAMBLE && list_empty(&cmdbatch->cmdlist)) diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index b20f1ff895b4..50dcd39fac58 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -852,8 +852,8 @@ kgsl_sharedmem_readl(const struct kgsl_memdesc *memdesc, if (offsetbytes % sizeof(uint32_t) != 0) return -EINVAL; - WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size); - if (offsetbytes + sizeof(uint32_t) > memdesc->size) + WARN_ON(offsetbytes > (memdesc->size - sizeof(uint32_t))); + if (offsetbytes > (memdesc->size - sizeof(uint32_t))) return -ERANGE; rmb(); @@ -875,8 +875,8 @@ kgsl_sharedmem_writel(struct kgsl_device *device, if (offsetbytes % sizeof(uint32_t) != 0) return -EINVAL; - WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size); - if (offsetbytes + sizeof(uint32_t) > memdesc->size) + WARN_ON(offsetbytes > (memdesc->size - sizeof(uint32_t))); + if (offsetbytes > (memdesc->size - sizeof(uint32_t))) return -ERANGE; kgsl_cffdump_write(device, memdesc->gpuaddr + offsetbytes, @@ -901,8 +901,8 @@ kgsl_sharedmem_readq(const struct kgsl_memdesc *memdesc, if (offsetbytes % sizeof(uint32_t) != 0) return -EINVAL; - WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size); - if (offsetbytes + sizeof(uint32_t) > memdesc->size) + WARN_ON(offsetbytes > (memdesc->size - sizeof(uint32_t))); + if (offsetbytes > (memdesc->size - sizeof(uint32_t))) return -ERANGE; /* @@ -928,8 +928,8 @@ kgsl_sharedmem_writeq(struct kgsl_device *device, if (offsetbytes % sizeof(uint32_t) != 0) return -EINVAL; - WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size); - if (offsetbytes + sizeof(uint32_t) > memdesc->size) + WARN_ON(offsetbytes > (memdesc->size - sizeof(uint32_t))); + if (offsetbytes > (memdesc->size - sizeof(uint32_t))) return -ERANGE; kgsl_cffdump_write(device, lower_32_bits(memdesc->gpuaddr + offsetbytes), src); diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c index 291d6d52fd7a..898110fe882c 100644 --- a/drivers/input/touchscreen/gt9xx/goodix_tool.c +++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c @@ -1,7 +1,7 @@ /* drivers/input/touchscreen/goodix_tool.c * * 2010 - 2012 Goodix Technology. - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,10 +69,6 @@ static void tool_set_proc_name(char *procname) char month[4] = {0}; int i = 0, n_month = 1, n_day = 0, n_year = 0, ret; - snprintf(date, 20, "%s", __DATE__); - - /* pr_debug("compile date: %s", date); */ - ret = sscanf(date, "%s %d %d", month, &n_day, &n_year); if (!ret) return; diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index 28b8851aade2..d4dc15cea38a 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -1,6 +1,6 @@ /* drivers/input/touchscreen/gt9xx.c * - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * Linux Foundation chooses to take subject only to the GPLv2 license * terms, and distributes only under these terms. @@ -51,6 +51,8 @@ #include <linux/module.h> #include <linux/input/mt.h> #include <linux/debugfs.h> +#include <linux/interrupt.h> +#include <linux/delay.h> #define GOODIX_DEV_NAME "Goodix-CTP" #define CFG_MAX_TOUCH_POINTS 5 @@ -650,7 +652,7 @@ void gtp_reset_guitar(struct goodix_ts_data *ts, int ms) else gpio_direction_output(ts->pdata->irq_gpio, 0); - usleep(RESET_DELAY_T3_US); + usleep_range(200, 250); gpio_direction_output(ts->pdata->reset_gpio, 1); msleep(RESET_DELAY_T4); @@ -743,7 +745,7 @@ static u8 gtp_enter_sleep(struct goodix_ts_data *ts) } return 0; } - usleep(5000); + usleep_range(5000, 5500); while (retry++ < GTP_I2C_RETRY_5) { ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); if (ret == 1) { @@ -812,7 +814,7 @@ err_retry: } else { ret = gpio_direction_output( ts->pdata->irq_gpio, 1); - usleep(5000); + usleep_range(5000, 5500); } } ret = gtp_i2c_test(ts->client); @@ -1174,11 +1176,10 @@ Output: static int gtp_request_irq(struct goodix_ts_data *ts) { int ret = 0; - const u8 irq_table[] = GTP_IRQ_TAB; ret = request_threaded_irq(ts->client->irq, NULL, goodix_ts_irq_handler, - irq_table[ts->int_trigger_type], + ts->pdata->irq_gpio_flags, ts->client->name, ts); if (ret) { ts->use_irq = false; @@ -1459,7 +1460,7 @@ static int goodix_power_init(struct goodix_ts_data *ts) "Regulator get failed vdd ret=%d\n", ret); } - ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc-i2c"); + ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc_i2c"); if (IS_ERR(ts->vcc_i2c)) { ret = PTR_ERR(ts->vcc_i2c); dev_info(&ts->client->dev, diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h index 028eb4babe0b..9cac7a33c33e 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.h +++ b/drivers/input/touchscreen/gt9xx/gt9xx.h @@ -1,6 +1,6 @@ /* drivers/input/touchscreen/gt9xx.h * - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * Linux Foundation chooses to take subject only to the GPLv2 license * terms, and distributes only under these terms. @@ -116,7 +116,7 @@ extern u16 show_len; extern u16 total_len; /***************************PART1:ON/OFF define*******************************/ -#define GTP_CUSTOM_CFG 0 +#define GTP_CUSTOM_CFG 1 #define GTP_ESD_PROTECT 0 #define GTP_IRQ_TAB {\ @@ -130,7 +130,7 @@ extern u16 total_len; #define GTP_IRQ_TAB_RISING 0 #define GTP_IRQ_TAB_FALLING 1 #if GTP_CUSTOM_CFG -#define GTP_MAX_HEIGHT 800 +#define GTP_MAX_HEIGHT 864 #define GTP_MAX_WIDTH 480 #define GTP_INT_TRIGGER GTP_IRQ_TAB_RISING #else diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c index 63f9c5c3ddfc..98f537b7a9b5 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx_update.c @@ -1,7 +1,7 @@ /* drivers/input/touchscreen/gt9xx_update.c * * 2010 - 2012 Goodix Technology. - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -389,7 +389,7 @@ s32 gup_enter_update_mode(struct i2c_client *client) /* step1:RST output low last at least 2ms */ gpio_direction_output(ts->pdata->reset_gpio, 0); - usleep(20000); + msleep(20); /* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */ gpio_direction_output(ts->pdata->irq_gpio, diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c index f69539afe0b2..b2110f8b6032 100644 --- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c +++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c @@ -117,7 +117,6 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data, bool *was_in_bl_mode); static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data); -static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data); static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data, bool rebuild); @@ -1686,12 +1685,6 @@ static void synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data, } if (status.unconfigured && !status.flash_prog) { pr_notice("%s: spontaneous reset detected\n", __func__); - retval = synaptics_rmi4_reinit_device(rmi4_data); - if (retval < 0) { - dev_err(rmi4_data->pdev->dev.parent, - "%s: Failed to reinit device\n", - __func__); - } } if (!report) @@ -3660,49 +3653,6 @@ exit: return; } -static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data) -{ - int retval; - struct synaptics_rmi4_fn *fhandler; - struct synaptics_rmi4_exp_fhandler *exp_fhandler; - struct synaptics_rmi4_device_info *rmi; - - rmi = &(rmi4_data->rmi4_mod_info); - - mutex_lock(&(rmi4_data->rmi4_reset_mutex)); - - synaptics_rmi4_free_fingers(rmi4_data); - - if (!list_empty(&rmi->support_fn_list)) { - list_for_each_entry(fhandler, &rmi->support_fn_list, link) { - if (fhandler->fn_number == SYNAPTICS_RMI4_F12) { - synaptics_rmi4_f12_set_enables(rmi4_data, 0); - break; - } - } - } - - retval = synaptics_rmi4_int_enable(rmi4_data, true); - if (retval < 0) - goto exit; - - mutex_lock(&exp_data.mutex); - if (!list_empty(&exp_data.list)) { - list_for_each_entry(exp_fhandler, &exp_data.list, link) - if (exp_fhandler->exp_fn->reinit != NULL) - exp_fhandler->exp_fn->reinit(rmi4_data); - } - mutex_unlock(&exp_data.mutex); - - synaptics_rmi4_set_configured(rmi4_data); - - retval = 0; - -exit: - mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); - return retval; -} - static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data, bool rebuild) { diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 34c01065b578..30c4d968927b 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -129,6 +129,7 @@ static u64 __maybe_unused gic_read_iar(void) asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat)); /* As per the architecture specification */ + isb(); mb(); return irqstat; } @@ -137,6 +138,7 @@ static void __maybe_unused gic_write_pmr(u64 val) { asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" (val)); /* As per the architecture specification */ + isb(); mb(); } @@ -156,6 +158,7 @@ static void __maybe_unused gic_write_sgi1r(u64 val) { asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val)); /* As per the architecture specification */ + isb(); mb(); } diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 0c9962817849..06cad663be25 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -28,6 +28,10 @@ obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o +ccflags-y += -Idrivers/media/platform/msm/camera_v2 +ccflags-y += -Idrivers/media/platform/msm/camera_v2/common +ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io +ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci obj-$(CONFIG_VIDEO_ADV7481) += adv7481.o obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o obj-$(CONFIG_VIDEO_ADV7511) += adv7511.o diff --git a/drivers/media/i2c/adv7481.c b/drivers/media/i2c/adv7481.c index 359a860fdabb..2ba8cb9623da 100644 --- a/drivers/media/i2c/adv7481.c +++ b/drivers/media/i2c/adv7481.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,17 +27,27 @@ #include <media/v4l2-ctrls.h> #include <linux/mutex.h> #include <linux/delay.h> + +#include <linux/platform_device.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> + #include <media/adv7481.h> #include <media/msm_ba.h> #include "adv7481_reg.h" +#include "msm_cci.h" +#include "msm_camera_i2c.h" +#include "msm_camera_io_util.h" +#include "msm_camera_dt_util.h" + #define DRIVER_NAME "adv7481" -#define I2C_RW_DELAY 100 -#define I2C_SW_RST_DELAY 10000 -#define GPIO_HW_DELAY_LOW 100000 -#define GPIO_HW_DELAY_HI 10000 +#define I2C_RW_DELAY 1 +#define I2C_SW_RST_DELAY 5000 +#define GPIO_HW_RST_DELAY_HI 10000 +#define GPIO_HW_RST_DELAY_LOW 10000 #define SDP_MIN_SLEEP 5000 #define SDP_MAX_SLEEP 6000 #define SDP_NUM_TRIES 30 @@ -45,11 +55,44 @@ #define LOCK_MAX_SLEEP 6000 #define LOCK_NUM_TRIES 20 +#define MAX_DEFAULT_WIDTH 1280 +#define MAX_DEFAULT_HEIGHT 720 +#define MAX_DEFAULT_FRAME_RATE 60 +#define MAX_DEFAULT_PIX_CLK_HZ 74240000 + #define ONE_MHZ_TO_HZ 1000000 +enum adv7481_gpio_t { + + CCI_I2C_SDA = 0, + CCI_I2C_SCL, + + ADV7481_GPIO_RST, + + ADV7481_GPIO_INT1, + ADV7481_GPIO_INT2, + ADV7481_GPIO_INT3, + + ADV7481_GPIO_MAX, +}; + struct adv7481_state { /* Platform Data */ struct adv7481_platform_data pdata; + struct device *dev; + + /* VREG */ + struct camera_vreg_t *cci_vreg; + struct regulator *cci_reg_ptr[MAX_REGULATOR]; + int32_t regulator_count; + + /* I2C */ + struct msm_camera_i2c_client i2c_client; + u32 cci_master; + u32 i2c_slave_addr; + u32 i2c_csi_slave_addr; + u32 i2c_vpp_slave_addr; + u32 register_page; /* V4L2 Data */ struct v4l2_subdev sd; @@ -63,19 +106,24 @@ struct adv7481_state { struct workqueue_struct *work_queues; struct mutex mutex; - struct i2c_client *client; - struct i2c_client *i2c_csi_txa; - struct i2c_client *i2c_csi_txb; - struct i2c_client *i2c_hdmi; - struct i2c_client *i2c_edid; - struct i2c_client *i2c_cp; - struct i2c_client *i2c_sdp; - struct i2c_client *i2c_rep; + uint8_t i2c_io_addr; + uint8_t i2c_csi_txa_addr; + uint8_t i2c_csi_txb_addr; + uint8_t i2c_hdmi_addr; + uint8_t i2c_edid_addr; + uint8_t i2c_cp_addr; + uint8_t i2c_sdp_addr; + uint8_t i2c_rep_addr; + uint8_t i2c_cbus_addr; /* device status and Flags */ int irq; int device_num; int powerup; + int cec_detected; + + /* GPIOs */ + struct gpio gpio_array[ADV7481_GPIO_MAX]; /* routing configuration data */ int csia_src; @@ -196,6 +244,9 @@ const uint8_t adv7481_default_edid_data[] = { #define ADV7481_EDID_SIZE ARRAY_SIZE(adv7481_default_edid_data) +static u32 adv7481_inp_to_ba(u32 adv_input); +static bool adv7481_is_timing_locked(struct adv7481_state *state); + static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) { return &(container_of(ctrl->handler, @@ -208,50 +259,102 @@ static inline struct adv7481_state *to_state(struct v4l2_subdev *sd) } /* I2C Rd/Rw Functions */ -static int adv7481_wr_byte(struct i2c_client *i2c_client, unsigned int reg, - unsigned int value) +static int32_t adv7481_cci_i2c_write(struct msm_camera_i2c_client *i2c_client, + uint8_t reg, uint16_t *data, + enum msm_camera_i2c_data_type data_type) { - int ret; + return i2c_client->i2c_func_tbl->i2c_write(i2c_client, reg, + *data, data_type); +} + +static int32_t adv7481_cci_i2c_read(struct msm_camera_i2c_client *i2c_client, + uint8_t reg, uint16_t *data, + enum msm_camera_i2c_data_type data_type) +{ + return i2c_client->i2c_func_tbl->i2c_read(i2c_client, reg, + data, data_type); +} + +static int32_t adv7481_wr_byte(struct msm_camera_i2c_client *c_i2c_client, + uint8_t sid, uint8_t reg, uint8_t data) +{ + uint16_t write_data = data; + int ret = 0; + + c_i2c_client->cci_client->sid = sid; - ret = i2c_smbus_write_byte_data(i2c_client, reg & 0xFF, value); - usleep_range(I2C_RW_DELAY, 2*I2C_RW_DELAY); + ret = adv7481_cci_i2c_write(c_i2c_client, reg, &write_data, + MSM_CAMERA_I2C_BYTE_DATA); + if (ret < 0) + pr_err("Error %d writing cci i2c\n", ret); return ret; } -static int adv7481_rd_byte(struct i2c_client *i2c_client, unsigned int reg) +static uint8_t adv7481_rd_byte(struct msm_camera_i2c_client *c_i2c_client, + uint8_t sid, uint8_t reg) { + uint16_t data = 0; + int ret = 0; + + c_i2c_client->cci_client->sid = sid; + ret = adv7481_cci_i2c_read(c_i2c_client, reg, &data, + MSM_CAMERA_I2C_BYTE_DATA); + if (ret < 0) { + pr_err("Error %d reading cci i2c\n", ret); + return ret; + } + + return (uint8_t)(data & 0xFF); +} + +static uint16_t adv7481_rd_word(struct msm_camera_i2c_client *c_i2c_client, + uint8_t sid, uint8_t reg) +{ + uint16_t data = 0; int ret; - ret = i2c_smbus_read_byte_data(i2c_client, reg & 0xFF); - usleep_range(I2C_RW_DELAY, 2*I2C_RW_DELAY); + c_i2c_client->cci_client->sid = sid; + ret = adv7481_cci_i2c_read(c_i2c_client, reg, &data, + MSM_CAMERA_I2C_WORD_DATA); + if (ret < 0) { + pr_err("Error %d reading cci i2c\n", ret); + return ret; + } - return ret; + return data; } static int adv7481_set_irq(struct adv7481_state *state) { int ret = 0; - ret = adv7481_wr_byte(state->client, IO_REG_PAD_CTRL_1_ADDR, + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_PAD_CTRL_1_ADDR, ADV_REG_SETFIELD(1, IO_PDN_INT2) | ADV_REG_SETFIELD(1, IO_PDN_INT3) | ADV_REG_SETFIELD(1, IO_INV_LLC) | ADV_REG_SETFIELD(AD_MID_DRIVE_STRNGTH, IO_DRV_LLC_PAD)); - ret |= adv7481_wr_byte(state->client, IO_REG_INT1_CONF_ADDR, + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_INT1_CONF_ADDR, ADV_REG_SETFIELD(AD_ACTIVE_UNTIL_CLR, IO_INTRQ_DUR_SEL) | ADV_REG_SETFIELD(AD_OP_DRIVE_LOW, IO_INTRQ_OP_SEL)); - ret |= adv7481_wr_byte(state->client, IO_REG_INT2_CONF_ADDR, + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_INT2_CONF_ADDR, ADV_REG_SETFIELD(1, IO_CP_LOCK_UNLOCK_EDGE_SEL)); - ret |= adv7481_wr_byte(state->client, IO_REG_DATAPATH_INT_MASKB_ADDR, + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_DATAPATH_INT_MASKB_ADDR, ADV_REG_SETFIELD(1, IO_CP_LOCK_CP_MB1) | ADV_REG_SETFIELD(1, IO_CP_UNLOCK_CP_MB1) | ADV_REG_SETFIELD(1, IO_VMUTE_REQUEST_HDMI_MB1) | ADV_REG_SETFIELD(1, IO_INT_SD_MB1)); - /* Set hpa */ - ret |= adv7481_wr_byte(state->client, IO_HDMI_LVL_INT_MASKB_3_ADDR, - ADV_REG_SETFIELD(1, IO_CABLE_DET_A_MB1)); + /* Set cable detect */ + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_HDMI_LVL_INT_MASKB_3_ADDR, + ADV_REG_SETFIELD(1, IO_CABLE_DET_A_MB1) | + ADV_REG_SETFIELD(1, IO_V_LOCKED_MB1) | + ADV_REG_SETFIELD(1, IO_DE_REGEN_LCK_MB1)); if (ret) pr_err("%s: Failed %d to setup interrupt regs\n", @@ -262,6 +365,20 @@ static int adv7481_set_irq(struct adv7481_state *state) return ret; } +static int adv7481_reset_irq(struct adv7481_state *state) +{ + int ret = 0; + + disable_irq(state->irq); + + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_DATAPATH_INT_MASKB_ADDR, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_HDMI_LVL_INT_MASKB_3_ADDR, 0x00); + + return ret; +} + static int adv7481_set_edid(struct adv7481_state *state) { int i; @@ -269,24 +386,27 @@ static int adv7481_set_edid(struct adv7481_state *state) uint8_t edid_state; /* Enable Manual Control of EDID on Port A */ - ret |= adv7481_wr_byte(state->i2c_rep, 0x74, 0x01); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_rep_addr, 0x74, + 0x01); /* Disable Auto Enable of EDID */ - ret |= adv7481_wr_byte(state->i2c_rep, 0x7A, 0x08); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_rep_addr, 0x7A, + 0x08); /* Set Primary EDID Size to 256 Bytes */ - ret |= adv7481_wr_byte(state->i2c_rep, 0x70, 0x20); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_rep_addr, 0x70, + 0x20); /* * Readback EDID enable state after a combination of manual * and automatic functions */ - edid_state = adv7481_rd_byte(state->i2c_rep, + edid_state = adv7481_rd_byte(&state->i2c_client, state->i2c_rep_addr, HDMI_REG_RO_EDID_DEBUG_2_ADDR); pr_debug("%s: Readback EDID enable state: 0x%x\n", __func__, edid_state); for (i = 0; i < ADV7481_EDID_SIZE; i++) { - ret |= adv7481_wr_byte(state->i2c_edid, i, - adv7481_default_edid_data[i]); + ret |= adv7481_wr_byte(&state->i2c_client, + state->i2c_edid_addr, i, adv7481_default_edid_data[i]); } return ret; @@ -304,43 +424,131 @@ static irqreturn_t adv7481_irq(int irq, void *dev) static void adv7481_irq_delay_work(struct work_struct *work) { struct adv7481_state *state; - uint8_t status; + uint8_t int_raw_status; + uint8_t int_status; + uint8_t raw_status; state = container_of(work, struct adv7481_state, irq_delayed_work.work); mutex_lock(&state->mutex); - /* workaround for irq trigger */ - status = adv7481_rd_byte(state->client, + /* Read raw irq status register */ + int_raw_status = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_INT_RAW_STATUS_ADDR); pr_debug("%s: dev: %d got int raw status: 0x%x\n", __func__, - state->device_num, status); - - status = adv7481_rd_byte(state->client, - IO_REG_DATAPATH_INT_STATUS_ADDR); - - pr_debug("%s: dev: %d got datapath int status: 0x%x\n", __func__, - state->device_num, status); + state->device_num, int_raw_status); + state->cec_detected = ADV_REG_GETFIELD(int_raw_status, IO_INT_CEC_ST); + + if (ADV_REG_GETFIELD(int_raw_status, IO_INTRQ1_RAW)) { + int lock_status = -1; + struct v4l2_event event = {0}; + int *ptr = (int *)event.u.data; + + pr_debug("%s: dev: %d got intrq1_raw\n", __func__, + state->device_num); + int_status = adv7481_rd_byte(&state->i2c_client, + state->i2c_io_addr, + IO_REG_DATAPATH_INT_STATUS_ADDR); + + raw_status = adv7481_rd_byte(&state->i2c_client, + state->i2c_io_addr, + IO_REG_DATAPATH_RAW_STATUS_ADDR); + + adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_DATAPATH_INT_CLEAR_ADDR, int_status); + + pr_debug("%s: dev: %d got datapath int status: 0x%x\n", + __func__, state->device_num, int_status); + + pr_debug("%s: dev: %d got datapath raw status: 0x%x\n", + __func__, state->device_num, raw_status); + + if (ADV_REG_GETFIELD(int_status, IO_CP_LOCK_CP_ST) && + ADV_REG_GETFIELD(raw_status, IO_CP_LOCK_CP_RAW)) { + lock_status = 0; + pr_debug( + "%s: set lock_status IO_CP_LOCK_CP_RAW: 0x%x\n", + __func__, lock_status); + } + if (ADV_REG_GETFIELD(int_status, IO_CP_UNLOCK_CP_ST) && + ADV_REG_GETFIELD(raw_status, IO_CP_UNLOCK_CP_RAW)) { + lock_status = 1; + pr_debug( + "%s: set lock_status IO_CP_UNLOCK_CP_RAW: 0x%x\n", + __func__, lock_status); + } + if (lock_status >= 0) { + ptr[0] = adv7481_inp_to_ba(state->mode); + ptr[1] = lock_status; + event.type = lock_status ? + V4L2_EVENT_MSM_BA_SIGNAL_LOST_LOCK : + V4L2_EVENT_MSM_BA_SIGNAL_IN_LOCK; + v4l2_subdev_notify(&state->sd, + event.type, &event); + } + } - adv7481_wr_byte(state->client, - IO_REG_DATAPATH_INT_CLEAR_ADDR, status); + if (ADV_REG_GETFIELD(int_raw_status, IO_INT_HDMI_ST)) { + int cable_detected = 0; + struct v4l2_event event = {0}; + int *ptr = (int *)event.u.data; - status = adv7481_rd_byte(state->client, - IO_REG_DATAPATH_RAW_STATUS_ADDR); + ptr[0] = adv7481_inp_to_ba(state->mode); - pr_debug("%s: dev: %d got datapath rawstatus: 0x%x\n", __func__, - state->device_num, status); + pr_debug("%s: dev: %d got int_hdmi_st\n", __func__, + state->device_num); - status = adv7481_rd_byte(state->client, - IO_HDMI_LVL_INT_STATUS_3_ADDR); + int_status = adv7481_rd_byte(&state->i2c_client, + state->i2c_io_addr, + IO_HDMI_LVL_INT_STATUS_3_ADDR); - pr_debug("%s: dev: %d got hdmi lvl int status 3: 0x%x\n", __func__, - state->device_num, status); + raw_status = adv7481_rd_byte(&state->i2c_client, + state->i2c_io_addr, + IO_HDMI_LVL_RAW_STATUS_3_ADDR); - adv7481_wr_byte(state->client, - IO_HDMI_LVL_INT_CLEAR_3_ADDR, status); + pr_debug("%s: dev: %d got hdmi lvl int status 3: 0x%x\n", + __func__, state->device_num, int_status); + pr_debug("%s: dev: %d got hdmi lvl raw status 3: 0x%x\n", + __func__, state->device_num, raw_status); + + + if (ADV_REG_GETFIELD(int_status, IO_CABLE_DET_A_ST)) { + cable_detected = ADV_REG_GETFIELD(raw_status, + IO_CABLE_DET_A_RAW); + pr_debug("%s: set cable_detected: 0x%x\n", + __func__, cable_detected); + ptr[1] = cable_detected; + event.type = V4L2_EVENT_MSM_BA_CABLE_DETECT; + v4l2_subdev_notify(&state->sd, + event.type, &event); + } + /* Assumption is that vertical sync int + * is the last one to come */ + if (ADV_REG_GETFIELD(int_status, IO_V_LOCKED_ST)) { + if (ADV_REG_GETFIELD(raw_status, + IO_TMDSPLL_LCK_A_RAW) && + ADV_REG_GETFIELD(raw_status, + IO_V_LOCKED_RAW) && + ADV_REG_GETFIELD(raw_status, + IO_DE_REGEN_LCK_RAW)) { + pr_debug("%s: port settings changed\n", + __func__); + event.type = + V4L2_EVENT_MSM_BA_PORT_SETTINGS_CHANGED; + v4l2_subdev_notify(&state->sd, + event.type, &event); + } + } + } + /* Clear all other interrupts */ + adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_HDMI_LVL_INT_CLEAR_1_ADDR, 0xFF); + adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_HDMI_LVL_INT_CLEAR_2_ADDR, 0xFF); + adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_HDMI_LVL_INT_CLEAR_3_ADDR, 0xFF); mutex_unlock(&state->mutex); } @@ -350,110 +558,100 @@ static int adv7481_cec_wakeup(struct adv7481_state *state, bool enable) uint8_t val; int ret = 0; - val = adv7481_rd_byte(state->client, + val = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_PWR_DN2_XTAL_HIGH_ADDR); val = ADV_REG_GETFIELD(val, IO_PROG_XTAL_FREQ_HIGH); if (enable) { /* CEC wake up enabled in power-down mode */ val |= ADV_REG_SETFIELD(1, IO_CTRL_CEC_WAKE_UP_PWRDN2B) | ADV_REG_SETFIELD(0, IO_CTRL_CEC_WAKE_UP_PWRDNB); - ret = adv7481_wr_byte(state->client, + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_PWR_DN2_XTAL_HIGH_ADDR, val); } else { /* CEC wake up disabled in power-down mode */ val |= ADV_REG_SETFIELD(0, IO_CTRL_CEC_WAKE_UP_PWRDN2B) | ADV_REG_SETFIELD(1, IO_CTRL_CEC_WAKE_UP_PWRDNB); - ret = adv7481_wr_byte(state->client, + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_PWR_DN2_XTAL_HIGH_ADDR, val); } return ret; } /* Initialize adv7481 I2C Settings */ -static int adv7481_dev_init(struct adv7481_state *state, - struct i2c_client *client) +static int adv7481_dev_init(struct adv7481_state *state) { + uint16_t chip_rev_id; int ret; mutex_lock(&state->mutex); /* Soft reset */ - ret = adv7481_wr_byte(state->client, - IO_REG_MAIN_RST_ADDR, IO_REG_MAIN_RST_VALUE); + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_MAIN_RST_ADDR, IO_REG_MAIN_RST_VALUE); /* Delay required following I2C reset and I2C transactions */ - usleep_range(I2C_SW_RST_DELAY, I2C_SW_RST_DELAY+1000); + usleep_range(I2C_SW_RST_DELAY, I2C_SW_RST_DELAY + 1000); + + chip_rev_id = adv7481_rd_word(&state->i2c_client, state->i2c_io_addr, + IO_REG_CHIP_REV_ID_1_ADDR); + pr_debug("%s: ADV7481 chip rev id: 0x%x", __func__, chip_rev_id); /* Disable CEC wake up in power-down mode */ ret |= adv7481_cec_wakeup(state, 0); /* Setting Vid_Std to 720x480p60 */ - ret |= adv7481_wr_byte(state->client, - IO_REG_CP_VID_STD_ADDR, 0x4A); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CP_VID_STD_ADDR, 0x4A); /* Configure I2C Maps and I2C Communication Settings */ /* io_reg_f2 I2C Auto Increment */ - ret |= adv7481_wr_byte(state->client, IO_REG_I2C_CFG_ADDR, - IO_REG_I2C_AUTOINC_EN_REG_VALUE); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_I2C_CFG_ADDR, IO_REG_I2C_AUTOINC_EN_REG_VALUE); /* DPLL Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_DPLL_ADDR, - IO_REG_DPLL_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_DPLL_ADDR, IO_REG_DPLL_SADDR); /* CP Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_CP_ADDR, - IO_REG_CP_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CP_ADDR, IO_REG_CP_SADDR); /* HDMI RX Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_HDMI_ADDR, - IO_REG_HDMI_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_HDMI_ADDR, IO_REG_HDMI_SADDR); /* EDID Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_EDID_ADDR, - IO_REG_EDID_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_EDID_ADDR, IO_REG_EDID_SADDR); /* HDMI RX Repeater Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_HDMI_REP_ADDR, - IO_REG_HDMI_REP_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_HDMI_REP_ADDR, IO_REG_HDMI_REP_SADDR); /* HDMI RX Info-frame Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_HDMI_INF_ADDR, - IO_REG_HDMI_INF_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_HDMI_INF_ADDR, IO_REG_HDMI_INF_SADDR); /* CBUS Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_CBUS_ADDR, - IO_REG_CBUS_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CBUS_ADDR, IO_REG_CBUS_SADDR); /* CEC Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_CEC_ADDR, - IO_REG_CEC_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CEC_ADDR, IO_REG_CEC_SADDR); /* SDP Main Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_SDP_ADDR, - IO_REG_SDP_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_SDP_ADDR, IO_REG_SDP_SADDR); /* CSI-TXB Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_CSI_TXB_ADDR, - IO_REG_CSI_TXB_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CSI_TXB_ADDR, IO_REG_CSI_TXB_SADDR); /* CSI-TXA Map Address */ - ret |= adv7481_wr_byte(state->client, IO_REG_CSI_TXA_ADDR, - IO_REG_CSI_TXA_SADDR); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CSI_TXA_ADDR, IO_REG_CSI_TXA_SADDR); if (ret) { pr_err("%s: Failed dev init %d\n", __func__, ret); goto err_exit; } /* Configure i2c clients */ - state->i2c_csi_txa = i2c_new_dummy(client->adapter, - IO_REG_CSI_TXA_SADDR >> 1); - state->i2c_csi_txb = i2c_new_dummy(client->adapter, - IO_REG_CSI_TXB_SADDR >> 1); - state->i2c_cp = i2c_new_dummy(client->adapter, - IO_REG_CP_SADDR >> 1); - state->i2c_hdmi = i2c_new_dummy(client->adapter, - IO_REG_HDMI_SADDR >> 1); - state->i2c_edid = i2c_new_dummy(client->adapter, - IO_REG_EDID_SADDR >> 1); - state->i2c_sdp = i2c_new_dummy(client->adapter, - IO_REG_SDP_SADDR >> 1); - state->i2c_rep = i2c_new_dummy(client->adapter, - IO_REG_HDMI_REP_SADDR >> 1); - - if (!state->i2c_csi_txa || !state->i2c_csi_txb || !state->i2c_cp || - !state->i2c_sdp || !state->i2c_hdmi || !state->i2c_edid || - !state->i2c_rep) { - pr_err("%s: Additional I2C Client Fail\n", __func__); - ret = -EFAULT; - goto err_exit; - } + state->i2c_csi_txa_addr = IO_REG_CSI_TXA_SADDR >> 1; + state->i2c_csi_txb_addr = IO_REG_CSI_TXB_SADDR >> 1; + state->i2c_cp_addr = IO_REG_CP_SADDR >> 1; + state->i2c_hdmi_addr = IO_REG_HDMI_SADDR >> 1; + state->i2c_edid_addr = IO_REG_EDID_SADDR >> 1; + state->i2c_sdp_addr = IO_REG_SDP_SADDR >> 1; + state->i2c_rep_addr = IO_REG_HDMI_REP_SADDR >> 1; + state->i2c_cbus_addr = IO_REG_CBUS_SADDR >> 1; ret = adv7481_set_edid(state); ret |= adv7481_set_irq(state); @@ -465,28 +663,27 @@ err_exit: } /* Initialize adv7481 hardware */ -static int adv7481_hw_init(struct adv7481_platform_data *pdata, - struct adv7481_state *state) +static int adv7481_hw_init(struct adv7481_state *state) { int ret = 0; - if (!pdata) { - pr_err("%s: PDATA is NULL\n", __func__); - return -EFAULT; - } - mutex_lock(&state->mutex); - if (gpio_is_valid(pdata->rstb_gpio)) { - ret = gpio_request(pdata->rstb_gpio, "rstb_gpio"); - if (ret) { - pr_err("%s: Request GPIO Fail %d\n", __func__, ret); - goto err_exit; - } - ret = gpio_direction_output(pdata->rstb_gpio, 0); - usleep_range(GPIO_HW_DELAY_LOW, GPIO_HW_DELAY_LOW+1000); - ret = gpio_direction_output(pdata->rstb_gpio, 1); - usleep_range(GPIO_HW_DELAY_HI, GPIO_HW_DELAY_HI+1000); + /* Bring ADV7481 out of reset */ + ret = gpio_request_array(&state->gpio_array[ADV7481_GPIO_RST], 1); + if (ret < 0) { + pr_err("%s: Failed to request reset GPIO %d\n", __func__, ret); + goto err_exit; + } + if (gpio_is_valid(state->gpio_array[ADV7481_GPIO_RST].gpio)) { + ret |= gpio_direction_output( + state->gpio_array[ADV7481_GPIO_RST].gpio, 0); + usleep_range(GPIO_HW_RST_DELAY_LOW, GPIO_HW_RST_DELAY_LOW + + 1000); + ret |= gpio_direction_output( + state->gpio_array[ADV7481_GPIO_RST].gpio, 1); + usleep_range(GPIO_HW_RST_DELAY_HI, GPIO_HW_RST_DELAY_HI + + 1000); if (ret) { pr_err("%s: Set GPIO Fail %d\n", __func__, ret); goto err_exit; @@ -494,22 +691,21 @@ static int adv7481_hw_init(struct adv7481_platform_data *pdata, } /* Only setup IRQ1 for now... */ - if (gpio_is_valid(pdata->irq1_gpio)) { - ret = gpio_request(pdata->irq1_gpio, "irq_gpio"); - if (ret) { - pr_err("%s: Failed to request irq_gpio %d\n", - __func__, ret); - goto err_exit; - } - - ret = gpio_direction_input(pdata->irq1_gpio); + ret = gpio_request_array(&state->gpio_array[ADV7481_GPIO_INT1], 1); + if (ret < 0) { + pr_err("%s: Failed to request irq_gpio %d\n", __func__, ret); + goto err_exit; + } + if (gpio_is_valid(state->gpio_array[ADV7481_GPIO_INT1].gpio)) { + ret |= gpio_direction_input( + state->gpio_array[ADV7481_GPIO_INT1].gpio); if (ret) { pr_err("%s: Failed gpio_direction irq %d\n", __func__, ret); goto err_exit; } - - state->irq = gpio_to_irq(pdata->irq1_gpio); + state->irq = gpio_to_irq( + state->gpio_array[ADV7481_GPIO_INT1].gpio); if (state->irq) { ret = request_irq(state->irq, adv7481_irq, IRQF_ONESHOT | IRQF_TRIGGER_FALLING, @@ -519,18 +715,16 @@ static int adv7481_hw_init(struct adv7481_platform_data *pdata, __func__, ret); goto err_exit; } + /* disable irq until chip interrupts are programmed */ + disable_irq(state->irq); } else { pr_err("%s: Failed gpio_to_irq %d\n", __func__, ret); ret = -EINVAL; goto err_exit; } - - /* disable irq until chip interrupts are programmed */ - disable_irq(state->irq); - - INIT_DELAYED_WORK(&state->irq_delayed_work, - adv7481_irq_delay_work); } + INIT_DELAYED_WORK(&state->irq_delayed_work, + adv7481_irq_delay_work); err_exit: mutex_unlock(&state->mutex); @@ -548,31 +742,40 @@ static int adv7481_s_ctrl(struct v4l2_ctrl *ctrl) pr_debug("Enter %s: id = 0x%x\n", __func__, ctrl->id); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - temp = adv7481_rd_byte(state->client, CP_REG_VID_ADJ); + temp = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_VID_ADJ); temp |= CP_CTR_VID_ADJ_EN; - ret = adv7481_wr_byte(state->client, CP_REG_VID_ADJ, temp); - ret |= adv7481_wr_byte(state->client, - CP_REG_BRIGHTNESS, ctrl->val); + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_VID_ADJ, temp); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_BRIGHTNESS, ctrl->val); break; case V4L2_CID_CONTRAST: - temp = adv7481_rd_byte(state->client, CP_REG_VID_ADJ); + temp = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_VID_ADJ); temp |= CP_CTR_VID_ADJ_EN; - ret = adv7481_wr_byte(state->client, CP_REG_VID_ADJ, temp); - ret |= adv7481_wr_byte(state->client, - CP_REG_CONTRAST, ctrl->val); + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_VID_ADJ, temp); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_CONTRAST, ctrl->val); break; case V4L2_CID_SATURATION: - temp = adv7481_rd_byte(state->client, CP_REG_VID_ADJ); + temp = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_VID_ADJ); temp |= CP_CTR_VID_ADJ_EN; - ret = adv7481_wr_byte(state->client, CP_REG_VID_ADJ, temp); - ret |= adv7481_wr_byte(state->client, - CP_REG_SATURATION, ctrl->val); + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_VID_ADJ, temp); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_SATURATION, ctrl->val); break; case V4L2_CID_HUE: - temp = adv7481_rd_byte(state->client, CP_REG_VID_ADJ); + temp = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_VID_ADJ); temp |= CP_CTR_VID_ADJ_EN; - ret = adv7481_wr_byte(state->client, CP_REG_VID_ADJ, temp); - ret |= adv7481_wr_byte(state->client, CP_REG_HUE, ctrl->val); + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_VID_ADJ, temp); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CP_REG_HUE, ctrl->val); break; default: break; @@ -611,6 +814,108 @@ static int adv7481_s_power(struct v4l2_subdev *sd, int on) return ret; } +static int adv7481_set_cec_logical_addr(struct adv7481_state *state, int *la) +{ + int rc = 0; + uint8_t val; + + if (!la) { + pr_err("%s: NULL pointer provided\n", __func__); + return -EINVAL; + } + + val = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + CEC_REG_LOG_ADDR_MASK_ADDR); + if (ADV_REG_GETFIELD(val, CEC_REG_LOG_ADDR_MASK0)) { + val = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + CEC_REG_LOGICAL_ADDRESS0_1_ADDR); + val = ADV_REG_RSTFIELD(val, CEC_REG_LOGICAL_ADDRESS0); + val |= ADV_REG_SETFIELD(*la, CEC_REG_LOGICAL_ADDRESS0); + rc = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CEC_REG_LOGICAL_ADDRESS0_1_ADDR, val); + } else if (ADV_REG_GETFIELD(val, CEC_REG_LOG_ADDR_MASK1)) { + val = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + CEC_REG_LOGICAL_ADDRESS0_1_ADDR); + val = ADV_REG_RSTFIELD(val, CEC_REG_LOGICAL_ADDRESS1); + val |= ADV_REG_SETFIELD(*la, CEC_REG_LOGICAL_ADDRESS1); + rc = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CEC_REG_LOGICAL_ADDRESS0_1_ADDR, val); + } else if (ADV_REG_GETFIELD(val, CEC_REG_LOG_ADDR_MASK2)) { + val = ADV_REG_SETFIELD(*la, CEC_REG_LOGICAL_ADDRESS2); + rc = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CEC_REG_LOGICAL_ADDRESS2_ADDR, val); + } else { + pr_err("No cec logical address mask set\n"); + } + + return rc; +} + +static int adv7481_cec_powerup(struct adv7481_state *state, int *powerup) +{ + int rc = 0; + uint8_t val = 0; + + if (!powerup) { + pr_err("%s: NULL pointer provided\n", __func__); + return -EINVAL; + } + + pr_debug("%s: set power %d\n", __func__, *powerup); + + val = ADV_REG_SETFIELD(*powerup, CEC_REG_CEC_POWER_UP); + rc = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + CEC_REG_CEC_POWER_UP_ADDR, val); + + return rc; +} + +static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct adv7481_state *state = to_state(sd); + int *ret_val = arg; + long ret = 0; + int param = 0; + + pr_debug("Enter %s with command: 0x%x", __func__, cmd); + + if (!sd) + return -EINVAL; + + switch (cmd) { + case VIDIOC_HDMI_RX_CEC_S_LOGICAL: + ret = adv7481_set_cec_logical_addr(state, arg); + break; + case VIDIOC_HDMI_RX_CEC_CLEAR_LOGICAL: + ret = adv7481_set_cec_logical_addr(state, ¶m); + break; + case VIDIOC_HDMI_RX_CEC_G_PHYSICAL: + if (ret_val) { + *ret_val = 0; + } else { + pr_err("%s: NULL pointer provided\n", __func__); + ret = -EINVAL; + } + break; + case VIDIOC_HDMI_RX_CEC_G_CONNECTED: + if (ret_val) { + *ret_val = state->cec_detected; + } else { + pr_err("%s: NULL pointer provided\n", __func__); + ret = -EINVAL; + } + break; + case VIDIOC_HDMI_RX_CEC_S_ENABLE: + ret = adv7481_cec_powerup(state, arg); + break; + default: + pr_err("Not a typewriter! Command: 0x%x", cmd); + ret = -ENOTTY; + break; + } + return ret; +} + static int adv7481_get_sd_timings(struct adv7481_state *state, int *sd_standard) { int ret = 0; @@ -621,17 +926,16 @@ static int adv7481_get_sd_timings(struct adv7481_state *state, int *sd_standard) return -EINVAL; do { - sdp_stat = adv7481_rd_byte(state->i2c_sdp, - SDP_RO_MAIN_STATUS1_ADDR); + sdp_stat = adv7481_rd_byte(&state->i2c_client, + state->i2c_sdp_addr, SDP_RO_MAIN_STATUS1_ADDR); usleep_range(SDP_MIN_SLEEP, SDP_MAX_SLEEP); timeout++; - sdp_stat2 = adv7481_rd_byte(state->i2c_sdp, - SDP_RO_MAIN_STATUS1_ADDR); + sdp_stat2 = adv7481_rd_byte(&state->i2c_client, + state->i2c_sdp_addr, SDP_RO_MAIN_STATUS1_ADDR); } while ((sdp_stat != sdp_stat2) && (timeout < SDP_NUM_TRIES)); if (sdp_stat != sdp_stat2) { - pr_err("%s(%d), adv7481 SDP status unstable: 1\n", - __func__, __LINE__); + pr_err("%s, adv7481 SDP status unstable: 1\n", __func__); return -ETIMEDOUT; } @@ -681,22 +985,35 @@ static int adv7481_set_cvbs_mode(struct adv7481_state *state) pr_debug("Enter %s\n", __func__); state->mode = ADV7481_IP_CVBS_1; /* cvbs video settings ntsc etc */ - ret = adv7481_wr_byte(state->client, 0x00, 0x30); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x0f, 0x00); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x00, 0x00); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x03, 0x42); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x04, 0x07); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x13, 0x00); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x17, 0x41); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x31, 0x12); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x52, 0xcd); - ret |= adv7481_wr_byte(state->i2c_sdp, 0x0e, 0xff); - val = adv7481_rd_byte(state->client, IO_REG_CSI_PIX_EN_SEL_ADDR); + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + 0x00, 0x30); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x0f, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x00, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x03, 0x42); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x04, 0x07); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x13, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x17, 0x41); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x31, 0x12); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x52, 0xcd); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x0e, 0xff); + val = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CSI_PIX_EN_SEL_ADDR); /* Output of SD core routed to MIPI CSI 4-lane Tx */ val |= ADV_REG_SETFIELD(0x10, IO_CTRL_CSI4_IN_SEL); - ret |= adv7481_wr_byte(state->client, IO_REG_CSI_PIX_EN_SEL_ADDR, val); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CSI_PIX_EN_SEL_ADDR, val); /* Enable autodetect */ - ret |= adv7481_wr_byte(state->i2c_sdp, 0x0e, 0x81); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x0e, 0x81); return ret; } @@ -713,69 +1030,101 @@ static int adv7481_set_hdmi_mode(struct adv7481_state *state) * YUV 422 out via TxA CSI: 4-Lane */ /* Disable chip powerdown & Enable HDMI Rx block */ - temp = adv7481_rd_byte(state->client, IO_REG_PWR_DOWN_CTRL_ADDR); + temp = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_PWR_DOWN_CTRL_ADDR); val = ADV_REG_SETFIELD(1, IO_CTRL_RX_EN) | ADV_REG_SETFIELD(0, IO_CTRL_RX_PWDN) | ADV_REG_SETFIELD(0, IO_CTRL_XTAL_PWDN) | ADV_REG_SETFIELD(0, IO_CTRL_CORE_PWDN) | ADV_REG_SETFIELD(0, IO_CTRL_MASTER_PWDN); - ret = adv7481_wr_byte(state->client, IO_REG_PWR_DOWN_CTRL_ADDR, val); + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_PWR_DOWN_CTRL_ADDR, val); /* SDR mode */ - ret |= adv7481_wr_byte(state->client, 0x11, 0x48); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + 0x11, 0x48); /* Set CP core to YUV out */ - ret |= adv7481_wr_byte(state->client, 0x04, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + 0x04, 0x00); /* Set CP core to SDR 422 */ - ret |= adv7481_wr_byte(state->client, 0x12, 0xF2); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + 0x12, 0xF2); /* Saturate both Luma and Chroma values to 254 */ - ret |= adv7481_wr_byte(state->client, 0x17, 0x80); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + 0x17, 0x80); /* Set CP core to enable AV codes */ - ret |= adv7481_wr_byte(state->client, 0x03, 0x86); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + 0x03, 0x86); /* ADI RS CP Core: */ - ret |= adv7481_wr_byte(state->i2c_cp, 0x7C, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_cp_addr, + 0x7C, 0x00); /* Set CP core Phase Adjustment */ - ret |= adv7481_wr_byte(state->client, 0x0C, 0xE0); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + 0x0C, 0xE0); /* LLC/PIX/SPI PINS TRISTATED AUD Outputs Enabled */ - ret |= adv7481_wr_byte(state->client, IO_PAD_CTRLS_ADDR, 0xDD); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_PAD_CTRLS_ADDR, 0xDD); /* Enable Tx A CSI 4-Lane & data from CP core */ val = ADV_REG_SETFIELD(1, IO_CTRL_CSI4_EN) | ADV_REG_SETFIELD(1, IO_CTRL_PIX_OUT_EN) | ADV_REG_SETFIELD(0, IO_CTRL_CSI4_IN_SEL); - ret |= adv7481_wr_byte(state->client, IO_REG_CSI_PIX_EN_SEL_ADDR, - val); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_CSI_PIX_EN_SEL_ADDR, val); /* start to configure HDMI Rx once io-map is configured */ /* Enable HDCP 1.1 */ - ret |= adv7481_wr_byte(state->i2c_rep, 0x40, 0x83); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_rep_addr, + 0x40, 0x83); /* Foreground Channel = A */ - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x00, 0x08); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x00, 0x08); /* ADI Required Write */ - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x98, 0xFF); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x99, 0xA3); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x9A, 0x00); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x9B, 0x0A); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x9D, 0x40); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0xCB, 0x09); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x98, 0xFF); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x99, 0xA3); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x9A, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x9B, 0x0A); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x9D, 0x40); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0xCB, 0x09); /* ADI RS */ - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x3D, 0x10); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x3E, 0x7B); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x3F, 0x5E); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x4E, 0xFE); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x4F, 0x18); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x57, 0xA3); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x58, 0x04); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x85, 0x10); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x3D, 0x10); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x3E, 0x7B); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x3F, 0x5E); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x4E, 0xFE); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x4F, 0x18); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x57, 0xA3); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x58, 0x04); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x85, 0x10); /* Enable All Terminations */ - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x83, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x83, 0x00); /* ADI RS */ - ret |= adv7481_wr_byte(state->i2c_hdmi, 0xA3, 0x01); - ret |= adv7481_wr_byte(state->i2c_hdmi, 0xBE, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0xA3, 0x01); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0xBE, 0x00); /* HPA Manual Enable */ - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x6C, 0x01); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x6C, 0x01); /* HPA Asserted */ - ret |= adv7481_wr_byte(state->i2c_hdmi, 0xF8, 0x01); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0xF8, 0x01); /* Audio Mute Speed Set to Fastest (Smallest Step Size) */ - ret |= adv7481_wr_byte(state->i2c_hdmi, 0x0F, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, + 0x0F, 0x00); return ret; } @@ -860,7 +1209,7 @@ static int adv7481_set_ip_mode(struct adv7481_state *state, int input) } static int adv7481_set_op_src(struct adv7481_state *state, - int output, int input) + int output, int input) { int ret = 0; int temp = 0; @@ -897,10 +1246,11 @@ static int adv7481_set_op_src(struct adv7481_state *state, default: ret = -EINVAL; } - temp = adv7481_rd_byte(state->client, + temp = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_PWR_DOWN_CTRL_ADDR); temp |= val; - adv7481_wr_byte(state->client, IO_REG_PWR_DOWN_CTRL_ADDR, temp); + adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + IO_REG_PWR_DOWN_CTRL_ADDR, temp); state->csia_src = input; break; case ADV7481_OP_CSIB: @@ -915,11 +1265,11 @@ static int adv7481_set_op_src(struct adv7481_state *state, return ret; } -static u32 ba_inp_to_adv7481(u32 input) +static u32 ba_inp_to_adv7481(u32 ba_input) { u32 adv_input = ADV7481_IP_HDMI; - switch (input) { + switch (ba_input) { case BA_IP_CVBS_0: adv_input = ADV7481_IP_CVBS_1; break; @@ -954,6 +1304,42 @@ static u32 ba_inp_to_adv7481(u32 input) return adv_input; } +static u32 adv7481_inp_to_ba(u32 adv_input) +{ + u32 ba_input = BA_IP_HDMI_1; + + switch (adv_input) { + case ADV7481_IP_CVBS_1: + ba_input = BA_IP_CVBS_0; + break; + case ADV7481_IP_CVBS_2: + ba_input = BA_IP_CVBS_1; + break; + case ADV7481_IP_CVBS_3: + ba_input = BA_IP_CVBS_2; + break; + case ADV7481_IP_CVBS_4: + ba_input = BA_IP_CVBS_3; + break; + case ADV7481_IP_CVBS_5: + ba_input = BA_IP_CVBS_4; + break; + case ADV7481_IP_CVBS_6: + ba_input = BA_IP_CVBS_5; + break; + case ADV7481_IP_HDMI: + ba_input = BA_IP_HDMI_1; + break; + case ADV7481_IP_TTL: + ba_input = BA_IP_TTL; + break; + default: + ba_input = BA_IP_HDMI_1; + break; + } + return ba_input; +} + static int adv7481_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { @@ -986,6 +1372,27 @@ unlock_exit: return ret; } +static bool adv7481_is_timing_locked(struct adv7481_state *state) +{ + bool ret = false; + int val1 = 0; + int val2 = 0; + + /* Check Timing Lock IO Map Status3:0x71[0] && 0x71[1] && 0x71[7] */ + val1 = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, + IO_HDMI_LVL_RAW_STATUS_3_ADDR); + val2 = adv7481_rd_byte(&state->i2c_client, state->i2c_cp_addr, + CP_REG_STDI_CH_ADDR); + + if (ADV_REG_GETFIELD(val1, IO_DE_REGEN_LCK_RAW) && + ADV_REG_GETFIELD(val1, IO_V_LOCKED_RAW) && + ADV_REG_GETFIELD(val1, IO_TMDSPLL_LCK_A_RAW) && + ADV_REG_GETFIELD(val2, CP_STDI_DVALID_CH1)) + ret = true; + + return ret; +} + static int adv7481_get_hdmi_timings(struct adv7481_state *state, struct adv7481_vid_params *vid_params, struct adv7481_hdmi_params *hdmi_params) @@ -998,13 +1405,15 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, pr_debug("Enter %s\n", __func__); /* Check TMDS PLL Lock and Frequency */ - temp1 = adv7481_rd_byte(state->i2c_hdmi, HDMI_REG_HDMI_PARAM4_ADDR); + temp1 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, + HDMI_REG_HDMI_PARAM4_ADDR); hdmi_params->pll_lock = ADV_REG_GETFIELD(temp1, HDMI_REG_TMDS_PLL_LOCKED); if (hdmi_params->pll_lock) { - temp1 = adv7481_rd_byte(state->i2c_hdmi, - HDMI_REG_TMDS_FREQ_ADDR); - temp2 = adv7481_rd_byte(state->i2c_hdmi, + temp1 = adv7481_rd_byte(&state->i2c_client, + state->i2c_hdmi_addr, HDMI_REG_TMDS_FREQ_ADDR); + temp2 = adv7481_rd_byte(&state->i2c_client, + state->i2c_hdmi_addr, HDMI_REG_TMDS_FREQ_FRAC_ADDR); hdmi_params->tmds_freq = ADV_REG_GETFIELD(temp1, HDMI_REG_TMDS_FREQ); @@ -1015,34 +1424,29 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, hdmi_params->tmds_freq += ADV_REG_GETFIELD(temp2, HDMI_REG_TMDS_FREQ_FRAC)*ONE_MHZ_TO_HZ/128; } else { - pr_err("%s: PLL not locked return EBUSY\n", __func__); - return -EBUSY; + pr_err("%s(%d): PLL not locked return EBUSY\n", + __func__, __LINE__); + ret = -EBUSY; + goto set_default; } - /* Check Timing Lock IO Map Status3:0x71[0] && 0x71[1] && 0x71[7] */ + /* Check Timing Lock */ do { - temp1 = adv7481_rd_byte(state->client, - IO_HDMI_LVL_RAW_STATUS_3_ADDR); - temp2 = adv7481_rd_byte(state->i2c_cp, - CP_REG_STDI_CH_ADDR); - - if (ADV_REG_GETFIELD(temp1, IO_DE_REGEN_LCK_RAW) && - ADV_REG_GETFIELD(temp1, IO_V_LOCKED_RAW) && - ADV_REG_GETFIELD(temp1, IO_TMDSPLL_LCK_A_RAW) && - ADV_REG_GETFIELD(temp2, CP_STDI_DVALID_CH1)) + if (adv7481_is_timing_locked(state)) break; count++; usleep_range(LOCK_MIN_SLEEP, LOCK_MAX_SLEEP); } while (count < LOCK_NUM_TRIES); if (count >= LOCK_NUM_TRIES) { - pr_err("%s(%d), adv7481 HDMI DE regeneration block NOT Locked: 0x%x", - __func__, __LINE__, temp1); + pr_err("%s(%d), HDMI DE regeneration block NOT Locked\n", + __func__, __LINE__); } /* Check Timing Lock HDMI Map V:0x07[7], H:0x7[5] */ do { - temp1 = adv7481_rd_byte(state->i2c_hdmi, + temp1 = adv7481_rd_byte(&state->i2c_client, + state->i2c_hdmi_addr, HDMI_REG_LINE_WIDTH_1_ADDR); if (ADV_REG_GETFIELD(temp1, HDMI_VERT_FILTER_LOCKED) && @@ -1059,7 +1463,8 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, } /* Check HDMI Parameters */ - temp1 = adv7481_rd_byte(state->i2c_hdmi, HDMI_REG_FIELD1_HEIGHT1_ADDR); + temp1 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, + HDMI_REG_FIELD1_HEIGHT1_ADDR); hdmi_params->color_depth = ADV_REG_GETFIELD(temp1, HDMI_REG_DEEP_COLOR_MODE); @@ -1068,22 +1473,25 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, HDMI_REG_HDMI_INTERLACED); fieldfactor = (vid_params->intrlcd == 1) ? 2 : 1; - temp1 = adv7481_rd_byte(state->i2c_hdmi, HDMI_REG_HDMI_PARAM5_ADDR); + temp1 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, + HDMI_REG_HDMI_PARAM5_ADDR); hdmi_params->pix_rep = ADV_REG_GETFIELD(temp1, HDMI_REG_PIXEL_REPETITION); /* Get Active Timing Data HDMI Map H:0x07[4:0] + 0x08[7:0] */ - temp1 = adv7481_rd_byte(state->i2c_hdmi, HDMI_REG_LINE_WIDTH_1_ADDR); - temp2 = adv7481_rd_byte(state->i2c_hdmi, HDMI_REG_LINE_WIDTH_2_ADDR); + temp1 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, + HDMI_REG_LINE_WIDTH_1_ADDR); + temp2 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, + HDMI_REG_LINE_WIDTH_2_ADDR); vid_params->act_pix = (((ADV_REG_GETFIELD(temp1, HDMI_REG_LINE_WIDTH_1) << 8) & 0x1F00) | ADV_REG_GETFIELD(temp2, HDMI_REG_LINE_WIDTH_2)); /* Get Total Timing Data HDMI Map H:0x1E[5:0] + 0x1F[7:0] */ - temp1 = adv7481_rd_byte(state->i2c_hdmi, + temp1 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_TOTAL_LINE_WIDTH_1_ADDR); - temp2 = adv7481_rd_byte(state->i2c_hdmi, + temp2 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_TOTAL_LINE_WIDTH_2_ADDR); vid_params->tot_pix = (((ADV_REG_GETFIELD(temp1, HDMI_REG_TOTAL_LINE_WIDTH_1) << 8) & 0x3F00) | @@ -1091,9 +1499,9 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, HDMI_REG_TOTAL_LINE_WIDTH_2)); /* Get Active Timing Data HDMI Map V:0x09[4:0] + 0x0A[7:0] */ - temp1 = adv7481_rd_byte(state->i2c_hdmi, + temp1 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_FIELD0_HEIGHT_1_ADDR); - temp2 = adv7481_rd_byte(state->i2c_hdmi, + temp2 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_FIELD0_HEIGHT_2_ADDR); vid_params->act_lines = (((ADV_REG_GETFIELD(temp1, HDMI_REG_FIELD0_HEIGHT_1) << 8) & 0x1F00) | @@ -1101,9 +1509,9 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, HDMI_REG_FIELD0_HEIGHT_2)); /* Get Total Timing Data HDMI Map V:0x26[5:0] + 0x27[7:0] */ - temp1 = adv7481_rd_byte(state->i2c_hdmi, + temp1 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_FIELD0_TOTAL_HEIGHT_1_ADDR); - temp2 = adv7481_rd_byte(state->i2c_hdmi, + temp2 = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_FIELD0_TOTAL_HEIGHT_2_ADDR); vid_params->tot_lines = (((ADV_REG_GETFIELD(temp1, HDMI_REG_FIELD0_TOT_HEIGHT_1) << 8) & 0x3F00) | @@ -1139,6 +1547,18 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, (hdmi_params->pix_rep + 1)); } +set_default: + if (ret) { + pr_debug("%s(%d), error %d resort to default fmt\n", + __func__, __LINE__, ret); + vid_params->act_pix = MAX_DEFAULT_WIDTH; + vid_params->act_lines = MAX_DEFAULT_HEIGHT; + vid_params->fr_rate = MAX_DEFAULT_FRAME_RATE; + vid_params->pix_clk = MAX_DEFAULT_PIX_CLK_HZ; + vid_params->intrlcd = 0; + ret = 0; + } + pr_debug("%s(%d), adv7481 TMDS Resolution: %d x %d @ %d fps\n", __func__, __LINE__, vid_params->act_pix, vid_params->act_lines, @@ -1170,15 +1590,22 @@ static int adv7481_query_dv_timings(struct v4l2_subdev *sd, switch (state->mode) { case ADV7481_IP_HDMI: case ADV7481_IP_CVBS_1_HDMI_SIM: - adv7481_get_hdmi_timings(state, &vid_params, &hdmi_params); - timings->type = V4L2_DV_BT_656_1120; - bt_timings->width = vid_params.act_pix; - bt_timings->height = vid_params.act_lines; - bt_timings->pixelclock = vid_params.pix_clk; - bt_timings->interlaced = vid_params.intrlcd ? + ret = adv7481_get_hdmi_timings(state, &vid_params, + &hdmi_params); + if (!ret) { + timings->type = V4L2_DV_BT_656_1120; + bt_timings->width = vid_params.act_pix; + bt_timings->height = vid_params.act_lines; + bt_timings->pixelclock = vid_params.pix_clk; + bt_timings->interlaced = vid_params.intrlcd ? V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; - if (bt_timings->interlaced == V4L2_DV_INTERLACED) - bt_timings->height /= 2; + if (bt_timings->interlaced == V4L2_DV_INTERLACED) + bt_timings->height /= 2; + } else { + pr_err( + "%s: Error in adv7481_get_hdmi_timings. ret %d\n", + __func__, ret); + } break; default: return -EINVAL; @@ -1195,7 +1622,8 @@ static int adv7481_query_sd_std(struct v4l2_subdev *sd, v4l2_std_id *std) uint8_t tStatus = 0x0; pr_debug("Enter %s\n", __func__); - tStatus = adv7481_rd_byte(state->i2c_sdp, SDP_RO_MAIN_STATUS1_ADDR); + tStatus = adv7481_rd_byte(&state->i2c_client, state->i2c_sdp_addr, + SDP_RO_MAIN_STATUS1_ADDR); if (!ADV_REG_GETFIELD(tStatus, SDP_RO_MAIN_IN_LOCK)) pr_err("%s(%d), adv7481 SD Input NOT Locked: 0x%x\n", __func__, __LINE__, tStatus); @@ -1267,11 +1695,17 @@ static int adv7481_g_mbus_fmt(struct v4l2_subdev *sd, switch (state->mode) { case ADV7481_IP_HDMI: case ADV7481_IP_CVBS_1_HDMI_SIM: - adv7481_get_hdmi_timings(state, &vid_params, &hdmi_params); - fmt->width = vid_params.act_pix; - fmt->height = vid_params.act_lines; - if (vid_params.intrlcd) - fmt->height /= 2; + ret = adv7481_get_hdmi_timings(state, &vid_params, + &hdmi_params); + if (!ret) { + fmt->width = vid_params.act_pix; + fmt->height = vid_params.act_lines; + if (vid_params.intrlcd) + fmt->height /= 2; + } else { + pr_err("%s: Error %d in adv7481_get_hdmi_timings\n", + __func__, ret); + } break; default: return -EINVAL; @@ -1290,17 +1724,17 @@ static int adv7481_set_audio_spdif(struct adv7481_state *state, if (on) { /* Configure I2S_SDATA output pin as an SPDIF output 0x6E[3] */ - val = adv7481_rd_byte(state->i2c_hdmi, + val = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_MUX_SPDIF_TO_I2S_ADDR); val |= ADV_REG_SETFIELD(1, HDMI_MUX_SPDIF_TO_I2S_EN); - ret = adv7481_wr_byte(state->i2c_hdmi, + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_MUX_SPDIF_TO_I2S_ADDR, val); } else { /* Configure I2S_SDATA output pin as an I2S output 0x6E[3] */ - val = adv7481_rd_byte(state->i2c_hdmi, + val = adv7481_rd_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_MUX_SPDIF_TO_I2S_ADDR); val &= ~ADV_REG_SETFIELD(1, HDMI_MUX_SPDIF_TO_I2S_EN); - ret = adv7481_wr_byte(state->i2c_hdmi, + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_hdmi_addr, HDMI_REG_MUX_SPDIF_TO_I2S_ADDR, val); } return ret; @@ -1310,40 +1744,42 @@ static int adv7481_csi_powerdown(struct adv7481_state *state, enum adv7481_output output) { int ret; - struct i2c_client *csi_map; + uint8_t csi_map; uint8_t val = 0; pr_debug("Enter %s for output: %d\n", __func__, output); /* Select CSI TX to configure data */ if (output == ADV7481_OP_CSIA) { - csi_map = state->i2c_csi_txa; + csi_map = state->i2c_csi_txa_addr; } else if (output == ADV7481_OP_CSIB) { - csi_map = state->i2c_csi_txb; + csi_map = state->i2c_csi_txb_addr; } else if (output == ADV7481_OP_TTL) { /* For now use TxA */ - csi_map = state->i2c_csi_txa; + csi_map = state->i2c_csi_txa_addr; } else { /* Default to TxA */ - csi_map = state->i2c_csi_txa; + csi_map = state->i2c_csi_txa_addr; } /* CSI Tx: power down DPHY */ - ret = adv7481_wr_byte(csi_map, CSI_REG_TX_DPHY_PWDN_ADDR, + ret = adv7481_wr_byte(&state->i2c_client, csi_map, + CSI_REG_TX_DPHY_PWDN_ADDR, ADV_REG_SETFIELD(1, CSI_CTRL_DPHY_PWDN)); /* ADI Required Write */ - ret |= adv7481_wr_byte(csi_map, 0x31, 0x82); - ret |= adv7481_wr_byte(csi_map, 0x1e, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0x31, 0x82); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0x1e, 0x00); /* CSI TxA: # Lane : Power Off */ val = ADV_REG_SETFIELD(1, CSI_CTRL_TX_PWRDN) | ADV_REG_SETFIELD(state->tx_lanes, CSI_CTRL_NUM_LANES); - ret |= adv7481_wr_byte(csi_map, CSI_REG_TX_CFG1_ADDR, val); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, + CSI_REG_TX_CFG1_ADDR, val); /* * ADI Recommended power down sequence * DPHY and CSI Tx A Power down Sequence * CSI TxA: MIPI PLL DIS */ - ret |= adv7481_wr_byte(csi_map, 0xda, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0xda, 0x00); /* ADI Required Write */ - ret |= adv7481_wr_byte(csi_map, 0xc1, 0x3b); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0xc1, 0x3b); pr_debug("Exit %s, ret: %d\n", __func__, ret); @@ -1354,7 +1790,7 @@ static int adv7481_csi_powerup(struct adv7481_state *state, enum adv7481_output output) { int ret; - struct i2c_client *csi_map; + uint8_t csi_map; uint8_t val = 0; uint8_t csi_sel = 0; @@ -1364,7 +1800,7 @@ static int adv7481_csi_powerup(struct adv7481_state *state, csi_sel = ADV_REG_SETFIELD(1, IO_CTRL_CSI4_EN) | ADV_REG_SETFIELD(1, IO_CTRL_PIX_OUT_EN) | ADV_REG_SETFIELD(0, IO_CTRL_CSI4_IN_SEL); - csi_map = state->i2c_csi_txa; + csi_map = state->i2c_csi_txa_addr; } else if (output == ADV7481_OP_CSIB) { /* Enable 1-Lane MIPI Tx, enable pixel output and * route SD through Pixel port @@ -1373,54 +1809,57 @@ static int adv7481_csi_powerup(struct adv7481_state *state, ADV_REG_SETFIELD(1, IO_CTRL_PIX_OUT_EN) | ADV_REG_SETFIELD(1, IO_CTRL_SD_THRU_PIX_OUT) | ADV_REG_SETFIELD(0, IO_CTRL_CSI4_IN_SEL); - csi_map = state->i2c_csi_txb; + csi_map = state->i2c_csi_txb_addr; } else if (output == ADV7481_OP_TTL) { /* For now use TxA */ - csi_map = state->i2c_csi_txa; + csi_map = state->i2c_csi_txa_addr; } else { /* Default to TxA */ - csi_map = state->i2c_csi_txa; + csi_map = state->i2c_csi_txa_addr; } /* Enable Tx A/B CSI #-lane */ - ret = adv7481_wr_byte(state->client, + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_CSI_PIX_EN_SEL_ADDR, csi_sel); /* TXA MIPI lane settings for CSI */ /* CSI TxA: # Lane : Power Off */ val = ADV_REG_SETFIELD(1, CSI_CTRL_TX_PWRDN) | ADV_REG_SETFIELD(state->tx_lanes, CSI_CTRL_NUM_LANES); - ret |= adv7481_wr_byte(csi_map, CSI_REG_TX_CFG1_ADDR, val); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, + CSI_REG_TX_CFG1_ADDR, val); /* CSI TxA: Auto D-PHY Timing */ val |= ADV_REG_SETFIELD(1, CSI_CTRL_AUTO_PARAMS); - ret |= adv7481_wr_byte(csi_map, CSI_REG_TX_CFG1_ADDR, val); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, + CSI_REG_TX_CFG1_ADDR, val); /* DPHY and CSI Tx A */ - ret |= adv7481_wr_byte(csi_map, 0xdb, 0x10); - ret |= adv7481_wr_byte(csi_map, 0xd6, 0x07); - ret |= adv7481_wr_byte(csi_map, 0xc4, 0x0a); - ret |= adv7481_wr_byte(csi_map, 0x71, 0x33); - ret |= adv7481_wr_byte(csi_map, 0x72, 0x11); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0xdb, 0x10); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0xd6, 0x07); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0xc4, 0x0a); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0x71, 0x33); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0x72, 0x11); /* CSI TxA: power up DPHY */ - ret |= adv7481_wr_byte(csi_map, 0xf0, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0xf0, 0x00); /* ADI Required Write */ - ret |= adv7481_wr_byte(csi_map, 0x31, 0x82); - ret |= adv7481_wr_byte(csi_map, 0x1e, 0x40); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0x31, 0x82); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0x1e, 0x40); /* adi Recommended power up sequence */ /* DPHY and CSI Tx A Power up Sequence */ /* CSI TxA: MIPI PLL EN */ - ret |= adv7481_wr_byte(csi_map, 0xda, 0x01); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0xda, 0x01); msleep(200); /* CSI TxA: # MIPI Lane : Power ON */ val = ADV_REG_SETFIELD(0, CSI_CTRL_TX_PWRDN) | ADV_REG_SETFIELD(1, CSI_CTRL_AUTO_PARAMS) | ADV_REG_SETFIELD(state->tx_lanes, CSI_CTRL_NUM_LANES); - ret |= adv7481_wr_byte(csi_map, CSI_REG_TX_CFG1_ADDR, val); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, + CSI_REG_TX_CFG1_ADDR, val); msleep(100); /* ADI Required Write */ - ret |= adv7481_wr_byte(csi_map, 0xc1, 0x2b); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0xc1, 0x2b); msleep(100); /* ADI Required Write */ - ret |= adv7481_wr_byte(csi_map, 0x31, 0x80); + ret |= adv7481_wr_byte(&state->i2c_client, csi_map, 0x31, 0x80); pr_debug("Exit %s, ret: %d\n", __func__, ret); @@ -1476,42 +1915,30 @@ static int adv7481_g_input_status(struct v4l2_subdev *sd, u32 *status) { int ret = 0; struct adv7481_state *state = to_state(sd); - uint8_t val1 = 0; - uint8_t val2 = 0; + uint8_t val = 0; uint32_t count = 0; pr_debug("Enter %s\n", __func__); if (ADV7481_IP_HDMI == state->mode) { - /* - * Check Timing Lock IO Map Status3:0x71[0] && - * 0x71[1] && 0x71[7] - */ + /* Check Timing Lock */ do { - val1 = adv7481_rd_byte(state->client, - IO_HDMI_LVL_RAW_STATUS_3_ADDR); - val2 = adv7481_rd_byte(state->i2c_cp, - CP_REG_STDI_CH_ADDR); - - if (ADV_REG_GETFIELD(val1, IO_DE_REGEN_LCK_RAW) && - ADV_REG_GETFIELD(val1, IO_V_LOCKED_RAW) && - ADV_REG_GETFIELD(val1, IO_TMDSPLL_LCK_A_RAW) && - ADV_REG_GETFIELD(val2, CP_STDI_DVALID_CH1)) + if (adv7481_is_timing_locked(state)) break; count++; usleep_range(LOCK_MIN_SLEEP, LOCK_MAX_SLEEP); } while (count < LOCK_NUM_TRIES); if (count >= LOCK_NUM_TRIES) { - pr_err("%s(%d), HDMI DE regeneration block NOT Locked: 0x%x, 0x%x", - __func__, __LINE__, val1, val2); + pr_err("%s(%d), HDMI DE regeneration block NOT Locked\n", + __func__, __LINE__); *status |= V4L2_IN_ST_NO_SIGNAL; } } else { - val1 = adv7481_rd_byte(state->i2c_sdp, + val = adv7481_rd_byte(&state->i2c_client, state->i2c_sdp_addr, SDP_RO_MAIN_STATUS1_ADDR); - if (!ADV_REG_GETFIELD(val1, SDP_RO_MAIN_IN_LOCK)) { + if (!ADV_REG_GETFIELD(val, SDP_RO_MAIN_IN_LOCK)) { pr_err("%s(%d), SD Input NOT Locked: 0x%x\n", - __func__, __LINE__, val1); + __func__, __LINE__, val); *status |= V4L2_IN_ST_NO_SIGNAL; } } @@ -1539,6 +1966,7 @@ static const struct v4l2_subdev_video_ops adv7481_video_ops = { static const struct v4l2_subdev_core_ops adv7481_core_ops = { .s_power = adv7481_s_power, + .ioctl = adv7481_ioctl, }; static const struct v4l2_ctrl_ops adv7481_ctrl_ops = { @@ -1552,6 +1980,8 @@ static const struct v4l2_subdev_ops adv7481_ops = { static int adv7481_init_v4l2_controls(struct adv7481_state *state) { + int ret = 0; + v4l2_ctrl_handler_init(&state->ctrl_hdl, 4); v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7481_ctrl_ops, @@ -1565,59 +1995,218 @@ static int adv7481_init_v4l2_controls(struct adv7481_state *state) state->sd.ctrl_handler = &state->ctrl_hdl; if (state->ctrl_hdl.error) { - int err = state->ctrl_hdl.error; + ret = state->ctrl_hdl.error; v4l2_ctrl_handler_free(&state->ctrl_hdl); - return err; + } else { + v4l2_ctrl_handler_setup(&state->ctrl_hdl); } - v4l2_ctrl_handler_setup(&state->ctrl_hdl); - return 0; + pr_err("%s: Exit with ret: %d\n", __func__, ret); + return ret; +} + +static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = { + .i2c_read = msm_camera_cci_i2c_read, + .i2c_read_seq = msm_camera_cci_i2c_read_seq, + .i2c_write = msm_camera_cci_i2c_write, + .i2c_write_table = msm_camera_cci_i2c_write_table, + .i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table, + .i2c_write_table_w_microdelay = + msm_camera_cci_i2c_write_table_w_microdelay, + .i2c_util = msm_sensor_cci_i2c_util, + .i2c_poll = msm_camera_cci_i2c_poll, +}; + +static int adv7481_cci_init(struct adv7481_state *state) +{ + struct msm_camera_cci_client *cci_client = NULL; + int ret = 0; + + pr_err("%s: Enter\n", __func__); + + state->i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl; + state->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; + state->i2c_client.cci_client = kzalloc(sizeof( + struct msm_camera_cci_client), GFP_KERNEL); + cci_client = state->i2c_client.cci_client; + if (!cci_client) { + ret = -ENOMEM; + goto err_cci_init; + } + cci_client->cci_subdev = msm_cci_get_subdev(); + pr_debug("%s cci_subdev: %p\n", __func__, cci_client->cci_subdev); + cci_client->cci_i2c_master = state->cci_master; + cci_client->sid = state->i2c_slave_addr; + cci_client->retries = 3; + cci_client->id_map = 0; + cci_client->i2c_freq_mode = I2C_FAST_MODE; + ret = state->i2c_client.i2c_func_tbl->i2c_util( + &state->i2c_client, MSM_CCI_INIT); + if (ret < 0) + pr_err("%s - cci_init failed\n", __func__); + + pr_debug("%s i2c_client.client: %p\n", __func__, + state->i2c_client.client); + +err_cci_init: + return ret; +} + +static int adv7481_parse_dt(struct adv7481_state *state) +{ + struct device_node *np = state->dev->of_node; + unsigned int i; + int gpio_count = 0; + int flag_count = 0; + int label_count = 0; + int ret = 0; + + /* config CCI */ + ret = of_property_read_u32(np, "qcom,cci-master", + &state->cci_master); + if (ret < 0 || state->cci_master >= MASTER_MAX) { + pr_err("%s: failed ret %d\n", __func__, ret); + goto exit; + } + pr_debug("%s: cci_master: 0x%x\n", __func__, state->cci_master); + ret = of_property_read_u32(np, "qcom,slave-addr", + &state->i2c_slave_addr); + if (ret < 0) { + pr_err("%s: failed ret %d\n", __func__, ret); + goto exit; + } + pr_debug("%s: i2c_slave_addr: 0x%x\n", __func__, state->i2c_slave_addr); + state->i2c_io_addr = (uint8_t)state->i2c_slave_addr; + + ret = of_property_read_u32(np, "qcom,csi-slave-addr", + &state->i2c_csi_slave_addr); + if (ret < 0) { + pr_err("%s: failed ret %d\n", __func__, ret); + goto exit; + } + pr_debug("%s: i2c_csi_slave_addr: 0x%x\n", __func__, + state->i2c_csi_slave_addr); + ret = of_property_read_u32(np, "qcom,vpp-slave-addr", + &state->i2c_vpp_slave_addr); + if (ret < 0) { + pr_err("%s: failed ret %d\n", __func__, ret); + goto exit; + } + pr_debug("%s: i2c_vpp_slave_addr: 0x%x\n", __func__, + state->i2c_vpp_slave_addr); + + ret = adv7481_cci_init(state); + if (ret < 0) { + pr_err("%s: failed adv7481_cci_init ret %d\n", __func__, ret); + goto exit; + } + /* Configure GPIOs */ + gpio_count = of_gpio_count(np); + pr_debug("%s: of_gpio_count: 0x%x\n", __func__, gpio_count); + flag_count = of_property_count_u32_elems(np, "qcom,gpio-tbl-flags"); + pr_debug("%s: gpio-tbl-flags: 0x%x\n", __func__, flag_count); + label_count = of_property_count_strings(np, "qcom,gpio-tbl-label"); + pr_debug("%s: gpio-tbl-label: 0x%x\n", __func__, label_count); + if (gpio_count != ADV7481_GPIO_MAX || + flag_count != ADV7481_GPIO_MAX || + label_count != ADV7481_GPIO_MAX) { + ret = -EFAULT; + pr_err("%s: failed to configure GPIO ret -EFAULT\n", __func__); + goto exit; + } + for (i = 0; i < ADV7481_GPIO_MAX; i++) { + u32 tmp; + + state->gpio_array[i].gpio = of_get_gpio(np, i); + of_property_read_u32_index(np, "qcom,gpio-tbl-flags", i, &tmp); + state->gpio_array[i].flags = tmp; + of_property_read_string_index(np, "qcom,gpio-tbl-label", i, + &state->gpio_array[i].label); + pr_debug("%s: gpio_array[%d] = %d\n", __func__, i, + state->gpio_array[i].gpio); + } + pr_debug("%s: End read back gpio from dt...", __func__); + +exit: + return ret; } -static int adv7481_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static const struct of_device_id adv7481_id[] = { + { .compatible = "qcom,adv7481", }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, adv7481_id); + +static int adv7481_probe(struct platform_device *pdev) { struct adv7481_state *state; + const struct of_device_id *device_id; struct adv7481_platform_data *pdata = NULL; struct v4l2_subdev *sd; - struct v4l2_ctrl_handler *hdl; int ret; - pr_debug("Attempting to probe...\n"); - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - pr_err("%s %s Check i2c Functionality Fail\n", - __func__, client->name); - ret = -EIO; + device_id = of_match_device(adv7481_id, &pdev->dev); + if (!device_id) { + pr_err("%s: device_id is NULL\n", __func__); + ret = -ENODEV; goto err; } - v4l_info(client, "chip found @ 0x%02x (%s)\n", - client->addr, client->adapter->name); /* Create 7481 State */ - state = devm_kzalloc(&client->dev, - sizeof(struct adv7481_state), GFP_KERNEL); + state = devm_kzalloc(&pdev->dev, + sizeof(struct adv7481_state), GFP_KERNEL); if (state == NULL) { ret = -ENOMEM; - pr_err("Check Kzalloc Fail\n"); - goto err_mem; + goto err; } - state->client = client; + state->dev = &pdev->dev; + mutex_init(&state->mutex); + /* config VREG */ + ret = msm_camera_get_dt_vreg_data(pdev->dev.of_node, + &(state->cci_vreg), &(state->regulator_count)); + if (ret < 0) { + pr_err("%s:cci get_dt_vreg failed\n", __func__); + goto err_mem_free; + } + + ret = msm_camera_config_vreg(&pdev->dev, state->cci_vreg, + state->regulator_count, NULL, 0, + &state->cci_reg_ptr[0], 1); + if (ret < 0) { + pr_err("%s:cci config_vreg failed\n", __func__); + goto err_mem_free; + } + + ret = msm_camera_enable_vreg(&pdev->dev, state->cci_vreg, + state->regulator_count, NULL, 0, + &state->cci_reg_ptr[0], 1); + if (ret < 0) { + pr_err("%s:cci enable_vreg failed\n", __func__); + goto err_mem_free; + } + pr_debug("%s - VREG Initialized...\n", __func__); + + ret = adv7481_parse_dt(state); + pr_debug("%s - Done parsing dt...\n", __func__); + /* Get and Check Platform Data */ - pdata = (struct adv7481_platform_data *) client->dev.platform_data; + pdata = (struct adv7481_platform_data *) pdev->dev.platform_data; if (!pdata) { ret = -ENOMEM; - pr_err("Getting Platform data failed\n"); - goto err_mem; + pr_err("%s(%d): Getting Platform data failed\n", + __func__, __LINE__); + goto err_mem_free; } - /* Configure and Register V4L2 I2C Sub-device */ + /* Configure and Register V4L2 Sub-device */ sd = &state->sd; - v4l2_i2c_subdev_init(sd, client, &adv7481_ops); + v4l2_subdev_init(sd, &adv7481_ops); + sd->owner = pdev->dev.driver->owner; + v4l2_set_subdevdata(sd, state); + strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; state->sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS; @@ -1627,32 +2216,35 @@ static int adv7481_probe(struct i2c_client *client, ret = media_entity_init(&state->sd.entity, 1, &state->pad, 0); if (ret) { ret = -EIO; - pr_err("Media entity init failed\n"); + pr_err("%s(%d): Media entity init failed\n", + __func__, __LINE__); goto err_media_entity; } /* Initialize HW Config */ - ret = adv7481_hw_init(pdata, state); + ret = adv7481_hw_init(state); if (ret) { ret = -EIO; - pr_err("HW Initialisation Failed\n"); + pr_err("%s: HW Initialisation Failed\n", __func__); goto err_media_entity; } /* Register V4l2 Control Functions */ - hdl = &state->ctrl_hdl; - v4l2_ctrl_handler_init(hdl, 4); - adv7481_init_v4l2_controls(state); + ret = adv7481_init_v4l2_controls(state); + if (ret) { + pr_err("%s: V4L2 Controls Initialisation Failed %d\n", + __func__, ret); + } - /* Initials ADV7481 State Settings */ + /* Initial ADV7481 State Settings */ state->tx_auto_params = ADV7481_AUTO_PARAMS; - state->tx_lanes = ADV7481_MIPI_2LANE; /* Initialize SW Init Settings and I2C sub maps 7481 */ - ret = adv7481_dev_init(state, client); + ret = adv7481_dev_init(state); if (ret) { ret = -EIO; - pr_err("SW Initialisation Failed\n"); + pr_err("%s(%d): SW Initialisation Failed\n", + __func__, __LINE__); goto err_media_entity; } @@ -1672,7 +2264,7 @@ static int adv7481_probe(struct i2c_client *client, err_media_entity: media_entity_cleanup(&sd->entity); -err_mem: +err_mem_free: kfree(state); err: if (!ret) @@ -1680,50 +2272,39 @@ err: return ret; } -static int adv7481_remove(struct i2c_client *client) +static int adv7481_remove(struct platform_device *pdev) { - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct adv7481_state *state = to_state(sd); + struct adv7481_state *state; - msm_ba_unregister_subdev_node(sd); - v4l2_device_unregister_subdev(sd); - media_entity_cleanup(&sd->entity); + state = pdev->dev.platform_data; + msm_ba_unregister_subdev_node(&state->sd); + v4l2_device_unregister_subdev(&state->sd); + media_entity_cleanup(&state->sd.entity); v4l2_ctrl_handler_free(&state->ctrl_hdl); + adv7481_reset_irq(state); if (state->irq > 0) free_irq(state->irq, state); - i2c_unregister_device(state->i2c_csi_txa); - i2c_unregister_device(state->i2c_csi_txb); - i2c_unregister_device(state->i2c_hdmi); - i2c_unregister_device(state->i2c_edid); - i2c_unregister_device(state->i2c_cp); - i2c_unregister_device(state->i2c_sdp); - i2c_unregister_device(state->i2c_rep); + cancel_delayed_work(&state->irq_delayed_work); mutex_destroy(&state->mutex); kfree(state); return 0; } -static const struct i2c_device_id adv7481_id[] = { - { DRIVER_NAME, 0 }, - {}, -}; -MODULE_DEVICE_TABLE(i2c, adv7481_id); - - -static struct i2c_driver adv7481_driver = { +static struct platform_driver adv7481_driver = { .driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, + .of_match_table = adv7481_id, }, .probe = adv7481_probe, .remove = adv7481_remove, - .id_table = adv7481_id, }; -module_i2c_driver(adv7481_driver); +module_driver(adv7481_driver, platform_driver_register, + platform_driver_unregister); MODULE_DESCRIPTION("ADI ADV7481 HDMI/MHL/SD video receiver"); diff --git a/drivers/media/i2c/adv7481_reg.h b/drivers/media/i2c/adv7481_reg.h index a4e14fa18e0a..a2dffa978b6d 100644 --- a/drivers/media/i2c/adv7481_reg.h +++ b/drivers/media/i2c/adv7481_reg.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,155 +19,233 @@ #define ADV_REG_GETFIELD(val, field) \ (((val) & (field##_BMSK)) >> (field##_SHFT)) +#define ADV_REG_RSTFIELD(val, field) \ + ((val) & ~((field##_BMSK) << (field##_SHFT))) + /* IO Map Registers */ -#define IO_REG_MAIN_RST_ADDR 0xFF -#define IO_REG_MAIN_RST_VALUE 0xFF - -#define IO_REG_PWR_DOWN_CTRL_ADDR 0x00 -#define IO_CTRL_RX_EN_BMSK 0x0040 -#define IO_CTRL_RX_EN_SHFT 6 -#define IO_CTRL_RX_PWDN_BMSK 0x0020 -#define IO_CTRL_RX_PWDN_SHFT 5 -#define IO_CTRL_XTAL_PWDN_BMSK 0x0004 -#define IO_CTRL_XTAL_PWDN_SHFT 2 -#define IO_CTRL_CORE_PWDN_BMSK 0x0002 -#define IO_CTRL_CORE_PWDN_SHFT 1 -#define IO_CTRL_MASTER_PWDN_BMSK 0x0001 -#define IO_CTRL_MASTER_PWDN_SHFT 0 - -#define IO_REG_PWR_DN2_XTAL_HIGH_ADDR 0x01 -#define IO_CTRL_CEC_WAKE_UP_PWRDN2B_BMSK 0x0080 -#define IO_CTRL_CEC_WAKE_UP_PWRDN2B_SHFT 7 +#define IO_REG_MAIN_RST_ADDR 0xFF +#define IO_REG_MAIN_RST_VALUE 0xFF + +#define IO_REG_PWR_DOWN_CTRL_ADDR 0x00 +#define IO_CTRL_RX_EN_BMSK 0x0040 +#define IO_CTRL_RX_EN_SHFT 6 +#define IO_CTRL_RX_PWDN_BMSK 0x0020 +#define IO_CTRL_RX_PWDN_SHFT 5 +#define IO_CTRL_XTAL_PWDN_BMSK 0x0004 +#define IO_CTRL_XTAL_PWDN_SHFT 2 +#define IO_CTRL_CORE_PWDN_BMSK 0x0002 +#define IO_CTRL_CORE_PWDN_SHFT 1 +#define IO_CTRL_MASTER_PWDN_BMSK 0x0001 +#define IO_CTRL_MASTER_PWDN_SHFT 0 + +#define IO_REG_PWR_DN2_XTAL_HIGH_ADDR 0x01 +#define IO_CTRL_CEC_WAKE_UP_PWRDN2B_BMSK 0x0080 +#define IO_CTRL_CEC_WAKE_UP_PWRDN2B_SHFT 7 #define IO_CTRL_CEC_WAKE_UP_PWRDNB_BMSK 0x0040 #define IO_CTRL_CEC_WAKE_UP_PWRDNB_SHFT 6 -#define IO_PROG_XTAL_FREQ_HIGH_BMSK 0x003F -#define IO_PROG_XTAL_FREQ_HIGH_SHFT 0 +#define IO_PROG_XTAL_FREQ_HIGH_BMSK 0x003F +#define IO_PROG_XTAL_FREQ_HIGH_SHFT 0 -#define IO_REG_XTAL_FREQ_LOW_ADDR 0x02 -#define IO_PROG_XTAL_FREQ_LOW_BMSK 0x00FF -#define IO_PROG_XTAL_FREQ_LOW_SHFT 0 +#define IO_REG_XTAL_FREQ_LOW_ADDR 0x02 +#define IO_PROG_XTAL_FREQ_LOW_BMSK 0x00FF +#define IO_PROG_XTAL_FREQ_LOW_SHFT 0 -#define IO_REG_CP_VID_STD_ADDR 0x05 +#define IO_REG_CP_VID_STD_ADDR 0x05 -#define IO_REG_CSI_PIX_EN_SEL_ADDR 0x10 -#define IO_CTRL_CSI4_EN_BMSK 0x0080 -#define IO_CTRL_CSI4_EN_SHFT 7 -#define IO_CTRL_CSI1_EN_BMSK 0x0040 -#define IO_CTRL_CSI1_EN_SHFT 6 +#define IO_REG_CSI_PIX_EN_SEL_ADDR 0x10 +#define IO_CTRL_CSI4_EN_BMSK 0x0080 +#define IO_CTRL_CSI4_EN_SHFT 7 +#define IO_CTRL_CSI1_EN_BMSK 0x0040 +#define IO_CTRL_CSI1_EN_SHFT 6 #define IO_CTRL_PIX_OUT_EN_BMSK 0x0020 #define IO_CTRL_PIX_OUT_EN_SHFT 5 -#define IO_CTRL_SD_THRU_PIX_OUT_BMSK 0x0010 -#define IO_CTRL_SD_THRU_PIX_OUT_SHFT 4 -#define IO_CTRL_CSI4_IN_SEL_BMSK 0x000C -#define IO_CTRL_CSI4_IN_SEL_SHFT 2 +#define IO_CTRL_SD_THRU_PIX_OUT_BMSK 0x0010 +#define IO_CTRL_SD_THRU_PIX_OUT_SHFT 4 +#define IO_CTRL_CSI4_IN_SEL_BMSK 0x000C +#define IO_CTRL_CSI4_IN_SEL_SHFT 2 -#define IO_PAD_CTRLS_ADDR 0x0E +#define IO_PAD_CTRLS_ADDR 0x0E +#define IO_PAD_FILTER_CTRLS_ADDR 0x0F -#define IO_REG_I2C_CFG_ADDR 0xF2 +#define IO_REG_I2C_CFG_ADDR 0xF2 #define IO_REG_I2C_AUTOINC_EN_REG_VALUE 0x01 -#define IO_CTRL_MASTER_PWDN_REG_VALUE 0x01 - -#define IO_HDMI_LVL_RAW_STATUS_3_ADDR 0x71 -#define IO_TMDSPLL_LCK_A_RAW_BMSK 0x0080 -#define IO_TMDSPLL_LCK_A_RAW_SHFT 7 -#define IO_CABLE_DET_A_RAW_BMSK 0x0040 -#define IO_CABLE_DET_A_RAW_SHFT 6 -#define IO_V_LOCKED_RAW_BMSK 0x0002 -#define IO_V_LOCKED_RAW_SHFT 1 -#define IO_DE_REGEN_LCK_RAW_BMSK 0x0001 -#define IO_DE_REGEN_LCK_RAW_SHFT 0 +#define IO_CTRL_MASTER_PWDN_REG_VALUE 0x01 /* Interrupts */ -#define IO_HDMI_LVL_INT_STATUS_3_ADDR 0x72 -#define IO_CABLE_DET_A_ST_BMSK 0x0040 -#define IO_CABLE_DET_A_ST_SHFT 6 +#define IO_HDMI_LVL_INT_CLEAR_1_ADDR 0x69 -#define IO_HDMI_LVL_INT_CLEAR_3_ADDR 0x73 +#define IO_HDMI_LVL_INT_MASKB_1_ADDR 0x6B +#define IO_AVI_INFO_MB1_BMSK 0x0001 +#define IO_AVI_INFO_MB1_SHFT 0 + +#define IO_HDMI_LVL_INT_CLEAR_2_ADDR 0x6E + +#define IO_HDMI_LVL_RAW_STATUS_3_ADDR 0x71 +#define IO_TMDSPLL_LCK_A_RAW_BMSK 0x0080 +#define IO_TMDSPLL_LCK_A_RAW_SHFT 7 +#define IO_CABLE_DET_A_RAW_BMSK 0x0040 +#define IO_CABLE_DET_A_RAW_SHFT 6 +#define IO_V_LOCKED_RAW_BMSK 0x0002 +#define IO_V_LOCKED_RAW_SHFT 1 +#define IO_DE_REGEN_LCK_RAW_BMSK 0x0001 +#define IO_DE_REGEN_LCK_RAW_SHFT 0 + +#define IO_HDMI_LVL_INT_STATUS_3_ADDR 0x72 +#define IO_CABLE_DET_A_ST_BMSK 0x0040 +#define IO_CABLE_DET_A_ST_SHFT 6 +#define IO_V_LOCKED_ST_BMSK 0x0002 +#define IO_V_LOCKED_ST_SHFT 1 +#define IO_DE_REGEN_LCK_ST_BMSK 0x0001 +#define IO_DE_REGEN_LCK_ST_SHFT 0 + +#define IO_HDMI_LVL_INT_CLEAR_3_ADDR 0x73 #define IO_CABLE_DET_A_CLR_BMSK 0x0040 #define IO_CABLE_DET_A_CLR_SHFT 6 -#define IO_HDMI_LVL_INT2_MASKB_3_ADDR 0x74 +#define IO_HDMI_LVL_INT2_MASKB_3_ADDR 0x74 #define IO_CABLE_DET_A_MB2_BMSK 0x0040 #define IO_CABLE_DET_A_MB2_SHFT 6 -#define IO_HDMI_LVL_INT_MASKB_3_ADDR 0x75 +#define IO_HDMI_LVL_INT_MASKB_3_ADDR 0x75 #define IO_CABLE_DET_A_MB1_BMSK 0x0040 #define IO_CABLE_DET_A_MB1_SHFT 6 - -#define IO_REG_PAD_CTRL_1_ADDR 0x1D -#define IO_PDN_INT1_BMSK 0x0080 -#define IO_PDN_INT1_SHFT 7 -#define IO_PDN_INT2_BMSK 0x0040 -#define IO_PDN_INT2_SHFT 6 -#define IO_PDN_INT3_BMSK 0x0020 -#define IO_PDN_INT3_SHFT 5 +#define IO_V_LOCKED_MB1_BMSK 0x0002 +#define IO_V_LOCKED_MB1_SHFT 1 +#define IO_DE_REGEN_LCK_MB1_BMSK 0x0001 +#define IO_DE_REGEN_LCK_MB1_SHFT 0 + +#define IO_HDMI_EDG_RAW_STATUS_1_ADDR 0x80 +#define IO_NEW_AVI_INFO_RAW_BMSK 0x0001 +#define IO_NEW_AVI_INFO_RAW_SHFT 0 + +#define IO_HDMI_EDG_INT_STATUS_1_ADDR 0x81 +#define IO_NEW_AVI_INFO_ST_BMSK 0x0001 +#define IO_NEW_AVI_INFO_ST_SHFT 0 + +#define IO_HDMI_EDG_INT_CLEAR_1_ADDR 0x82 +#define IO_NEW_AVI_INFO_CLR_BMSK 0x0001 +#define IO_NEW_AVI_INFO_CLR_SHFT 0 + +#define IO_HDMI_EDG_INT2_MASKB_1_ADDR 0x83 +#define IO_NEW_AVI_INFO_MB2_BMSK 0x0001 +#define IO_NEW_AVI_INFO_MB2_SHFT 0 + +#define IO_HDMI_EDG_INT_MASKB_1_ADDR 0x84 +#define IO_NEW_AVI_INFO_MB1_BMSK 0x0001 +#define IO_NEW_AVI_INFO_MB1_SHFT 0 + +#define IO_HDMI_EDG_INT_CLEAR_2_ADDR 0x87 +#define IO_HDMI_EDG_INT_CLEAR_3_ADDR 0x8C + +#define IO_REG_PAD_CTRL_1_ADDR 0x1D +#define IO_PDN_INT1_BMSK 0x0080 +#define IO_PDN_INT1_SHFT 7 +#define IO_PDN_INT2_BMSK 0x0040 +#define IO_PDN_INT2_SHFT 6 +#define IO_PDN_INT3_BMSK 0x0020 +#define IO_PDN_INT3_SHFT 5 #define IO_INV_LLC_BMSK 0x0010 #define IO_INV_LLC_SHFT 4 -#define IO_DRV_LLC_PAD_BMSK 0x000C -#define IO_DRV_LLC_PAD_SHFT 2 - -#define IO_REG_INT_RAW_STATUS_ADDR 0x3F - -#define IO_REG_INT1_CONF_ADDR 0x40 -#define IO_INTRQ_DUR_SEL_BMSK 0x00C0 -#define IO_INTRQ_DUR_SEL_SHFT 6 -#define IO_INTRQ_OP_SEL_BMSK 0x0003 -#define IO_INTRQ_OP_SEL_SHFT 0 - -#define IO_REG_INT2_CONF_ADDR 0x41 -#define IO_INTRQ2_DUR_SEL_BMSK 0x00C0 -#define IO_INTRQ2_DUR_SEL_SHFT 6 +#define IO_DRV_LLC_PAD_BMSK 0x000C +#define IO_DRV_LLC_PAD_SHFT 2 + +#define IO_REG_INT_RAW_STATUS_ADDR 0x3F +#define IO_INT_CEC_ST_BMSK 0x0010 +#define IO_INT_CEC_ST_SHFT 4 +#define IO_INT_HDMI_ST_BMSK 0x0008 +#define IO_INT_HDMI_ST_SHFT 3 +#define IO_INTRQ3_RAW_BMSK 0x0004 +#define IO_INTRQ3_RAW_SHFT 2 +#define IO_INTRQ2_RAW_BMSK 0x0002 +#define IO_INTRQ2_RAW_SHFT 1 +#define IO_INTRQ1_RAW_BMSK 0x0001 +#define IO_INTRQ1_RAW_SHFT 0 + +#define IO_REG_INT1_CONF_ADDR 0x40 +#define IO_INTRQ_DUR_SEL_BMSK 0x00C0 +#define IO_INTRQ_DUR_SEL_SHFT 6 +#define IO_INTRQ_OP_SEL_BMSK 0x0003 +#define IO_INTRQ_OP_SEL_SHFT 0 + +#define IO_REG_INT2_CONF_ADDR 0x41 +#define IO_INTRQ2_DUR_SEL_BMSK 0x00C0 +#define IO_INTRQ2_DUR_SEL_SHFT 6 #define IO_CP_LOCK_UNLOCK_EDGE_SEL_BMSK 0x0020 #define IO_CP_LOCK_UNLOCK_EDGE_SEL_SHFT 5 -#define IO_EN_UMASK_RAW_INTRQ2_BMSK 0x0008 -#define IO_EN_UMASK_RAW_INTRQ2_SHFT 3 +#define IO_EN_UMASK_RAW_INTRQ2_BMSK 0x0008 +#define IO_EN_UMASK_RAW_INTRQ2_SHFT 3 #define IO_INT2_EN_BMSK 0x0004 #define IO_INT2_EN_SHFT 2 -#define IO_INTRQ2_OP_SEL_BMSK 0x0003 -#define IO_INTRQ2_OP_SEL_SHFT 0 +#define IO_INTRQ2_OP_SEL_BMSK 0x0003 +#define IO_INTRQ2_OP_SEL_SHFT 0 #define IO_REG_DATAPATH_RAW_STATUS_ADDR 0x43 +#define IO_CP_LOCK_CP_RAW_BMSK 0x0080 +#define IO_CP_LOCK_CP_RAW_SHFT 7 +#define IO_CP_UNLOCK_CP_RAW_BMSK 0x0040 +#define IO_CP_UNLOCK_CP_RAW_SHFT 6 +#define IO_VMUTE_REQUEST_HDMI_RAW_BMSK 0x0020 +#define IO_VMUTE_REQUEST_HDMI_RAW_SHFT 5 +#define IO_MPU_STIM_INTRQ_RAW_BMSK 0x0002 +#define IO_MPU_STIM_INTRQ_RAW_SHFT 1 +#define IO_INT_SD_RAW_BMSK 0x0001 +#define IO_INT_SD_RAW_SHFT 0 + #define IO_REG_DATAPATH_INT_STATUS_ADDR 0x44 -#define IO_REG_DATAPATH_INT_CLEAR_ADDR 0x45 - -#define IO_REG_DATAPATH_INT_MASKB_ADDR 0x47 -#define IO_CP_LOCK_CP_MB1_BMSK 0x0080 -#define IO_CP_LOCK_CP_MB1_SHFT 7 -#define IO_CP_UNLOCK_CP_MB1_BMSK 0x0040 -#define IO_CP_UNLOCK_CP_MB1_SHFT 6 -#define IO_VMUTE_REQUEST_HDMI_MB1_BMSK 0x0020 -#define IO_VMUTE_REQUEST_HDMI_MB1_SHFT 5 -#define IO_MPU_STIM_INTRQ_MB1_BMSK 0x0002 -#define IO_MPU_STIM_INTRQ_MB1_SHFT 1 -#define IO_INT_SD_MB1_BMSK 0x0001 -#define IO_INT_SD_MB1_SHFT 0 +#define IO_CP_LOCK_CP_ST_BMSK 0x0080 +#define IO_CP_LOCK_CP_ST_SHFT 7 +#define IO_CP_UNLOCK_CP_ST_BMSK 0x0040 +#define IO_CP_UNLOCK_CP_ST_SHFT 6 +#define IO_VMUTE_REQUEST_HDMI_ST_BMSK 0x0020 +#define IO_VMUTE_REQUEST_HDMI_ST_SHFT 5 +#define IO_MPU_STIM_INTRQ_ST_BMSK 0x0002 +#define IO_MPU_STIM_INTRQ_ST_SHFT 1 +#define IO_INT_SD_ST_BMSK 0x0001 +#define IO_INT_SD_ST_SHFT 0 + +#define IO_REG_DATAPATH_INT_CLEAR_ADDR 0x45 + +#define IO_REG_DATAPATH_INT_MASKB_ADDR 0x47 +#define IO_CP_LOCK_CP_MB1_BMSK 0x0080 +#define IO_CP_LOCK_CP_MB1_SHFT 7 +#define IO_CP_UNLOCK_CP_MB1_BMSK 0x0040 +#define IO_CP_UNLOCK_CP_MB1_SHFT 6 +#define IO_VMUTE_REQUEST_HDMI_MB1_BMSK 0x0020 +#define IO_VMUTE_REQUEST_HDMI_MB1_SHFT 5 +#define IO_MPU_STIM_INTRQ_MB1_BMSK 0x0002 +#define IO_MPU_STIM_INTRQ_MB1_SHFT 1 +#define IO_INT_SD_MB1_BMSK 0x0001 +#define IO_INT_SD_MB1_SHFT 0 + +#define IO_REG_CHIP_REV_ID_1_ADDR 0xDF +#define IO_REG_CHIP_REV_ID_2_ADDR 0xE0 /* Offsets */ -#define IO_REG_DPLL_ADDR 0xF3 -#define IO_REG_CP_ADDR 0xF4 -#define IO_REG_HDMI_ADDR 0xF5 -#define IO_REG_EDID_ADDR 0xF6 -#define IO_REG_HDMI_REP_ADDR 0xF7 -#define IO_REG_HDMI_INF_ADDR 0xF8 -#define IO_REG_CBUS_ADDR 0xF9 -#define IO_REG_CEC_ADDR 0xFA -#define IO_REG_SDP_ADDR 0xFB -#define IO_REG_CSI_TXB_ADDR 0xFC -#define IO_REG_CSI_TXA_ADDR 0xFD +#define IO_REG_DPLL_ADDR 0xF3 +#define IO_REG_CP_ADDR 0xF4 +#define IO_REG_HDMI_ADDR 0xF5 +#define IO_REG_EDID_ADDR 0xF6 +#define IO_REG_HDMI_REP_ADDR 0xF7 +#define IO_REG_HDMI_INF_ADDR 0xF8 +#define IO_REG_CBUS_ADDR 0xF9 +#define IO_REG_CEC_ADDR 0xFA +#define IO_REG_SDP_ADDR 0xFB +#define IO_REG_CSI_TXB_ADDR 0xFC +#define IO_REG_CSI_TXA_ADDR 0xFD /* Sub Address Map Locations */ -#define IO_REG_DPLL_SADDR 0x4C -#define IO_REG_CP_SADDR 0x44 -#define IO_REG_HDMI_SADDR 0x74 -#define IO_REG_EDID_SADDR 0x78 -#define IO_REG_HDMI_REP_SADDR 0x64 -#define IO_REG_HDMI_INF_SADDR 0x62 -#define IO_REG_CBUS_SADDR 0xF0 -#define IO_REG_CEC_SADDR 0x82 -#define IO_REG_SDP_SADDR 0xF2 -#define IO_REG_CSI_TXB_SADDR 0x90 -#define IO_REG_CSI_TXA_SADDR 0x94 +#define IO_REG_DPLL_SADDR 0x4C +#define IO_REG_CP_SADDR 0x44 +#define IO_REG_HDMI_SADDR 0x74 +#define IO_REG_EDID_SADDR 0x78 +#define IO_REG_HDMI_REP_SADDR 0x64 +#define IO_REG_HDMI_INF_SADDR 0x62 +#define IO_REG_CBUS_SADDR 0xF0 +#define IO_REG_CEC_SADDR 0x82 +#define IO_REG_SDP_SADDR 0xF2 +#define IO_REG_CSI_TXB_SADDR 0x90 +#define IO_REG_CSI_TXA_SADDR 0x94 /* HDMI Map Registers */ #define HDMI_REG_HDMI_PARAM4_ADDR 0x04 @@ -179,10 +257,10 @@ #define HDMI_REG_AUDIO_PLL_LOCKED_SHFT 0 #define HDMI_REG_HDMI_PARAM5_ADDR 0x05 -#define HDMI_REG_HDMI_MODE_BMSK 0x0080 +#define HDMI_REG_HDMI_MODE_BMSK 0x0080 #define HDMI_REG_TMDS_FREQ_0_SHFT 7 -#define HDMI_REG_HDMI_CONT_ENCRYPT_BMSK 0x0040 -#define HDMI_REG_HDMI_CONT_ENCRYPT_SHFT 6 +#define HDMI_REG_HDMI_CONT_ENCRYPT_BMSK 0x0040 +#define HDMI_REG_HDMI_CONT_ENCRYPT_SHFT 6 #define HDMI_REG_DVI_HSYNC_POLARITY_BMSK 0x0020 #define HDMI_REG_DVI_HSYNC_POLARITY_SHFT 5 #define HDMI_REG_DVI_VSYNC_POLARITY_BMSK 0x0010 @@ -233,13 +311,13 @@ #define HDMI_REG_FIELD0_TOT_HEIGHT_2_BMSK 0x00FF #define HDMI_REG_FIELD0_TOT_HEIGHT_2_SHFT 0 -#define HDMI_REG_DIS_CABLE_DET_RST_ADDR 0x48 +#define HDMI_REG_DIS_CABLE_DET_RST_ADDR 0x48 #define HDMI_DIS_CABLE_DET_RST_BMSK 0x0040 #define HDMI_DIS_CABLE_DET_RST_SHFT 6 -#define HDMI_REG_TMDS_FREQ_ADDR 0x51 -#define HDMI_REG_TMDS_FREQ_BMSK 0x00FF -#define HDMI_REG_TMDS_FREQ_SHFT 0 +#define HDMI_REG_TMDS_FREQ_ADDR 0x51 +#define HDMI_REG_TMDS_FREQ_BMSK 0x00FF +#define HDMI_REG_TMDS_FREQ_SHFT 0 #define HDMI_REG_TMDS_FREQ_FRAC_ADDR 0x52 #define HDMI_REG_TMDS_FREQ_0_BMSK 0x0080 @@ -247,7 +325,7 @@ #define HDMI_REG_TMDS_FREQ_FRAC_BMSK 0x007F #define HDMI_REG_TMDS_FREQ_FRAC_SHFT 0 -#define HDMI_REG_RST_CTRLS_ADDR 0x5A +#define HDMI_REG_RST_CTRLS_ADDR 0x5A #define HDMI_HDCP_REPT_EDID_RST_BMSK 0x0008 #define HDMI_HDCP_REPT_EDID_RST_SHFT 3 @@ -261,19 +339,55 @@ #define HDMI_MAN_EDID_A_ENABLE_SHFT 0 #define HDMI_REG_RO_EDID_DEBUG_2_ADDR 0x76 -#define HDMI_EDID_A_ENABLE_BMSK 0x0001 -#define HDMI_EDID_A_ENABLE_SHFT 0 +#define HDMI_EDID_A_ENABLE_BMSK 0x0001 +#define HDMI_EDID_A_ENABLE_SHFT 0 + +/* CEC Map Registers */ +#define CEC_REG_LOG_ADDR_MASK_ADDR 0x27 +#define CEC_REG_LOG_ADDR_MASK2_BMSK 0x0040 +#define CEC_REG_LOG_ADDR_MASK2_SHFT 6 +#define CEC_REG_LOG_ADDR_MASK1_BMSK 0x0020 +#define CEC_REG_LOG_ADDR_MASK1_SHFT 5 +#define CEC_REG_LOG_ADDR_MASK0_BMSK 0x0010 +#define CEC_REG_LOG_ADDR_MASK0_SHFT 4 +#define CEC_REG_ERROR_REPORT_MODE_BMSK 0x0008 +#define CEC_REG_ERROR_REPORT_MODE_SHFT 3 +#define CEC_REG_ERROR_REPORT_DET_BMSK 0x0004 +#define CEC_REG_ERROR_REPORT_DET_SHFT 2 +#define CEC_REG_FORCE_NACK_BMSK 0x0002 +#define CEC_REG_FORCE_NACK_SHFT 1 +#define CEC_REG_FORCE_IGNORE_BMSK 0x0001 +#define CEC_REG_FORCE_IGNORE_SHFT 0 + +#define CEC_REG_LOGICAL_ADDRESS0_1_ADDR 0x28 +#define CEC_REG_LOGICAL_ADDRESS1_BMSK 0x00F0 +#define CEC_REG_LOGICAL_ADDRESS1_SHFT 4 +#define CEC_REG_LOGICAL_ADDRESS0_BMSK 0x000F +#define CEC_REG_LOGICAL_ADDRESS0_SHFT 0 + +#define CEC_REG_LOGICAL_ADDRESS2_ADDR 0x29 +#define CEC_REG_LOGICAL_ADDRESS2_BMSK 0x000F +#define CEC_REG_LOGICAL_ADDRESS2_SHFT 0 + +#define CEC_REG_CEC_POWER_UP_ADDR 0x2A +#define CEC_REG_CEC_POWER_UP_BMSK 0x0001 +#define CEC_REG_CEC_POWER_UP_SHFT 0 + +#define CEC_REG_CLR_RX_RDY_SFT_RST_ADDR 0x2C +#define CEC_REG_CEC_SOFT_RESET_BMSK 0x0001 +#define CEC_REG_CEC_SOFT_RESET_SHFT 0 + /* CP Map Registers */ -#define CP_REG_CONTRAST 0x3A -#define CP_REG_SATURATION 0x3B -#define CP_REG_BRIGHTNESS 0x3C -#define CP_REG_HUE 0x3D -#define CP_REG_VID_ADJ 0x3E -#define CP_CTR_VID_ADJ_EN 0x80 +#define CP_REG_CONTRAST 0x3A +#define CP_REG_SATURATION 0x3B +#define CP_REG_BRIGHTNESS 0x3C +#define CP_REG_HUE 0x3D +#define CP_REG_VID_ADJ 0x3E +#define CP_CTR_VID_ADJ_EN 0x80 #define CP_REG_STDI_CH_ADDR 0xB1 -#define CP_STDI_DVALID_CH1_BMSK 0x0080 -#define CP_STDI_DVALID_CH1_SHFT 7 +#define CP_STDI_DVALID_CH1_BMSK 0x0080 +#define CP_STDI_DVALID_CH1_SHFT 7 /* SDP R/O Main Map Registers */ #define SDP_RO_MAIN_STATUS1_ADDR 0x10 @@ -298,50 +412,50 @@ #define CSI_CTRL_TX_PWRDN_SHFT 7 #define CSI_CTRL_AUTO_PARAMS_BMSK 0x0020 #define CSI_CTRL_AUTO_PARAMS_SHFT 5 -#define CSI_CTRL_NUM_LANES_BMSK 0x0007 -#define CSI_CTRL_NUM_LANES_SHFT 0 +#define CSI_CTRL_NUM_LANES_BMSK 0x0007 +#define CSI_CTRL_NUM_LANES_SHFT 0 #define CSI_REG_TX_DPHY_PWDN_ADDR 0xF0 -#define CSI_CTRL_DPHY_PWDN_BMSK 0x0001 -#define CSI_CTRL_DPHY_PWDN_SHFT 0 +#define CSI_CTRL_DPHY_PWDN_BMSK 0x0001 +#define CSI_CTRL_DPHY_PWDN_SHFT 0 enum adv7481_adresult { - AD_NTSM_M_J = 0x0, - AD_NTSC_4_43 = 0x1, - AD_PAL_M = 0x2, - AD_PAL_60 = 0x3, - AD_PAL_B_G = 0x4, - AD_SECAM = 0x5, - AD_PAL_COMB_N = 0x6, - AD_SECAM_525 = 0x7, + AD_NTSM_M_J = 0x0, + AD_NTSC_4_43 = 0x1, + AD_PAL_M = 0x2, + AD_PAL_60 = 0x3, + AD_PAL_B_G = 0x4, + AD_SECAM = 0x5, + AD_PAL_COMB_N = 0x6, + AD_SECAM_525 = 0x7, }; enum adv7481_color_depth { - CD_8BIT = 0x0, - CD_10BIT = 0x1, - CD_12BIT = 0x2, - CD_16BIT = 0x3, + CD_8BIT = 0x0, + CD_10BIT = 0x1, + CD_12BIT = 0x2, + CD_16BIT = 0x3, }; enum adv7481_intrq_dur_sel { - AD_4_XTAL_PER = 0x0, - AD_16_XTAL_PER = 0x1, - AD_64_XTAL_PER = 0x2, - AD_ACTIVE_UNTIL_CLR = 0x3, + AD_4_XTAL_PER = 0x0, + AD_16_XTAL_PER = 0x1, + AD_64_XTAL_PER = 0x2, + AD_ACTIVE_UNTIL_CLR = 0x3, }; enum adv7481_intrq_op_sel { - AD_OP_OPEN_DRAIN = 0x0, - AD_OP_DRIVE_LOW = 0x1, - AD_OP_DRIVE_HIGH = 0x2, - AD_OP_DISABLED = 0x3, + AD_OP_OPEN_DRAIN = 0x0, + AD_OP_DRIVE_LOW = 0x1, + AD_OP_DRIVE_HIGH = 0x2, + AD_OP_DISABLED = 0x3, }; enum adv7481_drv_llc_pad { - AD_LLC_PAD_NOT_USED = 0x0, - AD_MIN_DRIVE_STRNGTH = 0x1, - AD_MID_DRIVE_STRNGTH = 0x2, - AD_MAX_DRIVE_STRNGTH = 0x3, + AD_LLC_PAD_NOT_USED = 0x0, + AD_MIN_DRIVE_STRNGTH = 0x1, + AD_MID_DRIVE_STRNGTH = 0x2, + AD_MAX_DRIVE_STRNGTH = 0x3, }; #endif diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c index e703791fd8e6..5d5ceb75653c 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c +++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c @@ -229,7 +229,7 @@ static void cam_smmu_print_list(int idx) pr_err("index = %d ", idx); list_for_each_entry(mapping, &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { - pr_err("ion_fd = %d, paddr= 0x%p, len = %u\n", + pr_err("ion_fd = %d, paddr= 0x%pK, len = %u\n", mapping->ion_fd, (void *)mapping->paddr, (unsigned int)mapping->len); } @@ -240,10 +240,10 @@ static void cam_smmu_print_table(void) int i; for (i = 0; i < iommu_cb_set.cb_num; i++) { - pr_err("i= %d, handle= %d, name_addr=%p\n", i, + pr_err("i= %d, handle= %d, name_addr=%pK\n", i, (int)iommu_cb_set.cb_info[i].handle, (void *)iommu_cb_set.cb_info[i].name); - pr_err("dev = %p ", iommu_cb_set.cb_info[i].dev); + pr_err("dev = %pK ", iommu_cb_set.cb_info[i].dev); } } @@ -306,18 +306,18 @@ static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr) end_addr = (unsigned long)mapping->paddr + mapping->len; if (start_addr <= current_addr && current_addr < end_addr) { - pr_err("Error: va %p is valid: range:%p-%p, fd = %d cb: %s\n", + pr_err("Error: va %pK is valid: range:%pK-%pK, fd = %d cb: %s\n", vaddr, (void *)start_addr, (void *)end_addr, mapping->ion_fd, iommu_cb_set.cb_info[idx].name); return; } else { - CDBG("va %p is not in this range: %p-%p, fd = %d\n", + CDBG("va %pK is not in this range: %pK-%pK, fd = %d\n", vaddr, (void *)start_addr, (void *)end_addr, mapping->ion_fd); } } - pr_err("Cannot find vaddr:%p in SMMU. %s uses invalid virtual address\n", + pr_err("Cannot find vaddr:%pK in SMMU. %s uses invalid virtual address\n", vaddr, iommu_cb_set.cb_info[idx].name); return; } @@ -393,7 +393,7 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain, if (!token) { pr_err("Error: token is NULL\n"); - pr_err("Error: domain = %p, device = %p\n", domain, dev); + pr_err("Error: domain = %pK, device = %pK\n", domain, dev); pr_err("iova = %lX, flags = %d\n", iova, flags); return 0; } @@ -705,7 +705,7 @@ static void cam_smmu_clean_buffer_list(int idx) list_for_each_entry_safe(mapping_info, temp, &iommu_cb_set.cb_info[idx].smmu_buf_list, list) { - CDBG("Free mapping address %p, i = %d, fd = %d\n", + CDBG("Free mapping address %pK, i = %d, fd = %d\n", (void *)mapping_info->paddr, idx, mapping_info->ion_fd); @@ -800,11 +800,11 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, } if (table->sgl) { - CDBG("DMA buf: %p, device: %p, attach: %p, table: %p\n", + CDBG("DMA buf: %pK, device: %pK, attach: %pK, table: %pK\n", (void *)buf, (void *)iommu_cb_set.cb_info[idx].dev, (void *)attach, (void *)table); - CDBG("table sgl: %p, rc: %d, dma_address: 0x%x\n", + CDBG("table sgl: %pK, rc: %d, dma_address: 0x%x\n", (void *)table->sgl, rc, (unsigned int)table->sgl->dma_address); } else { @@ -838,7 +838,7 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, rc = -ENOSPC; goto err_unmap_sg; } - CDBG("ion_fd = %d, dev = %p, paddr= %p, len = %u\n", ion_fd, + CDBG("ion_fd = %d, dev = %pK, paddr= %pK, len = %u\n", ion_fd, (void *)iommu_cb_set.cb_info[idx].dev, (void *)*paddr_ptr, (unsigned int)*len_ptr); @@ -862,10 +862,10 @@ static int cam_smmu_unmap_buf_and_remove_from_list( { if ((!mapping_info->buf) || (!mapping_info->table) || (!mapping_info->attach)) { - pr_err("Error: Invalid params dev = %p, table = %p", + pr_err("Error: Invalid params dev = %pK, table = %pK", (void *)iommu_cb_set.cb_info[idx].dev, (void *)mapping_info->table); - pr_err("Error:dma_buf = %p, attach = %p\n", + pr_err("Error:dma_buf = %pK, attach = %pK\n", (void *)mapping_info->buf, (void *)mapping_info->attach); return -EINVAL; @@ -989,7 +989,7 @@ static int cam_smmu_alloc_scratch_buffer_add_to_list(int idx, CDBG("%s: nents = %lu, idx = %d, virt_len = %zx\n", __func__, nents, idx, virt_len); - CDBG("%s: phys_len = %zx, iommu_dir = %d, virt_addr = %p\n", + CDBG("%s: phys_len = %zx, iommu_dir = %d, virt_addr = %pK\n", __func__, phys_len, iommu_dir, virt_addr); /* This table will go inside the 'mapping' structure @@ -1055,7 +1055,7 @@ static int cam_smmu_alloc_scratch_buffer_add_to_list(int idx, mapping_info->ref_count = 1; mapping_info->phys_len = phys_len; - CDBG("%s: paddr = %p, len = %zx, phys_len = %zx", + CDBG("%s: paddr = %pK, len = %zx, phys_len = %zx", __func__, (void *)mapping_info->paddr, mapping_info->len, mapping_info->phys_len); @@ -1093,7 +1093,7 @@ static int cam_smmu_free_scratch_buffer_remove_from_list( &iommu_cb_set.cb_info[idx].scratch_map; if (!mapping_info->table) { - pr_err("Error: Invalid params: dev = %p, table = %p, ", + pr_err("Error: Invalid params: dev = %pK, table = %pK, ", (void *)iommu_cb_set.cb_info[idx].dev, (void *)mapping_info->table); return -EINVAL; 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 33e1299cd027..21ac680bc9ae 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 @@ -165,7 +165,7 @@ int msm_camera_get_clk_info(struct platform_device *pdev, rc = PTR_ERR((*clk_ptr)[i]); goto err4; } - CDBG("clk ptr[%d] :%p\n", i, (*clk_ptr)[i]); + CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]); } devm_kfree(&pdev->dev, rates); @@ -289,7 +289,7 @@ int msm_camera_get_clk_info_and_rates( rc = PTR_ERR(clks[i]); goto err5; } - CDBG("clk ptr[%d] :%p\n", i, clks[i]); + CDBG("clk ptr[%d] :%pK\n", i, clks[i]); } *pclk_info = clk_info; *pclks = clks; @@ -405,7 +405,7 @@ long msm_camera_clk_set_rate(struct device *dev, if (!dev || !clk || (clk_rate < 0)) return -EINVAL; - CDBG("clk : %p, enable : %ld\n", clk, clk_rate); + CDBG("clk : %pK, enable : %ld\n", clk, clk_rate); if (clk_rate > 0) { rate = clk_round_rate(clk, clk_rate); @@ -436,7 +436,7 @@ int msm_camera_put_clk_info(struct platform_device *pdev, if (clk_ptr[i] != NULL) devm_clk_put(&pdev->dev, (*clk_ptr)[i]); - CDBG("clk ptr[%d] :%p\n", i, (*clk_ptr)[i]); + CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]); } devm_kfree(&pdev->dev, *clk_info); devm_kfree(&pdev->dev, *clk_ptr); @@ -460,7 +460,7 @@ int msm_camera_put_clk_info_and_rates(struct platform_device *pdev, for (i = cnt - 1; i >= 0; i--) { if (clk_ptr[i] != NULL) devm_clk_put(&pdev->dev, (*clk_ptr)[i]); - CDBG("clk ptr[%d] :%p\n", i, (*clk_ptr)[i]); + CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]); } devm_kfree(&pdev->dev, *clk_info); devm_kfree(&pdev->dev, *clk_ptr); @@ -531,7 +531,7 @@ int msm_camera_get_regulator_info(struct platform_device *pdev, rc = -EINVAL; goto err1; } - CDBG("vdd ptr[%d] :%p\n", i, tmp_reg[i].vdd); + CDBG("vdd ptr[%d] :%pK\n", i, tmp_reg[i].vdd); } *num_reg = cnt; @@ -607,7 +607,7 @@ void msm_camera_put_regulators(struct platform_device *pdev, for (i = cnt - 1; i >= 0; i--) { if (vdd_info[i] && !IS_ERR_OR_NULL(vdd_info[i]->vdd)) devm_regulator_put(vdd_info[i]->vdd); - CDBG("vdd ptr[%d] :%p\n", i, vdd_info[i]->vdd); + CDBG("vdd ptr[%d] :%pK\n", i, vdd_info[i]->vdd); } devm_kfree(&pdev->dev, *vdd_info); @@ -646,7 +646,7 @@ int msm_camera_register_irq(struct platform_device *pdev, rc = -EINVAL; } - CDBG("Registered irq for %s[resource - %p]\n", irq_name, irq); + CDBG("Registered irq for %s[resource - %pK]\n", irq_name, irq); return rc; } @@ -671,7 +671,7 @@ int msm_camera_register_threaded_irq(struct platform_device *pdev, rc = -EINVAL; } - CDBG("Registered irq for %s[resource - %p]\n", irq_name, irq); + CDBG("Registered irq for %s[resource - %pK]\n", irq_name, irq); return rc; } @@ -703,7 +703,7 @@ int msm_camera_unregister_irq(struct platform_device *pdev, return -EINVAL; } - CDBG("Un Registering irq for [resource - %p]\n", irq); + CDBG("Un Registering irq for [resource - %pK]\n", irq); devm_free_irq(&pdev->dev, irq->start, dev_id); return 0; @@ -730,7 +730,7 @@ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, } if (reserve_mem) { - CDBG("device:%p, mem : %p, size : %d\n", + CDBG("device:%pK, mem : %pK, size : %d\n", &pdev->dev, mem, (int)resource_size(mem)); if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), @@ -749,7 +749,7 @@ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, return NULL; } - CDBG("base : %p\n", base); + CDBG("base : %pK\n", base); return base; } EXPORT_SYMBOL(msm_camera_get_reg_base); @@ -793,7 +793,7 @@ int msm_camera_put_reg_base(struct platform_device *pdev, pr_err("err: mem resource %s not found\n", device_name); return -EINVAL; } - CDBG("mem : %p, size : %d\n", mem, (int)resource_size(mem)); + CDBG("mem : %pK, size : %d\n", mem, (int)resource_size(mem)); devm_iounmap(&pdev->dev, base); if (reserve_mem) diff --git a/drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c index f978f97d7895..51a9ea85d1f3 100644 --- a/drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c +++ b/drivers/media/platform/msm/camera_v2/common/msm_camera_io_util.c @@ -27,7 +27,7 @@ void msm_camera_io_w(u32 data, void __iomem *addr) { - CDBG("%s: 0x%p %08x\n", __func__, (addr), (data)); + CDBG("%s: 0x%pK %08x\n", __func__, (addr), (data)); writel_relaxed((data), (addr)); } @@ -43,7 +43,7 @@ int32_t msm_camera_io_w_block(const u32 *addr, void __iomem *base, return -EINVAL; for (i = 0; i < len; i++) { - CDBG("%s: len =%d val=%x base =%p\n", __func__, + CDBG("%s: len =%d val=%x base =%pK\n", __func__, len, addr[i], base); writel_relaxed(addr[i], base); } @@ -62,7 +62,7 @@ int32_t msm_camera_io_w_reg_block(const u32 *addr, void __iomem *base, return -EINVAL; for (i = 0; i < len; i = i + 2) { - CDBG("%s: len =%d val=%x base =%p reg=%x\n", __func__, + CDBG("%s: len =%d val=%x base =%pK reg=%x\n", __func__, len, addr[i + 1], base, addr[i]); writel_relaxed(addr[i + 1], base + addr[i]); } @@ -71,7 +71,7 @@ int32_t msm_camera_io_w_reg_block(const u32 *addr, void __iomem *base, void msm_camera_io_w_mb(u32 data, void __iomem *addr) { - CDBG("%s: 0x%p %08x\n", __func__, (addr), (data)); + CDBG("%s: 0x%pK %08x\n", __func__, (addr), (data)); /* ensure write is done */ wmb(); writel_relaxed((data), (addr)); @@ -89,7 +89,7 @@ int32_t msm_camera_io_w_mb_block(const u32 *addr, void __iomem *base, u32 len) for (i = 0; i < len; i++) { /* ensure write is done */ wmb(); - CDBG("%s: len =%d val=%x base =%p\n", __func__, + CDBG("%s: len =%d val=%x base =%pK\n", __func__, len, addr[i], base); writel_relaxed(addr[i], base); } @@ -102,7 +102,7 @@ u32 msm_camera_io_r(void __iomem *addr) { uint32_t data = readl_relaxed(addr); - CDBG("%s: 0x%p %08x\n", __func__, (addr), (data)); + CDBG("%s: 0x%pK %08x\n", __func__, (addr), (data)); return data; } @@ -114,7 +114,7 @@ u32 msm_camera_io_r_mb(void __iomem *addr) data = readl_relaxed(addr); /* ensure read is done */ rmb(); - CDBG("%s: 0x%p %08x\n", __func__, (addr), (data)); + CDBG("%s: 0x%pK %08x\n", __func__, (addr), (data)); return data; } @@ -180,7 +180,7 @@ void msm_camera_io_dump(void __iomem *addr, int size, int enable) u32 *p = (u32 *) addr; u32 data; - CDBG("%s: addr=%p size=%d\n", __func__, addr, size); + CDBG("%s: addr=%pK size=%d\n", __func__, addr, size); if (!p || (size <= 0) || !enable) return; @@ -216,12 +216,12 @@ void msm_camera_io_dump_wstring_base(void __iomem *addr, { int i, u = sizeof(struct msm_cam_dump_string_info); - pr_debug("%s: addr=%p data=%p size=%d u=%d, cnt=%d\n", __func__, + pr_debug("%s: addr=%pK data=%pK size=%d u=%d, cnt=%d\n", __func__, addr, dump_data, size, u, (size/u)); if (!addr || (size <= 0) || !dump_data) { - pr_err("%s: addr=%p data=%p size=%d\n", __func__, + pr_err("%s: addr=%pK data=%pK size=%d\n", __func__, addr, dump_data, size); return; } @@ -233,7 +233,7 @@ void msm_camera_io_dump_wstring_base(void __iomem *addr, void msm_camera_io_memcpy(void __iomem *dest_addr, void __iomem *src_addr, u32 len) { - CDBG("%s: %p %p %d\n", __func__, dest_addr, src_addr, len); + CDBG("%s: %pK %pK %d\n", __func__, dest_addr, src_addr, len); msm_camera_io_memcpy_toio(dest_addr, src_addr, len / 4); } @@ -728,7 +728,7 @@ int msm_camera_request_gpio_table(struct gpio *gpio_tbl, uint8_t size, int rc = 0, i = 0, err = 0; if (!gpio_tbl || !size) { - pr_err("%s:%d invalid gpio_tbl %p / size %d\n", __func__, + pr_err("%s:%d invalid gpio_tbl %pK / size %d\n", __func__, __LINE__, gpio_tbl, size); return -EINVAL; } @@ -772,7 +772,7 @@ int msm_camera_get_dt_reg_settings(struct device_node *of_node, unsigned int cnt; if (!of_node || !dt_prop_name || !size || !reg_s) { - pr_err("%s: Error invalid args %p:%p:%p:%p\n", + pr_err("%s: Error invalid args %pK:%pK:%pK:%pK\n", __func__, size, reg_s, of_node, dt_prop_name); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h index 993203bb9dff..4155eb8a6faf 100644 --- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h +++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h @@ -252,6 +252,7 @@ struct msm_fd_device { struct work_struct work; struct completion hw_halt_completion; int recovery_mode; + uint32_t clk_rate_idx; }; #endif /* __MSM_FD_DEV_H__ */ diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c index 24683441d5ed..a20f40a0969f 100644 --- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c +++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c @@ -669,7 +669,7 @@ int32_t msm_fd_hw_set_dt_parms_by_name(struct msm_fd_device *fd, dt_reg_settings[i + MSM_FD_REG_ADDR_OFFSET_IDX], dt_reg_settings[i + MSM_FD_REG_VALUE_IDX] & dt_reg_settings[i + MSM_FD_REG_MASK_IDX]); - pr_debug("%s:%d] %p %08x\n", __func__, __LINE__, + pr_debug("%s:%d] %pK %08x\n", __func__, __LINE__, fd->iomem_base[base_idx] + dt_reg_settings[i + MSM_FD_REG_ADDR_OFFSET_IDX], dt_reg_settings[i + MSM_FD_REG_VALUE_IDX] & @@ -822,6 +822,45 @@ static int msm_fd_hw_set_clock_rate_idx(struct msm_fd_device *fd, return 0; } + +/** + * msm_fd_hw_update_settings() - API to set clock rate and bus settings + * @fd: Pointer to fd device. + * @buf: fd buffer + */ +static int msm_fd_hw_update_settings(struct msm_fd_device *fd, + struct msm_fd_buffer *buf) +{ + int ret = 0; + uint32_t clk_rate_idx; + + if (!buf) + return 0; + + clk_rate_idx = buf->settings.speed; + if (fd->clk_rate_idx == clk_rate_idx) + return 0; + + if (fd->bus_client) { + ret = msm_fd_hw_bus_request(fd, clk_rate_idx); + if (ret < 0) { + dev_err(fd->dev, "Fail bus scale update %d\n", ret); + return -EINVAL; + } + } + + ret = msm_fd_hw_set_clock_rate_idx(fd, clk_rate_idx); + if (ret < 0) { + dev_err(fd->dev, "Fail to set clock rate idx\n"); + goto end; + } + dev_dbg(fd->dev, "set clk %d %d", fd->clk_rate_idx, clk_rate_idx); + fd->clk_rate_idx = clk_rate_idx; + +end: + return ret; +} + /* * msm_fd_hw_get - Get fd hw for performing any hw operation. * @fd: Pointer to fd device. @@ -868,6 +907,8 @@ int msm_fd_hw_get(struct msm_fd_device *fd, unsigned int clock_rate_idx) ret = msm_fd_hw_set_dt_parms(fd); if (ret < 0) goto error_set_dt; + + fd->clk_rate_idx = clock_rate_idx; } fd->ref_count++; @@ -1228,6 +1269,8 @@ int msm_fd_hw_schedule_and_start(struct msm_fd_device *fd) spin_unlock(&fd->slock); + msm_fd_hw_update_settings(fd, buf); + return 0; } @@ -1266,5 +1309,7 @@ int msm_fd_hw_schedule_next_buffer(struct msm_fd_device *fd) } spin_unlock(&fd->slock); + msm_fd_hw_update_settings(fd, buf); + return 0; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c index 3331f0d4c340..94e974529e56 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c @@ -62,13 +62,13 @@ static int msm_buf_check_head_sanity(struct msm_isp_bufq *bufq) } if (prev->next != &bufq->head) { - pr_err("%s: Error! head prev->next is %p should be %p\n", + pr_err("%s: Error! head prev->next is %pK should be %pK\n", __func__, prev->next, &bufq->head); return -EINVAL; } if (next->prev != &bufq->head) { - pr_err("%s: Error! head next->prev is %p should be %p\n", + pr_err("%s: Error! head next->prev is %pK should be %pK\n", __func__, next->prev, &bufq->head); return -EINVAL; } @@ -228,7 +228,7 @@ static void msm_isp_unprepare_v4l2_buf( struct msm_isp_bufq *bufq = NULL; if (!buf_mgr || !buf_info) { - pr_err("%s: NULL ptr %p %p\n", __func__, + pr_err("%s: NULL ptr %pK %pK\n", __func__, buf_mgr, buf_info); return; } @@ -255,7 +255,7 @@ static int msm_isp_map_buf(struct msm_isp_buf_mgr *buf_mgr, int ret; if (!buf_mgr || !mapped_info) { - pr_err_ratelimited("%s: %d] NULL ptr buf_mgr %p mapped_info %p\n", + pr_err_ratelimited("%s: %d] NULL ptr buf_mgr %pK mapped_info %pK\n", __func__, __LINE__, buf_mgr, mapped_info); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index 354fda32ff3b..eebcecc7bbe6 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -616,6 +616,7 @@ struct dual_vfe_resource { struct msm_vfe_stats_shared_data *stats_data[MAX_VFE]; struct msm_vfe_axi_shared_data *axi_data[MAX_VFE]; uint32_t wm_reload_mask[MAX_VFE]; + uint32_t epoch_sync_mask; }; struct master_slave_resource_info { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c index e1e579bc292c..f15f234c007e 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c @@ -920,7 +920,7 @@ static int msm_vfe46_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_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index ea3c8f71912b..ebf38dd387d6 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -1058,7 +1058,7 @@ static int msm_vfe47_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; } @@ -1443,6 +1443,8 @@ static void msm_vfe47_update_camif_state(struct vfe_device *vfe_dev, if ((vfe_dev->hvx_cmd > HVX_DISABLE) && (vfe_dev->hvx_cmd <= HVX_ROUND_TRIP)) msm_vfe47_configure_hvx(vfe_dev, 1); + else + msm_vfe47_configure_hvx(vfe_dev, 0); bus_en = ((vfe_dev->axi_data. 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 c98b8ad6306b..a5952a5b9b0a 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 @@ -146,6 +146,14 @@ int msm_isp_validate_axi_request(struct msm_vfe_axi_shared_data *axi_data, case V4L2_PIX_FMT_SGBRG10: case V4L2_PIX_FMT_SGRBG10: case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SBGGR10DPCM6: + case V4L2_PIX_FMT_SGBRG10DPCM6: + case V4L2_PIX_FMT_SGRBG10DPCM6: + case V4L2_PIX_FMT_SRGGB10DPCM6: + case V4L2_PIX_FMT_SBGGR10DPCM8: + case V4L2_PIX_FMT_SGBRG10DPCM8: + case V4L2_PIX_FMT_SGRBG10DPCM8: + case V4L2_PIX_FMT_SRGGB10DPCM8: case V4L2_PIX_FMT_SBGGR12: case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SGRBG12: @@ -272,6 +280,14 @@ static uint32_t msm_isp_axi_get_plane_size( case V4L2_PIX_FMT_SGBRG10: case V4L2_PIX_FMT_SGRBG10: case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SBGGR10DPCM6: + case V4L2_PIX_FMT_SGBRG10DPCM6: + case V4L2_PIX_FMT_SGRBG10DPCM6: + case V4L2_PIX_FMT_SRGGB10DPCM6: + case V4L2_PIX_FMT_SBGGR10DPCM8: + case V4L2_PIX_FMT_SGBRG10DPCM8: + case V4L2_PIX_FMT_SGRBG10DPCM8: + case V4L2_PIX_FMT_SRGGB10DPCM8: case V4L2_PIX_FMT_QBGGR10: case V4L2_PIX_FMT_QGBRG10: case V4L2_PIX_FMT_QGRBG10: @@ -528,6 +544,89 @@ static void msm_isp_cfg_framedrop_reg(struct vfe_device *vfe_dev, } /** + * msm_isp_check_epoch_status() - check the epock signal for framedrop + * + * @vfe_dev: The h/w on which the epoch signel is reveived + * @frame_src: The source of the epoch signal for this frame + * + * For dual vfe case and pixel stream, if both vfe's epoch signal is + * received, this function will return success. + * It will also return the vfe1 for further process + * For none dual VFE stream or none pixl source, this + * funciton will just return success. + * + * Returns 1 - epoch received is complete. + * 0 - epoch reveived is not complete. + */ +static int msm_isp_check_epoch_status(struct vfe_device **vfe_dev, + enum msm_vfe_input_src frame_src) +{ + struct vfe_device *vfe_dev_cur = *vfe_dev; + struct vfe_device *vfe_dev_other = NULL; + uint32_t vfe_id_other = 0; + uint32_t vfe_id_cur = 0; + uint32_t epoch_mask = 0; + unsigned long flags; + int completed = 0; + + spin_lock_irqsave( + &vfe_dev_cur->common_data->common_dev_data_lock, flags); + + if (vfe_dev_cur->is_split && + frame_src == VFE_PIX_0) { + if (vfe_dev_cur->pdev->id == ISP_VFE0) { + vfe_id_cur = ISP_VFE0; + vfe_id_other = ISP_VFE1; + } else { + vfe_id_cur = ISP_VFE1; + vfe_id_other = ISP_VFE0; + } + vfe_dev_other = vfe_dev_cur->common_data->dual_vfe_res-> + vfe_dev[vfe_id_other]; + + if (vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask & (1 << vfe_id_cur)) { + /* serious scheduling delay */ + pr_err("Missing epoch: vfe %d, epoch mask 0x%x\n", + vfe_dev_cur->pdev->id, + vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask); + goto fatal; + } + + vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask |= (1 << vfe_id_cur); + + epoch_mask = (1 << vfe_id_cur) | (1 << vfe_id_other); + if ((vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask & epoch_mask) == epoch_mask) { + + if (vfe_id_other == ISP_VFE0) + *vfe_dev = vfe_dev_cur; + else + *vfe_dev = vfe_dev_other; + + vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask &= ~epoch_mask; + completed = 1; + } + } else + completed = 1; + + spin_unlock_irqrestore( + &vfe_dev_cur->common_data->common_dev_data_lock, flags); + + return completed; +fatal: + spin_unlock_irqrestore( + &vfe_dev_cur->common_data->common_dev_data_lock, flags); + /* new error event code will be added later */ + msm_isp_halt_send_error(vfe_dev_cur, ISP_EVENT_PING_PONG_MISMATCH); + return 0; +} + + +/** * msm_isp_update_framedrop_reg() - Update frame period pattern on h/w * @vfe_dev: The h/w on which the perion pattern is updated. * @frame_src: Input source. @@ -542,10 +641,15 @@ void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev, enum msm_vfe_input_src frame_src) { int i; - struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; + struct msm_vfe_axi_shared_data *axi_data = NULL; struct msm_vfe_axi_stream *stream_info; unsigned long flags; + if (msm_isp_check_epoch_status(&vfe_dev, frame_src) != 1) + return; + + axi_data = &vfe_dev->axi_data; + for (i = 0; i < VFE_AXI_SRC_MAX; i++) { if (SRC_TO_INTF(axi_data->stream_info[i].stream_src) != frame_src) { @@ -621,7 +725,7 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, int i; if (!vfe_dev || !sof_info) { - pr_err("%s %d failed: vfe_dev %p sof_info %p\n", __func__, + pr_err("%s %d failed: vfe_dev %pK sof_info %pK\n", __func__, __LINE__, vfe_dev, sof_info); return; } @@ -1180,7 +1284,7 @@ static int msm_isp_axi_stream_enable_cfg( !dual_vfe_res->axi_data[ISP_VFE0] || !dual_vfe_res->vfe_base[ISP_VFE1] || !dual_vfe_res->axi_data[ISP_VFE1]) { - pr_err("%s:%d failed vfe0 %p %p vfe %p %p\n", + pr_err("%s:%d failed vfe0 %pK %pK vfe %pK %pK\n", __func__, __LINE__, dual_vfe_res->vfe_base[ISP_VFE0], dual_vfe_res->axi_data[ISP_VFE0], @@ -1354,19 +1458,9 @@ void msm_isp_axi_cfg_update(struct vfe_device *vfe_dev, cfg_wm_reg(vfe_dev, stream_info, j); /*Resume AXI*/ stream_info->state = RESUME_PENDING; - if (vfe_dev->is_split) { - msm_isp_update_dual_HW_axi(vfe_dev, - stream_info); - } else { - msm_isp_axi_stream_enable_cfg( - vfe_dev, - &axi_data->stream_info[i], 1); - stream_info->state = RESUMING; - } + msm_isp_update_dual_HW_axi(vfe_dev, stream_info); } else if (stream_info->state == RESUMING) { - stream_info->runtime_output_format = - stream_info->output_format; - stream_info->state = ACTIVE; + msm_isp_update_dual_HW_axi(vfe_dev, stream_info); } spin_unlock_irqrestore(&stream_info->lock, flags); } @@ -1565,7 +1659,7 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev, !dual_vfe_res->axi_data[ISP_VFE0] || !dual_vfe_res->vfe_base[ISP_VFE1] || !dual_vfe_res->axi_data[ISP_VFE1]) { - pr_err("%s:%d failed vfe0 %p %p vfe %p %p\n", + pr_err("%s:%d failed vfe0 %pK %pK vfe %pK %pK\n", __func__, __LINE__, dual_vfe_res->vfe_base[ISP_VFE0], dual_vfe_res->axi_data[ISP_VFE0], @@ -1846,7 +1940,7 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, uint32_t pingpong_bit; if (!vfe_dev || !stream_info || !ts || !sof_info) { - pr_err("%s %d vfe_dev %p stream_info %p ts %p op_info %p\n", + pr_err("%s %d vfe_dev %pK stream_info %pK ts %pK op_info %pK\n", __func__, __LINE__, vfe_dev, stream_info, ts, sof_info); return -EINVAL; @@ -1902,6 +1996,13 @@ static void msm_isp_get_camif_update_state_and_halt( pix_stream_cnt++; } + if (vfe_dev->axi_data.num_active_stream == stream_cfg_cmd->num_streams + && (stream_cfg_cmd->cmd == STOP_STREAM || + stream_cfg_cmd->cmd == STOP_IMMEDIATELY)) + *halt = 1; + else + *halt = 0; + if ((pix_stream_cnt) && (axi_data->src_info[VFE_PIX_0].input_mux != EXTERNAL_READ)) { if (cur_pix_stream_cnt == 0 && pix_stream_cnt && @@ -1909,24 +2010,17 @@ static void msm_isp_get_camif_update_state_and_halt( *camif_update = ENABLE_CAMIF; else if (cur_pix_stream_cnt && (cur_pix_stream_cnt - pix_stream_cnt) == 0 && - stream_cfg_cmd->cmd == STOP_STREAM) - *camif_update = DISABLE_CAMIF; - else if (cur_pix_stream_cnt && - (cur_pix_stream_cnt - pix_stream_cnt) == 0 && - stream_cfg_cmd->cmd == STOP_IMMEDIATELY) - *camif_update = DISABLE_CAMIF_IMMEDIATELY; + (stream_cfg_cmd->cmd == STOP_STREAM || + stream_cfg_cmd->cmd == STOP_IMMEDIATELY)) { + if (*halt) + *camif_update = DISABLE_CAMIF_IMMEDIATELY; + else + *camif_update = DISABLE_CAMIF; + } else *camif_update = NO_UPDATE; } else *camif_update = NO_UPDATE; - - if (vfe_dev->axi_data.num_active_stream == stream_cfg_cmd->num_streams - && (stream_cfg_cmd->cmd == STOP_STREAM || - stream_cfg_cmd->cmd == STOP_IMMEDIATELY)) - *halt = 1; - else - *halt = 0; - } static void msm_isp_update_camif_output_count( @@ -2136,7 +2230,7 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev, unsigned long flags; if (!reset_cmd) { - pr_err("%s: NULL pointer reset cmd %p\n", __func__, reset_cmd); + pr_err("%s: NULL pointer reset cmd %pK\n", __func__, reset_cmd); rc = -1; return rc; } @@ -2418,28 +2512,54 @@ static int msm_isp_update_dual_HW_axi(struct vfe_device *vfe_dev, } dual_vfe_res = vfe_dev->common_data->dual_vfe_res; + if (vfe_dev->is_split) { + if (!dual_vfe_res->vfe_dev[ISP_VFE0] || + !dual_vfe_res->vfe_dev[ISP_VFE1] || + !dual_vfe_res->axi_data[ISP_VFE0] || + !dual_vfe_res->axi_data[ISP_VFE1]) { + pr_err("%s: Error in dual vfe resource\n", __func__); + rc = -EINVAL; + } else { + if (stream_info->state == RESUME_PENDING && + (dual_vfe_res->axi_data[!vfe_dev->pdev->id]-> + stream_info[stream_idx].state == + RESUME_PENDING)) { + /* Update the AXI only after both ISPs receiving + the Reg update interrupt*/ + for (vfe_id = 0; vfe_id < MAX_VFE; vfe_id++) { + rc = msm_isp_axi_stream_enable_cfg( + dual_vfe_res->vfe_dev[vfe_id], + &dual_vfe_res-> + axi_data[vfe_id]-> + stream_info[stream_idx], 1); + dual_vfe_res->axi_data[vfe_id]-> + stream_info[stream_idx].state = + RESUMING; + } + } else if (stream_info->state == RESUMING && + (dual_vfe_res->axi_data[!vfe_dev->pdev->id]-> + stream_info[stream_idx].state == RESUMING)) { + for (vfe_id = 0; vfe_id < MAX_VFE; vfe_id++) { + dual_vfe_res->axi_data[vfe_id]-> + stream_info[stream_idx]. + runtime_output_format = + stream_info->output_format; + dual_vfe_res->axi_data[vfe_id]-> + stream_info[stream_idx].state = + ACTIVE; + } + } - if (!dual_vfe_res->vfe_dev[ISP_VFE0] || - !dual_vfe_res->vfe_dev[ISP_VFE1] || - !dual_vfe_res->axi_data[ISP_VFE0] || - !dual_vfe_res->axi_data[ISP_VFE1]) { - pr_err("%s: Error in dual vfe resource\n", __func__); - rc = -EINVAL; + } } else { - if (stream_info->state == RESUME_PENDING && - (dual_vfe_res->axi_data[!vfe_dev->pdev->id]-> - stream_info[stream_idx].state == RESUME_PENDING)) { - /* Update the AXI only after both ISPs receiving the - Reg update interrupt*/ - for (vfe_id = 0; vfe_id < MAX_VFE; vfe_id++) { - rc = msm_isp_axi_stream_enable_cfg( - dual_vfe_res->vfe_dev[vfe_id], - &dual_vfe_res->axi_data[vfe_id]-> - stream_info[stream_idx], 1); - dual_vfe_res->axi_data[vfe_id]-> - stream_info[stream_idx].state = - RESUMING; - } + if (stream_info->state == RESUME_PENDING) { + msm_isp_axi_stream_enable_cfg( + vfe_dev, stream_info, 0); + stream_info->state = RESUMING; + } else if (stream_info->state == RESUMING) { + stream_info->runtime_output_format = + stream_info->output_format; + stream_info->state = ACTIVE; } } return rc; @@ -2549,6 +2669,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, vfe_dev->hw_info->vfe_ops.core_ops. update_camif_state(vfe_dev, camif_update); vfe_dev->axi_data.camif_state = CAMIF_ENABLE; + vfe_dev->common_data->dual_vfe_res->epoch_sync_mask = 0; } if (wait_for_complete) { @@ -2610,34 +2731,20 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev, wait_for_complete_for_this_stream = 0; stream_info->state = STOP_PENDING; - ISP_DBG("Stop axi Stream 0x%x\n", stream_info->stream_id); - if (stream_info->stream_src == CAMIF_RAW || - stream_info->stream_src == IDEAL_RAW) { - /* We dont get reg update IRQ for raw snapshot - * so frame skip cant be ocnfigured - */ - if ((camif_update != DISABLE_CAMIF_IMMEDIATELY) && - (!ext_read)) - wait_for_complete_for_this_stream = 1; - - } else if (stream_info->stream_type == BURST_STREAM && - stream_info->runtime_num_burst_capture == 0) { - /* Configure AXI writemasters to stop immediately - * since for burst case, write masters already skip - * all frames. - */ - if (stream_info->stream_src == RDI_INTF_0 || - stream_info->stream_src == RDI_INTF_1 || - stream_info->stream_src == RDI_INTF_2) - wait_for_complete_for_this_stream = 1; - } else { - if ((camif_update != DISABLE_CAMIF_IMMEDIATELY) && - !halt && (!ext_read)) - wait_for_complete_for_this_stream = 1; - } - ISP_DBG("%s: vfe_dev %d camif_update %d halt %d wait %d\n", - __func__, vfe_dev->pdev->id, camif_update, halt, + + if (!halt && !ext_read && + !(stream_info->stream_type == BURST_STREAM && + stream_info->runtime_num_burst_capture == 0)) + wait_for_complete_for_this_stream = 1; + + ISP_DBG("%s: stream 0x%x, vfe %d camif %d halt %d wait %d\n", + __func__, + stream_info->stream_id, + vfe_dev->pdev->id, + camif_update, + halt, wait_for_complete_for_this_stream); + intf = SRC_TO_INTF(stream_info->stream_src); if (!wait_for_complete_for_this_stream || stream_info->state == INACTIVE || @@ -2821,7 +2928,7 @@ static int msm_isp_return_empty_buffer(struct vfe_device *vfe_dev, struct msm_isp_timestamp timestamp; if (!vfe_dev || !stream_info) { - pr_err("%s %d failed: vfe_dev %p stream_info %p\n", __func__, + pr_err("%s %d failed: vfe_dev %pK stream_info %pK\n", __func__, __LINE__, vfe_dev, stream_info); return -EINVAL; } @@ -2900,7 +3007,7 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, bool dual_vfe = false; if (!vfe_dev || !stream_info) { - pr_err("%s %d failed: vfe_dev %p stream_info %p\n", __func__, + pr_err("%s %d failed: vfe_dev %pK stream_info %pK\n", __func__, __LINE__, vfe_dev, stream_info); return -EINVAL; } @@ -3552,7 +3659,7 @@ void msm_isp_axi_disable_all_wm(struct vfe_device *vfe_dev) int i, j; if (!vfe_dev || !axi_data) { - pr_err("%s: error %p %p\n", __func__, vfe_dev, axi_data); + pr_err("%s: error %pK %pK\n", __func__, vfe_dev, axi_data); return; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c index 7eaffad3f9ad..03c587e2ede1 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c @@ -88,8 +88,9 @@ static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev, !dual_vfe_res->stats_data[ISP_VFE0] || !dual_vfe_res->vfe_base[ISP_VFE1] || !dual_vfe_res->stats_data[ISP_VFE1]) { - pr_err("%s:%d error vfe0 %p %p vfe1 %p %p\n", __func__, - __LINE__, dual_vfe_res->vfe_base[ISP_VFE0], + pr_err("%s:%d error vfe0 %pK %pK vfe1 %pK %pK\n", + __func__, __LINE__, + dual_vfe_res->vfe_base[ISP_VFE0], dual_vfe_res->stats_data[ISP_VFE0], dual_vfe_res->vfe_base[ISP_VFE1], dual_vfe_res->stats_data[ISP_VFE1]); @@ -156,7 +157,7 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev, uint32_t stats_idx; if (!vfe_dev || !ts || !buf_event || !stream_info) { - pr_err("%s:%d failed: invalid params %p %p %p %p\n", + pr_err("%s:%d failed: invalid params %pK %pK %pK %pK\n", __func__, __LINE__, vfe_dev, ts, buf_event, stream_info); return -EINVAL; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 8a6c395e9812..dc209d744054 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -468,14 +468,14 @@ static int msm_isp_get_max_clk_rate(struct vfe_device *vfe_dev, long *rate) long round_rate = 0; if (!vfe_dev || !rate) { - pr_err("%s:%d failed: vfe_dev %p rate %p\n", __func__, __LINE__, - vfe_dev, rate); + pr_err("%s:%d failed: vfe_dev %pK rate %pK\n", __func__, + __LINE__, vfe_dev, rate); return -EINVAL; } *rate = 0; if (!vfe_dev->hw_info) { - pr_err("%s:%d failed: vfe_dev->hw_info %p\n", __func__, + pr_err("%s:%d failed: vfe_dev->hw_info %pK\n", __func__, __LINE__, vfe_dev->hw_info); return -EINVAL; } @@ -505,13 +505,13 @@ static int msm_isp_get_clk_rates(struct vfe_device *vfe_dev, int32_t rc = 0; uint32_t svs = 0, nominal = 0, turbo = 0; if (!vfe_dev || !rates) { - pr_err("%s:%d failed: vfe_dev %p rates %p\n", __func__, + pr_err("%s:%d failed: vfe_dev %pK rates %pK\n", __func__, __LINE__, vfe_dev, rates); return -EINVAL; } if (!vfe_dev->pdev) { - pr_err("%s:%d failed: vfe_dev->pdev %p\n", __func__, + pr_err("%s:%d failed: vfe_dev->pdev %pK\n", __func__, __LINE__, vfe_dev->pdev); return -EINVAL; } @@ -519,7 +519,7 @@ static int msm_isp_get_clk_rates(struct vfe_device *vfe_dev, of_node = vfe_dev->pdev->dev.of_node; if (!of_node) { - pr_err("%s %d failed: of_node = %p\n", __func__, + pr_err("%s %d failed: of_node = %pK\n", __func__, __LINE__, of_node); return -EINVAL; } @@ -625,9 +625,7 @@ static int msm_isp_cfg_pix(struct vfe_device *vfe_dev, } pix_cfg = &input_cfg->d.pix_cfg; - if ((pix_cfg->hvx_cmd > HVX_DISABLE) && - (pix_cfg->hvx_cmd <= HVX_ROUND_TRIP)) - vfe_dev->hvx_cmd = pix_cfg->hvx_cmd; + vfe_dev->hvx_cmd = pix_cfg->hvx_cmd; vfe_dev->is_split = input_cfg->d.pix_cfg.is_split; vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock = @@ -730,7 +728,7 @@ static int msm_isp_set_dual_HW_master_slave_mode( unsigned long flags; if (!vfe_dev || !arg) { - pr_err("%s: Error! Invalid input vfe_dev %p arg %p\n", + pr_err("%s: Error! Invalid input vfe_dev %pK arg %pK\n", __func__, vfe_dev, arg); return -EINVAL; } @@ -821,7 +819,7 @@ static int msm_isp_proc_cmd_list_unlocked(struct vfe_device *vfe_dev, void *arg) struct msm_vfe_cfg_cmd_list cmd, cmd_next; if (!vfe_dev || !arg) { - pr_err("%s:%d failed: vfe_dev %p arg %p", __func__, __LINE__, + pr_err("%s:%d failed: vfe_dev %pK arg %pK", __func__, __LINE__, vfe_dev, arg); return -EINVAL; } @@ -891,7 +889,7 @@ static int msm_isp_proc_cmd_list_compat(struct vfe_device *vfe_dev, void *arg) struct msm_vfe_cfg_cmd2 current_cmd; if (!vfe_dev || !arg) { - pr_err("%s:%d failed: vfe_dev %p arg %p", __func__, __LINE__, + pr_err("%s:%d failed: vfe_dev %pK arg %pK", __func__, __LINE__, vfe_dev, arg); return -EINVAL; } @@ -948,10 +946,10 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd); if (!vfe_dev || !vfe_dev->vfe_base) { - pr_err("%s:%d failed: invalid params %p\n", + pr_err("%s:%d failed: invalid params %pK\n", __func__, __LINE__, vfe_dev); if (vfe_dev) - pr_err("%s:%d failed %p\n", __func__, + pr_err("%s:%d failed %pK\n", __func__, __LINE__, vfe_dev->vfe_base); return -EINVAL; } @@ -1136,10 +1134,10 @@ static long msm_isp_ioctl_compat(struct v4l2_subdev *sd, long rc = 0; if (!vfe_dev || !vfe_dev->vfe_base) { - pr_err("%s:%d failed: invalid params %p\n", + pr_err("%s:%d failed: invalid params %pK\n", __func__, __LINE__, vfe_dev); if (vfe_dev) - pr_err("%s:%d failed %p\n", __func__, + pr_err("%s:%d failed %pK\n", __func__, __LINE__, vfe_dev->vfe_base); return -EINVAL; } @@ -1185,13 +1183,13 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, uint32_t *cfg_data, uint32_t cmd_len) { if (!vfe_dev || !reg_cfg_cmd) { - pr_err("%s:%d failed: vfe_dev %p reg_cfg_cmd %p\n", __func__, + pr_err("%s:%d failed: vfe_dev %pK reg_cfg_cmd %pK\n", __func__, __LINE__, vfe_dev, reg_cfg_cmd); return -EINVAL; } if ((reg_cfg_cmd->cmd_type != VFE_CFG_MASK) && (!cfg_data || !cmd_len)) { - pr_err("%s:%d failed: cmd type %d cfg_data %p cmd_len %d\n", + pr_err("%s:%d failed: cmd type %d cfg_data %pK cmd_len %d\n", __func__, __LINE__, reg_cfg_cmd->cmd_type, cfg_data, cmd_len); return -EINVAL; @@ -1613,6 +1611,14 @@ int msm_isp_cal_word_per_line(uint32_t output_format, case V4L2_PIX_FMT_SGRBG10: case V4L2_PIX_FMT_SRGGB10: case V4L2_PIX_FMT_Y10: + case V4L2_PIX_FMT_SBGGR10DPCM6: + case V4L2_PIX_FMT_SGBRG10DPCM6: + case V4L2_PIX_FMT_SGRBG10DPCM6: + case V4L2_PIX_FMT_SRGGB10DPCM6: + case V4L2_PIX_FMT_SBGGR10DPCM8: + case V4L2_PIX_FMT_SGBRG10DPCM8: + case V4L2_PIX_FMT_SGRBG10DPCM8: + case V4L2_PIX_FMT_SRGGB10DPCM8: val = CAL_WORD(pixel_per_line, 5, 32); break; case V4L2_PIX_FMT_SBGGR12: @@ -1690,6 +1696,14 @@ enum msm_isp_pack_fmt msm_isp_get_pack_format(uint32_t output_format) case V4L2_PIX_FMT_SGBRG10: case V4L2_PIX_FMT_SGRBG10: case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SBGGR10DPCM6: + case V4L2_PIX_FMT_SGBRG10DPCM6: + case V4L2_PIX_FMT_SGRBG10DPCM6: + case V4L2_PIX_FMT_SRGGB10DPCM6: + case V4L2_PIX_FMT_SBGGR10DPCM8: + case V4L2_PIX_FMT_SGBRG10DPCM8: + case V4L2_PIX_FMT_SGRBG10DPCM8: + case V4L2_PIX_FMT_SRGGB10DPCM8: case V4L2_PIX_FMT_SBGGR12: case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SGRBG12: @@ -1777,6 +1791,14 @@ int msm_isp_get_bit_per_pixel(uint32_t output_format) case V4L2_PIX_FMT_SGBRG10: case V4L2_PIX_FMT_SGRBG10: case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SBGGR10DPCM6: + case V4L2_PIX_FMT_SGBRG10DPCM6: + case V4L2_PIX_FMT_SGRBG10DPCM6: + case V4L2_PIX_FMT_SRGGB10DPCM6: + case V4L2_PIX_FMT_SBGGR10DPCM8: + case V4L2_PIX_FMT_SGBRG10DPCM8: + case V4L2_PIX_FMT_SGRBG10DPCM8: + case V4L2_PIX_FMT_SRGGB10DPCM8: case V4L2_PIX_FMT_QBGGR10: case V4L2_PIX_FMT_QGBRG10: case V4L2_PIX_FMT_QGRBG10: @@ -1834,7 +1856,7 @@ static int msm_isp_process_iommu_page_fault(struct vfe_device *vfe_dev) { int rc = vfe_dev->buf_mgr->pagefault_debug_disable; - pr_err("%s:%d] VFE%d Handle Page fault! vfe_dev %p\n", __func__, + pr_err("%s:%d] VFE%d Handle Page fault! vfe_dev %pK\n", __func__, __LINE__, vfe_dev->pdev->id, vfe_dev); msm_isp_halt_send_error(vfe_dev, ISP_EVENT_IOMMU_P_FAULT); @@ -2026,7 +2048,7 @@ void msm_isp_do_tasklet(unsigned long data) uint32_t irq_status0, irq_status1, pingpong_status; if (vfe_dev->vfe_base == NULL || vfe_dev->vfe_open_cnt == 0) { - ISP_DBG("%s: VFE%d open cnt = %d, device closed(base = %p)\n", + ISP_DBG("%s: VFE%d open cnt = %d, device closed(base = %pK)\n", __func__, vfe_dev->pdev->id, vfe_dev->vfe_open_cnt, vfe_dev->vfe_base); return; @@ -2099,7 +2121,7 @@ static void msm_vfe_iommu_fault_handler(struct iommu_domain *domain, vfe_dev->page_fault_addr = iova; if (!vfe_dev->buf_mgr || !vfe_dev->buf_mgr->ops || !vfe_dev->axi_data.num_active_stream) { - pr_err("%s:%d buf_mgr %p active strms %d\n", __func__, + pr_err("%s:%d buf_mgr %pK active strms %d\n", __func__, __LINE__, vfe_dev->buf_mgr, vfe_dev->axi_data.num_active_stream); goto end; @@ -2116,7 +2138,7 @@ static void msm_vfe_iommu_fault_handler(struct iommu_domain *domain, } mutex_unlock(&vfe_dev->core_mutex); } else { - ISP_DBG("%s:%d] no token received: %p\n", + ISP_DBG("%s:%d] no token received: %pK\n", __func__, __LINE__, token); goto end; } @@ -2131,11 +2153,16 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ISP_DBG("%s open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt); - if (vfe_dev->common_data == NULL) { - pr_err("%s: Error in probe. No common_data\n", __func__); + if (vfe_dev->common_data == NULL || + vfe_dev->common_data->dual_vfe_res == NULL) { + pr_err("%s: Error in probe. No common_data or dual vfe res\n", + __func__); return -EINVAL; } + if (vfe_dev->pdev->id == ISP_VFE0) + vfe_dev->common_data->dual_vfe_res->epoch_sync_mask = 0; + mutex_lock(&vfe_dev->realtime_mutex); mutex_lock(&vfe_dev->core_mutex); @@ -2146,7 +2173,7 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } if (vfe_dev->vfe_base) { - pr_err("%s:%d invalid params cnt %d base %p\n", __func__, + pr_err("%s:%d invalid params cnt %d base %pK\n", __func__, __LINE__, vfe_dev->vfe_open_cnt, vfe_dev->vfe_base); vfe_dev->vfe_base = NULL; } 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 640379de1ac5..abfae4ffa600 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c @@ -1292,7 +1292,7 @@ static int msm_ispif_set_vfe_info(struct ispif_device *ispif, { if (!vfe_info || (vfe_info->num_vfe == 0) || (vfe_info->num_vfe > ispif->hw_num_isps)) { - pr_err("Invalid VFE info: %p %d\n", vfe_info, + pr_err("Invalid VFE info: %pK %d\n", vfe_info, (vfe_info ? vfe_info->num_vfe : 0)); return -EINVAL; } @@ -1327,7 +1327,7 @@ static int msm_ispif_init(struct ispif_device *ispif, if (ispif->csid_version >= CSID_VERSION_V30) { if (!ispif->clk_mux_mem || !ispif->clk_mux_io) { - pr_err("%s csi clk mux mem %p io %p\n", __func__, + pr_err("%s csi clk mux mem %pK io %pK\n", __func__, ispif->clk_mux_mem, ispif->clk_mux_io); rc = -ENOMEM; return rc; diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c index 9339029dbc0f..071ce0a41ed9 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -805,7 +805,7 @@ void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p, new_data = hw_cmd_p->data & hw_cmd_p->mask; new_data |= old_data; - JPEG_DBG("%s:%d] %p %08x\n", __func__, __LINE__, + JPEG_DBG("%s:%d] %pK %08x\n", __func__, __LINE__, paddr, new_data); msm_camera_io_w(new_data, paddr); } @@ -908,7 +908,7 @@ void msm_jpeg_io_dump(void *base, int size) int i; u32 *p = (u32 *) addr; u32 data; - JPEG_DBG_HIGH("%s:%d] %p %d", __func__, __LINE__, addr, size); + JPEG_DBG_HIGH("%s:%d] %pK %d", __func__, __LINE__, addr, size); line_str[0] = '\0'; p_str = line_str; for (i = 0; i < size/4; i++) { diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c index e076d356d112..266a5a6be2a2 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c @@ -210,7 +210,7 @@ static int32_t msm_jpeg_set_init_dt_parms(struct msm_jpeg_device *pgmn_dev, return -EINVAL; } for (i = 0; i < dt_count; i = i + 2) { - JPEG_DBG("%s:%d] %p %08x\n", + JPEG_DBG("%s:%d] %pK %08x\n", __func__, __LINE__, base + dt_reg_settings[i], dt_reg_settings[i + 1]); diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c index 2e2841aed1a2..d27f56a9ad65 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c @@ -754,7 +754,7 @@ int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev) __LINE__, rc); goto platform_init_fail; } - JPEG_DBG("%s:%d] platform resources - base %p, irq %d\n", + JPEG_DBG("%s:%d] platform resources - base %pK, irq %d\n", __func__, __LINE__, pgmn_dev->base, (int)pgmn_dev->jpeg_irq_res->start); msm_jpeg_q_cleanup(&pgmn_dev->evt_q); diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c index 41086936a0b1..f3ceaad21bf5 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c @@ -93,7 +93,7 @@ static inline u32 msm_jpegdma_hw_read_reg(struct msm_jpegdma_device *dma, static inline void msm_jpegdma_hw_write_reg(struct msm_jpegdma_device *dma, enum msm_jpegdma_mem_resources base_idx, u32 reg, u32 value) { - pr_debug("%s:%d]%p %08x\n", __func__, __LINE__, + pr_debug("%s:%d]%pK %08x\n", __func__, __LINE__, dma->iomem_base[base_idx] + reg, value); msm_camera_io_w(value, dma->iomem_base[base_idx] + reg); 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 f7246f2bc192..0e4a453902aa 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 @@ -248,7 +248,7 @@ static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id, break; } if (WARN_ON(vb2_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; @@ -290,7 +290,7 @@ static int msm_vb2_buf_done(struct vb2_buffer *vb, int session_id, break; } if (WARN_ON(vb2_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 55fc18e45068..3ee49dba555d 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 @@ -148,7 +148,7 @@ void msm_cpp_vbif_register_error_handler(void *dev, int (*client_vbif_error_handler)(void *, uint32_t)) { if (dev == NULL || client >= VBIF_CLIENT_MAX) { - pr_err("%s: Fail to register handler! dev = %p, client %d\n", + pr_err("%s: Fail to register handler! dev = %pK,client %d\n", __func__, dev, client); return; } @@ -1054,7 +1054,7 @@ int cpp_vbif_error_handler(void *dev, uint32_t vbif_error) struct cpp_device *cpp_dev = NULL; if (dev == NULL || vbif_error >= CPP_VBIF_ERROR_MAX) { - pr_err("failed: dev %p, vbif error %d\n", dev, vbif_error); + pr_err("failed: dev %pK,vbif error %d\n", dev, vbif_error); return -EINVAL; } @@ -1083,13 +1083,13 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) CPP_DBG("E\n"); if (!sd || !fh) { - pr_err("Wrong input parameters sd %p fh %p!", + pr_err("Wrong input parameters sd %pK fh %pK!", sd, fh); return -EINVAL; } cpp_dev = v4l2_get_subdevdata(sd); if (!cpp_dev) { - pr_err("failed: cpp_dev %p\n", cpp_dev); + pr_err("failed: cpp_dev %pK\n", cpp_dev); return -EINVAL; } mutex_lock(&cpp_dev->mutex); @@ -1112,7 +1112,7 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return -ENODEV; } - CPP_DBG("open %d %p\n", i, &fh->vfh); + CPP_DBG("open %d %pK\n", i, &fh->vfh); cpp_dev->cpp_open_cnt++; if (cpp_dev->cpp_open_cnt == 1) { rc = cpp_init_hardware(cpp_dev); @@ -1158,7 +1158,7 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) cpp_dev = v4l2_get_subdevdata(sd); if (!cpp_dev) { - pr_err("failed: cpp_dev %p\n", cpp_dev); + pr_err("failed: cpp_dev %pK\n", cpp_dev); return -EINVAL; } @@ -1446,7 +1446,7 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) mutex_lock(&cpp_dev->mutex); if (!work || (cpp_timer.data.cpp_dev->state != CPP_STATE_ACTIVE)) { - pr_err("Invalid work:%p or state:%d\n", work, + pr_err("Invalid work:%pK or state:%d\n", work, cpp_timer.data.cpp_dev->state); /* Do not flush queue here as it is not a fatal error */ goto end; @@ -2512,7 +2512,7 @@ static int msm_cpp_copy_from_ioctl_ptr(void *dst_ptr, { int ret; if ((ioctl_ptr->ioctl_ptr == NULL) || (ioctl_ptr->len == 0)) { - pr_err("%s: Wrong ioctl_ptr %p / len %zu\n", __func__, + pr_err("%s: Wrong ioctl_ptr %pK / len %zu\n", __func__, ioctl_ptr, ioctl_ptr->len); return -EINVAL; } @@ -2535,7 +2535,7 @@ static int msm_cpp_copy_from_ioctl_ptr(void *dst_ptr, { int ret; if ((ioctl_ptr->ioctl_ptr == NULL) || (ioctl_ptr->len == 0)) { - pr_err("%s: Wrong ioctl_ptr %p / len %zu\n", __func__, + pr_err("%s: Wrong ioctl_ptr %pK / len %zu\n", __func__, ioctl_ptr, ioctl_ptr->len); return -EINVAL; } @@ -2607,14 +2607,14 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg, break; default: { if (ioctl_ptr == NULL) { - pr_err("Wrong ioctl_ptr %p\n", ioctl_ptr); + pr_err("Wrong ioctl_ptr %pK\n", ioctl_ptr); return -EINVAL; } *ioctl_ptr = arg; if ((*ioctl_ptr == NULL) || ((*ioctl_ptr)->ioctl_ptr == NULL)) { - pr_err("Wrong arg %p\n", arg); + pr_err("Wrong arg %pK\n", arg); return -EINVAL; } break; @@ -2631,7 +2631,7 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, int rc = 0; if (sd == NULL) { - pr_err("sd %p\n", sd); + pr_err("sd %pK\n", sd); return -EINVAL; } cpp_dev = v4l2_get_subdevdata(sd); @@ -2707,7 +2707,7 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, &cpp_dev->pdev->dev); if (rc) { dev_err(&cpp_dev->pdev->dev, - "Fail to loc blob %s dev %p, rc:%d\n", + "Fail to loc blob %s dev %pK, rc:%d\n", cpp_dev->fw_name_bin, &cpp_dev->pdev->dev, rc); kfree(cpp_dev->fw_name_bin); @@ -3170,14 +3170,15 @@ static long msm_cpp_subdev_do_ioctl( struct v4l2_fh *vfh = NULL; if ((arg == NULL) || (file == NULL)) { - pr_err("Invalid input parameters arg %p, file %p\n", arg, file); + pr_err("Invalid input parameters arg %pK, file %pK\n", + arg, file); return -EINVAL; } vdev = video_devdata(file); sd = vdev_to_v4l2_subdev(vdev); if (sd == NULL) { - pr_err("Invalid input parameter sd %p\n", sd); + pr_err("Invalid input parameter sd %pK\n", sd); return -EINVAL; } vfh = file->private_data; @@ -3451,7 +3452,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, } cpp_dev = v4l2_get_subdevdata(sd); if (!vdev || !cpp_dev) { - pr_err("Invalid vdev %p or cpp_dev %p structures!", + pr_err("Invalid vdev %pK or cpp_dev %pK structures!", vdev, cpp_dev); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c index bf4d3595ecf4..f2f1dca81f18 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c +++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c @@ -56,12 +56,12 @@ static void vpe_mem_dump(const char * const name, const void * const addr, int i; u32 *p = (u32 *) addr; u32 data; - VPE_DBG("%s: (%s) %p %d\n", __func__, name, addr, size); + VPE_DBG("%s: (%s) %pK %d\n", __func__, name, addr, size); line_str[0] = '\0'; p_str = line_str; for (i = 0; i < size/4; i++) { if (i % 4 == 0) { - snprintf(p_str, 12, "%p: ", p); + snprintf(p_str, 12, "%pK: ", p); p_str += 10; } data = *p++; @@ -614,7 +614,7 @@ static int vpe_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) goto err_mutex_unlock; } - VPE_DBG("open %d %p\n", i, &fh->vfh); + VPE_DBG("open %d %pK\n", i, &fh->vfh); vpe_dev->vpe_open_cnt++; if (vpe_dev->vpe_open_cnt == 1) { rc = vpe_init_hardware(vpe_dev); @@ -669,7 +669,7 @@ static int vpe_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return -ENODEV; } - VPE_DBG("close %d %p\n", i, &fh->vfh); + VPE_DBG("close %d %pK\n", i, &fh->vfh); vpe_dev->vpe_open_cnt--; if (vpe_dev->vpe_open_cnt == 0) { vpe_deinit_mem(vpe_dev); diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c index 0ad3d9a51f20..c33e66fdbbb5 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -583,7 +583,7 @@ static int32_t msm_actuator_move_focus( if ((a_ctrl->region_size <= 0) || (a_ctrl->region_size > MAX_ACTUATOR_REGION) || (!move_params->ringing_params)) { - pr_err("Invalid-region size = %d, ringing_params = %p\n", + pr_err("Invalid-region size = %d, ringing_params = %pK\n", a_ctrl->region_size, move_params->ringing_params); return -EFAULT; } @@ -703,7 +703,7 @@ static int32_t msm_actuator_bivcm_move_focus( if ((a_ctrl->region_size <= 0) || (a_ctrl->region_size > MAX_ACTUATOR_REGION) || (!move_params->ringing_params)) { - pr_err("Invalid-region size = %d, ringing_params = %p\n", + pr_err("Invalid-region size = %d, ringing_params = %pK\n", a_ctrl->region_size, move_params->ringing_params); return -EFAULT; } @@ -1516,7 +1516,7 @@ static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd, struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd); void __user *argp = (void __user *)arg; CDBG("Enter\n"); - CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp); + CDBG("%s:%d a_ctrl %pK argp %pK\n", __func__, __LINE__, a_ctrl, argp); switch (cmd) { case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID: return msm_actuator_get_subdev_id(a_ctrl, argp); @@ -1777,7 +1777,7 @@ static int32_t msm_actuator_i2c_probe(struct i2c_client *client, goto probe_failure; } - CDBG("client = 0x%p\n", client); + CDBG("client = 0x%pK\n", client); rc = of_property_read_u32(client->dev.of_node, "cell-index", &act_ctrl_t->subdev_id); diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index 7099d9f7d7ae..817870e7d814 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -945,7 +945,7 @@ static int32_t msm_cci_i2c_read_bytes(struct v4l2_subdev *sd, uint16_t read_bytes = 0; if (!sd || !c_ctrl) { - pr_err("%s:%d sd %p c_ctrl %p\n", __func__, + pr_err("%s:%d sd %pK c_ctrl %pK\n", __func__, __LINE__, sd, c_ctrl); return -EINVAL; } @@ -1238,7 +1238,7 @@ static int32_t msm_cci_i2c_set_sync_prms(struct v4l2_subdev *sd, cci_dev = v4l2_get_subdevdata(sd); if (!cci_dev || !c_ctrl) { - pr_err("%s:%d failed: invalid params %p %p\n", __func__, + pr_err("%s:%d failed: invalid params %pK %pK\n", __func__, __LINE__, cci_dev, c_ctrl); rc = -EINVAL; return rc; @@ -1260,7 +1260,7 @@ static int32_t msm_cci_init(struct v4l2_subdev *sd, cci_dev = v4l2_get_subdevdata(sd); if (!cci_dev || !c_ctrl) { - pr_err("%s:%d failed: invalid params %p %p\n", __func__, + pr_err("%s:%d failed: invalid params %pK %pK\n", __func__, __LINE__, cci_dev, c_ctrl); rc = -EINVAL; return rc; @@ -1539,7 +1539,7 @@ static int32_t msm_cci_write(struct v4l2_subdev *sd, cci_dev = v4l2_get_subdevdata(sd); if (!cci_dev || !c_ctrl) { - pr_err("%s:%d failed: invalid params %p %p\n", __func__, + pr_err("%s:%d failed: invalid params %pK %pK\n", __func__, __LINE__, cci_dev, c_ctrl); rc = -EINVAL; return rc; @@ -1984,7 +1984,7 @@ static int msm_cci_probe(struct platform_device *pdev) { struct cci_device *new_cci_dev; int rc = 0, i = 0; - CDBG("%s: pdev %p device id = %d\n", __func__, pdev, pdev->id); + CDBG("%s: pdev %pK device id = %d\n", __func__, pdev, pdev->id); new_cci_dev = kzalloc(sizeof(struct cci_device), GFP_KERNEL); if (!new_cci_dev) { pr_err("%s: no enough memory\n", __func__); @@ -1996,7 +1996,7 @@ static int msm_cci_probe(struct platform_device *pdev) ARRAY_SIZE(new_cci_dev->msm_sd.sd.name), "msm_cci"); v4l2_set_subdevdata(&new_cci_dev->msm_sd.sd, new_cci_dev); platform_set_drvdata(pdev, &new_cci_dev->msm_sd.sd); - CDBG("%s sd %p\n", __func__, &new_cci_dev->msm_sd.sd); + CDBG("%s sd %pK\n", __func__, &new_cci_dev->msm_sd.sd); if (pdev->dev.of_node) of_property_read_u32((&pdev->dev)->of_node, "cell-index", &pdev->id); @@ -2071,7 +2071,7 @@ static int msm_cci_probe(struct platform_device *pdev) if (!new_cci_dev->write_wq[i]) pr_err("Failed to create write wq\n"); } - CDBG("%s cci subdev %p\n", __func__, &new_cci_dev->msm_sd.sd); + CDBG("%s cci subdev %pK\n", __func__, &new_cci_dev->msm_sd.sd); CDBG("%s line %d\n", __func__, __LINE__); return 0; diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c index ef07a540bbe2..46e859464acb 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c @@ -265,7 +265,7 @@ static int msm_csid_config(struct csid_device *csid_dev, void __iomem *csidbase; csidbase = csid_dev->base; if (!csidbase || !csid_params) { - pr_err("%s:%d csidbase %p, csid params %p\n", __func__, + pr_err("%s:%d csidbase %pK, csid params %pK\n", __func__, __LINE__, csidbase, csid_params); return -EINVAL; } @@ -651,7 +651,7 @@ static int32_t msm_csid_cmd(struct csid_device *csid_dev, void __user *arg) struct csid_cfg_data *cdata = (struct csid_cfg_data *)arg; if (!csid_dev || !cdata) { - pr_err("%s:%d csid_dev %p, cdata %p\n", __func__, __LINE__, + pr_err("%s:%d csid_dev %pK, cdata %pK\n", __func__, __LINE__, csid_dev, cdata); return -EINVAL; } @@ -792,7 +792,7 @@ static int32_t msm_csid_cmd32(struct csid_device *csid_dev, void __user *arg) cdata = &local_arg; if (!csid_dev || !cdata) { - pr_err("%s:%d csid_dev %p, cdata %p\n", __func__, __LINE__, + pr_err("%s:%d csid_dev %pK, cdata %pK\n", __func__, __LINE__, csid_dev, cdata); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c index cc8eed39701d..7bdaf67ccb25 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c @@ -46,7 +46,7 @@ #define CSI_3PHASE_HW 1 #define MAX_LANES 4 #define CLOCK_OFFSET 0x700 -#define CSIPHY_SOF_DEBUG_COUNT 3 +#define CSIPHY_SOF_DEBUG_COUNT 2 #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) @@ -497,7 +497,7 @@ static int msm_csiphy_lane_config(struct csiphy_device *csiphy_dev, val |= csiphy_params->csid_core; } msm_camera_io_w(val, csiphy_dev->clk_mux_base); - CDBG("%s clk mux addr %p val 0x%x\n", __func__, + CDBG("%s clk mux addr %pK val 0x%x\n", __func__, csiphy_dev->clk_mux_base, val); /* ensure write is done */ mb(); @@ -623,6 +623,47 @@ static int msm_csiphy_lane_config(struct csiphy_device *csiphy_dev, return rc; } +void msm_csiphy_disable_irq( + struct csiphy_device *csiphy_dev) +{ + void __iomem *csiphybase; + + csiphybase = csiphy_dev->base; + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl11.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl12.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl13.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl14.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl15.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl16.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl17.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl18.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl19.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl20.addr); + msm_camera_io_w(0, + csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl21.addr); +} + static irqreturn_t msm_csiphy_irq(int irq_num, void *data) { uint32_t irq; @@ -632,8 +673,10 @@ static irqreturn_t msm_csiphy_irq(int irq_num, void *data) if (csiphy_dev->csiphy_sof_debug == SOF_DEBUG_ENABLE) { if (csiphy_dev->csiphy_sof_debug_count < CSIPHY_SOF_DEBUG_COUNT) csiphy_dev->csiphy_sof_debug_count++; - else + else { + msm_csiphy_disable_irq(csiphy_dev); return IRQ_HANDLED; + } } for (i = 0; i < csiphy_dev->num_irq_registers; i++) { @@ -881,7 +924,7 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) mipi_csiphy_glbl_pwr_cfg_addr); } else { if (!csi_lane_params) { - pr_err("%s:%d failed: csi_lane_params %p\n", __func__, + pr_err("%s:%d failed: csi_lane_params %pK\n", __func__, __LINE__, csi_lane_params); return -EINVAL; } @@ -987,7 +1030,7 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) mipi_csiphy_glbl_pwr_cfg_addr); } else { if (!csi_lane_params) { - pr_err("%s:%d failed: csi_lane_params %p\n", __func__, + pr_err("%s:%d failed: csi_lane_params %pK\n", __func__, __LINE__, csi_lane_params); return -EINVAL; } @@ -1027,7 +1070,6 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) mipi_csiphy_glbl_pwr_cfg_addr); } if (csiphy_dev->csiphy_sof_debug == SOF_DEBUG_ENABLE) { - csiphy_dev->csiphy_sof_debug = SOF_DEBUG_DISABLE; rc = msm_camera_enable_irq(csiphy_dev->irq, false); } diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c index 8e5064637f73..c9f2c8c63df8 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c @@ -696,7 +696,7 @@ static long msm_eeprom_subdev_ioctl(struct v4l2_subdev *sd, struct msm_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd); void __user *argp = (void __user *)arg; CDBG("%s E\n", __func__); - CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, e_ctrl, argp); + CDBG("%s:%d a_ctrl %pK argp %pK\n", __func__, __LINE__, e_ctrl, argp); switch (cmd) { case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID: return msm_eeprom_get_subdev_id(e_ctrl, argp); @@ -795,7 +795,7 @@ static int msm_eeprom_i2c_probe(struct i2c_client *client, } e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops; e_ctrl->eeprom_mutex = &msm_eeprom_mutex; - CDBG("%s client = 0x%p\n", __func__, client); + CDBG("%s client = 0x%pK\n", __func__, client); e_ctrl->eboard_info = (struct msm_eeprom_board_info *)(id->driver_data); if (!e_ctrl->eboard_info) { pr_err("%s:%d board info NULL\n", __func__, __LINE__); @@ -1521,7 +1521,7 @@ static long msm_eeprom_subdev_ioctl32(struct v4l2_subdev *sd, void __user *argp = (void __user *)arg; CDBG("%s E\n", __func__); - CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, e_ctrl, argp); + CDBG("%s:%d a_ctrl %pK argp %pK\n", __func__, __LINE__, e_ctrl, argp); switch (cmd) { case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID: return msm_eeprom_get_subdev_id(e_ctrl, argp); 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 86d61e7a8185..84bd3fe3fb85 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 @@ -347,7 +347,7 @@ static int32_t msm_flash_i2c_release( int32_t rc = 0; if (!(&flash_ctrl->power_info) || !(&flash_ctrl->flash_i2c_client)) { - pr_err("%s:%d failed: %p %p\n", + pr_err("%s:%d failed: %pK %pK\n", __func__, __LINE__, &flash_ctrl->power_info, &flash_ctrl->flash_i2c_client); return -EINVAL; diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c index af4723520045..6b867bfb5c4a 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c @@ -34,7 +34,7 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg, /* Validate input parameters */ if (!cam_vreg || !power_setting) { - pr_err("%s:%d failed: cam_vreg %p power_setting %p", __func__, + pr_err("%s:%d failed: cam_vreg %pK power_setting %pK", __func__, __LINE__, cam_vreg, power_setting); return -EINVAL; } @@ -1327,7 +1327,7 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl, CDBG("%s:%d\n", __func__, __LINE__); if (!ctrl || !sensor_i2c_client) { - pr_err("failed ctrl %p sensor_i2c_client %p\n", ctrl, + pr_err("failed ctrl %pK sensor_i2c_client %pK\n", ctrl, sensor_i2c_client); return -EINVAL; } @@ -1549,7 +1549,7 @@ int msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl, CDBG("%s:%d\n", __func__, __LINE__); if (!ctrl || !sensor_i2c_client) { - pr_err("failed ctrl %p sensor_i2c_client %p\n", ctrl, + pr_err("failed ctrl %pK sensor_i2c_client %pK\n", ctrl, sensor_i2c_client); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c index 6a4dcdce43d6..d09e29dd4af0 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c @@ -106,7 +106,7 @@ int msm_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl) struct msm_camera_i2c_client *sensor_i2c_client; if (!s_ctrl) { - pr_err("%s:%d failed: s_ctrl %p\n", + pr_err("%s:%d failed: s_ctrl %pK\n", __func__, __LINE__, s_ctrl); return -EINVAL; } @@ -119,7 +119,7 @@ int msm_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl) sensor_i2c_client = s_ctrl->sensor_i2c_client; if (!power_info || !sensor_i2c_client) { - pr_err("%s:%d failed: power_info %p sensor_i2c_client %p\n", + pr_err("%s:%d failed: power_info %pK sensor_i2c_client %pK\n", __func__, __LINE__, power_info, sensor_i2c_client); return -EINVAL; } @@ -137,7 +137,7 @@ int msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl) uint32_t retry = 0; if (!s_ctrl) { - pr_err("%s:%d failed: %p\n", + pr_err("%s:%d failed: %pK\n", __func__, __LINE__, s_ctrl); return -EINVAL; } @@ -152,7 +152,7 @@ int msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl) if (!power_info || !sensor_i2c_client || !slave_info || !sensor_name) { - pr_err("%s:%d failed: %p %p %p %p\n", + pr_err("%s:%d failed: %pK %pK %pK %pK\n", __func__, __LINE__, power_info, sensor_i2c_client, slave_info, sensor_name); return -EINVAL; @@ -208,7 +208,7 @@ int msm_sensor_match_id(struct msm_sensor_ctrl_t *s_ctrl) const char *sensor_name; if (!s_ctrl) { - pr_err("%s:%d failed: %p\n", + pr_err("%s:%d failed: %pK\n", __func__, __LINE__, s_ctrl); return -EINVAL; } @@ -217,7 +217,7 @@ int msm_sensor_match_id(struct msm_sensor_ctrl_t *s_ctrl) sensor_name = s_ctrl->sensordata->sensor_name; if (!sensor_i2c_client || !slave_info || !sensor_name) { - pr_err("%s:%d failed: %p %p %p\n", + pr_err("%s:%d failed: %pK %pK %pK\n", __func__, __LINE__, sensor_i2c_client, slave_info, sensor_name); return -EINVAL; @@ -1450,13 +1450,13 @@ int32_t msm_sensor_init_default_params(struct msm_sensor_ctrl_t *s_ctrl) /* Validate input parameters */ if (!s_ctrl) { - pr_err("%s:%d failed: invalid params s_ctrl %p\n", __func__, + pr_err("%s:%d failed: invalid params s_ctrl %pK\n", __func__, __LINE__, s_ctrl); return -EINVAL; } if (!s_ctrl->sensor_i2c_client) { - pr_err("%s:%d failed: invalid params sensor_i2c_client %p\n", + pr_err("%s:%d failed: invalid params sensor_i2c_client %pK\n", __func__, __LINE__, s_ctrl->sensor_i2c_client); return -EINVAL; } @@ -1465,7 +1465,7 @@ int32_t msm_sensor_init_default_params(struct msm_sensor_ctrl_t *s_ctrl) s_ctrl->sensor_i2c_client->cci_client = kzalloc(sizeof( struct msm_camera_cci_client), GFP_KERNEL); if (!s_ctrl->sensor_i2c_client->cci_client) { - pr_err("%s:%d failed: no memory cci_client %p\n", __func__, + pr_err("%s:%d failed: no memory cci_client %pK\n", __func__, __LINE__, s_ctrl->sensor_i2c_client->cci_client); return -ENOMEM; } diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index 36ad8470a916..d075a6d25b3e 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -474,10 +474,8 @@ static int32_t msm_sensor_get_power_down_settings(void *setting, } /* Allocate memory for power down setting */ pd = kzalloc(sizeof(*pd) * size_down, GFP_KERNEL); - if (!pd) { - pr_err("failed: no memory power_setting %p", pd); + if (!pd) return -EFAULT; - } if (slave_info->power_setting_array.power_down_setting) { #ifdef CONFIG_COMPAT @@ -541,10 +539,8 @@ static int32_t msm_sensor_get_power_up_settings(void *setting, /* Allocate memory for power up setting */ pu = kzalloc(sizeof(*pu) * size, GFP_KERNEL); - if (!pu) { - pr_err("failed: no memory power_setting %p", pu); + if (!pu) return -ENOMEM; - } #ifdef CONFIG_COMPAT if (is_compat_task()) { @@ -655,22 +651,20 @@ int32_t msm_sensor_driver_probe(void *setting, /* Validate input parameters */ if (!setting) { - pr_err("failed: slave_info %p", setting); + pr_err("failed: slave_info %pK", setting); return -EINVAL; } /* Allocate memory for slave info */ slave_info = kzalloc(sizeof(*slave_info), GFP_KERNEL); - if (!slave_info) { - pr_err("failed: no memory slave_info %p", slave_info); + if (!slave_info) return -ENOMEM; - } #ifdef CONFIG_COMPAT if (is_compat_task()) { struct msm_camera_sensor_slave_info32 *slave_info32 = kzalloc(sizeof(*slave_info32), GFP_KERNEL); if (!slave_info32) { - pr_err("failed: no memory for slave_info32 %p\n", + pr_err("failed: no memory for slave_info32 %pK\n", slave_info32); rc = -ENOMEM; goto free_slave_info; @@ -765,13 +759,13 @@ int32_t msm_sensor_driver_probe(void *setting, /* Extract s_ctrl from camera id */ s_ctrl = g_sctrl[slave_info->camera_id]; if (!s_ctrl) { - pr_err("failed: s_ctrl %p for camera_id %d", s_ctrl, + pr_err("failed: s_ctrl %pK for camera_id %d", s_ctrl, slave_info->camera_id); rc = -EINVAL; goto free_slave_info; } - CDBG("s_ctrl[%d] %p", slave_info->camera_id, s_ctrl); + CDBG("s_ctrl[%d] %pK", slave_info->camera_id, s_ctrl); if (s_ctrl->is_probe_succeed == 1) { /* @@ -811,12 +805,9 @@ int32_t msm_sensor_driver_probe(void *setting, camera_info = kzalloc(sizeof(struct msm_camera_slave_info), GFP_KERNEL); - if (!camera_info) { - pr_err("failed: no memory slave_info %p", camera_info); + if (!camera_info) goto free_slave_info; - } - s_ctrl->sensordata->slave_info = camera_info; /* Fill sensor slave info */ @@ -828,7 +819,7 @@ int32_t msm_sensor_driver_probe(void *setting, /* Fill CCI master, slave address and CCI default params */ if (!s_ctrl->sensor_i2c_client) { - pr_err("failed: sensor_i2c_client %p", + pr_err("failed: sensor_i2c_client %pK", s_ctrl->sensor_i2c_client); rc = -EINVAL; goto free_camera_info; @@ -841,7 +832,7 @@ int32_t msm_sensor_driver_probe(void *setting, cci_client = s_ctrl->sensor_i2c_client->cci_client; if (!cci_client) { - pr_err("failed: cci_client %p", cci_client); + pr_err("failed: cci_client %pK", cci_client); goto free_camera_info; } cci_client->cci_i2c_master = s_ctrl->cci_i2c_master; @@ -1129,7 +1120,7 @@ static int32_t msm_sensor_driver_parse(struct msm_sensor_ctrl_t *s_ctrl) s_ctrl->sensor_i2c_client = kzalloc(sizeof(*s_ctrl->sensor_i2c_client), GFP_KERNEL); if (!s_ctrl->sensor_i2c_client) { - pr_err("failed: no memory sensor_i2c_client %p", + pr_err("failed: no memory sensor_i2c_client %pK", s_ctrl->sensor_i2c_client); return -ENOMEM; } @@ -1138,7 +1129,7 @@ static int32_t msm_sensor_driver_parse(struct msm_sensor_ctrl_t *s_ctrl) s_ctrl->msm_sensor_mutex = kzalloc(sizeof(*s_ctrl->msm_sensor_mutex), GFP_KERNEL); if (!s_ctrl->msm_sensor_mutex) { - pr_err("failed: no memory msm_sensor_mutex %p", + pr_err("failed: no memory msm_sensor_mutex %pK", s_ctrl->msm_sensor_mutex); goto FREE_SENSOR_I2C_CLIENT; } @@ -1167,7 +1158,7 @@ static int32_t msm_sensor_driver_parse(struct msm_sensor_ctrl_t *s_ctrl) /* Store sensor control structure in static database */ g_sctrl[s_ctrl->id] = s_ctrl; - CDBG("g_sctrl[%d] %p", s_ctrl->id, g_sctrl[s_ctrl->id]); + CDBG("g_sctrl[%d] %pK", s_ctrl->id, g_sctrl[s_ctrl->id]); return rc; @@ -1191,10 +1182,8 @@ static int32_t msm_sensor_driver_platform_probe(struct platform_device *pdev) /* Create sensor control structure */ s_ctrl = kzalloc(sizeof(*s_ctrl), GFP_KERNEL); - if (!s_ctrl) { - pr_err("failed: no memory s_ctrl %p", s_ctrl); + if (!s_ctrl) return -ENOMEM; - } platform_set_drvdata(pdev, s_ctrl); @@ -1238,10 +1227,8 @@ static int32_t msm_sensor_driver_i2c_probe(struct i2c_client *client, /* Create sensor control structure */ s_ctrl = kzalloc(sizeof(*s_ctrl), GFP_KERNEL); - if (!s_ctrl) { - pr_err("failed: no memory s_ctrl %p", s_ctrl); + if (!s_ctrl) return -ENOMEM; - } i2c_set_clientdata(client, s_ctrl); diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c index 8b6e3d3e1f78..ed0b9742bddb 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -64,7 +64,7 @@ static int32_t msm_sensor_driver_cmd(struct msm_sensor_init_t *s_init, /* Validate input parameters */ if (!s_init || !cfg) { - pr_err("failed: s_init %p cfg %p", s_init, cfg); + pr_err("failed: s_init %pK cfg %pK", s_init, cfg); return -EINVAL; } @@ -106,7 +106,7 @@ static long msm_sensor_init_subdev_ioctl(struct v4l2_subdev *sd, /* Validate input parameters */ if (!s_init) { - pr_err("failed: s_init %p", s_init); + pr_err("failed: s_init %pK", s_init); return -EINVAL; } @@ -167,12 +167,10 @@ static int __init msm_sensor_init_module(void) int ret = 0; /* Allocate memory for msm_sensor_init control structure */ s_init = kzalloc(sizeof(struct msm_sensor_init_t), GFP_KERNEL); - if (!s_init) { - pr_err("failed: no memory s_init %p", NULL); + if (!s_init) return -ENOMEM; - } - CDBG("MSM_SENSOR_INIT_MODULE %p", NULL); + CDBG("MSM_SENSOR_INIT_MODULE %pK", NULL); /* Initialize mutex */ mutex_init(&s_init->imutex); diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c index 947eeafc480c..82c9e5c5befa 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c @@ -448,7 +448,7 @@ static long msm_ois_subdev_ioctl(struct v4l2_subdev *sd, struct msm_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd); void __user *argp = (void __user *)arg; CDBG("Enter\n"); - CDBG("%s:%d o_ctrl %p argp %p\n", __func__, __LINE__, o_ctrl, argp); + CDBG("%s:%d o_ctrl %pK argp %pK\n", __func__, __LINE__, o_ctrl, argp); switch (cmd) { case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID: return msm_ois_get_subdev_id(o_ctrl, argp); @@ -553,7 +553,7 @@ static int32_t msm_ois_i2c_probe(struct i2c_client *client, goto probe_failure; } - CDBG("client = 0x%p\n", client); + CDBG("client = 0x%pK\n", client); rc = of_property_read_u32(client->dev.of_node, "cell-index", &ois_ctrl_t->subdev_id); diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c index db0ea848a964..dd9973b965f9 100644 --- a/drivers/media/platform/msm/vidc/hfi_response_handler.c +++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -108,6 +108,7 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, struct hfi_frame_size *frame_sz; struct hfi_profile_level *profile_level; struct hfi_bit_depth *pixel_depth; + struct hfi_pic_struct *pic_struct; u8 *data_ptr; int prop_id; enum msm_vidc_pixel_depth luma_bit_depth, chroma_bit_depth; @@ -193,6 +194,17 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, chroma_bit_depth); data_ptr += sizeof(struct hfi_bit_depth); break; + case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: + data_ptr = data_ptr + sizeof(u32); + pic_struct = (struct hfi_pic_struct *) data_ptr; + event_notify.pic_struct = + pic_struct->progressive_only; + dprintk(VIDC_DBG, + "Progressive only flag: %d\n", + pic_struct->progressive_only); + data_ptr += + sizeof(struct hfi_pic_struct); + break; default: dprintk(VIDC_ERR, "%s cmd: %#x not supported\n", diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 6f58437368f3..2ad0a7349de8 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -3015,17 +3015,8 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) atomic_inc(&inst->seq_hdr_reqs); break; case V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME: - if (ctrl->val < inst->capability.ltr_count.min || - ctrl->val >= inst->capability.ltr_count.max) { - dprintk(VIDC_ERR, - "Error setting useltr %d range: [%d,%d)\n", - ctrl->val, inst->capability.ltr_count.min, - inst->capability.ltr_count.max); - rc = -ENOTSUPP; - break; - } property_id = HAL_CONFIG_VENC_USELTRFRAME; - use_ltr.ref_ltr = (0x1 << ctrl->val); + use_ltr.ref_ltr = ctrl->val; use_ltr.use_constraint = false; use_ltr.frames = 0; pdata = &use_ltr; diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 4ed5bff2d0a7..f03693096311 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -1176,6 +1176,7 @@ void *msm_vidc_open(int core_id, int session_type) inst->core = core; inst->bit_depth = MSM_VIDC_BIT_DEPTH_8; inst->instant_bitrate = 0; + inst->pic_struct = MSM_VIDC_PIC_STRUCT_PROGRESSIVE; for (i = SESSION_MSG_INDEX(SESSION_MSG_START); i <= SESSION_MSG_INDEX(SESSION_MSG_END); i++) { diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index e889a6046eca..120f651ecf0f 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -44,8 +44,6 @@ V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT #define V4L2_EVENT_RELEASE_BUFFER_REFERENCE \ V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE -#define V4L2_EVENT_SEQ_BITDEPTH_CHANGED_INSUFFICIENT \ - V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT #define MAX_SUPPORTED_INSTANCES 16 @@ -1023,8 +1021,8 @@ static void handle_event_change(enum hal_command_response cmd, void *data) int event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT; struct v4l2_event seq_changed_event = {0}; int rc = 0; - bool bit_depth_changed = false; struct hfi_device *hdev; + u32 *ptr = NULL; if (!event_notify) { dprintk(VIDC_WARN, "Got an empty event from hfi\n"); @@ -1144,23 +1142,46 @@ static void handle_event_change(enum hal_command_response cmd, void *data) break; } + /* Bit depth and pic struct changed event are combined into a single + * event (insufficient event) for the userspace. Currently bitdepth + * changes is only for HEVC and interlaced support is for all + * codecs except HEVC + * event data is now as follows: + * u32 *ptr = seq_changed_event.u.data; + * ptr[0] = height + * ptr[1] = width + * ptr[2] = flag to indicate bit depth or/and pic struct changed + * ptr[3] = bit depth + * ptr[4] = pic struct (progressive or interlaced) + */ + + ptr = (u32 *)seq_changed_event.u.data; + ptr[2] = 0x0; + ptr[3] = inst->bit_depth; + ptr[4] = inst->pic_struct; + + if (inst->bit_depth != event_notify->bit_depth) { + inst->bit_depth = event_notify->bit_depth; + ptr[2] |= V4L2_EVENT_BITDEPTH_FLAG; + ptr[3] = inst->bit_depth; + event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT; + dprintk(VIDC_DBG, + "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT due to bit-depth change\n"); + } + + if (inst->pic_struct != event_notify->pic_struct) { + inst->pic_struct = event_notify->pic_struct; + event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT; + ptr[2] |= V4L2_EVENT_PICSTRUCT_FLAG; + ptr[4] = inst->pic_struct; + dprintk(VIDC_DBG, + "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT due to pic-struct change\n"); + } + if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) { dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT\n"); inst->reconfig_height = event_notify->height; inst->reconfig_width = event_notify->width; - - if (inst->bit_depth != event_notify->bit_depth) { - inst->bit_depth = event_notify->bit_depth; - bit_depth_changed = true; - seq_changed_event.u.data[0] = inst->bit_depth; - event = V4L2_EVENT_SEQ_BITDEPTH_CHANGED_INSUFFICIENT; - dprintk(VIDC_DBG, - "V4L2_EVENT_SEQ_BITDEPTH_CHANGED_INSUFFICIENT\n"); - } else { - dprintk(VIDC_DBG, - "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT\n"); - } - inst->in_reconfig = true; } else { dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_SUFFICIENT\n"); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 113c6ccb326b..19459647abbe 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -290,6 +290,7 @@ struct msm_vidc_inst { unsigned long instant_bitrate; u32 buffers_held_in_driver; atomic_t in_flush; + u32 pic_struct; }; extern struct msm_vidc_drv *vidc_driver; diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 5118fb43699f..64a4d9717901 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -3278,6 +3278,26 @@ exit: return; } +static void __dump_venus_debug_registers(struct venus_hfi_device *device) +{ + u32 reg; + + dprintk(VIDC_ERR, "Dumping Venus registers...\n"); + reg = __read_register(device, VENUS_VBIF_XIN_HALT_CTRL1); + dprintk(VIDC_ERR, "VENUS_VBIF_XIN_HALT_CTRL1: 0x%x\n", reg); + + reg = __read_register(device, + VIDC_VENUS_WRAPPER_MMCC_VENUS0_POWER_STATUS); + dprintk(VIDC_ERR, + "VIDC_VENUS_WRAPPER_MMCC_VENUS0_POWER_STATUS: 0x%x\n", reg); + + reg = __read_register(device, VIDC_WRAPPER_CPU_STATUS); + dprintk(VIDC_ERR, "VIDC_WRAPPER_CPU_STATUS: 0x%x\n", reg); + + reg = __read_register(device, VIDC_CPU_CS_SCIACMDARG0); + dprintk(VIDC_ERR, "VIDC_CPU_CS_SCIACMDARG0: 0x%x\n", reg); +} + static void __process_sys_error(struct venus_hfi_device *device) { struct hfi_sfr_struct *vsfr = NULL; @@ -3393,6 +3413,7 @@ static int __response_handler(struct venus_hfi_device *device) dprintk(VIDC_ERR, "SFR Message from FW: %s\n", vsfr->rg_data); + __dump_venus_debug_registers(device); dprintk(VIDC_ERR, "Received watchdog timeout\n"); packets[packet_count++] = info; goto exit; @@ -3417,6 +3438,7 @@ static int __response_handler(struct venus_hfi_device *device) /* Process the packet types that we're interested in */ switch (info->response_type) { case HAL_SYS_ERROR: + __dump_venus_debug_registers(device); __process_sys_error(device); break; case HAL_SYS_RELEASE_RESOURCE_DONE: diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h index dcaf9ce8d1bb..063208b8f188 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h @@ -1338,6 +1338,7 @@ struct msm_vidc_cb_event { u32 hal_event_type; ion_phys_addr_t packet_buffer; ion_phys_addr_t extra_data_buffer; + u32 pic_struct; }; struct msm_vidc_cb_data_done { diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h index 04f006c50f27..ad438d9d03af 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h @@ -291,6 +291,9 @@ struct hfi_buffer_info { (HFI_PROPERTY_PARAM_VDEC_COMMON_START + 0x003) #define HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH \ (HFI_PROPERTY_PARAM_VDEC_COMMON_START + 0x007) +#define HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT \ + (HFI_PROPERTY_PARAM_VDEC_COMMON_START + 0x009) + #define HFI_PROPERTY_CONFIG_VDEC_COMMON_START \ (HFI_DOMAIN_BASE_VDEC + HFI_ARCH_COMMON_OFFSET + 0x4000) @@ -419,6 +422,10 @@ struct hfi_buffer_info { #define HFI_PROPERTY_CONFIG_VPE_OPERATIONS \ (HFI_PROPERTY_CONFIG_VPE_COMMON_START + 0x002) +struct hfi_pic_struct { + u32 progressive_only; +}; + struct hfi_bitrate { u32 bit_rate; u32 layer_id; diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h index ae84cfff2a38..35a68de3a1a2 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.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 @@ -139,6 +139,7 @@ #define VIDC_VBIF_AT_OLD_HIGH (VIDC_VBIF_BASE_OFFS + 0xC08) #define VIDC_VBIF_AT_NEW_BASE (VIDC_VBIF_BASE_OFFS + 0xC10) #define VIDC_VBIF_AT_NEW_HIGH (VIDC_VBIF_BASE_OFFS + 0xC18) +#define VENUS_VBIF_XIN_HALT_CTRL1 (VIDC_VBIF_BASE_OFFS + 0x204) #define VENUS_VBIF_AXI_HALT_CTRL0 (VIDC_VBIF_BASE_OFFS + 0x208) #define VENUS_VBIF_AXI_HALT_CTRL1 (VIDC_VBIF_BASE_OFFS + 0x20C) @@ -150,6 +151,8 @@ (VIDC_WRAPPER_BASE_OFFS + 0x20) #define VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL \ (VIDC_WRAPPER_BASE_OFFS + 0x24) +#define VIDC_VENUS_WRAPPER_MMCC_VENUS0_POWER_STATUS \ + (VIDC_WRAPPER_BASE_OFFS + 0x44) #define VIDC_CTRL_INIT 0x000D2048 #define VIDC_CTRL_INIT_RESERVED_BITS31_1__M 0xFFFFFFFE diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 2c3b6674a161..786cf5f55ffe 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -432,7 +432,6 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, smc_id = TZ_OS_APP_SHUTDOWN_ID; desc.arginfo = TZ_OS_APP_SHUTDOWN_ID_PARAM_ID; desc.args[0] = req->app_id; - __qseecom_reentrancy_check_if_no_app_blocked(smc_id); ret = scm_call2(smc_id, &desc); break; } @@ -2218,6 +2217,9 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data, return 0; } + __qseecom_cleanup_app(data); + __qseecom_reentrancy_check_if_no_app_blocked(TZ_OS_APP_SHUTDOWN_ID); + if (data->client.app_id > 0) { spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, @@ -2246,11 +2248,9 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data, } } - if (found_dead_app) { + if (found_dead_app) pr_warn("cleanup app_id %d(%s)\n", data->client.app_id, (char *)data->client.app_name); - __qseecom_cleanup_app(data); - } if (unload) { struct qseecom_unload_app_ireq req; @@ -2279,7 +2279,6 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data, if (resp.result == QSEOS_RESULT_SUCCESS) pr_debug("App (%d) is unloaded!!\n", data->client.app_id); - __qseecom_cleanup_app(data); if (resp.result == QSEOS_RESULT_INCOMPLETE) { ret = __qseecom_process_incomplete_cmd(data, &resp); if (ret) { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index ad857aa1d1fe..bfa6fe51445d 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -2389,9 +2389,16 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) goto out; if (mmc_can_sleepawake(host)) { + /* + * For caching host->ios to cached_ios we need to + * make sure that clocks are not gated otherwise + * cached_ios->clock will be 0. + */ + mmc_host_clk_hold(host); memcpy(&host->cached_ios, &host->ios, sizeof(host->cached_ios)); mmc_cache_card_ext_csd(host); err = mmc_sleepawake(host, true); + mmc_host_clk_release(host); } else if (!mmc_host_is_spi(host)) { err = mmc_deselect_cards(host); } diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index c1aaf0336cf2..3702e2823cc1 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -712,13 +712,26 @@ struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, int err = 0; struct ubi_ainf_peb *aeb, *tmp_aeb; - if (!list_empty(&ai->free)) { - aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list); + list_for_each_entry_safe(aeb, tmp_aeb, &ai->free, u.list) { list_del(&aeb->u.list); + if (aeb->ec == UBI_UNKNOWN) { + ubi_err(ubi, "PEB %d in freelist has unknown EC", + aeb->pnum); + aeb->ec = ai->mean_ec; + } + err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1); + if (err) { + ubi_err(ubi, "Erase failed for PEB %d in freelist", + aeb->pnum); + list_add(&aeb->u.list, &ai->erase); + continue; + } + aeb->ec += 1; dbg_bld("return free PEB %d, EC %d", aeb->pnum, aeb->ec); return aeb; } + /* * We try to erase the first physical eraseblock from the erase list * and pick it if we succeed, or try to erase the next one if not. And diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 617541e86f80..3575202c9ff3 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -1105,9 +1105,11 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, * Re-erase the PEB before using it. This should minimize any issues * from decay of charge in this block. */ - err = ubi_wl_erase_peb(ubi, pnum); - if (err) - return err; + if (ubi->wl_is_inited) { + err = ubi_wl_erase_peb(ubi, pnum); + if (err) + return err; + } err = self_check_peb_ec_hdr(ubi, pnum); if (err) @@ -1128,8 +1130,10 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, p = (char *)vid_hdr - ubi->vid_hdr_shift; err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); - if (!err) + + if (!err && ubi->wl_is_inited) ubi_wl_update_peb_sqnum(ubi, pnum, vid_hdr); + return err; } diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index fdb1931f66ed..cb0389933c45 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -598,6 +598,7 @@ struct ubi_device { char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2]; bool scrub_in_progress; atomic_t scrub_work_count; + int wl_is_inited; /* I/O sub-system's stuff */ long long flash_size; diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 22a30bbaa1bd..e3dfaa4d7eee 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1873,6 +1873,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) if (err) goto out_free; + ubi->wl_is_inited = 1; return 0; out_free: diff --git a/drivers/net/wireless/cnss/Kconfig b/drivers/net/wireless/cnss/Kconfig index 0e46da4e646e..3291f4ad6179 100644 --- a/drivers/net/wireless/cnss/Kconfig +++ b/drivers/net/wireless/cnss/Kconfig @@ -9,29 +9,6 @@ config CNSS This driver also adds support to integrate WLAN module to subsystem restart framework. -config CNSS_PCI - tristate "Flag to enable platform driver for PCIe based wifi device" - select CNSS - depends on PCI - depends on PCI_MSI - ---help--- - This module specifies whether CNSS Platform Driver supports PCI. - This flag needs to be disabled if CNSS platform Driver need to be - supported for other buses. - The Flag depends on the CNSS Platform Driver and PCI. This Flag - is used by the CLD driver to use the PCIe exported API's through - CNSS Driver. - -config CNSS_SDIO - tristate "Flag to enable platform driver for SIDO based wifi device" - select CNSS - depends on MMC_SDHCI - depends on MMC_SDHCI_MSM - ---help--- - This module specifies whether CNSS Platform Driver supports SDIO. - This flag needs to be disabled if CNSS platform Driver need to be - supported for other buses. - config CNSS_MAC_BUG bool "Enable/disable 0-4K memory initialization for QCA6174" depends on CNSS diff --git a/drivers/net/wireless/cnss/Makefile b/drivers/net/wireless/cnss/Makefile index 8f6f88524d4a..ed450da8cbfb 100644 --- a/drivers/net/wireless/cnss/Makefile +++ b/drivers/net/wireless/cnss/Makefile @@ -1,6 +1,6 @@ # Makefile for CNSS platform driver -obj-$(CONFIG_CNSS_PCI) += cnss_pci.o -obj-$(CONFIG_CNSS_SDIO) += cnss_sdio.o +obj-$(CONFIG_CNSS) += cnss_pci.o +obj-$(CONFIG_CNSS) += cnss_sdio.o obj-$(CONFIG_CNSS) += cnss_common.o obj-$(CONFIG_HTC_WLAN_NV) += custom_platdev.o diff --git a/drivers/net/wireless/cnss/cnss_common.c b/drivers/net/wireless/cnss/cnss_common.c index 428c2f6ad5e6..3709604a2df6 100644 --- a/drivers/net/wireless/cnss/cnss_common.c +++ b/drivers/net/wireless/cnss/cnss_common.c @@ -244,7 +244,7 @@ EXPORT_SYMBOL(cnss_dump_stack); enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev) { - if (!dev && !dev->bus) + if (!dev || !dev->bus) return CNSS_BUS_NONE; if (memcmp(dev->bus->name, "sdio", 4) == 0) @@ -255,122 +255,127 @@ enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev) return CNSS_BUS_NONE; } -#ifdef CONFIG_CNSS_SDIO int cnss_common_request_bus_bandwidth(struct device *dev, int bandwidth) { - if (CNSS_BUS_SDIO == cnss_get_dev_bus_type(dev)) - return cnss_sdio_request_bus_bandwidth(bandwidth); - else - return 0; -} -EXPORT_SYMBOL(cnss_common_request_bus_bandwidth); - -void *cnss_common_get_virt_ramdump_mem(struct device *dev, unsigned long *size) -{ - if (CNSS_BUS_SDIO == cnss_get_dev_bus_type(dev)) - return cnss_sdio_get_virt_ramdump_mem(size); - else - return NULL; -} -EXPORT_SYMBOL(cnss_common_get_virt_ramdump_mem); - -void cnss_common_device_self_recovery(struct device *dev) -{ - if (CNSS_BUS_SDIO == cnss_get_dev_bus_type(dev)) - cnss_sdio_device_self_recovery(); -} -EXPORT_SYMBOL(cnss_common_device_self_recovery); - -void cnss_common_schedule_recovery_work(struct device *dev) -{ - if (CNSS_BUS_SDIO == cnss_get_dev_bus_type(dev)) - cnss_sdio_schedule_recovery_work(); -} -EXPORT_SYMBOL(cnss_common_schedule_recovery_work); - -void cnss_common_device_crashed(struct device *dev) -{ - if (CNSS_BUS_SDIO == cnss_get_dev_bus_type(dev)) - cnss_sdio_device_crashed(); -} -EXPORT_SYMBOL(cnss_common_device_crashed); - -u8 *cnss_common_get_wlan_mac_address(struct device *dev, uint32_t *num) -{ - if (CNSS_BUS_SDIO == cnss_get_dev_bus_type(dev)) - return cnss_sdio_get_wlan_mac_address(num); - else - return NULL; -} -EXPORT_SYMBOL(cnss_common_get_wlan_mac_address); - -int cnss_common_set_wlan_mac_address( - struct device *dev, const u8 *in, uint32_t len) -{ - if (CNSS_BUS_SDIO == cnss_get_dev_bus_type(dev)) - return cnss_sdio_set_wlan_mac_address(in, len); - else - return -EINVAL; -} -EXPORT_SYMBOL(cnss_common_set_wlan_mac_address); -#endif + int ret; + + switch (cnss_get_dev_bus_type(dev)) { + case CNSS_BUS_SDIO: + ret = cnss_sdio_request_bus_bandwidth(bandwidth); + break; + case CNSS_BUS_PCI: + ret = cnss_pci_request_bus_bandwidth(bandwidth); + break; + default: + pr_debug("%s: Invalid device type\n", __func__); + ret = -EINVAL; + break; + } -#ifdef CONFIG_CNSS_PCI -int cnss_common_request_bus_bandwidth(struct device *dev, int bandwidth) -{ - if (CNSS_BUS_PCI == cnss_get_dev_bus_type(dev)) - return cnss_pci_request_bus_bandwidth(bandwidth); - else - return 0; + return ret; } EXPORT_SYMBOL(cnss_common_request_bus_bandwidth); void *cnss_common_get_virt_ramdump_mem(struct device *dev, unsigned long *size) { - if (CNSS_BUS_PCI == cnss_get_dev_bus_type(dev)) + switch (cnss_get_dev_bus_type(dev)) { + case CNSS_BUS_SDIO: + return cnss_sdio_get_virt_ramdump_mem(size); + case CNSS_BUS_PCI: return cnss_pci_get_virt_ramdump_mem(size); - else + default: + pr_debug("%s: Invalid device type\n", __func__); return NULL; + } } EXPORT_SYMBOL(cnss_common_get_virt_ramdump_mem); void cnss_common_device_self_recovery(struct device *dev) { - if (CNSS_BUS_PCI == cnss_get_dev_bus_type(dev)) + switch (cnss_get_dev_bus_type(dev)) { + case CNSS_BUS_SDIO: + cnss_sdio_device_self_recovery(); + break; + case CNSS_BUS_PCI: cnss_pci_device_self_recovery(); + break; + default: + pr_debug("%s: Invalid device type\n", __func__); + break; + } } EXPORT_SYMBOL(cnss_common_device_self_recovery); void cnss_common_schedule_recovery_work(struct device *dev) { - if (CNSS_BUS_PCI == cnss_get_dev_bus_type(dev)) + switch (cnss_get_dev_bus_type(dev)) { + case CNSS_BUS_SDIO: + cnss_sdio_schedule_recovery_work(); + break; + case CNSS_BUS_PCI: cnss_pci_schedule_recovery_work(); + break; + default: + pr_debug("%s: Invalid device type\n", __func__); + break; + } } EXPORT_SYMBOL(cnss_common_schedule_recovery_work); void cnss_common_device_crashed(struct device *dev) { - if (CNSS_BUS_PCI == cnss_get_dev_bus_type(dev)) + switch (cnss_get_dev_bus_type(dev)) { + case CNSS_BUS_SDIO: + cnss_sdio_device_crashed(); + break; + case CNSS_BUS_PCI: cnss_pci_device_crashed(); + break; + default: + pr_debug("%s: Invalid device type\n", __func__); + break; + } } EXPORT_SYMBOL(cnss_common_device_crashed); u8 *cnss_common_get_wlan_mac_address(struct device *dev, uint32_t *num) { - if (CNSS_BUS_PCI == cnss_get_dev_bus_type(dev)) - return cnss_pci_get_wlan_mac_address(num); - else - return NULL; + u8 *ret; + + switch (cnss_get_dev_bus_type(dev)) { + case CNSS_BUS_SDIO: + ret = cnss_sdio_get_wlan_mac_address(num); + break; + case CNSS_BUS_PCI: + ret = cnss_pci_get_wlan_mac_address(num); + break; + default: + pr_debug("%s: Invalid device type\n", __func__); + ret = NULL; + break; + } + return ret; } EXPORT_SYMBOL(cnss_common_get_wlan_mac_address); int cnss_common_set_wlan_mac_address( struct device *dev, const u8 *in, uint32_t len) { - if (CNSS_BUS_PCI == cnss_get_dev_bus_type(dev)) - return cnss_pcie_set_wlan_mac_address(in, len); - else - return -EINVAL; + int ret; + + switch (cnss_get_dev_bus_type(dev)) { + case CNSS_BUS_SDIO: + ret = cnss_sdio_set_wlan_mac_address(in, len); + break; + case CNSS_BUS_PCI: + ret = cnss_pcie_set_wlan_mac_address(in, len); + break; + default: + pr_debug("%s: Invalid device type\n", __func__); + ret = -EINVAL; + break; + } + + return ret; } EXPORT_SYMBOL(cnss_common_set_wlan_mac_address); -#endif diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index 68aa612e9c4c..a9f553fe6b52 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -41,11 +41,7 @@ #include <linux/scatterlist.h> #include <linux/log2.h> #include <linux/etherdevice.h> -#ifdef CONFIG_PCI_MSM #include <linux/msm_pcie.h> -#else -#include <mach/msm_pcie.h> -#endif #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/subsystem_notif.h> #include <soc/qcom/ramdump.h> @@ -1518,6 +1514,95 @@ static void cnss_smmu_remove(struct device *dev) penv->smmu_mapping = NULL; } +#ifdef CONFIG_PCI_MSM +struct pci_saved_state *cnss_pci_store_saved_state(struct pci_dev *dev) +{ + return pci_store_saved_state(dev); +} + +int cnss_msm_pcie_pm_control( + enum msm_pcie_pm_opt pm_opt, u32 bus_num, + struct pci_dev *pdev, u32 options) +{ + return msm_pcie_pm_control(pm_opt, bus_num, pdev, NULL, options); +} + +int cnss_pci_load_and_free_saved_state( + struct pci_dev *dev, struct pci_saved_state **state) +{ + return pci_load_and_free_saved_state(dev, state); +} + +int cnss_msm_pcie_shadow_control(struct pci_dev *dev, bool enable) +{ + return msm_pcie_shadow_control(dev, enable); +} + +int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg) +{ + return msm_pcie_deregister_event(reg); +} + +int cnss_msm_pcie_recover_config(struct pci_dev *dev) +{ + return msm_pcie_recover_config(dev); +} + +int cnss_msm_pcie_register_event(struct msm_pcie_register_event *reg) +{ + return msm_pcie_register_event(reg); +} + +int cnss_msm_pcie_enumerate(u32 rc_idx) +{ + return msm_pcie_enumerate(rc_idx); +} +#else /* !defined CONFIG_PCI_MSM */ + +struct pci_saved_state *cnss_pci_store_saved_state(struct pci_dev *dev) +{ + return NULL; +} + +int cnss_msm_pcie_pm_control( + enum msm_pcie_pm_opt pm_opt, u32 bus_num, + struct pci_dev *pdev, u32 options) +{ + return -ENODEV; +} + +int cnss_pci_load_and_free_saved_state( + struct pci_dev *dev, struct pci_saved_state **state) +{ + return 0; +} + +int cnss_msm_pcie_shadow_control(struct pci_dev *dev, bool enable) +{ + return -ENODEV; +} + +int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg) +{ + return -ENODEV; +} + +int cnss_msm_pcie_recover_config(struct pci_dev *dev) +{ + return -ENODEV; +} + +int cnss_msm_pcie_register_event(struct msm_pcie_register_event *reg) +{ + return -ENODEV; +} + +int cnss_msm_pcie_enumerate(u32 rc_idx) +{ + return -EPROBE_DEFER; +} +#endif + static int cnss_wlan_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -1570,11 +1655,11 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev, if (penv->pcie_link_state) { pci_save_state(pdev); - penv->saved_state = pci_store_saved_state(pdev); + penv->saved_state = cnss_pci_store_saved_state(pdev); - ret = msm_pcie_pm_control(MSM_PCIE_SUSPEND, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS); + ret = cnss_msm_pcie_pm_control( + MSM_PCIE_SUSPEND, cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS); if (ret) { pr_err("Failed to shutdown PCIe link\n"); goto err_pcie_suspend; @@ -1674,7 +1759,7 @@ static int cnss_wlan_pci_suspend(struct device *dev) if (penv->pcie_link_state) { pci_save_state(pdev); - penv->saved_state = pci_store_saved_state(pdev); + penv->saved_state = cnss_pci_store_saved_state(pdev); } } penv->monitor_wake_intr = false; @@ -1698,8 +1783,8 @@ static int cnss_wlan_pci_resume(struct device *dev) if (wdriver->resume && !penv->pcie_link_down_ind) { if (penv->saved_state) - pci_load_and_free_saved_state(pdev, - &penv->saved_state); + cnss_pci_load_and_free_saved_state( + pdev, &penv->saved_state); pci_restore_state(pdev); ret = wdriver->resume(pdev); @@ -1867,11 +1952,11 @@ void cnss_pci_recovery_work_handler(struct work_struct *recovery) cnss_pci_device_self_recovery(); } -DECLARE_WORK(recovery_work, cnss_pci_recovery_work_handler); +DECLARE_WORK(cnss_pci_recovery_work, cnss_pci_recovery_work_handler); void cnss_schedule_recovery_work(void) { - schedule_work(&recovery_work); + schedule_work(&cnss_pci_recovery_work); } EXPORT_SYMBOL(cnss_schedule_recovery_work); @@ -1898,7 +1983,7 @@ void cnss_pci_events_cb(struct msm_pcie_notify *notify) spin_unlock_irqrestore(&pci_link_down_lock, flags); pr_err("PCI link down, schedule recovery\n"); - schedule_work(&recovery_work); + schedule_work(&cnss_pci_recovery_work); break; case MSM_PCIE_EVENT_WAKEUP: @@ -1932,13 +2017,13 @@ void cnss_wlan_pci_link_down(void) spin_unlock_irqrestore(&pci_link_down_lock, flags); pr_err("PCI link down detected by host driver, schedule recovery!\n"); - schedule_work(&recovery_work); + schedule_work(&cnss_pci_recovery_work); } EXPORT_SYMBOL(cnss_wlan_pci_link_down); int cnss_pcie_shadow_control(struct pci_dev *dev, bool enable) { - return msm_pcie_shadow_control(dev, enable); + return cnss_msm_pcie_shadow_control(dev, enable); } EXPORT_SYMBOL(cnss_pcie_shadow_control); @@ -2224,14 +2309,14 @@ again: penv->event_reg.mode = MSM_PCIE_TRIGGER_CALLBACK; penv->event_reg.callback = cnss_pci_events_cb; penv->event_reg.options = MSM_PCIE_CONFIG_NO_RECOVERY; - ret = msm_pcie_register_event(&penv->event_reg); + ret = cnss_msm_pcie_register_event(&penv->event_reg); if (ret) pr_err("%s: PCIe event register failed! %d\n", __func__, ret); if (!penv->pcie_link_state && !penv->pcie_link_down_ind) { - ret = msm_pcie_pm_control(MSM_PCIE_RESUME, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS); + ret = cnss_msm_pcie_pm_control( + MSM_PCIE_RESUME, cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS); if (ret) { pr_err("PCIe link bring-up failed\n"); goto err_pcie_link_up; @@ -2239,9 +2324,9 @@ again: penv->pcie_link_state = PCIE_LINK_UP; } else if (!penv->pcie_link_state && penv->pcie_link_down_ind) { - ret = msm_pcie_pm_control(MSM_PCIE_RESUME, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS_RESUME_LINK_DOWN); + ret = cnss_msm_pcie_pm_control( + MSM_PCIE_RESUME, cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS_RESUME_LINK_DOWN); if (ret) { pr_err("PCIe link bring-up failed (link down option)\n"); @@ -2249,7 +2334,7 @@ again: } penv->pcie_link_state = PCIE_LINK_UP; - ret = msm_pcie_recover_config(pdev); + ret = cnss_msm_pcie_recover_config(pdev); if (ret) { pr_err("cnss: PCI link failed to recover\n"); goto err_pcie_link_up; @@ -2262,7 +2347,8 @@ again: if (wdrv->probe) { if (penv->saved_state) - pci_load_and_free_saved_state(pdev, &penv->saved_state); + cnss_pci_load_and_free_saved_state( + pdev, &penv->saved_state); pci_restore_state(pdev); @@ -2276,11 +2362,12 @@ again: goto err_wlan_probe; } pci_save_state(pdev); - penv->saved_state = pci_store_saved_state(pdev); - msm_pcie_deregister_event(&penv->event_reg); - msm_pcie_pm_control(MSM_PCIE_SUSPEND, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS); + penv->saved_state = cnss_pci_store_saved_state(pdev); + cnss_msm_pcie_deregister_event(&penv->event_reg); + cnss_msm_pcie_pm_control( + MSM_PCIE_SUSPEND, + cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS); penv->pcie_link_state = PCIE_LINK_DOWN; cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW); msleep(WLAN_ENABLE_DELAY); @@ -2298,14 +2385,14 @@ again: err_wlan_probe: pci_save_state(pdev); - penv->saved_state = pci_store_saved_state(pdev); + penv->saved_state = cnss_pci_store_saved_state(pdev); err_pcie_link_up: - msm_pcie_deregister_event(&penv->event_reg); + cnss_msm_pcie_deregister_event(&penv->event_reg); if (penv->pcie_link_state) { - msm_pcie_pm_control(MSM_PCIE_SUSPEND, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS); + cnss_msm_pcie_pm_control( + MSM_PCIE_SUSPEND, cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS); penv->pcie_link_state = PCIE_LINK_DOWN; } @@ -2361,24 +2448,24 @@ void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver) wcnss_prealloc_check_memory_leak(); wcnss_pre_alloc_reset(); - msm_pcie_deregister_event(&penv->event_reg); + cnss_msm_pcie_deregister_event(&penv->event_reg); if (penv->pcie_link_state && !penv->pcie_link_down_ind) { pci_save_state(pdev); - penv->saved_state = pci_store_saved_state(pdev); + penv->saved_state = cnss_pci_store_saved_state(pdev); - if (msm_pcie_pm_control(MSM_PCIE_SUSPEND, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS)) { + if (cnss_msm_pcie_pm_control( + MSM_PCIE_SUSPEND, cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS)) { pr_err("Failed to shutdown PCIe link\n"); return; } } else if (penv->pcie_link_state && penv->pcie_link_down_ind) { penv->saved_state = NULL; - if (msm_pcie_pm_control(MSM_PCIE_SUSPEND, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS_SUSPEND_LINK_DOWN)) { + if (cnss_msm_pcie_pm_control( + MSM_PCIE_SUSPEND, cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS_SUSPEND_LINK_DOWN)) { pr_err("Failed to shutdown PCIe link (with linkdown option)\n"); return; } @@ -2404,10 +2491,10 @@ int cnss_wlan_pm_control(bool vote) if (!penv || !penv->pdev) return -ENODEV; - return msm_pcie_pm_control( + return cnss_msm_pcie_pm_control( vote ? MSM_PCIE_DISABLE_PC : MSM_PCIE_ENABLE_PC, cnss_get_pci_dev_bus_number(penv->pdev), - penv->pdev, NULL, PM_OPTIONS); + penv->pdev, PM_OPTIONS); } EXPORT_SYMBOL(cnss_wlan_pm_control); #endif @@ -2426,7 +2513,7 @@ EXPORT_SYMBOL(cnss_release_pm_sem); void cnss_pci_schedule_recovery_work(void) { - schedule_work(&recovery_work); + schedule_work(&cnss_pci_recovery_work); } void *cnss_pci_get_virt_ramdump_mem(unsigned long *size) @@ -2493,9 +2580,9 @@ static int cnss_shutdown(const struct subsys_desc *subsys, bool force_stop) wdrv->shutdown(pdev); if (penv->pcie_link_state) { - if (msm_pcie_pm_control(MSM_PCIE_SUSPEND, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS_SUSPEND_LINK_DOWN)) { + if (cnss_msm_pcie_pm_control( + MSM_PCIE_SUSPEND, cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS_SUSPEND_LINK_DOWN)) { pr_debug("cnss: Failed to shutdown PCIe link!\n"); ret = -EFAULT; } @@ -2547,16 +2634,17 @@ static int cnss_powerup(const struct subsys_desc *subsys) } if (!penv->pcie_link_state) { - ret = msm_pcie_pm_control(MSM_PCIE_RESUME, + ret = cnss_msm_pcie_pm_control( + MSM_PCIE_RESUME, cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS_RESUME_LINK_DOWN); + pdev, PM_OPTIONS_RESUME_LINK_DOWN); if (ret) { pr_err("cnss: Failed to bring-up PCIe link!\n"); goto err_pcie_link_up; } penv->pcie_link_state = PCIE_LINK_UP; - ret = msm_pcie_recover_config(penv->pdev); + ret = cnss_msm_pcie_recover_config(penv->pdev); if (ret) { pr_err("cnss: PCI link failed to recover\n"); goto err_pcie_link_up; @@ -2566,8 +2654,8 @@ static int cnss_powerup(const struct subsys_desc *subsys) if (wdrv && wdrv->reinit) { if (penv->saved_state) - pci_load_and_free_saved_state(pdev, - &penv->saved_state); + cnss_pci_load_and_free_saved_state( + pdev, &penv->saved_state); pci_restore_state(pdev); @@ -2590,10 +2678,11 @@ out: err_wlan_reinit: pci_save_state(pdev); - penv->saved_state = pci_store_saved_state(pdev); - msm_pcie_pm_control(MSM_PCIE_SUSPEND, + penv->saved_state = cnss_pci_store_saved_state(pdev); + cnss_msm_pcie_pm_control( + MSM_PCIE_SUSPEND, cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS); + pdev, PM_OPTIONS); penv->pcie_link_state = PCIE_LINK_DOWN; err_pcie_link_up: @@ -2778,7 +2867,7 @@ static int cnss_probe(struct platform_device *pdev) goto err_get_rc; } - ret = msm_pcie_enumerate(rc_num); + ret = cnss_msm_pcie_enumerate(rc_num); if (ret) { pr_err("%s: Failed to enable PCIe RC%x!\n", __func__, rc_num); goto err_pcie_enumerate; @@ -3260,14 +3349,15 @@ int cnss_auto_suspend(void) if (penv->pcie_link_state) { pci_save_state(pdev); - penv->saved_state = pci_store_saved_state(pdev); + penv->saved_state = cnss_pci_store_saved_state(pdev); pci_disable_device(pdev); ret = pci_set_power_state(pdev, PCI_D3hot); if (ret) pr_err("%s: Set D3Hot failed: %d\n", __func__, ret); - if (msm_pcie_pm_control(MSM_PCIE_SUSPEND, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS)) { + if (cnss_msm_pcie_pm_control( + MSM_PCIE_SUSPEND, + cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS)) { pr_err("%s: Failed to shutdown PCIe link\n", __func__); ret = -EAGAIN; goto out; @@ -3294,9 +3384,9 @@ int cnss_auto_resume(void) pdev = penv->pdev; if (!penv->pcie_link_state) { - if (msm_pcie_pm_control(MSM_PCIE_RESUME, - cnss_get_pci_dev_bus_number(pdev), - pdev, NULL, PM_OPTIONS)) { + if (cnss_msm_pcie_pm_control( + MSM_PCIE_RESUME, cnss_get_pci_dev_bus_number(pdev), + pdev, PM_OPTIONS)) { pr_err("%s: Failed to resume PCIe link\n", __func__); ret = -EAGAIN; goto out; @@ -3308,7 +3398,7 @@ int cnss_auto_resume(void) } if (penv->saved_state) - pci_load_and_free_saved_state(pdev, &penv->saved_state); + cnss_pci_load_and_free_saved_state(pdev, &penv->saved_state); pci_restore_state(pdev); pci_set_master(pdev); diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c index e4596cc67be1..a43dc60ec424 100644 --- a/drivers/net/wireless/cnss/cnss_sdio.c +++ b/drivers/net/wireless/cnss/cnss_sdio.c @@ -214,74 +214,6 @@ void cnss_sdio_remove_pm_qos(void) } EXPORT_SYMBOL(cnss_sdio_remove_pm_qos); -int cnss_request_bus_bandwidth(int bandwidth) -{ - int ret; - struct cnss_sdio_bus_bandwidth *bus_bandwidth; - - if (!cnss_pdata) - return -ENODEV; - - bus_bandwidth = &cnss_pdata->bus_bandwidth; - if (!bus_bandwidth->bus_client) - return -ENOSYS; - - switch (bandwidth) { - case CNSS_BUS_WIDTH_NONE: - case CNSS_BUS_WIDTH_LOW: - case CNSS_BUS_WIDTH_MEDIUM: - case CNSS_BUS_WIDTH_HIGH: - ret = msm_bus_scale_client_update_request( - bus_bandwidth->bus_client, bandwidth); - if (!ret) { - bus_bandwidth->current_bandwidth_vote = bandwidth; - } else { - pr_debug( - "%s: could not set bus bandwidth %d, ret = %d\n", - __func__, bandwidth, ret); - } - break; - default: - pr_debug("%s: Invalid request %d", __func__, bandwidth); - ret = -EINVAL; - } - - return ret; -} -EXPORT_SYMBOL(cnss_request_bus_bandwidth); - -void cnss_request_pm_qos_type(int latency_type, u32 qos_val) -{ - if (!cnss_pdata) - return; - - pr_debug("%s: PM QoS value: %d\n", __func__, qos_val); - pm_qos_add_request(&cnss_pdata->qos_request, latency_type, qos_val); -} -EXPORT_SYMBOL(cnss_request_pm_qos_type); - -void cnss_request_pm_qos(u32 qos_val) -{ - if (!cnss_pdata) - return; - - pr_debug("%s: PM QoS value: %d\n", __func__, qos_val); - pm_qos_add_request( - &cnss_pdata->qos_request, - PM_QOS_CPU_DMA_LATENCY, qos_val); -} -EXPORT_SYMBOL(cnss_request_pm_qos); - -void cnss_remove_pm_qos(void) -{ - if (!cnss_pdata) - return; - - pm_qos_remove_request(&cnss_pdata->qos_request); - pr_debug("%s: PM QoS removed\n", __func__); -} -EXPORT_SYMBOL(cnss_remove_pm_qos); - static int cnss_sdio_shutdown(const struct subsys_desc *subsys, bool force_stop) { struct cnss_sdio_info *cnss_info; @@ -578,56 +510,17 @@ void cnss_sdio_device_crashed(void) } } -void *cnss_get_virt_ramdump_mem(unsigned long *size) -{ - if (!cnss_pdata || !cnss_pdata->pdev) - return NULL; - - *size = cnss_pdata->ssr_info.ramdump_size; - - return cnss_pdata->ssr_info.ramdump_addr; -} -EXPORT_SYMBOL(cnss_get_virt_ramdump_mem); - -void cnss_device_self_recovery(void) -{ - cnss_sdio_shutdown(NULL, false); - msleep(WLAN_RECOVERY_DELAY); - cnss_sdio_powerup(NULL); -} -EXPORT_SYMBOL(cnss_device_self_recovery); - static void cnss_sdio_recovery_work_handler(struct work_struct *recovery) { cnss_sdio_device_self_recovery(); } -DECLARE_WORK(recovery_work, cnss_sdio_recovery_work_handler); +DECLARE_WORK(cnss_sdio_recovery_work, cnss_sdio_recovery_work_handler); void cnss_sdio_schedule_recovery_work(void) { - schedule_work(&recovery_work); -} - -void cnss_schedule_recovery_work(void) -{ - schedule_work(&recovery_work); + schedule_work(&cnss_sdio_recovery_work); } -EXPORT_SYMBOL(cnss_schedule_recovery_work); - -void cnss_device_crashed(void) -{ - struct cnss_ssr_info *ssr_info; - - if (!cnss_pdata) - return; - ssr_info = &cnss_pdata->ssr_info; - if (ssr_info->subsys) { - subsys_set_crash_status(ssr_info->subsys, true); - subsystem_restart_dev(ssr_info->subsys); - } -} -EXPORT_SYMBOL(cnss_device_crashed); /** * cnss_get_restart_level() - cnss get restart level API @@ -1277,13 +1170,6 @@ u8 *cnss_sdio_get_wlan_mac_address(uint32_t *num) } EXPORT_SYMBOL(cnss_sdio_get_wlan_mac_address); -u8 *cnss_get_wlan_mac_address(struct device *dev, uint32_t *num) -{ - *num = 0; - return NULL; -} -EXPORT_SYMBOL(cnss_get_wlan_mac_address); - static const struct of_device_id cnss_sdio_dt_match[] = { {.compatible = "qcom,cnss_sdio"}, {} diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index 4e3d1411ce89..218af71d6112 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -585,6 +585,8 @@ struct msm_pcie_dev_t { uint32_t cpl_timeout; uint32_t current_bdf; short current_short_bdf; + uint32_t perst_delay_us_min; + uint32_t perst_delay_us_max; uint32_t tlp_rd_size; bool linkdown_panic; bool ep_wakeirq; @@ -1822,6 +1824,10 @@ static void msm_pcie_show_status(struct msm_pcie_dev_t *dev) dev->cpl_timeout); PCIE_DBG_FS(dev, "current_bdf: 0x%x\n", dev->current_bdf); + PCIE_DBG_FS(dev, "perst_delay_us_min: %dus\n", + dev->perst_delay_us_min); + PCIE_DBG_FS(dev, "perst_delay_us_max: %dus\n", + dev->perst_delay_us_max); PCIE_DBG_FS(dev, "tlp_rd_size: 0x%x\n", dev->tlp_rd_size); PCIE_DBG_FS(dev, "rc_corr_counter: %lu\n", @@ -4256,8 +4262,7 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) dev->rc_idx); gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, 1 - dev->gpio[MSM_PCIE_GPIO_PERST].on); - usleep_range(PERST_PROPAGATION_DELAY_US_MIN, - PERST_PROPAGATION_DELAY_US_MAX); + usleep_range(dev->perst_delay_us_min, dev->perst_delay_us_max); /* set max tlp read size */ msm_pcie_write_reg_field(dev->dm_core, PCIE20_DEVICE_CONTROL_STATUS, @@ -5121,7 +5126,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 */ @@ -5772,6 +5777,34 @@ static int msm_pcie_probe(struct platform_device *pdev) PCIE_DBG(&msm_pcie_dev[rc_idx], "RC%d: cpl-timeout: 0x%x.\n", rc_idx, msm_pcie_dev[rc_idx].cpl_timeout); + msm_pcie_dev[rc_idx].perst_delay_us_min = + PERST_PROPAGATION_DELAY_US_MIN; + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,perst-delay-us-min", + &msm_pcie_dev[rc_idx].perst_delay_us_min); + if (ret) + PCIE_DBG(&msm_pcie_dev[rc_idx], + "RC%d: perst-delay-us-min does not exist. Use default value %dus.\n", + rc_idx, msm_pcie_dev[rc_idx].perst_delay_us_min); + else + PCIE_DBG(&msm_pcie_dev[rc_idx], + "RC%d: perst-delay-us-min: %dus.\n", + rc_idx, msm_pcie_dev[rc_idx].perst_delay_us_min); + + msm_pcie_dev[rc_idx].perst_delay_us_max = + PERST_PROPAGATION_DELAY_US_MAX; + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,perst-delay-us-max", + &msm_pcie_dev[rc_idx].perst_delay_us_max); + if (ret) + PCIE_DBG(&msm_pcie_dev[rc_idx], + "RC%d: perst-delay-us-max does not exist. Use default value %dus.\n", + rc_idx, msm_pcie_dev[rc_idx].perst_delay_us_max); + else + PCIE_DBG(&msm_pcie_dev[rc_idx], + "RC%d: perst-delay-us-max: %dus.\n", + rc_idx, msm_pcie_dev[rc_idx].perst_delay_us_max); + msm_pcie_dev[rc_idx].tlp_rd_size = PCIE_TLP_RD_SIZE; ret = of_property_read_u32(pdev->dev.of_node, "qcom,tlp-rd-size", diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c index 13ea3b2fb920..f4a2d17db38d 100644 --- a/drivers/platform/msm/ipa/ipa_api.c +++ b/drivers/platform/msm/ipa/ipa_api.c @@ -2503,6 +2503,32 @@ int ipa_set_required_perf_profile(enum ipa_voltage_level floor_voltage, } EXPORT_SYMBOL(ipa_set_required_perf_profile); +/** + * ipa_get_ipc_logbuf() - return a pointer to IPA driver IPC log + */ +void *ipa_get_ipc_logbuf(void) +{ + void *ret; + + IPA_API_DISPATCH_RETURN_PTR(ipa_get_ipc_logbuf); + + return ret; +} +EXPORT_SYMBOL(ipa_get_ipc_logbuf); + +/** + * ipa_get_ipc_logbuf_low() - return a pointer to IPA driver IPC low prio log + */ +void *ipa_get_ipc_logbuf_low(void) +{ + void *ret; + + IPA_API_DISPATCH_RETURN_PTR(ipa_get_ipc_logbuf_low); + + return ret; +} +EXPORT_SYMBOL(ipa_get_ipc_logbuf_low); + static const struct dev_pm_ops ipa_pm_ops = { .suspend_noirq = ipa_ap_suspend, .resume_noirq = ipa_ap_resume, diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h index 7edbf4e5b1d9..054b3654e9dc 100644 --- a/drivers/platform/msm/ipa/ipa_api.h +++ b/drivers/platform/msm/ipa/ipa_api.h @@ -303,6 +303,10 @@ struct ipa_api_controller { int (*ipa_set_required_perf_profile)( enum ipa_voltage_level floor_voltage, u32 bandwidth_mbps); + void *(*ipa_get_ipc_logbuf)(void); + + void *(*ipa_get_ipc_logbuf_low)(void); + }; #ifdef CONFIG_IPA diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c index c9abf140d8e3..21a230c3c1ff 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c @@ -34,52 +34,42 @@ #define IPA_USB_DRV_NAME "ipa_usb" -#define IPA_USB_IPC_LOG_PAGES 10 -#define IPA_USB_IPC_LOG(buf, fmt, args...) \ - ipc_log_string((buf), \ - DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) #define IPA_USB_DBG(fmt, args...) \ do { \ pr_debug(IPA_USB_DRV_NAME " %s:%d " fmt, \ __func__, __LINE__, ## args); \ - if (ipa3_usb_ctx) { \ - IPA_USB_IPC_LOG(ipa3_usb_ctx->logbuf, fmt, ## args); \ - IPA_USB_IPC_LOG(ipa3_usb_ctx->logbuf_low, \ - fmt, ## args); \ - } \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_USB_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_USB_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define IPA_USB_DBG_LOW(fmt, args...) \ do { \ pr_debug(IPA_USB_DRV_NAME " %s:%d " fmt, \ __func__, __LINE__, ## args); \ - if (ipa3_usb_ctx && \ - ipa3_usb_ctx->enable_low_prio_print) { \ - IPA_USB_IPC_LOG(ipa3_usb_ctx->logbuf_low, \ - fmt, ## args); \ - } \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_USB_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define IPA_USB_ERR(fmt, args...) \ do { \ pr_err(IPA_USB_DRV_NAME " %s:%d " fmt, \ __func__, __LINE__, ## args); \ - if (ipa3_usb_ctx) { \ - IPA_USB_IPC_LOG(ipa3_usb_ctx->logbuf, fmt, ## args); \ - IPA_USB_IPC_LOG(ipa3_usb_ctx->logbuf_low, \ - fmt, ## args); \ - } \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_USB_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_USB_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define IPA_USB_INFO(fmt, args...) \ do { \ pr_info(IPA_USB_DRV_NAME " %s:%d " fmt, \ __func__, __LINE__, ## args); \ - if (ipa3_usb_ctx) { \ - IPA_USB_IPC_LOG(ipa3_usb_ctx->logbuf, fmt, ## args); \ - IPA_USB_IPC_LOG(ipa3_usb_ctx->logbuf_low, \ - fmt, ## args); \ - } \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_USB_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_USB_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) struct ipa_usb_xdci_connect_params_internal { @@ -189,10 +179,6 @@ struct ipa3_usb_context { ttype_ctx[IPA_USB_TRANSPORT_MAX]; struct dentry *dfile_state_info; struct dentry *dent; - struct dentry *dfile_enable_low_prio; - void *logbuf; - void *logbuf_low; - u32 enable_low_prio_print; }; enum ipa3_usb_op { @@ -492,7 +478,7 @@ static void ipa3_usb_notify_do(enum ipa3_usb_transport_type ttype, void *user_data; int res; - IPA_USB_DBG_LOW("Trying to notify USB with %s\n", + IPA_USB_DBG("Trying to notify USB with %s\n", ipa3_usb_notify_event_to_string(event)); cb = ipa3_usb_ctx->ttype_ctx[ttype].ipa_usb_notify_cb; @@ -500,7 +486,7 @@ static void ipa3_usb_notify_do(enum ipa3_usb_transport_type ttype, if (cb) { res = cb(event, user_data); - IPA_USB_DBG_LOW("Notified USB with %s. is_dpl=%d result=%d\n", + IPA_USB_DBG("Notified USB with %s. is_dpl=%d result=%d\n", ipa3_usb_notify_event_to_string(event), IPA3_USB_IS_TTYPE_DPL(ttype), res); } @@ -1229,7 +1215,7 @@ static int ipa3_usb_request_xdci_channel( chan_params.chan_params.ring_base_addr = params->xfer_ring_base_addr; chan_params.chan_params.ring_base_vaddr = NULL; - chan_params.chan_params.use_db_eng = GSI_CHAN_DIRECT_MODE; + chan_params.chan_params.use_db_eng = GSI_CHAN_DB_MODE; chan_params.chan_params.max_prefetch = GSI_ONE_PREFETCH_SEG; if (params->dir == GSI_CHAN_DIR_FROM_GSI) chan_params.chan_params.low_weight = @@ -1250,6 +1236,9 @@ static int ipa3_usb_request_xdci_channel( params->xfer_scratch.depcmd_low_addr; chan_params.chan_scratch.xdci.depcmd_hi_addr = params->xfer_scratch.depcmd_hi_addr; + chan_params.chan_scratch.xdci.outstanding_threshold = + ((params->teth_prot == IPA_USB_MBIM) ? 1 : 2) * + chan_params.chan_params.re_size; /* max_outstanding_tre is set in ipa3_request_gsi_channel() */ result = ipa3_request_gsi_channel(&chan_params, out_params); if (result) { @@ -1789,33 +1778,6 @@ connect_ul_fail: return result; } -static int ipa_usb_ipc_logging_init(void) -{ - int result; - - ipa3_usb_ctx->logbuf = ipc_log_context_create(IPA_USB_IPC_LOG_PAGES, - "ipa_usb", 0); - if (ipa3_usb_ctx->logbuf == NULL) { - /* we can't use ipa_usb print macros on failures */ - pr_err("ipa_usb: failed to get logbuf\n"); - return -ENOMEM; - } - - ipa3_usb_ctx->logbuf_low = ipc_log_context_create(IPA_USB_IPC_LOG_PAGES, - "ipa_usb_low", 0); - if (ipa3_usb_ctx->logbuf_low == NULL) { - pr_err("ipa_usb: failed to get logbuf_low\n"); - result = -ENOMEM; - goto fail_logbuf_low; - } - - return 0; - -fail_logbuf_low: - ipc_log_context_destroy(ipa3_usb_ctx->logbuf); - return result; -} - #ifdef CONFIG_DEBUG_FS static char dbg_buff[IPA_USB_MAX_MSG_LEN]; @@ -1980,8 +1942,6 @@ const struct file_operations ipa3_ipa_usb_ops = { static void ipa_usb_debugfs_init(void) { const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH; - const mode_t read_write_mode = S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP; ipa3_usb_ctx->dent = debugfs_create_dir("ipa_usb", 0); if (IS_ERR(ipa3_usb_ctx->dent)) { @@ -1998,16 +1958,6 @@ static void ipa_usb_debugfs_init(void) goto fail; } - ipa3_usb_ctx->dfile_enable_low_prio = - debugfs_create_u32("enable_low_prio_print", - read_write_mode, ipa3_usb_ctx->dent, - &ipa3_usb_ctx->enable_low_prio_print); - if (!ipa3_usb_ctx->dfile_enable_low_prio || - IS_ERR(ipa3_usb_ctx->dfile_enable_low_prio)) { - IPA_USB_ERR("could not create enable_low_prio_print file\n"); - goto fail; - } - return; fail: @@ -2620,14 +2570,6 @@ static int __init ipa3_usb_init(void) } memset(ipa3_usb_ctx, 0, sizeof(struct ipa3_usb_context)); - res = ipa_usb_ipc_logging_init(); - if (res) { - /* IPA_USB_ERR will crash on NULL dereference if we use macro*/ - pr_err("ipa_usb: failed to initialize ipc logging\n"); - res = -EFAULT; - goto ipa_usb_init_ipc_log_fail; - } - for (i = 0; i < IPA_USB_MAX_TETH_PROT_SIZE; i++) ipa3_usb_ctx->teth_prot_ctx[i].state = IPA_USB_TETH_PROT_INVALID; @@ -2668,9 +2610,6 @@ static int __init ipa3_usb_init(void) ipa_usb_workqueue_fail: IPA_USB_ERR(":init failed (%d)\n", -res); - ipc_log_context_destroy(ipa3_usb_ctx->logbuf); - ipc_log_context_destroy(ipa3_usb_ctx->logbuf_low); -ipa_usb_init_ipc_log_fail: kfree(ipa3_usb_ctx); return res; } diff --git a/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c index c388925f4679..521bdafab76f 100644 --- a/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c +++ b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c @@ -23,49 +23,37 @@ #include <linux/types.h> #include <linux/ipv6.h> #include <net/addrconf.h> -#include <linux/ipc_logging.h> #include <linux/ipa.h> #include <linux/cdev.h> #include <linux/ipa_odu_bridge.h> +#include "../ipa_common_i.h" #define ODU_BRIDGE_DRV_NAME "odu_ipa_bridge" -#define ODU_IPC_LOG_PAGES 10 -#define ODU_IPC_LOG(buf, fmt, args...) \ - ipc_log_string((buf), \ - ODU_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) - #define ODU_BRIDGE_DBG(fmt, args...) \ do { \ pr_debug(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \ __func__, __LINE__, ## args); \ - if (odu_bridge_ctx) { \ - ODU_IPC_LOG(odu_bridge_ctx->logbuf, \ - fmt, ## args); \ - ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \ - fmt, ## args); \ - } \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define ODU_BRIDGE_DBG_LOW(fmt, args...) \ do { \ pr_debug(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \ __func__, __LINE__, ## args); \ - if (odu_bridge_ctx && \ - odu_bridge_ctx->enable_low_prio_print) { \ - ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \ - fmt, ## args); \ - } \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define ODU_BRIDGE_ERR(fmt, args...) \ do { \ pr_err(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \ __func__, __LINE__, ## args); \ - if (odu_bridge_ctx) { \ - ODU_IPC_LOG(odu_bridge_ctx->logbuf, \ - fmt, ## args); \ - ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \ - fmt, ## args); \ - } \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define ODU_BRIDGE_FUNC_ENTRY() \ @@ -158,7 +146,6 @@ struct odu_bridge_ctx { u32 ipa_sys_desc_size; void *logbuf; void *logbuf_low; - u32 enable_low_prio_print; }; static struct odu_bridge_ctx *odu_bridge_ctx; @@ -683,7 +670,6 @@ static long compat_odu_bridge_ioctl(struct file *file, static struct dentry *dent; static struct dentry *dfile_stats; static struct dentry *dfile_mode; -static struct dentry *dfile_low_prio; static ssize_t odu_debugfs_stats(struct file *file, char __user *ubuf, @@ -806,15 +792,6 @@ static void odu_debugfs_init(void) goto fail; } - dfile_low_prio = debugfs_create_u32("enable_low_prio_print", - read_write_mode, - dent, &odu_bridge_ctx->enable_low_prio_print); - if (!dfile_low_prio) { - ODU_BRIDGE_ERR("could not create enable_low_prio_print file\n"); - goto fail; - } - - return; fail: debugfs_remove_recursive(dent); } @@ -1104,34 +1081,6 @@ static void odu_bridge_deregister_properties(void) ODU_BRIDGE_FUNC_EXIT(); } -static int odu_bridge_ipc_logging_init(void) -{ - int result; - - odu_bridge_ctx->logbuf = ipc_log_context_create(ODU_IPC_LOG_PAGES, - "ipa_odu_bridge", 0); - if (odu_bridge_ctx->logbuf == NULL) { - /* we can't use odu_bridge print macros on failures */ - pr_err("odu_bridge: failed to get logbuf\n"); - return -ENOMEM; - } - - odu_bridge_ctx->logbuf_low = - ipc_log_context_create(ODU_IPC_LOG_PAGES, - "ipa_odu_bridge_low", 0); - if (odu_bridge_ctx->logbuf_low == NULL) { - pr_err("odu_bridge: failed to get logbuf_low\n"); - result = -ENOMEM; - goto fail_logbuf_low; - } - - return 0; - -fail_logbuf_low: - ipc_log_context_destroy(odu_bridge_ctx->logbuf); - return result; -} - /** * odu_bridge_init() - Initialize the ODU bridge driver * @params: initialization parameters @@ -1183,13 +1132,6 @@ int odu_bridge_init(struct odu_bridge_params *params) return -ENOMEM; } - res = odu_bridge_ipc_logging_init(); - if (res) { - /* ODU_BRIDGE_ERR will crash on NULL if we use it here*/ - pr_err("odu_bridge: failed to initialize ipc logging\n"); - res = -EFAULT; - goto fail_ipc_create; - } odu_bridge_ctx->class = class_create(THIS_MODULE, ODU_BRIDGE_DRV_NAME); if (!odu_bridge_ctx->class) { ODU_BRIDGE_ERR("Class_create err.\n"); @@ -1264,9 +1206,6 @@ fail_device_create: fail_alloc_chrdev_region: class_destroy(odu_bridge_ctx->class); fail_class_create: - ipc_log_context_destroy(odu_bridge_ctx->logbuf); - ipc_log_context_destroy(odu_bridge_ctx->logbuf_low); -fail_ipc_create: kfree(odu_bridge_ctx); odu_bridge_ctx = NULL; return res; diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h index 8149837b2de0..d906169f7098 100644 --- a/drivers/platform/msm/ipa/ipa_common_i.h +++ b/drivers/platform/msm/ipa/ipa_common_i.h @@ -12,6 +12,7 @@ #ifndef _IPA_COMMON_I_H_ #define _IPA_COMMON_I_H_ +#include <linux/ipc_logging.h> #define __FILENAME__ \ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) @@ -114,6 +115,13 @@ struct ipa_active_client_logging_info { extern const char *ipa_clients_strings[]; +#define IPA_IPC_LOGGING(buf, fmt, args...) \ + do { \ + if (buf) \ + ipc_log_string((buf), fmt, __func__, __LINE__, \ + ## args); \ + } while (0) + void ipa_inc_client_enable_clks(struct ipa_active_client_logging_info *id); void ipa_dec_client_disable_clks(struct ipa_active_client_logging_info *id); int ipa_inc_client_enable_clks_no_block( @@ -123,6 +131,8 @@ int ipa_resume_resource(enum ipa_rm_resource_name name); int ipa_suspend_resource_sync(enum ipa_rm_resource_name resource); int ipa_set_required_perf_profile(enum ipa_voltage_level floor_voltage, u32 bandwidth_mbps); +void *ipa_get_ipc_logbuf(void); +void *ipa_get_ipc_logbuf_low(void); #endif /* _IPA_COMMON_I_H_ */ diff --git a/drivers/platform/msm/ipa/ipa_rm.c b/drivers/platform/msm/ipa/ipa_rm.c index 53c72b154096..d0bde0e9654b 100644 --- a/drivers/platform/msm/ipa/ipa_rm.c +++ b/drivers/platform/msm/ipa/ipa_rm.c @@ -657,7 +657,7 @@ static void ipa_rm_wq_handler(struct work_struct *work) container_of(work, struct ipa_rm_wq_work_type, work); - IPA_RM_DBG("%s cmd=%d event=%d notify_registered_only=%d\n", + IPA_RM_DBG_LOW("%s cmd=%d event=%d notify_registered_only=%d\n", ipa_rm_resource_str(ipa_rm_work->resource_name), ipa_rm_work->wq_cmd, ipa_rm_work->event, @@ -714,7 +714,7 @@ static void ipa_rm_wq_resume_handler(struct work_struct *work) container_of(work, struct ipa_rm_wq_suspend_resume_work_type, work); - IPA_RM_DBG("resume work handler: %s", + IPA_RM_DBG_LOW("resume work handler: %s", ipa_rm_resource_str(ipa_rm_work->resource_name)); if (!IPA_RM_RESORCE_IS_CONS(ipa_rm_work->resource_name)) { @@ -750,7 +750,7 @@ static void ipa_rm_wq_suspend_handler(struct work_struct *work) container_of(work, struct ipa_rm_wq_suspend_resume_work_type, work); - IPA_RM_DBG("suspend work handler: %s", + IPA_RM_DBG_LOW("suspend work handler: %s", ipa_rm_resource_str(ipa_rm_work->resource_name)); if (!IPA_RM_RESORCE_IS_CONS(ipa_rm_work->resource_name)) { @@ -947,7 +947,7 @@ static void ipa_rm_perf_profile_notify_to_ipa_work(struct work_struct *work) work); int res; - IPA_RM_DBG("calling to IPA driver. voltage %d bandwidth %d\n", + IPA_RM_DBG_LOW("calling to IPA driver. voltage %d bandwidth %d\n", notify_work->volt, notify_work->bandwidth_mbps); res = ipa_set_required_perf_profile(notify_work->volt, @@ -957,7 +957,7 @@ static void ipa_rm_perf_profile_notify_to_ipa_work(struct work_struct *work) goto bail; } - IPA_RM_DBG("IPA driver notified\n"); + IPA_RM_DBG_LOW("IPA driver notified\n"); bail: kfree(notify_work); } @@ -995,7 +995,7 @@ void ipa_rm_perf_profile_change(enum ipa_rm_resource_name resource_name) u32 sum_bw_prod = 0; u32 sum_bw_cons = 0; - IPA_RM_DBG("%s\n", ipa_rm_resource_str(resource_name)); + IPA_RM_DBG_LOW("%s\n", ipa_rm_resource_str(resource_name)); if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph, resource_name, @@ -1021,7 +1021,7 @@ void ipa_rm_perf_profile_change(enum ipa_rm_resource_name resource_name) switch (resource->state) { case IPA_RM_GRANTED: case IPA_RM_REQUEST_IN_PROGRESS: - IPA_RM_DBG("max_bw = %d, needed_bw = %d\n", + IPA_RM_DBG_LOW("max_bw = %d, needed_bw = %d\n", resource->max_bw, resource->needed_bw); *bw_ptr = min(resource->max_bw, resource->needed_bw); ipa_rm_ctx->prof_vote.volt[resource_name] = @@ -1039,7 +1039,7 @@ void ipa_rm_perf_profile_change(enum ipa_rm_resource_name resource_name) WARN_ON(1); return; } - IPA_RM_DBG("resource bandwidth: %d voltage: %d\n", *bw_ptr, + IPA_RM_DBG_LOW("resource bandwidth: %d voltage: %d\n", *bw_ptr, resource->floor_voltage); ipa_rm_ctx->prof_vote.curr_volt = IPA_VOLTAGE_UNSPECIFIED; @@ -1057,17 +1057,17 @@ void ipa_rm_perf_profile_change(enum ipa_rm_resource_name resource_name) for (i = 0; i < IPA_RM_RESOURCE_CONS_MAX; i++) sum_bw_cons += ipa_rm_ctx->prof_vote.bw_cons[i]; - IPA_RM_DBG("all prod bandwidth: %d all cons bandwidth: %d\n", + IPA_RM_DBG_LOW("all prod bandwidth: %d all cons bandwidth: %d\n", sum_bw_prod, sum_bw_cons); ipa_rm_ctx->prof_vote.curr_bw = min(sum_bw_prod, sum_bw_cons); if (ipa_rm_ctx->prof_vote.curr_volt == old_volt && ipa_rm_ctx->prof_vote.curr_bw == old_bw) { - IPA_RM_DBG("same voting\n"); + IPA_RM_DBG_LOW("same voting\n"); return; } - IPA_RM_DBG("new voting: voltage %d bandwidth %d\n", + IPA_RM_DBG_LOW("new voting: voltage %d bandwidth %d\n", ipa_rm_ctx->prof_vote.curr_volt, ipa_rm_ctx->prof_vote.curr_bw); diff --git a/drivers/platform/msm/ipa/ipa_rm_i.h b/drivers/platform/msm/ipa/ipa_rm_i.h index 65dbff66a6dd..e0c1582e8543 100644 --- a/drivers/platform/msm/ipa/ipa_rm_i.h +++ b/drivers/platform/msm/ipa/ipa_rm_i.h @@ -16,15 +16,36 @@ #include <linux/workqueue.h> #include <linux/ipa.h> #include "ipa_rm_resource.h" +#include "ipa_common_i.h" #define IPA_RM_DRV_NAME "ipa_rm" #define IPA_RM_DBG_LOW(fmt, args...) \ - pr_debug(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_debug(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \ + ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) #define IPA_RM_DBG(fmt, args...) \ - pr_debug(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_debug(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \ + ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPA_RM_ERR(fmt, args...) \ - pr_err(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_err(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \ + ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) #define IPA_RM_RESOURCE_CONS_MAX \ (IPA_RM_RESOURCE_MAX - IPA_RM_RESOURCE_PROD_MAX) diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c index 75424eb768f4..597598df6997 100644 --- a/drivers/platform/msm/ipa/ipa_rm_resource.c +++ b/drivers/platform/msm/ipa/ipa_rm_resource.c @@ -85,9 +85,9 @@ int ipa_rm_resource_consumer_release_work( { int driver_result; - IPA_RM_DBG("calling driver CB\n"); + IPA_RM_DBG_LOW("calling driver CB\n"); driver_result = consumer->release_resource(); - IPA_RM_DBG("driver CB returned with %d\n", driver_result); + IPA_RM_DBG_LOW("driver CB returned with %d\n", driver_result); /* * Treat IPA_RM_RELEASE_IN_PROGRESS as IPA_RM_RELEASED * for CONS which remains in RELEASE_IN_PROGRESS. @@ -120,9 +120,9 @@ int ipa_rm_resource_consumer_request_work(struct ipa_rm_resource_cons *consumer, { int driver_result; - IPA_RM_DBG("calling driver CB\n"); + IPA_RM_DBG_LOW("calling driver CB\n"); driver_result = consumer->request_resource(); - IPA_RM_DBG("driver CB returned with %d\n", driver_result); + IPA_RM_DBG_LOW("driver CB returned with %d\n", driver_result); if (driver_result == 0) { if (notify_completion) { ipa_rm_resource_consumer_handle_cb(consumer, @@ -151,7 +151,7 @@ int ipa_rm_resource_consumer_request( enum ipa_rm_resource_state prev_state; struct ipa_active_client_logging_info log_info; - IPA_RM_DBG("%s state: %d\n", + IPA_RM_DBG_LOW("%s state: %d\n", ipa_rm_resource_str(consumer->resource.name), consumer->resource.state); @@ -166,7 +166,7 @@ int ipa_rm_resource_consumer_request( ipa_rm_resource_str(consumer->resource.name)); if (prev_state == IPA_RM_RELEASE_IN_PROGRESS || ipa_inc_client_enable_clks_no_block(&log_info) != 0) { - IPA_RM_DBG("async resume work for %s\n", + IPA_RM_DBG_LOW("async resume work for %s\n", ipa_rm_resource_str(consumer->resource.name)); ipa_rm_wq_send_resume_cmd(consumer->resource.name, prev_state, @@ -198,10 +198,10 @@ int ipa_rm_resource_consumer_request( if (inc_usage_count) consumer->usage_count++; bail: - IPA_RM_DBG("%s new state: %d\n", + IPA_RM_DBG_LOW("%s new state: %d\n", ipa_rm_resource_str(consumer->resource.name), consumer->resource.state); - IPA_RM_DBG("EXIT with %d\n", result); + IPA_RM_DBG_LOW("EXIT with %d\n", result); return result; } @@ -214,7 +214,7 @@ int ipa_rm_resource_consumer_release( int result = 0; enum ipa_rm_resource_state save_state; - IPA_RM_DBG("%s state: %d\n", + IPA_RM_DBG_LOW("%s state: %d\n", ipa_rm_resource_str(consumer->resource.name), consumer->resource.state); save_state = consumer->resource.state; @@ -255,10 +255,10 @@ int ipa_rm_resource_consumer_release( goto bail; } bail: - IPA_RM_DBG("%s new state: %d\n", + IPA_RM_DBG_LOW("%s new state: %d\n", ipa_rm_resource_str(consumer->resource.name), consumer->resource.state); - IPA_RM_DBG("EXIT with %d\n", result); + IPA_RM_DBG_LOW("EXIT with %d\n", result); return result; } @@ -278,7 +278,7 @@ void ipa_rm_resource_producer_notify_clients( { struct ipa_rm_notification_info *reg_info; - IPA_RM_DBG("%s event: %d notify_registered_only: %d\n", + IPA_RM_DBG_LOW("%s event: %d notify_registered_only: %d\n", ipa_rm_resource_str(producer->resource.name), event, notify_registered_only); @@ -287,12 +287,12 @@ void ipa_rm_resource_producer_notify_clients( if (notify_registered_only && !reg_info->explicit) continue; - IPA_RM_DBG("Notifying %s event: %d\n", + IPA_RM_DBG_LOW("Notifying %s event: %d\n", ipa_rm_resource_str(producer->resource.name), event); reg_info->reg_params.notify_cb(reg_info->reg_params.user_data, event, 0); - IPA_RM_DBG("back from client CB\n"); + IPA_RM_DBG_LOW("back from client CB\n"); } } @@ -823,7 +823,7 @@ int ipa_rm_resource_producer_request(struct ipa_rm_resource_prod *producer) } unlock_and_bail: if (state != producer->resource.state) - IPA_RM_DBG("%s state changed %d->%d\n", + IPA_RM_DBG_LOW("%s state changed %d->%d\n", ipa_rm_resource_str(producer->resource.name), state, producer->resource.state); @@ -889,7 +889,7 @@ int ipa_rm_resource_producer_release(struct ipa_rm_resource_prod *producer) } bail: if (state != producer->resource.state) - IPA_RM_DBG("%s state changed %d->%d\n", + IPA_RM_DBG_LOW("%s state changed %d->%d\n", ipa_rm_resource_str(producer->resource.name), state, producer->resource.state); @@ -901,7 +901,7 @@ static void ipa_rm_resource_producer_handle_cb( struct ipa_rm_resource_prod *producer, enum ipa_rm_event event) { - IPA_RM_DBG("%s state: %d event: %d pending_request: %d\n", + IPA_RM_DBG_LOW("%s state: %d event: %d pending_request: %d\n", ipa_rm_resource_str(producer->resource.name), producer->resource.state, event, @@ -950,7 +950,7 @@ static void ipa_rm_resource_producer_handle_cb( goto unlock_and_bail; } unlock_and_bail: - IPA_RM_DBG("%s new state: %d\n", + IPA_RM_DBG_LOW("%s new state: %d\n", ipa_rm_resource_str(producer->resource.name), producer->resource.state); bail: @@ -973,7 +973,7 @@ void ipa_rm_resource_consumer_handle_cb(struct ipa_rm_resource_cons *consumer, IPA_RM_ERR("invalid params\n"); return; } - IPA_RM_DBG("%s state: %d event: %d\n", + IPA_RM_DBG_LOW("%s state: %d event: %d\n", ipa_rm_resource_str(consumer->resource.name), consumer->resource.state, event); @@ -1013,7 +1013,7 @@ void ipa_rm_resource_consumer_handle_cb(struct ipa_rm_resource_cons *consumer, return; bail: - IPA_RM_DBG("%s new state: %d\n", + IPA_RM_DBG_LOW("%s new state: %d\n", ipa_rm_resource_str(consumer->resource.name), consumer->resource.state); } @@ -1040,7 +1040,7 @@ int ipa_rm_resource_set_perf_profile(struct ipa_rm_resource *resource, } if (profile->max_supported_bandwidth_mbps == resource->max_bw) { - IPA_RM_DBG("same profile\n"); + IPA_RM_DBG_LOW("same profile\n"); return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c index 6cfa477608b5..2255a74331cb 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c @@ -497,7 +497,7 @@ int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc, } } else { tx_pkt->mem.base = desc[i].frag; - tx_pkt->mem.size = skb_frag_size(desc[i].frag); + tx_pkt->mem.size = desc[i].len; if (!desc[i].dma_address_valid) { tx_pkt->mem.phys_base = @@ -1634,6 +1634,7 @@ int ipa2_tx_dp(enum ipa_client_type dst, struct sk_buff *skb, for (f = 0; f < num_frags; f++) { desc[2+f].frag = &skb_shinfo(skb)->frags[f]; desc[2+f].type = IPA_DATA_DESC_SKB_PAGED; + desc[2+f].len = skb_frag_size(desc[2+f].frag); } /* don't free skb till frag mappings are released */ @@ -1673,6 +1674,7 @@ int ipa2_tx_dp(enum ipa_client_type dst, struct sk_buff *skb, for (f = 0; f < num_frags; f++) { desc[1+f].frag = &skb_shinfo(skb)->frags[f]; desc[1+f].type = IPA_DATA_DESC_SKB_PAGED; + desc[1+f].len = skb_frag_size(desc[1+f].frag); } /* don't free skb till frag mappings are released */ diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c index 7a8318a6e138..00f18333587b 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c @@ -854,11 +854,6 @@ static int ipa_q6_clnt_svc_event_notify(struct notifier_block *this, queue_delayed_work(ipa_clnt_req_workqueue, &work_svc_arrive, 0); break; - case QMI_SERVER_EXIT: - if (!atomic_read(&workqueues_stopped)) - queue_delayed_work(ipa_clnt_req_workqueue, - &work_svc_exit, 0); - break; default: break; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c index fe315bd1e4b1..6fd9b4e61e02 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c @@ -4936,6 +4936,18 @@ static int ipa2_stop_gsi_channel(u32 clnt_hdl) return -EFAULT; } +static void *ipa2_get_ipc_logbuf(void) +{ + /* no support for IPC logging in IPAv2 */ + return NULL; +} + +static void *ipa2_get_ipc_logbuf_low(void) +{ + /* no support for IPC logging in IPAv2 */ + return NULL; +} + int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type, struct ipa_api_controller *api_ctrl) @@ -5072,6 +5084,9 @@ int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_suspend_resource_sync = ipa2_suspend_resource_sync; api_ctrl->ipa_set_required_perf_profile = ipa2_set_required_perf_profile; + api_ctrl->ipa_get_ipc_logbuf = ipa2_get_ipc_logbuf; + api_ctrl->ipa_get_ipc_logbuf_low = ipa2_get_ipc_logbuf_low; + return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index a8036602ec2f..322fe1fe6de8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -67,8 +67,6 @@ #define IPA_TRANSPORT_PROD_TIMEOUT_MSEC 100 -#define IPA_IPC_LOG_PAGES 50 - #define IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE 2048 #define IPA3_ACTIVE_CLIENT_LOG_TYPE_EP 0 @@ -3958,13 +3956,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, result = -ENOMEM; goto fail_logbuf; } - ipa3_ctx->logbuf_low = - ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa_low", 0); - if (ipa3_ctx->logbuf_low == NULL) { - IPAERR("failed to get logbuf_low\n"); - result = -ENOMEM; - goto fail_logbuf_low; - } ipa3_ctx->pdev = ipa_dev; ipa3_ctx->uc_pdev = ipa_dev; @@ -4460,8 +4451,6 @@ fail_bus_reg: fail_bind: kfree(ipa3_ctx->ctrl); fail_mem_ctrl: - ipc_log_context_destroy(ipa3_ctx->logbuf_low); -fail_logbuf_low: ipc_log_context_destroy(ipa3_ctx->logbuf); fail_logbuf: kfree(ipa3_ctx); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index f4e17074f409..f5f5cdae0e32 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -1152,7 +1152,8 @@ int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params, memcpy(&ep->chan_scratch, ¶ms->chan_scratch, sizeof(union __packed gsi_channel_scratch)); - ep->chan_scratch.xdci.max_outstanding_tre = gsi_ep_cfg_ptr->ipa_if_aos; + ep->chan_scratch.xdci.max_outstanding_tre = + params->chan_params.re_size * gsi_ep_cfg_ptr->ipa_if_tlv; gsi_res = gsi_write_channel_scratch(ep->gsi_chan_hdl, params->chan_scratch); if (gsi_res != GSI_STATUS_SUCCESS) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 96832869a496..0ca7b662aa17 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -1587,6 +1587,43 @@ static ssize_t ipa3_clear_active_clients_log(struct file *file, return count; } +static ssize_t ipa3_enable_ipc_low(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + unsigned long missing; + s8 option = 0; + + if (sizeof(dbg_buff) < count + 1) + return -EFAULT; + + missing = copy_from_user(dbg_buff, ubuf, count); + if (missing) + return -EFAULT; + + dbg_buff[count] = '\0'; + if (kstrtos8(dbg_buff, 0, &option)) + return -EFAULT; + + if (option) { + if (!ipa3_ctx->logbuf_low) { + ipa3_ctx->logbuf_low = + ipc_log_context_create(IPA_IPC_LOG_PAGES, + "ipa_low", 0); + } + + if (ipa3_ctx->logbuf_low == NULL) { + IPAERR("failed to get logbuf_low\n"); + return -EFAULT; + } + } else { + if (ipa3_ctx->logbuf_low) + ipc_log_context_destroy(ipa3_ctx->logbuf_low); + ipa3_ctx->logbuf_low = NULL; + } + + return count; +} + const struct file_operations ipa3_gen_reg_ops = { .read = ipa3_read_gen_reg, }; @@ -1671,6 +1708,10 @@ const struct file_operations ipa3_active_clients = { .write = ipa3_clear_active_clients_log, }; +const struct file_operations ipa3_ipc_low_ops = { + .write = ipa3_enable_ipc_low, +}; + void ipa3_debugfs_init(void) { const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH; @@ -1883,8 +1924,8 @@ void ipa3_debugfs_init(void) goto fail; } - file = debugfs_create_u32("enable_low_prio_print", read_write_mode, - dent, &ipa3_ctx->enable_low_prio_print); + file = debugfs_create_file("enable_low_prio_print", write_only_mode, + dent, 0, &ipa3_ipc_low_ops); if (!file) { IPAERR("could not create enable_low_prio_print file\n"); goto fail; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c index 966f279d863b..9d1ff18d7ed0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -33,16 +33,38 @@ #define IPADMA_DRV_NAME "ipa_dma" #define IPADMA_DBG(fmt, args...) \ - pr_debug(IPADMA_DRV_NAME " %s:%d " fmt, \ - __func__, __LINE__, ## args) + do { \ + pr_debug(IPADMA_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPADMA_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPADMA_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + +#define IPADMA_DBG_LOW(fmt, args...) \ + do { \ + pr_debug(IPADMA_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPADMA_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPADMA_ERR(fmt, args...) \ - pr_err(IPADMA_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_err(IPADMA_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPADMA_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPADMA_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) #define IPADMA_FUNC_ENTRY() \ - IPADMA_DBG("ENTRY\n") + IPADMA_DBG_LOW("ENTRY\n") #define IPADMA_FUNC_EXIT() \ - IPADMA_DBG("EXIT\n") + IPADMA_DBG_LOW("EXIT\n") #ifdef CONFIG_DEBUG_FS #define IPADMA_MAX_MSG_LEN 1024 @@ -255,7 +277,7 @@ int ipa3_dma_enable(void) } mutex_lock(&ipa3_dma_ctx->enable_lock); if (ipa3_dma_ctx->is_enabled) { - IPADMA_DBG("Already enabled.\n"); + IPADMA_ERR("Already enabled.\n"); mutex_unlock(&ipa3_dma_ctx->enable_lock); return -EPERM; } @@ -281,7 +303,7 @@ static bool ipa3_dma_work_pending(void) IPADMA_DBG("pending uc\n"); return true; } - IPADMA_DBG("no pending work\n"); + IPADMA_DBG_LOW("no pending work\n"); return false; } @@ -309,7 +331,7 @@ int ipa3_dma_disable(void) mutex_lock(&ipa3_dma_ctx->enable_lock); spin_lock_irqsave(&ipa3_dma_ctx->pending_lock, flags); if (!ipa3_dma_ctx->is_enabled) { - IPADMA_DBG("Already disabled.\n"); + IPADMA_ERR("Already disabled.\n"); spin_unlock_irqrestore(&ipa3_dma_ctx->pending_lock, flags); mutex_unlock(&ipa3_dma_ctx->enable_lock); return -EPERM; @@ -358,7 +380,7 @@ int ipa3_dma_sync_memcpy(u64 dest, u64 src, int len) bool stop_polling = false; IPADMA_FUNC_ENTRY(); - IPADMA_DBG("input parameters: dest = 0x%llx, src = 0x%llx, len = %d\n", + IPADMA_DBG_LOW("dest = 0x%llx, src = 0x%llx, len = %d\n", dest, src, len); if (ipa3_dma_ctx == NULL) { IPADMA_ERR("IPADMA isn't initialized, can't memcpy\n"); @@ -390,7 +412,7 @@ int ipa3_dma_sync_memcpy(u64 dest, u64 src, int len) if (atomic_read(&ipa3_dma_ctx->sync_memcpy_pending_cnt) >= IPA_DMA_MAX_PENDING_SYNC) { atomic_dec(&ipa3_dma_ctx->sync_memcpy_pending_cnt); - IPADMA_DBG("Reached pending requests limit\n"); + IPADMA_ERR("Reached pending requests limit\n"); return -EFAULT; } } @@ -575,7 +597,7 @@ int ipa3_dma_async_memcpy(u64 dest, u64 src, int len, unsigned long flags; IPADMA_FUNC_ENTRY(); - IPADMA_DBG("input parameters: dest = 0x%llx, src = 0x%llx, len = %d\n", + IPADMA_DBG_LOW("dest = 0x%llx, src = 0x%llx, len = %d\n", dest, src, len); if (ipa3_dma_ctx == NULL) { IPADMA_ERR("IPADMA isn't initialized, can't memcpy\n"); @@ -612,7 +634,7 @@ int ipa3_dma_async_memcpy(u64 dest, u64 src, int len, if (atomic_read(&ipa3_dma_ctx->async_memcpy_pending_cnt) >= IPA_DMA_MAX_PENDING_ASYNC) { atomic_dec(&ipa3_dma_ctx->async_memcpy_pending_cnt); - IPADMA_DBG("Reached pending requests limit\n"); + IPADMA_ERR("Reached pending requests limit\n"); return -EFAULT; } } @@ -774,7 +796,7 @@ void ipa3_dma_destroy(void) IPADMA_FUNC_ENTRY(); if (!ipa3_dma_ctx) { - IPADMA_DBG("IPADMA isn't initialized\n"); + IPADMA_ERR("IPADMA isn't initialized\n"); return; } @@ -919,7 +941,7 @@ static ssize_t ipa3_dma_debugfs_reset_statistics(struct file *file, switch (in_num) { case 0: if (ipa3_dma_work_pending()) - IPADMA_DBG("Note, there are pending memcpy\n"); + IPADMA_ERR("Note, there are pending memcpy\n"); atomic_set(&ipa3_dma_ctx->total_async_memcpy, 0); atomic_set(&ipa3_dma_ctx->total_sync_memcpy, 0); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 73961224f441..5e67101a987f 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -52,7 +52,6 @@ #define IPA_SIZE_DL_CSUM_META_TRAILER 8 #define IPA_GSI_EVT_RING_LEN 4096 -#define IPA_GSI_CHANNEL_RING_LEN 4096 #define IPA_GSI_MAX_CH_LOW_WEIGHT 15 #define IPA_GSI_EVT_RING_INT_MODT 3200 /* 0.1s under 32KHz clock */ @@ -75,7 +74,8 @@ static void ipa3_cleanup_wlan_rx_common_cache(void); static void ipa3_wq_repl_rx(struct work_struct *work); static void ipa3_dma_memcpy_notify(struct ipa3_sys_context *sys, struct ipa3_mem_buffer *mem_info); -static int ipa_gsi_setup_channel(struct ipa3_ep_context *ep); +static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in, + struct ipa3_ep_context *ep); static int ipa_populate_tag_field(struct ipa3_desc *desc, struct ipa3_tx_pkt_wrapper *tx_pkt, struct ipahal_imm_cmd_pyld **tag_pyld_ret); @@ -1174,7 +1174,7 @@ int ipa3_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl) } if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) { - result = ipa_gsi_setup_channel(ep); + result = ipa_gsi_setup_channel(sys_in, ep); if (result) { IPAERR("Failed to setup GSI channel\n"); goto fail_gen2; @@ -3569,7 +3569,8 @@ static void ipa_dma_gsi_irq_rx_notify_cb(struct gsi_chan_xfer_notify *notify) } -static int ipa_gsi_setup_channel(struct ipa3_ep_context *ep) +static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in, + struct ipa3_ep_context *ep) { struct gsi_evt_ring_props gsi_evt_ring_props; struct gsi_chan_props gsi_channel_props; @@ -3642,10 +3643,19 @@ static int ipa_gsi_setup_channel(struct ipa3_ep_context *ep) gsi_channel_props.evt_ring_hdl = ep->gsi_evt_ring_hdl; gsi_channel_props.re_size = GSI_CHAN_RE_SIZE_16B; - gsi_channel_props.ring_len = IPA_GSI_CHANNEL_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. For PROD pipes there is also an additional descriptor + * for TAG STATUS immediate command. + */ + if (IPA_CLIENT_IS_PROD(ep->client)) + gsi_channel_props.ring_len = 4 * in->desc_fifo_sz; + else + gsi_channel_props.ring_len = 2 * in->desc_fifo_sz; gsi_channel_props.ring_base_vaddr = - dma_alloc_coherent(ipa3_ctx->pdev, IPA_GSI_CHANNEL_RING_LEN, - &dma_addr, 0); + dma_alloc_coherent(ipa3_ctx->pdev, gsi_channel_props.ring_len, + &dma_addr, 0); gsi_channel_props.ring_base_addr = dma_addr; /* copy mem info */ @@ -3655,7 +3665,7 @@ static int ipa_gsi_setup_channel(struct ipa3_ep_context *ep) ep->gsi_mem_info.chan_ring_base_vaddr = gsi_channel_props.ring_base_vaddr; - gsi_channel_props.use_db_eng = GSI_CHAN_DIRECT_MODE; + gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE; gsi_channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG; if (ep->client == IPA_CLIENT_APPS_CMD_PROD) gsi_channel_props.low_weight = IPA_GSI_MAX_CH_LOW_WEIGHT; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index f58751d4c0d3..bb94b95eabb9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -22,12 +22,6 @@ static const u32 ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN_MAX] = { 32, 64}; #define HDR_PROC_TYPE_IS_VALID(type) \ ((type) >= 0 && (type) < IPA_HDR_PROC_MAX) -/* uCP command numbers */ -#define IPA_HDR_UCP_802_3_TO_802_3 6 -#define IPA_HDR_UCP_802_3_TO_ETHII 7 -#define IPA_HDR_UCP_ETHII_TO_802_3 8 -#define IPA_HDR_UCP_ETHII_TO_ETHII 9 - /** * ipa3_generate_hdr_hw_tbl() - generates the headers table * @mem: [out] buffer to put the header table @@ -60,8 +54,8 @@ static int ipa3_generate_hdr_hw_tbl(struct ipa3_mem_buffer *mem) continue; IPADBG_LOW("hdr of len %d ofst=%d\n", entry->hdr_len, entry->offset_entry->offset); - memcpy(mem->base + entry->offset_entry->offset, entry->hdr, - entry->hdr_len); + ipahal_cp_hdr_to_hw_buff(mem->base, entry->offset_entry->offset, + entry->hdr, entry->hdr_len); } return 0; @@ -77,52 +71,13 @@ static void ipa3_hdr_proc_ctx_to_hw_format(struct ipa3_mem_buffer *mem, link) { IPADBG_LOW("processing type %d ofst=%d\n", entry->type, entry->offset_entry->offset); - if (entry->type == IPA_HDR_PROC_NONE) { - struct ipa3_hdr_proc_ctx_add_hdr_seq *ctx; - - ctx = (struct ipa3_hdr_proc_ctx_add_hdr_seq *) - (mem->base + entry->offset_entry->offset); - ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD; - ctx->hdr_add.tlv.length = 1; - ctx->hdr_add.tlv.value = entry->hdr->hdr_len; - ctx->hdr_add.hdr_addr = (entry->hdr->is_hdr_proc_ctx) ? - entry->hdr->phys_base : - hdr_base_addr + - entry->hdr->offset_entry->offset; - IPADBG_LOW("header address 0x%x\n", - ctx->hdr_add.hdr_addr); - ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END; - ctx->end.length = 0; - ctx->end.value = 0; - } else { - struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq *ctx; - - ctx = (struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq *) - (mem->base + entry->offset_entry->offset); - ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD; - ctx->hdr_add.tlv.length = 1; - ctx->hdr_add.tlv.value = entry->hdr->hdr_len; - ctx->hdr_add.hdr_addr = (entry->hdr->is_hdr_proc_ctx) ? - entry->hdr->phys_base : - hdr_base_addr + - entry->hdr->offset_entry->offset; - IPADBG_LOW("header address 0x%x\n", - ctx->hdr_add.hdr_addr); - ctx->cmd.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD; - ctx->cmd.length = 0; - if (entry->type == IPA_HDR_PROC_ETHII_TO_ETHII) - ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_ETHII; - else if (entry->type == IPA_HDR_PROC_ETHII_TO_802_3) - ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_802_3; - else if (entry->type == IPA_HDR_PROC_802_3_TO_ETHII) - ctx->cmd.value = IPA_HDR_UCP_802_3_TO_ETHII; - else if (entry->type == IPA_HDR_PROC_802_3_TO_802_3) - ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3; - IPADBG_LOW("command id %d\n", ctx->cmd.value); - ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END; - ctx->end.length = 0; - ctx->end.value = 0; - } + ipahal_cp_proc_ctx_to_hw_buff(entry->type, mem->base, + entry->offset_entry->offset, + entry->hdr->hdr_len, + entry->hdr->is_hdr_proc_ctx, + entry->hdr->phys_base, + hdr_base_addr, + entry->hdr->offset_entry->offset); } } @@ -395,9 +350,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, hdr_entry->ref_cnt++; entry->cookie = IPA_COOKIE; - needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ? - sizeof(struct ipa3_hdr_proc_ctx_add_hdr_seq) : - sizeof(struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq); + needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type); if (needed_len <= ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN0]) { bin = IPA_HDR_PROC_CTX_BIN0; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h index 1b732efe2b2c..38a63f8a67ba 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h @@ -16,11 +16,6 @@ /* This header defines various HW related data types */ -/* Processing context TLV type */ -#define IPA_PROC_CTX_TLV_TYPE_END 0 -#define IPA_PROC_CTX_TLV_TYPE_HDR_ADD 1 -#define IPA_PROC_CTX_TLV_TYPE_PROC_CMD 3 - #define IPA_RULE_ID_INVALID 0x3FF /** @@ -94,40 +89,6 @@ struct ipa3_rt_rule_hw_hdr { } u; }; -/** - * struct ipa3_hdr_proc_ctx_tlv - - * HW structure of IPA processing context header - TLV part - * @type: 0 - end type - * 1 - header addition type - * 3 - processing command type - * @length: number of bytes after tlv - * for type: - * 0 - needs to be 0 - * 1 - header addition length - * 3 - number of 32B including type and length. - * @value: specific value for type - * for type: - * 0 - needs to be 0 - * 1 - header length - * 3 - command ID (see IPA_HDR_UCP_* definitions) - */ -struct ipa3_hdr_proc_ctx_tlv { - u32 type:8; - u32 length:8; - u32 value:16; -}; - -/** - * struct ipa3_hdr_proc_ctx_hdr_add - - * HW structure of IPA processing context - add header tlv - * @tlv: IPA processing context TLV - * @hdr_addr: processing context header address - */ -struct ipa3_hdr_proc_ctx_hdr_add { - struct ipa3_hdr_proc_ctx_tlv tlv; - u32 hdr_addr; -}; - #define IPA_A5_MUX_HDR_EXCP_FLAG_IP BIT(7) #define IPA_A5_MUX_HDR_EXCP_FLAG_NAT BIT(6) #define IPA_A5_MUX_HDR_EXCP_FLAG_SW_FLT BIT(5) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 62c764d29171..cec83ef7a202 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -27,7 +27,6 @@ #include <asm/dma-iommu.h> #include <linux/iommu.h> #include <linux/platform_device.h> -#include <linux/ipc_logging.h> #include <linux/firmware.h> #include "ipa_hw_defs.h" #include "ipa_ram_mmap.h" @@ -56,32 +55,35 @@ #define IPA_MAX_STATUS_STAT_NUM 30 -#define IPA_IPC_LOGGING(buf, fmt, args...) \ - ipc_log_string((buf), \ - DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) +#define IPA_IPC_LOG_PAGES 50 #define IPADBG(fmt, args...) \ do { \ pr_debug(DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args);\ if (ipa3_ctx) { \ - IPA_IPC_LOGGING(ipa3_ctx->logbuf, fmt, ## args); \ - IPA_IPC_LOGGING(ipa3_ctx->logbuf_low, fmt, ## args); \ + IPA_IPC_LOGGING(ipa3_ctx->logbuf, \ + DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa3_ctx->logbuf_low, \ + DRV_NAME " %s:%d " fmt, ## args); \ } \ } while (0) #define IPADBG_LOW(fmt, args...) \ do { \ pr_debug(DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args);\ - if (ipa3_ctx && ipa3_ctx->enable_low_prio_print) \ - IPA_IPC_LOGGING(ipa3_ctx->logbuf_low, fmt, ## args); \ + if (ipa3_ctx) \ + IPA_IPC_LOGGING(ipa3_ctx->logbuf_low, \ + DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define IPAERR(fmt, args...) \ do { \ pr_err(DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args);\ if (ipa3_ctx) { \ - IPA_IPC_LOGGING(ipa3_ctx->logbuf, fmt, ## args); \ - IPA_IPC_LOGGING(ipa3_ctx->logbuf_low, fmt, ## args); \ + IPA_IPC_LOGGING(ipa3_ctx->logbuf, \ + DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa3_ctx->logbuf_low, \ + DRV_NAME " %s:%d " fmt, ## args); \ } \ } while (0) @@ -394,30 +396,6 @@ struct ipa3_hdr_proc_ctx_offset_entry { }; /** - * struct ipa3_hdr_proc_ctx_add_hdr_seq - - * IPA processing context header - add header sequence - * @hdr_add: add header command - * @end: tlv end command (cmd.type must be 0) - */ -struct ipa3_hdr_proc_ctx_add_hdr_seq { - struct ipa3_hdr_proc_ctx_hdr_add hdr_add; - struct ipa3_hdr_proc_ctx_tlv end; -}; - -/** - * struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq - - * IPA processing context header - process command sequence - * @hdr_add: add header command - * @cmd: tlv processing command (cmd.type must be 3) - * @end: tlv end command (cmd.type must be 0) - */ -struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq { - struct ipa3_hdr_proc_ctx_hdr_add hdr_add; - struct ipa3_hdr_proc_ctx_tlv cmd; - struct ipa3_hdr_proc_ctx_tlv end; -}; - -/** struct ipa3_hdr_proc_ctx_entry - IPA processing context header table entry * @link: entry's link in global header table entries list * @type: @@ -1432,7 +1410,6 @@ struct ipa3_ready_cb_info { * @ctrl: holds the core specific operations based on * core version (vtable like) * @enable_clock_scaling: clock scaling is enabled ? - * @enable_low_prio_print: enable low priority prints * @curr_ipa_clk_rate: ipa3_clk current rate * @wcstats: wlan common buffer stats * @uc_ctx: uC interface context @@ -1537,7 +1514,6 @@ struct ipa3_context { struct device *uc_pdev; spinlock_t idr_lock; u32 enable_clock_scaling; - u32 enable_low_prio_print; u32 curr_ipa_clk_rate; bool q6_proxy_clk_vote_valid; u32 ipa_num_pipes; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c index 45d3b13049bc..ca022b6332dd 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c @@ -413,12 +413,6 @@ int ipa3_remove_interrupt_handler(enum ipa_irq_type interrupt) return -EFAULT; } - kfree(ipa_interrupt_to_cb[irq_num].private_data); - ipa_interrupt_to_cb[irq_num].deferred_flag = false; - ipa_interrupt_to_cb[irq_num].handler = NULL; - ipa_interrupt_to_cb[irq_num].private_data = NULL; - ipa_interrupt_to_cb[irq_num].interrupt = -1; - /* clean SUSPEND_IRQ_EN_EE_n_ADDR for L2 interrupt */ if ((interrupt == IPA_TX_SUSPEND_IRQ) && (ipa3_ctx->ipa_hw_type == IPA_HW_v3_1)) { @@ -431,6 +425,13 @@ int ipa3_remove_interrupt_handler(enum ipa_irq_type interrupt) val &= ~bmsk; ipa3_uc_rg10_write_reg(IPA_IRQ_EN_EE_n, ipa_ee, val); + /* delete the handlers after clean-up interrupts */ + kfree(ipa_interrupt_to_cb[irq_num].private_data); + ipa_interrupt_to_cb[irq_num].deferred_flag = false; + ipa_interrupt_to_cb[irq_num].handler = NULL; + ipa_interrupt_to_cb[irq_num].private_data = NULL; + ipa_interrupt_to_cb[irq_num].interrupt = -1; + return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c index 82f63d3cf5a5..517093adbe81 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c @@ -21,15 +21,42 @@ #include "ipa_qmi_service.h" #define IPA_MHI_DRV_NAME "ipa_mhi" + + #define IPA_MHI_DBG(fmt, args...) \ - pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ - __func__, __LINE__, ## args) + do { \ + pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + +#define IPA_MHI_DBG_LOW(fmt, args...) \ + do { \ + pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + + #define IPA_MHI_ERR(fmt, args...) \ - pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + + #define IPA_MHI_FUNC_ENTRY() \ - IPA_MHI_DBG("ENTRY\n") + IPA_MHI_DBG_LOW("ENTRY\n") #define IPA_MHI_FUNC_EXIT() \ - IPA_MHI_DBG("EXIT\n") + IPA_MHI_DBG_LOW("EXIT\n") #define IPA_MHI_GSI_ER_START 10 #define IPA_MHI_GSI_ER_END 16 @@ -756,12 +783,12 @@ static void ipa3_mhi_rm_prod_notify(void *user_data, enum ipa_rm_event event, switch (event) { case IPA_RM_RESOURCE_GRANTED: - IPA_MHI_DBG("IPA_RM_RESOURCE_GRANTED\n"); + IPA_MHI_DBG_LOW("IPA_RM_RESOURCE_GRANTED\n"); complete_all(&ipa3_mhi_ctx->rm_prod_granted_comp); break; case IPA_RM_RESOURCE_RELEASED: - IPA_MHI_DBG("IPA_RM_RESOURCE_RELEASED\n"); + IPA_MHI_DBG_LOW("IPA_RM_RESOURCE_RELEASED\n"); break; default: @@ -828,7 +855,7 @@ static int ipa3_mhi_rm_cons_request(void) } spin_unlock_irqrestore(&ipa3_mhi_ctx->state_lock, flags); - IPA_MHI_DBG("EXIT with %d\n", res); + IPA_MHI_DBG_LOW("EXIT with %d\n", res); return res; } @@ -878,7 +905,7 @@ static int ipa3_mhi_request_prod(void) IPA_MHI_FUNC_ENTRY(); reinit_completion(&ipa3_mhi_ctx->rm_prod_granted_comp); - IPA_MHI_DBG("requesting mhi prod\n"); + IPA_MHI_DBG_LOW("requesting mhi prod\n"); res = ipa_rm_request_resource(IPA_RM_RESOURCE_MHI_PROD); if (res) { if (res != -EINPROGRESS) { @@ -894,7 +921,7 @@ static int ipa3_mhi_request_prod(void) } } - IPA_MHI_DBG("mhi prod granted\n"); + IPA_MHI_DBG_LOW("mhi prod granted\n"); IPA_MHI_FUNC_EXIT(); return 0; @@ -1071,11 +1098,12 @@ static bool ipa3_mhi_gsi_channel_empty(struct ipa3_mhi_channel_ctx *channel) IPA_MHI_FUNC_ENTRY(); if (!channel->stop_in_proc) { - IPA_MHI_DBG("Channel is not in STOP_IN_PROC\n"); + IPA_MHI_DBG_LOW("Channel is not in STOP_IN_PROC\n"); return true; } - IPA_MHI_DBG("Stopping GSI channel %ld\n", channel->ep->gsi_chan_hdl); + IPA_MHI_DBG_LOW("Stopping GSI channel %ld\n", + channel->ep->gsi_chan_hdl); res = gsi_stop_channel(channel->ep->gsi_chan_hdl); if (res != 0 && res != -GSI_STATUS_AGAIN && @@ -1087,7 +1115,7 @@ static bool ipa3_mhi_gsi_channel_empty(struct ipa3_mhi_channel_ctx *channel) } if (res == 0) { - IPA_MHI_DBG("GSI channel %ld STOP\n", + IPA_MHI_DBG_LOW("GSI channel %ld STOP\n", channel->ep->gsi_chan_hdl); channel->stop_in_proc = false; return true; @@ -1129,7 +1157,7 @@ static bool ipa3_mhi_wait_for_ul_empty_timeout(unsigned int msecs) } if (time_after(jiffies, jiffies_start + jiffies_timeout)) { - IPA_MHI_DBG("timeout waiting for UL empty\n"); + IPA_MHI_DBG_LOW("timeout waiting for UL empty\n"); break; } @@ -1441,31 +1469,31 @@ static int ipa_mhi_start_uc_channel(struct ipa3_mhi_channel_ctx *channel, static void ipa_mhi_dump_ch_ctx(struct ipa3_mhi_channel_ctx *channel) { - IPA_MHI_DBG("ch_id %d\n", channel->id); - IPA_MHI_DBG("chstate 0x%x\n", channel->ch_ctx_host.chstate); - IPA_MHI_DBG("brstmode 0x%x\n", channel->ch_ctx_host.brstmode); - IPA_MHI_DBG("pollcfg 0x%x\n", channel->ch_ctx_host.pollcfg); - IPA_MHI_DBG("chtype 0x%x\n", channel->ch_ctx_host.chtype); - IPA_MHI_DBG("erindex 0x%x\n", channel->ch_ctx_host.erindex); - IPA_MHI_DBG("rbase 0x%llx\n", channel->ch_ctx_host.rbase); - IPA_MHI_DBG("rlen 0x%llx\n", channel->ch_ctx_host.rlen); - IPA_MHI_DBG("rp 0x%llx\n", channel->ch_ctx_host.rp); - IPA_MHI_DBG("wp 0x%llx\n", channel->ch_ctx_host.wp); + IPA_MHI_DBG_LOW("ch_id %d\n", channel->id); + IPA_MHI_DBG_LOW("chstate 0x%x\n", channel->ch_ctx_host.chstate); + IPA_MHI_DBG_LOW("brstmode 0x%x\n", channel->ch_ctx_host.brstmode); + IPA_MHI_DBG_LOW("pollcfg 0x%x\n", channel->ch_ctx_host.pollcfg); + IPA_MHI_DBG_LOW("chtype 0x%x\n", channel->ch_ctx_host.chtype); + IPA_MHI_DBG_LOW("erindex 0x%x\n", channel->ch_ctx_host.erindex); + IPA_MHI_DBG_LOW("rbase 0x%llx\n", channel->ch_ctx_host.rbase); + IPA_MHI_DBG_LOW("rlen 0x%llx\n", channel->ch_ctx_host.rlen); + IPA_MHI_DBG_LOW("rp 0x%llx\n", channel->ch_ctx_host.rp); + IPA_MHI_DBG_LOW("wp 0x%llx\n", channel->ch_ctx_host.wp); } static void ipa_mhi_dump_ev_ctx(struct ipa3_mhi_channel_ctx *channel) { - IPA_MHI_DBG("ch_id %d event id %d\n", channel->id, + IPA_MHI_DBG_LOW("ch_id %d event id %d\n", channel->id, channel->ch_ctx_host.erindex); - IPA_MHI_DBG("intmodc 0x%x\n", channel->ev_ctx_host.intmodc); - IPA_MHI_DBG("intmodt 0x%x\n", channel->ev_ctx_host.intmodt); - IPA_MHI_DBG("ertype 0x%x\n", channel->ev_ctx_host.ertype); - IPA_MHI_DBG("msivec 0x%x\n", channel->ev_ctx_host.msivec); - IPA_MHI_DBG("rbase 0x%llx\n", channel->ev_ctx_host.rbase); - IPA_MHI_DBG("rlen 0x%llx\n", channel->ev_ctx_host.rlen); - IPA_MHI_DBG("rp 0x%llx\n", channel->ev_ctx_host.rp); - IPA_MHI_DBG("wp 0x%llx\n", channel->ev_ctx_host.wp); + IPA_MHI_DBG_LOW("intmodc 0x%x\n", channel->ev_ctx_host.intmodc); + IPA_MHI_DBG_LOW("intmodt 0x%x\n", channel->ev_ctx_host.intmodt); + IPA_MHI_DBG_LOW("ertype 0x%x\n", channel->ev_ctx_host.ertype); + IPA_MHI_DBG_LOW("msivec 0x%x\n", channel->ev_ctx_host.msivec); + IPA_MHI_DBG_LOW("rbase 0x%llx\n", channel->ev_ctx_host.rbase); + IPA_MHI_DBG_LOW("rlen 0x%llx\n", channel->ev_ctx_host.rlen); + IPA_MHI_DBG_LOW("rp 0x%llx\n", channel->ev_ctx_host.rp); + IPA_MHI_DBG_LOW("wp 0x%llx\n", channel->ev_ctx_host.wp); } static int ipa_mhi_read_ch_ctx(struct ipa3_mhi_channel_ctx *channel) @@ -1671,9 +1699,10 @@ static int ipa_mhi_start_gsi_channel(struct ipa3_mhi_channel_ctx *channel, channel->channel_context_addr + offsetof(struct ipa3_mhi_ch_ctx, wp)); ch_scratch.mhi.assert_bit40 = ipa3_mhi_ctx->assert_bit40; - ch_scratch.mhi.max_outstanding_tre = 0; + ch_scratch.mhi.max_outstanding_tre = + ep_cfg->ipa_if_tlv * ch_props.re_size; ch_scratch.mhi.outstanding_threshold = - 4 * GSI_CHAN_RE_SIZE_16B; + min(ep_cfg->ipa_if_tlv / 2, 8) * ch_props.re_size; ch_scratch.mhi.oob_mod_threshold = 4; if (channel->ch_ctx_host.brstmode == IPA_MHI_BURST_MODE_DEFAULT || channel->ch_ctx_host.brstmode == IPA_MHI_BURST_MODE_ENABLE) { @@ -2234,7 +2263,7 @@ static int ipa3_mhi_suspend_ul_channels(void) if (ipa3_mhi_ctx->ul_channels[i].state != IPA_HW_MHI_CHANNEL_STATE_RUN) continue; - IPA_MHI_DBG("suspending channel %d\n", + IPA_MHI_DBG_LOW("suspending channel %d\n", ipa3_mhi_ctx->ul_channels[i].id); if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) @@ -2270,7 +2299,7 @@ static int ipa3_mhi_resume_ul_channels(bool LPTransitionRejected) IPA_HW_MHI_CHANNEL_STATE_SUSPEND) continue; channel = &ipa3_mhi_ctx->ul_channels[i]; - IPA_MHI_DBG("resuming channel %d\n", channel->id); + IPA_MHI_DBG_LOW("resuming channel %d\n", channel->id); if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) { if (channel->brstmode_enabled && @@ -2323,7 +2352,7 @@ static int ipa3_mhi_stop_event_update_ul_channels(void) if (ipa3_mhi_ctx->ul_channels[i].state != IPA_HW_MHI_CHANNEL_STATE_SUSPEND) continue; - IPA_MHI_DBG("stop update event channel %d\n", + IPA_MHI_DBG_LOW("stop update event channel %d\n", ipa3_mhi_ctx->ul_channels[i].id); res = ipa3_uc_mhi_stop_event_update_channel( ipa3_mhi_ctx->ul_channels[i].index); @@ -2350,7 +2379,7 @@ static int ipa3_mhi_suspend_dl_channels(void) if (ipa3_mhi_ctx->dl_channels[i].state != IPA_HW_MHI_CHANNEL_STATE_RUN) continue; - IPA_MHI_DBG("suspending channel %d\n", + IPA_MHI_DBG_LOW("suspending channel %d\n", ipa3_mhi_ctx->dl_channels[i].id); if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) res = ipa3_mhi_suspend_gsi_channel( @@ -2385,7 +2414,7 @@ static int ipa3_mhi_resume_dl_channels(bool LPTransitionRejected) IPA_HW_MHI_CHANNEL_STATE_SUSPEND) continue; channel = &ipa3_mhi_ctx->dl_channels[i]; - IPA_MHI_DBG("resuming channel %d\n", channel->id); + IPA_MHI_DBG_LOW("resuming channel %d\n", channel->id); if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) { if (channel->brstmode_enabled && @@ -2436,7 +2465,7 @@ static int ipa3_mhi_stop_event_update_dl_channels(void) if (ipa3_mhi_ctx->dl_channels[i].state != IPA_HW_MHI_CHANNEL_STATE_SUSPEND) continue; - IPA_MHI_DBG("stop update event channel %d\n", + IPA_MHI_DBG_LOW("stop update event channel %d\n", ipa3_mhi_ctx->dl_channels[i].id); res = ipa3_uc_mhi_stop_event_update_channel( ipa3_mhi_ctx->dl_channels[i].index); @@ -2576,7 +2605,7 @@ static bool ipa3_mhi_has_open_aggr_frame(void) int ipa_ep_idx; aggr_state_active = ipahal_read_reg(IPA_STATE_AGGR_ACTIVE); - IPA_MHI_DBG("IPA_STATE_AGGR_ACTIVE_OFST 0x%x\n", aggr_state_active); + IPA_MHI_DBG_LOW("IPA_STATE_AGGR_ACTIVE_OFST 0x%x\n", aggr_state_active); for (i = 0; i < IPA_MHI_MAX_DL_CHANNELS; i++) { channel = &ipa3_mhi_ctx->dl_channels[i]; @@ -2646,7 +2675,7 @@ int ipa3_mhi_suspend(bool force) return res; } force_clear = true; - IPA_MHI_DBG("force clear datapath enabled\n"); + IPA_MHI_DBG_LOW("force clear datapath enabled\n"); empty = ipa3_mhi_wait_for_ul_empty_timeout( IPA_MHI_CH_EMPTY_TIMEOUT_MSEC); @@ -2675,7 +2704,7 @@ int ipa3_mhi_suspend(bool force) BUG(); return res; } - IPA_MHI_DBG("force clear datapath disabled\n"); + IPA_MHI_DBG_LOW("force clear datapath disabled\n"); ipa3_mhi_ctx->qmi_req_id++; } @@ -2700,14 +2729,14 @@ int ipa3_mhi_suspend(bool force) */ IPA_ACTIVE_CLIENTS_INC_SIMPLE(); - IPA_MHI_DBG("release prod\n"); + IPA_MHI_DBG_LOW("release prod\n"); res = ipa3_mhi_release_prod(); if (res) { IPA_MHI_ERR("ipa3_mhi_release_prod failed %d\n", res); goto fail_release_prod; } - IPA_MHI_DBG("wait for cons release\n"); + IPA_MHI_DBG_LOW("wait for cons release\n"); res = ipa3_mhi_wait_for_cons_release(); if (res) { IPA_MHI_ERR("ipa3_mhi_wait_for_cons_release failed %d\n", res); @@ -2771,7 +2800,7 @@ fail_suspend_ul_channel: IPA_MHI_ERR("failed to disable force clear\n"); BUG(); } - IPA_MHI_DBG("force clear datapath disabled\n"); + IPA_MHI_DBG_LOW("force clear datapath disabled\n"); ipa3_mhi_ctx->qmi_req_id++; } return res; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c index 4cd655aa8124..6444dcf3cfdc 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c @@ -356,7 +356,7 @@ static void ipa3_a5_svc_recv_msg(struct work_struct *work) int rc; do { - IPAWANDBG("Notified about a Receive Event"); + IPAWANDBG_LOW("Notified about a Receive Event"); rc = qmi_recv_msg(ipa3_svc_handle); } while (rc == 0); if (rc != -ENOMSG) @@ -430,7 +430,7 @@ static int ipa3_check_qmi_response(int rc, req_id, result, error); return result; } - IPAWANDBG("Received %s successfully\n", resp_type); + IPAWANDBG_LOW("Received %s successfully\n", resp_type); return 0; } @@ -762,7 +762,7 @@ static void ipa3_q6_clnt_recv_msg(struct work_struct *work) int rc; do { - IPAWANDBG("Notified about a Receive Event"); + IPAWANDBG_LOW("Notified about a Receive Event"); rc = qmi_recv_msg(ipa_q6_clnt); } while (rc == 0); if (rc != -ENOMSG) @@ -774,7 +774,7 @@ static void ipa3_q6_clnt_notify(struct qmi_handle *handle, { switch (event) { case QMI_RECV_MSG: - IPAWANDBG("client qmi recv message called"); + IPAWANDBG_LOW("client qmi recv message called"); if (!workqueues_stopped) queue_delayed_work(ipa_clnt_resp_workqueue, &ipa3_work_recv_msg_client, 0); @@ -1154,7 +1154,7 @@ int ipa3_qmi_get_data_stats(struct ipa_get_data_stats_req_msg_v01 *req, resp_desc.msg_id = QMI_IPA_GET_DATA_STATS_RESP_V01; resp_desc.ei_array = ipa3_get_data_stats_resp_msg_data_v01_ei; - IPAWANDBG("Sending QMI_IPA_GET_DATA_STATS_REQ_V01\n"); + IPAWANDBG_LOW("Sending QMI_IPA_GET_DATA_STATS_REQ_V01\n"); rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, req, sizeof(struct ipa_get_data_stats_req_msg_v01), @@ -1162,7 +1162,7 @@ int ipa3_qmi_get_data_stats(struct ipa_get_data_stats_req_msg_v01 *req, sizeof(struct ipa_get_data_stats_resp_msg_v01), QMI_SEND_STATS_REQ_TIMEOUT_MS); - IPAWANDBG("QMI_IPA_GET_DATA_STATS_RESP_V01 received\n"); + IPAWANDBG_LOW("QMI_IPA_GET_DATA_STATS_RESP_V01 received\n"); return ipa3_check_qmi_response(rc, QMI_IPA_GET_DATA_STATS_REQ_V01, resp->resp.result, @@ -1183,7 +1183,7 @@ int ipa3_qmi_get_network_stats(struct ipa_get_apn_data_stats_req_msg_v01 *req, resp_desc.msg_id = QMI_IPA_GET_APN_DATA_STATS_RESP_V01; resp_desc.ei_array = ipa3_get_apn_data_stats_resp_msg_data_v01_ei; - IPAWANDBG("Sending QMI_IPA_GET_APN_DATA_STATS_REQ_V01\n"); + IPAWANDBG_LOW("Sending QMI_IPA_GET_APN_DATA_STATS_REQ_V01\n"); rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, req, sizeof(struct ipa_get_apn_data_stats_req_msg_v01), @@ -1191,7 +1191,7 @@ int ipa3_qmi_get_network_stats(struct ipa_get_apn_data_stats_req_msg_v01 *req, sizeof(struct ipa_get_apn_data_stats_resp_msg_v01), QMI_SEND_STATS_REQ_TIMEOUT_MS); - IPAWANDBG("QMI_IPA_GET_APN_DATA_STATS_RESP_V01 received\n"); + IPAWANDBG_LOW("QMI_IPA_GET_APN_DATA_STATS_RESP_V01 received\n"); return ipa3_check_qmi_response(rc, QMI_IPA_GET_APN_DATA_STATS_REQ_V01, resp->resp.result, @@ -1215,14 +1215,14 @@ int ipa3_qmi_set_data_quota(struct ipa_set_data_usage_quota_req_msg_v01 *req) resp_desc.msg_id = QMI_IPA_SET_DATA_USAGE_QUOTA_RESP_V01; resp_desc.ei_array = ipa3_set_data_usage_quota_resp_msg_data_v01_ei; - IPAWANDBG("Sending QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01\n"); + IPAWANDBG_LOW("Sending QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01\n"); rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, req, sizeof(struct ipa_set_data_usage_quota_req_msg_v01), &resp_desc, &resp, sizeof(resp), QMI_SEND_STATS_REQ_TIMEOUT_MS); - IPAWANDBG("QMI_IPA_SET_DATA_USAGE_QUOTA_RESP_V01 received\n"); + IPAWANDBG_LOW("QMI_IPA_SET_DATA_USAGE_QUOTA_RESP_V01 received\n"); return ipa3_check_qmi_response(rc, QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01, resp.resp.result, @@ -1249,13 +1249,13 @@ int ipa3_qmi_stop_data_qouta(void) resp_desc.msg_id = QMI_IPA_STOP_DATA_USAGE_QUOTA_RESP_V01; resp_desc.ei_array = ipa3_stop_data_usage_quota_resp_msg_data_v01_ei; - IPAWANDBG("Sending QMI_IPA_STOP_DATA_USAGE_QUOTA_REQ_V01\n"); + IPAWANDBG_LOW("Sending QMI_IPA_STOP_DATA_USAGE_QUOTA_REQ_V01\n"); rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, &req, sizeof(req), &resp_desc, &resp, sizeof(resp), QMI_SEND_STATS_REQ_TIMEOUT_MS); - IPAWANDBG("QMI_IPA_STOP_DATA_USAGE_QUOTA_RESP_V01 received\n"); + IPAWANDBG_LOW("QMI_IPA_STOP_DATA_USAGE_QUOTA_RESP_V01 received\n"); return ipa3_check_qmi_response(rc, QMI_IPA_STOP_DATA_USAGE_QUOTA_REQ_V01, resp.resp.result, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h index 5f6722d3fbac..0f641204cc77 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h @@ -31,11 +31,39 @@ #define SUBSYS_MODEM "modem" #define IPAWANDBG(fmt, args...) \ - pr_debug(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_debug(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + DEV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + DEV_NAME " %s:%d " fmt, ## args); \ + } while (0) + + +#define IPAWANDBG_LOW(fmt, args...) \ + do { \ + pr_debug(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + DEV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPAWANERR(fmt, args...) \ - pr_err(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_err(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + DEV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + DEV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPAWANINFO(fmt, args...) \ - pr_info(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) + do { \ + pr_info(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + DEV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + DEV_NAME " %s:%d " fmt, ## args); \ + } while (0) extern struct ipa3_qmi_context *ipa3_qmi_ctx; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 5ea39b732ee6..5574ef88398b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -4439,6 +4439,21 @@ int ipa3_disable_apps_wan_cons_deaggr(uint32_t agg_size, uint32_t agg_count) return res; } +static void *ipa3_get_ipc_logbuf(void) +{ + if (ipa3_ctx) + return ipa3_ctx->logbuf; + + return NULL; +} + +static void *ipa3_get_ipc_logbuf_low(void) +{ + if (ipa3_ctx) + return ipa3_ctx->logbuf_low; + + return NULL; +} int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, struct ipa_api_controller *api_ctrl) @@ -4576,6 +4591,8 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_suspend_resource_sync = ipa3_suspend_resource_sync; api_ctrl->ipa_set_required_perf_profile = ipa3_set_required_perf_profile; + api_ctrl->ipa_get_ipc_logbuf = ipa3_get_ipc_logbuf; + api_ctrl->ipa_get_ipc_logbuf_low = ipa3_get_ipc_logbuf_low; return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c index 1fbe8865e2d1..6a282d70a189 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c @@ -10,7 +10,6 @@ * GNU General Public License for more details. */ -#include <linux/ipc_logging.h> #include <linux/debugfs.h> #include "ipahal.h" #include "ipahal_i.h" @@ -987,46 +986,12 @@ const char *ipahal_pkt_status_exception_str( return ipahal_pkt_status_exception_to_str[exception]; } -static int ipahal_ipc_logging_init(void) -{ - ipahal_ctx->ipc_logbuf = - ipc_log_context_create(IPAHAL_IPC_LOG_PAGES, "ipahal", 0); - if (!ipahal_ctx->ipc_logbuf) { - /* Cannot use the logging macros as no log buffers yet */ - pr_err("ipaghal: failed to create ipc_logbuf\n"); - return -ENOMEM; - } - - ipahal_ctx->ipc_logbuf_low = - ipc_log_context_create(IPAHAL_IPC_LOG_PAGES, "ipahal_low", 0); - if (!ipahal_ctx->ipc_logbuf_low) { - /* Cannot use the logging macros as no log buffers yet */ - pr_err("ipaghal: failed to create ipc_logbuf_low\n"); - ipc_log_context_destroy(ipahal_ctx->ipc_logbuf); - return -ENOMEM; - } - - return 0; -} - #ifdef CONFIG_DEBUG_FS static void ipahal_debugfs_init(void) { - const mode_t read_write_mode = S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP; - ipahal_ctx->dent = debugfs_create_dir("ipahal", 0); if (!ipahal_ctx->dent || IS_ERR(ipahal_ctx->dent)) { IPAHAL_ERR("fail to create ipahal debugfs folder\n"); - return; - } - - ipahal_ctx->dfile_enable_low_prio_ipc = - debugfs_create_u32("enable_low_prio_log", read_write_mode, - ipahal_ctx->dent, &ipahal_ctx->enable_low_prio_ipc); - if (!ipahal_ctx->dfile_enable_low_prio_ipc || - IS_ERR(ipahal_ctx->dfile_enable_low_prio_ipc)) { - IPAHAL_ERR("fail create enable_low_prio_log debugfs file\n"); goto fail; } @@ -1053,6 +1018,223 @@ static void ipahal_debugfs_init(void) {} static void ipahal_debugfs_remove(void) {} #endif /* CONFIG_DEBUG_FS */ +/* + * ipahal_cp_hdr_to_hw_buff_v3() - copy header to hardware buffer according to + * base address and offset given. + * @base: dma base address + * @offset: offset from base address where the data will be copied + * @hdr: the header to be copied + * @hdr_len: the length of the header + */ +static void ipahal_cp_hdr_to_hw_buff_v3(void *const base, u32 offset, + u8 *const hdr, u32 hdr_len) +{ + memcpy(base + offset, hdr, hdr_len); +} + +/* + * ipahal_cp_proc_ctx_to_hw_buff_v3() - copy processing context to + * base address and offset given. + * @type: header processing context type (no processing context, + * IPA_HDR_PROC_ETHII_TO_ETHII etc.) + * @base: dma base address + * @offset: offset from base address where the data will be copied + * @hdr_len: the length of the header + * @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr + * @phys_base: memory location in DDR + * @hdr_base_addr: base address in table + * @hdr_offset_entry: offset from hdr_base_addr in table + */ +static void ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type, + void *const base, u32 offset, + u32 hdr_len, bool is_hdr_proc_ctx, + dma_addr_t phys_base, u32 hdr_base_addr, + u32 hdr_offset_entry){ + if (type == IPA_HDR_PROC_NONE) { + struct ipa_hw_hdr_proc_ctx_add_hdr_seq *ctx; + + ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_seq *) + (base + offset); + ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD; + ctx->hdr_add.tlv.length = 1; + ctx->hdr_add.tlv.value = hdr_len; + ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base : + hdr_base_addr + hdr_offset_entry; + IPAHAL_DBG("header address 0x%x\n", + ctx->hdr_add.hdr_addr); + ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END; + ctx->end.length = 0; + ctx->end.value = 0; + } else { + struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *ctx; + + ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *) + (base + offset); + ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD; + ctx->hdr_add.tlv.length = 1; + ctx->hdr_add.tlv.value = hdr_len; + ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base : + hdr_base_addr + hdr_offset_entry; + IPAHAL_DBG("header address 0x%x\n", + ctx->hdr_add.hdr_addr); + ctx->cmd.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD; + ctx->cmd.length = 0; + switch (type) { + case IPA_HDR_PROC_ETHII_TO_ETHII: + ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_ETHII; + break; + case IPA_HDR_PROC_ETHII_TO_802_3: + ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_802_3; + break; + case IPA_HDR_PROC_802_3_TO_ETHII: + ctx->cmd.value = IPA_HDR_UCP_802_3_TO_ETHII; + break; + case IPA_HDR_PROC_802_3_TO_802_3: + ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3; + break; + default: + IPAHAL_ERR("unknown ipa_hdr_proc_type %d", type); + BUG(); + } + IPAHAL_DBG("command id %d\n", ctx->cmd.value); + ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END; + ctx->end.length = 0; + ctx->end.value = 0; + } +} + +/* + * ipahal_get_proc_ctx_needed_len_v3() - calculates the needed length for + * addition of header processing context according to the type of processing + * context. + * @type: header processing context type (no processing context, + * IPA_HDR_PROC_ETHII_TO_ETHII etc.) + */ +static int ipahal_get_proc_ctx_needed_len_v3(enum ipa_hdr_proc_type type) +{ + return (type == IPA_HDR_PROC_NONE) ? + sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_seq) : + sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq); +} + +/* + * struct ipahal_hdr_funcs - headers handling functions for specific IPA + * version + * @ipahal_cp_hdr_to_hw_buff - copy function for regular headers + */ +struct ipahal_hdr_funcs { + void (*ipahal_cp_hdr_to_hw_buff)(void *const base, u32 offset, + u8 *const hdr, u32 hdr_len); + + void (*ipahal_cp_proc_ctx_to_hw_buff)(enum ipa_hdr_proc_type type, + void *const base, u32 offset, u32 hdr_len, + bool is_hdr_proc_ctx, dma_addr_t phys_base, + u32 hdr_base_addr, u32 hdr_offset_entry); + + int (*ipahal_get_proc_ctx_needed_len)(enum ipa_hdr_proc_type type); +}; + +static struct ipahal_hdr_funcs hdr_funcs; + +static void ipahal_hdr_init(enum ipa_hw_type ipa_hw_type) +{ + + IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type); + + /* + * once there are changes in HW and need to use different case, insert + * new case for the new h/w. put the default always for the latest HW + * and make sure all previous supported versions have their cases. + */ + switch (ipa_hw_type) { + case IPA_HW_v3_0: + default: + hdr_funcs.ipahal_cp_hdr_to_hw_buff = + ipahal_cp_hdr_to_hw_buff_v3; + hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff = + ipahal_cp_proc_ctx_to_hw_buff_v3; + hdr_funcs.ipahal_get_proc_ctx_needed_len = + ipahal_get_proc_ctx_needed_len_v3; + } + IPAHAL_DBG("Exit\n"); +} + +/* + * ipahal_cp_hdr_to_hw_buff() - copy header to hardware buffer according to + * base address and offset given. + * @base: dma base address + * @offset: offset from base address where the data will be copied + * @hdr: the header to be copied + * @hdr_len: the length of the header + */ +void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *const hdr, + u32 hdr_len) +{ + IPAHAL_DBG_LOW("Entry\n"); + IPAHAL_DBG("base %p, offset %d, hdr %p, hdr_len %d\n", base, + offset, hdr, hdr_len); + BUG_ON(!base || !hdr_len || !hdr); + + hdr_funcs.ipahal_cp_hdr_to_hw_buff(base, offset, hdr, hdr_len); + + IPAHAL_DBG_LOW("Exit\n"); +} + +/* + * ipahal_cp_proc_ctx_to_hw_buff() - copy processing context to + * base address and offset given. + * @type: type of header processing context + * @base: dma base address + * @offset: offset from base address where the data will be copied + * @hdr_len: the length of the header + * @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr + * @phys_base: memory location in DDR + * @hdr_base_addr: base address in table + * @hdr_offset_entry: offset from hdr_base_addr in table + */ +void ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type, + void *const base, u32 offset, u32 hdr_len, + bool is_hdr_proc_ctx, dma_addr_t phys_base, + u32 hdr_base_addr, u32 hdr_offset_entry) +{ + IPAHAL_DBG_LOW("entry\n"); + IPAHAL_DBG( + "type %d, base %p, offset %d, hdr_len %d, is_hdr_proc_ctx %d, hdr_base_addr %d, hdr_offset_entry %d\n" + , type, base, offset, hdr_len, is_hdr_proc_ctx, + hdr_base_addr, hdr_offset_entry); + + BUG_ON(!base || + !hdr_len || + (!phys_base && !hdr_base_addr) || + !hdr_base_addr); + + hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff(type, base, offset, + hdr_len, is_hdr_proc_ctx, phys_base, + hdr_base_addr, hdr_offset_entry); + + IPAHAL_DBG_LOW("Exit\n"); +} + +/* + * ipahal_get_proc_ctx_needed_len() - calculates the needed length for + * addition of header processing context according to the type of processing + * context + * @type: header processing context type (no processing context, + * IPA_HDR_PROC_ETHII_TO_ETHII etc.) + */ +int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type) +{ + int res; + + IPAHAL_DBG("entry\n"); + + res = hdr_funcs.ipahal_get_proc_ctx_needed_len(type); + + IPAHAL_DBG("Exit\n"); + + return res; +} + int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base) { int result; @@ -1067,23 +1249,16 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base) goto bail_err_exit; } - if (ipahal_ipc_logging_init()) { - /* Cannot use the logging macros as no log buffers yet */ - pr_err("ipahal: failed to initialize ipc logging\n"); - result = -ENOMEM; - goto bail_free_ctx; - } - if (ipa_hw_type < IPA_HW_v3_0) { IPAHAL_ERR("ipahal supported on IPAv3 and later only\n"); result = -EINVAL; - goto bail_destroy_ipc; + goto bail_free_ctx; } if (!base) { IPAHAL_ERR("invalid memory io mapping addr\n"); result = -EINVAL; - goto bail_destroy_ipc; + goto bail_free_ctx; } ipahal_ctx->hw_type = ipa_hw_type; @@ -1092,28 +1267,27 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base) if (ipahal_reg_init(ipa_hw_type)) { IPAHAL_ERR("failed to init ipahal reg\n"); result = -EFAULT; - goto bail_destroy_ipc; + goto bail_free_ctx; } if (ipahal_imm_cmd_init(ipa_hw_type)) { IPAHAL_ERR("failed to init ipahal imm cmd\n"); result = -EFAULT; - goto bail_destroy_ipc; + goto bail_free_ctx; } if (ipahal_pkt_status_init(ipa_hw_type)) { IPAHAL_ERR("failed to init ipahal pkt status\n"); result = -EFAULT; - goto bail_destroy_ipc; + goto bail_free_ctx; } + ipahal_hdr_init(ipa_hw_type); + ipahal_debugfs_init(); return 0; -bail_destroy_ipc: - ipc_log_context_destroy(ipahal_ctx->ipc_logbuf_low); - ipc_log_context_destroy(ipahal_ctx->ipc_logbuf); bail_free_ctx: kfree(ipahal_ctx); ipahal_ctx = NULL; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h index 8591ff046624..1380b409d334 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h @@ -597,6 +597,41 @@ void ipahal_pkt_status_parse(const void *unparsed_status, const char *ipahal_pkt_status_exception_str( enum ipahal_pkt_status_exception exception); +/* + * ipahal_cp_hdr_to_hw_buff() - copy header to hardware buffer according to + * base address and offset given. + * @base: dma base address + * @offset: offset from base address where the data will be copied + * @hdr: the header to be copied + * @hdr_len: the length of the header + */ +void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *hdr, u32 hdr_len); + +/* + * ipahal_cp_proc_ctx_to_hw_buff() - copy processing context to + * base address and offset given. + * @type: type of header processing context + * @base: dma base address + * @offset: offset from base address where the data will be copied + * @hdr_len: the length of the header + * @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr + * @phys_base: memory location in DDR + * @hdr_base_addr: base address in table + * @hdr_offset_entry: offset from hdr_base_addr in table + */ +void ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type, + void *base, u32 offset, u32 hdr_len, + bool is_hdr_proc_ctx, dma_addr_t phys_base, + u32 hdr_base_addr, u32 hdr_offset_entry); + +/* + * ipahal_get_proc_ctx_needed_len() - calculates the needed length for addition + * of header processing context according to the type of processing context + * @type: header processing context type (no processing context, + * IPA_HDR_PROC_ETHII_TO_ETHII etc.) + */ +int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type); + int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base); void ipahal_destroy(void); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h index 3c513a7d4dc1..6a22240e951b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h @@ -13,44 +13,37 @@ #ifndef _IPAHAL_I_H_ #define _IPAHAL_I_H_ -#define IPAHAL_DRV_NAME "ipahal" +#include <linux/ipa.h> +#include "../../ipa_common_i.h" -#define IPAHAL_IPC_LOG_PAGES 10 -#define IPAHAL_IPC_LOG(buf, fmt, args...) \ - ipc_log_string((buf), \ - IPAHAL_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) +#define IPAHAL_DRV_NAME "ipahal" #define IPAHAL_DBG(fmt, args...) \ do { \ - pr_debug(IPAHAL_DRV_NAME " %s:%d " fmt, \ - __func__, __LINE__, ## args); \ - if (likely(ipahal_ctx)) { \ - IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf, fmt, ## args); \ - IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf_low, \ - fmt, ## args); \ - } \ + pr_debug(IPAHAL_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \ + ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define IPAHAL_DBG_LOW(fmt, args...) \ do { \ - pr_debug(IPAHAL_DRV_NAME " %s:%d " fmt, \ - __func__, __LINE__, ## args); \ - if (likely(ipahal_ctx) && \ - ipahal_ctx->enable_low_prio_ipc) { \ - IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf_low, \ - fmt, ## args); \ - } \ + pr_debug(IPAHAL_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \ + ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) #define IPAHAL_ERR(fmt, args...) \ do { \ - pr_err(IPAHAL_DRV_NAME " %s:%d " fmt, \ - __func__, __LINE__, ## args); \ - if (likely(ipahal_ctx)) { \ - IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf, fmt, ## args); \ - IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf_low, \ - fmt, ## args); \ - } \ + pr_err(IPAHAL_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \ + ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \ + IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \ + IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) /* @@ -58,21 +51,13 @@ * @hw_type: IPA H/W type/version. * @base: Base address to be used for accessing IPA memory. This is * I/O memory mapped address. - * @ipc_logbuf: IPC debug logs buffer - * @ipc_logbuf_low: IPC Low priority debug logs buffer - * @enable_low_prio_ipc: Flag telling to enable low priority logging * Controlled by debugfs. default is off * @dent: Debugfs folder dir entry - * @dfile_enable_low_prio_ipc: Debugfs file for enable_low_prio_ipc */ struct ipahal_context { enum ipa_hw_type hw_type; void __iomem *base; - void *ipc_logbuf; - void *ipc_logbuf_low; - u32 enable_low_prio_ipc; struct dentry *dent; - struct dentry *dfile_enable_low_prio_ipc; }; extern struct ipahal_context *ipahal_ctx; @@ -486,4 +471,75 @@ struct ipa_pkt_status_hw { /* Size of H/W Packet Status */ #define IPA3_0_PKT_STATUS_SIZE 32 +/* Headers and processing context H/W structures and definitions */ + +/* uCP command numbers */ +#define IPA_HDR_UCP_802_3_TO_802_3 6 +#define IPA_HDR_UCP_802_3_TO_ETHII 7 +#define IPA_HDR_UCP_ETHII_TO_802_3 8 +#define IPA_HDR_UCP_ETHII_TO_ETHII 9 + +/* Processing context TLV type */ +#define IPA_PROC_CTX_TLV_TYPE_END 0 +#define IPA_PROC_CTX_TLV_TYPE_HDR_ADD 1 +#define IPA_PROC_CTX_TLV_TYPE_PROC_CMD 3 + +/** + * struct ipa_hw_hdr_proc_ctx_tlv - + * HW structure of IPA processing context header - TLV part + * @type: 0 - end type + * 1 - header addition type + * 3 - processing command type + * @length: number of bytes after tlv + * for type: + * 0 - needs to be 0 + * 1 - header addition length + * 3 - number of 32B including type and length. + * @value: specific value for type + * for type: + * 0 - needs to be 0 + * 1 - header length + * 3 - command ID (see IPA_HDR_UCP_* definitions) + */ +struct ipa_hw_hdr_proc_ctx_tlv { + u32 type:8; + u32 length:8; + u32 value:16; +}; + +/** + * struct ipa_hw_hdr_proc_ctx_hdr_add - + * HW structure of IPA processing context - add header tlv + * @tlv: IPA processing context TLV + * @hdr_addr: processing context header address + */ +struct ipa_hw_hdr_proc_ctx_hdr_add { + struct ipa_hw_hdr_proc_ctx_tlv tlv; + u32 hdr_addr; +}; + +/** + * struct ipa_hw_hdr_proc_ctx_add_hdr_seq - + * IPA processing context header - add header sequence + * @hdr_add: add header command + * @end: tlv end command (cmd.type must be 0) + */ +struct ipa_hw_hdr_proc_ctx_add_hdr_seq { + struct ipa_hw_hdr_proc_ctx_hdr_add hdr_add; + struct ipa_hw_hdr_proc_ctx_tlv end; +}; + +/** + * struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq - + * IPA processing context header - process command sequence + * @hdr_add: add header command + * @cmd: tlv processing command (cmd.type must be 3) + * @end: tlv end command (cmd.type must be 0) + */ +struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq { + struct ipa_hw_hdr_proc_ctx_hdr_add hdr_add; + struct ipa_hw_hdr_proc_ctx_tlv cmd; + struct ipa_hw_hdr_proc_ctx_tlv end; +}; + #endif /* _IPAHAL_I_H_ */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c index 3451bf80a4fa..5694904ae429 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c @@ -10,7 +10,6 @@ * GNU General Public License for more details. */ -#include <linux/ipc_logging.h> #include <linux/init.h> #include <linux/ipa.h> #include <linux/kernel.h> diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 4b530ed8d010..eba5029509d8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -1051,7 +1051,7 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) struct ipa_tx_meta meta; if (skb->protocol != htons(ETH_P_MAP)) { - IPAWANDBG + IPAWANDBG_LOW ("SW filtering out none QMAP packet received from %s", current->comm); return NETDEV_TX_OK; @@ -1074,11 +1074,11 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) if (atomic_read(&wwan_ptr->outstanding_pkts) >= wwan_ptr->outstanding_high) { if (!qmap_check) { - IPAWANDBG("pending(%d)/(%d)- stop(%d), qmap_chk(%d)\n", + IPAWANDBG_LOW("pending(%d)/(%d)- stop(%d)\n", atomic_read(&wwan_ptr->outstanding_pkts), wwan_ptr->outstanding_high, - netif_queue_stopped(dev), - qmap_check); + netif_queue_stopped(dev)); + IPAWANDBG_LOW("qmap_chk(%d)\n", qmap_check); netif_stop_queue(dev); return NETDEV_TX_BUSY; } @@ -1165,7 +1165,7 @@ static void apps_ipa_tx_complete_notify(void *priv, netif_queue_stopped(wwan_ptr->net) && atomic_read(&wwan_ptr->outstanding_pkts) < (wwan_ptr->outstanding_low)) { - IPAWANDBG("Outstanding low (%d) - waking up queue\n", + IPAWANDBG_LOW("Outstanding low (%d) - waking up queue\n", wwan_ptr->outstanding_low); netif_wake_queue(wwan_ptr->net); } @@ -1193,7 +1193,7 @@ static void apps_ipa_packet_receive_notify(void *priv, int result; unsigned int packet_len = skb->len; - IPAWANDBG("Rx packet was received"); + IPAWANDBG_LOW("Rx packet was received"); if (evt != IPA_RECEIVE) { IPAWANERR("A none IPA_RECEIVE event in wan_ipa_receive\n"); return; @@ -1733,10 +1733,10 @@ static void ipa3_q6_rm_notify_cb(void *user_data, { switch (event) { case IPA_RM_RESOURCE_GRANTED: - IPAWANDBG("%s: Q6_PROD GRANTED CB\n", __func__); + IPAWANDBG_LOW("%s: Q6_PROD GRANTED CB\n", __func__); break; case IPA_RM_RESOURCE_RELEASED: - IPAWANDBG("%s: Q6_PROD RELEASED CB\n", __func__); + IPAWANDBG_LOW("%s: Q6_PROD RELEASED CB\n", __func__); break; default: return; @@ -1843,7 +1843,7 @@ static void ipa3_wake_tx_queue(struct work_struct *work) */ static void ipa3_rm_resource_granted(void *dev) { - IPAWANDBG("Resource Granted - starting queue\n"); + IPAWANDBG_LOW("Resource Granted - starting queue\n"); schedule_work(&ipa3_tx_wakequeue_work); } @@ -2209,7 +2209,7 @@ static int rmnet_ipa_ap_suspend(struct device *dev) struct net_device *netdev = IPA_NETDEV(); struct ipa3_wwan_private *wwan_ptr; - IPAWANDBG("Enter...\n"); + IPAWANDBG_LOW("Enter...\n"); if (netdev == NULL) { IPAWANERR("netdev is NULL.\n"); return 0; @@ -2231,7 +2231,7 @@ static int rmnet_ipa_ap_suspend(struct device *dev) netif_tx_lock_bh(netdev); ipa_rm_release_resource(IPA_RM_RESOURCE_WWAN_0_PROD); netif_tx_unlock_bh(netdev); - IPAWANDBG("Exit\n"); + IPAWANDBG_LOW("Exit\n"); return 0; } @@ -2250,10 +2250,10 @@ static int rmnet_ipa_ap_resume(struct device *dev) { struct net_device *netdev = IPA_NETDEV(); - IPAWANDBG("Enter...\n"); + IPAWANDBG_LOW("Enter...\n"); if (netdev) netif_wake_queue(netdev); - IPAWANDBG("Exit\n"); + IPAWANDBG_LOW("Exit\n"); return 0; } @@ -2337,7 +2337,7 @@ static int ipa3_ssr_notifier_cb(struct notifier_block *this, break; } - IPAWANDBG("Exit\n"); + IPAWANDBG_LOW("Exit\n"); return NOTIFY_DONE; } @@ -2614,7 +2614,7 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, IPAWANERR("reset the pipe stats\n"); } else { /* print tethered-client enum */ - IPAWANDBG("Tethered-client enum(%d)\n", data->ipa_client); + IPAWANDBG_LOW("Tethered-client enum(%d)\n", data->ipa_client); } rc = ipa3_qmi_get_data_stats(req, resp); @@ -2632,16 +2632,17 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, if (resp->dl_dst_pipe_stats_list_valid) { for (pipe_len = 0; pipe_len < resp->dl_dst_pipe_stats_list_len; pipe_len++) { - IPAWANDBG("Check entry(%d) dl_dst_pipe(%d)\n", + IPAWANDBG_LOW("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, resp->dl_dst_pipe_stats_list [pipe_len].pipe_index); - IPAWANDBG("dl_p_v4(%lu)v6(%lu) dl_b_v4(%lu)v6(%lu)\n", + IPAWANDBG_LOW("dl_p_v4(%lu)v6(%lu)\n", (unsigned long int) resp-> dl_dst_pipe_stats_list[pipe_len]. num_ipv4_packets, (unsigned long int) resp-> dl_dst_pipe_stats_list[pipe_len]. - num_ipv6_packets, + num_ipv6_packets); + IPAWANDBG_LOW("dl_b_v4(%lu)v6(%lu)\n", (unsigned long int) resp-> dl_dst_pipe_stats_list[pipe_len]. num_ipv4_bytes, @@ -2671,7 +2672,7 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, } } } - IPAWANDBG("v4_rx_p(%lu) v6_rx_p(%lu) v4_rx_b(%lu) v6_rx_b(%lu)\n", + IPAWANDBG_LOW("v4_rx_p(%lu) v6_rx_p(%lu) v4_rx_b(%lu) v6_rx_b(%lu)\n", (unsigned long int) data->ipv4_rx_packets, (unsigned long int) data->ipv6_rx_packets, (unsigned long int) data->ipv4_rx_bytes, @@ -2680,17 +2681,18 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, if (resp->ul_src_pipe_stats_list_valid) { for (pipe_len = 0; pipe_len < resp->ul_src_pipe_stats_list_len; pipe_len++) { - IPAWANDBG("Check entry(%d) ul_dst_pipe(%d)\n", + IPAWANDBG_LOW("Check entry(%d) ul_dst_pipe(%d)\n", pipe_len, resp->ul_src_pipe_stats_list[pipe_len]. pipe_index); - IPAWANDBG("ul_p_v4(%lu)v6(%lu)ul_b_v4(%lu)v6(%lu)\n", + IPAWANDBG_LOW("ul_p_v4(%lu)v6(%lu)\n", (unsigned long int) resp-> ul_src_pipe_stats_list[pipe_len]. num_ipv4_packets, (unsigned long int) resp-> ul_src_pipe_stats_list[pipe_len]. - num_ipv6_packets, + num_ipv6_packets); + IPAWANDBG_LOW("ul_b_v4(%lu)v6(%lu)\n", (unsigned long int) resp-> ul_src_pipe_stats_list[pipe_len]. num_ipv4_bytes, @@ -2720,7 +2722,7 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, } } } - IPAWANDBG("tx_p_v4(%lu)v6(%lu)tx_b_v4(%lu) v6(%lu)\n", + IPAWANDBG_LOW("tx_p_v4(%lu)v6(%lu)tx_b_v4(%lu) v6(%lu)\n", (unsigned long int) data->ipv4_tx_packets, (unsigned long int) data->ipv6_tx_packets, (unsigned long int) data->ipv4_tx_bytes, diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c index 608e6f23435e..80b07ab79163 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-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 @@ -147,8 +147,7 @@ static long ipa3_wan_ioctl(struct file *filp, break; case WAN_IOC_POLL_TETHERING_STATS: - IPAWANDBG("device %s got WAN_IOCTL_POLL_TETHERING_STATS :>>>\n", - DRIVER_NAME); + IPAWANDBG_LOW("got WAN_IOCTL_POLL_TETHERING_STATS :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_poll_tethering_stats); param = kzalloc(pyld_sz, GFP_KERNEL); if (!param) { @@ -172,8 +171,7 @@ static long ipa3_wan_ioctl(struct file *filp, break; case WAN_IOC_SET_DATA_QUOTA: - IPAWANDBG("device %s got WAN_IOCTL_SET_DATA_QUOTA :>>>\n", - DRIVER_NAME); + IPAWANDBG_LOW("got WAN_IOCTL_SET_DATA_QUOTA :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_set_data_quota); param = kzalloc(pyld_sz, GFP_KERNEL); if (!param) { @@ -197,8 +195,7 @@ static long ipa3_wan_ioctl(struct file *filp, break; case WAN_IOC_SET_TETHER_CLIENT_PIPE: - IPAWANDBG("device %s got WAN_IOC_SET_TETHER_CLIENT_PIPE :>>>\n", - DRIVER_NAME); + IPAWANDBG_LOW("got WAN_IOC_SET_TETHER_CLIENT_PIPE :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_set_tether_client_pipe); param = kzalloc(pyld_sz, GFP_KERNEL); if (!param) { @@ -218,8 +215,7 @@ static long ipa3_wan_ioctl(struct file *filp, break; case WAN_IOC_QUERY_TETHER_STATS: - IPAWANDBG("device %s got WAN_IOC_QUERY_TETHER_STATS :>>>\n", - DRIVER_NAME); + IPAWANDBG_LOW("got WAN_IOC_QUERY_TETHER_STATS :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_query_tether_stats); param = kzalloc(pyld_sz, GFP_KERNEL); if (!param) { @@ -245,7 +241,7 @@ static long ipa3_wan_ioctl(struct file *filp, break; case WAN_IOC_RESET_TETHER_STATS: - IPAWANDBG("device %s got WAN_IOC_RESET_TETHER_STATS :>>>\n", + IPAWANDBG_LOW("device %s got WAN_IOC_RESET_TETHER_STATS :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct wan_ioctl_reset_tether_stats); param = kzalloc(pyld_sz, GFP_KERNEL); diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 9338e643c0ec..42c3c588678e 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -245,6 +245,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(restricted_charging), POWER_SUPPLY_ATTR(current_capability), POWER_SUPPLY_ATTR(typec_mode), + POWER_SUPPLY_ATTR(allow_hvdcp3), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ diff --git a/drivers/power/qcom/apm.c b/drivers/power/qcom/apm.c index 9a36e5035ddd..ab5ee5a199e5 100644 --- a/drivers/power/qcom/apm.c +++ b/drivers/power/qcom/apm.c @@ -629,9 +629,15 @@ done: #define MSM8953_APCC_APM_MODE 0x000002a8 #define MSM8953_APCC_APM_CTL_STS 0x000002b0 +/* 8953 constants */ +#define MSM8953_APM_SWITCH_TIMEOUT_US 500 + +/* Register bit mask definitions */ +#define MSM8953_APM_CTL_STS_MASK 0x1f + static int msm8953_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) { - int timeout = MSM_APM_SWITCH_TIMEOUT_US; + int timeout = MSM8953_APM_SWITCH_TIMEOUT_US; u32 regval; int ret = 0; unsigned long flags; @@ -648,7 +654,7 @@ static int msm8953_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) while (timeout > 0) { regval = readl_relaxed(ctrl_dev->reg_base + MSM8953_APCC_APM_CTL_STS); - if ((regval & MSM_APM_CTL_STS_MASK) == + if ((regval & MSM8953_APM_CTL_STS_MASK) == MSM8953_APM_MX_DONE_VAL) break; @@ -672,7 +678,7 @@ static int msm8953_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) static int msm8953_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) { - int timeout = MSM_APM_SWITCH_TIMEOUT_US; + int timeout = MSM8953_APM_SWITCH_TIMEOUT_US; u32 regval; int ret = 0; unsigned long flags; @@ -689,7 +695,7 @@ static int msm8953_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) while (timeout > 0) { regval = readl_relaxed(ctrl_dev->reg_base + MSM8953_APCC_APM_CTL_STS); - if ((regval & MSM_APM_CTL_STS_MASK) == + if ((regval & MSM8953_APM_CTL_STS_MASK) == MSM8953_APM_APCC_DONE_VAL) break; diff --git a/drivers/power/qcom/msm-core.c b/drivers/power/qcom/msm-core.c index dea9bc89ca5c..c817acf1bb26 100644 --- a/drivers/power/qcom/msm-core.c +++ b/drivers/power/qcom/msm-core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -377,6 +377,7 @@ static int update_userspace_power(struct sched_params __user *argp) struct cpu_activity_info *node; struct cpu_static_info *sp, *clear_sp; int cpumask, cluster, mpidr; + bool pdata_valid[NR_CPUS] = {0}; get_user(cpumask, &argp->cpumask); get_user(cluster, &argp->cluster); @@ -448,13 +449,19 @@ static int update_userspace_power(struct sched_params __user *argp) } cpu_stats[cpu].ptable = per_cpu(ptable, cpu); repopulate_stats(cpu); - - blocking_notifier_call_chain( - &msm_core_stats_notifier_list, cpu, NULL); + pdata_valid[cpu] = true; } } spin_unlock(&update_lock); + for_each_possible_cpu(cpu) { + if (pdata_valid[cpu]) + continue; + + blocking_notifier_call_chain( + &msm_core_stats_notifier_list, cpu, NULL); + } + activate_power_table = true; return 0; diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c index 60dca083e093..f2077213eaef 100644 --- a/drivers/power/qpnp-smbcharger.c +++ b/drivers/power/qpnp-smbcharger.c @@ -139,6 +139,7 @@ struct smbchg_chip { bool vbat_above_headroom; bool force_aicl_rerun; bool hvdcp3_supported; + bool allow_hvdcp3_detection; bool restricted_charging; bool skip_usb_suspend_for_fake_battery; bool hvdcp_not_supported; @@ -5104,6 +5105,30 @@ static int fake_insertion_removal(struct smbchg_chip *chip, bool insertion) return 0; } +static void smbchg_handle_hvdcp3_disable(struct smbchg_chip *chip) +{ + enum power_supply_type usb_supply_type; + char *usb_type_name = "NULL"; + + if (chip->allow_hvdcp3_detection) + return; + + chip->pulse_cnt = 0; + + if (is_hvdcp_present(chip)) { + smbchg_change_usb_supply_type(chip, + POWER_SUPPLY_TYPE_USB_HVDCP); + } else if (is_usb_present(chip)) { + read_usb_type(chip, &usb_type_name, &usb_supply_type); + smbchg_change_usb_supply_type(chip, usb_supply_type); + if (usb_supply_type == POWER_SUPPLY_TYPE_USB_DCP) + schedule_delayed_work(&chip->hvdcp_det_work, + msecs_to_jiffies(HVDCP_NOTIFY_MS)); + } else { + smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); + } +} + static int smbchg_prepare_for_pulsing(struct smbchg_chip *chip) { int rc = 0; @@ -5158,6 +5183,8 @@ static int smbchg_prepare_for_pulsing(struct smbchg_chip *chip) goto handle_removal; } + set_usb_psy_dp_dm(chip, POWER_SUPPLY_DP_DM_DP0P6_DMF); + /* disable APSD */ pr_smb(PR_MISC, "Disabling APSD\n"); rc = smbchg_sec_masked_write(chip, @@ -5181,7 +5208,6 @@ static int smbchg_prepare_for_pulsing(struct smbchg_chip *chip) smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, AICL_EN_BIT, AICL_EN_BIT); - set_usb_psy_dp_dm(chip, POWER_SUPPLY_DP_DM_DP0P6_DMF); /* * DCP will switch to HVDCP in this time by removing the short * between DP DM @@ -5319,6 +5345,9 @@ out: pr_smb(PR_MISC, "HVDCP removed\n"); update_usb_status(chip, 0, 0); } + + smbchg_handle_hvdcp3_disable(chip); + return rc; } @@ -5503,6 +5532,8 @@ static int smbchg_unprepare_for_pulsing_lite(struct smbchg_chip *chip) if (rc < 0) pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); + smbchg_handle_hvdcp3_disable(chip); + return rc; } @@ -5717,6 +5748,7 @@ static enum power_supply_property smbchg_battery_properties[] = { POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, POWER_SUPPLY_PROP_RERUN_AICL, POWER_SUPPLY_PROP_RESTRICTED_CHARGING, + POWER_SUPPLY_PROP_ALLOW_HVDCP3, }; static int smbchg_battery_set_property(struct power_supply *psy, @@ -5794,6 +5826,12 @@ static int smbchg_battery_set_property(struct power_supply *psy, if (chip->typec_psy) update_typec_otg_status(chip, val->intval, false); break; + case POWER_SUPPLY_PROP_ALLOW_HVDCP3: + if (chip->allow_hvdcp3_detection != val->intval) { + chip->allow_hvdcp3_detection = !!val->intval; + power_supply_changed(&chip->batt_psy); + } + break; default: return -EINVAL; } @@ -5817,6 +5855,7 @@ static int smbchg_battery_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_DP_DM: case POWER_SUPPLY_PROP_RERUN_AICL: case POWER_SUPPLY_PROP_RESTRICTED_CHARGING: + case POWER_SUPPLY_PROP_ALLOW_HVDCP3: rc = 1; break; default: @@ -5914,6 +5953,9 @@ static int smbchg_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW: val->intval = smbchg_get_iusb(chip); break; + case POWER_SUPPLY_PROP_ALLOW_HVDCP3: + val->intval = chip->allow_hvdcp3_detection; + break; default: return -EINVAL; } @@ -6327,7 +6369,8 @@ static irqreturn_t usbin_uv_handler(int irq, void *_chip) * set usb_psy's dp=f dm=f if this is a new insertion, i.e. it is * not already src_detected and usbin_uv is seen falling */ - if (!(reg & USBIN_UV_BIT) && !(reg & USBIN_SRC_DET_BIT)) { + if (!(reg & USBIN_UV_BIT) && !(reg & USBIN_SRC_DET_BIT) && + !chip->hvdcp_3_det_ignore_uv) { pr_smb(PR_MISC, "setting usb psy dp=f dm=f\n"); power_supply_set_dp_dm(chip->usb_psy, POWER_SUPPLY_DP_DM_DPF_DMF); @@ -7826,6 +7869,7 @@ static int smbchg_check_chg_version(struct smbchg_chip *chip) chip->schg_version = QPNP_SCHG; break; case PMI8950: + chip->wa_flags |= SMBCHG_RESTART_WA; case PMI8937: chip->wa_flags |= SMBCHG_BATT_OV_WA; if (pmic_rev_id->rev4 < 2) /* PMI8950 1.0 */ { @@ -8133,6 +8177,7 @@ static int smbchg_probe(struct spmi_device *spmi) } } chip->psy_registered = true; + chip->allow_hvdcp3_detection = true; if (chip->cfg_chg_led_support && chip->schg_version == QPNP_SCHG_LITE) { diff --git a/drivers/regulator/cpr-regulator.c b/drivers/regulator/cpr-regulator.c index 49941e368756..7afaacf4b4c2 100644 --- a/drivers/regulator/cpr-regulator.c +++ b/drivers/regulator/cpr-regulator.c @@ -5166,10 +5166,16 @@ static void tsens_threshold_notify(struct therm_threshold *tsens_cb_data) break; } - rc = sensor_mgr_set_threshold(tsens_cb_data->sensor_id, - tsens_cb_data->threshold); - if (rc < 0) - cpr_err(cpr_vreg, "Failed to set temp. threshold, rc=%d\n", rc); + if (tsens_cb_data->cur_state != tsens_cb_data->trip_triggered) { + rc = sensor_mgr_set_threshold(tsens_cb_data->sensor_id, + tsens_cb_data->threshold); + if (rc < 0) + cpr_err(cpr_vreg, + "Failed to set temp. threshold, rc=%d\n", rc); + else + tsens_cb_data->cur_state = + tsens_cb_data->trip_triggered; + } } static int cpr_check_tsens(struct cpr_regulator *cpr_vreg) diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c index db82cfad77c2..be87975c45aa 100644 --- a/drivers/regulator/cpr3-regulator.c +++ b/drivers/regulator/cpr3-regulator.c @@ -5818,6 +5818,42 @@ static int cpr3_regulator_validate_controller(struct cpr3_controller *ctrl) } /** + * cpr3_panic_callback() - panic notification callback function. This function + * is invoked when a kernel panic occurs. + * @nfb: Notifier block pointer of CPR3 controller + * @event: Value passed unmodified to notifier function + * @data: Pointer passed unmodified to notifier function + * + * Return: NOTIFY_OK + */ +static int cpr3_panic_callback(struct notifier_block *nfb, + unsigned long event, void *data) +{ + struct cpr3_controller *ctrl = container_of(nfb, + struct cpr3_controller, panic_notifier); + struct cpr3_panic_regs_info *regs_info = ctrl->panic_regs_info; + struct cpr3_reg_info *reg; + void __iomem *virt_addr; + int i = 0; + + for (i = 0; i < regs_info->reg_count; i++) { + reg = &(regs_info->regs[i]); + virt_addr = ioremap(reg->addr, 0x4); + reg->value = readl_relaxed(virt_addr); + iounmap(virt_addr); + pr_err("%s[0x%08x] = 0x%08x\n", reg->name, reg->addr, + reg->value); + } + /* + * Barrier to ensure that the information has been updated in the + * structure. + */ + mb(); + + return NOTIFY_OK; +} + +/** * cpr3_regulator_register() - register the regulators for a CPR3 controller and * perform CPR hardware initialization * @pdev: Platform device pointer for the CPR3 controller @@ -5968,6 +6004,13 @@ int cpr3_regulator_register(struct platform_device *pdev, list_add(&ctrl->list, &cpr3_controller_list); mutex_unlock(&cpr3_controller_list_mutex); + if (ctrl->panic_regs_info) { + /* Register panic notification call back */ + ctrl->panic_notifier.notifier_call = cpr3_panic_callback; + atomic_notifier_chain_register(&panic_notifier_list, + &ctrl->panic_notifier); + } + return 0; free_regulators: @@ -6021,5 +6064,9 @@ int cpr3_regulator_unregister(struct cpr3_controller *ctrl) for (j = 0; j < ctrl->thread[i].vreg_count; j++) regulator_unregister(ctrl->thread[i].vreg[j].rdev); + if (ctrl->panic_notifier.notifier_call) + atomic_notifier_chain_unregister(&panic_notifier_list, + &ctrl->panic_notifier); + return 0; } diff --git a/drivers/regulator/cpr3-regulator.h b/drivers/regulator/cpr3-regulator.h index 0c4b6cb66805..d750b70519d1 100644 --- a/drivers/regulator/cpr3-regulator.h +++ b/drivers/regulator/cpr3-regulator.h @@ -494,6 +494,35 @@ struct cpr3_aging_sensor_info { }; /** + * struct cpr3_reg_info - Register information data structure + * @name: Register name + * @addr: Register physical address + * @value: Register content + * + * This data structure is used to dump some critical register contents + * when the device crashes due to a kernel panic. + */ +struct cpr3_reg_info { + const char *name; + u32 addr; + u32 value; +}; + +/** + * struct cpr3_panic_regs_info - Data structure to dump critical register + * contents. + * @reg_count: Number of elements in the regs array + * @regs: Array of critical registers information + * + * This data structure is used to dump critical register contents when + * the device crashes due to a kernel panic. + */ +struct cpr3_panic_regs_info { + int reg_count; + struct cpr3_reg_info *regs; +}; + +/** * struct cpr3_controller - CPR3 controller data structure * @dev: Device pointer for the CPR3 controller device * @name: Unique name for the CPR3 controller @@ -662,6 +691,9 @@ struct cpr3_aging_sensor_info { * VDD supply voltage to settle after being increased or * decreased by step_volt microvolts which is used when * SDELTA voltage margin adjustments are applied. + * @panic_regs_info: Array of panic registers information which provides the + * list of registers to dump when the device crashes. + * @panic_notifier: Notifier block registered to global panic notifier list. * * This structure contains both configuration and runtime state data. The * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled, @@ -755,6 +787,8 @@ struct cpr3_controller { u32 temp_sensor_id_start; u32 temp_sensor_id_end; u32 voltage_settling_time; + struct cpr3_panic_regs_info *panic_regs_info; + struct notifier_block panic_notifier; }; /* Used for rounding voltages to the closest physically available set point. */ diff --git a/drivers/regulator/cpr3-util.c b/drivers/regulator/cpr3-util.c index 164579344c81..57631b14b5f6 100644 --- a/drivers/regulator/cpr3-util.c +++ b/drivers/regulator/cpr3-util.c @@ -1020,6 +1020,74 @@ static int cpr3_parse_irq_affinity(struct cpr3_controller *ctrl) return 0; } +static int cpr3_panic_notifier_init(struct cpr3_controller *ctrl) +{ + struct device_node *node = ctrl->dev->of_node; + struct cpr3_panic_regs_info *panic_regs_info; + struct cpr3_reg_info *regs; + int i, reg_count, len, rc = 0; + + if (!of_find_property(node, "qcom,cpr-panic-reg-addr-list", &len)) { + /* panic register address list not specified */ + return rc; + } + + reg_count = len / sizeof(u32); + if (!reg_count) { + cpr3_err(ctrl, "qcom,cpr-panic-reg-addr-list has invalid len = %d\n", + len); + return -EINVAL; + } + + if (!of_find_property(node, "qcom,cpr-panic-reg-name-list", NULL)) { + cpr3_err(ctrl, "property qcom,cpr-panic-reg-name-list not specified\n"); + return -EINVAL; + } + + len = of_property_count_strings(node, "qcom,cpr-panic-reg-name-list"); + if (reg_count != len) { + cpr3_err(ctrl, "qcom,cpr-panic-reg-name-list should have %d strings\n", + reg_count); + return -EINVAL; + } + + panic_regs_info = devm_kzalloc(ctrl->dev, sizeof(*panic_regs_info), + GFP_KERNEL); + if (!panic_regs_info) + return -ENOMEM; + + regs = devm_kcalloc(ctrl->dev, reg_count, sizeof(*regs), GFP_KERNEL); + if (!regs) + return -ENOMEM; + + for (i = 0; i < reg_count; i++) { + rc = of_property_read_string_index(node, + "qcom,cpr-panic-reg-name-list", i, + &(regs[i].name)); + if (rc) { + cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-name-list, rc=%d\n", + rc); + return rc; + } + + rc = of_property_read_u32_index(node, + "qcom,cpr-panic-reg-addr-list", i, + &(regs[i].addr)); + if (rc) { + cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-addr-list, rc=%d\n", + rc); + return rc; + } + regs[i].value = 0xFFFFFFFF; + } + + panic_regs_info->reg_count = reg_count; + panic_regs_info->regs = regs; + ctrl->panic_regs_info = panic_regs_info; + + return rc; +} + /** * cpr3_parse_common_ctrl_data() - parse common CPR3 controller properties from * device tree @@ -1147,6 +1215,8 @@ int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl) } } + rc = cpr3_panic_notifier_init(ctrl); + return rc; } diff --git a/drivers/soc/qcom/bam_dmux.c b/drivers/soc/qcom/bam_dmux.c index d23f9b9e1059..b3d5fee03ffe 100644 --- a/drivers/soc/qcom/bam_dmux.c +++ b/drivers/soc/qcom/bam_dmux.c @@ -1956,7 +1956,8 @@ static void ul_wakeup(void) &ul_wakeup_ack_completion, msecs_to_jiffies(UL_WAKEUP_TIMEOUT_MS)); wait_for_ack = 0; - if (unlikely(ret == 0) && ssrestart_check()) { + if (unlikely(in_global_reset == 1) + || (unlikely(ret == 0) && ssrestart_check())) { mutex_unlock(&wakeup_lock); BAM_DMUX_LOG("%s timeout previous ack\n", __func__); return; @@ -1967,7 +1968,8 @@ static void ul_wakeup(void) BAM_DMUX_LOG("%s waiting for wakeup ack\n", __func__); ret = wait_for_completion_timeout(&ul_wakeup_ack_completion, msecs_to_jiffies(UL_WAKEUP_TIMEOUT_MS)); - if (unlikely(ret == 0) && ssrestart_check()) { + if (unlikely(in_global_reset == 1) + || (unlikely(ret == 0) && ssrestart_check())) { mutex_unlock(&wakeup_lock); BAM_DMUX_LOG("%s timeout wakeup ack\n", __func__); return; @@ -1975,7 +1977,8 @@ static void ul_wakeup(void) BAM_DMUX_LOG("%s waiting completion\n", __func__); ret = wait_for_completion_timeout(&bam_connection_completion, msecs_to_jiffies(UL_WAKEUP_TIMEOUT_MS)); - if (unlikely(ret == 0) && ssrestart_check()) { + if (unlikely(in_global_reset == 1) + || (unlikely(ret == 0) && ssrestart_check())) { mutex_unlock(&wakeup_lock); BAM_DMUX_LOG("%s timeout power on\n", __func__); return; @@ -2207,6 +2210,9 @@ static int restart_notifier_cb(struct notifier_block *this, if (code == SUBSYS_BEFORE_SHUTDOWN) { BAM_DMUX_LOG("%s: begin\n", __func__); in_global_reset = 1; + /* wakeup ul_wakeup() thread*/ + complete_all(&ul_wakeup_ack_completion); + complete_all(&bam_connection_completion); /* sync to ensure the driver sees SSR */ synchronize_srcu(&bam_dmux_srcu); BAM_DMUX_LOG("%s: ssr signaling complete\n", __func__); diff --git a/drivers/soc/qcom/pil-q6v5.c b/drivers/soc/qcom/pil-q6v5.c index eb8e6d510d1e..0055c018c195 100644 --- a/drivers/soc/qcom/pil-q6v5.c +++ b/drivers/soc/qcom/pil-q6v5.c @@ -113,7 +113,7 @@ int pil_q6v5_make_proxy_votes(struct pil_desc *pil) goto err_qdss_vote; } - ret = regulator_set_voltage(drv->vreg_cx, uv, uv); + ret = regulator_set_voltage(drv->vreg_cx, uv, INT_MAX); if (ret) { dev_err(pil->dev, "Failed to request vdd_cx voltage.\n"); goto err_cx_voltage; diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c index 653f665b6e5d..14e46b38c6df 100644 --- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c +++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c @@ -210,6 +210,25 @@ bool apr_tal_notify_rx_intent_req(void *handle, const void *priv, return false; } +static void apr_tal_notify_remote_rx_intent(void *handle, const void *priv, + size_t size) +{ + struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv; + + if (!apr_ch) { + pr_err("%s: Invalid apr_ch\n", __func__); + return; + } + /* + * This is to make sure that the far end has queued at least one intent + * before we attmpt any IPC. A simple bool flag is used here instead of + * a counter, as the far end is required to guarantee intent + * availability for all use cases once the channel is fully opened. + */ + pr_debug("%s: remote queued an intent\n", __func__); + apr_ch->if_remote_intent_ready = true; +} + void apr_tal_notify_state(void *handle, const void *priv, unsigned event) { struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv; @@ -295,6 +314,7 @@ struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, uint32_t dl, open_cfg.notify_tx_done = apr_tal_notify_tx_done; open_cfg.notify_state = apr_tal_notify_state; open_cfg.notify_rx_intent_req = apr_tal_notify_rx_intent_req; + open_cfg.notify_remote_rx_intent = apr_tal_notify_remote_rx_intent; open_cfg.priv = apr_ch; /* * The transport name "smd_trans" is required if far end is using SMD. @@ -321,6 +341,15 @@ struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, uint32_t dl, goto close_link; } + /* + * Remote intent is not required for GLINK <--> SMD IPC, so this is + * designed not to fail the open call. + */ + rc = wait_event_timeout(apr_ch->wait, + apr_ch->if_remote_intent_ready, 5 * HZ); + if (rc == 0) + pr_err("%s: TIMEOUT for remote intent readiness\n", __func__); + rc = apr_tal_rx_intents_config(apr_ch, APR_DEFAULT_NUM_OF_INTENTS, APR_MAX_BUF); if (rc) { @@ -356,6 +385,7 @@ int apr_tal_close(struct apr_svc_ch_dev *apr_ch) apr_ch->handle = NULL; apr_ch->func = NULL; apr_ch->priv = NULL; + apr_ch->if_remote_intent_ready = false; mutex_unlock(&apr_ch->m_lock); exit: return rc; diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index d66fab897ab3..19930c37e5a6 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -70,17 +70,20 @@ enum p_subsys_state { /** * enum subsys_state - state of a subsystem (public) + * @SUBSYS_OFFLINING: subsystem is offlining * @SUBSYS_OFFLINE: subsystem is offline * @SUBSYS_ONLINE: subsystem is online * * The 'public' side of the subsytem state, exposed to userspace. */ enum subsys_state { + SUBSYS_OFFLINING, SUBSYS_OFFLINE, SUBSYS_ONLINE, }; static const char * const subsys_states[] = { + [SUBSYS_OFFLINING] = "OFFLINING", [SUBSYS_OFFLINE] = "OFFLINE", [SUBSYS_ONLINE] = "ONLINE", }; @@ -728,6 +731,7 @@ static void subsys_stop(struct subsys_device *subsys) if (!of_property_read_bool(subsys->desc->dev->of_node, "qcom,pil-force-shutdown")) { + subsys_set_state(subsys, SUBSYS_OFFLINING); subsys->desc->sysmon_shutdown_ret = sysmon_send_shutdown(subsys->desc); if (subsys->desc->sysmon_shutdown_ret) diff --git a/drivers/soundwire/soundwire.c b/drivers/soundwire/soundwire.c index 23642fe38ef3..2ca4faedd4b3 100644 --- a/drivers/soundwire/soundwire.c +++ b/drivers/soundwire/soundwire.c @@ -240,6 +240,43 @@ void swr_port_response(struct swr_master *mstr, u8 tid) EXPORT_SYMBOL(swr_port_response); /** + * swr_slvdev_datapath_control - Enables/Disables soundwire slave device + * data path + * @dev: pointer to soundwire slave device + * @dev_num: device number of the soundwire slave device + * + * Returns error code for failure and 0 for success + */ +int swr_slvdev_datapath_control(struct swr_device *dev, u8 dev_num, + bool enable) +{ + struct swr_master *master; + + if (!dev) + return -ENODEV; + + master = dev->master; + if (!master) + return -EINVAL; + + if (dev->group_id) { + /* Broadcast */ + if (master->gr_sid != dev_num) { + if (!master->gr_sid) + master->gr_sid = dev_num; + else + return 0; + } + } + + if (master->slvdev_datapath_control) + master->slvdev_datapath_control(master, enable); + + return 0; +} +EXPORT_SYMBOL(swr_slvdev_datapath_control); + +/** * swr_connect_port - enable soundwire slave port(s) * @dev: pointer to soundwire slave device * @port_id: logical port id(s) of soundwire slave device diff --git a/drivers/soundwire/swr-wcd-ctrl.c b/drivers/soundwire/swr-wcd-ctrl.c index b18ffca8d735..83fb7dc6fae2 100644 --- a/drivers/soundwire/swr-wcd-ctrl.c +++ b/drivers/soundwire/swr-wcd-ctrl.c @@ -601,6 +601,62 @@ static struct swr_port_info *swrm_get_port(struct swr_master *master, return port; } +static void swrm_slvdev_datapath_control(struct swr_master *master, + bool enable) +{ + u8 bank; + u32 value, n_col; + struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master); + int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | + SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | + SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); + int col_mask = SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK; + u8 active_bank; + + bank = get_inactive_bank_num(swrm); + + dev_dbg(swrm->dev, "%s: enable: %d, slvdev_dp_enable_cnt: %d\n", + __func__, enable, swrm->slvdev_dp_enable_cnt); + + if (enable) { + swrm->slvdev_dp_enable_cnt++; + active_bank = bank ? 0 : 1; + value = swrm->read(swrm->handle, + SWRM_MCP_FRAME_CTRL_BANK_ADDR(active_bank)); + if (((value & col_mask) >> + SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) == + SWR_MAX_COL) + return; + + /* set Row = 48 and col = 16 */ + n_col = SWR_MAX_COL; + } else { + /* + * Do not change to 48x2 if number of channels configured + * as stereo and if disable datapath is called for the + * first slave device + */ + swrm->slvdev_dp_enable_cnt--; + if (swrm->slvdev_dp_enable_cnt > 0) + return; + + /* set Row = 48 and col = 2 */ + n_col = SWR_MIN_COL; + } + + value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); + value &= (~mask); + value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | + (n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | + (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); + swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); + + dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, + SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); + + enable_bank_switch(swrm, bank, SWR_MAX_ROW, n_col); +} + static void swrm_apply_port_config(struct swr_master *master) { u32 value; @@ -615,10 +671,6 @@ static void swrm_apply_port_config(struct swr_master *master) u32 val[SWRM_MAX_PORT_REG]; int len = 0; - int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | - SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | - SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); - if (!swrm) { pr_err("%s: Invalid handle to swr controller\n", __func__); @@ -629,15 +681,6 @@ static void swrm_apply_port_config(struct swr_master *master) dev_dbg(swrm->dev, "%s: enter bank: %d master_ports: %d\n", __func__, bank, master->num_port); - /* set Row = 48 and col = 16 */ - value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); - value &= (~mask); - value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | - (7 << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | - (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); - swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); - dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, - SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank)); @@ -703,7 +746,6 @@ static void swrm_apply_port_config(struct swr_master *master) } } swrm->bulk_write(swrm->handle, reg, val, len); - enable_bank_switch(swrm, bank, SWR_MAX_ROW, SWR_MAX_COL); } static int swrm_connect_port(struct swr_master *master, @@ -1057,6 +1099,7 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) u32 value[SWRM_MAX_INIT_REG]; int len = 0; + swrm->slvdev_dp_enable_cnt = 0; /* Clear Rows and Cols */ val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | @@ -1174,6 +1217,7 @@ static int swrm_probe(struct platform_device *pdev) swrm->master.get_logical_dev_num = swrm_get_logical_dev_num; swrm->master.connect_port = swrm_connect_port; swrm->master.disconnect_port = swrm_disconnect_port; + swrm->master.slvdev_datapath_control = swrm_slvdev_datapath_control; swrm->master.dev.parent = &pdev->dev; swrm->master.dev.of_node = pdev->dev.of_node; swrm->master.num_port = 0; diff --git a/drivers/soundwire/swr-wcd-ctrl.h b/drivers/soundwire/swr-wcd-ctrl.h index b5d477523315..a9248425deea 100644 --- a/drivers/soundwire/swr-wcd-ctrl.h +++ b/drivers/soundwire/swr-wcd-ctrl.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 @@ -96,6 +96,7 @@ struct swr_mstr_ctrl { struct platform_device *pdev; int num_rx_chs; u8 num_cfg_devs; + u8 slvdev_dp_enable_cnt; }; #endif /* _SWR_WCD_CTRL_H */ diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c index b21b6888b169..9244af11e0c9 100644 --- a/drivers/thermal/msm_thermal.c +++ b/drivers/thermal/msm_thermal.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -159,7 +159,6 @@ static bool ocr_nodes_called; static bool ocr_probed; static bool ocr_reg_init_defer; static bool hotplug_enabled; -static bool interrupt_mode_enable; static bool msm_thermal_probed; static bool gfx_crit_phase_ctrl_enabled; static bool gfx_warm_phase_ctrl_enabled; @@ -1806,14 +1805,14 @@ static int vdd_restriction_apply_voltage(struct rail *r, int level) /* level = -1: disable, level = 0,1,2..n: enable */ if (level == -1) { ret = regulator_set_voltage(r->reg, r->min_level, - r->levels[r->num_levels - 1]); + INT_MAX); if (!ret) r->curr_level = -1; pr_debug("Requested min level for %s. curr level: %d\n", r->name, r->curr_level); } else if (level >= 0 && level < (r->num_levels)) { ret = regulator_set_voltage(r->reg, r->levels[level], - r->levels[r->num_levels - 1]); + INT_MAX); if (!ret) r->curr_level = level; pr_debug("Requesting level %d for %s. curr level: %d\n", @@ -2695,8 +2694,12 @@ static void vdd_mx_notify(struct therm_threshold *trig_thresh) pr_err("Failed to remove vdd mx restriction\n"); } mutex_unlock(&vdd_mx_mutex); - sensor_mgr_set_threshold(trig_thresh->sensor_id, + + if (trig_thresh->cur_state != trig_thresh->trip_triggered) { + sensor_mgr_set_threshold(trig_thresh->sensor_id, trig_thresh->threshold); + trig_thresh->cur_state = trig_thresh->trip_triggered; + } } static void msm_thermal_bite(int zone_id, long temp) @@ -4069,8 +4072,11 @@ static void cx_phase_ctrl_notify(struct therm_threshold *trig_thresh) cx_phase_unlock_exit: mutex_unlock(&cx_mutex); cx_phase_ctrl_exit: - sensor_mgr_set_threshold(trig_thresh->sensor_id, + if (trig_thresh->cur_state != trig_thresh->trip_triggered) { + sensor_mgr_set_threshold(trig_thresh->sensor_id, trig_thresh->threshold); + trig_thresh->cur_state = trig_thresh->trip_triggered; + } return; } @@ -4198,8 +4204,11 @@ static void vdd_restriction_notify(struct therm_threshold *trig_thresh) unlock_and_exit: mutex_unlock(&vdd_rstr_mutex); set_and_exit: - sensor_mgr_set_threshold(trig_thresh->sensor_id, + if (trig_thresh->cur_state != trig_thresh->trip_triggered) { + sensor_mgr_set_threshold(trig_thresh->sensor_id, trig_thresh->threshold); + trig_thresh->cur_state = trig_thresh->trip_triggered; + } return; } @@ -4247,8 +4256,11 @@ static void ocr_notify(struct therm_threshold *trig_thresh) unlock_and_exit: mutex_unlock(&ocr_mutex); set_and_exit: - sensor_mgr_set_threshold(trig_thresh->sensor_id, - trig_thresh->threshold); + if (trig_thresh->cur_state != trig_thresh->trip_triggered) { + sensor_mgr_set_threshold(trig_thresh->sensor_id, + trig_thresh->threshold); + trig_thresh->cur_state = trig_thresh->trip_triggered; + } return; } @@ -4483,6 +4495,7 @@ int sensor_mgr_init_threshold(struct threshold_info *thresh_inp, thresh_ptr[i].notify = callback; thresh_ptr[i].trip_triggered = -1; thresh_ptr[i].parent = thresh_inp; + thresh_ptr[i].cur_state = -1; thresh_ptr[i].threshold[0].temp = high_temp * tsens_scaling_factor; thresh_ptr[i].threshold[0].trip = @@ -4503,6 +4516,7 @@ int sensor_mgr_init_threshold(struct threshold_info *thresh_inp, thresh_ptr->notify = callback; thresh_ptr->trip_triggered = -1; thresh_ptr->parent = thresh_inp; + thresh_ptr->cur_state = -1; thresh_ptr->threshold[0].temp = high_temp * tsens_scaling_factor; thresh_ptr->threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI; @@ -4679,10 +4693,9 @@ static void __ref disable_msm_thermal(void) static void interrupt_mode_init(void) { - if (!msm_thermal_probed) { - interrupt_mode_enable = true; + if (!msm_thermal_probed) return; - } + if (polling_enabled) { polling_enabled = 0; create_sensor_zone_id_map(); @@ -5784,6 +5797,13 @@ static int probe_vdd_mx(struct device_node *node, if (ret) goto read_node_done; + /* + * Monitor only this sensor if defined, otherwise monitor all tsens + */ + key = "qcom,mx-restriction-sensor_id"; + if (of_property_read_u32(node, key, &data->vdd_mx_sensor_id)) + data->vdd_mx_sensor_id = MONITOR_ALL_TSENS; + vdd_mx = devm_regulator_get(&pdev->dev, "vdd-mx"); if (IS_ERR_OR_NULL(vdd_mx)) { ret = PTR_ERR(vdd_mx); @@ -5810,7 +5830,7 @@ static int probe_vdd_mx(struct device_node *node, } ret = sensor_mgr_init_threshold(&thresh[MSM_VDD_MX_RESTRICTION], - MONITOR_ALL_TSENS, + data->vdd_mx_sensor_id, data->vdd_mx_temp_degC + data->vdd_mx_temp_hyst_degC, data->vdd_mx_temp_degC, vdd_mx_notify); @@ -6749,6 +6769,9 @@ static void thermal_mx_config_read(struct seq_file *m, void *data) if (vdd_cx) seq_printf(m, "cx retention value:%d\n", msm_thermal_info.vdd_cx_min); + if (msm_thermal_info.vdd_mx_sensor_id != MONITOR_ALL_TSENS) + seq_printf(m, "tsens sensor:tsens_tz_sensor%d\n", + msm_thermal_info.vdd_mx_sensor_id); } } @@ -7094,11 +7117,6 @@ static int msm_thermal_dev_probe(struct platform_device *pdev) ret = msm_thermal_init(&data); msm_thermal_probed = true; - if (interrupt_mode_enable) { - interrupt_mode_init(); - interrupt_mode_enable = false; - } - return ret; fail: if (ret) @@ -7234,7 +7252,6 @@ int __init msm_thermal_late_init(void) } } msm_thermal_add_mx_nodes(); - interrupt_mode_init(); create_cpu_topology_sysfs(); create_thermal_debugfs(); msm_thermal_add_bucket_info_nodes(); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 27508d2b5bfe..3690303f33cc 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1553,6 +1553,8 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); usbmon_urb_submit(&hcd->self, urb); + if (hcd->driver->log_urb) + hcd->driver->log_urb(urb, "S", urb->status); /* NOTE requirements on root-hub callers (usbfs and the hub * driver, for now): URBs' urb->transfer_buffer must be @@ -1575,6 +1577,8 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) if (unlikely(status)) { usbmon_urb_submit_error(&hcd->self, urb, status); + if (hcd->driver->log_urb) + hcd->driver->log_urb(urb, "E", status); urb->hcpriv = NULL; INIT_LIST_HEAD(&urb->urb_list); atomic_dec(&urb->use_count); @@ -1663,6 +1667,8 @@ static void __usb_hcd_giveback_urb(struct urb *urb) unmap_urb_for_dma(hcd, urb); usbmon_urb_complete(&hcd->self, urb, status); + if (hcd->driver->log_urb) + hcd->driver->log_urb(urb, "C", status); usb_anchor_suspend_wakeups(anchor); usb_unanchor_urb(urb); if (likely(status == 0)) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2222899c4b69..3c26acd61b5c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4327,7 +4327,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { bool did_new_scheme = false; - if (use_new_scheme(udev, retry_counter)) { + if (use_new_scheme(udev, retry_counter) && + !((hcd->driver->flags & HCD_RT_OLD_ENUM) && + !hdev->parent)) { struct usb_device_descriptor *buf; int r = 0; diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 206664ca6e2c..47f6327d3eed 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -67,6 +67,10 @@ static int cpu_to_affin; module_param(cpu_to_affin, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(cpu_to_affin, "affin usb irq to this cpu"); +static bool disable_host_mode; +module_param(disable_host_mode, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(disable_host_mode, "To stop HOST mode detection"); + static int override_phy_init; module_param(override_phy_init, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq"); @@ -657,11 +661,34 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep, int ret = 0, size; bool superspeed; + /* + * We must obtain the lock of the dwc3 core driver, + * including disabling interrupts, so we will be sure + * that we are the only ones that configure the HW device + * core and ensure that we queuing the request will finish + * as soon as possible so we will release back the lock. + */ + spin_lock_irqsave(&dwc->lock, flags); + if (!dep->endpoint.desc) { + dev_err(mdwc->dev, + "%s: trying to queue request %p to disabled ep %s\n", + __func__, request, ep->name); + spin_unlock_irqrestore(&dwc->lock, flags); + return -EPERM; + } + + if (!request) { + dev_err(mdwc->dev, "%s: request is NULL\n", __func__); + spin_unlock_irqrestore(&dwc->lock, flags); + return -EINVAL; + } + if (!(request->udc_priv & MSM_SPS_MODE)) { /* Not SPS mode, call original queue */ dev_vdbg(mdwc->dev, "%s: not sps mode, use regular queue\n", __func__); + spin_unlock_irqrestore(&dwc->lock, flags); return (mdwc->original_ep_ops[dep->number])->queue(ep, request, gfp_flags); @@ -670,36 +697,29 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep, /* HW restriction regarding TRB size (8KB) */ if (req->request.length < 0x2000) { dev_err(mdwc->dev, "%s: Min TRB size is 8KB\n", __func__); + spin_unlock_irqrestore(&dwc->lock, flags); return -EINVAL; } - spin_lock_irqsave(&dwc->lock, flags); - if (!dep->endpoint.desc) { - dev_err(mdwc->dev, - "%s: trying to queue request %p to disabled ep %s\n", - __func__, request, ep->name); - return -EPERM; - } - if (dep->number == 0 || dep->number == 1) { dev_err(mdwc->dev, "%s: trying to queue dbm request %p to control ep %s\n", __func__, request, ep->name); + spin_unlock_irqrestore(&dwc->lock, flags); return -EPERM; } - if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list) || !list_empty(&dep->req_queued)) { dev_err(mdwc->dev, "%s: trying to queue dbm request %p tp ep %s\n", __func__, request, ep->name); + spin_unlock_irqrestore(&dwc->lock, flags); return -EPERM; } dep->busy_slot = 0; dep->free_slot = 0; - spin_unlock_irqrestore(&dwc->lock, flags); /* * Override req->complete function, but before doing that, * store it's original pointer in the req_complete_list. @@ -707,6 +727,7 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep, req_complete = kzalloc(sizeof(*req_complete), gfp_flags); if (!req_complete) { dev_err(mdwc->dev, "%s: not enough memory\n", __func__); + spin_unlock_irqrestore(&dwc->lock, flags); return -ENOMEM; } req_complete->req = request; @@ -722,22 +743,6 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep, dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRHI(0)), DWC3_GEVNTSIZ_SIZE(size)); - /* - * We must obtain the lock of the dwc3 core driver, - * including disabling interrupts, so we will be sure - * that we are the only ones that configure the HW device - * core and ensure that we queuing the request will finish - * as soon as possible so we will release back the lock. - */ - spin_lock_irqsave(&dwc->lock, flags); - if (!dep->endpoint.desc) { - dev_err(mdwc->dev, - "%s: trying to queue request %p to disabled ep %s\n", - __func__, request, ep->name); - ret = -EPERM; - goto err; - } - ret = __dwc3_msm_ep_queue(dep, req); if (ret < 0) { dev_err(mdwc->dev, @@ -2380,6 +2385,12 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, if (mdwc->id_state == id) break; + if (disable_host_mode && !id) { + dev_dbg(mdwc->dev, "%s: Ignoring ID change event :%d\n", + __func__, mdwc->id_state); + break; + } + /* Let OTG know about ID detection */ mdwc->id_state = id; dbg_event(0xFF, "id_state", mdwc->id_state); diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 998885649d27..4afaaaadff31 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -7,7 +7,7 @@ ccflags-y += -I$(srctree)/drivers/usb/gadget/udc -I$(srctree)/drivers/usb/gad obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o libcomposite-y := usbstring.o config.o epautoconf.o -libcomposite-y += composite.o functions.o configfs.o u_f.o +libcomposite-y += composite.o functions.o u_f.o obj-y += debug.o g_android-y := android.o diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index 210b66c51afa..2f4a3626aa5f 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -1293,13 +1293,13 @@ static int acc_setup(void) INIT_DELAYED_WORK(&dev->start_work, acc_start_work); INIT_WORK(&dev->hid_work, acc_hid_work); - /* _acc_dev must be set before calling usb_gadget_register_driver */ - _acc_dev = dev; - ret = misc_register(&acc_device); if (ret) goto err; + /* _acc_dev must be set before calling usb_gadget_register_driver */ + _acc_dev = dev; + return 0; err: diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 9922e7d12bdd..e9a66f93f2e0 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2857,10 +2857,8 @@ static int _ffs_func_bind(struct usb_configuration *c, struct ffs_data *ffs = func->ffs; const int full = !!func->ffs->fs_descs_count; - const int high = gadget_is_dualspeed(func->gadget) && - func->ffs->hs_descs_count; - const int super = gadget_is_superspeed(func->gadget) && - func->ffs->ss_descs_count; + const int high = func->ffs->hs_descs_count; + const int super = func->ffs->ss_descs_count; int fs_len, hs_len, ss_len, ret, i; @@ -3576,8 +3574,6 @@ static void ffs_closed(struct ffs_data *ffs) || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount)) goto done; - unregister_gadget_item(ffs_obj->opts-> - func_inst.group.cg_item.ci_parent->ci_parent); done: ffs_dev_unlock(); } diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index cf42842c542e..0d636008bb4b 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -3645,7 +3645,6 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item) struct config_item *gadget; gadget = group->cg_item.ci_parent->ci_parent; - unregister_gadget_item(gadget); } fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs); diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c index 6ce347871d11..fcd590b4e7d3 100644 --- a/drivers/usb/gadget/function/f_qdss.c +++ b/drivers/usb/gadget/function/f_qdss.c @@ -1107,32 +1107,37 @@ EXPORT_SYMBOL(usb_qdss_open); void usb_qdss_close(struct usb_qdss_ch *ch) { struct f_qdss *qdss = ch->priv_usb; - struct usb_gadget *gadget = qdss->cdev->gadget; + struct usb_gadget *gadget; unsigned long flags; int status; pr_debug("usb_qdss_close\n"); spin_lock_irqsave(&qdss_lock, flags); + if (!qdss || !qdss->usb_connected) { + ch->app_conn = 0; + spin_unlock_irqrestore(&qdss_lock, flags); + return; + } + usb_ep_dequeue(qdss->port.data, qdss->endless_req); usb_ep_free_request(qdss->port.data, qdss->endless_req); qdss->endless_req = NULL; + gadget = qdss->cdev->gadget; ch->app_conn = 0; spin_unlock_irqrestore(&qdss_lock, flags); - if (qdss->usb_connected) { - status = uninit_data(qdss->port.data); - if (status) - pr_err("%s: uninit_data error\n", __func__); + status = uninit_data(qdss->port.data); + if (status) + pr_err("%s: uninit_data error\n", __func__); - status = set_qdss_data_connection( + status = set_qdss_data_connection( gadget, qdss->port.data, qdss->port.data->address, 0); - if (status) - pr_err("%s:qdss_disconnect error\n", __func__); - } + if (status) + pr_err("%s:qdss_disconnect error\n", __func__); usb_gadget_restart(gadget); } EXPORT_SYMBOL(usb_qdss_close); diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index a138f948324c..1d89e3045f2a 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -1150,8 +1150,6 @@ static struct usb_function_instance *rndis_alloc_inst(void) descs[0] = &opts->rndis_os_desc; names[0] = "rndis"; - usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, - names, THIS_MODULE); config_group_init_type_name(&opts->func_inst.group, "", &rndis_func_type); diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index 23f35856685d..25963de5777e 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -1395,6 +1395,13 @@ static long gser_ioctl(struct file *fp, unsigned cmd, unsigned long arg) smd_port_num = gserial_ports[gser->port_num].client_port_num; + if (smd_write_arg.size > GSERIAL_BUF_LEN) { + pr_err("%s: Invalid size:%u, max: %u", __func__, + smd_write_arg.size, GSERIAL_BUF_LEN); + ret = -EINVAL; + break; + } + pr_debug("%s: Copying %d bytes from user buffer to local\n", __func__, smd_write_arg.size); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d1d60e02e723..9ac96f365600 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -526,6 +526,8 @@ static int ehci_init(struct usb_hcd *hcd) hw->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); /* clear interrupt enables, set irq latency */ + log2_irq_thresh = ehci->log2_irq_thresh; + if (log2_irq_thresh < 0 || log2_irq_thresh > 6) log2_irq_thresh = 0; temp = 1 << (16 + log2_irq_thresh); @@ -778,6 +780,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) pstatus = ehci_readl(ehci, &ehci->regs->port_status[i]); + /*set RS bit in case of remote wakeup*/ + if (ehci_is_TDI(ehci) && !(cmd & CMD_RUN) && + (pstatus & PORT_SUSPEND)) + ehci_writel(ehci, cmd | CMD_RUN, + &ehci->regs->command); + if (pstatus & PORT_OWNER) continue; if (!(test_bit(i, &ehci->suspended_ports) && diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 51c022d5ae54..7baa8846d6cf 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -275,6 +275,14 @@ int ehci_bus_suspend (struct usb_hcd *hcd) if (t1 & PORT_OWNER) set_bit(port, &ehci->owned_ports); else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) { + /* clear RS bit before setting SUSP bit + * and wait for HCH to get set. */ + if (ehci->susp_sof_bug) { + spin_unlock_irq(&ehci->lock); + ehci_halt(ehci); + spin_lock_irq(&ehci->lock); + } + t2 |= PORT_SUSPEND; set_bit(port, &ehci->bus_suspended); } @@ -338,8 +346,9 @@ int ehci_bus_suspend (struct usb_hcd *hcd) if (ehci->bus_suspended) udelay(150); - /* turn off now-idle HC */ - ehci_halt (ehci); + /* if this bit is set, controller is already haled */ + if (!ehci->susp_sof_bug) + ehci_halt(ehci); /* turn off now-idle HC */ spin_lock_irq(&ehci->lock); if (ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_POLL_DEAD)) @@ -1179,7 +1188,11 @@ int ehci_hub_control( */ temp &= ~PORT_WKCONN_E; temp |= PORT_WKDISC_E | PORT_WKOC_E; - ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); + if (ehci->susp_sof_bug) + ehci_writel(ehci, temp, status_reg); + else + ehci_writel(ehci, temp | PORT_SUSPEND, + status_reg); if (ehci->has_tdi_phy_lpm) { spin_unlock_irqrestore(&ehci->lock, flags); msleep(5);/* 5ms for HCD enter low pwr mode */ diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c index ff9536a0bc76..ad591ec4a99e 100644 --- a/drivers/usb/host/ehci-msm-hsic.c +++ b/drivers/usb/host/ehci-msm-hsic.c @@ -1,6 +1,6 @@ /* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation * - * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. * * Partly derived from ehci-fsl.c and ehci-hcd.c * Copyright (c) 2000-2004 by David Brownell @@ -92,6 +92,7 @@ struct msm_hsic_hcd { int wakeup_irq; bool wakeup_irq_enabled; int async_irq; + void __iomem *tlmm_regs; uint32_t async_int_cnt; atomic_t pm_usage_cnt; uint32_t bus_perf_client; @@ -642,14 +643,7 @@ static void msm_hsic_clk_reset(struct msm_hsic_hcd *mehci) } } -#define IOMEM(x) ((void __force __iomem *)(x)) -#define MSM_TLMM_BASE IOMEM(0xFA017000) -#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0) -#define HSIC_DATA_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C4) -#define HSIC_CAL_PAD_CTL (MSM_TLMM_BASE+0x20C8) -#define HSIC_LV_MODE 0x04 #define HSIC_PAD_CALIBRATION 0xA8 -#define HSIC_GPIO_PAD_VAL 0x0A0AAA10 #define LINK_RESET_TIMEOUT_USEC (250 * 1000) static void msm_hsic_phy_reset(struct msm_hsic_hcd *mehci) @@ -666,8 +660,8 @@ static void msm_hsic_phy_reset(struct msm_hsic_hcd *mehci) static int msm_hsic_start(struct msm_hsic_hcd *mehci) { struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data; - int ret; - void __iomem *reg; + int ret, *seq, seq_count; + u32 val; if (mehci->hsic_pinctrl) { ret = msm_hsic_config_pinctrl(mehci, 1); @@ -687,13 +681,22 @@ static int msm_hsic_start(struct msm_hsic_hcd *mehci) } /* HSIC init sequence when HSIC signals (Strobe/Data) are - routed via GPIOs */ - if (pdata && ((pdata->strobe && pdata->data) || mehci->hsic_pinctrl)) { - - if (!pdata->ignore_cal_pad_config) { - /* Enable LV_MODE in HSIC_CAL_PAD_CTL register */ - writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL); - mb(); + routed via TLMM */ + if (mehci->tlmm_regs) { + /* Program TLMM pad configuration for HSIC */ + seq = pdata->tlmm_init_seq; + seq_count = pdata->tlmm_seq_count; + if (seq && seq_count) { + while (seq[0] >= 0 && seq_count > 0) { + val = readl_relaxed(mehci->tlmm_regs + seq[0]); + val |= seq[1]; + dev_dbg(mehci->dev, "%s: writing %x to %p\n", + __func__, + val, mehci->tlmm_regs + seq[0]); + writel_relaxed(val, mehci->tlmm_regs + seq[0]); + seq += 2; + seq_count -= 2; + } } /*set periodic calibration interval to ~2.048sec in @@ -703,30 +706,13 @@ static int msm_hsic_start(struct msm_hsic_hcd *mehci) /* Enable periodic IO calibration in HSIC_CFG register */ ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30); - /* Configure GPIO pins for HSIC functionality mode */ - ret = msm_hsic_config_gpios(mehci, 1); - if (ret) { - dev_err(mehci->dev, " gpio configuarion failed\n"); - goto free_resume_gpio; - } - if (pdata->strobe_pad_offset) { - /* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */ - reg = MSM_TLMM_BASE + pdata->strobe_pad_offset; - writel_relaxed(readl_relaxed(reg) | 0x2000000, reg); - } else { - /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */ - reg = HSIC_STROBE_GPIO_PAD_CTL; - writel_relaxed(HSIC_GPIO_PAD_VAL, reg); - } - - if (pdata->data_pad_offset) { - /* Set CORE_CTL_EN in HSIC_DATA GPIO PAD_CTL register */ - reg = MSM_TLMM_BASE + pdata->data_pad_offset; - writel_relaxed(readl_relaxed(reg) | 0x2000000, reg); - } else { - /* Set LV_MODE=0x1 and DCC=0x2 in STROBE GPIO PAD_CTL */ - reg = HSIC_DATA_GPIO_PAD_CTL; - writel_relaxed(HSIC_GPIO_PAD_VAL, reg); + if (pdata->strobe && pdata->data) { + /* Configure GPIO pins for HSIC functionality mode */ + ret = msm_hsic_config_gpios(mehci, 1); + if (ret) { + dev_err(mehci->dev, " gpio configuarion failed\n"); + goto free_resume_gpio; + } } mb(); @@ -1522,7 +1508,7 @@ static struct hc_driver msm_hsic_driver = { * generic hardware linkage */ .irq = msm_hsic_irq, - .flags = HCD_USB2 | HCD_MEMORY, + .flags = HCD_USB2 | HCD_MEMORY | HCD_RT_OLD_ENUM | HCD_BH, .reset = ehci_hsic_reset, .start = ehci_run, @@ -1558,6 +1544,7 @@ static struct hc_driver msm_hsic_driver = { .bus_suspend = ehci_hsic_bus_suspend, .bus_resume = ehci_hsic_bus_resume, + .log_urb = dbg_log_event, .dump_regs = dump_hsic_regs, .set_autosuspend_delay = ehci_msm_set_autosuspend_delay, @@ -1628,15 +1615,6 @@ static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init) if (IS_ERR(mehci->inactivity_clk)) dev_dbg(mehci->dev, "failed to get inactivity_clk\n"); - /* - * alt_core_clk is for LINK to be used during PHY RESET in - * targets on which link does NOT use asynchronous reset methodology. - * clock rate appropriately set by target specific clock driver - */ - mehci->alt_core_clk = devm_clk_get(mehci->dev, "alt_core_clk"); - if (IS_ERR(mehci->alt_core_clk)) - dev_dbg(mehci->dev, "failed to get alt_core_clk\n"); - ret = clk_set_rate(mehci->core_clk, clk_round_rate(mehci->core_clk, LONG_MAX)); if (ret) @@ -1647,13 +1625,6 @@ static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init) if (ret) dev_err(mehci->dev, "failed to set phy_clk rate\n"); - if (!IS_ERR(mehci->alt_core_clk)) { - ret = clk_set_rate(mehci->alt_core_clk, - clk_round_rate(mehci->alt_core_clk, LONG_MAX)); - if (ret) - dev_err(mehci->dev, "failed to set_rate alt_core_clk\n"); - } - ret = clk_set_rate(mehci->cal_clk, clk_round_rate(mehci->cal_clk, LONG_MAX)); if (ret) @@ -1989,12 +1960,6 @@ struct msm_hsic_host_platform_data *msm_hsic_dt_to_pdata( "qcom,phy-susp-sof-workaround"); pdata->phy_reset_sof_workaround = of_property_read_bool(node, "qcom,phy-reset-sof-workaround"); - pdata->ignore_cal_pad_config = of_property_read_bool(node, - "hsic,ignore-cal-pad-config"); - of_property_read_u32(node, "hsic,strobe-pad-offset", - &pdata->strobe_pad_offset); - of_property_read_u32(node, "hsic,data-pad-offset", - &pdata->data_pad_offset); of_property_read_u32(node, "hsic,reset-delay", &pdata->reset_delay); of_property_read_u32(node, "hsic,log2-itc", @@ -2028,7 +1993,7 @@ static int ehci_hsic_msm_probe(struct platform_device *pdev) struct msm_hsic_hcd *mehci; struct msm_hsic_host_platform_data *pdata; unsigned long wakeup_irq_flags = 0; - int ret; + int ret, len; dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n"); @@ -2093,6 +2058,19 @@ static int ehci_hsic_msm_probe(struct platform_device *pdev) pdata = mehci->dev->platform_data; platform_set_drvdata(pdev, hcd); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res && pdata->tlmm_init_seq) { + dev_err(&pdev->dev, "Unable to get TLMM memory resource\n"); + ret = -ENODEV; + goto unmap; + } else if (res) { + mehci->tlmm_regs = ioremap(res->start, resource_size(res)); + if (IS_ERR(mehci->tlmm_regs)) { + ret = PTR_ERR(mehci->tlmm_regs); + goto unmap; + } + } + spin_lock_init(&mehci->wakeup_lock); if (pdata->phy_sof_workaround) { @@ -2145,6 +2123,22 @@ static int ehci_hsic_msm_probe(struct platform_device *pdev) goto unmap; } + of_get_property(mehci->dev->of_node, "qcom,hsic-tlmm-init-seq", &len); + if (len) { + pdata->tlmm_init_seq = devm_kzalloc(&pdev->dev, len, + GFP_KERNEL); + if (!pdata->tlmm_init_seq) + return -ENODEV; + pdata->tlmm_seq_count = len / sizeof(*pdata->tlmm_init_seq); + ret = of_property_read_u32_array(mehci->dev->of_node, + "qcom,hsic-tlmm-init-seq", + pdata->tlmm_init_seq, pdata->tlmm_seq_count); + if (ret) { + dev_err(&pdev->dev, "hsic init-seq failed:%d\n", ret); + pdata->tlmm_seq_count = 0; + } + } + ret = msm_hsic_init_vddcx(mehci, 1); if (ret) { dev_err(&pdev->dev, "unable to initialize VDDCX\n"); diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 965eb17f3924..d530a99ed3e5 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -300,13 +300,19 @@ static int xhci_plat_runtime_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int ret; if (!xhci) return 0; dev_dbg(dev, "xhci-plat runtime suspend\n"); - return xhci_suspend(xhci, true); + disable_irq(hcd->irq); + ret = xhci_suspend(xhci, true); + if (ret) + enable_irq(hcd->irq); + + return ret; } static int xhci_plat_runtime_resume(struct device *dev) @@ -321,6 +327,7 @@ static int xhci_plat_runtime_resume(struct device *dev) dev_dbg(dev, "xhci-plat runtime resume\n"); ret = xhci_resume(xhci, false); + enable_irq(hcd->irq); pm_runtime_mark_last_busy(dev); return ret; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3986eef398bd..a7e5a084a603 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -949,6 +949,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) if (xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, delay)) { xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } @@ -964,6 +966,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) if (xhci_handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) { xhci_warn(xhci, "WARN: xHC save state timeout\n"); + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h index 2082ac893c37..9bd7e29a8aba 100644 --- a/drivers/video/msm/mdss/mdss.h +++ b/drivers/video/msm/mdss/mdss.h @@ -158,7 +158,6 @@ enum mdss_hw_quirk { MDSS_QUIRK_DSC_RIGHT_ONLY_PU, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT, MDSS_QUIRK_DMA_BI_DIR, - MDSS_QUIRK_MIN_BUS_VOTE, MDSS_QUIRK_FMT_PACK_PATTERN, MDSS_QUIRK_NEED_SECURE_MAP, MDSS_QUIRK_SRC_SPLIT_ALWAYS, @@ -354,6 +353,10 @@ struct mdss_data_type { u32 rot_block_size; + /* HW RT bus (AXI) */ + u32 hw_rt_bus_hdl; + u32 hw_rt_bus_ref_cnt; + /* data bus (AXI) */ u32 bus_hdl; u32 bus_ref_cnt; @@ -374,6 +377,7 @@ struct mdss_data_type { u32 ao_bw_uc_idx; /* active only idx */ struct msm_bus_scale_pdata *bus_scale_table; struct msm_bus_scale_pdata *reg_bus_scale_table; + struct msm_bus_scale_pdata *hw_rt_bus_scale_table; u32 max_bw_low; u32 max_bw_high; u32 max_bw_per_pipe; diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c index abad4e135184..b18c2e210b04 100644 --- a/drivers/video/msm/mdss/mdss_debug.c +++ b/drivers/video/msm/mdss/mdss_debug.c @@ -1390,6 +1390,9 @@ void mdss_misr_disable(struct mdss_data_type *mdata, map = mdss_misr_get_map(req->block_id, ctl, mdata, ctl->is_video_mode); + if (!map) + return; + /* clear the map data */ memset(map->crc_ping, 0, sizeof(map->crc_ping)); memset(map->crc_pong, 0, sizeof(map->crc_pong)); diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index cf66127a8bb4..696cd953058e 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -2892,6 +2892,12 @@ static int mdss_dsi_cont_splash_config(struct mdss_panel_info *pinfo, mdss_dsi_panel_pwm_enable(ctrl_pdata); ctrl_pdata->ctrl_state |= (CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE | CTRL_STATE_DSI_ACTIVE); + + /* + * MDP client removes this extra vote during splash reconfigure + * for command mode panel from interface. DSI removes the vote + * during suspend-resume for video mode panel. + */ if (ctrl_pdata->panel_data.panel_info.type == MIPI_CMD_PANEL) clk_handle = ctrl_pdata->mdp_clk_handle; else diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h index 72ed1d38c4cd..9876ac354867 100644 --- a/drivers/video/msm/mdss/mdss_dsi.h +++ b/drivers/video/msm/mdss/mdss_dsi.h @@ -527,7 +527,8 @@ struct mdss_dsi_ctrl_pdata { void *clk_mngr; void *dsi_clk_handle; void *mdp_clk_handle; - int m_vote_cnt; + int m_dsi_vote_cnt; + int m_mdp_vote_cnt; /* debugfs structure */ struct mdss_dsi_debugfs_info *debugfs_info; diff --git a/drivers/video/msm/mdss/mdss_dsi_clk.c b/drivers/video/msm/mdss/mdss_dsi_clk.c index 727d6707444c..377aeb7cad47 100644 --- a/drivers/video/msm/mdss/mdss_dsi_clk.c +++ b/drivers/video/msm/mdss/mdss_dsi_clk.c @@ -722,8 +722,30 @@ error: return rc; } +bool is_dsi_clk_in_ecg_state(void *client) +{ + struct mdss_dsi_clk_client_info *c = client; + struct mdss_dsi_clk_mngr *mngr; + bool is_ecg = false; + + + if (!client) { + pr_err("Invalid client params\n"); + goto end; + } + + mngr = c->mngr; + + mutex_lock(&mngr->clk_mutex); + is_ecg = (c->core_clk_state == MDSS_DSI_CLK_EARLY_GATE); + mutex_unlock(&mngr->clk_mutex); + +end: + return is_ecg; +} + int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, - enum mdss_dsi_clk_state state) + enum mdss_dsi_clk_state state, u32 index) { int rc = 0; struct mdss_dsi_clk_client_info *c = client; @@ -744,7 +766,7 @@ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, c->name, mngr->name, clk, state, c->core_clk_state, c->link_clk_state); - MDSS_XLOG(clk, state, c->core_clk_state, c->link_clk_state); + MDSS_XLOG(index, clk, state, c->core_clk_state, c->link_clk_state); /* * Refcount handling rules: * 1. Increment refcount whenever ON is called @@ -810,7 +832,7 @@ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, pr_debug("[%s]%s: change=%d, Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n", c->name, mngr->name, changed, c->core_refcount, c->core_clk_state, c->link_refcount, c->link_clk_state); - MDSS_XLOG(clk, state, c->core_clk_state, c->link_clk_state); + MDSS_XLOG(index, clk, state, c->core_clk_state, c->link_clk_state); if (changed) { rc = dsi_recheck_clk_state(mngr); diff --git a/drivers/video/msm/mdss/mdss_dsi_clk.h b/drivers/video/msm/mdss/mdss_dsi_clk.h index d42228b48171..8478426a815b 100644 --- a/drivers/video/msm/mdss/mdss_dsi_clk.h +++ b/drivers/video/msm/mdss/mdss_dsi_clk.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 @@ -194,6 +194,7 @@ int mdss_dsi_clk_deregister(void *client); * @client: client handle. * @clk: Type of clock requested (enum mdss_dsi_clk_type). * @state: clock state requested. + * @index: controller index. * * This routine is used to request a new clock state for a specific clock. If * turning ON the clocks, this guarantees that clocks will be on before @@ -203,7 +204,7 @@ int mdss_dsi_clk_deregister(void *client); * @return: error code. */ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, - enum mdss_dsi_clk_state state); + enum mdss_dsi_clk_state state, u32 index); /** * mdss_dsi_clk_set_link_rate() - set clock rate for link clocks @@ -235,4 +236,16 @@ int mdss_dsi_clk_set_link_rate(void *client, enum mdss_dsi_link_clk_type clk, * @return:error code. */ int mdss_dsi_clk_force_toggle(void *client, u32 clk); + +/** + * is_dsi_clk_in_ecg_state() - Checks the current state of clocks + * @client: client handle. + * + * This routine returns checks the clocks status for client and return + * success code based on it. + * + * @return:true: if clocks are in ECG state + * false: for all other cases + */ +bool is_dsi_clk_in_ecg_state(void *client); #endif /* _MDSS_DSI_CLK_H_ */ diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c index 4e1e1782dccf..0573e3bed919 100644 --- a/drivers/video/msm/mdss/mdss_dsi_host.c +++ b/drivers/video/msm/mdss/mdss_dsi_host.c @@ -2785,12 +2785,6 @@ static int dsi_event_thread(void *data) pr_debug("%s: Handling underflow event\n", __func__); __dsi_fifo_error_handler(ctrl, true); - } else { - pr_err("%s: ctrl recovery not defined\n", - __func__); - MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", - "dsi0_phy", "dsi1_ctrl", "dsi1_phy", "vbif", - "vbif_nrt", "dbg_bus", "vbif_dbg_bus", "panic"); } mutex_unlock(&ctrl->mutex); } diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c index 83d1be33b770..058e09577150 100644 --- a/drivers/video/msm/mdss/mdss_dsi_panel.c +++ b/drivers/video/msm/mdss/mdss_dsi_panel.c @@ -373,7 +373,7 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) } if (gpio_is_valid(ctrl_pdata->mode_gpio)) { - bool out; + bool out = false; if (pinfo->mode_gpio_state == MODE_GPIO_HIGH) out = true; @@ -1819,6 +1819,9 @@ static int mdss_dsi_parse_panel_features(struct device_node *np, pinfo->panel_ack_disabled = pinfo->sim_panel_mode ? 1 : of_property_read_bool(np, "qcom,panel-ack-disabled"); + pinfo->allow_phy_power_off = of_property_read_bool(np, + "qcom,panel-allow-phy-poweroff"); + mdss_dsi_parse_esd_params(np, ctrl); if (pinfo->panel_ack_disabled && pinfo->esd_check_enabled) { diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index e9a6ad7dacaf..0151598de8e3 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -3707,7 +3707,7 @@ static int mdss_fb_set_par(struct fb_info *info) { struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; struct fb_var_screeninfo *var = &info->var; - int old_imgType; + int old_imgType, old_format; int ret = 0; ret = mdss_fb_pan_idle(mfd); @@ -3790,6 +3790,12 @@ static int mdss_fb_set_par(struct fb_info *info) mfd->fbi->fix.smem_len = PAGE_ALIGN(mfd->fbi->fix.line_length * mfd->fbi->var.yres) * mfd->fb_page; + old_format = mdss_grayscale_to_mdp_format(var->grayscale); + if (!IS_ERR_VALUE(old_format)) { + if (old_format != mfd->panel_info->out_format) + mfd->panel_reconfig = true; + } + if (mfd->panel_reconfig || (mfd->fb_imgType != old_imgType)) { mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable); mdss_fb_var_to_panelinfo(var, mfd->panel_info); diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c index f5c45571f0d2..36c24302658d 100644 --- a/drivers/video/msm/mdss/mdss_hdmi_edid.c +++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c @@ -2346,6 +2346,24 @@ bool hdmi_edid_get_scdc_support(void *input) return scdc_present; } +/** + * hdmi_edid_sink_scramble_override() - check if override has been enabled + * @input: edid data + * + * Return true if scrambling override is enabled false otherwise. + */ +bool hdmi_edid_sink_scramble_override(void *input) +{ + struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; + + if (edid_ctrl->edid_override && + (edid_ctrl->override_data.scramble != -1)) + return true; + + return false; + +} + bool hdmi_edid_get_sink_scrambler_support(void *input) { struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input; diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.h b/drivers/video/msm/mdss/mdss_hdmi_edid.h index d485e370d3aa..368df21ba457 100644 --- a/drivers/video/msm/mdss/mdss_hdmi_edid.h +++ b/drivers/video/msm/mdss/mdss_hdmi_edid.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-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 @@ -32,6 +32,7 @@ int hdmi_edid_parser(void *edid_ctrl); u32 hdmi_edid_get_raw_data(void *edid_ctrl, u8 *buf, u32 size); u8 hdmi_edid_get_sink_scaninfo(void *edid_ctrl, u32 resolution); u32 hdmi_edid_get_sink_mode(void *edid_ctrl); +bool hdmi_edid_sink_scramble_override(void *input); bool hdmi_edid_get_sink_scrambler_support(void *input); bool hdmi_edid_get_scdc_support(void *input); int hdmi_edid_get_audio_blk(void *edid_ctrl, diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c index b300c4aba599..415b19533f16 100644 --- a/drivers/video/msm/mdss/mdss_hdmi_tx.c +++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c @@ -77,6 +77,7 @@ #define HDMI_DEFAULT_MAX_PCLK_RATE 148500 #define HDMI_TX_3_MAX_PCLK_RATE 297000 #define HDMI_TX_4_MAX_PCLK_RATE 600000 +#define HDMI_TX_KHZ_TO_HZ 1000U /* Enable HDCP by default */ static bool hdcp_feature_on = true; @@ -90,6 +91,9 @@ static bool hdcp_feature_on = true; #define VENDOR_IFRAME_LINE_NUMBER 3 #define MAX_EDID_READ_RETRY 5 +#define HDMI_TX_MIN_FPS 20000 +#define HDMI_TX_MAX_FPS 120000 + enum { DATA_BYTE_1, DATA_BYTE_2, @@ -162,6 +166,7 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl, static int hdmi_tx_setup_tmds_clk_rate(struct hdmi_tx_ctrl *hdmi_ctrl); static void hdmi_tx_set_vendor_specific_infoframe( struct hdmi_tx_ctrl *hdmi_ctrl); +static void hdmi_tx_fps_work(struct work_struct *work); static struct mdss_hw hdmi_tx_hw = { .hw_ndx = MDSS_HW_HDMI, @@ -390,12 +395,15 @@ static int hdmi_tx_get_vic_from_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl, new_vic = pinfo->vic; DEV_DBG("%s: %s is supported\n", __func__, msm_hdmi_mode_2string(new_vic)); + pinfo->lcdc.frame_rate = info.refresh_rate; } else { DEV_ERR("%s: invalid or not supported vic %d\n", __func__, pinfo->vic); return -EPERM; } } else { + u64 pclk; + timing.active_h = pinfo->xres; timing.back_porch_h = pinfo->lcdc.h_back_porch; timing.front_porch_h = pinfo->lcdc.h_front_porch; @@ -416,7 +424,10 @@ static int hdmi_tx_get_vic_from_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl, timing.active_v, timing.back_porch_v, timing.front_porch_v, timing.pulse_width_v, v_total); - timing.pixel_freq = ((unsigned long int)pinfo->clk_rate / 1000); + pclk = pinfo->clk_rate; + do_div(pclk, HDMI_TX_KHZ_TO_HZ); + + timing.pixel_freq = (unsigned long) pclk; if (h_total && v_total) { timing.refresh_rate = ((timing.pixel_freq * 1000) / (h_total * v_total)) * 1000; @@ -742,6 +753,41 @@ end: return ret; } +static int hdmi_tx_update_pixel_clk(struct hdmi_tx_ctrl *hdmi_ctrl, int fps) +{ + struct dss_module_power *power_data = NULL; + struct mdss_panel_info *pinfo; + int rc = 0; + + if (!hdmi_ctrl) { + DEV_ERR("%s: invalid input\n", __func__); + rc = -EINVAL; + goto end; + } + + pinfo = &hdmi_ctrl->panel_data.panel_info; + + power_data = &hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM]; + if (!power_data) { + DEV_ERR("%s: Error: invalid power data\n", __func__); + rc = -EINVAL; + goto end; + } + + if (power_data->clk_config->rate == pinfo->clk_rate) { + rc = -EINVAL; + goto end; + } + + power_data->clk_config->rate = pinfo->clk_rate; + + DEV_DBG("%s: rate %ld\n", __func__, power_data->clk_config->rate); + + msm_dss_clk_set_rate(power_data->clk_config, power_data->num_clk); +end: + return rc; +} + static ssize_t hdmi_tx_sysfs_wta_hot_plug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -935,6 +981,9 @@ static ssize_t hdmi_tx_sysfs_wta_hpd(struct device *dev, hdmi_tx_config_5v(hdmi_ctrl, false); } else { hdmi_tx_hpd_off(hdmi_ctrl); + + hdmi_ctrl->sdev.state = 0; + hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); } break; @@ -1905,6 +1954,7 @@ static int hdmi_tx_init_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl) pinfo->lcdc.v_back_porch = timing.back_porch_v; pinfo->lcdc.v_front_porch = timing.front_porch_v; pinfo->lcdc.v_pulse_width = timing.pulse_width_v; + pinfo->lcdc.frame_rate = timing.refresh_rate; pinfo->type = DTV_PANEL; pinfo->pdest = DISPLAY_3; @@ -1912,6 +1962,9 @@ static int hdmi_tx_init_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl) pinfo->bpp = 24; pinfo->fb_num = 1; + pinfo->min_fps = HDMI_TX_MIN_FPS; + pinfo->max_fps = HDMI_TX_MAX_FPS; + pinfo->lcdc.border_clr = 0; /* blk */ pinfo->lcdc.underflow_clr = 0xff; /* blue */ pinfo->lcdc.hsync_skew = 0; @@ -2105,6 +2158,18 @@ end: return ret; } /* hdmi_tx_check_capability */ +static void hdmi_tx_update_panel_data(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + struct mdss_panel_info *pinfo = &hdmi_ctrl->panel_data.panel_info; + + pinfo->saved_total = mdss_panel_get_htotal(pinfo, true); + pinfo->saved_fporch = hdmi_ctrl->vid_cfg.timing.front_porch_h; + + pinfo->current_fps = hdmi_ctrl->vid_cfg.timing.refresh_rate; + pinfo->default_fps = hdmi_ctrl->vid_cfg.timing.refresh_rate; + pinfo->lcdc.frame_rate = hdmi_ctrl->vid_cfg.timing.refresh_rate; +} + static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl, struct mdss_panel_info *pinfo) { @@ -2183,9 +2248,27 @@ static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl, hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], vid_cfg->vic, false); + hdmi_tx_update_panel_data(hdmi_ctrl); + return res_changed; } /* hdmi_tx_set_video_fmt */ +static bool hdmi_tx_check_for_video_update(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + struct msm_hdmi_mode_timing_info *timing = &hdmi_ctrl->vid_cfg.timing; + struct mdss_panel_info *pinfo = &hdmi_ctrl->panel_data.panel_info; + + if (timing->back_porch_h != pinfo->lcdc.h_back_porch || + timing->front_porch_h != pinfo->lcdc.h_front_porch || + timing->pulse_width_h != pinfo->lcdc.h_pulse_width || + timing->back_porch_v != pinfo->lcdc.v_back_porch || + timing->front_porch_v != pinfo->lcdc.v_front_porch || + timing->pulse_width_v != pinfo->lcdc.v_pulse_width) + return true; + + return false; +} + static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl) { u32 total_v = 0; @@ -2197,6 +2280,7 @@ static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl) u32 div = 0; struct dss_io_data *io = NULL; struct msm_hdmi_mode_timing_info *timing = NULL; + struct mdss_panel_info *pinfo; if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); @@ -2214,6 +2298,9 @@ static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl) DEV_ERR("%s: Core io is not initialized\n", __func__); return -EPERM; } + + pinfo = &hdmi_ctrl->panel_data.panel_info; + /* * In case of YUV420 output, Horizontal timing parameters should be * reduced by half @@ -2221,6 +2308,35 @@ static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl) if (hdmi_ctrl->vid_cfg.avi_iframe.pixel_format == MDP_Y_CBCR_H2V2) div = 1; + if (pinfo->dynamic_fps) { + if (!hdmi_tx_check_for_video_update(hdmi_ctrl)) + return -EINVAL; + + if (pinfo->dfps_update == + DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || + pinfo->dfps_update == + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { + DEV_DBG("%s: hfp=%d, hbp=%d, hpw=%d\n", __func__, + pinfo->lcdc.h_front_porch, + pinfo->lcdc.h_back_porch, + pinfo->lcdc.h_pulse_width); + + timing->back_porch_h = pinfo->lcdc.h_back_porch; + timing->front_porch_h = pinfo->lcdc.h_front_porch; + timing->pulse_width_h = pinfo->lcdc.h_pulse_width; + } else if (pinfo->dfps_update == + DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) { + DEV_DBG("%s: vfp=%d, vbp=%d, vpw=%d\n", __func__, + pinfo->lcdc.v_front_porch, + pinfo->lcdc.v_back_porch, + pinfo->lcdc.v_pulse_width); + + timing->back_porch_v = pinfo->lcdc.v_back_porch; + timing->front_porch_v = pinfo->lcdc.v_front_porch; + timing->pulse_width_v = pinfo->lcdc.v_pulse_width; + } + } + total_h = (hdmi_tx_get_h_total(timing) >> div) - 1; total_v = hdmi_tx_get_v_total(timing) - 1; @@ -3308,15 +3424,17 @@ int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl) rate = hdmi_tx_setup_tmds_clk_rate(hdmi_ctrl); - if (rate > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) { - scrambler_on = true; - tmds_clock_ratio = 1; - } else { - if (hdmi_edid_get_sink_scrambler_support(edid_data)) + scrambler_on = hdmi_edid_get_sink_scrambler_support(edid_data); + + if (!hdmi_edid_sink_scramble_override(edid_data)) { + if (rate > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) scrambler_on = true; } if (scrambler_on) { + if (rate > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) + tmds_clock_ratio = 1; + rc = hdmi_scdc_write(&hdmi_ctrl->ddc_ctrl, HDMI_TX_SCDC_TMDS_BIT_CLOCK_RATIO_UPDATE, tmds_clock_ratio); @@ -3957,6 +4075,7 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl) init_completion(&hdmi_ctrl->hpd_int_done); INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work); + INIT_WORK(&hdmi_ctrl->fps_work, hdmi_tx_fps_work); INIT_WORK(&hdmi_ctrl->cable_notify_work, hdmi_tx_cable_notify_work); INIT_DELAYED_WORK(&hdmi_ctrl->hdcp_cb_work, hdmi_tx_hdcp_cb_work); @@ -4088,6 +4207,127 @@ static char *hdmi_tx_get_event_name(int event) } } +static void hdmi_tx_update_fps(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + int rc = 0, vic = 0; + u64 pclk; + struct mdss_panel_data *pdata; + struct mdss_panel_info *pinfo; + struct msm_hdmi_mode_timing_info timing = {0}; + + if (!hdmi_ctrl) { + DEV_ERR("%s: invalid input\n", __func__); + return; + } + + pdata = &hdmi_ctrl->panel_data; + pinfo = &pdata->panel_info; + + if (!pinfo->dynamic_fps) { + DEV_DBG("%s: Dynamic fps not enabled\n", __func__); + return; + } + + if (hdmi_ctrl->dynamic_fps == pinfo->current_fps) { + DEV_DBG("%s: Panel is already at this FPS: %d\n", + __func__, hdmi_ctrl->dynamic_fps); + return; + } + + if (hdmi_tx_is_hdcp_enabled(hdmi_ctrl)) + hdmi_tx_hdcp_off(hdmi_ctrl); + + if (pinfo->dfps_update == DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { + if (hdmi_tx_video_setup(hdmi_ctrl)) { + DEV_DBG("%s: no change in video timing\n", __func__); + return; + } + + if (hdmi_tx_update_pixel_clk(hdmi_ctrl, + hdmi_ctrl->dynamic_fps)) { + DEV_DBG("%s: no change in clk\n", __func__); + return; + } + + pinfo->saved_total = mdss_panel_get_htotal(pinfo, true); + pinfo->saved_fporch = pinfo->lcdc.h_front_porch; + } else if (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) { + if (hdmi_tx_video_setup(hdmi_ctrl)) { + DEV_DBG("%s: no change in video timing\n", __func__); + return; + } + + pinfo->saved_total = mdss_panel_get_htotal(pinfo, true); + pinfo->saved_fporch = pinfo->lcdc.h_front_porch; + } else if (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) { + if (hdmi_tx_video_setup(hdmi_ctrl)) { + DEV_DBG("%s: no change in video timing\n", __func__); + return; + } + + pinfo->saved_total = mdss_panel_get_vtotal(pinfo); + pinfo->saved_fporch = pinfo->lcdc.v_front_porch; + } else if (pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { + if (hdmi_tx_update_pixel_clk(hdmi_ctrl, + hdmi_ctrl->dynamic_fps)) { + DEV_DBG("%s: no change in clk\n", __func__); + return; + } + } + + pinfo->current_fps = hdmi_ctrl->dynamic_fps; + pinfo->default_fps = hdmi_ctrl->dynamic_fps; + pinfo->lcdc.frame_rate = hdmi_ctrl->dynamic_fps; + pinfo->dynamic_fps = false; + + rc = hdmi_get_supported_mode(&timing, &hdmi_ctrl->ds_data, + hdmi_ctrl->vid_cfg.vic); + + if (rc || !timing.supported) { + DEV_ERR("%s: timing details\n", __func__); + return; + } + + timing.back_porch_h = pinfo->lcdc.h_back_porch; + timing.front_porch_h = pinfo->lcdc.h_front_porch; + timing.pulse_width_h = pinfo->lcdc.h_pulse_width; + + timing.back_porch_v = pinfo->lcdc.v_back_porch; + timing.front_porch_v = pinfo->lcdc.v_front_porch; + timing.pulse_width_v = pinfo->lcdc.v_pulse_width; + + timing.refresh_rate = hdmi_ctrl->dynamic_fps; + + pclk = pinfo->clk_rate; + do_div(pclk, HDMI_TX_KHZ_TO_HZ); + timing.pixel_freq = (unsigned long) pclk; + + hdmi_ctrl->vid_cfg.timing = timing; + + vic = hdmi_get_video_id_code(&timing, &hdmi_ctrl->ds_data); + + if (vic > 0 && hdmi_ctrl->vid_cfg.vic != vic) { + hdmi_ctrl->vid_cfg.vic = vic; + DEV_DBG("%s: switched to new resolution id %d\n", + __func__, vic); + } + + hdmi_tx_start_hdcp(hdmi_ctrl); +} + +static void hdmi_tx_fps_work(struct work_struct *work) +{ + struct hdmi_tx_ctrl *hdmi_ctrl = NULL; + + hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, fps_work); + if (!hdmi_ctrl) { + DEV_DBG("%s: invalid input\n", __func__); + return; + } + + hdmi_tx_update_fps(hdmi_ctrl); +} + static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data, int event, void *arg) { @@ -4100,6 +4340,13 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data, return -EINVAL; } + /* UPDATE FPS is called from atomic context */ + if (event == MDSS_EVENT_PANEL_UPDATE_FPS) { + hdmi_ctrl->dynamic_fps = (u32) (unsigned long)arg; + queue_work(hdmi_ctrl->workq, &hdmi_ctrl->fps_work); + return rc; + } + mutex_lock(&hdmi_ctrl->tx_lock); DEV_DBG("%s: event = %s suspend=%d, hpd_feature=%d\n", __func__, diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h index 170837dcc9e6..df2895244794 100644 --- a/drivers/video/msm/mdss/mdss_hdmi_tx.h +++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h @@ -150,6 +150,7 @@ struct hdmi_tx_ctrl { u32 hpd_feature_on; u32 hpd_initialized; u32 vote_hdmi_core_on; + u32 dynamic_fps; u8 timing_gen_on; u8 mhl_hpd_on; u8 hdcp_status; @@ -157,6 +158,7 @@ struct hdmi_tx_ctrl { struct hdmi_util_ds_data ds_data; struct completion hpd_int_done; struct work_struct hpd_int_work; + struct work_struct fps_work; struct delayed_work hdcp_cb_work; struct work_struct cable_notify_work; diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c index 4640c3f505b6..555ba1ba5b1c 100644 --- a/drivers/video/msm/mdss/mdss_hdmi_util.c +++ b/drivers/video/msm/mdss/mdss_hdmi_util.c @@ -595,29 +595,13 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in, break; } - if (vic < 0) { - for (i = 0; i < HDMI_VFRMT_MAX; i++) { - ret = hdmi_get_supported_mode(&supported_timing, - ds_data, i); - if (ret || !supported_timing.supported) - continue; - if (timing_in->active_h != supported_timing.active_h) - continue; - if (timing_in->active_v != supported_timing.active_v) - continue; - vic = (int)supported_timing.video_format; - break; - } - } - - if (vic < 0) { + if (vic < 0) pr_err("timing is not supported h=%d v=%d\n", timing_in->active_h, timing_in->active_v); - } - + else + pr_debug("vic = %d timing = %s\n", vic, + msm_hdmi_mode_2string((u32)vic)); exit: - pr_debug("vic = %d timing = %s\n", vic, - msm_hdmi_mode_2string((u32)vic)); return vic; } /* hdmi_get_video_id_code */ diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c index 18c6c01b50db..6347578b90c0 100644 --- a/drivers/video/msm/mdss/mdss_mdp.c +++ b/drivers/video/msm/mdss/mdss_mdp.c @@ -433,6 +433,18 @@ static int mdss_mdp_bus_scale_register(struct mdss_data_type *mdata) mdata->reg_bus_hdl); } + if (mdata->hw_rt_bus_scale_table && !mdata->hw_rt_bus_hdl) { + mdata->hw_rt_bus_hdl = + msm_bus_scale_register_client( + mdata->hw_rt_bus_scale_table); + if (!mdata->hw_rt_bus_hdl) + /* Continue without reg_bus scaling */ + pr_warn("hw_rt_bus client register failed\n"); + else + pr_debug("register hw_rt_bus=%x\n", + mdata->hw_rt_bus_hdl); + } + /* * Following call will not result in actual vote rather update the * current index and ab/ib value. When continuous splash is enabled, @@ -454,6 +466,11 @@ static void mdss_mdp_bus_scale_unregister(struct mdss_data_type *mdata) msm_bus_scale_unregister_client(mdata->reg_bus_hdl); mdata->reg_bus_hdl = 0; } + + if (mdata->hw_rt_bus_hdl) { + msm_bus_scale_unregister_client(mdata->hw_rt_bus_hdl); + mdata->hw_rt_bus_hdl = 0; + } } /* @@ -1155,6 +1172,54 @@ unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked) } /** + * mdss_bus_rt_bw_vote() -- place bus bandwidth request + * @enable: value of enable or disable + * + * hw_rt table has two entries, 0 and Min Vote (1Mhz) + * while attaching SMMU and for few TZ operations which + * happen at very early stage, we will request Min Vote + * thru this handle. + * + */ +static int mdss_bus_rt_bw_vote(bool enable) +{ + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + int rc = 0; + bool changed = false; + + if (!mdata->hw_rt_bus_hdl) + return 0; + + if (enable) { + if (mdata->hw_rt_bus_ref_cnt == 0) + changed = true; + mdata->hw_rt_bus_ref_cnt++; + } else { + if (mdata->hw_rt_bus_ref_cnt != 0) { + mdata->hw_rt_bus_ref_cnt--; + if (mdata->hw_rt_bus_ref_cnt == 0) + changed = true; + } else { + pr_warn("%s: bus bw votes are not balanced\n", + __func__); + } + } + + pr_debug("%pS: task:%s bw_cnt=%d changed=%d enable=%d\n", + __builtin_return_address(0), current->group_leader->comm, + mdata->hw_rt_bus_ref_cnt, changed, enable); + + if (changed) { + rc = msm_bus_scale_client_update_request(mdata->hw_rt_bus_hdl, + enable ? 1 : 0); + if (rc) + pr_err("%s: Bus bandwidth vote failed\n", __func__); + } + + return rc; +} + +/** * __mdss_mdp_reg_access_clk_enable - Enable minimum MDSS clocks required * for register access */ @@ -1164,9 +1229,7 @@ static inline void __mdss_mdp_reg_access_clk_enable( if (enable) { mdss_update_reg_bus_vote(mdata->reg_bus_clt, VOTE_INDEX_LOW); - if (mdss_has_quirk(mdata, MDSS_QUIRK_MIN_BUS_VOTE)) - mdss_bus_scale_set_quota(MDSS_HW_RT, - SZ_1M, SZ_1M); + mdss_bus_rt_bw_vote(true); mdss_mdp_clk_update(MDSS_CLK_AHB, 1); mdss_mdp_clk_update(MDSS_CLK_AXI, 1); mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 1); @@ -1174,8 +1237,7 @@ static inline void __mdss_mdp_reg_access_clk_enable( mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 0); mdss_mdp_clk_update(MDSS_CLK_AXI, 0); mdss_mdp_clk_update(MDSS_CLK_AHB, 0); - if (mdss_has_quirk(mdata, MDSS_QUIRK_MIN_BUS_VOTE)) - mdss_bus_scale_set_quota(MDSS_HW_RT, 0, 0); + mdss_bus_rt_bw_vote(false); mdss_update_reg_bus_vote(mdata->reg_bus_clt, VOTE_INDEX_DISABLE); } @@ -1255,9 +1317,7 @@ int mdss_iommu_ctrl(int enable) * finished handoff, as it may still be working with phys addr */ if (!mdata->iommu_attached && !mdata->handoff_pending) { - if (mdss_has_quirk(mdata, MDSS_QUIRK_MIN_BUS_VOTE)) - mdss_bus_scale_set_quota(MDSS_HW_RT, - SZ_1M, SZ_1M); + mdss_bus_rt_bw_vote(true); rc = mdss_smmu_attach(mdata); } mdata->iommu_ref_cnt++; @@ -1266,10 +1326,7 @@ int mdss_iommu_ctrl(int enable) mdata->iommu_ref_cnt--; if (mdata->iommu_ref_cnt == 0) { rc = mdss_smmu_detach(mdata); - if (mdss_has_quirk(mdata, - MDSS_QUIRK_MIN_BUS_VOTE)) - mdss_bus_scale_set_quota(MDSS_HW_RT, - 0, 0); + mdss_bus_rt_bw_vote(false); } } else { pr_err("unbalanced iommu ref\n"); @@ -1780,7 +1837,6 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdss_mdp_init_default_prefill_factors(mdata); set_bit(MDSS_QOS_OTLIM, mdata->mdss_qos_map); mdss_set_quirk(mdata, MDSS_QUIRK_DMA_BI_DIR); - mdss_set_quirk(mdata, MDSS_QUIRK_MIN_BUS_VOTE); mdss_set_quirk(mdata, MDSS_QUIRK_NEED_SECURE_MAP); break; case MDSS_MDP_HW_REV_115: @@ -1801,7 +1857,6 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdss_mdp_init_default_prefill_factors(mdata); set_bit(MDSS_QOS_OTLIM, mdata->mdss_qos_map); mdss_set_quirk(mdata, MDSS_QUIRK_DMA_BI_DIR); - mdss_set_quirk(mdata, MDSS_QUIRK_MIN_BUS_VOTE); mdss_set_quirk(mdata, MDSS_QUIRK_NEED_SECURE_MAP); break; case MDSS_MDP_HW_REV_300: @@ -4183,6 +4238,23 @@ static int mdss_mdp_parse_dt_bus_scale(struct platform_device *pdev) pr_debug("mdss-reg-bus not found\n"); } + node = of_get_child_by_name(pdev->dev.of_node, "qcom,mdss-hw-rt-bus"); + if (node) { + mdata->hw_rt_bus_scale_table = + msm_bus_pdata_from_node(pdev, node); + if (IS_ERR_OR_NULL(mdata->hw_rt_bus_scale_table)) { + rc = PTR_ERR(mdata->hw_rt_bus_scale_table); + if (!rc) + pr_err("hw_rt_bus_scale failed rc=%d\n", rc); + rc = 0; + mdata->hw_rt_bus_scale_table = NULL; + } + } else { + rc = 0; + mdata->hw_rt_bus_scale_table = NULL; + pr_debug("mdss-hw-rt-bus not found\n"); + } + return rc; } #else diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c index f5413b73f27d..6b71931cb582 100644 --- a/drivers/video/msm/mdss/mdss_mdp_ctl.c +++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c @@ -1161,7 +1161,7 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe, prefill_params.is_hflip = pipe->flags & MDP_FLIP_LR; prefill_params.is_cmd = !mixer->ctl->is_video_mode; prefill_params.pnum = pipe->num; - prefill_params.is_bwc = mdss_mdp_is_ubwc_format(pipe->src_fmt); + prefill_params.is_ubwc = mdss_mdp_is_ubwc_format(pipe->src_fmt); prefill_params.is_nv12 = mdss_mdp_is_nv12_format(pipe->src_fmt); mdss_mdp_get_bw_vote_mode(mixer, mdata->mdp_rev, perf, @@ -4276,16 +4276,16 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl, } previous_frame_pu_type = mdss_mdp_get_pu_type(ctl); - mdss_mdp_set_mixer_roi(ctl->mixer_left, l_roi); - if (ctl->mixer_left) + if (ctl->mixer_left) { + mdss_mdp_set_mixer_roi(ctl->mixer_left, l_roi); ctl->roi = ctl->mixer_left->roi; + } if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) { struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl); - if (sctl) { - mdss_mdp_set_mixer_roi(sctl->mixer_left, r_roi); - if (sctl->mixer_left) + if (sctl && sctl->mixer_left) { + mdss_mdp_set_mixer_roi(sctl->mixer_left, r_roi); sctl->roi = sctl->mixer_left->roi; } } else if (is_dual_lm_single_display(ctl->mfd) && ctl->mixer_right) { diff --git a/drivers/video/msm/mdss/mdss_mdp_layer.c b/drivers/video/msm/mdss/mdss_mdp_layer.c index 8d0167a94837..cd95c3c9de9b 100644 --- a/drivers/video/msm/mdss/mdss_mdp_layer.c +++ b/drivers/video/msm/mdss/mdss_mdp_layer.c @@ -345,7 +345,7 @@ static int __validate_layer_reconfig(struct mdp_input_layer *layer, */ if (pipe->csc_coeff_set != layer->color_space) { src_fmt = mdss_mdp_get_format_params(layer->buffer.format); - if (pipe->src_fmt->is_yuv && src_fmt->is_yuv) { + if (pipe->src_fmt->is_yuv && src_fmt && src_fmt->is_yuv) { status = -EPERM; pr_err("csc change is not permitted on used pipe\n"); } diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index 12779107632a..081f1bd0a24b 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -3365,18 +3365,20 @@ static ssize_t mdss_mdp_misr_store(struct device *dev, req.frame_count = 1; } else { pr_err("misr not supported fo this fb:%d\n", mfd->index); + rc = -ENODEV; + return rc; } if (enable_misr) { mdss_misr_set(mdata, &req , ctl); - if (is_panel_split(mfd)) + if ((ctl->intf_type == MDSS_INTF_DSI) && is_panel_split(mfd)) mdss_misr_set(mdata, &sreq , ctl); } else { mdss_misr_disable(mdata, &req, ctl); - if (is_panel_split(mfd)) + if ((ctl->intf_type == MDSS_INTF_DSI) && is_panel_split(mfd)) mdss_misr_disable(mdata, &sreq , ctl); } @@ -4824,6 +4826,7 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd) int rc; struct mdss_overlay_private *mdp5_data; struct mdss_mdp_ctl *ctl = NULL; + struct mdss_data_type *mdata; if (!mfd) return -ENODEV; @@ -4835,6 +4838,10 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd) if (!mdp5_data) return -EINVAL; + mdata = mfd_to_mdata(mfd); + if (!mdata) + return -EINVAL; + mdss_mdp_set_lm_flag(mfd); if (!mdp5_data->ctl) { @@ -4864,9 +4871,16 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd) if (rc) goto panel_on; + /* Skip the overlay start and kickoff for all displays + if handoff is pending. Previously we skipped it for DTV + panel and pluggable panels (bridge chip hdmi case). But + it does not cover the case where there is a non pluggable + tertiary display. Using the flag handoff_pending to skip + overlay start and kickoff should cover all cases + TODO: In the long run, the overlay start and kickoff + should not be skipped, instead, the handoff can be done */ if (!mfd->panel_info->cont_splash_enabled && - (mfd->panel_info->type != DTV_PANEL) && - !mfd->panel_info->is_pluggable) { + !mdata->handoff_pending) { rc = mdss_mdp_overlay_start(mfd); if (rc) goto end; diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h index bd9b44ff2a9c..c97c946ae2f1 100644 --- a/drivers/video/msm/mdss/mdss_panel.h +++ b/drivers/video/msm/mdss/mdss_panel.h @@ -606,6 +606,7 @@ struct mdss_panel_info { bool ulps_suspend_enabled; bool panel_ack_disabled; bool esd_check_enabled; + bool allow_phy_power_off; char dfps_update; /* new requested fps before it is updated in hw */ int new_fps; diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c index 502e0069d880..722460a6693e 100644 --- a/drivers/video/msm/mdss/msm_mdss_io_8974.c +++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c @@ -1847,7 +1847,11 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, { int rc = 0; struct mdss_dsi_ctrl_pdata *mctrl = NULL; - int i; + int i, *vote_cnt; + + void *m_clk_handle; + bool is_ecg = false; + int state = MDSS_DSI_CLK_OFF; if (!ctrl) { pr_err("%s: Invalid arg\n", __func__); @@ -1879,6 +1883,18 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, } /* + * it should add and remove extra votes based on voting clients to avoid + * removal of legitimate vote from DSI client. + */ + if (mctrl && (clk_handle == ctrl->dsi_clk_handle)) { + m_clk_handle = mctrl->dsi_clk_handle; + vote_cnt = &mctrl->m_dsi_vote_cnt; + } else if (mctrl) { + m_clk_handle = mctrl->mdp_clk_handle; + vote_cnt = &mctrl->m_mdp_vote_cnt; + } + + /* * When DSI is used in split mode, the link clock for master controller * has to be turned on first before the link clock for slave can be * turned on. In case the current controller is a slave, an ON vote is @@ -1890,18 +1906,24 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, __func__, ctrl->ndx, clk_type, clk_state, __builtin_return_address(0), mctrl ? 1 : 0); if (mctrl && (clk_type & MDSS_DSI_LINK_CLK)) { - rc = mdss_dsi_clk_req_state(mctrl->dsi_clk_handle, - MDSS_DSI_ALL_CLKS, - MDSS_DSI_CLK_ON); + if (clk_state != MDSS_DSI_CLK_ON) { + /* preserve clk state; do not turn off forcefully */ + is_ecg = is_dsi_clk_in_ecg_state(m_clk_handle); + if (is_ecg) + state = MDSS_DSI_CLK_EARLY_GATE; + } + + rc = mdss_dsi_clk_req_state(m_clk_handle, + MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON, mctrl->ndx); if (rc) { pr_err("%s: failed to turn on mctrl clocks, rc=%d\n", __func__, rc); goto error; } - ctrl->m_vote_cnt++; + (*vote_cnt)++; } - rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state); + rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state, ctrl->ndx); if (rc) { pr_err("%s: failed set clk state, rc = %d\n", __func__, rc); goto error; @@ -1930,24 +1952,24 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, * for ON, since the previous ECG state must have * removed two votes to let clocks turn off. * - * To satisfy the above requirement, m_vote_cnt keeps track of + * To satisfy the above requirement, vote_cnt keeps track of * the number of ON votes for master requested by slave. For - * every OFF/ECG state request, Either 2 or m_vote_cnt number of + * every OFF/ECG state request, Either 2 or vote_cnt number of * votes are removed depending on which is lower. */ - for (i = 0; (i < ctrl->m_vote_cnt && i < 2); i++) { - rc = mdss_dsi_clk_req_state(mctrl->dsi_clk_handle, - MDSS_DSI_ALL_CLKS, - MDSS_DSI_CLK_OFF); + for (i = 0; (i < *vote_cnt && i < 2); i++) { + rc = mdss_dsi_clk_req_state(m_clk_handle, + MDSS_DSI_ALL_CLKS, state, mctrl->ndx); if (rc) { pr_err("%s: failed to set mctrl clk state, rc = %d\n", __func__, rc); goto error; } } - ctrl->m_vote_cnt -= i; - pr_debug("%s: ctrl=%d, m_vote_cnt=%d\n", __func__, ctrl->ndx, - ctrl->m_vote_cnt); + (*vote_cnt) -= i; + pr_debug("%s: ctrl=%d, vote_cnt=%d dsi_vote_cnt=%d mdp_vote_cnt:%d\n", + __func__, ctrl->ndx, *vote_cnt, mctrl->m_dsi_vote_cnt, + mctrl->m_mdp_vote_cnt); } error: diff --git a/drivers/video/msm/msm_dba/adv7533.c b/drivers/video/msm/msm_dba/adv7533.c index a3b4466d105d..8503d84e0de4 100644 --- a/drivers/video/msm/msm_dba/adv7533.c +++ b/drivers/video/msm/msm_dba/adv7533.c @@ -880,8 +880,8 @@ static void adv7533_handle_cec_intr(struct adv7533 *pdata, u8 cec_status) { u8 cec_int_clear = 0x08; bool cec_rx_intr = false; - u8 cec_rx_ready; - u8 cec_rx_timestamp; + u8 cec_rx_ready = 0; + u8 cec_rx_timestamp = 0; if (!pdata) { pr_err("%s: Invalid input\n", __func__); @@ -983,7 +983,7 @@ end: static void *adv7533_handle_hpd_intr(struct adv7533 *pdata) { - int ret; + int ret = 0; u8 hpd_state; u8 connected = 0, disconnected = 0; diff --git a/include/dt-bindings/clock/msm-clocks-8996.h b/include/dt-bindings/clock/msm-clocks-8996.h index 82ca331c7057..9a0fc514ce68 100644 --- a/include/dt-bindings/clock/msm-clocks-8996.h +++ b/include/dt-bindings/clock/msm-clocks-8996.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -542,4 +542,5 @@ #define clk_audio_ap_clk 0x312ac429 #define clk_audio_pmi_clk 0xb7ba2274 #define clk_audio_ap_clk2 0xf0fbaf5b +#define clk_audio_lpass_mclk2 0x0122abee #endif diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h index 3b25d7d1280c..768c44d9ea8b 100644 --- a/include/linux/diagchar.h +++ b/include/linux/diagchar.h @@ -144,10 +144,10 @@ the appropriate macros. */ /* This needs to be modified manually now, when we add a new RANGE of SSIDs to the msg_mask_tbl */ #define MSG_MASK_TBL_CNT 25 -#define APPS_EVENT_LAST_ID 0x0ABB +#define APPS_EVENT_LAST_ID 0x0B14 #define MSG_SSID_0 0 -#define MSG_SSID_0_LAST 117 +#define MSG_SSID_0_LAST 118 #define MSG_SSID_1 500 #define MSG_SSID_1_LAST 506 #define MSG_SSID_2 1000 @@ -335,7 +335,8 @@ static const uint32_t msg_bld_masks_0[] = { MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL, MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL, MSG_LVL_MED, - MSG_LVL_MED + MSG_LVL_MED, + MSG_LVL_HIGH }; static const uint32_t msg_bld_masks_1[] = { @@ -853,7 +854,7 @@ static const uint32_t msg_bld_masks_23[] = { /* LOG CODES */ static const uint32_t log_code_last_tbl[] = { 0x0, /* EQUIP ID 0 */ - 0x192C, /* EQUIP ID 1 */ + 0x1966, /* EQUIP ID 1 */ 0x0, /* EQUIP ID 2 */ 0x0, /* EQUIP ID 3 */ 0x4910, /* EQUIP ID 4 */ diff --git a/include/linux/ipa.h b/include/linux/ipa.h index 3a87177b623f..0dd2f0bf9c23 100644 --- a/include/linux/ipa.h +++ b/include/linux/ipa.h @@ -524,7 +524,11 @@ struct ipa_ext_intf { * in system-BAM mode * @ipa_ep_cfg: IPA EP configuration * @client: the type of client who "owns" the EP - * @desc_fifo_sz: size of desc FIFO + * @desc_fifo_sz: size of desc FIFO. This number is used to allocate the desc + * fifo for BAM. For GSI, this size is used by IPA driver as a + * baseline to calculate the GSI ring size in the following way: + * For PROD pipes, GSI ring is 4 * desc_fifo_sz. + For PROD pipes, GSI ring is 2 * desc_fifo_sz. * @priv: callback cookie * @notify: callback * priv - callback cookie diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 5cd72b06bec7..7bebacaee0ac 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -75,8 +75,8 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size); void memblock_trim_memory(phys_addr_t align); int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); -void memblock_region_resize_late_begin(void); -void memblock_region_resize_late_end(void); +unsigned long memblock_region_resize_late_begin(void); +void memblock_region_resize_late_end(unsigned long); /* Low level functions */ int memblock_add_range(struct memblock_type *type, diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h index 138aeca4f7fb..65dbdd7756e2 100644 --- a/include/linux/msm_thermal.h +++ b/include/linux/msm_thermal.h @@ -1,5 +1,5 @@ /* - * 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 @@ -74,6 +74,7 @@ struct msm_thermal_data { int32_t cx_phase_request_key; int32_t vdd_mx_temp_degC; int32_t vdd_mx_temp_hyst_degC; + int32_t vdd_mx_sensor_id; int32_t therm_reset_temp_degC; }; @@ -91,6 +92,7 @@ struct therm_threshold { int32_t trip_triggered; void (*notify)(struct therm_threshold *); struct threshold_info *parent; + int32_t cur_state; }; struct threshold_info { diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 705ac2f7181c..d10a4e1dd1b0 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -208,6 +208,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_RESTRICTED_CHARGING, POWER_SUPPLY_PROP_CURRENT_CAPABILITY, POWER_SUPPLY_PROP_TYPEC_MODE, + POWER_SUPPLY_PROP_ALLOW_HVDCP3, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ diff --git a/include/linux/qdsp6v2/apr_tal.h b/include/linux/qdsp6v2/apr_tal.h index eeb6ede976ad..ee8b2f5a8b5b 100644 --- a/include/linux/qdsp6v2/apr_tal.h +++ b/include/linux/qdsp6v2/apr_tal.h @@ -87,6 +87,7 @@ struct apr_svc_ch_dev { wait_queue_head_t wait; void *priv; unsigned channel_state; + bool if_remote_intent_ready; }; #else struct apr_svc_ch_dev { diff --git a/include/linux/sched.h b/include/linux/sched.h index cfe267dfde27..2db6efb4a19f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1324,6 +1324,7 @@ struct task_struct { u32 init_load_pct; u64 last_wake_ts; u64 last_switch_out_ts; + u64 last_cpu_selected_ts; #ifdef CONFIG_SCHED_QHMP u64 run_start; #endif diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index 719a40be8cf1..35b07496dd44 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -69,6 +69,7 @@ extern unsigned int sysctl_sched_boost; extern unsigned int sysctl_early_detection_duration; extern unsigned int sysctl_sched_small_wakee_task_load_pct; extern unsigned int sysctl_sched_big_waker_task_load_pct; +extern unsigned int sysctl_sched_prefer_sync_wakee_to_waker; #ifdef CONFIG_SCHED_QHMP extern unsigned int sysctl_sched_min_runtime; diff --git a/include/linux/soundwire/soundwire.h b/include/linux/soundwire/soundwire.h index f19e871d6ac2..4b957245209e 100644 --- a/include/linux/soundwire/soundwire.h +++ b/include/linux/soundwire/soundwire.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 @@ -151,6 +151,7 @@ struct swr_master { const void *buf, size_t len); int (*get_logical_dev_num)(struct swr_master *mstr, u64 dev_id, u8 *dev_num); + void (*slvdev_datapath_control)(struct swr_master *mstr, bool enable); }; static inline struct swr_master *to_swr_master(struct device *dev) @@ -304,4 +305,6 @@ extern int swr_device_down(struct swr_device *swr_dev); extern int swr_reset_device(struct swr_device *swr_dev); +extern int swr_slvdev_datapath_control(struct swr_device *swr_dev, u8 dev_num, + bool enable); #endif /* _LINUX_SOUNDWIRE_H */ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index c42bd0a6b34a..9a30c1e01fb2 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -235,6 +235,8 @@ struct hc_driver { #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ #define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */ #define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */ +#define HCD_RT_OLD_ENUM 0x0008 /* HC supports short enumeration + on root port */ #define HCD_USB11 0x0010 /* USB 1.1 */ #define HCD_USB2 0x0020 /* USB 2.0 */ #define HCD_USB25 0x0030 /* Wireless USB 1.0 (USB 2.5)*/ @@ -381,6 +383,7 @@ struct hc_driver { int (*disable_usb3_lpm_timeout)(struct usb_hcd *, struct usb_device *, enum usb3_link_state state); int (*find_raw_port_number)(struct usb_hcd *, int); + void (*log_urb)(struct urb *urb, char *event, unsigned extra); void (*dump_regs)(struct usb_hcd *); void (*set_autosuspend_delay)(struct usb_device *); void (*reset_sof_bug_handler)(struct usb_hcd *hcd, u32 val); diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 939d06688928..d32fffd40b90 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -599,6 +599,8 @@ struct msm_hsic_host_platform_data { /* gpio used to resume peripheral */ unsigned resume_gpio; + int *tlmm_init_seq; + int tlmm_seq_count; /*swfi latency is required while driving resume on to the bus */ u32 swfi_latency; diff --git a/include/net/cnss.h b/include/net/cnss.h index e9d0ca85d7f2..b37bbab30579 100644 --- a/include/net/cnss.h +++ b/include/net/cnss.h @@ -16,9 +16,7 @@ #include <linux/skbuff.h> #include <linux/pci.h> #include <net/cnss_common.h> -#ifdef CONFIG_CNSS_SDIO #include <linux/mmc/sdio_func.h> -#endif #ifdef CONFIG_CNSS #define CNSS_MAX_FILE_NAME 20 @@ -189,7 +187,6 @@ enum { }; extern int cnss_get_restart_level(void); -#ifdef CONFIG_CNSS_SDIO struct cnss_sdio_wlan_driver { const char *name; const struct sdio_device_id *id_table; @@ -212,5 +209,4 @@ extern int cnss_wlan_query_oob_status(void); extern int cnss_wlan_register_oob_irq_handler(oob_irq_handler_t handler, void *pm_oob); extern int cnss_wlan_unregister_oob_irq_handler(void *pm_oob); -#endif #endif /* _NET_CNSS_H_ */ diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 5bffd4f1ac68..d2cf8c2973d3 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -2,6 +2,7 @@ * Video for Linux Two header file * * Copyright (C) 1999-2012 the contributors + * 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 as published by @@ -410,6 +411,12 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SGBRG10DPCM8 v4l2_fourcc('b', 'G', 'A', '8') #define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0') #define V4L2_PIX_FMT_SRGGB10DPCM8 v4l2_fourcc('b', 'R', 'A', '8') + /* 10bit raw bayer DPCM compressed to 6 bits */ +#define V4L2_PIX_FMT_SBGGR10DPCM6 v4l2_fourcc('b', 'B', 'A', '6') +#define V4L2_PIX_FMT_SGBRG10DPCM6 v4l2_fourcc('b', 'G', 'A', '6') +#define V4L2_PIX_FMT_SGRBG10DPCM6 v4l2_fourcc('B', 'D', '1', '6') +#define V4L2_PIX_FMT_SRGGB10DPCM6 v4l2_fourcc('b', 'R', 'A', '6') + /* * 10bit raw bayer, expanded to 16 bits * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... @@ -1893,12 +1900,19 @@ struct v4l2_streamparm { #define V4L2_EVENT_MOTION_DET 6 #define V4L2_EVENT_PRIVATE_START 0x08000000 +#define V4L2_EVENT_BITDEPTH_FLAG 0x1 +#define V4L2_EVENT_PICSTRUCT_FLAG 0x2 + #define V4L2_EVENT_MSM_VIDC_START (V4L2_EVENT_PRIVATE_START + 0x00001000) #define V4L2_EVENT_MSM_VIDC_FLUSH_DONE (V4L2_EVENT_MSM_VIDC_START + 1) #define V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT \ (V4L2_EVENT_MSM_VIDC_START + 2) #define V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT \ (V4L2_EVENT_MSM_VIDC_START + 3) +/* + * Bitdepth changed insufficient is deprecated now, however retaining + * to prevent changing the values of the other macros after bitdepth + */ #define V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT \ (V4L2_EVENT_MSM_VIDC_START + 4) #define V4L2_EVENT_MSM_VIDC_SYS_ERROR (V4L2_EVENT_MSM_VIDC_START + 5) diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h index 3985e9750af7..01e52b6f7b44 100644 --- a/include/uapi/media/msm_camsensor_sdk.h +++ b/include/uapi/media/msm_camsensor_sdk.h @@ -18,6 +18,7 @@ #define CSI_DECODE_8BIT 1 #define CSI_DECODE_10BIT 2 #define CSI_DECODE_12BIT 3 +#define CSI_DECODE_DPCM_10_6_10 4 #define CSI_DECODE_DPCM_10_8_10 5 #define MAX_CID 16 #define I2C_SEQ_REG_DATA_MAX 1024 diff --git a/include/uapi/media/msm_vidc.h b/include/uapi/media/msm_vidc.h index ac36b23bfa97..eaf2f5e02d0e 100644 --- a/include/uapi/media/msm_vidc.h +++ b/include/uapi/media/msm_vidc.h @@ -225,4 +225,9 @@ enum msm_vidc_pixel_depth { MSM_VIDC_BIT_DEPTH_10, MSM_VIDC_BIT_DEPTH_UNSUPPORTED = 0XFFFFFFFF, }; + +/*enum msm_vidc_pic_struct */ +#define MSM_VIDC_PIC_STRUCT_MAYBE_INTERLACED 0x0 +#define MSM_VIDC_PIC_STRUCT_PROGRESSIVE 0x1 + #endif diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 96e250d87936..a19ca1b74160 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -512,7 +512,6 @@ void pm_qos_add_request(struct pm_qos_request *req, #ifdef CONFIG_SMP case PM_QOS_REQ_AFFINE_IRQ: if (irq_can_set_affinity(req->irq)) { - int ret = 0; struct irq_desc *desc = irq_to_desc(req->irq); struct cpumask *mask = desc->irq_data.affinity; @@ -522,13 +521,6 @@ void pm_qos_add_request(struct pm_qos_request *req, req->irq_notify.notify = pm_qos_irq_notify; req->irq_notify.release = pm_qos_irq_release; - ret = irq_set_affinity_notifier(req->irq, - &req->irq_notify); - if (ret) { - WARN(1, KERN_ERR "IRQ affinity notify set failed\n"); - req->type = PM_QOS_REQ_ALL_CORES; - cpumask_setall(&req->cpus_affine); - } } else { req->type = PM_QOS_REQ_ALL_CORES; cpumask_setall(&req->cpus_affine); @@ -550,6 +542,24 @@ void pm_qos_add_request(struct pm_qos_request *req, trace_pm_qos_add_request(pm_qos_class, value); pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints, req, PM_QOS_ADD_REQ, value); + +#ifdef CONFIG_SMP + if (req->type == PM_QOS_REQ_AFFINE_IRQ && + irq_can_set_affinity(req->irq)) { + int ret = 0; + + ret = irq_set_affinity_notifier(req->irq, + &req->irq_notify); + if (ret) { + WARN(1, "IRQ affinity notify set failed\n"); + req->type = PM_QOS_REQ_ALL_CORES; + cpumask_setall(&req->cpus_affine); + pm_qos_update_target( + pm_qos_array[pm_qos_class]->constraints, + req, PM_QOS_UPDATE_REQ, value); + } + } +#endif } EXPORT_SYMBOL_GPL(pm_qos_add_request); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 7ccf09ac095a..c61bd0932136 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2822,6 +2822,7 @@ static inline void mark_task_starting(struct task_struct *p) wallclock = sched_ktime_clock(); p->ravg.mark_start = p->last_wake_ts = wallclock; + p->last_cpu_selected_ts = wallclock; p->last_switch_out_ts = 0; } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 0f30df8f25af..8214707009fd 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2480,6 +2480,13 @@ unsigned int __read_mostly sched_big_waker_task_load; unsigned int __read_mostly sysctl_sched_big_waker_task_load_pct = 25; /* + * Prefer the waker CPU for sync wakee task, if the CPU has only 1 runnable + * task. This eliminates the LPM exit latency associated with the idle + * CPUs in the waker cluster. + */ +unsigned int __read_mostly sysctl_sched_prefer_sync_wakee_to_waker; + +/* * CPUs with load greater than the sched_spill_load_threshold are not * eligible for task placement. When all CPUs in a cluster achieve a * load higher than this level, tasks becomes eligible for inter @@ -2548,6 +2555,9 @@ static unsigned int __read_mostly sched_short_sleep_task_threshold = 2000 * NSEC_PER_USEC; unsigned int __read_mostly sysctl_sched_select_prev_cpu_us = 2000; +static unsigned int __read_mostly +sched_long_cpu_selection_threshold = 100 * NSEC_PER_MSEC; + unsigned int __read_mostly sysctl_sched_restrict_cluster_spill; void update_up_down_migrate(void) @@ -3239,6 +3249,7 @@ bias_to_prev_cpu(struct cpu_select_env *env, struct cluster_cpu_stats *stats) struct sched_cluster *cluster; if (env->boost || env->reason || env->need_idle || + !task->ravg.mark_start || !sched_short_sleep_task_threshold) return false; @@ -3247,6 +3258,10 @@ bias_to_prev_cpu(struct cpu_select_env *env, struct cluster_cpu_stats *stats) unlikely(!cpu_active(prev_cpu))) return false; + if (task->ravg.mark_start - task->last_cpu_selected_ts >= + sched_long_cpu_selection_threshold) + return false; + /* * This function should be used by task wake up path only as it's * assuming p->last_switch_out_ts as last sleep time. @@ -3307,6 +3322,7 @@ static int select_best_cpu(struct task_struct *p, int target, int reason, struct cluster_cpu_stats stats; bool fast_path = false; struct related_thread_group *grp; + int cpu = raw_smp_processor_id(); struct cpu_select_env env = { .p = p, @@ -3345,12 +3361,20 @@ static int select_best_cpu(struct task_struct *p, int target, int reason, else env.rtg = grp; } else { - cluster = cpu_rq(smp_processor_id())->cluster; - if (wake_to_waker_cluster(&env) && - cluster_allowed(p, cluster)) { - env.need_waker_cluster = 1; - bitmap_zero(env.candidate_list, NR_CPUS); - __set_bit(cluster->id, env.candidate_list); + cluster = cpu_rq(cpu)->cluster; + if (wake_to_waker_cluster(&env)) { + if (sysctl_sched_prefer_sync_wakee_to_waker && + cpu_rq(cpu)->nr_running == 1 && + cpumask_test_cpu(cpu, tsk_cpus_allowed(p)) && + cpu_active(cpu)) { + fast_path = true; + target = cpu; + goto out; + } else if (cluster_allowed(p, cluster)) { + env.need_waker_cluster = 1; + bitmap_zero(env.candidate_list, NR_CPUS); + __set_bit(cluster->id, env.candidate_list); + } } else if (bias_to_prev_cpu(&env, &stats)) { fast_path = true; goto out; @@ -3393,6 +3417,7 @@ retry: if (stats.best_capacity_cpu >= 0) target = stats.best_capacity_cpu; } + p->last_cpu_selected_ts = sched_ktime_clock(); out: rcu_read_unlock(); @@ -4784,17 +4809,25 @@ static void check_enqueue_throttle(struct cfs_rq *cfs_rq); static void enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) { + bool renorm = !(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_WAKING); + bool curr = cfs_rq->curr == se; + /* - * Update the normalized vruntime before updating min_vruntime - * through calling update_curr(). + * If we're the current task, we must renormalise before calling + * update_curr(). */ - if (!(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_WAKING)) + if (renorm && curr) se->vruntime += cfs_rq->min_vruntime; + update_curr(cfs_rq); + /* - * Update run-time statistics of the 'current'. + * Otherwise, renormalise after, such that we're placed at the current + * moment in time, instead of some random moment in the past. */ - update_curr(cfs_rq); + if (renorm && !curr) + se->vruntime += cfs_rq->min_vruntime; + enqueue_entity_load_avg(cfs_rq, se, flags & ENQUEUE_WAKEUP); account_entity_enqueue(cfs_rq, se); update_cfs_shares(cfs_rq); @@ -4806,7 +4839,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) update_stats_enqueue(cfs_rq, se, !!(flags & ENQUEUE_MIGRATING)); check_spread(cfs_rq, se); - if (se != cfs_rq->curr) + if (!curr) __enqueue_entity(cfs_rq, se); se->on_rq = 1; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4fa328e14820..3065771d7971 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -481,6 +481,15 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "sched_prefer_sync_wakee_to_waker", + .data = &sysctl_sched_prefer_sync_wakee_to_waker, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, #ifdef CONFIG_SCHED_FREQ_INPUT { .procname = "sched_new_task_windows", diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 0f5df4abc4bf..17b5a671cf44 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -256,10 +256,8 @@ int perf_trace_add(struct perf_event *p_event, int flags) void perf_trace_del(struct perf_event *p_event, int flags) { struct ftrace_event_call *tp_event = p_event->tp_event; - if(!hlist_unhashed(&p_event->hlist_entry)) + if (!hlist_unhashed(&p_event->hlist_entry)) hlist_del_rcu(&p_event->hlist_entry); - else - return; tp_event->class->reg(tp_event, TRACE_REG_PERF_DEL, p_event); } diff --git a/mm/memblock.c b/mm/memblock.c index eb9667374e04..eb096ebc475e 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -21,6 +21,7 @@ #include <linux/memblock.h> #include <linux/preempt.h> #include <linux/seqlock.h> +#include <linux/irqflags.h> #include <asm-generic/sections.h> #include <linux/io.h> @@ -1557,30 +1558,35 @@ void __init memblock_allow_resize(void) memblock_can_resize = 1; } -static void __init_memblock memblock_resize_late(int begin) +static unsigned long __init_memblock +memblock_resize_late(int begin, unsigned long flags) { static int memblock_can_resize_old; if (begin) { preempt_disable(); + local_irq_save(flags); memblock_can_resize_old = memblock_can_resize; memblock_can_resize = 0; raw_write_seqcount_begin(&memblock_seq); } else { raw_write_seqcount_end(&memblock_seq); memblock_can_resize = memblock_can_resize_old; + local_irq_restore(flags); preempt_enable(); } + + return flags; } -void __init_memblock memblock_region_resize_late_begin(void) +unsigned long __init_memblock memblock_region_resize_late_begin(void) { - memblock_resize_late(1); + return memblock_resize_late(1, 0); } -void __init_memblock memblock_region_resize_late_end(void) +void __init_memblock memblock_region_resize_late_end(unsigned long flags) { - memblock_resize_late(0); + memblock_resize_late(0, flags); } static int __init early_memblock(char *p) diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index 46456684350c..4f1ce53f7efa 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -1923,11 +1923,6 @@ static int ipc_router_send_ctl_msg( ret = process_resume_tx_msg(msg, pkt); } else if (xprt_info && (msg->cmd == IPC_ROUTER_CTRL_CMD_HELLO || xprt_info->initialized)) { - ret = ipc_router_get_xprt_info_ref(xprt_info); - if (ret < 0) { - IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__); - return ret; - } mutex_lock(&xprt_info->tx_lock_lhb2); ipc_router_log_msg(xprt_info->log_ctx, IPC_ROUTER_LOG_EVENT_TX, msg, hdr, NULL, NULL); @@ -1936,14 +1931,11 @@ static int ipc_router_send_ctl_msg( mutex_unlock(&xprt_info->tx_lock_lhb2); IPC_RTR_ERR("%s: Prepend Header failed\n", __func__); release_pkt(pkt); - kref_put(&xprt_info->ref, - ipc_router_release_xprt_info_ref); return ret; } ret = xprt_info->xprt->write(pkt, pkt->length, xprt_info->xprt); mutex_unlock(&xprt_info->tx_lock_lhb2); - kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref); } release_pkt(pkt); @@ -3254,9 +3246,16 @@ static int msm_ipc_router_send_resume_tx(void *data) __func__, hdr->src_node_id); return -ENODEV; } + ret = ipc_router_get_xprt_info_ref(rt_entry->xprt_info); + if (ret < 0) { + IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__); + kref_put(&rt_entry->ref, ipc_router_release_rtentry); + return ret; + } ret = ipc_router_send_ctl_msg(rt_entry->xprt_info, &msg, hdr->src_node_id); kref_put(&rt_entry->ref, ipc_router_release_rtentry); + kref_put(&rt_entry->xprt_info->ref, ipc_router_release_xprt_info_ref); if (ret < 0) IPC_RTR_ERR( "%s: Send Resume_Tx Failed SRC_NODE: %d SRC_PORT: %d DEST_NODE: %d", diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index 87603f69eabc..4b9095d337ba 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1174,6 +1174,38 @@ static void iface_stat_update(struct net_device *net_dev, bool stash_only) spin_unlock_bh(&iface_stat_list_lock); } +/* Guarantied to return a net_device that has a name */ +static void get_dev_and_dir(const struct sk_buff *skb, + struct xt_action_param *par, + enum ifs_tx_rx *direction, + const struct net_device **el_dev) +{ + BUG_ON(!direction || !el_dev); + + if (par->in) { + *el_dev = par->in; + *direction = IFS_RX; + } else if (par->out) { + *el_dev = par->out; + *direction = IFS_TX; + } else { + pr_err("qtaguid[%d]: %s(): no par->in/out?!!\n", + par->hooknum, __func__); + BUG(); + } + if (unlikely(!(*el_dev)->name)) { + pr_err("qtaguid[%d]: %s(): no dev->name?!!\n", + par->hooknum, __func__); + BUG(); + } + if (skb->dev && *el_dev != skb->dev) { + MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs par->%s=%p %s\n", + par->hooknum, skb->dev, skb->dev->name, + *direction == IFS_RX ? "in" : "out", *el_dev, + (*el_dev)->name); + } +} + /* * Update stats for the specified interface from the skb. * Do nothing if the entry @@ -1185,50 +1217,27 @@ static void iface_stat_update_from_skb(const struct sk_buff *skb, { struct iface_stat *entry; const struct net_device *el_dev; - enum ifs_tx_rx direction = par->in ? IFS_RX : IFS_TX; + enum ifs_tx_rx direction; int bytes = skb->len; int proto; - if (!skb->dev) { - MT_DEBUG("qtaguid[%d]: no skb->dev\n", par->hooknum); - el_dev = par->in ? : par->out; - } else { - const struct net_device *other_dev; - el_dev = skb->dev; - other_dev = par->in ? : par->out; - if (el_dev != other_dev) { - MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs " - "par->(in/out)=%p %s\n", - par->hooknum, el_dev, el_dev->name, other_dev, - other_dev->name); - } - } - - if (unlikely(!el_dev)) { - pr_err_ratelimited("qtaguid[%d]: %s(): no par->in/out?!!\n", - par->hooknum, __func__); - BUG(); - } else if (unlikely(!el_dev->name)) { - pr_err_ratelimited("qtaguid[%d]: %s(): no dev->name?!!\n", - par->hooknum, __func__); - BUG(); - } else { - proto = ipx_proto(skb, par); - MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n", - par->hooknum, el_dev->name, el_dev->type, - par->family, proto); - } + get_dev_and_dir(skb, par, &direction, &el_dev); + proto = ipx_proto(skb, par); + MT_DEBUG("qtaguid[%d]: iface_stat: %s(%s): " + "type=%d fam=%d proto=%d dir=%d\n", + par->hooknum, __func__, el_dev->name, el_dev->type, + par->family, proto, direction); spin_lock_bh(&iface_stat_list_lock); entry = get_iface_entry(el_dev->name); if (entry == NULL) { - IF_DEBUG("qtaguid: iface_stat: %s(%s): not tracked\n", - __func__, el_dev->name); + IF_DEBUG("qtaguid[%d]: iface_stat: %s(%s): not tracked\n", + par->hooknum, __func__, el_dev->name); spin_unlock_bh(&iface_stat_list_lock); return; } - IF_DEBUG("qtaguid: %s(%s): entry=%p\n", __func__, + IF_DEBUG("qtaguid[%d]: %s(%s): entry=%p\n", par->hooknum, __func__, el_dev->name, entry); data_counters_update(&entry->totals_via_skb, 0, direction, proto, @@ -1293,13 +1302,13 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, iface_entry = get_iface_entry(ifname); if (!iface_entry) { - pr_err_ratelimited("qtaguid: iface_stat: stat_update() " + pr_err_ratelimited("qtaguid: tag_stat: stat_update() " "%s not found\n", ifname); return; } /* It is ok to process data when an iface_entry is inactive */ - MT_DEBUG("qtaguid: iface_stat: stat_update() dev=%s entry=%p\n", + MT_DEBUG("qtaguid: tag_stat: stat_update() dev=%s entry=%p\n", ifname, iface_entry); /* @@ -1316,7 +1325,7 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, tag = combine_atag_with_uid(acct_tag, uid); uid_tag = make_tag_from_uid(uid); } - MT_DEBUG("qtaguid: iface_stat: stat_update(): " + MT_DEBUG("qtaguid: tag_stat: stat_update(): " " looking for tag=0x%llx (uid=%u) in ife=%p\n", tag, get_uid_from_tag(tag), iface_entry); /* Loop over tag list under this interface for {acct_tag,uid_tag} */ @@ -1576,8 +1585,8 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb, struct sock *sk; unsigned int hook_mask = (1 << par->hooknum); - MT_DEBUG("qtaguid: find_sk(skb=%p) hooknum=%d family=%d\n", skb, - par->hooknum, par->family); + MT_DEBUG("qtaguid[%d]: find_sk(skb=%p) family=%d\n", + par->hooknum, skb, par->family); /* * Let's not abuse the the xt_socket_get*_sk(), or else it will @@ -1598,8 +1607,8 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb, } if (sk) { - MT_DEBUG("qtaguid: %p->sk_proto=%u " - "->sk_state=%d\n", sk, sk->sk_protocol, sk->sk_state); + MT_DEBUG("qtaguid[%d]: %p->sk_proto=%u->sk_state=%d\n", + par->hooknum, sk, sk->sk_protocol, sk->sk_state); /* * When in TCP_TIME_WAIT the sk is not a "struct sock" but * "struct inet_timewait_sock" which is missing fields. @@ -1618,37 +1627,19 @@ static void account_for_uid(const struct sk_buff *skb, struct xt_action_param *par) { const struct net_device *el_dev; + enum ifs_tx_rx direction; + int proto; - if (!skb->dev) { - MT_DEBUG("qtaguid[%d]: no skb->dev\n", par->hooknum); - el_dev = par->in ? : par->out; - } else { - const struct net_device *other_dev; - el_dev = skb->dev; - other_dev = par->in ? : par->out; - if (el_dev != other_dev) { - MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs " - "par->(in/out)=%p %s\n", - par->hooknum, el_dev, el_dev->name, other_dev, - other_dev->name); - } - } - - if (unlikely(!el_dev)) { - pr_info("qtaguid[%d]: no par->in/out?!!\n", par->hooknum); - } else if (unlikely(!el_dev->name)) { - pr_info("qtaguid[%d]: no dev->name?!!\n", par->hooknum); - } else { - int proto = ipx_proto(skb, par); - MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n", - par->hooknum, el_dev->name, el_dev->type, - par->family, proto); + get_dev_and_dir(skb, par, &direction, &el_dev); + proto = ipx_proto(skb, par); + MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d dir=%d\n", + par->hooknum, el_dev->name, el_dev->type, + par->family, proto, direction); - if_tag_stat_update(el_dev->name, uid, - skb->sk ? skb->sk : alternate_sk, - par->in ? IFS_RX : IFS_TX, - proto, skb->len); - } + if_tag_stat_update(el_dev->name, uid, + skb->sk ? skb->sk : alternate_sk, + direction, + proto, skb->len); } static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) @@ -1660,6 +1651,11 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) kuid_t sock_uid; bool res; bool set_sk_callback_lock = false; + /* + * TODO: unhack how to force just accounting. + * For now we only do tag stats when the uid-owner is not requested + */ + bool do_tag_stat = !(info->match & XT_QTAGUID_UID); if (unlikely(module_passive)) return (info->match ^ info->invert) == 0; @@ -1733,12 +1729,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) * couldn't find the owner, so for now we just count them * against the system. */ - /* - * TODO: unhack how to force just accounting. - * For now we only do iface stats when the uid-owner is not - * requested. - */ - if (!(info->match & XT_QTAGUID_UID)) + if (do_tag_stat) account_for_uid(skb, sk, 0, par); MT_DEBUG("qtaguid[%d]: leaving (sk?sk->sk_socket)=%p\n", par->hooknum, @@ -1753,18 +1744,15 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) filp = sk->sk_socket->file; if (filp == NULL) { MT_DEBUG("qtaguid[%d]: leaving filp=NULL\n", par->hooknum); - account_for_uid(skb, sk, 0, par); + if (do_tag_stat) + account_for_uid(skb, sk, 0, par); res = ((info->match ^ info->invert) & (XT_QTAGUID_UID | XT_QTAGUID_GID)) == 0; atomic64_inc(&qtu_events.match_no_sk_file); goto put_sock_ret_res; } sock_uid = filp->f_cred->fsuid; - /* - * TODO: unhack how to force just accounting. - * For now we only do iface stats when the uid-owner is not requested - */ - if (!(info->match & XT_QTAGUID_UID)) + if (do_tag_stat) account_for_uid(skb, sk, from_kuid(&init_user_ns, sock_uid), par); /* diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c index 6c40f229d5d6..9d04b2f8ddd9 100644 --- a/net/rmnet_data/rmnet_data_handlers.c +++ b/net/rmnet_data/rmnet_data_handlers.c @@ -516,10 +516,8 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, rmnet_stats_ul_checksum(ckresult); } - if (((config->egress_data_format & - RMNET_EGRESS_FORMAT_MAP_CKSUMV4) && - (!(config->egress_data_format & - RMNET_EGRESS_FORMAT_AGGREGATION))) || + if ((!(config->egress_data_format & + RMNET_EGRESS_FORMAT_AGGREGATION)) || ((orig_dev->features & NETIF_F_GSO) && skb_is_nonlinear(skb))) map_header = rmnet_map_add_map_header (skb, additional_header_length, RMNET_MAP_NO_PAD_BYTES); diff --git a/net/wireless/reg.c b/net/wireless/reg.c index c3ecf366a27a..4fa9d4aa9456 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1747,22 +1747,14 @@ __reg_process_hint_driver(struct regulatory_request *driver_request) { struct regulatory_request *lr = get_last_request(); - if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { - if (regdom_changes(driver_request->alpha2)) - return REG_REQ_OK; + if (!regdom_changes(driver_request->alpha2)) return REG_REQ_ALREADY_SET; - } - /* - * This would happen if you unplug and plug your card - * back in or if you add a new device for which the previously - * loaded card also agrees on the regulatory domain. - */ - if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && - !regdom_changes(driver_request->alpha2)) - return REG_REQ_ALREADY_SET; + if (lr->initiator == NL80211_REGDOM_SET_BY_USER) + return REG_REQ_INTERSECT; + else + return REG_REQ_OK; - return REG_REQ_INTERSECT; } /** diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 00977873300c..d0e6d351aba8 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -292,12 +292,15 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; skb_dst_force(skb); + dev_hold(skb->dev); nexthdr = x->type->input(x, skb); if (nexthdr == -EINPROGRESS) return 0; resume: + dev_put(skb->dev); + spin_lock(&x->lock); if (nexthdr <= 0) { if (nexthdr == -EBADMSG) { diff --git a/sound/soc/codecs/audio-ext-clk.c b/sound/soc/codecs/audio-ext-clk.c index 511bea3070e3..013021e08001 100644 --- a/sound/soc/codecs/audio-ext-clk.c +++ b/sound/soc/codecs/audio-ext-clk.c @@ -28,6 +28,7 @@ enum clk_mux { AP_CLK2, LPASS_MCLK, + LPASS_MCLK2, }; struct pinctrl_info { @@ -77,6 +78,15 @@ static const struct afe_clk_cfg lpass_default = { 0, }; +static struct afe_clk_set lpass_default2 = { + Q6AFE_LPASS_CLK_CONFIG_API_VERSION, + Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR, + Q6AFE_LPASS_IBIT_CLK_12_P288_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, +}; + static inline struct audio_ext_ap_clk *to_audio_ap_clk(struct clk *clk) { return container_of(clk, struct audio_ext_ap_clk, c); @@ -224,6 +234,58 @@ err: kfree(lpass_clk); } +static int audio_ext_lpass_mclk2_prepare(struct clk *clk) +{ + struct audio_ext_lpass_mclk *audio_lpass_mclk2; + struct pinctrl_info *pnctrl_info; + int ret; + + audio_lpass_mclk2 = container_of(clk, struct audio_ext_lpass_mclk, c); + pnctrl_info = &audio_lpass_mclk2->pnctrl_info; + + if (pnctrl_info->pinctrl) { + ret = pinctrl_select_state(pnctrl_info->pinctrl, + pnctrl_info->active); + if (ret) { + pr_err("%s: active state select failed with %d\n", + __func__, ret); + return -EIO; + } + } + + lpass_default2.enable = 1; + ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &lpass_default2); + if (ret < 0) { + pr_err("%s: failed to set clock, ret = %d\n", __func__, ret); + return -EINVAL; + } + + return 0; +} + +static void audio_ext_lpass_mclk2_unprepare(struct clk *clk) +{ + struct audio_ext_lpass_mclk *audio_lpass_mclk2; + struct pinctrl_info *pnctrl_info; + int ret; + + audio_lpass_mclk2 = container_of(clk, struct audio_ext_lpass_mclk, c); + pnctrl_info = &audio_lpass_mclk2->pnctrl_info; + + if (pnctrl_info->pinctrl) { + ret = pinctrl_select_state(pnctrl_info->pinctrl, + pnctrl_info->sleep); + if (ret) + pr_err("%s: sleep state select failed with %d\n", + __func__, ret); + } + + lpass_default2.enable = 0; + ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &lpass_default2); + if (ret < 0) + pr_err("%s: failed to reset clock, ret = %d\n", __func__, ret); +} + static struct clk_ops audio_ext_ap_clk_ops = { .prepare = audio_ext_clk_prepare, .unprepare = audio_ext_clk_unprepare, @@ -239,6 +301,11 @@ static struct clk_ops audio_ext_lpass_mclk_ops = { .unprepare = audio_ext_lpass_mclk_unprepare, }; +static struct clk_ops audio_ext_lpass_mclk2_ops = { + .prepare = audio_ext_lpass_mclk2_prepare, + .unprepare = audio_ext_lpass_mclk2_unprepare, +}; + static struct audio_ext_pmi_clk audio_pmi_clk = { .gpio = -EINVAL, .c = { @@ -273,11 +340,20 @@ static struct audio_ext_lpass_mclk audio_lpass_mclk = { }, }; +static struct audio_ext_lpass_mclk audio_lpass_mclk2 = { + .c = { + .dbg_name = "audio_ext_lpass_mclk2", + .ops = &audio_ext_lpass_mclk2_ops, + CLK_INIT(audio_lpass_mclk2.c), + }, +}; + static struct clk_lookup audio_ref_clock[] = { CLK_LIST(audio_ap_clk), CLK_LIST(audio_pmi_clk), CLK_LIST(audio_ap_clk2), CLK_LIST(audio_lpass_mclk), + CLK_LIST(audio_lpass_mclk2), }; static int audio_get_pinctrl(struct platform_device *pdev, enum clk_mux mux) @@ -293,6 +369,9 @@ static int audio_get_pinctrl(struct platform_device *pdev, enum clk_mux mux) case LPASS_MCLK: pnctrl_info = &audio_lpass_mclk.pnctrl_info; break; + case LPASS_MCLK2: + pnctrl_info = &audio_lpass_mclk2.pnctrl_info; + break; default: dev_err(&pdev->dev, "%s Not a valid MUX ID: %d\n", __func__, mux); @@ -368,6 +447,11 @@ static int audio_ref_clk_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s: Parsing pinctrl %s failed\n", __func__, "LPASS_MCLK"); + ret = audio_get_pinctrl(pdev, LPASS_MCLK2); + if (ret) + dev_dbg(&pdev->dev, "%s: Parsing pinctrl %s failed\n", + __func__, "LPASS_MCLK2"); + ret = of_msm_clock_register(pdev->dev.of_node, audio_ref_clock, ARRAY_SIZE(audio_ref_clock)); if (ret) @@ -458,6 +542,12 @@ static int audio_ref_clk_remove(struct platform_device *pdev) pnctrl_info->pinctrl = NULL; } + pnctrl_info = &audio_lpass_mclk2.pnctrl_info; + if (pnctrl_info->pinctrl) { + devm_pinctrl_put(pnctrl_info->pinctrl); + pnctrl_info->pinctrl = NULL; + } + return 0; } diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index 4fa9be38d2d3..8d7970b01d7a 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -2183,6 +2183,51 @@ static int msm8x16_wcd_boost_option_set(struct snd_kcontrol *kcontrol, return 0; } +static int msm8x16_wcd_spk_boost_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + if (msm8x16_wcd->spk_boost_set == false) { + ucontrol->value.integer.value[0] = 0; + } else if (msm8x16_wcd->spk_boost_set == true) { + ucontrol->value.integer.value[0] = 1; + } else { + dev_err(codec->dev, "%s: ERROR: Unsupported Speaker Boost = %d\n", + __func__, msm8x16_wcd->spk_boost_set); + return -EINVAL; + } + + dev_dbg(codec->dev, "%s: msm8x16_wcd->spk_boost_set = %d\n", __func__, + msm8x16_wcd->spk_boost_set); + return 0; +} + +static int msm8x16_wcd_spk_boost_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); + + switch (ucontrol->value.integer.value[0]) { + case 0: + msm8x16_wcd->spk_boost_set = false; + break; + case 1: + msm8x16_wcd->spk_boost_set = true; + break; + default: + return -EINVAL; + } + dev_dbg(codec->dev, "%s: msm8x16_wcd->spk_boost_set = %d\n", + __func__, msm8x16_wcd->spk_boost_set); + return 0; +} + static int msm8x16_wcd_ext_spk_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -2546,6 +2591,9 @@ static const struct snd_kcontrol_new msm8x16_wcd_snd_controls[] = { SOC_ENUM_EXT("EAR PA Gain", msm8x16_wcd_ear_pa_gain_enum[0], msm8x16_wcd_pa_gain_get, msm8x16_wcd_pa_gain_put), + SOC_ENUM_EXT("Speaker Boost", msm8x16_wcd_spk_boost_ctl_enum[0], + msm8x16_wcd_spk_boost_get, msm8x16_wcd_spk_boost_set), + SOC_ENUM_EXT("Ext Spk Boost", msm8x16_wcd_ext_spk_boost_ctl_enum[0], msm8x16_wcd_ext_spk_boost_get, msm8x16_wcd_ext_spk_boost_set), diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 08a067de9e91..b0ee24d4089d 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -357,6 +357,12 @@ enum { HPH_PA_DELAY, SB_CLK_GEAR, CLASSH_CONFIG, + ANC_MIC_AMIC1, + ANC_MIC_AMIC2, + ANC_MIC_AMIC3, + ANC_MIC_AMIC4, + ANC_MIC_AMIC5, + ANC_MIC_AMIC6, }; enum { @@ -552,6 +558,7 @@ static struct snd_soc_dai_driver tasha_dai[]; static int wcd9335_get_micb_vout_ctl_val(u32 micb_mv); static int tasha_config_compander(struct snd_soc_codec *, int, int); +static void tasha_codec_set_tx_hold(struct snd_soc_codec *, u16, bool); /* Hold instance to soundwire platform device */ struct tasha_swr_ctrl_data { @@ -3593,7 +3600,7 @@ static int tasha_codec_enable_anc(struct snd_soc_dapm_widget *w, WCD9335_CDC_ANC0_IIR_COEFF_2_CTL); anc_writes_size = anc_cal_size / 2; snd_soc_update_bits(codec, - WCD9335_CDC_ANC0_CLK_RESET_CTL, 0x38, 0x38); + WCD9335_CDC_ANC0_CLK_RESET_CTL, 0x39, 0x39); } else if (!strcmp(w->name, "RX INT2 DAC") || !strcmp(w->name, "RX INT4 DAC")) { tasha_realign_anc_coeff(codec, @@ -3601,7 +3608,7 @@ static int tasha_codec_enable_anc(struct snd_soc_dapm_widget *w, WCD9335_CDC_ANC1_IIR_COEFF_2_CTL); i = anc_cal_size / 2; snd_soc_update_bits(codec, - WCD9335_CDC_ANC1_CLK_RESET_CTL, 0x38, 0x38); + WCD9335_CDC_ANC1_CLK_RESET_CTL, 0x39, 0x39); } for (; i < anc_writes_size; i++) { @@ -3611,16 +3618,23 @@ static int tasha_codec_enable_anc(struct snd_soc_dapm_widget *w, if (!strcmp(w->name, "RX INT1 DAC") || !strcmp(w->name, "RX INT3 DAC")) { snd_soc_update_bits(codec, - WCD9335_CDC_ANC0_CLK_RESET_CTL, 0x38, 0x00); + WCD9335_CDC_ANC0_CLK_RESET_CTL, 0x08, 0x08); } else if (!strcmp(w->name, "RX INT2 DAC") || !strcmp(w->name, "RX INT4 DAC")) { snd_soc_update_bits(codec, - WCD9335_CDC_ANC1_CLK_RESET_CTL, 0x38, 0x00); + WCD9335_CDC_ANC1_CLK_RESET_CTL, 0x08, 0x08); } if (!hwdep_cal) release_firmware(fw); break; + case SND_SOC_DAPM_POST_PMU: + /* Remove ANC Rx from reset */ + snd_soc_update_bits(codec, WCD9335_CDC_ANC0_CLK_RESET_CTL, + 0x08, 0x00); + snd_soc_update_bits(codec, WCD9335_CDC_ANC1_CLK_RESET_CTL, + 0x08, 0x00); + break; case SND_SOC_DAPM_POST_PMD: if (!strcmp(w->name, "ANC HPHL PA") || !strcmp(w->name, "ANC EAR PA") || @@ -3660,6 +3674,22 @@ err: return ret; } +static void tasha_codec_clear_anc_tx_hold(struct tasha_priv *tasha) +{ + if (test_and_clear_bit(ANC_MIC_AMIC1, &tasha->status_mask)) + tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC1, false); + if (test_and_clear_bit(ANC_MIC_AMIC2, &tasha->status_mask)) + tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC2, false); + if (test_and_clear_bit(ANC_MIC_AMIC3, &tasha->status_mask)) + tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC3, false); + if (test_and_clear_bit(ANC_MIC_AMIC4, &tasha->status_mask)) + tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC4, false); + if (test_and_clear_bit(ANC_MIC_AMIC5, &tasha->status_mask)) + tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC5, false); + if (test_and_clear_bit(ANC_MIC_AMIC6, &tasha->status_mask)) + tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC6, false); +} + static void tasha_codec_hph_post_pa_config(struct tasha_priv *tasha, int mode, int event) { @@ -3678,6 +3708,13 @@ static void tasha_codec_hph_post_pa_config(struct tasha_priv *tasha, scale_val = 0x1; break; } + if (tasha->anc_func) { + /* Clear Tx FE HOLD if both PAs are enabled */ + if ((snd_soc_read(tasha->codec, WCD9335_ANA_HPH) & + 0xC0) == 0xC0) { + tasha_codec_clear_anc_tx_hold(tasha); + } + } break; case SND_SOC_DAPM_PRE_PMD: scale_val = 0x6; @@ -3744,9 +3781,19 @@ static int tasha_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + if ((!(strcmp(w->name, "ANC HPHR PA"))) && + (test_bit(HPH_PA_DELAY, &tasha->status_mask))) { + snd_soc_update_bits(codec, WCD9335_ANA_HPH, 0xC0, 0xC0); + } set_bit(HPH_PA_DELAY, &tasha->status_mask); break; case SND_SOC_DAPM_POST_PMU: + if ((snd_soc_read(codec, WCD9335_ANA_HPH) & 0xC0) != 0xC0) + /* If PA_EN is not set (potentially in ANC case) then + * do nothing for POST_PMU and let left channel handle + * everything. + */ + break; /* * 7ms sleep is required after PA is enabled as per * HW requirement @@ -3764,13 +3811,31 @@ static int tasha_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WCD9335_CDC_RX2_RX_PATH_MIX_CTL, 0x10, 0x00); + + if (!(strcmp(w->name, "ANC HPHR PA"))) { + /* Do everything needed for left channel */ + snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CTL, + 0x10, 0x00); + /* Remove mix path mute if it is enabled */ + if ((snd_soc_read(codec, + WCD9335_CDC_RX1_RX_PATH_MIX_CTL)) & + 0x10) + snd_soc_update_bits(codec, + WCD9335_CDC_RX1_RX_PATH_MIX_CTL, + 0x10, 0x00); + /* Remove ANC Rx from reset */ + ret = tasha_codec_enable_anc(w, kcontrol, event); + } tasha_codec_override(codec, hph_mode, event); break; + case SND_SOC_DAPM_PRE_PMD: blocking_notifier_call_chain(&tasha->notifier, WCD_EVENT_PRE_HPHR_PA_OFF, &tasha->mbhc); tasha_codec_hph_post_pa_config(tasha, hph_mode, event); + if (!(strcmp(w->name, "ANC HPHR PA"))) + snd_soc_update_bits(codec, WCD9335_ANA_HPH, 0x40, 0x00); break; case SND_SOC_DAPM_POST_PMD: /* 5ms sleep is required after PA is disabled as per @@ -3806,9 +3871,19 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + if ((!(strcmp(w->name, "ANC HPHL PA"))) && + (test_bit(HPH_PA_DELAY, &tasha->status_mask))) { + snd_soc_update_bits(codec, WCD9335_ANA_HPH, 0xC0, 0xC0); + } set_bit(HPH_PA_DELAY, &tasha->status_mask); break; case SND_SOC_DAPM_POST_PMU: + if ((snd_soc_read(codec, WCD9335_ANA_HPH) & 0xC0) != 0xC0) + /* If PA_EN is not set (potentially in ANC case) then + * do nothing for POST_PMU and let right channel handle + * everything. + */ + break; /* * 7ms sleep is required after PA is enabled as per * HW requirement @@ -3827,6 +3902,22 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_MIX_CTL, 0x10, 0x00); + + if (!(strcmp(w->name, "ANC HPHL PA"))) { + /* Do everything needed for right channel */ + snd_soc_update_bits(codec, WCD9335_CDC_RX2_RX_PATH_CTL, + 0x10, 0x00); + /* Remove mix path mute if it is enabled */ + if ((snd_soc_read(codec, + WCD9335_CDC_RX2_RX_PATH_MIX_CTL)) & + 0x10) + snd_soc_update_bits(codec, + WCD9335_CDC_RX2_RX_PATH_MIX_CTL, + 0x10, 0x00); + + /* Remove ANC Rx from reset */ + ret = tasha_codec_enable_anc(w, kcontrol, event); + } tasha_codec_override(codec, hph_mode, event); break; case SND_SOC_DAPM_PRE_PMD: @@ -3834,6 +3925,8 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, WCD_EVENT_PRE_HPHL_PA_OFF, &tasha->mbhc); tasha_codec_hph_post_pa_config(tasha, hph_mode, event); + if (!(strcmp(w->name, "ANC HPHL PA"))) + snd_soc_update_bits(codec, WCD9335_ANA_HPH, 0x80, 0x00); break; case SND_SOC_DAPM_POST_PMD: /* 5ms sleep is required after PA is disabled as per @@ -3901,6 +3994,9 @@ static int tasha_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, lineout_mix_vol_reg, 0x10, 0x00); + if (!(strcmp(w->name, "ANC LINEOUT1 PA")) || + !(strcmp(w->name, "ANC LINEOUT2 PA"))) + ret = tasha_codec_enable_anc(w, kcontrol, event); tasha_codec_override(codec, CLS_AB, event); break; case SND_SOC_DAPM_POST_PMD: @@ -5233,8 +5329,8 @@ static int tasha_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w, { int adc_mux_n = w->shift; struct snd_soc_codec *codec = w->codec; + struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec); int amic_n; - u16 amic_reg; dev_dbg(codec->dev, "%s: event: %d\n", __func__, event); @@ -5242,8 +5338,13 @@ static int tasha_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: amic_n = tasha_codec_find_amic_input(codec, adc_mux_n); if (amic_n) { - amic_reg = WCD9335_ANA_AMIC1 + amic_n - 1; - tasha_codec_set_tx_hold(codec, amic_reg, false); + /* + * Prevent ANC Rx pop by leaving Tx FE in HOLD + * state until PA is up. Track AMIC being used + * so we can release the HOLD later. + */ + set_bit(ANC_MIC_AMIC1 + amic_n - 1, + &tasha->status_mask); } break; default: @@ -10357,11 +10458,11 @@ static const struct snd_soc_dapm_widget tasha_dapm_widgets[] = { tasha_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_PGA_E("ANC HPHL PA", WCD9335_ANA_HPH, 7, 0, NULL, 0, + SND_SOC_DAPM_PGA_E("ANC HPHL PA", SND_SOC_NOPM, 0, 0, NULL, 0, tasha_codec_enable_hphl_pa, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_PGA_E("ANC HPHR PA", WCD9335_ANA_HPH, 6, 0, NULL, 0, + SND_SOC_DAPM_PGA_E("ANC HPHR PA", SND_SOC_NOPM, 0, 0, NULL, 0, tasha_codec_enable_hphr_pa, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), diff --git a/sound/soc/codecs/wsa881x-analog.c b/sound/soc/codecs/wsa881x-analog.c index 04bccb4a8ad2..2bb6cf805926 100644 --- a/sound/soc/codecs/wsa881x-analog.c +++ b/sound/soc/codecs/wsa881x-analog.c @@ -903,7 +903,8 @@ static int wsa881x_startup(struct wsa881x_pdata *pdata) if (pdata->enable_mclk) { ret = pdata->enable_mclk(card, true); if (ret < 0) { - pr_err("%s: mclk enable failed %d\n", + dev_err_ratelimited(codec->dev, + "%s: mclk enable failed %d\n", __func__, ret); return ret; } @@ -966,7 +967,8 @@ static int32_t wsa881x_resource_acquire(struct snd_soc_codec *codec, if (enable) { ret = wsa881x_startup(wsa881x); if (ret < 0) { - pr_err("%s: failed to startup\n", __func__); + dev_err_ratelimited(codec->dev, + "%s: failed to startup\n", __func__); return ret; } } @@ -975,7 +977,8 @@ static int32_t wsa881x_resource_acquire(struct snd_soc_codec *codec, if (!enable) { ret = wsa881x_shutdown(wsa881x); if (ret < 0) - pr_err("%s: failed to shutdown\n", __func__); + dev_err_ratelimited(codec->dev, + "%s: failed to shutdown\n", __func__); } return ret; } @@ -984,12 +987,18 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec, struct wsa_temp_register *wsa_temp_reg) { struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec); + int ret = 0; if (!wsa881x) { dev_err(codec->dev, "%s: wsa881x is NULL\n", __func__); return -EINVAL; } - wsa881x_resource_acquire(codec, true); + ret = wsa881x_resource_acquire(codec, true); + if (ret) { + dev_err_ratelimited(codec->dev, + "%s: resource acquire fail\n", __func__); + return ret; + } if (WSA881X_IS_2_0(wsa881x->version)) { snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00); @@ -1007,9 +1016,12 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec, wsa_temp_reg->d2_msb = snd_soc_read(codec, WSA881X_OTP_REG_3); wsa_temp_reg->d2_lsb = snd_soc_read(codec, WSA881X_OTP_REG_4); - wsa881x_resource_acquire(codec, false); + ret = wsa881x_resource_acquire(codec, false); + if (ret) + dev_err_ratelimited(codec->dev, + "%s: resource release fail\n", __func__); - return 0; + return ret; } static int wsa881x_probe(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index 4322711376a6..c54957e88b04 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.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 @@ -740,6 +740,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w, wsa881x_boost_ctrl(codec, ENABLE); break; case SND_SOC_DAPM_POST_PMD: + swr_slvdev_datapath_control(wsa881x->swr_slave, + wsa881x->swr_slave->dev_num, + false); if (wsa881x->boost_enable) wsa881x_boost_ctrl(codec, DISABLE); wsa881x_resource_acquire(codec, DISABLE); @@ -805,6 +808,9 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w, regmap_multi_reg_write(wsa881x->regmap, wsa881x_pre_pmu_pa, ARRAY_SIZE(wsa881x_pre_pmu_pa)); + swr_slvdev_datapath_control(wsa881x->swr_slave, + wsa881x->swr_slave->dev_num, + true); break; case SND_SOC_DAPM_POST_PMU: if (WSA881X_IS_2_0(wsa881x->version)) { diff --git a/sound/soc/msm/msm8952-dai-links.c b/sound/soc/msm/msm8952-dai-links.c index 2b341beadd06..25ad870ad1ef 100644 --- a/sound/soc/msm/msm8952-dai-links.c +++ b/sound/soc/msm/msm8952-dai-links.c @@ -1512,7 +1512,7 @@ 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 *msm8952_dai_links = NULL; - int num_links, ret, len1, len2, len3, len4; + int num_links, ret, len1, len2, len3, len4 = 0; enum codec_variant codec_ver = 0; const char *tasha_lite[NUM_OF_TASHA_LITE_DEVICE] = { "msm8952-tashalite-snd-card", diff --git a/sound/soc/msm/msm8996.c b/sound/soc/msm/msm8996.c index f06d5d365283..13cfd93bbbef 100644 --- a/sound/soc/msm/msm8996.c +++ b/sound/soc/msm/msm8996.c @@ -2897,7 +2897,14 @@ static int msm8996_wcd93xx_codec_up(struct snd_soc_codec *codec) do { if (!q6core_is_adsp_ready()) { - pr_err("%s: ADSP Audio isn't ready\n", __func__); + pr_err_ratelimited("%s: ADSP Audio isn't ready\n", + __func__); + /* + * 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); } else { pr_debug("%s: ADSP Audio is ready\n", __func__); adsp_ready = 1; diff --git a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c index e6667cc12439..be30f8f172d6 100644 --- a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +++ b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-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. @@ -1370,7 +1370,11 @@ static int msm_ds2_dap_handle_commands(u32 cmd, void *arg) int ret = 0, port_id = 0; int32_t data; struct dolby_param_data *dolby_data = (struct dolby_param_data *)arg; - get_user(data, &dolby_data->data[0]); + if (get_user(data, &dolby_data->data[0])) { + pr_debug("%s error getting data\n", __func__); + ret = -EFAULT; + goto end; + } pr_debug("%s: param_id %d,be_id %d,device_id 0x%x,length %d,data %d\n", __func__, dolby_data->param_id, dolby_data->be_id, @@ -1489,11 +1493,23 @@ static int msm_ds2_dap_set_param(u32 cmd, void *arg) goto end; } + off = ds2_dap_params_offset[idx]; + if ((dolby_data->length <= 0) || + (dolby_data->length > TOTAL_LENGTH_DS2_PARAM - off)) { + pr_err("%s: invalid length %d at idx %d\n", + __func__, dolby_data->length, idx); + rc = -EINVAL; + goto end; + } + /* cache the parameters */ ds2_dap_params[cdev].dap_params_modified[idx] += 1; for (j = 0; j < dolby_data->length; j++) { - off = ds2_dap_params_offset[idx]; - get_user(data, &dolby_data->data[j]); + if (get_user(data, &dolby_data->data[j])) { + pr_debug("%s:error getting data\n", __func__); + rc = -EFAULT; + goto end; + } ds2_dap_params[cdev].params_val[off + j] = data; pr_debug("%s:off %d,val[i/p:o/p]-[%d / %d]\n", __func__, off, data, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 62a315f50a7b..1425e6633ed4 100755 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -86,9 +86,9 @@ static int quat_mi2s_switch_enable; static int fm_pcmrx_switch_enable; static int lsm_mux_slim_port; static int slim0_rx_aanc_fb_port; -static int msm_route_ec_ref_rx = 9; /* NONE */ +static int msm_route_ec_ref_rx; static uint32_t voc_session_id = ALL_SESSION_VSID; -static int msm_route_ext_ec_ref = AFE_PORT_INVALID; +static int msm_route_ext_ec_ref; static bool is_custom_stereo_on; static bool is_ds2_on; @@ -2338,41 +2338,44 @@ static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = wlist->widgets[0]; int mux = ucontrol->value.enumerated.item[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - int ret = 0; - bool state = false; + int ret = 1; + bool state = true; + uint16_t ext_ec_ref_port_id; struct snd_soc_dapm_update *update = NULL; - pr_debug("%s: msm_route_ec_ref_rx = %d value = %ld\n", - __func__, msm_route_ext_ec_ref, - ucontrol->value.integer.value[0]); - mutex_lock(&routing_lock); - switch (ucontrol->value.integer.value[0]) { - case EC_PORT_ID_PRIMARY_MI2S_TX: - msm_route_ext_ec_ref = AFE_PORT_ID_PRIMARY_MI2S_TX; - state = true; + msm_route_ext_ec_ref = ucontrol->value.integer.value[0]; + + switch (msm_route_ext_ec_ref) { + case EXT_EC_REF_PRI_MI2S_TX: + ext_ec_ref_port_id = AFE_PORT_ID_PRIMARY_MI2S_TX; break; - case EC_PORT_ID_SECONDARY_MI2S_TX: - msm_route_ext_ec_ref = AFE_PORT_ID_SECONDARY_MI2S_TX; - state = true; + case EXT_EC_REF_SEC_MI2S_TX: + ext_ec_ref_port_id = AFE_PORT_ID_SECONDARY_MI2S_TX; break; - case EC_PORT_ID_TERTIARY_MI2S_TX: - msm_route_ext_ec_ref = AFE_PORT_ID_TERTIARY_MI2S_TX; - state = true; + case EXT_EC_REF_TERT_MI2S_TX: + ext_ec_ref_port_id = AFE_PORT_ID_TERTIARY_MI2S_TX; break; - case EC_PORT_ID_QUATERNARY_MI2S_TX: - msm_route_ext_ec_ref = AFE_PORT_ID_QUATERNARY_MI2S_TX; - state = true; + case EXT_EC_REF_QUAT_MI2S_TX: + ext_ec_ref_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; break; - case EC_PORT_ID_SLIMBUS_1_TX: - msm_route_ext_ec_ref = SLIMBUS_1_TX; - state = true; + case EXT_EC_REF_QUIN_MI2S_TX: + ext_ec_ref_port_id = AFE_PORT_ID_QUINARY_MI2S_TX; break; + case EXT_EC_REF_SLIM_1_TX: + ext_ec_ref_port_id = SLIMBUS_1_TX; + break; + case EXT_EC_REF_NONE: default: - msm_route_ext_ec_ref = AFE_PORT_INVALID; + ext_ec_ref_port_id = AFE_PORT_INVALID; + state = false; break; } - if (!voc_set_ext_ec_ref(msm_route_ext_ec_ref, state)) { + + pr_debug("%s: val = %d ext_ec_ref_port_id = 0x%0x state = %d\n", + __func__, msm_route_ext_ec_ref, ext_ec_ref_port_id, state); + + if (!voc_set_ext_ec_ref(ext_ec_ref_port_id, state)) { mutex_unlock(&routing_lock); snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update); } else { @@ -2383,11 +2386,12 @@ static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol, } static const char * const ext_ec_ref_rx[] = {"NONE", "PRI_MI2S_TX", - "SEC_MI2S_TX", "TERT_MI2S_TX", - "QUAT_MI2S_TX", "SLIM_1_TX"}; + "SEC_MI2S_TX", "TERT_MI2S_TX", + "QUAT_MI2S_TX", "QUIN_MI2S_TX", + "SLIM_1_TX"}; static const struct soc_enum msm_route_ext_ec_ref_rx_enum[] = { - SOC_ENUM_SINGLE_EXT(6, ext_ec_ref_rx), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ext_ec_ref_rx), ext_ec_ref_rx), }; static const struct snd_kcontrol_new voc_ext_ec_mux = @@ -8665,7 +8669,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_3_RX", NULL, "SLIMBUS3_DL_HL"}, {"SLIMBUS4_DL_HL", "Switch", "SLIM4_DL_HL"}, {"SLIMBUS_4_RX", NULL, "SLIMBUS4_DL_HL"}, - {"SLIMBUS6_DL_HL", "Switch", "SLIM6_DL_HL"}, + {"SLIMBUS6_DL_HL", "Switch", "SLIM0_DL_HL"}, {"SLIMBUS_6_RX", NULL, "SLIMBUS6_DL_HL"}, {"SLIM0_UL_HL", NULL, "SLIMBUS_0_TX"}, {"SLIM1_UL_HL", NULL, "SLIMBUS_1_TX"}, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index e191aba79138..f1ec04dafeb5 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -306,6 +306,16 @@ enum msm_pcm_routing_event { MSM_PCM_RT_EVT_MAX, }; +enum { + EXT_EC_REF_NONE = 0, + EXT_EC_REF_PRI_MI2S_TX, + EXT_EC_REF_SEC_MI2S_TX, + EXT_EC_REF_TERT_MI2S_TX, + EXT_EC_REF_QUAT_MI2S_TX, + EXT_EC_REF_QUIN_MI2S_TX, + EXT_EC_REF_SLIM_1_TX, +}; + #define INVALID_SESSION -1 #define SESSION_TYPE_RX 0 #define SESSION_TYPE_TX 1 diff --git a/sound/usb/card.c b/sound/usb/card.c index 9ca09d2b6c71..339ce6bc8e75 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -675,7 +675,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) int err = -ENODEV; down_read(&chip->shutdown_rwsem); - if (chip->probing && chip->in_pm) + if (chip->probing || chip->in_pm) err = 0; else if (!chip->shutdown) err = usb_autopm_get_interface(chip->pm_intf); |