Merge "Merge 79477f89b2
on remote branch."
This commit is contained in:
commit
ebf8b93373
|
@ -18,6 +18,7 @@ Required properties:
|
|||
"qcom,gcc-8994"
|
||||
"qcom,gcc-8994v2"
|
||||
"qcom,gcc-8952"
|
||||
"qcom,gcc-spm-8952"
|
||||
"qcom,gcc-8976"
|
||||
"qcom,gcc-fsm9010"
|
||||
"qcom,rpmcc-8994"
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
Voltage Sensors
|
||||
|
||||
Voltage Sensors are hardware blocks that sense the voltage at
|
||||
a particular point in hardware. The device is capable of issuing
|
||||
interrupts when a programmed min or max threshold is crossed.
|
||||
|
||||
Required Properties
|
||||
- compatible:
|
||||
Must be 'qcom,msm-vsens'
|
||||
|
||||
- reg:
|
||||
specifies the address and size of the Voltage Sensor block
|
||||
|
||||
- reg-names:
|
||||
"base" to identify the physical address base of the
|
||||
Voltage Sensor block.
|
||||
|
||||
- label:
|
||||
String indicating this vsens instance.
|
||||
|
||||
- qcom,vsens-cpus:
|
||||
Array of CPU phandles which correspond to the cores which are
|
||||
supplied power by the rail monitored by this vsens device.
|
||||
|
||||
- qcom,vsens-cal-id:
|
||||
The VSENS rail id to index into the SMEM data which points to
|
||||
the calibarated voltage and vsens-codes. This value is determined
|
||||
based on the number of voltage-sensors supported on a target.
|
||||
|
||||
Optional Properties
|
||||
- interrupts:
|
||||
IRQ lines used by Voltage Sensors
|
||||
|
||||
- interrupt-names:
|
||||
Descriptive names for IRQs used by Voltage Sensors.
|
||||
"max": maximum threshold crossed IRQ
|
||||
"min": minium threshold crossed IRQ
|
||||
|
||||
- qcom,temperature-pct:
|
||||
The percentage shift in voltage values over operational
|
||||
temperature range. This value is used to lower the floor
|
||||
and raise a ceiling voltage to account for temperature
|
||||
shifts. If not specified a default value of 15% is used.
|
||||
|
||||
- qcom,min-operational-floor-uv:
|
||||
The min floor voltage below which the voltage sensor
|
||||
is not operational and must be disabled. If this
|
||||
is not specified the voltage sensor is assumed to be
|
||||
operational for all voltage ranges.
|
||||
|
||||
- clocks:
|
||||
Array of clock tuples in which each tuple consists of a
|
||||
phandle to a clock device and a clock ID number.
|
||||
|
||||
- clock-names:
|
||||
The name of the voltage-sensor clock. The supported
|
||||
clock-name is 'vsens-clk'.
|
||||
|
||||
- qcom,corner-clock-rate:
|
||||
The clock rate (HZ) of the voltage sensor clock
|
||||
for each corner. The number of entries should match
|
||||
the 'qcom,num-corners'.
|
||||
|
||||
- qcom,calib-clock-rate:
|
||||
The clock rate (HZ) at which the VSENS calibration
|
||||
is done.
|
||||
|
||||
- qcom,num-corners:
|
||||
The number of corners supported by the voltage sensor.
|
||||
Its determined by the number of operating frequencies of
|
||||
the vsens-clk.
|
||||
|
||||
Sub Node required regulators
|
||||
- qcom,vsens-voltage:
|
||||
A node to indicate the voltage range monitored by the sensor.
|
||||
|
||||
- qcom,vsens-corner:
|
||||
A node to indicate the current corner of the voltage sensor.
|
||||
|
||||
Sub-nodes required properties for 'qcom,vsens-voltage' regulator
|
||||
|
||||
- regulator-name: A string used to describe the regulator
|
||||
- regulator-min-microvolt: Minimum voltage level expected to be
|
||||
monitored by the voltage sensor for
|
||||
a rail.
|
||||
- regulator-max-microvolt: Maximum voltage level expected to be
|
||||
monitored by the voltage sensor for
|
||||
a rail.
|
||||
|
||||
Sub-nodes required properties for 'qcom,vsens-corner' regulator
|
||||
|
||||
- regulator-name: A string used to describe the regulator
|
||||
- regulator-min-microvolt: The lowest corner supported by the voltage
|
||||
sensor. Its value is 1.
|
||||
- regulator-max-microvolt: The max corner supported by the voltage sensor.
|
||||
Its value is equal to 'qcom,num-corners'.
|
||||
|
||||
Any property defined as part of the core regulator binding, defined in
|
||||
regulator.txt, can also be used.
|
||||
|
||||
Example:
|
||||
vsens_apc0: vsens@b1d6000 {
|
||||
compatible = "qcom,msm-vsens";
|
||||
reg = <0xb1d6000 0xc>;
|
||||
reg-names = "base";
|
||||
interrupts = <0 265 0>,
|
||||
<0 266 0>;
|
||||
interrupt-names = "max",
|
||||
"min";
|
||||
label = "vsens-acpu0";
|
||||
|
||||
qcom,vsens-cal-id = <3>;
|
||||
qcom,vsens-cpus = <&CPU0 &CPU1 &CPU2 &CPU3>;
|
||||
|
||||
clock-names = "vsens_clk";
|
||||
clocks = <&clock_gcc clk_gcc_aps_0_clk>;
|
||||
|
||||
qcom,num-corners = <2>;
|
||||
qcom,corner-clock-rate =
|
||||
<300000000 540000000>;
|
||||
qcom,calib-clock-rate = <540000000>;
|
||||
qcom,min-operational-floor-uv = <500000>;
|
||||
qcom,temperature-pct = <20>;
|
||||
|
||||
vsens_apc0_voltage:qcom,vsens-voltage {
|
||||
regulator-name = "msm-vsens-apc0-voltage";
|
||||
regulator-min-microvolt = <700000>;
|
||||
regulator-max-microvolt = <1165000>;
|
||||
};
|
||||
|
||||
vsens_apc0_corner:qcom,vsens-corner {
|
||||
regulator-name = "msm-vsens-apc0-corner";
|
||||
regulator-min-microvolt = <1>;
|
||||
regulator-max-microvolt = <2>;
|
||||
};
|
||||
};
|
|
@ -14,6 +14,7 @@ Required properties:
|
|||
|
||||
Optional properties:
|
||||
- qcom,secure_io Indicates register access are secured.
|
||||
- qcom,shared-irq Indicates ccci-hwmon counters share the interrupt.
|
||||
|
||||
Example:
|
||||
qcom,msmcci-hwmon {
|
||||
|
|
|
@ -106,6 +106,14 @@ Required properties
|
|||
to the respective cursor pipes. Number of xin ids
|
||||
defined should match the number of offsets
|
||||
defined in property: qcom,mdss-pipe-cursor-off
|
||||
- qcom,mdss-pipe-cursor-clk-ctrl-off: Array of offsets describing clk control
|
||||
offsets for dynamic clock gating. 1st value
|
||||
in the array represents offset of the control
|
||||
register. 2nd value represents bit offset within
|
||||
control register and 3rd value represents bit
|
||||
offset within status register. Number of tuples
|
||||
defined should match the number of offsets
|
||||
defined in property: qcom,mdss-pipe-cursor-off
|
||||
- qcom,mdss-ctl-off: Array of offset addresses for the available ctl
|
||||
hw blocks within MDP, these offsets are
|
||||
calculated from register "mdp_phys" defined in
|
||||
|
|
|
@ -6,22 +6,27 @@ Required properties :
|
|||
- interrupt-parent: Should be phandle for the interrupt controller
|
||||
that services interrupts for this device.
|
||||
- interrupt: IRQ line
|
||||
- <supply-name>-supply: handle to the regulator device tree node.
|
||||
"supply-name" is "vdd_io" regulator to drive I2C SCL and SDA lines.
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-names : This should be defined if a target uses pinctrl framework
|
||||
for INT_N pin. See "pinctrl" in
|
||||
for INT_N and ENB pin. See "pinctrl" in
|
||||
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
|
||||
It should specify the names of the configs that pinctrl can install in driver.
|
||||
Following are the pinctrl config that can be installed:
|
||||
"usbc_int_default" : Default configuration of INT_N pin.
|
||||
|
||||
"usbc_int_default" : Default configuration of pins.
|
||||
- pericom,enb-gpio : This corresponds to GPIO that is used to drive ENB pin.
|
||||
GPIO flag represents whether ENB pin is active-high(0) or active-low(1).
|
||||
|
||||
Example :
|
||||
pericom-type-c@3d {
|
||||
compatible = "pericom,usb-type-c";
|
||||
reg = <0x3d>;
|
||||
interrupt-parent = <&msm_gpio>;
|
||||
interrupts = <102 0>; /* MSM GPIO 102 */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usbc_int_default>;
|
||||
};
|
||||
pericom-type-c@3d {
|
||||
compatible = "pericom,usb-type-c";
|
||||
reg = <0x3d>;
|
||||
vdd_io-supply = <&pm8950_l5>;
|
||||
interrupt-parent = <&msm_gpio>;
|
||||
interrupts = <102 2>; /* MSM GPIO 102, TRIGGER_FALLING */
|
||||
pericom,enb-gpio = <&msm_gpio 101 0x1>; /* active low ENB */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usbc_int_default>;
|
||||
};
|
||||
|
|
|
@ -263,7 +263,6 @@ Optional Properties:
|
|||
- qcom,chg-led-support A bool property to support the charger led feature.
|
||||
- qcom,chg-led-sw-controls A bool property to allow the software to control
|
||||
the charger led without a valid charger.
|
||||
- qcom,enable-hvdcp-9v A bool property to enable 9V HVDCP 2.0 detection.
|
||||
|
||||
Example:
|
||||
qcom,qpnp-smbcharger {
|
||||
|
|
|
@ -649,6 +649,12 @@ Optional properties:
|
|||
the RPM corner to the corresponding APC virtual
|
||||
corner. This property must be defined if
|
||||
'rpm-apc-supply' is present.
|
||||
- qcom,vsens-corner-map: Array of integers which define the mapping of the VSENS corner to the
|
||||
corresponding APC fuse corner. The qcom,vsens-corner-map and
|
||||
vdd-vsense-corner-supply properties must both be specified for a given
|
||||
cpr-regulator device or neither must be specified.
|
||||
- vdd-vsens-corner-supply: Regulator to specify the current operating fuse corner to the Voltage Sensor.
|
||||
- vdd-vsens-voltage-supply: Regulator to specify the corner floor/ceiling voltages to the Voltage Sensor.
|
||||
|
||||
Example:
|
||||
apc_vreg_corner: regulator@f9018000 {
|
||||
|
@ -722,6 +728,10 @@ Example:
|
|||
qcom,cpr-clamp-timer-interval = <1>;
|
||||
qcom,cpr-apc-volt-step = <5000>;
|
||||
|
||||
qcom,vsens-corner-map = <1 2 2>;
|
||||
vdd-vsens-corner-supply = <&vsens_apc0_corner>;
|
||||
vdd-vsens-voltage-supply = <&vsens_apc0_voltage>;
|
||||
|
||||
rpm-apc-supply = <&rpm_apc_vreg>;
|
||||
qcom,rpm-apc-corner-map = <4 4 5 5 7 7 7 7 7 7 7 7>;
|
||||
|
||||
|
|
|
@ -563,15 +563,15 @@
|
|||
"cpu0_clk", "cpu1_clk", "cpu2_clk",
|
||||
"cpu3_clk", "cpu4_clk", "cpu5_clk",
|
||||
"cpu6_clk", "cpu7_clk", "l2_clk";
|
||||
clocks = <&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_cci>;
|
||||
clocks = <&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_cci_clk>;
|
||||
|
||||
qcom,tz-flushes-cache;
|
||||
};
|
||||
|
|
|
@ -219,7 +219,7 @@
|
|||
cci_cache: qcom,cci {
|
||||
compatible = "devfreq-simple-dev";
|
||||
clock-names = "devfreq_clk";
|
||||
clocks = <&clock_cpu clk_a53ssmux_cci>;
|
||||
clocks = <&clock_cpu clk_cci_clk>;
|
||||
governor = "cpufreq";
|
||||
freq-tbl-khz =
|
||||
< 200000 >,
|
||||
|
@ -330,15 +330,15 @@
|
|||
clock-names = "l2_clk", "cpu0_clk", "cpu1_clk", "cpu2_clk",
|
||||
"cpu3_clk", "cpu4_clk", "cpu5_clk",
|
||||
"cpu6_clk", "cpu7_clk";
|
||||
clocks = <&clock_cpu clk_a53ssmux_cci>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>;
|
||||
clocks = <&clock_cpu clk_cci_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>;
|
||||
|
||||
qcom,governor-per-policy;
|
||||
|
||||
|
|
|
@ -38,16 +38,16 @@
|
|||
eeprom0: qcom,eeprom@0{
|
||||
cell-index = <0>;
|
||||
reg = <0x00>;
|
||||
qcom,eeprom-name = "sunny_q13v04b";
|
||||
qcom,eeprom-name = "sunny_q13v06k";
|
||||
compatible = "qcom,eeprom";
|
||||
qcom,slave-addr = <0x20>;
|
||||
qcom,cci-master = <0>;
|
||||
qcom,num-blocks = <7>;
|
||||
qcom,num-blocks = <8>;
|
||||
|
||||
qcom,page0 = <1 0x0100 2 0x01 1 1>;
|
||||
qcom,poll0 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem0 = <0 0x0 2 0 1 0>;
|
||||
qcom,page1 = <1 0x5002 2 0x3 1 1>;
|
||||
qcom,page1 = <1 0x5002 2 0x5 1 1>;
|
||||
qcom,poll1 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem1 = <0 0x0 2 0 1 0>;
|
||||
qcom,page2 = <1 0x3d84 2 0xc0 1 0>;
|
||||
|
@ -56,15 +56,19 @@
|
|||
qcom,page3 = <1 0x3d88 2 0x7220 2 0>;
|
||||
qcom,poll3 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem3 = <0 0x0 2 0 1 0>;
|
||||
qcom,page4 = <1 0x3d8a 2 0x7369 2 0>;
|
||||
qcom,page4 = <1 0x3d8a 2 0x73BA 2 0>;
|
||||
qcom,poll4 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem4 = <0 0x0 2 0 1 0>;
|
||||
qcom,page5 = <1 0x3d81 2 0x01 1 15>;
|
||||
qcom,poll5 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem5 = <229 0x7220 2 0 1 0>;
|
||||
qcom,page6 = <1 0x5002 2 0x1 1 1>;
|
||||
qcom,mem5 = <411 0x7220 2 0 1 0>;
|
||||
qcom,page6 = <1 0x5002 2 0x7 1 1>;
|
||||
qcom,poll6 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem6 = <0 0x0 2 0 1 0>;
|
||||
qcom,page7 = <0 0 0 0 0 0>;
|
||||
qcom,poll7 = <0 0 0 0 0 0>;
|
||||
qcom,saddr7 = <0xa0>;
|
||||
qcom,mem7 = <470 0x16ba 2 0 1 0>;
|
||||
|
||||
cam_vdig-supply = <&pm8950_l23>;
|
||||
cam_vana-supply = <&pm8950_l22>;
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
qcom,mdss-pipe-rgb-clk-ctrl-offsets = <0x2ac 4 8>,
|
||||
<0x2b4 4 8>;
|
||||
qcom,mdss-pipe-dma-clk-ctrl-offsets = <0x2ac 8 12>;
|
||||
qcom,mdss-pipe-cursor-clk-ctrl-offsets = <0x3a8 16 15>;
|
||||
|
||||
qcom,mdss-smp-data = <8 8192>;
|
||||
|
||||
|
|
|
@ -147,6 +147,8 @@
|
|||
};
|
||||
|
||||
clock_gcc: qcom,gcc@1800000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "qcom,gcc-8952";
|
||||
reg = <0x1800000 0x80000>,
|
||||
<0xb116000 0x00040>,
|
||||
|
@ -160,6 +162,15 @@
|
|||
vdd_hf_dig-supply = <&pm8950_s2_level_ao>;
|
||||
vdd_hf_pll-supply = <&pm8950_l7_ao>;
|
||||
#clock-cells = <1>;
|
||||
ranges;
|
||||
qcom,spm@0 {
|
||||
compatible = "qcom,gcc-spm-8952";
|
||||
reg = <0x0b111200 0x100>,
|
||||
<0x0b011200 0x100>,
|
||||
<0x0b1d4000 0x100>;
|
||||
reg-names = "spm_c0_base", "spm_c1_base",
|
||||
"spm_cci_base";
|
||||
};
|
||||
};
|
||||
|
||||
clock_gcc_mdss: qcom,gcc-mdss@1ac8300 {
|
||||
|
@ -283,6 +294,12 @@
|
|||
clock-frequency = <32768>;
|
||||
};
|
||||
|
||||
qcom,mpm2-sleep-counter@4a3000 {
|
||||
compatible = "qcom,mpm2-sleep-counter";
|
||||
reg = <0x4a3000 0x1000>;
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
|
||||
timer {
|
||||
compatible = "arm,armv8-timer";
|
||||
interrupts = <1 2 0xff08>,
|
||||
|
@ -295,7 +312,7 @@
|
|||
cci_cache: qcom,cci {
|
||||
compatible = "devfreq-simple-dev";
|
||||
clock-names = "devfreq_clk";
|
||||
clocks = <&clock_cpu clk_a53ssmux_cci>;
|
||||
clocks = <&clock_cpu clk_cci_clk>;
|
||||
governor = "cpufreq";
|
||||
freq-tbl-khz =
|
||||
< 200000 >,
|
||||
|
@ -391,15 +408,15 @@
|
|||
clock-names = "l2_clk", "cpu0_clk", "cpu1_clk", "cpu2_clk",
|
||||
"cpu3_clk", "cpu4_clk", "cpu5_clk",
|
||||
"cpu6_clk", "cpu7_clk";
|
||||
clocks = <&clock_cpu clk_a53ssmux_cci>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_bc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>,
|
||||
<&clock_cpu clk_a53ssmux_lc>;
|
||||
clocks = <&clock_cpu clk_cci_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_bc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>,
|
||||
<&clock_cpu clk_a53_lc_clk>;
|
||||
|
||||
qcom,governor-per-policy;
|
||||
|
||||
|
@ -1307,8 +1324,8 @@
|
|||
|
||||
sdhc_1: sdhci@7824000 {
|
||||
compatible = "qcom,sdhci-msm";
|
||||
reg = <0x7824900 0x500>, <0x7824000 0x800>;
|
||||
reg-names = "hc_mem", "core_mem";
|
||||
reg = <0x7824900 0x500>, <0x7824000 0x800>, <0x7824E00 0x200>;
|
||||
reg-names = "hc_mem", "core_mem", "cmdq_mem";
|
||||
|
||||
interrupts = <0 123 0>, <0 138 0>;
|
||||
interrupt-names = "hc_irq", "pwr_irq";
|
||||
|
|
|
@ -142,6 +142,8 @@
|
|||
qcom,lra-auto-res-mode="qwd";
|
||||
qcom,lra-high-z="opt1";
|
||||
qcom,lra-res-cal-period = <0>;
|
||||
qcom,correct-lra-drive-freq;
|
||||
qcom,misc-trim-error-rc19p2-clk-reg-present;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -246,6 +246,8 @@
|
|||
};
|
||||
|
||||
clock_cpu: qcom,cpu-clock-8976@b016000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "qcom,cpu-clock-8976";
|
||||
reg = <0xb114000 0x68>,
|
||||
<0xb014000 0x68>,
|
||||
|
@ -378,6 +380,15 @@
|
|||
< 556800000 5>,
|
||||
< 614400000 6>;
|
||||
#clock-cells = <1>;
|
||||
ranges;
|
||||
qcom,spm@0 {
|
||||
compatible = "qcom,cpu-spm-8976";
|
||||
reg = <0x0b111200 0x100>,
|
||||
<0x0b011200 0x100>,
|
||||
<0x0b1d4000 0x100>;
|
||||
reg-names = "spm_c0_base", "spm_c1_base",
|
||||
"spm_cci_base";
|
||||
};
|
||||
};
|
||||
|
||||
cci_cache: qcom,cci {
|
||||
|
|
|
@ -38,16 +38,16 @@
|
|||
eeprom0: qcom,eeprom@0{
|
||||
cell-index = <0>;
|
||||
reg = <0x00>;
|
||||
qcom,eeprom-name = "sunny_q13v04b";
|
||||
qcom,eeprom-name = "sunny_q13v06k";
|
||||
compatible = "qcom,eeprom";
|
||||
qcom,slave-addr = <0x20>;
|
||||
qcom,cci-master = <0>;
|
||||
qcom,num-blocks = <7>;
|
||||
qcom,num-blocks = <8>;
|
||||
|
||||
qcom,page0 = <1 0x0100 2 0x01 1 1>;
|
||||
qcom,poll0 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem0 = <0 0x0 2 0 1 0>;
|
||||
qcom,page1 = <1 0x5002 2 0x3 1 1>;
|
||||
qcom,page1 = <1 0x5002 2 0x5 1 1>;
|
||||
qcom,poll1 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem1 = <0 0x0 2 0 1 0>;
|
||||
qcom,page2 = <1 0x3d84 2 0xc0 1 0>;
|
||||
|
@ -56,15 +56,19 @@
|
|||
qcom,page3 = <1 0x3d88 2 0x7220 2 0>;
|
||||
qcom,poll3 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem3 = <0 0x0 2 0 1 0>;
|
||||
qcom,page4 = <1 0x3d8a 2 0x7369 2 0>;
|
||||
qcom,page4 = <1 0x3d8a 2 0x73BA 2 0>;
|
||||
qcom,poll4 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem4 = <0 0x0 2 0 1 0>;
|
||||
qcom,page5 = <1 0x3d81 2 0x01 1 15>;
|
||||
qcom,poll5 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem5 = <229 0x7220 2 0 1 0>;
|
||||
qcom,page6 = <1 0x5002 2 0x1 1 1>;
|
||||
qcom,mem5 = <411 0x7220 2 0 1 0>;
|
||||
qcom,page6 = <1 0x5002 2 0x7 1 1>;
|
||||
qcom,poll6 = <0 0x0 2 0 1 1>;
|
||||
qcom,mem6 = <0 0x0 2 0 1 0>;
|
||||
qcom,page7 = <0 0 0 0 0 0>;
|
||||
qcom,poll7 = <0 0 0 0 0 0>;
|
||||
qcom,saddr7 = <0xa0>;
|
||||
qcom,mem7 = <470 0x16ba 2 0 1 0>;
|
||||
|
||||
cam_vdig-supply = <&pm8950_l23>;
|
||||
cam_vana-supply = <&pm8950_l22>;
|
||||
|
|
|
@ -75,6 +75,19 @@
|
|||
};
|
||||
};
|
||||
|
||||
&i2c_2 {
|
||||
pericom-type-c@3d {
|
||||
compatible = "pericom,usb-type-c";
|
||||
reg = <0x3d>;
|
||||
vdd_io-supply = <&pm8950_l5>;
|
||||
interrupt-parent = <&msm_gpio>;
|
||||
interrupts = <102 2>; /* MSM GPIO 102, TRIGGER_FALLING */
|
||||
pericom,enb-gpio = <&msm_gpio 101 0x1>; /* active low ENB */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usbc_int_default>;
|
||||
};
|
||||
};
|
||||
|
||||
&soc {
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
qcom,mdss-pipe-rgb-clk-ctrl-offsets = <0x2ac 4 8>,
|
||||
<0x2b4 4 8>;
|
||||
qcom,mdss-pipe-dma-clk-ctrl-offsets = <0x2ac 8 12>;
|
||||
qcom,mdss-pipe-cursor-clk-ctrl-offsets = <0x3a8 16 15>;
|
||||
|
||||
qcom,mdss-smp-data = <10 10240>;
|
||||
|
||||
|
|
|
@ -165,6 +165,8 @@
|
|||
qcom,lra-auto-res-mode="qwd";
|
||||
qcom,lra-high-z="opt1";
|
||||
qcom,lra-res-cal-period = <0>;
|
||||
qcom,correct-lra-drive-freq;
|
||||
qcom,misc-trim-error-rc19p2-clk-reg-present;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -109,6 +109,17 @@
|
|||
};
|
||||
};
|
||||
|
||||
usb_c_intn_pin {
|
||||
qcom,pins = <&gp 101>, <&gp 102>;
|
||||
qcom,num-grp-pins = <2>;
|
||||
qcom,pin-func = <0>;
|
||||
label = "usb_typec-gpio";
|
||||
usbc_int_default: usbc_int_default {
|
||||
drive-strength = <2>; /* 2 MA */
|
||||
bias-pull-up; /* PULL UP*/
|
||||
};
|
||||
};
|
||||
|
||||
cti_trigout_b0 {
|
||||
qcom,pins = <&gp 22>;
|
||||
qcom,num-grp-pins = <1>;
|
||||
|
|
|
@ -444,6 +444,16 @@
|
|||
qcom,target-dev = <&cpubw>;
|
||||
};
|
||||
|
||||
qcom,msmcci-ccimon {
|
||||
compatible = "qcom,msmcci-hwmon";
|
||||
reg = <0xb1dc000 0xb0>,
|
||||
<0xb1dc004 0xb0>;
|
||||
interrupts = <0 272 4>;
|
||||
qcom,counter-event-sel = <1 2>;
|
||||
qcom,target-dev = <&cci_cache>;
|
||||
qcom,shared-irq;
|
||||
};
|
||||
|
||||
devfreq-cpufreq {
|
||||
cpubw-cpufreq {
|
||||
target-dev = <&cpubw>;
|
||||
|
|
|
@ -445,6 +445,7 @@ CONFIG_MMC_BLOCK_TEST=m
|
|||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
CONFIG_MMC_SDHCI_MSM=y
|
||||
CONFIG_MMC_CQ_HCI=y
|
||||
CONFIG_LEDS_TRIGGERS=y
|
||||
CONFIG_SWITCH=y
|
||||
CONFIG_EDAC=y
|
||||
|
@ -535,6 +536,7 @@ CONFIG_MSM_OCMEM=y
|
|||
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
|
||||
CONFIG_MSM_BOOT_STATS=y
|
||||
CONFIG_MSM_SCM=y
|
||||
CONFIG_MSM_VSENS=y
|
||||
CONFIG_MEM_SHARE_QMI_SERVICE=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
|
|
|
@ -224,6 +224,7 @@ CONFIG_BLK_DEV_LOOP=y
|
|||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_APDS9930=y
|
||||
CONFIG_QSEECOM=y
|
||||
CONFIG_USB_EXT_TYPE_C=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_SCSI_TGT=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
|
@ -450,6 +451,7 @@ CONFIG_MMC_BLOCK_TEST=m
|
|||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
CONFIG_MMC_SDHCI_MSM=y
|
||||
CONFIG_MMC_CQ_HCI=y
|
||||
CONFIG_LEDS_TRIGGERS=y
|
||||
CONFIG_SWITCH=y
|
||||
CONFIG_EDAC=y
|
||||
|
@ -553,6 +555,7 @@ CONFIG_MSM_OCMEM_NONSECURE=y
|
|||
CONFIG_MSM_BOOT_STATS=y
|
||||
CONFIG_MSM_SCM=y
|
||||
CONFIG_MSM_XPU_ERR_FATAL=y
|
||||
CONFIG_MSM_VSENS=y
|
||||
CONFIG_MEM_SHARE_QMI_SERVICE=y
|
||||
CONFIG_MSM_TZ_LOG=y
|
||||
CONFIG_EXT2_FS=y
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <linux/miscdevice.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/rtmutex.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/poll.h>
|
||||
|
@ -46,7 +45,7 @@
|
|||
#include <uapi/linux/android/binder.h>
|
||||
#include "binder_trace.h"
|
||||
|
||||
static DEFINE_RT_MUTEX(binder_main_lock);
|
||||
static DEFINE_MUTEX(binder_main_lock);
|
||||
static DEFINE_MUTEX(binder_deferred_lock);
|
||||
static DEFINE_MUTEX(binder_mmap_lock);
|
||||
|
||||
|
@ -426,14 +425,14 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd)
|
|||
static inline void binder_lock(const char *tag)
|
||||
{
|
||||
trace_binder_lock(tag);
|
||||
rt_mutex_lock(&binder_main_lock);
|
||||
mutex_lock(&binder_main_lock);
|
||||
trace_binder_locked(tag);
|
||||
}
|
||||
|
||||
static inline void binder_unlock(const char *tag)
|
||||
{
|
||||
trace_binder_unlock(tag);
|
||||
rt_mutex_unlock(&binder_main_lock);
|
||||
mutex_unlock(&binder_main_lock);
|
||||
}
|
||||
|
||||
static void binder_set_nice(long nice)
|
||||
|
|
|
@ -443,17 +443,21 @@ static void diag_close_logging_process(int pid)
|
|||
|
||||
}
|
||||
|
||||
static int diagchar_close(struct inode *inode, struct file *file)
|
||||
static int diag_remove_client_entry(struct file *file)
|
||||
{
|
||||
int i = -1;
|
||||
struct diagchar_priv *diagpriv_data = file->private_data;
|
||||
struct diagchar_priv *diagpriv_data = NULL;
|
||||
struct diag_dci_client_tbl *dci_entry = NULL;
|
||||
|
||||
pr_debug("diag: process exit %s\n", current->comm);
|
||||
if (!(file->private_data)) {
|
||||
pr_alert("diag: Invalid file pointer");
|
||||
return -ENOMEM;
|
||||
if (!file) {
|
||||
DIAG_LOG(DIAG_DEBUG_USERSPACE, "Invalid file pointer \n");
|
||||
return -ENOENT;
|
||||
}
|
||||
if (!(file->private_data)) {
|
||||
DIAG_LOG(DIAG_DEBUG_USERSPACE, "Invalid private data \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
diagpriv_data = file->private_data;
|
||||
|
||||
if (!driver)
|
||||
return -ENOMEM;
|
||||
|
@ -488,6 +492,11 @@ static int diagchar_close(struct inode *inode, struct file *file)
|
|||
mutex_unlock(&driver->diagchar_mutex);
|
||||
return 0;
|
||||
}
|
||||
static int diagchar_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: process exit %s\n", current->comm);
|
||||
return diag_remove_client_entry(file);
|
||||
}
|
||||
|
||||
void diag_record_stats(int type, int flag)
|
||||
{
|
||||
|
@ -2381,7 +2390,9 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
|
|||
data_type = driver->data_ready[index] & DEINIT_TYPE;
|
||||
COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
|
||||
driver->data_ready[index] ^= DEINIT_TYPE;
|
||||
goto exit;
|
||||
mutex_unlock(&driver->diagchar_mutex);
|
||||
diag_remove_client_entry(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (driver->data_ready[index] & MSG_MASKS_TYPE) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/msm-bus.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/clk/msm-clock-generic.h>
|
||||
|
@ -46,6 +47,14 @@ enum {
|
|||
|
||||
const char *mux_names[] = { "c1", "c0", "cci"};
|
||||
|
||||
struct cpu_clk_8939 {
|
||||
u32 cpu_reg_mask;
|
||||
cpumask_t cpumask;
|
||||
bool hw_low_power_ctrl;
|
||||
struct pm_qos_request req;
|
||||
struct clk c;
|
||||
};
|
||||
|
||||
static struct mux_div_clk a53ssmux_bc = {
|
||||
.ops = &rcg_mux_div_ops,
|
||||
.safe_freq = 400000000,
|
||||
|
@ -57,7 +66,6 @@ static struct mux_div_clk a53ssmux_bc = {
|
|||
.c = {
|
||||
.dbg_name = "a53ssmux_bc",
|
||||
.ops = &clk_ops_mux_div_clk,
|
||||
.vdd_class = &vdd_cpu_bc,
|
||||
CLK_INIT(a53ssmux_bc.c),
|
||||
},
|
||||
.parents = (struct clk_src[8]) {},
|
||||
|
@ -77,7 +85,6 @@ static struct mux_div_clk a53ssmux_lc = {
|
|||
.c = {
|
||||
.dbg_name = "a53ssmux_lc",
|
||||
.ops = &clk_ops_mux_div_clk,
|
||||
.vdd_class = &vdd_cpu_lc,
|
||||
CLK_INIT(a53ssmux_lc.c),
|
||||
},
|
||||
.parents = (struct clk_src[8]) {},
|
||||
|
@ -97,7 +104,6 @@ static struct mux_div_clk a53ssmux_cci = {
|
|||
.c = {
|
||||
.dbg_name = "a53ssmux_cci",
|
||||
.ops = &clk_ops_mux_div_clk,
|
||||
.vdd_class = &vdd_cpu_cci,
|
||||
CLK_INIT(a53ssmux_cci.c),
|
||||
},
|
||||
.parents = (struct clk_src[8]) {},
|
||||
|
@ -106,14 +112,118 @@ static struct mux_div_clk a53ssmux_cci = {
|
|||
.src_shift = 8,
|
||||
};
|
||||
|
||||
static void do_nothing(void *unused) { }
|
||||
#define CPU_LATENCY_NO_L2_PC_US (300)
|
||||
|
||||
static inline struct cpu_clk_8939 *to_cpu_clk_8939(struct clk *c)
|
||||
{
|
||||
return container_of(c, struct cpu_clk_8939, c);
|
||||
}
|
||||
|
||||
static enum handoff cpu_clk_8939_handoff(struct clk *c)
|
||||
{
|
||||
c->rate = clk_get_rate(c->parent);
|
||||
return HANDOFF_DISABLED_CLK;
|
||||
}
|
||||
|
||||
static long cpu_clk_8939_round_rate(struct clk *c, unsigned long rate)
|
||||
{
|
||||
return clk_round_rate(c->parent, rate);
|
||||
}
|
||||
|
||||
static int cpu_clk_8939_set_rate(struct clk *c, unsigned long rate)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cpu_clk_8939 *cpuclk = to_cpu_clk_8939(c);
|
||||
bool hw_low_power_ctrl = cpuclk->hw_low_power_ctrl;
|
||||
|
||||
if (hw_low_power_ctrl) {
|
||||
memset(&cpuclk->req, 0, sizeof(cpuclk->req));
|
||||
cpumask_copy(&cpuclk->req.cpus_affine,
|
||||
(const struct cpumask *)&cpuclk->cpumask);
|
||||
cpuclk->req.type = PM_QOS_REQ_AFFINE_CORES;
|
||||
pm_qos_add_request(&cpuclk->req, PM_QOS_CPU_DMA_LATENCY,
|
||||
CPU_LATENCY_NO_L2_PC_US);
|
||||
smp_call_function_any(&cpuclk->cpumask, do_nothing,
|
||||
NULL, 1);
|
||||
}
|
||||
|
||||
ret = clk_set_rate(c->parent, rate);
|
||||
|
||||
if (hw_low_power_ctrl)
|
||||
pm_qos_remove_request(&cpuclk->req);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_ops_cpu = {
|
||||
.set_rate = cpu_clk_8939_set_rate,
|
||||
.round_rate = cpu_clk_8939_round_rate,
|
||||
.handoff = cpu_clk_8939_handoff,
|
||||
};
|
||||
|
||||
static struct cpu_clk_8939 a53_bc_clk = {
|
||||
.cpu_reg_mask = 0x3,
|
||||
.c = {
|
||||
.parent = &a53ssmux_bc.c,
|
||||
.ops = &clk_ops_cpu,
|
||||
.vdd_class = &vdd_cpu_bc,
|
||||
.dbg_name = "a53_bc_clk",
|
||||
CLK_INIT(a53_bc_clk.c),
|
||||
},
|
||||
};
|
||||
|
||||
static struct cpu_clk_8939 a53_lc_clk = {
|
||||
.cpu_reg_mask = 0x103,
|
||||
.c = {
|
||||
.parent = &a53ssmux_lc.c,
|
||||
.ops = &clk_ops_cpu,
|
||||
.vdd_class = &vdd_cpu_lc,
|
||||
.dbg_name = "a53_lc_clk",
|
||||
CLK_INIT(a53_lc_clk.c),
|
||||
},
|
||||
};
|
||||
|
||||
static struct cpu_clk_8939 cci_clk = {
|
||||
.c = {
|
||||
.parent = &a53ssmux_cci.c,
|
||||
.ops = &clk_ops_cpu,
|
||||
.vdd_class = &vdd_cpu_cci,
|
||||
.dbg_name = "cci_clk",
|
||||
CLK_INIT(cci_clk.c),
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_lookup cpu_clocks_8939[] = {
|
||||
CLK_LIST(a53ssmux_lc),
|
||||
CLK_LIST(a53ssmux_bc),
|
||||
CLK_LIST(a53ssmux_cci),
|
||||
CLK_LIST(a53_bc_clk),
|
||||
CLK_LIST(a53_lc_clk),
|
||||
CLK_LIST(cci_clk),
|
||||
};
|
||||
|
||||
static struct mux_div_clk *a53ssmux[] = {&a53ssmux_bc,
|
||||
&a53ssmux_lc, &a53ssmux_cci};
|
||||
static struct cpu_clk_8939 *cpuclk[] = { &a53_bc_clk, &a53_lc_clk, &cci_clk};
|
||||
|
||||
static struct clk *logical_cpu_to_clk(int cpu)
|
||||
{
|
||||
struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
|
||||
u32 reg;
|
||||
|
||||
/* CPU 0/1/2/3 --> a53_bc_clk and mask = 0x103
|
||||
* CPU 4/5/6/7 --> a53_lc_clk and mask = 0x3
|
||||
*/
|
||||
if (cpu_node && !of_property_read_u32(cpu_node, "reg", ®)) {
|
||||
if ((reg | a53_bc_clk.cpu_reg_mask) == a53_bc_clk.cpu_reg_mask)
|
||||
return &a53_lc_clk.c;
|
||||
if ((reg | a53_lc_clk.cpu_reg_mask) == a53_lc_clk.cpu_reg_mask)
|
||||
return &a53_bc_clk.c;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int of_get_fmax_vdd_class(struct platform_device *pdev, struct clk *c,
|
||||
char *prop_name)
|
||||
|
@ -357,7 +467,7 @@ static int cpu_parse_devicetree(struct platform_device *pdev, int mux_id)
|
|||
dev_err(&pdev->dev, "unable to get regulator\n");
|
||||
return PTR_ERR(regulator);
|
||||
}
|
||||
a53ssmux[mux_id]->c.vdd_class->regulator[0] = regulator;
|
||||
cpuclk[mux_id]->c.vdd_class->regulator[0] = regulator;
|
||||
|
||||
rc = of_get_clk_src(pdev, a53ssmux[mux_id]->parents, mux_id);
|
||||
if (IS_ERR_VALUE(rc))
|
||||
|
@ -391,15 +501,15 @@ static int clock_8939_pm_event(struct notifier_block *this,
|
|||
switch (event) {
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_SUSPEND:
|
||||
clk_unprepare(&a53ssmux_lc.c);
|
||||
clk_unprepare(&a53ssmux_bc.c);
|
||||
clk_unprepare(&a53ssmux_cci.c);
|
||||
clk_unprepare(&a53_lc_clk.c);
|
||||
clk_unprepare(&a53_bc_clk.c);
|
||||
clk_unprepare(&cci_clk.c);
|
||||
break;
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
case PM_SUSPEND_PREPARE:
|
||||
clk_prepare(&a53ssmux_lc.c);
|
||||
clk_prepare(&a53ssmux_bc.c);
|
||||
clk_prepare(&a53ssmux_cci.c);
|
||||
clk_prepare(&a53_lc_clk.c);
|
||||
clk_prepare(&a53_bc_clk.c);
|
||||
clk_prepare(&cci_clk.c);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -427,7 +537,7 @@ static int clock_a53_probe(struct platform_device *pdev)
|
|||
"qcom,speed%d-bin-v%d-%s",
|
||||
speed_bin, version, mux_names[mux_id]);
|
||||
|
||||
rc = of_get_fmax_vdd_class(pdev, &a53ssmux[mux_id]->c,
|
||||
rc = of_get_fmax_vdd_class(pdev, &cpuclk[mux_id]->c,
|
||||
prop_name);
|
||||
if (rc) {
|
||||
/* Fall back to most conservative PVS table */
|
||||
|
@ -436,7 +546,7 @@ static int clock_a53_probe(struct platform_device *pdev)
|
|||
|
||||
snprintf(prop_name, ARRAY_SIZE(prop_name),
|
||||
"qcom,speed0-bin-v0-%s", mux_names[mux_id]);
|
||||
rc = of_get_fmax_vdd_class(pdev, &a53ssmux[mux_id]->c,
|
||||
rc = of_get_fmax_vdd_class(pdev, &cpuclk[mux_id]->c,
|
||||
prop_name);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev,
|
||||
|
@ -454,14 +564,13 @@ static int clock_a53_probe(struct platform_device *pdev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rate = clk_get_rate(&a53ssmux[A53SS_MUX_CCI]->c);
|
||||
clk_set_rate(&a53ssmux[A53SS_MUX_CCI]->c, rate);
|
||||
rate = clk_get_rate(&cci_clk.c);
|
||||
clk_set_rate(&cci_clk.c, rate);
|
||||
|
||||
for (mux_id = 0; mux_id < A53SS_MUX_CCI; mux_id++) {
|
||||
/* Force a PLL reconfiguration */
|
||||
config_pll(mux_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't want the CPU clocks to be turned off at late init
|
||||
* if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
|
||||
|
@ -471,15 +580,26 @@ static int clock_a53_probe(struct platform_device *pdev)
|
|||
*/
|
||||
get_online_cpus();
|
||||
for_each_online_cpu(cpu) {
|
||||
WARN(clk_prepare_enable(&a53ssmux[cpu/4]->c),
|
||||
WARN(clk_prepare_enable(&cpuclk[cpu/4]->c),
|
||||
"Unable to turn on CPU clock");
|
||||
clk_prepare_enable(&a53ssmux_cci.c);
|
||||
clk_prepare_enable(&cci_clk.c);
|
||||
}
|
||||
put_online_cpus();
|
||||
register_pm_notifier(&clock_8939_pm_notifier);
|
||||
|
||||
cpu_clock_8939_dev = pdev;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
if (logical_cpu_to_clk(cpu) == &a53_bc_clk.c)
|
||||
cpumask_set_cpu(cpu, &a53_bc_clk.cpumask);
|
||||
if (logical_cpu_to_clk(cpu) == &a53_lc_clk.c)
|
||||
cpumask_set_cpu(cpu, &a53_lc_clk.cpumask);
|
||||
}
|
||||
|
||||
a53_lc_clk.hw_low_power_ctrl = true;
|
||||
a53_bc_clk.hw_low_power_ctrl = true;
|
||||
|
||||
register_pm_notifier(&clock_8939_pm_notifier);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <soc/qcom/clock-local2.h>
|
||||
#include <soc/qcom/clock-pll.h>
|
||||
#include <soc/qcom/clock-alpha-pll.h>
|
||||
|
@ -265,6 +266,10 @@ static struct pll_clk a53ss_cci_pll = {
|
|||
.main_output_mask = BIT(0),
|
||||
},
|
||||
.base = &virt_bases[APCS_CCI_PLL_BASE],
|
||||
.spm_ctrl = {
|
||||
.offset = 0x40,
|
||||
.event_bit = 0x0,
|
||||
},
|
||||
.c = {
|
||||
.parent = &xo_a_clk_src.c,
|
||||
.dbg_name = "a53ss_cci_pll",
|
||||
|
@ -311,6 +316,10 @@ static struct pll_clk a53ss_c0_pll = {
|
|||
.main_output_mask = BIT(0),
|
||||
},
|
||||
.base = &virt_bases[APCS_C0_PLL_BASE],
|
||||
.spm_ctrl = {
|
||||
.offset = 0x50,
|
||||
.event_bit = 0x4,
|
||||
},
|
||||
.c = {
|
||||
.parent = &xo_a_clk_src.c,
|
||||
.dbg_name = "a53ss_c0_pll",
|
||||
|
@ -366,6 +375,10 @@ static struct pll_clk a53ss_c1_pll = {
|
|||
.main_output_mask = BIT(0),
|
||||
},
|
||||
.base = &virt_bases[APCS_C1_PLL_BASE],
|
||||
.spm_ctrl = {
|
||||
.offset = 0x50,
|
||||
.event_bit = 0x4,
|
||||
},
|
||||
.c = {
|
||||
.parent = &xo_a_clk_src.c,
|
||||
.dbg_name = "a53ss_c1_pll",
|
||||
|
@ -3569,6 +3582,10 @@ static int msm_gcc_probe(struct platform_device *pdev)
|
|||
regval |= CLKFLAG_SLEEP_CYCLES << 4;
|
||||
writel_relaxed(regval, GCC_REG_BASE(OXILI_GMEM_CBCR));
|
||||
|
||||
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(&pdev->dev, "Registered GCC clocks\n");
|
||||
|
||||
return 0;
|
||||
|
@ -3588,9 +3605,78 @@ static struct platform_driver msm_clock_gcc_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int msm_gcc_spm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = NULL;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spm_c0_base");
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "SPM register base not defined for c0\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
a53ss_c0_pll.spm_ctrl.spm_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!a53ss_c0_pll.spm_ctrl.spm_base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap c0 spm registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spm_c1_base");
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "SPM register base not defined for c1\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
a53ss_c1_pll.spm_ctrl.spm_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!a53ss_c1_pll.spm_ctrl.spm_base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap c1 spm registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"spm_cci_base");
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "SPM register base not defined for cci\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
a53ss_cci_pll.spm_ctrl.spm_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!a53ss_cci_pll.spm_ctrl.spm_base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap cci spm registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Registered GCC SPM clocks\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id msm_clock_spm_match_table[] = {
|
||||
{ .compatible = "qcom,gcc-spm-8952" },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver msm_clock_spm_driver = {
|
||||
.probe = msm_gcc_spm_probe,
|
||||
.driver = {
|
||||
.name = "qcom,gcc-spm-8952",
|
||||
.of_match_table = msm_clock_spm_match_table,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init msm_gcc_init(void)
|
||||
{
|
||||
return platform_driver_register(&msm_clock_gcc_driver);
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&msm_clock_gcc_driver);
|
||||
if (!ret)
|
||||
ret = platform_driver_register(&msm_clock_spm_driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct clk_lookup msm_clocks_measure[] = {
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <trace/events/power.h>
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/trace_msm_low_power.h>
|
||||
#include "../../drivers/clk/qcom/clock.h"
|
||||
|
||||
#define SCLK_HZ (32768)
|
||||
#define SCM_HANDOFF_LOCK_ID "S:7"
|
||||
|
@ -1067,6 +1068,15 @@ static int lpm_suspend_enter(suspend_state_t state)
|
|||
if (idx > 0)
|
||||
update_debug_pc_event(CPU_ENTER, idx, 0xdeaffeed,
|
||||
0xdeaffeed, false);
|
||||
|
||||
/*
|
||||
* Print the clocks which are enabled during system suspend
|
||||
* This debug information is useful to know which are the
|
||||
* clocks that are enabled and preventing the system level
|
||||
* LPMs(XO and Vmin).
|
||||
*/
|
||||
clock_debug_print_enabled();
|
||||
|
||||
if (!use_psci)
|
||||
msm_cpu_pm_enter_sleep(cluster->cpu->levels[idx].mode, false);
|
||||
else
|
||||
|
|
|
@ -79,6 +79,12 @@ static void mon_disable(struct bwmon *m)
|
|||
static void mon_clear(struct bwmon *m)
|
||||
{
|
||||
writel_relaxed(0x1, MON_CLEAR(m));
|
||||
/*
|
||||
* The counter clear and IRQ clear bits are not in the same 4KB
|
||||
* region. So, we need to make sure the counter clear is completed
|
||||
* before we try to clear the IRQ or do any other counter operations.
|
||||
*/
|
||||
mb();
|
||||
}
|
||||
|
||||
static void mon_irq_enable(struct bwmon *m)
|
||||
|
|
|
@ -73,6 +73,7 @@ struct msmcci_hwmon {
|
|||
struct cache_hwmon hw;
|
||||
struct device *dev;
|
||||
bool secure_io;
|
||||
bool irq_shared;
|
||||
};
|
||||
|
||||
#define to_mon(ptr) container_of(ptr, struct msmcci_hwmon, hw)
|
||||
|
@ -156,6 +157,25 @@ static void mon_set_limit_single(struct msmcci_hwmon *m, int idx, u32 limit)
|
|||
write_mon_reg(m, idx, EVNT_CNT_MATCH_VAL, limit);
|
||||
}
|
||||
|
||||
static irqreturn_t msmcci_hwmon_shared_intr_handler(int irq, void *dev)
|
||||
{
|
||||
struct msmcci_hwmon *m = dev;
|
||||
int idx = -1, i;
|
||||
|
||||
for (i = 0; i < m->num_counters; i++) {
|
||||
if (mon_is_match_flag_set(m, i)) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == -1)
|
||||
return IRQ_NONE;
|
||||
|
||||
update_cache_hwmon(&m->hw);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t msmcci_hwmon_intr_handler(int irq, void *dev)
|
||||
{
|
||||
struct msmcci_hwmon *m = dev;
|
||||
|
@ -379,16 +399,24 @@ static void unregister_pm_nofitifier(void)
|
|||
mutex_unlock(¬ifier_reg_lock);
|
||||
}
|
||||
|
||||
static int start_hwmon(struct cache_hwmon *hw, struct mrps_stats *mrps)
|
||||
static int request_shared_interrupt(struct msmcci_hwmon *m)
|
||||
{
|
||||
struct msmcci_hwmon *m = to_mon(hw);
|
||||
unsigned int sample_ms = hw->df->profile->polling_ms;
|
||||
int ret, i;
|
||||
u32 limit;
|
||||
int ret;
|
||||
|
||||
ret = register_pm_notifier(m);
|
||||
ret = request_threaded_irq(m->irq[HIGH], NULL,
|
||||
msmcci_hwmon_shared_intr_handler,
|
||||
IRQF_ONESHOT | IRQF_SHARED,
|
||||
dev_name(m->dev), m);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev_err(m->dev, "Unable to register shared interrupt handler for irq %d\n",
|
||||
m->irq[HIGH]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int request_interrupts(struct msmcci_hwmon *m)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < m->num_counters; i++) {
|
||||
ret = request_threaded_irq(m->irq[i], NULL,
|
||||
|
@ -400,7 +428,36 @@ static int start_hwmon(struct cache_hwmon *hw, struct mrps_stats *mrps)
|
|||
goto irq_failure;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
irq_failure:
|
||||
for (i--; i > 0; i--) {
|
||||
disable_irq(m->irq[i]);
|
||||
free_irq(m->irq[i], m);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int start_hwmon(struct cache_hwmon *hw, struct mrps_stats *mrps)
|
||||
{
|
||||
struct msmcci_hwmon *m = to_mon(hw);
|
||||
unsigned int sample_ms = hw->df->profile->polling_ms;
|
||||
int ret, i;
|
||||
u32 limit;
|
||||
|
||||
ret = register_pm_notifier(m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (m->irq_shared)
|
||||
ret = request_shared_interrupt(m);
|
||||
else
|
||||
ret = request_interrupts(m);
|
||||
|
||||
if (ret) {
|
||||
unregister_pm_nofitifier();
|
||||
return ret;
|
||||
}
|
||||
mon_init(m);
|
||||
mon_disable(m);
|
||||
for (i = 0; i < m->num_counters; i++) {
|
||||
|
@ -412,14 +469,6 @@ static int start_hwmon(struct cache_hwmon *hw, struct mrps_stats *mrps)
|
|||
m->mon_enabled = true;
|
||||
|
||||
return 0;
|
||||
|
||||
irq_failure:
|
||||
for (i--; i > 0; i--) {
|
||||
disable_irq(m->irq[i]);
|
||||
free_irq(m->irq[i], m);
|
||||
}
|
||||
unregister_pm_nofitifier();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stop_hwmon(struct cache_hwmon *hw)
|
||||
|
@ -429,11 +478,15 @@ static void stop_hwmon(struct cache_hwmon *hw)
|
|||
|
||||
m->mon_enabled = false;
|
||||
mon_disable(m);
|
||||
|
||||
for (i = 0; i < m->num_counters; i++) {
|
||||
disable_irq(m->irq[i]);
|
||||
free_irq(m->irq[i], m);
|
||||
if (!m->irq_shared || i == HIGH) {
|
||||
disable_irq(m->irq[i]);
|
||||
free_irq(m->irq[i], m);
|
||||
}
|
||||
mon_clear_single(m, i);
|
||||
}
|
||||
|
||||
unregister_pm_nofitifier();
|
||||
}
|
||||
|
||||
|
@ -471,12 +524,14 @@ static int msmcci_hwmon_parse_dt(struct platform_device *pdev,
|
|||
}
|
||||
m->event_sel[idx] = sel;
|
||||
|
||||
m->irq[idx] = platform_get_irq(pdev, idx);
|
||||
if (m->irq[idx] < 0) {
|
||||
dev_err(dev, "Counter[%d] failed to get IRQ number\n", idx);
|
||||
return m->irq[idx];
|
||||
if (!m->irq_shared || idx == HIGH) {
|
||||
m->irq[idx] = platform_get_irq(pdev, idx);
|
||||
if (m->irq[idx] < 0) {
|
||||
dev_err(dev, "Counter[%d] failed to get IRQ number\n",
|
||||
idx);
|
||||
return m->irq[idx];
|
||||
}
|
||||
}
|
||||
|
||||
m->num_counters++;
|
||||
return 0;
|
||||
}
|
||||
|
@ -495,6 +550,9 @@ static int msmcci_hwmon_driver_probe(struct platform_device *pdev)
|
|||
m->secure_io = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,secure-io");
|
||||
|
||||
m->irq_shared = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,shared-irq");
|
||||
|
||||
ret = msmcci_hwmon_parse_dt(pdev, m, HIGH);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -68,7 +68,7 @@ struct kgsl_cmdbatch {
|
|||
struct timer_list timer;
|
||||
unsigned int marker_timestamp;
|
||||
struct kgsl_mem_entry *profiling_buf_entry;
|
||||
unsigned long profiling_buffer_gpuaddr;
|
||||
uint64_t profiling_buffer_gpuaddr;
|
||||
unsigned int profile_index;
|
||||
uint64_t submit_ticks;
|
||||
unsigned int global_ts;
|
||||
|
|
|
@ -173,6 +173,7 @@ struct flash_node_data {
|
|||
u32 boost_voltage_max;
|
||||
u16 max_current;
|
||||
u16 prgm_current;
|
||||
u16 prgm_current2;
|
||||
u16 duration;
|
||||
u8 id;
|
||||
u8 type;
|
||||
|
@ -914,26 +915,32 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
|
|||
}
|
||||
|
||||
if (led->pdata->hdrm_sns_ch0_en) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
if (flash_node->id == FLASH_LED_0 ||
|
||||
flash_node->id == FLASH_LED_SWITCH) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL0(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_DISABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense disable failed\n");
|
||||
return rc;
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense disable failed\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (led->pdata->hdrm_sns_ch1_en) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
if (flash_node->id == FLASH_LED_1 ||
|
||||
flash_node->id == FLASH_LED_SWITCH) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL1(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_DISABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense disable failed\n");
|
||||
return rc;
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense disable failed\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -969,8 +976,10 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
|
|||
}
|
||||
}
|
||||
|
||||
if (!led->flash_node[0].flash_on &&
|
||||
!led->flash_node[2].flash_on) {
|
||||
if (flash_node->id == FLASH_LED_SWITCH)
|
||||
flash_node->trigger = 0;
|
||||
|
||||
if (!(flash_node->trigger & FLASH_LED0_TRIGGER)) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
led->current_addr,
|
||||
FLASH_CURRENT_MASK, 0x00);
|
||||
|
@ -981,8 +990,7 @@ static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
|
|||
}
|
||||
}
|
||||
|
||||
if (!led->flash_node[1].flash_on &&
|
||||
!led->flash_node[3].flash_on) {
|
||||
if (!(flash_node->trigger & FLASH_LED1_TRIGGER)) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
led->current2_addr,
|
||||
FLASH_CURRENT_MASK, 0x00);
|
||||
|
@ -1014,6 +1022,7 @@ static void qpnp_flash_led_work(struct work_struct *work)
|
|||
union power_supply_propval psy_prop;
|
||||
int rc, brightness = flash_node->cdev.brightness;
|
||||
int max_curr_avail_ma = 0;
|
||||
int total_curr_ma = 0;
|
||||
int i;
|
||||
u8 val;
|
||||
|
||||
|
@ -1110,23 +1119,23 @@ static void qpnp_flash_led_work(struct work_struct *work)
|
|||
"Torch reg write failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
if (led->flash_node[led->num_leds - 1].id ==
|
||||
FLASH_LED_SWITCH) {
|
||||
val = (u8)(led->flash_node[2].prgm_current *
|
||||
|
||||
if (flash_node->id == FLASH_LED_SWITCH) {
|
||||
val = (u8)(flash_node->prgm_current *
|
||||
FLASH_TORCH_MAX_LEVEL
|
||||
/ led->flash_node[2].max_current);
|
||||
/ flash_node->max_current);
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
led->current_addr,
|
||||
FLASH_CURRENT_MASK, val);
|
||||
led->current_addr,
|
||||
FLASH_CURRENT_MASK, val);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Torch reg write failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
|
||||
val = (u8)(led->flash_node[3].prgm_current *
|
||||
val = (u8)(flash_node->prgm_current2 *
|
||||
FLASH_TORCH_MAX_LEVEL
|
||||
/ led->flash_node[3].max_current);
|
||||
/ flash_node->max_current);
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
led->current2_addr,
|
||||
FLASH_CURRENT_MASK, val);
|
||||
|
@ -1178,46 +1187,49 @@ static void qpnp_flash_led_work(struct work_struct *work)
|
|||
goto exit_flash_led_work;
|
||||
}
|
||||
|
||||
if (led->pdata->hdrm_sns_ch0_en) {
|
||||
if (led->flash_node[2].flash_on) {
|
||||
if (led->pdata->hdrm_sns_ch0_en ||
|
||||
led->pdata->hdrm_sns_ch1_en) {
|
||||
if (flash_node->id == FLASH_LED_SWITCH) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL0(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_ENABLE);
|
||||
flash_node->trigger &
|
||||
FLASH_LED0_TRIGGER ?
|
||||
FLASH_LED_HDRM_SNS_ENABLE :
|
||||
FLASH_LED_HDRM_SNS_DISABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense enable failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
} else {
|
||||
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL1(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
flash_node->trigger &
|
||||
FLASH_LED1_TRIGGER ?
|
||||
FLASH_LED_HDRM_SNS_ENABLE :
|
||||
FLASH_LED_HDRM_SNS_DISABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense enable failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
} else if (flash_node->id == FLASH_LED_0) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL0(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_DISABLE);
|
||||
FLASH_LED_HDRM_SNS_ENABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense disable failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (led->pdata->hdrm_sns_ch1_en) {
|
||||
if (led->flash_node[3].flash_on) {
|
||||
} else if (flash_node->id == FLASH_LED_1) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL1(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_ENABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense enable failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
} else {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL1(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_DISABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense diable failed\n");
|
||||
|
@ -1228,18 +1240,19 @@ static void qpnp_flash_led_work(struct work_struct *work)
|
|||
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_LED_STROBE_CTRL(led->base),
|
||||
FLASH_STROBE_MASK,
|
||||
flash_node->trigger);
|
||||
(flash_node->id == FLASH_LED_SWITCH ? FLASH_STROBE_MASK
|
||||
: flash_node->trigger),
|
||||
flash_node->trigger);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Strobe ctrl reg write failed\n");
|
||||
"Strobe reg write failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
} else if (flash_node->type == FLASH) {
|
||||
if (led->flash_node[0].flash_on)
|
||||
max_curr_avail_ma += led->flash_node[0].max_current;
|
||||
if (led->flash_node[1].flash_on)
|
||||
max_curr_avail_ma += led->flash_node[1].max_current;
|
||||
if (flash_node->trigger & FLASH_LED0_TRIGGER)
|
||||
max_curr_avail_ma += flash_node->max_current;
|
||||
if (flash_node->trigger & FLASH_LED1_TRIGGER)
|
||||
max_curr_avail_ma += flash_node->max_current;
|
||||
|
||||
psy_prop.intval = true;
|
||||
rc = led->battery_psy->set_property(led->battery_psy,
|
||||
|
@ -1282,53 +1295,33 @@ static void qpnp_flash_led_work(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
if (led->flash_node[led->num_leds - 1].id ==
|
||||
FLASH_LED_SWITCH) {
|
||||
if (led->flash_node[0].flash_on &&
|
||||
led->flash_node[1].flash_on) {
|
||||
if (max_curr_avail_ma <
|
||||
flash_node->prgm_current) {
|
||||
led->flash_node[0].prgm_current =
|
||||
led->flash_node[0].prgm_current
|
||||
* max_curr_avail_ma /
|
||||
flash_node->prgm_current;
|
||||
led->flash_node[1].prgm_current =
|
||||
led->flash_node[1].prgm_current
|
||||
* max_curr_avail_ma /
|
||||
flash_node->prgm_current;
|
||||
}
|
||||
} else {
|
||||
led->flash_node[0].prgm_current
|
||||
= (max_curr_avail_ma <
|
||||
led->flash_node[0].prgm_current)
|
||||
? max_curr_avail_ma :
|
||||
led->flash_node[0].prgm_current;
|
||||
if (flash_node->id == FLASH_LED_SWITCH) {
|
||||
if (flash_node->trigger & FLASH_LED0_TRIGGER)
|
||||
total_curr_ma += flash_node->prgm_current;
|
||||
else if (flash_node->trigger & FLASH_LED1_TRIGGER)
|
||||
total_curr_ma += flash_node->prgm_current2;
|
||||
|
||||
led->flash_node[1].prgm_current
|
||||
= (max_curr_avail_ma <
|
||||
led->flash_node[1].prgm_current)
|
||||
? max_curr_avail_ma :
|
||||
led->flash_node[1].prgm_current;
|
||||
if (max_curr_avail_ma < total_curr_ma) {
|
||||
flash_node->prgm_current *=
|
||||
max_curr_avail_ma / total_curr_ma;
|
||||
flash_node->prgm_current2 *=
|
||||
max_curr_avail_ma / total_curr_ma;
|
||||
}
|
||||
|
||||
val = (u8)(led->flash_node[0].prgm_current *
|
||||
FLASH_MAX_LEVEL /
|
||||
led->flash_node[0].max_current);
|
||||
val = (u8)(flash_node->prgm_current *
|
||||
FLASH_MAX_LEVEL / flash_node->max_current);
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
led->current_addr,
|
||||
FLASH_CURRENT_MASK, val);
|
||||
led->current_addr, FLASH_CURRENT_MASK, val);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Current register write failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
|
||||
val = (u8)(led->flash_node[1].prgm_current *
|
||||
FLASH_MAX_LEVEL /
|
||||
led->flash_node[1].max_current);
|
||||
val = (u8)(flash_node->prgm_current2 *
|
||||
FLASH_MAX_LEVEL / flash_node->max_current);
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
led->current2_addr,
|
||||
FLASH_CURRENT_MASK, val);
|
||||
led->current2_addr, FLASH_CURRENT_MASK, val);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Current register write failed\n");
|
||||
|
@ -1403,46 +1396,49 @@ static void qpnp_flash_led_work(struct work_struct *work)
|
|||
usleep(FLASH_RAMP_UP_DELAY_US);
|
||||
}
|
||||
|
||||
if (led->pdata->hdrm_sns_ch0_en) {
|
||||
if (led->flash_node[0].flash_on) {
|
||||
if (led->pdata->hdrm_sns_ch0_en ||
|
||||
led->pdata->hdrm_sns_ch1_en) {
|
||||
if (flash_node->id == FLASH_LED_SWITCH) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL0(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_ENABLE);
|
||||
(flash_node->trigger &
|
||||
FLASH_LED0_TRIGGER ?
|
||||
FLASH_LED_HDRM_SNS_ENABLE :
|
||||
FLASH_LED_HDRM_SNS_DISABLE));
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense enable failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
} else {
|
||||
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL1(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
(flash_node->trigger &
|
||||
FLASH_LED1_TRIGGER ?
|
||||
FLASH_LED_HDRM_SNS_ENABLE :
|
||||
FLASH_LED_HDRM_SNS_DISABLE));
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense enable failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
} else if (flash_node->id == FLASH_LED_0) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL0(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_DISABLE);
|
||||
FLASH_LED_HDRM_SNS_ENABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense disable failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (led->pdata->hdrm_sns_ch1_en) {
|
||||
if (led->flash_node[1].flash_on) {
|
||||
} else if (flash_node->id == FLASH_LED_1) {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL1(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_ENABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense enable failed\n");
|
||||
goto exit_flash_led_work;
|
||||
}
|
||||
} else {
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_HDRM_SNS_ENABLE_CTRL1(led->base),
|
||||
FLASH_LED_HDRM_SNS_ENABLE_MASK,
|
||||
FLASH_LED_HDRM_SNS_DISABLE);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Headroom sense disable failed\n");
|
||||
|
@ -1453,8 +1449,9 @@ static void qpnp_flash_led_work(struct work_struct *work)
|
|||
|
||||
rc = qpnp_led_masked_write(led->spmi_dev,
|
||||
FLASH_LED_STROBE_CTRL(led->base),
|
||||
FLASH_STROBE_MASK,
|
||||
flash_node->trigger);
|
||||
(flash_node->id == FLASH_LED_SWITCH ? FLASH_STROBE_MASK
|
||||
: flash_node->trigger),
|
||||
flash_node->trigger);
|
||||
if (rc) {
|
||||
dev_err(&led->spmi_dev->dev,
|
||||
"Strobe reg write failed\n");
|
||||
|
@ -1543,24 +1540,37 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
|
|||
else if (flash_node->type == FLASH)
|
||||
led->flash_node[led->num_leds - 1].type = FLASH;
|
||||
|
||||
led->flash_node[led->num_leds - 1].max_current
|
||||
= flash_node->max_current;
|
||||
|
||||
if (flash_node->id == FLASH_LED_0 ||
|
||||
flash_node->id == FLASH_LED_1) {
|
||||
if (value < FLASH_LED_MIN_CURRENT_MA && value != 0)
|
||||
value = FLASH_LED_MIN_CURRENT_MA;
|
||||
|
||||
flash_node->prgm_current = value;
|
||||
flash_node->flash_on = value ? true : false;
|
||||
if (value)
|
||||
if (value) {
|
||||
led->flash_node[led->num_leds - 1].trigger |=
|
||||
0x80 >> flash_node->id;
|
||||
else
|
||||
led->flash_node[led->num_leds - 1].trigger = 0;
|
||||
(0x80 >> flash_node->id);
|
||||
if (flash_node->id == FLASH_LED_0)
|
||||
led->flash_node[led->num_leds - 1].
|
||||
prgm_current = flash_node->prgm_current;
|
||||
else if (flash_node->id == FLASH_LED_1)
|
||||
led->flash_node[led->num_leds - 1].
|
||||
prgm_current2 =
|
||||
flash_node->prgm_current;
|
||||
} else {
|
||||
led->flash_node[led->num_leds - 1].trigger &=
|
||||
~(0x80 >> flash_node->id);
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (flash_node->id == FLASH_LED_SWITCH) {
|
||||
if (led->flash_node[0].flash_on ||
|
||||
led->flash_node[1].flash_on)
|
||||
flash_node->prgm_current =
|
||||
led->flash_node[0].prgm_current +
|
||||
led->flash_node[1].prgm_current;
|
||||
if (!value) {
|
||||
flash_node->prgm_current = 0;
|
||||
flash_node->prgm_current2 = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (value < FLASH_LED_MIN_CURRENT_MA && value != 0)
|
||||
|
|
|
@ -2722,7 +2722,7 @@ STREAM_BUFF_END:
|
|||
&buff_mgr_info);
|
||||
if (rc < 0) {
|
||||
rc = -EAGAIN;
|
||||
pr_err("error getting buffer rc:%d\n", rc);
|
||||
pr_err_ratelimited("error getting buffer rc:%d\n", rc);
|
||||
break;
|
||||
}
|
||||
buff_mgr_info.frame_id = frame_info.frame_id;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define MSM_VDEC_DVC_NAME "msm_vdec_8974"
|
||||
#define MIN_NUM_OUTPUT_BUFFERS 4
|
||||
#define MIN_NUM_CAPTURE_BUFFERS 6
|
||||
#define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS 1
|
||||
#define MAX_NUM_OUTPUT_BUFFERS VB2_MAX_FRAME
|
||||
#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8010
|
||||
#define MB_SIZE_IN_PIXEL (16 * 16)
|
||||
|
@ -1594,6 +1595,7 @@ static int msm_vdec_queue_setup(struct vb2_queue *q,
|
|||
struct msm_vidc_inst *inst;
|
||||
struct hal_buffer_requirements *bufreq;
|
||||
int extra_idx = 0;
|
||||
int min_buff_count = 0;
|
||||
|
||||
if (!q || !num_buffers || !num_planes
|
||||
|| !sizes || !q->drv_priv) {
|
||||
|
@ -1650,6 +1652,14 @@ static int msm_vdec_queue_setup(struct vb2_queue *q,
|
|||
*num_buffers = max(*num_buffers, bufreq->buffer_count_min);
|
||||
dprintk(VIDC_DBG, "Set actual output buffer count: %d\n",
|
||||
*num_buffers);
|
||||
|
||||
min_buff_count = (!!(inst->flags & VIDC_THUMBNAIL)) ?
|
||||
MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS :
|
||||
MIN_NUM_CAPTURE_BUFFERS;
|
||||
|
||||
*num_buffers = clamp_val(*num_buffers,
|
||||
min_buff_count, VB2_MAX_FRAME);
|
||||
|
||||
rc = set_actual_buffer_count(inst, *num_buffers,
|
||||
msm_comm_get_hal_output_buffer(inst));
|
||||
if (rc)
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
#define DEFAULT_BIT_RATE 64000
|
||||
#define BIT_RATE_STEP 100
|
||||
#define DEFAULT_FRAME_RATE 15
|
||||
#define MAX_SLICE_BYTE_SIZE 1024
|
||||
#define MIN_SLICE_BYTE_SIZE 1024
|
||||
#define MAX_SLICE_MB_SIZE 300
|
||||
#define MAX_SLICE_BYTE_SIZE ((MAX_BIT_RATE)>>3)
|
||||
#define MIN_SLICE_BYTE_SIZE 512
|
||||
#define MAX_SLICE_MB_SIZE ((4096 * 2304) >> 8)
|
||||
#define I_FRAME_QP 26
|
||||
#define P_FRAME_QP 28
|
||||
#define B_FRAME_QP 30
|
||||
#define MAX_INTRA_REFRESH_MBS 300
|
||||
#define MAX_INTRA_REFRESH_MBS ((4096 * 2304) >> 8)
|
||||
#define MAX_NUM_B_FRAMES 4
|
||||
#define MAX_LTR_FRAME_COUNT 10
|
||||
|
||||
|
|
|
@ -364,6 +364,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
|
|||
"Scalable Baseline",
|
||||
"Scalable High",
|
||||
"Scalable High Intra",
|
||||
"Stereo High",
|
||||
"Multiview High",
|
||||
"Constrained High",
|
||||
NULL,
|
||||
|
|
|
@ -958,7 +958,7 @@ static void wcd9335_bring_up(struct wcd9xxx *wcd9xxx)
|
|||
|
||||
if (val & 0x80) {
|
||||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_CODEC_RPM_RST_CTL, 0x01);
|
||||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_SIDO_SIDO_CCL_2, 0xB4);
|
||||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_SIDO_SIDO_CCL_2, 0xFC);
|
||||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_SIDO_SIDO_CCL_4, 0x21);
|
||||
__wcd9xxx_reg_write(wcd9xxx,
|
||||
WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
|
||||
|
@ -969,7 +969,7 @@ static void wcd9335_bring_up(struct wcd9xxx *wcd9xxx)
|
|||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_CODEC_RPM_RST_CTL, 0x3);
|
||||
} else {
|
||||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_CODEC_RPM_RST_CTL, 0x01);
|
||||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_SIDO_SIDO_CCL_2, 0xB4);
|
||||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_SIDO_SIDO_CCL_2, 0xFC);
|
||||
__wcd9xxx_reg_write(wcd9xxx, WCD9335_SIDO_SIDO_CCL_4, 0x21);
|
||||
__wcd9xxx_reg_write(wcd9xxx,
|
||||
WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
|
||||
|
@ -2948,12 +2948,22 @@ int wcd9xxx_disable_static_supplies_to_optimum(struct wcd9xxx *wcd9xxx,
|
|||
}
|
||||
EXPORT_SYMBOL(wcd9xxx_disable_static_supplies_to_optimum);
|
||||
|
||||
static int wcd9xxx_enable_static_supplies_to_optimum(
|
||||
struct wcd9xxx *wcd9xxx,
|
||||
struct wcd9xxx_pdata *pdata)
|
||||
/*
|
||||
* wcd9xxx_enable_static_supplies_to_optimum(): to set supplies to optimum mode
|
||||
* @wcd9xxx: Handle to the wcd9xxx core
|
||||
* @pdata: Handle for pdata
|
||||
*
|
||||
* To set all the static supplied to optimum mode so as to save power
|
||||
*
|
||||
* Return: returns 0 if success or error information to the caller in case
|
||||
* of failure.
|
||||
*/
|
||||
int wcd9xxx_enable_static_supplies_to_optimum(
|
||||
struct wcd9xxx *wcd9xxx, void *data)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
struct wcd9xxx_pdata *pdata = (struct wcd9xxx_pdata *)data;
|
||||
|
||||
for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
|
||||
if (pdata->regulator[i].ondemand)
|
||||
|
@ -2978,13 +2988,12 @@ static int wcd9xxx_enable_static_supplies_to_optimum(
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(wcd9xxx_enable_static_supplies_to_optimum);
|
||||
|
||||
static int wcd9xxx_slim_resume(struct slim_device *sldev)
|
||||
{
|
||||
struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
|
||||
struct wcd9xxx_pdata *pdata = sldev->dev.platform_data;
|
||||
|
||||
wcd9xxx_enable_static_supplies_to_optimum(wcd9xxx, pdata);
|
||||
return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
|
||||
}
|
||||
|
||||
|
@ -3000,9 +3009,7 @@ static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
|
|||
static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
|
||||
{
|
||||
struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
|
||||
struct wcd9xxx_pdata *pdata = sldev->dev.platform_data;
|
||||
|
||||
wcd9xxx_disable_static_supplies_to_optimum(wcd9xxx, pdata);
|
||||
return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,13 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define PERICOM_I2C_NAME "usb-type-c-pericom"
|
||||
#define PERICOM_I2C_DELAY_MS 30
|
||||
|
||||
#define CCD_DEFAULT 0x1
|
||||
#define CCD_MEDIUM 0x2
|
||||
|
@ -27,6 +30,8 @@
|
|||
#define MAX_CURRENT_MEDIUM 1500
|
||||
#define MAX_CURRENT_HIGH 3000
|
||||
|
||||
#define PIUSB_1P8_VOL_MAX 1800000 /* uV */
|
||||
|
||||
struct piusb_regs {
|
||||
u8 dev_id;
|
||||
u8 control;
|
||||
|
@ -48,6 +53,9 @@ struct pi_usb_type_c {
|
|||
struct power_supply *usb_psy;
|
||||
int max_current;
|
||||
bool attach_state;
|
||||
int enb_gpio;
|
||||
int enb_gpio_polarity;
|
||||
struct regulator *i2c_1p8;
|
||||
};
|
||||
static struct pi_usb_type_c *pi_usb;
|
||||
|
||||
|
@ -68,10 +76,10 @@ static int piusb_read_regdata(struct i2c_client *i2c)
|
|||
|
||||
rc = i2c_transfer(i2c->adapter, msgs, 1);
|
||||
if (rc < 0) {
|
||||
/* i2c read may fail if type-c plug removed, treat as detach */
|
||||
/* i2c read may fail if device not enabled or not present */
|
||||
dev_dbg(&i2c->dev, "i2c read from 0x%x failed %d\n", saddr, rc);
|
||||
pi_usb->attach_state = false;
|
||||
return 0;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
dev_dbg(&i2c->dev, "i2c read from 0x%x-[%x %x %x %x]\n", saddr,
|
||||
|
@ -141,7 +149,7 @@ static irqreturn_t piusb_irq(int irq, void *data)
|
|||
struct pi_usb_type_c *pi_usb = (struct pi_usb_type_c *)data;
|
||||
|
||||
/* i2c register update takes time, 30msec sleep required as per HPG */
|
||||
msleep(30);
|
||||
msleep(PERICOM_I2C_DELAY_MS);
|
||||
|
||||
ret = piusb_read_regdata(pi_usb->client);
|
||||
if (ret < 0)
|
||||
|
@ -157,10 +165,122 @@ out:
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int piusb_i2c_write(struct pi_usb_type_c *pi, u8 *data, int len)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = pi->client->addr,
|
||||
.flags = 0,
|
||||
.len = len,
|
||||
.buf = data,
|
||||
}
|
||||
};
|
||||
|
||||
ret = i2c_transfer(pi->client->adapter, msgs, 1);
|
||||
if (ret != 1) {
|
||||
dev_err(&pi->client->dev, "i2c write to [%x] failed %d\n",
|
||||
pi->client->addr, ret);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int piusb_i2c_enable(struct pi_usb_type_c *pi, bool enable)
|
||||
{
|
||||
u8 rst_assert[] = {0, 0x1};
|
||||
u8 rst_deassert[] = {0, 0x4};
|
||||
u8 pi_disable[] = {0, 0x80};
|
||||
|
||||
if (!enable) {
|
||||
if (piusb_i2c_write(pi, pi_disable, sizeof(pi_disable)))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (piusb_i2c_write(pi, rst_assert, sizeof(rst_assert)))
|
||||
return -EIO;
|
||||
|
||||
msleep(PERICOM_I2C_DELAY_MS);
|
||||
if (piusb_i2c_write(pi, rst_deassert, sizeof(rst_deassert)))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int piusb_gpio_config(struct pi_usb_type_c *pi, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!enable) {
|
||||
gpio_set_value(pi_usb->enb_gpio, !pi_usb->enb_gpio_polarity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request(&pi->client->dev, pi->enb_gpio,
|
||||
"pi_typec_enb_gpio");
|
||||
if (ret) {
|
||||
pr_err("unable to request gpio [%d]\n", pi->enb_gpio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(pi->enb_gpio, pi->enb_gpio_polarity);
|
||||
if (ret) {
|
||||
dev_err(&pi->client->dev, "set dir[%d] failed for gpio[%d]\n",
|
||||
pi->enb_gpio_polarity, pi->enb_gpio);
|
||||
return ret;
|
||||
}
|
||||
dev_dbg(&pi->client->dev, "set dir[%d] for gpio[%d]\n",
|
||||
pi->enb_gpio_polarity, pi->enb_gpio);
|
||||
|
||||
gpio_set_value(pi->enb_gpio, pi->enb_gpio_polarity);
|
||||
msleep(PERICOM_I2C_DELAY_MS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int piusb_ldo_init(struct pi_usb_type_c *pi, bool init)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!init) {
|
||||
regulator_set_voltage(pi->i2c_1p8, 0, PIUSB_1P8_VOL_MAX);
|
||||
rc = regulator_disable(pi->i2c_1p8);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pi->i2c_1p8 = devm_regulator_get(&pi->client->dev, "vdd_io");
|
||||
if (IS_ERR(pi->i2c_1p8)) {
|
||||
rc = PTR_ERR(pi->i2c_1p8);
|
||||
dev_err(&pi->client->dev, "unable to get 1p8(%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
rc = regulator_set_voltage(pi->i2c_1p8, PIUSB_1P8_VOL_MAX,
|
||||
PIUSB_1P8_VOL_MAX);
|
||||
if (rc) {
|
||||
dev_err(&pi->client->dev, "unable to set voltage(%d)\n", rc);
|
||||
goto put_1p8;
|
||||
}
|
||||
|
||||
rc = regulator_enable(pi->i2c_1p8);
|
||||
if (rc) {
|
||||
dev_err(&pi->client->dev, "unable to enable 1p8-reg(%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
put_1p8:
|
||||
regulator_set_voltage(pi->i2c_1p8, 0, PIUSB_1P8_VOL_MAX);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int piusb_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct power_supply *usb_psy;
|
||||
struct device_node *np = i2c->dev.of_node;
|
||||
enum of_gpio_flags flags;
|
||||
|
||||
usb_psy = power_supply_get_by_name("usb");
|
||||
if (!usb_psy) {
|
||||
|
@ -183,6 +303,30 @@ static int piusb_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
|
|||
goto out;
|
||||
}
|
||||
|
||||
pi_usb->enb_gpio = of_get_named_gpio_flags(np, "pericom,enb-gpio", 0,
|
||||
&flags);
|
||||
if (!gpio_is_valid(pi_usb->enb_gpio)) {
|
||||
dev_dbg(&i2c->dev, "enb gpio_get fail:%d\n", pi_usb->enb_gpio);
|
||||
} else {
|
||||
pi_usb->enb_gpio_polarity = !(flags & OF_GPIO_ACTIVE_LOW);
|
||||
ret = piusb_gpio_config(pi_usb, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = piusb_ldo_init(pi_usb, true);
|
||||
if (ret) {
|
||||
dev_err(&pi_usb->client->dev, "i2c ldo init failed\n");
|
||||
goto gpio_disable;
|
||||
}
|
||||
|
||||
ret = piusb_i2c_enable(pi_usb, true);
|
||||
if (ret) {
|
||||
dev_err(&pi_usb->client->dev, "i2c access failed\n");
|
||||
ret = -EPROBE_DEFER;
|
||||
goto ldo_disable;
|
||||
}
|
||||
|
||||
/* Update initial state to USB */
|
||||
piusb_irq(i2c->irq, pi_usb);
|
||||
|
||||
|
@ -191,13 +335,20 @@ static int piusb_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
|
|||
PERICOM_I2C_NAME, pi_usb);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "irq(%d) req failed-%d\n", i2c->irq, ret);
|
||||
goto out;
|
||||
goto i2c_disable;
|
||||
}
|
||||
|
||||
dev_dbg(&i2c->dev, "%s finished, addr:%d\n", __func__, i2c->addr);
|
||||
|
||||
return 0;
|
||||
|
||||
i2c_disable:
|
||||
piusb_i2c_enable(pi_usb, false);
|
||||
ldo_disable:
|
||||
piusb_ldo_init(pi_usb, false);
|
||||
gpio_disable:
|
||||
if (gpio_is_valid(pi_usb->enb_gpio))
|
||||
piusb_gpio_config(pi_usb, false);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -206,6 +357,10 @@ static int piusb_remove(struct i2c_client *i2c)
|
|||
{
|
||||
struct pi_usb_type_c *pi_usb = i2c_get_clientdata(i2c);
|
||||
|
||||
piusb_i2c_enable(pi_usb, false);
|
||||
piusb_ldo_init(pi_usb, false);
|
||||
if (gpio_is_valid(pi_usb->enb_gpio))
|
||||
piusb_gpio_config(pi_usb, false);
|
||||
devm_kfree(&i2c->dev, pi_usb);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -49,10 +49,14 @@ static int mmc_host_runtime_suspend(struct device *dev)
|
|||
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
||||
int ret = 0;
|
||||
ktime_t start = ktime_get();
|
||||
enum dev_state status = 0;
|
||||
|
||||
if (!mmc_use_core_runtime_pm(host))
|
||||
return 0;
|
||||
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, DEV_SUSPENDING);
|
||||
|
||||
if (host->card && mmc_card_cmdq(host->card)) {
|
||||
BUG_ON(host->cmdq_ctx.active_reqs);
|
||||
|
||||
|
@ -61,7 +65,7 @@ static int mmc_host_runtime_suspend(struct device *dev)
|
|||
if (ret) {
|
||||
mmc_card_clr_suspended(host->card);
|
||||
pr_err("%s: halt: failed: %d\n", __func__, ret);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
mmc_host_clk_hold(host);
|
||||
host->cmdq_ops->disable(host, true);
|
||||
|
@ -91,6 +95,10 @@ static int mmc_host_runtime_suspend(struct device *dev)
|
|||
*/
|
||||
if (ret == -ENOMEDIUM)
|
||||
ret = 0;
|
||||
out:
|
||||
status = !ret ? DEV_SUSPENDED : DEV_ERROR;
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, status);
|
||||
|
||||
trace_mmc_host_runtime_suspend(mmc_hostname(host), ret,
|
||||
ktime_to_us(ktime_sub(ktime_get(), start)));
|
||||
|
@ -102,10 +110,14 @@ static int mmc_host_runtime_resume(struct device *dev)
|
|||
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
||||
int ret = 0;
|
||||
ktime_t start = ktime_get();
|
||||
enum dev_state status = 0;
|
||||
|
||||
if (!mmc_use_core_runtime_pm(host))
|
||||
return 0;
|
||||
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, DEV_RESUMING);
|
||||
|
||||
ret = mmc_resume_host(host);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: %s: resume host: failed: ret: %d\n",
|
||||
|
@ -121,6 +133,11 @@ static int mmc_host_runtime_resume(struct device *dev)
|
|||
else
|
||||
mmc_card_clr_suspended(host->card);
|
||||
}
|
||||
|
||||
status = !ret ? DEV_RESUMED : DEV_ERROR;
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, status);
|
||||
|
||||
trace_mmc_host_runtime_resume(mmc_hostname(host), ret,
|
||||
ktime_to_us(ktime_sub(ktime_get(), start)));
|
||||
return ret;
|
||||
|
@ -133,9 +150,14 @@ static int mmc_host_suspend(struct device *dev)
|
|||
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
enum dev_state status = 0;
|
||||
|
||||
if (!mmc_use_core_pm(host))
|
||||
return 0;
|
||||
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, DEV_SUSPENDING);
|
||||
|
||||
spin_lock_irqsave(&host->clk_lock, flags);
|
||||
/*
|
||||
* let the driver know that suspend is in progress and must
|
||||
|
@ -152,7 +174,7 @@ static int mmc_host_suspend(struct device *dev)
|
|||
if (ret) {
|
||||
mmc_card_clr_suspended(host->card);
|
||||
pr_err("%s: halt: failed: %d\n", __func__, ret);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
mmc_host_clk_hold(host);
|
||||
host->cmdq_ops->disable(host, true);
|
||||
|
@ -179,6 +201,10 @@ static int mmc_host_suspend(struct device *dev)
|
|||
spin_lock_irqsave(&host->clk_lock, flags);
|
||||
host->dev_status = DEV_SUSPENDED;
|
||||
spin_unlock_irqrestore(&host->clk_lock, flags);
|
||||
out:
|
||||
status = !ret ? DEV_SUSPENDED : DEV_ERROR;
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -186,10 +212,13 @@ static int mmc_host_resume(struct device *dev)
|
|||
{
|
||||
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
||||
int ret = 0;
|
||||
enum dev_state status = 0;
|
||||
|
||||
if (!mmc_use_core_pm(host))
|
||||
return 0;
|
||||
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, DEV_RESUMING);
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
ret = mmc_resume_host(host);
|
||||
if (ret < 0) {
|
||||
|
@ -205,6 +234,10 @@ static int mmc_host_resume(struct device *dev)
|
|||
}
|
||||
}
|
||||
host->dev_status = DEV_RESUMED;
|
||||
status = !ret ? DEV_RESUMED : DEV_ERROR;
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, status);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1947,7 +1947,16 @@ static void sdhci_msm_bus_voting(struct sdhci_host *host, u32 enable)
|
|||
|
||||
if (!msm_host->msm_bus_vote.client_handle)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If mmc_host is starting resume we set the highest msm_bus
|
||||
* vote(which corresponding sdhci DT node can support) at the
|
||||
* start of resume itself, instead of putting multiple
|
||||
* msm_bus vote at each card initlization state/freq.
|
||||
* Since mmc_dev_state here has started resume process,
|
||||
* we simply return.
|
||||
*/
|
||||
if (msm_host->mmc_dev_state == DEV_RESUMING)
|
||||
return;
|
||||
bw = sdhci_get_bw_required(host, ios);
|
||||
if (enable) {
|
||||
sdhci_msm_bus_cancel_work_and_set_vote(host, bw);
|
||||
|
@ -3140,6 +3149,45 @@ void sdhci_msm_reset_enter(struct sdhci_host *host, u8 mask)
|
|||
if (msm_host->ice.pdev)
|
||||
writel_relaxed(1, host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL);
|
||||
}
|
||||
/*
|
||||
* sdhci_msm_notify_pm_status - notification from mmc_host
|
||||
* layer to msm platform about PM state of mmc_host device.
|
||||
*
|
||||
* enum dev_state state - PM state of mmc_host device.
|
||||
*
|
||||
* If mmc_host is starting resume we set the highest msm_bus
|
||||
* vote(which corresponding sdhci DT node can support) at the
|
||||
* start of resume itself, instead of putting multiple
|
||||
* msm_bus vote at each card initlization state/freq.
|
||||
*
|
||||
*/
|
||||
static void sdhci_msm_notify_pm_status(struct sdhci_host *host,
|
||||
enum dev_state state)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct sdhci_msm_host *msm_host = pltfm_host->priv;
|
||||
unsigned int bw;
|
||||
unsigned int *table = NULL;
|
||||
|
||||
if (msm_host->pdata->voting_data == NULL) {
|
||||
msm_host->mmc_dev_state = state;
|
||||
return;
|
||||
}
|
||||
|
||||
table = msm_host->pdata->voting_data->bw_vecs;
|
||||
if (state == DEV_RESUMING) {
|
||||
bw = table[msm_host->msm_bus_vote.max_bw_vote - 1];
|
||||
if (msm_host->pdata->mmc_bus_width == MMC_CAP_4_BIT_DATA)
|
||||
bw /= 2;
|
||||
sdhci_msm_bus_cancel_work_and_set_vote(host, bw);
|
||||
} else if (state == DEV_RESUMED) {
|
||||
/* Do Nothing
|
||||
* We assume that mmc_host layer will remove
|
||||
* the msm_bus vote once clk gets gated.
|
||||
*/
|
||||
}
|
||||
msm_host->mmc_dev_state = state;
|
||||
}
|
||||
|
||||
static void sdhci_msm_clear_set_dumpregs(struct sdhci_host *host, bool set)
|
||||
{
|
||||
|
@ -3202,6 +3250,7 @@ static struct sdhci_ops sdhci_msm_ops = {
|
|||
.reset_workaround = sdhci_msm_reset_workaround,
|
||||
.clear_set_dumpregs = sdhci_msm_clear_set_dumpregs,
|
||||
.notify_load = sdhci_msm_notify_load,
|
||||
.notify_pm_status = sdhci_msm_notify_pm_status,
|
||||
};
|
||||
|
||||
static int sdhci_msm_cfg_mpm_pin_wakeup(struct sdhci_host *host, unsigned mode)
|
||||
|
|
|
@ -162,6 +162,7 @@ struct sdhci_msm_host {
|
|||
bool use_cdclp533;
|
||||
bool use_updated_dll_reset;
|
||||
u32 caps_0;
|
||||
enum dev_state mmc_dev_state;
|
||||
struct sdhci_msm_ice_data ice;
|
||||
u32 ice_clk_rate;
|
||||
};
|
||||
|
|
|
@ -1687,6 +1687,14 @@ static inline void sdhci_update_power_policy(struct sdhci_host *host,
|
|||
host->power_policy = policy;
|
||||
}
|
||||
|
||||
static void sdhci_notify_pm_status(struct mmc_host *mmc, enum dev_state state)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
|
||||
if (host->ops->notify_pm_status)
|
||||
host->ops->notify_pm_status(host, state);
|
||||
}
|
||||
|
||||
static int sdhci_notify_load(struct mmc_host *mmc, enum mmc_load state)
|
||||
{
|
||||
int err = 0;
|
||||
|
@ -2871,6 +2879,7 @@ static const struct mmc_host_ops sdhci_ops = {
|
|||
.stop_request = sdhci_stop_request,
|
||||
.get_xfer_remain = sdhci_get_xfer_remain,
|
||||
.notify_load = sdhci_notify_load,
|
||||
.notify_pm_status = sdhci_notify_pm_status,
|
||||
};
|
||||
|
||||
/*****************************************************************************\
|
||||
|
|
|
@ -329,6 +329,8 @@ struct sdhci_ops {
|
|||
void (*reset_workaround)(struct sdhci_host *host, u32 enable);
|
||||
void (*clear_set_dumpregs)(struct sdhci_host *host, bool set);
|
||||
int (*notify_load)(struct sdhci_host *host, enum mmc_load state);
|
||||
void (*notify_pm_status)(struct sdhci_host *host,
|
||||
enum dev_state state);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
|
||||
|
|
|
@ -1234,6 +1234,7 @@ static void ecm_ipa_tx_complete_notify(void *priv,
|
|||
|
||||
atomic_dec(&ecm_ipa_ctx->outstanding_pkts);
|
||||
if (netif_queue_stopped(ecm_ipa_ctx->net) &&
|
||||
netif_carrier_ok(ecm_ipa_ctx->net) &&
|
||||
atomic_read(&ecm_ipa_ctx->outstanding_pkts) <
|
||||
(ecm_ipa_ctx->outstanding_low)) {
|
||||
ECM_IPA_DEBUG("outstanding low (%d) - waking up queue\n",
|
||||
|
|
|
@ -977,6 +977,7 @@ static void rndis_ipa_tx_complete_notify(void *private,
|
|||
|
||||
atomic_dec(&rndis_ipa_ctx->outstanding_pkts);
|
||||
if (netif_queue_stopped(rndis_ipa_ctx->net) &&
|
||||
netif_carrier_ok(rndis_ipa_ctx->net) &&
|
||||
atomic_read(&rndis_ipa_ctx->outstanding_pkts) <
|
||||
(rndis_ipa_ctx->outstanding_low)) {
|
||||
RNDIS_IPA_DEBUG("outstanding low boundary reached (%d)n",
|
||||
|
|
|
@ -3863,8 +3863,18 @@ void ipa_bam_reg_dump(void)
|
|||
if (__ratelimit(&_rs)) {
|
||||
ipa_inc_client_enable_clks();
|
||||
pr_err("IPA BAM START\n");
|
||||
sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 511950, 0, 0);
|
||||
sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0, 0, 0);
|
||||
if (ipa_ctx->ipa_hw_type < IPA_HW_v2_0) {
|
||||
sps_get_bam_debug_info(ipa_ctx->bam_handle, 5,
|
||||
511950, 0, 0);
|
||||
sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0,
|
||||
0, 0);
|
||||
} else {
|
||||
sps_get_bam_debug_info(ipa_ctx->bam_handle, 93,
|
||||
(SPS_BAM_PIPE(ipa_get_ep_mapping(IPA_CLIENT_USB_CONS))
|
||||
|
|
||||
SPS_BAM_PIPE(ipa_get_ep_mapping(IPA_CLIENT_USB_PROD))),
|
||||
0, 2);
|
||||
}
|
||||
ipa_dec_client_disable_clks();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#endif
|
||||
#include "idle.h"
|
||||
#include "pm-boot.h"
|
||||
#include "../../../arch/arm/mach-msm/clock.h"
|
||||
|
||||
#define SCM_CMD_TERMINATE_PC (0x2)
|
||||
#define SCM_CMD_CORE_HOTPLUGGED (0x10)
|
||||
|
@ -63,10 +62,9 @@ enum {
|
|||
MSM_PM_DEBUG_SUSPEND_LIMITS = BIT(2),
|
||||
MSM_PM_DEBUG_CLOCK = BIT(3),
|
||||
MSM_PM_DEBUG_RESET_VECTOR = BIT(4),
|
||||
MSM_PM_DEBUG_IDLE_CLK = BIT(5),
|
||||
MSM_PM_DEBUG_IDLE = BIT(6),
|
||||
MSM_PM_DEBUG_IDLE_LIMITS = BIT(7),
|
||||
MSM_PM_DEBUG_HOTPLUG = BIT(8),
|
||||
MSM_PM_DEBUG_IDLE = BIT(5),
|
||||
MSM_PM_DEBUG_IDLE_LIMITS = BIT(6),
|
||||
MSM_PM_DEBUG_HOTPLUG = BIT(7),
|
||||
};
|
||||
|
||||
enum msm_pc_count_offsets {
|
||||
|
@ -352,14 +350,6 @@ static bool msm_pm_power_collapse(bool from_idle)
|
|||
if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
|
||||
pr_info("CPU%u: %s: pre power down\n", cpu, __func__);
|
||||
|
||||
/* This spews a lot of messages when a core is hotplugged. This
|
||||
* information is most useful from last core going down during
|
||||
* power collapse
|
||||
*/
|
||||
if ((!from_idle && cpu_online(cpu))
|
||||
|| (MSM_PM_DEBUG_IDLE_CLK & msm_pm_debug_mask))
|
||||
clock_debug_print_enabled();
|
||||
|
||||
avsdscr = avs_get_avsdscr();
|
||||
avscsr = avs_get_avscsr();
|
||||
avs_set_avscsr(0); /* Disable AVS */
|
||||
|
|
|
@ -3847,7 +3847,7 @@ static irqreturn_t fg_soc_irq_handler(int irq, void *_chip)
|
|||
schedule_work(&chip->charge_full_work);
|
||||
if (chip->wa_flag & IADC_GAIN_COMP_WA
|
||||
&& chip->iadc_comp_data.gain_active) {
|
||||
fg_stay_awake(&chip->resume_soc_wakeup_source);
|
||||
fg_stay_awake(&chip->gain_comp_wakeup_source);
|
||||
schedule_work(&chip->gain_comp_work);
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ struct smbchg_chip {
|
|||
bool cfg_chg_led_sw_ctrl;
|
||||
bool vbat_above_headroom;
|
||||
bool force_aicl_rerun;
|
||||
bool enable_hvdcp_9v;
|
||||
bool hvdcp3_supported;
|
||||
u8 original_usbin_allowance;
|
||||
struct parallel_usb_cfg parallel;
|
||||
struct delayed_work parallel_en_work;
|
||||
|
@ -264,6 +264,7 @@ enum smbchg_wa {
|
|||
SMBCHG_AICL_DEGLITCH_WA = BIT(0),
|
||||
SMBCHG_HVDCP_9V_EN_WA = BIT(1),
|
||||
SMBCHG_USB100_WA = BIT(2),
|
||||
SMBCHG_BATT_OV_WA = BIT(3),
|
||||
};
|
||||
|
||||
enum print_reason {
|
||||
|
@ -3911,8 +3912,8 @@ static void smbchg_hvdcp_det_work(struct work_struct *work)
|
|||
int rc;
|
||||
|
||||
if (is_hvdcp_present(chip)) {
|
||||
if (chip->enable_hvdcp_9v
|
||||
&& (chip->wa_flags & SMBCHG_HVDCP_9V_EN_WA)) {
|
||||
if (!chip->hvdcp3_supported &&
|
||||
(chip->wa_flags & SMBCHG_HVDCP_9V_EN_WA)) {
|
||||
/* force HVDCP 2.0 */
|
||||
rc = force_9v_hvdcp(chip);
|
||||
if (rc)
|
||||
|
@ -4644,10 +4645,173 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
#define USB_CMD_APSD 0x41
|
||||
#define APSD_RERUN BIT(0)
|
||||
static int rerun_apsd(struct smbchg_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
|
||||
INIT_COMPLETION(chip->src_det_raised);
|
||||
INIT_COMPLETION(chip->usbin_uv_lowered);
|
||||
INIT_COMPLETION(chip->src_det_lowered);
|
||||
INIT_COMPLETION(chip->usbin_uv_raised);
|
||||
|
||||
/* re-run APSD */
|
||||
rc = smbchg_masked_write(chip, chip->usb_chgpth_base + USB_CMD_APSD,
|
||||
APSD_RERUN, APSD_RERUN);
|
||||
if (rc) {
|
||||
pr_err("Couldn't re-run APSD rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_smb(PR_MISC, "Waiting on rising usbin uv\n");
|
||||
rc = wait_for_usbin_uv(chip, true);
|
||||
if (rc < 0) {
|
||||
pr_err("wait for usbin uv failed rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_smb(PR_MISC, "Waiting on falling src det\n");
|
||||
rc = wait_for_src_detect(chip, false);
|
||||
if (rc < 0) {
|
||||
pr_err("wait for src detect failed rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_smb(PR_MISC, "Waiting on falling usbin uv\n");
|
||||
rc = wait_for_usbin_uv(chip, false);
|
||||
if (rc < 0) {
|
||||
pr_err("wait for usbin uv failed rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_smb(PR_MISC, "Waiting on rising src det\n");
|
||||
rc = wait_for_src_detect(chip, true);
|
||||
if (rc < 0) {
|
||||
pr_err("wait for src detect failed rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define SCHG_LITE_USBIN_HVDCP_5_9V 0x8
|
||||
#define SCHG_LITE_USBIN_HVDCP_5_9V_SEL_MASK 0x38
|
||||
#define SCHG_LITE_USBIN_HVDCP_SEL_IDLE BIT(3)
|
||||
static bool is_hvdcp_5v_cont_mode(struct smbchg_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
u8 reg = 0;
|
||||
|
||||
rc = smbchg_read(chip, ®,
|
||||
chip->usb_chgpth_base + USBIN_HVDCP_STS, 1);
|
||||
if (rc) {
|
||||
pr_err("Unable to read HVDCP status rc=%d\n", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
pr_smb(PR_STATUS, "HVDCP status = %x\n", reg);
|
||||
|
||||
if (reg & SCHG_LITE_USBIN_HVDCP_SEL_IDLE) {
|
||||
rc = smbchg_read(chip, ®,
|
||||
chip->usb_chgpth_base + INPUT_STS, 1);
|
||||
if (rc) {
|
||||
pr_err("Unable to read INPUT status rc=%d\n", rc);
|
||||
return false;
|
||||
}
|
||||
pr_smb(PR_STATUS, "INPUT status = %x\n", reg);
|
||||
if ((reg & SCHG_LITE_USBIN_HVDCP_5_9V_SEL_MASK) ==
|
||||
SCHG_LITE_USBIN_HVDCP_5_9V)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* check if HVDCP is already in 5V continuous mode */
|
||||
if (is_hvdcp_5v_cont_mode(chip)) {
|
||||
pr_smb(PR_MISC, "HVDCP by default is in 5V continuous mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* switch to 5V HVDCP */
|
||||
pr_smb(PR_MISC, "Switch to 5V HVDCP\n");
|
||||
rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG,
|
||||
HVDCP_ADAPTER_SEL_MASK, HVDCP_5V);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't configure HVDCP 5V rc=%d\n", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* wait for HVDCP to lower to 5V */
|
||||
msleep(500);
|
||||
/*
|
||||
* Check if the same hvdcp session is in progress. src_det should be
|
||||
* high and that we are still in 5V hvdcp
|
||||
*/
|
||||
if (!is_src_detect_high(chip)) {
|
||||
pr_smb(PR_MISC, "src det low after 500mS sleep\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* reduce input current limit to 300mA */
|
||||
pr_smb(PR_MISC, "Reduce mA = 300\n");
|
||||
mutex_lock(&chip->current_change_lock);
|
||||
chip->target_fastchg_current_ma = 300;
|
||||
rc = smbchg_set_thermal_limited_usb_current_max(chip,
|
||||
chip->target_fastchg_current_ma);
|
||||
mutex_unlock(&chip->current_change_lock);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't set usb current rc=%d continuing\n", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_smb(PR_MISC, "Disable AICL\n");
|
||||
smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
|
||||
AICL_EN_BIT, 0);
|
||||
|
||||
chip->hvdcp_3_det_ignore_uv = true;
|
||||
|
||||
/* re-run APSD */
|
||||
rc = rerun_apsd(chip);
|
||||
if (rc) {
|
||||
pr_err("APSD rerun failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
chip->hvdcp_3_det_ignore_uv = false;
|
||||
|
||||
pr_smb(PR_MISC, "Enable AICL\n");
|
||||
smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
|
||||
AICL_EN_BIT, AICL_EN_BIT);
|
||||
/*
|
||||
* DCP will switch to HVDCP in this time by removing the short
|
||||
* between DP DM
|
||||
*/
|
||||
msleep(HVDCP_NOTIFY_MS);
|
||||
/*
|
||||
* Check if the same hvdcp session is in progress. src_det should be
|
||||
* high and the usb type should be none since APSD was disabled
|
||||
*/
|
||||
if (!is_src_detect_high(chip)) {
|
||||
pr_smb(PR_MISC, "src det low after 2s sleep\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We are set if HVDCP in 5V continuous mode */
|
||||
if (!is_hvdcp_5v_cont_mode(chip)) {
|
||||
pr_err("HVDCP could not be set in 5V continuous mode\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
chip->hvdcp_3_det_ignore_uv = false;
|
||||
restore_from_hvdcp_detection(chip);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -4655,13 +4819,39 @@ static int smbchg_unprepare_for_pulsing_lite(struct smbchg_chip *chip)
|
|||
{
|
||||
int rc = 0;
|
||||
|
||||
pr_smb(PR_MISC, "Forcing 9V HVDCP 2.0\n");
|
||||
rc = force_9v_hvdcp(chip);
|
||||
if (rc) {
|
||||
pr_err("Failed to force 9V HVDCP=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Reset the input current limit */
|
||||
pr_smb(PR_MISC, "Reset ICL\n");
|
||||
mutex_lock(&chip->current_change_lock);
|
||||
chip->usb_target_current_ma = DEFAULT_WALL_CHG_MA;
|
||||
rc = smbchg_set_thermal_limited_usb_current_max(chip,
|
||||
chip->usb_target_current_ma);
|
||||
mutex_unlock(&chip->current_change_lock);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't set usb current rc=%d continuing\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define CMD_HVDCP_2 0x43
|
||||
#define SINGLE_INCREMENT BIT(0)
|
||||
#define SINGLE_DECREMENT BIT(1)
|
||||
static int smbchg_dp_pulse_lite(struct smbchg_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
pr_smb(PR_MISC, "Increment DP\n");
|
||||
rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_HVDCP_2,
|
||||
SINGLE_INCREMENT, SINGLE_INCREMENT);
|
||||
if (rc)
|
||||
pr_err("Single-increment failed rc=%d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -4669,6 +4859,12 @@ static int smbchg_dm_pulse_lite(struct smbchg_chip *chip)
|
|||
{
|
||||
int rc = 0;
|
||||
|
||||
pr_smb(PR_MISC, "Decrement DM\n");
|
||||
rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_HVDCP_2,
|
||||
SINGLE_DECREMENT, SINGLE_DECREMENT);
|
||||
if (rc)
|
||||
pr_err("Single-decrement failed rc=%d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -4737,6 +4933,10 @@ static int smbchg_dp_dm(struct smbchg_chip *chip, int val)
|
|||
chip->pulse_cnt--;
|
||||
pr_smb(PR_MISC, "pulse_cnt = %d\n", chip->pulse_cnt);
|
||||
break;
|
||||
case POWER_SUPPLY_DP_DM_HVDCP3_SUPPORTED:
|
||||
chip->hvdcp3_supported = true;
|
||||
pr_smb(PR_MISC, "HVDCP3 supported\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -5608,7 +5808,6 @@ static inline int get_bpd(const char *name)
|
|||
#define RECHG_THRESHOLD_SRC_BIT BIT(1)
|
||||
#define TERM_I_SRC_BIT BIT(2)
|
||||
#define TERM_SRC_FG BIT(2)
|
||||
#define CHGR_CFG2 0xFC
|
||||
#define CHG_INHIB_CFG_REG 0xF7
|
||||
#define CHG_INHIBIT_50MV_VAL 0x00
|
||||
#define CHG_INHIBIT_100MV_VAL 0x01
|
||||
|
@ -5616,9 +5815,11 @@ static inline int get_bpd(const char *name)
|
|||
#define CHG_INHIBIT_300MV_VAL 0x03
|
||||
#define CHG_INHIBIT_MASK 0x03
|
||||
#define USE_REGISTER_FOR_CURRENT BIT(2)
|
||||
#define CHGR_CFG2 0xFC
|
||||
#define CHG_EN_SRC_BIT BIT(7)
|
||||
#define CHG_EN_COMMAND_BIT BIT(6)
|
||||
#define P2F_CHG_TRAN BIT(5)
|
||||
#define CHG_BAT_OV_ECC BIT(4)
|
||||
#define I_TERM_BIT BIT(3)
|
||||
#define AUTO_RECHG_BIT BIT(2)
|
||||
#define CHARGER_INHIBIT_BIT BIT(0)
|
||||
|
@ -5660,6 +5861,50 @@ static inline int get_bpd(const char *name)
|
|||
#define APSD_RERUN_BIT BIT(0)
|
||||
#define OTG_OC_CFG 0xF1
|
||||
#define HICCUP_ENABLED_BIT BIT(6)
|
||||
static void batt_ov_wa_check(struct smbchg_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
u8 reg;
|
||||
|
||||
/* disable-'battery OV disables charging' feature */
|
||||
rc = smbchg_sec_masked_write(chip, chip->chgr_base + CHGR_CFG2,
|
||||
CHG_BAT_OV_ECC, 0);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Couldn't set chgr_cfg2 rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* if battery OV is set:
|
||||
* restart charging by disable/enable charging
|
||||
*/
|
||||
rc = smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Couldn't read Battery RT status rc = %d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reg & BAT_OV_BIT) {
|
||||
rc = smbchg_charging_en(chip, false);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Couldn't disable charging: rc = %d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* delay for charging-disable to take affect */
|
||||
msleep(200);
|
||||
|
||||
rc = smbchg_charging_en(chip, true);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Couldn't enable charging: rc = %d\n", rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int smbchg_hw_init(struct smbchg_chip *chip)
|
||||
{
|
||||
int rc, i;
|
||||
|
@ -6024,6 +6269,9 @@ static int smbchg_hw_init(struct smbchg_chip *chip)
|
|||
rc);
|
||||
}
|
||||
|
||||
if (chip->wa_flags & SMBCHG_BATT_OV_WA)
|
||||
batt_ov_wa_check(chip);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -6238,8 +6486,6 @@ static int smb_parse_dt(struct smbchg_chip *chip)
|
|||
"qcom,low-volt-dcin");
|
||||
chip->force_aicl_rerun = of_property_read_bool(node,
|
||||
"qcom,force-aicl-rerun");
|
||||
chip->enable_hvdcp_9v = of_property_read_bool(node,
|
||||
"qcom,enable-hvdcp-9v");
|
||||
|
||||
/* parse the battery missing detection pin source */
|
||||
rc = of_property_read_string(chip->spmi->dev.of_node,
|
||||
|
@ -6675,8 +6921,10 @@ static int smbchg_wa_config(struct smbchg_chip *chip)
|
|||
|
||||
switch (pmic_rev_id->pmic_subtype) {
|
||||
case PMI8994:
|
||||
chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA;
|
||||
chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA
|
||||
| SMBCHG_BATT_OV_WA;
|
||||
case PMI8950:
|
||||
chip->wa_flags |= SMBCHG_BATT_OV_WA;
|
||||
if (pmic_rev_id->rev4 < 2) /* PMI8950 1.0 */ {
|
||||
chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA;
|
||||
} else { /* rev > PMI8950 v1.0 */
|
||||
|
|
|
@ -279,6 +279,13 @@ struct cpr_regulator {
|
|||
int *save_ctl;
|
||||
int *save_irq;
|
||||
|
||||
int *vsens_corner_map;
|
||||
/* vsens status */
|
||||
bool vsens_enabled;
|
||||
/* vsens regulators */
|
||||
struct regulator *vdd_vsens_corner;
|
||||
struct regulator *vdd_vsens_voltage;
|
||||
|
||||
/* Config parameters */
|
||||
bool enable;
|
||||
u32 ref_clk_khz;
|
||||
|
@ -703,12 +710,20 @@ static int cpr_scale_voltage(struct cpr_regulator *cpr_vreg, int corner,
|
|||
{
|
||||
int rc = 0, vdd_mx_vmin = 0;
|
||||
int mem_acc_corner = cpr_vreg->mem_acc_corner_map[corner];
|
||||
int apc_corner;
|
||||
int fuse_corner = cpr_vreg->corner_map[corner];
|
||||
int apc_corner, vsens_corner;
|
||||
|
||||
/* Determine the vdd_mx voltage */
|
||||
if (dir != NO_CHANGE && cpr_vreg->vdd_mx != NULL)
|
||||
vdd_mx_vmin = cpr_mx_get(cpr_vreg, corner, new_apc_volt);
|
||||
|
||||
|
||||
if (cpr_vreg->vdd_vsens_voltage && cpr_vreg->vsens_enabled) {
|
||||
rc = regulator_disable(cpr_vreg->vdd_vsens_voltage);
|
||||
if (!rc)
|
||||
cpr_vreg->vsens_enabled = false;
|
||||
}
|
||||
|
||||
if (dir == DOWN) {
|
||||
if (!rc && cpr_vreg->mem_acc_vreg)
|
||||
rc = regulator_set_voltage(cpr_vreg->mem_acc_vreg,
|
||||
|
@ -750,6 +765,22 @@ static int cpr_scale_voltage(struct cpr_regulator *cpr_vreg, int corner,
|
|||
rc = cpr_mx_set(cpr_vreg, corner, vdd_mx_vmin);
|
||||
}
|
||||
|
||||
if (!rc && cpr_vreg->vdd_vsens_corner) {
|
||||
vsens_corner = cpr_vreg->vsens_corner_map[fuse_corner];
|
||||
rc = regulator_set_voltage(cpr_vreg->vdd_vsens_corner,
|
||||
vsens_corner, vsens_corner);
|
||||
}
|
||||
if (!rc && cpr_vreg->vdd_vsens_voltage) {
|
||||
rc = regulator_set_voltage(cpr_vreg->vdd_vsens_voltage,
|
||||
cpr_vreg->floor_volt[corner],
|
||||
cpr_vreg->ceiling_volt[corner]);
|
||||
if (!rc && !cpr_vreg->vsens_enabled) {
|
||||
rc = regulator_enable(cpr_vreg->vdd_vsens_voltage);
|
||||
if (!rc)
|
||||
cpr_vreg->vsens_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -4208,6 +4239,70 @@ static int cpr_rpm_apc_init(struct platform_device *pdev,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int cpr_vsens_init(struct platform_device *pdev,
|
||||
struct cpr_regulator *cpr_vreg)
|
||||
{
|
||||
int rc = 0, len = 0;
|
||||
struct device_node *of_node = pdev->dev.of_node;
|
||||
|
||||
if (of_find_property(of_node, "vdd-vsens-voltage-supply", NULL)) {
|
||||
cpr_vreg->vdd_vsens_voltage = devm_regulator_get(&pdev->dev,
|
||||
"vdd-vsens-voltage");
|
||||
if (IS_ERR_OR_NULL(cpr_vreg->vdd_vsens_voltage)) {
|
||||
rc = PTR_ERR(cpr_vreg->vdd_vsens_voltage);
|
||||
cpr_vreg->vdd_vsens_voltage = NULL;
|
||||
if (rc == -EPROBE_DEFER)
|
||||
return rc;
|
||||
/* device not found */
|
||||
cpr_debug(cpr_vreg, "regulator_get: vdd-vsens-voltage: rc=%d\n",
|
||||
rc);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (of_find_property(of_node, "vdd-vsens-corner-supply", NULL)) {
|
||||
cpr_vreg->vdd_vsens_corner = devm_regulator_get(&pdev->dev,
|
||||
"vdd-vsens-corner");
|
||||
if (IS_ERR_OR_NULL(cpr_vreg->vdd_vsens_corner)) {
|
||||
rc = PTR_ERR(cpr_vreg->vdd_vsens_corner);
|
||||
cpr_vreg->vdd_vsens_corner = NULL;
|
||||
if (rc == -EPROBE_DEFER)
|
||||
return rc;
|
||||
/* device not found */
|
||||
cpr_debug(cpr_vreg, "regulator_get: vdd-vsens-corner: rc=%d\n",
|
||||
rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!of_find_property(of_node, "qcom,vsens-corner-map", &len)) {
|
||||
cpr_err(cpr_vreg, "qcom,vsens-corner-map missing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len != cpr_vreg->num_fuse_corners * sizeof(u32)) {
|
||||
cpr_err(cpr_vreg, "qcom,vsens-corner-map length=%d is invalid: required:%d\n",
|
||||
len, cpr_vreg->num_fuse_corners);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cpr_vreg->vsens_corner_map = devm_kcalloc(&pdev->dev,
|
||||
(cpr_vreg->num_fuse_corners + 1),
|
||||
sizeof(*cpr_vreg->vsens_corner_map), GFP_KERNEL);
|
||||
if (!cpr_vreg->vsens_corner_map)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = of_property_read_u32_array(of_node,
|
||||
"qcom,vsens-corner-map",
|
||||
&cpr_vreg->vsens_corner_map[1],
|
||||
cpr_vreg->num_fuse_corners);
|
||||
if (rc)
|
||||
cpr_err(cpr_vreg, "read qcom,vsens-corner-map failed, rc = %d\n",
|
||||
rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cpr_init_cpr(struct platform_device *pdev,
|
||||
struct cpr_regulator *cpr_vreg)
|
||||
{
|
||||
|
@ -5024,6 +5119,13 @@ static int cpr_regulator_probe(struct platform_device *pdev)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
rc = cpr_vsens_init(pdev, cpr_vreg);
|
||||
if (rc) {
|
||||
cpr_err(cpr_vreg, "Initialize vsens configuration failed rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cpr_apc_init(pdev, cpr_vreg);
|
||||
if (rc) {
|
||||
if (rc != -EPROBE_DEFER)
|
||||
|
|
|
@ -686,6 +686,17 @@ config TRACER_PKT
|
|||
processor communication protocols. The profiling information
|
||||
can be logged into the tracer packet itself.
|
||||
|
||||
config MSM_VSENS
|
||||
bool "Voltage Sensor Monitoring"
|
||||
help
|
||||
Enable support for Voltage Sensing Block available on certain MSM
|
||||
chipsets. Voltage Sensing Block monitors the voltage at certain points
|
||||
in the chip and makes recent readings available via FIFO registers.
|
||||
It can also be configured to trigger an interrupt when a min or max threshold is
|
||||
crossed.
|
||||
|
||||
Say yes to support these devices.
|
||||
|
||||
source "drivers/soc/qcom/memshare/Kconfig"
|
||||
|
||||
endif # ARCH_MSM
|
||||
|
|
|
@ -91,3 +91,4 @@ obj-$(CONFIG_QCOM_EARLY_RANDOM) += early_random.o
|
|||
obj-$(CONFIG_MSM_PACMAN) += msm_pacman.o
|
||||
obj-$(CONFIG_MSM_TEST_PACMAN) += msm_test_pacman.o
|
||||
obj-$(CONFIG_TRACER_PKT) += tracer_pkt.o
|
||||
obj-$(CONFIG_MSM_VSENS) += vsens.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,6 +30,7 @@
|
|||
#include "swr-wcd-ctrl.h"
|
||||
|
||||
#define SWR_AUTO_SUSPEND_DELAY_MS 3000 /* delay in msec */
|
||||
#define SWR_DEV_ID_MASK 0xFFFFFFFF
|
||||
|
||||
static u8 mstr_ports[] = {100, 101, 102, 103, 104, 105, 106, 107};
|
||||
static u8 mstr_port_type[] = {SWR_DAC_PORT, SWR_COMP_PORT, SWR_BOOST_PORT,
|
||||
|
@ -908,6 +909,8 @@ static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id,
|
|||
SWRM_ENUMERATOR_SLAVE_DEV_ID_2(i))) << 32);
|
||||
id |= swrm->read(swrm->handle,
|
||||
SWRM_ENUMERATOR_SLAVE_DEV_ID_1(i));
|
||||
id = id & SWR_DEV_ID_MASK;
|
||||
|
||||
if (i == 1)
|
||||
id_0 = id;
|
||||
|
||||
|
@ -953,7 +956,7 @@ static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id,
|
|||
ret = 0;
|
||||
goto found;
|
||||
}
|
||||
} else if ((id = 0x21170214)) {
|
||||
} else if ((id == 0x21170214)) {
|
||||
dev_err(swrm->dev, "%s: device id 0x%llx expected to match with 0x%llx\n",
|
||||
__func__, id, dev_id);
|
||||
|
||||
|
|
|
@ -3326,6 +3326,12 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
|
|||
}
|
||||
}
|
||||
|
||||
if (ep->endless && udc->gadget.speed == USB_SPEED_FULL) {
|
||||
err("Queueing endless req is not supported for FS");
|
||||
retval = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* first nuke then test link, e.g. previous status has not sent */
|
||||
if (!list_empty(&mReq->queue)) {
|
||||
retval = -EBUSY;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/f_mtp.h>
|
||||
|
||||
#define MTP_RX_BUFFER_INIT_SIZE 1048576
|
||||
#define MTP_BULK_BUFFER_SIZE 16384
|
||||
#define INTR_BUFFER_SIZE 28
|
||||
|
||||
|
@ -71,7 +72,7 @@
|
|||
|
||||
#define MAX_ITERATION 100
|
||||
|
||||
unsigned int mtp_rx_req_len = MTP_BULK_BUFFER_SIZE;
|
||||
unsigned int mtp_rx_req_len = MTP_RX_BUFFER_INIT_SIZE;
|
||||
module_param(mtp_rx_req_len, uint, S_IRUGO | S_IWUSR);
|
||||
|
||||
unsigned int mtp_tx_req_len = MTP_BULK_BUFFER_SIZE;
|
||||
|
|
|
@ -1293,7 +1293,8 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
ncm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
|
||||
if (!ncm->notify_req)
|
||||
goto fail;
|
||||
ncm->notify_req->buf = kmalloc(NCM_STATUS_BYTECOUNT, GFP_KERNEL);
|
||||
ncm->notify_req->buf = kmalloc(NCM_STATUS_BYTECOUNT
|
||||
+ (cdev->gadget->extra_buf_alloc), GFP_KERNEL);
|
||||
if (!ncm->notify_req->buf)
|
||||
goto fail;
|
||||
ncm->notify_req->context = ncm;
|
||||
|
|
|
@ -820,7 +820,8 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
skb = req->context;
|
||||
/* Is aggregation already enabled and buffers allocated ? */
|
||||
if (dev->port_usb->multi_pkt_xfer && dev->tx_req_bufsize) {
|
||||
req->buf = kzalloc(dev->tx_req_bufsize, GFP_ATOMIC);
|
||||
req->buf = kzalloc(dev->tx_req_bufsize
|
||||
+ dev->gadget->extra_buf_alloc, GFP_ATOMIC);
|
||||
req->context = NULL;
|
||||
} else {
|
||||
req->buf = NULL;
|
||||
|
@ -859,8 +860,8 @@ static int alloc_tx_buffer(struct eth_dev *dev)
|
|||
list_for_each(act, &dev->tx_reqs) {
|
||||
req = container_of(act, struct usb_request, list);
|
||||
if (!req->buf) {
|
||||
req->buf = kzalloc(dev->tx_req_bufsize,
|
||||
GFP_ATOMIC);
|
||||
req->buf = kzalloc(dev->tx_req_bufsize
|
||||
+ dev->gadget->extra_buf_alloc, GFP_ATOMIC);
|
||||
if (!req->buf)
|
||||
goto free_buf;
|
||||
}
|
||||
|
|
|
@ -1654,8 +1654,10 @@ phcd_retry:
|
|||
}
|
||||
|
||||
if (device_may_wakeup(phy->dev)) {
|
||||
enable_irq_wake(motg->async_irq);
|
||||
enable_irq_wake(motg->irq);
|
||||
if (host_bus_suspend || device_bus_suspend) {
|
||||
enable_irq_wake(motg->async_irq);
|
||||
enable_irq_wake(motg->irq);
|
||||
}
|
||||
|
||||
if (motg->phy_irq)
|
||||
enable_irq_wake(motg->phy_irq);
|
||||
|
@ -1858,8 +1860,10 @@ skip_phy_resume:
|
|||
}
|
||||
|
||||
if (device_may_wakeup(phy->dev)) {
|
||||
disable_irq_wake(motg->async_irq);
|
||||
disable_irq_wake(motg->irq);
|
||||
if (motg->host_bus_suspend || motg->device_bus_suspend) {
|
||||
disable_irq_wake(motg->async_irq);
|
||||
disable_irq_wake(motg->irq);
|
||||
}
|
||||
|
||||
if (motg->phy_irq)
|
||||
disable_irq_wake(motg->phy_irq);
|
||||
|
@ -6191,7 +6195,7 @@ static int msm_otg_probe(struct platform_device *pdev)
|
|||
* pull-down during suspend without any additional
|
||||
* hardware re-work.
|
||||
*/
|
||||
if (motg->pdata->phy_dvdd_always_on)
|
||||
if (motg->pdata->phy_type == SNPS_FEMTO_PHY)
|
||||
motg->caps |= ALLOW_BUS_SUSPEND_WITHOUT_REWORK;
|
||||
|
||||
wake_lock(&motg->wlock);
|
||||
|
|
|
@ -444,6 +444,17 @@ int mdss_dba_utils_video_on(void *data, struct mdss_panel_info *pinfo)
|
|||
video_cfg.pclk_khz = pinfo->clk_rate / 1000;
|
||||
video_cfg.hdmi_mode = hdmi_edid_get_sink_mode(ud->edid_data);
|
||||
|
||||
/* Calculate number of DSI lanes configured */
|
||||
video_cfg.num_of_input_lanes = 0;
|
||||
if (pinfo->mipi.data_lane0)
|
||||
video_cfg.num_of_input_lanes++;
|
||||
if (pinfo->mipi.data_lane1)
|
||||
video_cfg.num_of_input_lanes++;
|
||||
if (pinfo->mipi.data_lane2)
|
||||
video_cfg.num_of_input_lanes++;
|
||||
if (pinfo->mipi.data_lane3)
|
||||
video_cfg.num_of_input_lanes++;
|
||||
|
||||
if (ud->ops.video_on)
|
||||
ret = ud->ops.video_on(ud->dba_data, true, &video_cfg, 0);
|
||||
|
||||
|
|
|
@ -2069,6 +2069,30 @@ static void mdss_dsi_dba_work(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
static int mdss_dsi_check_params(struct mdss_dsi_ctrl_pdata *ctrl, void *arg)
|
||||
{
|
||||
struct mdss_panel_info *reconf_pinfo, *pinfo;
|
||||
int rc = 0;
|
||||
|
||||
if (!ctrl || !arg)
|
||||
return 0;
|
||||
|
||||
pinfo = &ctrl->panel_data.panel_info;
|
||||
if (!pinfo->is_pluggable)
|
||||
return 0;
|
||||
|
||||
reconf_pinfo = (struct mdss_panel_info *)arg;
|
||||
|
||||
pr_debug("%s: reconfig xres: %d yres: %d, current xres: %d yres: %d\n",
|
||||
__func__, reconf_pinfo->xres, reconf_pinfo->yres,
|
||||
pinfo->xres, pinfo->yres);
|
||||
if ((reconf_pinfo->xres != pinfo->xres) ||
|
||||
(reconf_pinfo->yres != pinfo->yres))
|
||||
rc = 1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
|
||||
int event, void *arg)
|
||||
{
|
||||
|
@ -2091,6 +2115,8 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
|
|||
switch (event) {
|
||||
case MDSS_EVENT_CHECK_PARAMS:
|
||||
pr_debug("%s:Entered Case MDSS_EVENT_CHECK_PARAMS\n", __func__);
|
||||
if (mdss_dsi_check_params(ctrl_pdata, arg))
|
||||
rc = 1;
|
||||
ctrl_pdata->refresh_clk_rate = true;
|
||||
break;
|
||||
case MDSS_EVENT_LINK_READY:
|
||||
|
|
|
@ -280,6 +280,7 @@ struct msm_fb_data_type {
|
|||
void *cursor_buf;
|
||||
phys_addr_t cursor_buf_phys;
|
||||
dma_addr_t cursor_buf_iova;
|
||||
size_t cursor_buf_size;
|
||||
|
||||
int ext_ad_ctrl;
|
||||
u32 ext_bl_ctrl;
|
||||
|
|
|
@ -2476,10 +2476,17 @@ static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
|
|||
goto parse_fail;
|
||||
|
||||
rc = mdss_mdp_parse_dt_handler(pdev,
|
||||
"qcom,mdss-pipe-dma-xin-id", xin_id,
|
||||
"qcom,mdss-pipe-cursor-xin-id", xin_id,
|
||||
mdata->ncursor_pipes);
|
||||
if (rc)
|
||||
goto parse_fail;
|
||||
|
||||
rc = mdss_mdp_parse_dt_pipe_clk_ctrl(pdev,
|
||||
"qcom,mdss-pipe-cursor-clk-ctrl-offsets",
|
||||
mdata->cursor_pipes, mdata->ncursor_pipes);
|
||||
if (rc)
|
||||
goto parse_fail;
|
||||
|
||||
/* set the fetch id to an invalid value */
|
||||
for (i = 0; i < mdata->ncursor_pipes; i++)
|
||||
ftch_id[i] = -1;
|
||||
|
|
|
@ -707,7 +707,9 @@ int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
|
|||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (IS_RIGHT_MIXER_OV(req->flags, req->dst_rect.x, left_lm_w))
|
||||
if (IS_RIGHT_MIXER_OV(req->flags, req->dst_rect.x, left_lm_w)
|
||||
&& !(req->pipe_type == MDSS_MDP_PIPE_TYPE_CURSOR
|
||||
&& is_split_lm(mfd)))
|
||||
mixer_mux = MDSS_MDP_MIXER_MUX_RIGHT;
|
||||
else
|
||||
mixer_mux = MDSS_MDP_MIXER_MUX_LEFT;
|
||||
|
@ -1129,6 +1131,9 @@ exit_fail:
|
|||
|
||||
/* invalidate any overlays in this framebuffer after failure */
|
||||
list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
|
||||
if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR)
|
||||
continue;
|
||||
|
||||
pr_debug("freeing allocations for pipe %d\n", pipe->num);
|
||||
mdss_mdp_smp_unreserve(pipe);
|
||||
pipe->params_changed = 0;
|
||||
|
@ -1652,7 +1657,9 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
|
|||
pipe->num);
|
||||
mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
|
||||
mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
|
||||
pipe->dirty = true;
|
||||
|
||||
if (pipe->type != MDSS_MDP_PIPE_TYPE_CURSOR)
|
||||
pipe->dirty = true;
|
||||
|
||||
if (buf)
|
||||
__pipe_buf_mark_cleanup(mfd, buf);
|
||||
|
@ -3204,13 +3211,13 @@ int mdss_mdp_cursor_flush(struct msm_fb_data_type *mfd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mdss_mdp_cursor_pipe_setup(struct msm_fb_data_type *mfd,
|
||||
struct mdp_overlay *req, int cursor_pipe) {
|
||||
static int mdss_mdp_cursor_pipe_setup(struct msm_fb_data_type *mfd,
|
||||
struct mdp_overlay *req, int cursor_pipe,
|
||||
struct ion_handle *ion_handle, dma_addr_t iova, size_t size)
|
||||
{
|
||||
struct mdss_mdp_pipe *pipe;
|
||||
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
|
||||
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
|
||||
int ret = 0;
|
||||
u32 cursor_addr;
|
||||
struct mdss_mdp_data *buf = NULL;
|
||||
|
||||
req->id = mdp5_data->cursor_ndx[cursor_pipe];
|
||||
|
@ -3225,29 +3232,29 @@ int mdss_mdp_cursor_pipe_setup(struct msm_fb_data_type *mfd,
|
|||
pr_debug("req id:%d cursor_pipe:%d pnum:%d\n",
|
||||
req->id, cursor_pipe, pipe->ndx);
|
||||
|
||||
if (mdata->mdss_util->iommu_attached()) {
|
||||
cursor_addr = mfd->cursor_buf_iova;
|
||||
} else {
|
||||
if (MDSS_LPAE_CHECK(mfd->cursor_buf_phys)) {
|
||||
pr_err("can't access phy mem >4GB w/o iommu\n");
|
||||
ret = -ERANGE;
|
||||
if (iova) {
|
||||
buf = mdss_mdp_overlay_buf_alloc(mfd, pipe);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
mdp5_data->cursor_ndx[cursor_pipe] = pipe->ndx;
|
||||
buf->p[0].addr = iova;
|
||||
buf->p[0].srcp_ihdl = ion_handle;
|
||||
buf->p[0].len = size;
|
||||
buf->p[0].mapped = true;
|
||||
buf->num_planes = 1;
|
||||
buf->state = MDP_BUF_STATE_ACTIVE;
|
||||
} else if (!(req->flags & MDP_SOLID_FILL)) {
|
||||
buf = list_first_entry_or_null(&pipe->buf_queue,
|
||||
struct mdss_mdp_data, pipe_list);
|
||||
if (!buf) {
|
||||
pr_err("cursor pipe buf empty\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
cursor_addr = mfd->cursor_buf_phys;
|
||||
}
|
||||
|
||||
buf = mdss_mdp_overlay_buf_alloc(mfd, pipe);
|
||||
if (!buf) {
|
||||
pr_err("unable to allocate memory for cursor buffer\n");
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
mdp5_data->cursor_ndx[cursor_pipe] = pipe->ndx;
|
||||
buf->p[0].addr = cursor_addr;
|
||||
buf->p[0].len = mdss_mdp_get_cursor_frame_size(mdata);
|
||||
buf->num_planes = 1;
|
||||
|
||||
buf->state = MDP_BUF_STATE_ACTIVE;
|
||||
if (!(req->flags & MDP_SOLID_FILL))
|
||||
ret = mdss_mdp_pipe_queue_data(pipe, buf);
|
||||
else
|
||||
|
@ -3274,16 +3281,18 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
struct fb_image *img = &cursor->image;
|
||||
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
|
||||
struct mdp_overlay *req = NULL;
|
||||
struct mdss_rect roi;
|
||||
struct mdss_rect roi, src_crop;
|
||||
int ret = 0;
|
||||
struct fb_var_screeninfo *var = &mfd->fbi->var;
|
||||
u32 xres = var->xres;
|
||||
u32 yres = var->yres;
|
||||
u32 start_x = img->dx;
|
||||
u32 start_y = img->dy;
|
||||
u32 left_lm_w = left_lm_w_from_mfd(mfd);
|
||||
u32 cursor_frame_size = mdss_mdp_get_cursor_frame_size(mdata);
|
||||
u32 input_frame_size = img->width * img->height * 4;
|
||||
struct ion_handle *ion_handle = NULL;
|
||||
void *cursor_buf = NULL;
|
||||
struct ion_client *ion_client = mdss_get_ionclient();
|
||||
size_t size = 0;
|
||||
dma_addr_t iova = 0;
|
||||
unsigned long buf_size = 0;
|
||||
|
||||
ret = mutex_lock_interruptible(&mdp5_data->ov_lock);
|
||||
if (ret)
|
||||
|
@ -3294,15 +3303,10 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (input_frame_size > cursor_frame_size) {
|
||||
pr_err("Input frame bigger than max cursor size\n");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!cursor->enable) {
|
||||
mdss_mdp_curor_pipe_cleanup(mfd, CURSOR_PIPE_LEFT);
|
||||
mdss_mdp_curor_pipe_cleanup(mfd, CURSOR_PIPE_RIGHT);
|
||||
mfd->cursor_buf_size = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -3312,29 +3316,76 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (!mfd->cursor_buf && (cursor->set & FB_CUR_SETIMAGE)) {
|
||||
mfd->cursor_buf = dma_alloc_coherent(&mfd->pdev->dev,
|
||||
cursor_frame_size, (dma_addr_t *)
|
||||
&mfd->cursor_buf_phys, GFP_KERNEL);
|
||||
if (!mfd->cursor_buf) {
|
||||
pr_err("can't allocate cursor buffer\n");
|
||||
ret = -ENOMEM;
|
||||
/*
|
||||
* image width/height and src crop width/height are packed with
|
||||
* img->width/height and src crop x/y is passed through hotx/hoty
|
||||
* when using our HAL is used.
|
||||
*/
|
||||
if (img->width & 0xffff0000) {
|
||||
src_crop = (struct mdss_rect) {cursor->hot.x, cursor->hot.y,
|
||||
img->width >> 16, img->height >> 16};
|
||||
img->width &= 0x0000ffff;
|
||||
img->height &= 0x0000ffff;
|
||||
cursor->hot.x = 0;
|
||||
cursor->hot.y = 0;
|
||||
} else {
|
||||
src_crop = (struct mdss_rect) {0, 0, img->width, img->height};
|
||||
}
|
||||
|
||||
if ((src_crop.w > mdata->max_cursor_size) ||
|
||||
(src_crop.h > mdata->max_cursor_size) || (img->depth != 32) ||
|
||||
(start_x >= var->xres) || (start_y >= var->yres)) {
|
||||
pr_debug("start_x:%d, start_y:%d, src_crop{%d,%d,%d,%d} img->depth:%d\n",
|
||||
start_x, start_y, src_crop.x, src_crop.y,
|
||||
src_crop.w, src_crop.h, img->depth);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
size = img->width * img->height * 4;
|
||||
if (size != mfd->cursor_buf_size) {
|
||||
pr_debug("allocating cursor mem size:%zd\n", size);
|
||||
|
||||
if (!ion_client) {
|
||||
pr_err("ion client is not defined\n");
|
||||
ret = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = msm_iommu_map_contig_buffer(mfd->cursor_buf_phys,
|
||||
mdss_get_iommu_domain(MDSS_IOMMU_DOMAIN_UNSECURE),
|
||||
0, cursor_frame_size, SZ_4K, 0,
|
||||
&(mfd->cursor_buf_iova));
|
||||
if (IS_ERR_VALUE(ret)) {
|
||||
dma_free_coherent(&mfd->pdev->dev, cursor_frame_size,
|
||||
mfd->cursor_buf,
|
||||
(dma_addr_t) mfd->cursor_buf_phys);
|
||||
pr_err("unable to map cursor buffer to iommu(%d)\n",
|
||||
ret);
|
||||
ion_handle = ion_alloc(ion_client, size, SZ_4K,
|
||||
ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
|
||||
if (IS_ERR_OR_NULL(ion_handle)) {
|
||||
ret = PTR_ERR(ion_handle);
|
||||
pr_err("unable to alloc cursor mem from ion - %d\n",
|
||||
ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = ion_map_iommu(ion_client, ion_handle,
|
||||
mdss_get_iommu_domain(MDSS_IOMMU_DOMAIN_UNSECURE),
|
||||
0, SZ_4K, 0, &iova, &buf_size, 0, 0);
|
||||
if (IS_ERR_VALUE(ret)) {
|
||||
pr_err("cannot map cursor to IOMMU. ret=%d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
cursor_buf = ion_map_kernel(ion_client, ion_handle);
|
||||
if (IS_ERR_OR_NULL(cursor_buf)) {
|
||||
ret = PTR_ERR(cursor_buf);
|
||||
pr_err("cursor ION memory mapping failed - %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = copy_from_user(cursor_buf, img->data, size);
|
||||
if (ret) {
|
||||
pr_err("copy from user failed for cursor data\n");
|
||||
ret = -EFAULT;
|
||||
ion_unmap_kernel(ion_client, ion_handle);
|
||||
goto done;
|
||||
}
|
||||
ion_unmap_kernel(ion_client, ion_handle);
|
||||
mfd->cursor_buf_size = size;
|
||||
|
||||
mixer->cursor_hotx = 0;
|
||||
mixer->cursor_hoty = 0;
|
||||
}
|
||||
|
@ -3343,8 +3394,8 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
cursor->set);
|
||||
|
||||
if (cursor->set & FB_CUR_SETHOT) {
|
||||
if ((cursor->hot.x < img->width) &&
|
||||
(cursor->hot.y < img->height)) {
|
||||
if ((cursor->hot.x < src_crop.w) &&
|
||||
(cursor->hot.y < src_crop.h)) {
|
||||
mixer->cursor_hotx = cursor->hot.x;
|
||||
mixer->cursor_hoty = cursor->hot.y;
|
||||
/* Update cursor position */
|
||||
|
@ -3356,6 +3407,10 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
}
|
||||
}
|
||||
|
||||
pr_debug("src_crop{%d,%d,%d,%d}, img->width:%d, img->height:%d, hotx:%d, hoty:%d\n",
|
||||
src_crop.x, src_crop.y, src_crop.w, src_crop.h,
|
||||
img->width, img->height, cursor->hot.x, cursor->hot.y);
|
||||
|
||||
memset(&roi, 0, sizeof(struct mdss_rect));
|
||||
if (start_x > mixer->cursor_hotx) {
|
||||
start_x -= mixer->cursor_hotx;
|
||||
|
@ -3370,15 +3425,10 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
start_y = 0;
|
||||
}
|
||||
|
||||
roi.w = min(xres - start_x, img->width - roi.x);
|
||||
roi.h = min(yres - start_y, img->height - roi.y);
|
||||
|
||||
if ((roi.w > mdata->max_cursor_size) ||
|
||||
(roi.h > mdata->max_cursor_size) ||
|
||||
(img->depth != 32) || (start_x >= xres) || (start_y >= yres)) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
roi.w = min_t(u32, (var->xres - start_x), (src_crop.w - roi.x));
|
||||
roi.h = min_t(u32, (var->yres - start_y), (src_crop.h - roi.y));
|
||||
roi.x += src_crop.x;
|
||||
roi.y += src_crop.y;
|
||||
|
||||
req = kzalloc(sizeof(struct mdp_overlay), GFP_KERNEL);
|
||||
if (!req) {
|
||||
|
@ -3396,6 +3446,9 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
|
||||
mdss_mdp_set_rect(&req->src_rect, roi.x, roi.y, roi.w, roi.h);
|
||||
mdss_mdp_set_rect(&req->dst_rect, start_x, start_y, roi.w, roi.h);
|
||||
pr_debug("src{%d,%d,%d,%d}, dst{%d,%d,%d,%d}\n",
|
||||
roi.x, roi.y, roi.w, roi.h,
|
||||
start_x, start_y, roi.w, roi.h);
|
||||
|
||||
req->bg_color = img->bg_color;
|
||||
req->alpha = (img->fg_color >> ((32 - var->transp.offset) - 8)) & 0xff;
|
||||
|
@ -3405,18 +3458,6 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
req->blend_op = BLEND_OP_COVERAGE;
|
||||
req->transp_mask = img->bg_color & ~(0xff << var->transp.offset);
|
||||
|
||||
if (mfd->cursor_buf && (cursor->set & FB_CUR_SETIMAGE)) {
|
||||
ret = copy_from_user(mfd->cursor_buf, img->data,
|
||||
input_frame_size);
|
||||
if (ret) {
|
||||
pr_err("copy_from_user error. rc=%d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
mixer->cursor_hotx = 0;
|
||||
mixer->cursor_hoty = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When source split is enabled, only CURSOR_PIPE_LEFT is used,
|
||||
* with both mixers of the pipe staged all the time.
|
||||
|
@ -3427,29 +3468,35 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
*/
|
||||
if (mdata->has_src_split || (!is_split_lm(mfd))
|
||||
|| (mdata->ncursor_pipes == 1)) {
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_LEFT);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req,
|
||||
CURSOR_PIPE_LEFT, ion_handle, iova, size);
|
||||
} else if ((start_x + roi.w) <= left_lm_w) {
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_LEFT);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req,
|
||||
CURSOR_PIPE_LEFT, ion_handle, iova, size);
|
||||
if (ret)
|
||||
goto done;
|
||||
req->bg_color = 0;
|
||||
req->flags |= MDP_SOLID_FILL;
|
||||
req->dst_rect.x = left_lm_w;
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_RIGHT);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req,
|
||||
CURSOR_PIPE_RIGHT, NULL, 0, 0);
|
||||
} else if (start_x >= left_lm_w) {
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_RIGHT);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_RIGHT,
|
||||
ion_handle, iova, size);
|
||||
if (ret)
|
||||
goto done;
|
||||
req->bg_color = 0;
|
||||
req->flags |= MDP_SOLID_FILL;
|
||||
req->dst_rect.x = 0;
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_LEFT);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_LEFT,
|
||||
NULL, 0, 0);
|
||||
} else if ((start_x <= left_lm_w) && ((start_x + roi.w) >= left_lm_w)) {
|
||||
mdss_mdp_set_rect(&req->dst_rect, start_x, start_y,
|
||||
(left_lm_w - start_x), roi.h);
|
||||
mdss_mdp_set_rect(&req->src_rect, 0, 0, (left_lm_w -
|
||||
start_x), roi.h);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_LEFT);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req,
|
||||
CURSOR_PIPE_LEFT, ion_handle, iova, size);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
@ -3457,7 +3504,8 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd,
|
|||
+ roi.w) - left_lm_w), roi.h);
|
||||
mdss_mdp_set_rect(&req->src_rect, (left_lm_w - start_x), 0,
|
||||
(roi.w - (left_lm_w - start_x)), roi.h);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req, CURSOR_PIPE_RIGHT);
|
||||
ret = mdss_mdp_cursor_pipe_setup(mfd, req,
|
||||
CURSOR_PIPE_RIGHT, NULL, iova, size);
|
||||
} else {
|
||||
pr_err("Invalid case for cursor pipe setup\n");
|
||||
ret = -EINVAL;
|
||||
|
@ -3467,8 +3515,16 @@ done:
|
|||
if (ret) {
|
||||
mdss_mdp_curor_pipe_cleanup(mfd, CURSOR_PIPE_LEFT);
|
||||
mdss_mdp_curor_pipe_cleanup(mfd, CURSOR_PIPE_RIGHT);
|
||||
}
|
||||
|
||||
if (iova)
|
||||
ion_unmap_iommu(ion_client, ion_handle,
|
||||
mdss_get_iommu_domain(
|
||||
MDSS_IOMMU_DOMAIN_UNSECURE), 0);
|
||||
if (ion_handle)
|
||||
ion_free(ion_client, ion_handle);
|
||||
|
||||
mfd->cursor_buf_size = 0;
|
||||
}
|
||||
kfree(req);
|
||||
mutex_unlock(&mdp5_data->ov_lock);
|
||||
return ret;
|
||||
|
|
|
@ -1150,8 +1150,8 @@ static int mdss_mdp_is_pipe_idle(struct mdss_mdp_pipe *pipe,
|
|||
reg_val = readl_relaxed(mdata->mdp_base +
|
||||
pipe->clk_status.reg_off);
|
||||
|
||||
if (reg_val & clk_status_idle_mask)
|
||||
is_idle = false;
|
||||
if ((reg_val & clk_status_idle_mask) == 0)
|
||||
is_idle = true;
|
||||
|
||||
pr_debug("pipe#:%d clk_status:0x%x clk_status_idle_mask:0x%x\n",
|
||||
pipe->num, reg_val, clk_status_idle_mask);
|
||||
|
@ -1160,13 +1160,24 @@ static int mdss_mdp_is_pipe_idle(struct mdss_mdp_pipe *pipe,
|
|||
if (!ignore_force_on && (is_forced_on || !is_idle))
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* skip vbif check for cursor pipes as the same xin-id is shared
|
||||
* between cursor0, cursor1 and dsi
|
||||
*/
|
||||
if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR) {
|
||||
if (ignore_force_on && is_forced_on)
|
||||
is_idle = true;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
vbif_idle_mask = BIT(pipe->xin_id + 16);
|
||||
reg_val = MDSS_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL1, is_nrt_vbif);
|
||||
|
||||
if (reg_val & vbif_idle_mask)
|
||||
is_idle = true;
|
||||
|
||||
pr_debug("pipe#:%d XIN_HALT_CTRL1: 0x%x\n", pipe->num, reg_val);
|
||||
pr_debug("pipe#:%d XIN_HALT_CTRL1: 0x%x, vbif_idle_mask: 0x%x\n",
|
||||
pipe->num, reg_val, vbif_idle_mask);
|
||||
|
||||
exit:
|
||||
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl)
|
||||
{
|
||||
struct dsi_shared_data *sdata;
|
||||
struct mdss_dsi_ctrl_pdata *octrl;
|
||||
u32 reg_val = 0;
|
||||
|
||||
if (ctrl == NULL) {
|
||||
pr_err("%s: Invalid input data\n", __func__);
|
||||
|
@ -50,15 +52,47 @@ void mdss_dsi_phy_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl)
|
|||
}
|
||||
|
||||
sdata = ctrl->shared_data;
|
||||
octrl = mdss_dsi_get_other_ctrl(ctrl);
|
||||
|
||||
/* start phy sw reset */
|
||||
MIPI_OUTP(ctrl->ctrl_base + 0x12c, 0x0001);
|
||||
udelay(1000);
|
||||
wmb();
|
||||
/* end phy sw reset */
|
||||
MIPI_OUTP(ctrl->ctrl_base + 0x12c, 0x0000);
|
||||
udelay(100);
|
||||
wmb();
|
||||
/*
|
||||
* For dual dsi case if we do DSI PHY sw reset,
|
||||
* this will reset DSI PHY regulators also.
|
||||
* Since DSI PHY regulator is shared among both
|
||||
* the DSI controllers, we should not do DSI PHY
|
||||
* sw reset when the other DSI controller is still
|
||||
* active.
|
||||
*/
|
||||
mutex_lock(&sdata->phy_reg_lock);
|
||||
if ((sdata->hw_rev != MDSS_DSI_HW_REV_103) &&
|
||||
mdss_dsi_is_hw_config_dual(sdata) &&
|
||||
(octrl && octrl->is_phyreg_enabled)) {
|
||||
/* start phy lane and HW reset */
|
||||
reg_val = MIPI_INP(ctrl->ctrl_base + 0x12c);
|
||||
reg_val |= (BIT(16) | BIT(8));
|
||||
MIPI_OUTP(ctrl->ctrl_base + 0x12c, reg_val);
|
||||
udelay(1000);
|
||||
/* ensure phy lane and HW reset starts */
|
||||
wmb();
|
||||
/* end phy lane and HW reset */
|
||||
reg_val = MIPI_INP(ctrl->ctrl_base + 0x12c);
|
||||
reg_val &= ~(BIT(16) | BIT(8));
|
||||
MIPI_OUTP(ctrl->ctrl_base + 0x12c, reg_val);
|
||||
udelay(100);
|
||||
/* ensure phy lane and HW reset ends */
|
||||
wmb();
|
||||
} else {
|
||||
/* start phy sw reset */
|
||||
MIPI_OUTP(ctrl->ctrl_base + 0x12c, 0x0001);
|
||||
udelay(1000);
|
||||
/* ensure phy sw reset starts */
|
||||
wmb();
|
||||
/* end phy sw reset */
|
||||
MIPI_OUTP(ctrl->ctrl_base + 0x12c, 0x0000);
|
||||
udelay(100);
|
||||
/* ensure phy sw reset ends */
|
||||
wmb();
|
||||
}
|
||||
mutex_unlock(&sdata->phy_reg_lock);
|
||||
|
||||
if ((sdata->hw_rev == MDSS_DSI_HW_REV_103) &&
|
||||
!mdss_dsi_is_hw_config_dual(sdata) &&
|
||||
|
@ -336,13 +370,22 @@ static void mdss_dsi_phy_regulator_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
|
|||
}
|
||||
|
||||
sdata = ctrl->shared_data;
|
||||
other_ctrl = mdss_dsi_get_other_ctrl(ctrl);
|
||||
|
||||
mutex_lock(&sdata->phy_reg_lock);
|
||||
if (enable) {
|
||||
if (ctrl->shared_data->hw_rev == MDSS_DSI_HW_REV_103)
|
||||
if (ctrl->shared_data->hw_rev == MDSS_DSI_HW_REV_103) {
|
||||
mdss_dsi_20nm_phy_regulator_enable(ctrl);
|
||||
else
|
||||
mdss_dsi_28nm_phy_regulator_enable(ctrl);
|
||||
} else {
|
||||
/*
|
||||
* For dual dsi case, do not reconfigure dsi phy
|
||||
* regulator if the other dsi controller is still
|
||||
* active.
|
||||
*/
|
||||
if (!mdss_dsi_is_hw_config_dual(sdata) ||
|
||||
(other_ctrl && !other_ctrl->is_phyreg_enabled))
|
||||
mdss_dsi_28nm_phy_regulator_enable(ctrl);
|
||||
}
|
||||
ctrl->is_phyreg_enabled = 1;
|
||||
} else {
|
||||
/*
|
||||
|
@ -352,7 +395,6 @@ static void mdss_dsi_phy_regulator_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
|
|||
*/
|
||||
if (mdss_dsi_is_hw_config_split(ctrl->shared_data) ||
|
||||
mdss_dsi_is_hw_config_dual(ctrl->shared_data)) {
|
||||
other_ctrl = mdss_dsi_get_other_ctrl(ctrl);
|
||||
if (other_ctrl && !other_ctrl->is_phyreg_enabled)
|
||||
mdss_dsi_phy_regulator_disable(ctrl);
|
||||
} else {
|
||||
|
|
|
@ -1279,15 +1279,8 @@ static int adv7533_video_on(void *client, bool on,
|
|||
|
||||
mutex_lock(&pdata->ops_mutex);
|
||||
|
||||
/* configure lanes wrt resolution */
|
||||
if (cfg->v_active == 1080)
|
||||
lanes = 0x40;
|
||||
else if (cfg->v_active == 720)
|
||||
lanes = 0x30;
|
||||
else
|
||||
lanes = 0x10;
|
||||
|
||||
/* lane configuration, 4 lanes */
|
||||
/* DSI lane configuration */
|
||||
lanes = (cfg->num_of_input_lanes << 4);
|
||||
ADV7533_WRITE(I2C_ADDR_CEC_DSI, 0x1C, lanes);
|
||||
|
||||
adv7533_video_setup(pdata, cfg);
|
||||
|
|
|
@ -299,8 +299,11 @@
|
|||
#define clk_cci_m_clk 0xec7e8afc
|
||||
|
||||
#define clk_a53ssmux_lc 0x71a9377b
|
||||
#define clk_a53_lc_clk 0xc69f0878
|
||||
#define clk_a53ssmux_bc 0xb5983c42
|
||||
#define clk_a53_bc_clk 0xcf28e63a
|
||||
#define clk_a53ssmux_cci 0x15560bd5
|
||||
#define clk_cci_clk 0x96854074
|
||||
|
||||
#define clk_audio_ap_clk 0x312ac429
|
||||
#define clk_audio_pmi_clk 0xb7ba2274
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -14,8 +14,11 @@
|
|||
#ifndef __MSM_CLOCK_CPU_8939_H
|
||||
#define __MSM_CLOCK_CPU_8939_H
|
||||
|
||||
#define clk_a53ssmux_lc 0x71a9377b
|
||||
#define clk_a53ssmux_bc 0xb5983c42
|
||||
#define clk_a53ssmux_cci 0x15560bd5
|
||||
#define clk_a53ssmux_lc 0x71a9377b
|
||||
#define clk_a53_lc_clk 0xc69f0878
|
||||
#define clk_a53ssmux_bc 0xb5983c42
|
||||
#define clk_a53_bc_clk 0xcf28e63a
|
||||
#define clk_a53ssmux_cci 0x15560bd5
|
||||
#define clk_cci_clk 0x96854074
|
||||
|
||||
#endif
|
||||
|
|
|
@ -321,7 +321,9 @@ int wcd9xxx_slim_bulk_write(struct wcd9xxx *wcd9xxx,
|
|||
void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
|
||||
void *pdata);
|
||||
|
||||
int wcd9xxx_disable_static_supplies_to_optimum(
|
||||
int wcd9xxx_disable_static_supplies_to_optimum(struct wcd9xxx *wcd9xxx,
|
||||
void *data);
|
||||
int wcd9xxx_enable_static_supplies_to_optimum(
|
||||
struct wcd9xxx *wcd9xxx,
|
||||
void *pdata);
|
||||
|
||||
|
|
|
@ -91,6 +91,14 @@ enum mmc_load {
|
|||
MMC_LOAD_LOW,
|
||||
};
|
||||
|
||||
enum dev_state {
|
||||
DEV_SUSPENDING = 1,
|
||||
DEV_SUSPENDED,
|
||||
DEV_RESUMING,
|
||||
DEV_RESUMED,
|
||||
DEV_ERROR,
|
||||
};
|
||||
|
||||
struct mmc_cmdq_host_ops {
|
||||
int (*enable)(struct mmc_host *host);
|
||||
void (*disable)(struct mmc_host *host, bool soft);
|
||||
|
@ -164,6 +172,7 @@ struct mmc_host_ops {
|
|||
unsigned long (*get_max_frequency)(struct mmc_host *host);
|
||||
unsigned long (*get_min_frequency)(struct mmc_host *host);
|
||||
int (*notify_load)(struct mmc_host *, enum mmc_load);
|
||||
void (*notify_pm_status)(struct mmc_host *, enum dev_state);
|
||||
int (*stop_request)(struct mmc_host *host);
|
||||
unsigned int (*get_xfer_remain)(struct mmc_host *host);
|
||||
};
|
||||
|
@ -281,12 +290,6 @@ struct mmc_supply {
|
|||
struct regulator *vqmmc; /* Optional Vccq supply */
|
||||
};
|
||||
|
||||
enum dev_state {
|
||||
DEV_SUSPENDING = 1,
|
||||
DEV_SUSPENDED,
|
||||
DEV_RESUMED,
|
||||
};
|
||||
|
||||
struct mmc_host {
|
||||
struct device *parent;
|
||||
struct device class_dev;
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
POWER_SUPPLY_DP_DM_DP0P6_DM3P3 = 7,
|
||||
POWER_SUPPLY_DP_DM_DPF_DMF = 8,
|
||||
POWER_SUPPLY_DP_DM_DPR_DMR = 9,
|
||||
POWER_SUPPLY_DP_DM_HVDCP3_SUPPORTED = 10,
|
||||
};
|
||||
|
||||
enum power_supply_property {
|
||||
|
|
|
@ -524,13 +524,13 @@ static void msm8x16_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
|
|||
reg3 = snd_soc_read(codec, MSM8X16_WCD_A_ANALOG_MICB_2_EN);
|
||||
reg4 = snd_soc_read(codec, MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL);
|
||||
|
||||
/* disable FSM and micbias*/
|
||||
/* disable FSM and micbias and enable pullup*/
|
||||
snd_soc_update_bits(codec,
|
||||
MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL,
|
||||
0x80, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
MSM8X16_WCD_A_ANALOG_MICB_2_EN,
|
||||
0x80, 0x00);
|
||||
0xA5, 0x25);
|
||||
/*
|
||||
* Enable legacy electrical detection current sources
|
||||
* and disable fast ramp and enable manual switching
|
||||
|
|
|
@ -634,6 +634,15 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
|
|||
(mbhc->zr > mbhc->mbhc_cfg->linein_th)) {
|
||||
jack_type = SND_JACK_LINEOUT;
|
||||
mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
|
||||
if (mbhc->hph_status) {
|
||||
mbhc->hph_status &= ~(SND_JACK_HEADSET |
|
||||
SND_JACK_LINEOUT |
|
||||
SND_JACK_UNSUPPORTED);
|
||||
wcd_mbhc_jack_report(mbhc,
|
||||
&mbhc->headset_jack,
|
||||
mbhc->hph_status,
|
||||
WCD_MBHC_JACK_MASK);
|
||||
}
|
||||
pr_debug("%s: Marking jack type as SND_JACK_LINEOUT\n",
|
||||
__func__);
|
||||
}
|
||||
|
|
|
@ -9930,9 +9930,33 @@ static int tasha_codec_remove(struct snd_soc_codec *codec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tasha_codec_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
|
||||
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
|
||||
struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);
|
||||
|
||||
pr_debug("%s:suspend of tasha codec\n", __func__);
|
||||
wcd9xxx_disable_static_supplies_to_optimum(tasha->wcd9xxx, pdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tasha_codec_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
|
||||
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
|
||||
struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);
|
||||
|
||||
pr_debug("%s:resume of tasha codec\n", __func__);
|
||||
wcd9xxx_enable_static_supplies_to_optimum(tasha->wcd9xxx, pdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_tasha = {
|
||||
.probe = tasha_codec_probe,
|
||||
.remove = tasha_codec_remove,
|
||||
.suspend = tasha_codec_suspend,
|
||||
.resume = tasha_codec_resume,
|
||||
.controls = tasha_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(tasha_snd_controls),
|
||||
.dapm_widgets = tasha_dapm_widgets,
|
||||
|
@ -10367,11 +10391,13 @@ static void tasha_powershutdown(struct platform_device *pdev)
|
|||
struct wcd9xxx_pdata *pdata = dev_get_platdata(pdev->dev.parent);
|
||||
|
||||
tasha = platform_get_drvdata(pdev);
|
||||
gpio_direction_output(pdata->reset_gpio, 0);
|
||||
/* sleep for 500msec to follow codec power down sequence */
|
||||
msleep(500);
|
||||
wcd9xxx_disable_static_supplies_to_optimum(tasha->wcd9xxx, pdata);
|
||||
wcd9xxx_disable_supplies(tasha->wcd9xxx, pdata);
|
||||
gpio_direction_output(pdata->reset_gpio, 0);
|
||||
/* sleep for 60msec to follow codec power down sequence */
|
||||
usleep_range(60000, 60100);
|
||||
/* sleep for 500msec for the regulator to ramp down */
|
||||
msleep(500);
|
||||
}
|
||||
|
||||
static struct platform_driver tasha_codec_driver = {
|
||||
|
|
|
@ -4255,7 +4255,10 @@ static void wcd9xxx_mbhc_setup(struct wcd9xxx_mbhc *mbhc)
|
|||
gain = wcd9xxx_mbhc_cal_btn_det_mp(btn_det, MBHC_BTN_DET_GAIN);
|
||||
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B2_CTL, 0x78,
|
||||
gain[idx] << 3);
|
||||
snd_soc_update_bits(codec, WCD9XXX_A_MICB_2_MBHC, 0x04, 0x04);
|
||||
if (mbhc->mbhc_cb && mbhc->mbhc_cb->get_cdc_type &&
|
||||
mbhc->mbhc_cb->get_cdc_type() !=
|
||||
WCD9XXX_CDC_TYPE_TOMTOM)
|
||||
snd_soc_update_bits(codec, WCD9XXX_A_MICB_2_MBHC, 0x04, 0x04);
|
||||
|
||||
pr_debug("%s: leave\n", __func__);
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ struct wsa881x_pdata {
|
|||
struct wsa881x_tz_priv tz_pdata;
|
||||
int bg_cnt;
|
||||
int clk_cnt;
|
||||
int version;
|
||||
struct mutex bg_lock;
|
||||
struct mutex res_lock;
|
||||
};
|
||||
|
@ -338,22 +339,66 @@ static int wsa881x_i2c_get_client_index(struct i2c_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int wsa881x_temp_sensor_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
dev_dbg(codec->dev, "%s: enable:%d\n", __func__, enable);
|
||||
snd_soc_update_bits(codec, WSA881X_TEMP_OP, (0x01 << 2),
|
||||
(enable << 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_boost_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
if (enable) {
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PS_CTL, 0x40, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1,
|
||||
0xF0, 0xB0);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_ZX_CTL, 0x20, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_EN_CTL, 0x80, 0x80);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL,
|
||||
0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL,
|
||||
0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PS_CTL,
|
||||
0x40, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1,
|
||||
0xF0, 0xB0);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_ZX_CTL,
|
||||
0x20, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_EN_CTL,
|
||||
0x80, 0x80);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_LOOP_STABILITY,
|
||||
0x03, 0x03);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_MISC2_CTL,
|
||||
0xFF, 0x14);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_START_CTL,
|
||||
0x80, 0x80);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_START_CTL,
|
||||
0x03, 0x00);
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
|
||||
0x0C, 0x04);
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
|
||||
0x03, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1,
|
||||
0xF0, 0x70);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x03, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN,
|
||||
0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_CURRENT_LIMIT,
|
||||
0x0F, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_EN_CTL,
|
||||
0x80, 0x80);
|
||||
}
|
||||
/* For WSA8810, start-up time is 1500us as per qcrg sequence */
|
||||
usleep_range(1500, 1510);
|
||||
} else {
|
||||
/* ENSURE: Class-D amp is shutdown. CLK is still on */
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_EN_CTL, 0x80, 0x00);
|
||||
/* boost settle time is 1500us as per qcrg sequence */
|
||||
usleep_range(1500, 1510);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -363,17 +408,30 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
|
|||
u8 vsense_gain)
|
||||
{
|
||||
u8 value = 0;
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
|
||||
if (enable) {
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_OTP_REG_28,
|
||||
0x3F, 0x3A);
|
||||
snd_soc_update_bits(codec, WSA881X_BONGO_RESRV_REG1,
|
||||
0xFF, 0xB2);
|
||||
snd_soc_update_bits(codec, WSA881X_BONGO_RESRV_REG2,
|
||||
0xFF, 0x05);
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_VSENSE_VCM,
|
||||
0x08, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x02, 0x02);
|
||||
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x1C, 0x04);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x02, 0x02);
|
||||
}
|
||||
value = ((isense2_gain << 6) | (isense1_gain << 4) |
|
||||
(vsense_gain << 3));
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_GAIN,
|
||||
|
@ -381,8 +439,12 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
|
|||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_GAIN,
|
||||
0x01, 0x01);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_VSENSE_VCM,
|
||||
0x08, 0x08);
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x10, 0x10);
|
||||
else
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x08, 0x08);
|
||||
/*
|
||||
* 200us sleep is needed after visense txfe disable as per
|
||||
* HW requirement.
|
||||
|
@ -397,9 +459,13 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
|
|||
|
||||
static int wsa881x_visense_adc_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
if (enable) {
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_SEL_IBIAS, 0x70, 0x40);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_SEL_IBIAS,
|
||||
0x70, 0x40);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_SEL_IBIAS,
|
||||
0x07, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V, 0x80, 0x80);
|
||||
|
@ -460,8 +526,11 @@ static void wsa881x_clk_ctrl(struct snd_soc_codec *codec, bool enable)
|
|||
if (wsa881x->clk_cnt <= 0) {
|
||||
WARN_ON(wsa881x->clk_cnt < 0);
|
||||
wsa881x->clk_cnt = 0;
|
||||
snd_soc_write(codec, WSA881X_CDC_DIG_CLK_CTL, 0x00);
|
||||
snd_soc_write(codec, WSA881X_CDC_ANA_CLK_CTL, 0x00);
|
||||
snd_soc_write(codec, WSA881X_CDC_DIG_CLK_CTL, 0x00);
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec,
|
||||
WSA881X_CDC_TOP_CLK_CTL, 0x01, 0x00);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&wsa881x->res_lock);
|
||||
|
@ -469,6 +538,8 @@ static void wsa881x_clk_ctrl(struct snd_soc_codec *codec, bool enable)
|
|||
|
||||
static int wsa881x_rdac_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
if (enable) {
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL, 0x08, 0x00);
|
||||
|
@ -477,18 +548,26 @@ static int wsa881x_rdac_ctrl(struct snd_soc_codec *codec, bool enable)
|
|||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x20, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x40, 0x40);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x80, 0x80);
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_CAL,
|
||||
0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_OCP_CTL,
|
||||
0x30, 0x30);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_OCP_CTL,
|
||||
0x0C, 0x00);
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_GAIN, 0xF0, 0x40);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x01, 0x01);
|
||||
} else {
|
||||
/* Ensure class-D amp is off */
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x80, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x40, 0x00);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_spkr_pa_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
struct wsa881x_pdata *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
pr_debug("%s: enable:%d\n", __func__, enable);
|
||||
|
@ -497,44 +576,72 @@ static int wsa881x_spkr_pa_ctrl(struct snd_soc_codec *codec, bool enable)
|
|||
* Ensure: Boost is enabled and stable, Analog input is up
|
||||
* and outputting silence
|
||||
*/
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
if (!WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
0xFF, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V,
|
||||
0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
0xFF, 0x10);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG, 0xA0, 0xA0);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x80, 0x80);
|
||||
usleep_range(700, 710);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG, 0x00, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG,
|
||||
0xA0, 0xA0);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN,
|
||||
0x80, 0x80);
|
||||
usleep_range(700, 710);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG,
|
||||
0x00, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
0xFF, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V, 0x02, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V,
|
||||
0x02, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
0xFF, 0x00);
|
||||
} else
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN,
|
||||
0x80, 0x80);
|
||||
/* add 1000us delay as per qcrg */
|
||||
usleep_range(1000, 1010);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x01, 0x01);
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_CAL,
|
||||
0x01, 0x00);
|
||||
usleep_range(1000, 1010);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_GAIN, 0xF0,
|
||||
(wsa881x->spk_pa_gain << 4));
|
||||
if (wsa881x->visense_enable) {
|
||||
ret = msm_gpioset_activate(CLIENT_WSA_BONGO_1,
|
||||
"wsa_vi");
|
||||
if (ret) {
|
||||
pr_err("%s: gpio set cannot be activated %s\n",
|
||||
__func__, "wsa_vi");
|
||||
return ret;
|
||||
}
|
||||
wsa881x_visense_txfe_ctrl(codec, true,
|
||||
0x00, 0x01, 0x00);
|
||||
wsa881x_visense_adc_ctrl(codec, true);
|
||||
wsa881x_temp_sensor_ctrl(codec, true);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Ensure: Boost is still on, Stream from Analog input and
|
||||
* Speaker Protection has been stopped and input is at 0V
|
||||
*/
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_CAL,
|
||||
0x01, 0x01);
|
||||
usleep_range(1000, 1010);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_CAL,
|
||||
0x01, 0x00);
|
||||
msleep(20);
|
||||
snd_soc_update_bits(codec, WSA881X_ANA_CTL,
|
||||
0x03, 0x00);
|
||||
usleep_range(200, 210);
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x80, 0x00);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_temp_sensor_ctrl(struct snd_soc_codec *codec, bool enable)
|
||||
{
|
||||
dev_dbg(codec->dev, "%s: enable:%d\n", __func__, enable);
|
||||
snd_soc_update_bits(codec, WSA881X_TEMP_OP, (0x01 << 2),
|
||||
(enable << 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_get_boost(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
@ -623,44 +730,39 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
|
|||
pr_err("%s: wsa startup failed ret: %d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_RST_CTL, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_RST_CTL, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_CLOCK_CONFIG, 0x01, 0x01);
|
||||
wsa881x_clk_ctrl(codec, true);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_DIG_CLK_CTL, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_ANA_CLK_CTL, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_BIAS_REF_CTRL, 0x0F, 0x08);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_BIAS_REF_CTRL,
|
||||
0x0F, 0x08);
|
||||
wsa881x_bandgap_ctrl(codec, true);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BBM_CTL, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x40, 0x40);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BBM_CTL,
|
||||
0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0xC0, 0x80);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x06, 0x06);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL2, 0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_INT, 0x09, 0x09);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL2,
|
||||
0x04, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_INT,
|
||||
0x09, 0x09);
|
||||
}
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0xF0, 0x20);
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT,
|
||||
0x0E, 0x0E);
|
||||
if (wsa881x->boost_enable)
|
||||
wsa881x_boost_ctrl(codec, true);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
wsa881x_rdac_ctrl(codec, true);
|
||||
if (wsa881x->visense_enable) {
|
||||
ret = msm_gpioset_activate(CLIENT_WSA_BONGO_1,
|
||||
"wsa_vi");
|
||||
if (ret) {
|
||||
pr_err("%s: gpio set cannot be activated %s\n",
|
||||
__func__, "wsa_vi");
|
||||
return ret;
|
||||
}
|
||||
wsa881x_visense_txfe_ctrl(codec, true,
|
||||
0x00, 0x01, 0x00);
|
||||
wsa881x_visense_adc_ctrl(codec, true);
|
||||
wsa881x_temp_sensor_ctrl(codec, true);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAPM_PRE_PMD:
|
||||
wsa881x_rdac_ctrl(codec, false);
|
||||
if (wsa881x->visense_enable) {
|
||||
wsa881x_visense_adc_ctrl(codec, false);
|
||||
wsa881x_visense_txfe_ctrl(codec, false,
|
||||
0x00, 0x01, 0x00);
|
||||
wsa881x_visense_adc_ctrl(codec, false);
|
||||
ret = msm_gpioset_suspend(CLIENT_WSA_BONGO_1,
|
||||
"wsa_vi");
|
||||
if (ret) {
|
||||
|
@ -669,11 +771,11 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
wsa881x_rdac_ctrl(codec, false);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
if (wsa881x->boost_enable)
|
||||
wsa881x_boost_ctrl(codec, false);
|
||||
wsa881x_clk_ctrl(codec, false);
|
||||
wsa881x_bandgap_ctrl(codec, false);
|
||||
ret = wsa881x_shutdown(wsa881x);
|
||||
if (ret < 0) {
|
||||
|
@ -1084,6 +1186,11 @@ static int wsa881x_i2c_probe(struct i2c_client *client,
|
|||
client->dev.platform_data = pdata;
|
||||
i2c_set_clientdata(client, pdata);
|
||||
pdata->client[WSA881X_ANALOG_SLAVE] = client;
|
||||
if (pdata->version == WSA881X_2_0)
|
||||
wsa881x_update_regmap_2_0(
|
||||
pdata->regmap[WSA881X_ANALOG_SLAVE],
|
||||
WSA881X_ANALOG_SLAVE);
|
||||
|
||||
return ret;
|
||||
} else if (pdata->status == WSA881X_STATUS_PROBING) {
|
||||
pdata->index = wsa881x_index;
|
||||
|
@ -1141,6 +1248,15 @@ static int wsa881x_i2c_probe(struct i2c_client *client,
|
|||
wsa881x_probing_count++;
|
||||
goto err1;
|
||||
}
|
||||
pdata->version = wsa881x_i2c_read_device(pdata,
|
||||
WSA881X_CHIP_ID1);
|
||||
pr_debug("%s: wsa881x version: %d\n", __func__, pdata->version);
|
||||
if (pdata->version == WSA881X_2_0) {
|
||||
wsa881x_update_reg_defaults_2_0();
|
||||
wsa881x_update_regmap_2_0(
|
||||
pdata->regmap[WSA881X_DIGITAL_SLAVE],
|
||||
WSA881X_DIGITAL_SLAVE);
|
||||
}
|
||||
wsa881x_presence_count++;
|
||||
wsa881x_probing_count++;
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
|
|
|
@ -28,13 +28,23 @@
|
|||
#define WSA881X_DIGITAL_SLAVE 0
|
||||
#define WSA881X_ANALOG_SLAVE 1
|
||||
|
||||
enum {
|
||||
WSA881X_1_X = 0,
|
||||
WSA881X_2_0,
|
||||
};
|
||||
|
||||
#define WSA881X_IS_2_0(ver) \
|
||||
((ver == WSA881X_2_0) ? 1 : 0)
|
||||
|
||||
extern const u8 wsa881x_ana_reg_readable[WSA881X_CACHE_SIZE];
|
||||
extern const struct reg_default wsa881x_ana_reg_defaults[WSA881X_CACHE_SIZE];
|
||||
extern struct reg_default wsa881x_ana_reg_defaults[WSA881X_CACHE_SIZE];
|
||||
extern struct regmap_config wsa881x_ana_regmap_config[2];
|
||||
int wsa881x_get_client_index(void);
|
||||
int wsa881x_get_probing_count(void);
|
||||
int wsa881x_get_presence_count(void);
|
||||
int wsa881x_set_mclk_callback(
|
||||
int (*enable_mclk_callback)(struct snd_soc_card *, bool));
|
||||
void wsa881x_update_reg_defaults_2_0(void);
|
||||
void wsa881x_update_regmap_2_0(struct regmap *regmap, int flag);
|
||||
|
||||
#endif /* _WSA881X_H */
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#define WSA881X_CLOCK_CONFIG (WSA881X_DIGITAL_BASE+0x0009)
|
||||
#define WSA881X_ANA_CTL (WSA881X_DIGITAL_BASE+0x000A)
|
||||
#define WSA881X_SWR_RESET_EN (WSA881X_DIGITAL_BASE+0x000B)
|
||||
#define WSA881X_RESET_CTL (WSA881X_DIGITAL_BASE+0x000C)
|
||||
#define WSA881X_TADC_VALUE_CTL (WSA881X_DIGITAL_BASE+0x000F)
|
||||
#define WSA881X_TEMP_DETECT_CTL (WSA881X_DIGITAL_BASE+0x0010)
|
||||
#define WSA881X_TEMP_MSB (WSA881X_DIGITAL_BASE+0x0011)
|
||||
#define WSA881X_TEMP_LSB (WSA881X_DIGITAL_BASE+0x0012)
|
||||
|
@ -66,6 +68,7 @@
|
|||
#define WSA881X_TEMP_DEBUG_MSB (WSA881X_DIGITAL_BASE+0x003E)
|
||||
#define WSA881X_TEMP_DEBUG_LSB (WSA881X_DIGITAL_BASE+0x003F)
|
||||
#define WSA881X_SAMPLE_EDGE_SEL (WSA881X_DIGITAL_BASE+0x0044)
|
||||
#define WSA881X_IOPAD_CTL (WSA881X_DIGITAL_BASE+0x0045)
|
||||
#define WSA881X_SPARE_0 (WSA881X_DIGITAL_BASE+0x0050)
|
||||
#define WSA881X_SPARE_1 (WSA881X_DIGITAL_BASE+0x0051)
|
||||
#define WSA881X_SPARE_2 (WSA881X_DIGITAL_BASE+0x0052)
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define WSA881X_CLOCK_CONFIG (WSA881X_DIGITAL_BASE+0x0009)
|
||||
#define WSA881X_ANA_CTL (WSA881X_DIGITAL_BASE+0x000A)
|
||||
#define WSA881X_SWR_RESET_EN (WSA881X_DIGITAL_BASE+0x000B)
|
||||
#define WSA881X_RESET_CTL (WSA881X_DIGITAL_BASE+0x000C)
|
||||
#define WSA881X_TADC_VALUE_CTL (WSA881X_DIGITAL_BASE+0x000F)
|
||||
#define WSA881X_TEMP_DETECT_CTL (WSA881X_DIGITAL_BASE+0x0010)
|
||||
#define WSA881X_TEMP_MSB (WSA881X_DIGITAL_BASE+0x0011)
|
||||
#define WSA881X_TEMP_LSB (WSA881X_DIGITAL_BASE+0x0012)
|
||||
|
@ -67,6 +69,7 @@
|
|||
#define WSA881X_TEMP_DEBUG_MSB (WSA881X_DIGITAL_BASE+0x003E)
|
||||
#define WSA881X_TEMP_DEBUG_LSB (WSA881X_DIGITAL_BASE+0x003F)
|
||||
#define WSA881X_SAMPLE_EDGE_SEL (WSA881X_DIGITAL_BASE+0x0044)
|
||||
#define WSA881X_IOPAD_CTL (WSA881X_DIGITAL_BASE+0x0045)
|
||||
#define WSA881X_SPARE_0 (WSA881X_DIGITAL_BASE+0x0050)
|
||||
#define WSA881X_SPARE_1 (WSA881X_DIGITAL_BASE+0x0051)
|
||||
#define WSA881X_SPARE_2 (WSA881X_DIGITAL_BASE+0x0052)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "wsa881x-registers-analog.h"
|
||||
#include "wsa881x-analog.h"
|
||||
|
||||
const struct reg_default wsa881x_ana_reg_defaults[] = {
|
||||
struct reg_default wsa881x_ana_reg_defaults[] = {
|
||||
{WSA881X_CHIP_ID0, 0x00},
|
||||
{WSA881X_CHIP_ID1, 0x00},
|
||||
{WSA881X_CHIP_ID2, 0x00},
|
||||
|
@ -168,7 +168,7 @@ const struct reg_default wsa881x_ana_reg_defaults[] = {
|
|||
{WSA881X_SPKR_STATUS3, 0x00},
|
||||
};
|
||||
|
||||
const struct reg_default wsa881x_ana_reg_defaults_0[] = {
|
||||
struct reg_default wsa881x_ana_reg_defaults_0[] = {
|
||||
{WSA881X_CHIP_ID0, 0x00},
|
||||
{WSA881X_CHIP_ID1, 0x00},
|
||||
{WSA881X_CHIP_ID2, 0x00},
|
||||
|
@ -257,7 +257,7 @@ const struct reg_default wsa881x_ana_reg_defaults_0[] = {
|
|||
{WSA881X_OTP_REG_63, 0x40},
|
||||
};
|
||||
|
||||
const struct reg_default wsa881x_ana_reg_defaults_1[] = {
|
||||
struct reg_default wsa881x_ana_reg_defaults_1[] = {
|
||||
{WSA881X_BIAS_REF_CTRL - WSA881X_ANALOG_BASE, 0x6C},
|
||||
{WSA881X_BIAS_TEST - WSA881X_ANALOG_BASE, 0x16},
|
||||
{WSA881X_BIAS_BIAS - WSA881X_ANALOG_BASE, 0xF0},
|
||||
|
@ -322,6 +322,113 @@ const struct reg_default wsa881x_ana_reg_defaults_1[] = {
|
|||
{WSA881X_SPKR_STATUS3 - WSA881X_ANALOG_BASE, 0x00},
|
||||
};
|
||||
|
||||
struct reg_default wsa881x_rev_2_0_dig[] = {
|
||||
{WSA881X_RESET_CTL, 0x00},
|
||||
{WSA881X_TADC_VALUE_CTL, 0x01},
|
||||
{WSA881X_INTR_MASK, 0x1B},
|
||||
{WSA881X_IOPAD_CTL, 0x00},
|
||||
{WSA881X_OTP_REG_28, 0x3F},
|
||||
{WSA881X_OTP_REG_29, 0x3F},
|
||||
{WSA881X_OTP_REG_30, 0x01},
|
||||
{WSA881X_OTP_REG_31, 0x01},
|
||||
};
|
||||
|
||||
struct reg_default wsa881x_rev_2_0_ana[] = {
|
||||
{WSA881X_TEMP_ADC_CTRL, 0x03},
|
||||
{WSA881X_ADC_SEL_IBIAS, 0x45},
|
||||
{WSA881X_SPKR_DRV_GAIN, 0xC1},
|
||||
{WSA881X_SPKR_DAC_CTL, 0x42},
|
||||
{WSA881X_SPKR_BBM_CTL, 0x02},
|
||||
{WSA881X_SPKR_MISC_CTL1, 0x40},
|
||||
{WSA881X_SPKR_MISC_CTL2, 0x07},
|
||||
{WSA881X_SPKR_BIAS_INT, 0x5F},
|
||||
{WSA881X_SPKR_BIAS_PSRR, 0x44},
|
||||
{WSA881X_BOOST_PS_CTL, 0xA0},
|
||||
{WSA881X_BOOST_PRESET_OUT1, 0xB7},
|
||||
{WSA881X_BOOST_LOOP_STABILITY, 0x8D},
|
||||
{WSA881X_SPKR_PROT_ATEST2, 0x02},
|
||||
{WSA881X_BONGO_RESRV_REG1, 0x5E},
|
||||
{WSA881X_BONGO_RESRV_REG2, 0x07},
|
||||
};
|
||||
|
||||
struct reg_default wsa881x_rev_2_0_regmap_ana[] = {
|
||||
{WSA881X_TEMP_ADC_CTRL - WSA881X_ANALOG_BASE, 0x03},
|
||||
{WSA881X_ADC_SEL_IBIAS - WSA881X_ANALOG_BASE, 0x45},
|
||||
{WSA881X_SPKR_DRV_GAIN - WSA881X_ANALOG_BASE, 0xC1},
|
||||
{WSA881X_SPKR_DAC_CTL - WSA881X_ANALOG_BASE, 0x42},
|
||||
{WSA881X_SPKR_BBM_CTL - WSA881X_ANALOG_BASE, 0x02},
|
||||
{WSA881X_SPKR_MISC_CTL1 - WSA881X_ANALOG_BASE, 0x40},
|
||||
{WSA881X_SPKR_MISC_CTL2 - WSA881X_ANALOG_BASE, 0x07},
|
||||
{WSA881X_SPKR_BIAS_INT - WSA881X_ANALOG_BASE, 0x5F},
|
||||
{WSA881X_SPKR_BIAS_PSRR - WSA881X_ANALOG_BASE, 0x44},
|
||||
{WSA881X_BOOST_PS_CTL - WSA881X_ANALOG_BASE, 0xA0},
|
||||
{WSA881X_BOOST_PRESET_OUT1 - WSA881X_ANALOG_BASE, 0xB7},
|
||||
{WSA881X_BOOST_LOOP_STABILITY - WSA881X_ANALOG_BASE, 0x8D},
|
||||
{WSA881X_SPKR_PROT_ATEST2 - WSA881X_ANALOG_BASE, 0x02},
|
||||
{WSA881X_BONGO_RESRV_REG1 - WSA881X_ANALOG_BASE, 0x5E},
|
||||
{WSA881X_BONGO_RESRV_REG2 - WSA881X_ANALOG_BASE, 0x07},
|
||||
};
|
||||
|
||||
/**
|
||||
* wsa881x_update_reg_defaults_2_0 - update default values of regs for v2.0
|
||||
*
|
||||
* Bongo v2.0 has different default values for certain analog and digital
|
||||
* registers compared to v1.x. Therefore, update the values of these registers
|
||||
* with the values from tables defined above for v2.0.
|
||||
*/
|
||||
void wsa881x_update_reg_defaults_2_0(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wsa881x_rev_2_0_dig); i++) {
|
||||
for (j = 0; j < ARRAY_SIZE(wsa881x_ana_reg_defaults); j++)
|
||||
if (wsa881x_ana_reg_defaults[j].reg ==
|
||||
wsa881x_rev_2_0_dig[i].reg)
|
||||
wsa881x_ana_reg_defaults[j].def =
|
||||
wsa881x_rev_2_0_dig[i].def;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(wsa881x_rev_2_0_ana); i++) {
|
||||
for (j = 0; j < ARRAY_SIZE(wsa881x_ana_reg_defaults); j++)
|
||||
if (wsa881x_ana_reg_defaults[j].reg ==
|
||||
wsa881x_rev_2_0_ana[i].reg)
|
||||
wsa881x_ana_reg_defaults[j].def =
|
||||
wsa881x_rev_2_0_ana[i].def;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(wsa881x_update_reg_defaults_2_0);
|
||||
|
||||
/**
|
||||
* wsa881x_update_regmap_2_0 - update regmap framework with new tables
|
||||
* @regmap: pointer to bongo regmap structure
|
||||
* @flag: indicates digital or analog bongo slave
|
||||
*
|
||||
* Bongo v2.0 has some new registers for both analog and digital slaves.
|
||||
* Update the regmap framework with all the new registers.
|
||||
*/
|
||||
void wsa881x_update_regmap_2_0(struct regmap *regmap, int flag)
|
||||
{
|
||||
u16 ret = 0;
|
||||
|
||||
switch (flag) {
|
||||
case WSA881X_DIGITAL_SLAVE:
|
||||
ret = regmap_register_patch(regmap, wsa881x_rev_2_0_dig,
|
||||
ARRAY_SIZE(wsa881x_rev_2_0_dig));
|
||||
break;
|
||||
case WSA881X_ANALOG_SLAVE:
|
||||
ret = regmap_register_patch(regmap, wsa881x_rev_2_0_ana,
|
||||
ARRAY_SIZE(wsa881x_rev_2_0_ana));
|
||||
break;
|
||||
default:
|
||||
pr_debug("%s: unknown version", __func__);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
pr_err("%s: Failed to update regmap defaults ret= %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
EXPORT_SYMBOL(wsa881x_update_regmap_2_0);
|
||||
|
||||
static bool wsa881x_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return wsa881x_ana_reg_readable[reg];
|
||||
|
@ -330,20 +437,34 @@ static bool wsa881x_readable_register(struct device *dev, unsigned int reg)
|
|||
static bool wsa881x_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case WSA881X_CHIP_ID0:
|
||||
case WSA881X_CHIP_ID1:
|
||||
case WSA881X_CHIP_ID2:
|
||||
case WSA881X_CHIP_ID3:
|
||||
case WSA881X_BUS_ID:
|
||||
case WSA881X_TEMP_MSB:
|
||||
case WSA881X_TEMP_LSB:
|
||||
case WSA881X_SDM_PDM9_LSB:
|
||||
case WSA881X_SDM_PDM9_MSB:
|
||||
case WSA881X_OTP_REG_0:
|
||||
case WSA881X_OTP_REG_1:
|
||||
case WSA881X_OTP_REG_2:
|
||||
case WSA881X_OTP_REG_3:
|
||||
case WSA881X_OTP_REG_4:
|
||||
case WSA881X_OTP_REG_5:
|
||||
case WSA881X_OTP_REG_31:
|
||||
case WSA881X_TEMP_DOUT_MSB:
|
||||
case WSA881X_TEMP_DOUT_LSB:
|
||||
case WSA881X_TEMP_OP:
|
||||
case WSA881X_OTP_CTRL1:
|
||||
case WSA881X_INTR_STATUS:
|
||||
case WSA881X_ATE_TEST_MODE:
|
||||
case WSA881X_PIN_STATUS:
|
||||
case WSA881X_SWR_HM_TEST2:
|
||||
case WSA881X_SPKR_STATUS1:
|
||||
case WSA881X_SPKR_STATUS2:
|
||||
case WSA881X_SPKR_STATUS3:
|
||||
case WSA881X_SPKR_PROT_SAR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
#include "wsa881x-registers.h"
|
||||
#include "wsa881x.h"
|
||||
|
||||
/*
|
||||
* Default register reset values that are common across different versions
|
||||
* are defined here. If a register reset value is changed based on version
|
||||
* then remove it from this structure and add it in version specific
|
||||
* structures.
|
||||
*/
|
||||
static struct reg_default wsa881x_defaults[] = {
|
||||
{WSA881X_CHIP_ID0, 0x00},
|
||||
{WSA881X_CHIP_ID1, 0x00},
|
||||
|
@ -46,7 +52,6 @@ static struct reg_default wsa881x_defaults[] = {
|
|||
{WSA881X_OTP_CTRL1, 0x00},
|
||||
{WSA881X_HDRIVE_CTL_GROUP1, 0x00},
|
||||
{WSA881X_INTR_MODE, 0x00},
|
||||
{WSA881X_INTR_MASK, 0x1F},
|
||||
{WSA881X_INTR_STATUS, 0x00},
|
||||
{WSA881X_INTR_CLEAR, 0x00},
|
||||
{WSA881X_INTR_LEVEL, 0x00},
|
||||
|
@ -98,10 +103,6 @@ static struct reg_default wsa881x_defaults[] = {
|
|||
{WSA881X_OTP_REG_25, 0x01},
|
||||
{WSA881X_OTP_REG_26, 0x03},
|
||||
{WSA881X_OTP_REG_27, 0x11},
|
||||
{WSA881X_OTP_REG_28, 0xFF},
|
||||
{WSA881X_OTP_REG_29, 0xFF},
|
||||
{WSA881X_OTP_REG_30, 0xFF},
|
||||
{WSA881X_OTP_REG_31, 0xFF},
|
||||
{WSA881X_OTP_REG_63, 0x40},
|
||||
/* WSA881x Analog registers */
|
||||
{WSA881X_BIAS_REF_CTRL, 0x6C},
|
||||
|
@ -113,41 +114,29 @@ static struct reg_default wsa881x_defaults[] = {
|
|||
{WSA881X_TEMP_CLK_CTRL, 0x87},
|
||||
{WSA881X_TEMP_TEST, 0x00},
|
||||
{WSA881X_TEMP_BIAS, 0x51},
|
||||
{WSA881X_TEMP_ADC_CTRL, 0x00},
|
||||
{WSA881X_TEMP_DOUT_MSB, 0x00},
|
||||
{WSA881X_TEMP_DOUT_LSB, 0x00},
|
||||
{WSA881X_ADC_EN_MODU_V, 0x00},
|
||||
{WSA881X_ADC_EN_MODU_I, 0x00},
|
||||
{WSA881X_ADC_EN_DET_TEST_V, 0x00},
|
||||
{WSA881X_ADC_EN_DET_TEST_I, 0x00},
|
||||
{WSA881X_ADC_SEL_IBIAS, 0x25},
|
||||
{WSA881X_ADC_EN_SEL_IBAIS, 0x10},
|
||||
{WSA881X_SPKR_DRV_EN, 0x74},
|
||||
{WSA881X_SPKR_DRV_GAIN, 0x01},
|
||||
{WSA881X_SPKR_DAC_CTL, 0x40},
|
||||
{WSA881X_SPKR_DRV_DBG, 0x15},
|
||||
{WSA881X_SPKR_PWRSTG_DBG, 0x00},
|
||||
{WSA881X_SPKR_OCP_CTL, 0xD4},
|
||||
{WSA881X_SPKR_CLIP_CTL, 0x90},
|
||||
{WSA881X_SPKR_BBM_CTL, 0x00},
|
||||
{WSA881X_SPKR_MISC_CTL1, 0x80},
|
||||
{WSA881X_SPKR_MISC_CTL2, 0x00},
|
||||
{WSA881X_SPKR_BIAS_INT, 0x56},
|
||||
{WSA881X_SPKR_PA_INT, 0x54},
|
||||
{WSA881X_SPKR_BIAS_CAL, 0xAC},
|
||||
{WSA881X_SPKR_BIAS_PSRR, 0x54},
|
||||
{WSA881X_SPKR_STATUS1, 0x00},
|
||||
{WSA881X_SPKR_STATUS2, 0x00},
|
||||
{WSA881X_BOOST_EN_CTL, 0x18},
|
||||
{WSA881X_BOOST_CURRENT_LIMIT, 0x7A},
|
||||
{WSA881X_BOOST_PS_CTL, 0xC0},
|
||||
{WSA881X_BOOST_PRESET_OUT1, 0x77},
|
||||
{WSA881X_BOOST_PRESET_OUT2, 0x70},
|
||||
{WSA881X_BOOST_FORCE_OUT, 0x0E},
|
||||
{WSA881X_BOOST_LDO_PROG, 0x16},
|
||||
{WSA881X_BOOST_SLOPE_COMP_ISENSE_FB, 0x71},
|
||||
{WSA881X_BOOST_RON_CTL, 0x0F},
|
||||
{WSA881X_BOOST_LOOP_STABILITY, 0xAD},
|
||||
{WSA881X_BOOST_ZX_CTL, 0x34},
|
||||
{WSA881X_BOOST_START_CTL, 0x23},
|
||||
{WSA881X_BOOST_MISC1_CTL, 0x80},
|
||||
|
@ -159,15 +148,103 @@ static struct reg_default wsa881x_defaults[] = {
|
|||
{WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET1, 0x8D},
|
||||
{WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET2, 0x8D},
|
||||
{WSA881X_SPKR_PROT_ATEST1, 0x01},
|
||||
{WSA881X_SPKR_PROT_ATEST2, 0x00},
|
||||
{WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x8D},
|
||||
{WSA881X_SPKR_PROT_FE_VSENSE_BIAS_SET1, 0x4D},
|
||||
{WSA881X_BONGO_RESRV_REG1, 0x00},
|
||||
{WSA881X_BONGO_RESRV_REG2, 0x00},
|
||||
{WSA881X_SPKR_PROT_SAR, 0x00},
|
||||
{WSA881X_SPKR_STATUS3, 0x00},
|
||||
};
|
||||
|
||||
/* Default register reset values for WSA881x rev 1.0 or 1.1 */
|
||||
static struct reg_default wsa881x_rev_1_x[] = {
|
||||
{WSA881X_INTR_MASK, 0x1F},
|
||||
{WSA881X_OTP_REG_28, 0xFF},
|
||||
{WSA881X_OTP_REG_29, 0xFF},
|
||||
{WSA881X_OTP_REG_30, 0xFF},
|
||||
{WSA881X_OTP_REG_31, 0xFF},
|
||||
{WSA881X_TEMP_ADC_CTRL, 0x00},
|
||||
{WSA881X_ADC_SEL_IBIAS, 0x25},
|
||||
{WSA881X_SPKR_DRV_GAIN, 0x01},
|
||||
{WSA881X_SPKR_DAC_CTL, 0x40},
|
||||
{WSA881X_SPKR_BBM_CTL, 0x00},
|
||||
{WSA881X_SPKR_MISC_CTL1, 0x80},
|
||||
{WSA881X_SPKR_MISC_CTL2, 0x00},
|
||||
{WSA881X_SPKR_BIAS_INT, 0x56},
|
||||
{WSA881X_SPKR_BIAS_PSRR, 0x54},
|
||||
{WSA881X_BOOST_PS_CTL, 0xC0},
|
||||
{WSA881X_BOOST_PRESET_OUT1, 0x77},
|
||||
{WSA881X_BOOST_LOOP_STABILITY, 0xAD},
|
||||
{WSA881X_SPKR_PROT_ATEST2, 0x00},
|
||||
{WSA881X_BONGO_RESRV_REG1, 0x00},
|
||||
{WSA881X_BONGO_RESRV_REG2, 0x00},
|
||||
};
|
||||
|
||||
/* Default register reset values for WSA881x rev 2.0 */
|
||||
static struct reg_default wsa881x_rev_2_0[] = {
|
||||
{WSA881X_RESET_CTL, 0x00},
|
||||
{WSA881X_TADC_VALUE_CTL, 0x01},
|
||||
{WSA881X_INTR_MASK, 0x1B},
|
||||
{WSA881X_IOPAD_CTL, 0x00},
|
||||
{WSA881X_OTP_REG_28, 0x3F},
|
||||
{WSA881X_OTP_REG_29, 0x3F},
|
||||
{WSA881X_OTP_REG_30, 0x01},
|
||||
{WSA881X_OTP_REG_31, 0x01},
|
||||
{WSA881X_TEMP_ADC_CTRL, 0x03},
|
||||
{WSA881X_ADC_SEL_IBIAS, 0x45},
|
||||
{WSA881X_SPKR_DRV_GAIN, 0xC1},
|
||||
{WSA881X_SPKR_DAC_CTL, 0x42},
|
||||
{WSA881X_SPKR_BBM_CTL, 0x02},
|
||||
{WSA881X_SPKR_MISC_CTL1, 0x40},
|
||||
{WSA881X_SPKR_MISC_CTL2, 0x07},
|
||||
{WSA881X_SPKR_BIAS_INT, 0x5F},
|
||||
{WSA881X_SPKR_BIAS_PSRR, 0x44},
|
||||
{WSA881X_BOOST_PS_CTL, 0xA0},
|
||||
{WSA881X_BOOST_PRESET_OUT1, 0xB7},
|
||||
{WSA881X_BOOST_LOOP_STABILITY, 0x8D},
|
||||
{WSA881X_SPKR_PROT_ATEST2, 0x02},
|
||||
{WSA881X_BONGO_RESRV_REG1, 0x5E},
|
||||
{WSA881X_BONGO_RESRV_REG2, 0x07},
|
||||
};
|
||||
|
||||
/*
|
||||
* wsa881x_regmap_defaults - update regmap default register values
|
||||
* @regmap: pointer to regmap structure
|
||||
* @version: wsa881x version id
|
||||
*
|
||||
* Update regmap default register values based on version id
|
||||
*
|
||||
*/
|
||||
void wsa881x_regmap_defaults(struct regmap *regmap, u8 version)
|
||||
{
|
||||
u16 ret = 0;
|
||||
|
||||
if (!regmap) {
|
||||
pr_debug("%s: regmap structure is NULL\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (version) {
|
||||
case WSA881X_1_X:
|
||||
ret = regmap_register_patch(regmap,
|
||||
wsa881x_rev_1_x,
|
||||
ARRAY_SIZE(wsa881x_rev_1_x));
|
||||
break;
|
||||
case WSA881X_2_0:
|
||||
ret = regmap_register_patch(regmap,
|
||||
wsa881x_rev_2_0,
|
||||
ARRAY_SIZE(wsa881x_rev_2_0));
|
||||
break;
|
||||
default:
|
||||
pr_debug("%s: unknown version", __func__);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
pr_debug("%s: Failed to update regmap defaults ret= %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
EXPORT_SYMBOL(wsa881x_regmap_defaults);
|
||||
|
||||
static bool wsa881x_readable_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return wsa881x_reg_readable[reg];
|
||||
|
@ -176,8 +253,20 @@ static bool wsa881x_readable_register(struct device *dev, unsigned int reg)
|
|||
static bool wsa881x_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case WSA881X_CHIP_ID0:
|
||||
case WSA881X_CHIP_ID1:
|
||||
case WSA881X_CHIP_ID2:
|
||||
case WSA881X_CHIP_ID3:
|
||||
case WSA881X_BUS_ID:
|
||||
case WSA881X_TEMP_MSB:
|
||||
case WSA881X_TEMP_LSB:
|
||||
case WSA881X_SDM_PDM9_LSB:
|
||||
case WSA881X_SDM_PDM9_MSB:
|
||||
case WSA881X_OTP_CTRL1:
|
||||
case WSA881X_INTR_STATUS:
|
||||
case WSA881X_ATE_TEST_MODE:
|
||||
case WSA881X_PIN_STATUS:
|
||||
case WSA881X_SWR_HM_TEST2:
|
||||
case WSA881X_SPKR_STATUS1:
|
||||
case WSA881X_SPKR_STATUS2:
|
||||
case WSA881X_SPKR_STATUS3:
|
||||
|
@ -187,9 +276,11 @@ static bool wsa881x_volatile_register(struct device *dev, unsigned int reg)
|
|||
case WSA881X_OTP_REG_3:
|
||||
case WSA881X_OTP_REG_4:
|
||||
case WSA881X_OTP_REG_5:
|
||||
case WSA881X_OTP_REG_31:
|
||||
case WSA881X_TEMP_DOUT_MSB:
|
||||
case WSA881X_TEMP_DOUT_LSB:
|
||||
case WSA881X_TEMP_OP:
|
||||
case WSA881X_SPKR_PROT_SAR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -28,6 +28,8 @@ const u8 wsa881x_ana_reg_readable[WSA881X_CACHE_SIZE] = {
|
|||
[WSA881X_CLOCK_CONFIG] = 1,
|
||||
[WSA881X_ANA_CTL] = 1,
|
||||
[WSA881X_SWR_RESET_EN] = 1,
|
||||
[WSA881X_RESET_CTL] = 1,
|
||||
[WSA881X_TADC_VALUE_CTL] = 1,
|
||||
[WSA881X_TEMP_DETECT_CTL] = 1,
|
||||
[WSA881X_TEMP_MSB] = 1,
|
||||
[WSA881X_TEMP_LSB] = 1,
|
||||
|
@ -66,6 +68,7 @@ const u8 wsa881x_ana_reg_readable[WSA881X_CACHE_SIZE] = {
|
|||
[WSA881X_TEMP_DEBUG_MSB] = 1,
|
||||
[WSA881X_TEMP_DEBUG_LSB] = 1,
|
||||
[WSA881X_SAMPLE_EDGE_SEL] = 1,
|
||||
[WSA881X_IOPAD_CTL] = 1,
|
||||
[WSA881X_SPARE_0] = 1,
|
||||
[WSA881X_SPARE_1] = 1,
|
||||
[WSA881X_SPARE_2] = 1,
|
||||
|
|
|
@ -28,6 +28,8 @@ const u8 wsa881x_reg_readable[WSA881X_CACHE_SIZE] = {
|
|||
[WSA881X_CLOCK_CONFIG] = 1,
|
||||
[WSA881X_ANA_CTL] = 1,
|
||||
[WSA881X_SWR_RESET_EN] = 1,
|
||||
[WSA881X_RESET_CTL] = 1,
|
||||
[WSA881X_TADC_VALUE_CTL] = 1,
|
||||
[WSA881X_TEMP_DETECT_CTL] = 1,
|
||||
[WSA881X_TEMP_MSB] = 1,
|
||||
[WSA881X_TEMP_LSB] = 1,
|
||||
|
@ -66,6 +68,7 @@ const u8 wsa881x_reg_readable[WSA881X_CACHE_SIZE] = {
|
|||
[WSA881X_TEMP_DEBUG_MSB] = 1,
|
||||
[WSA881X_TEMP_DEBUG_LSB] = 1,
|
||||
[WSA881X_SAMPLE_EDGE_SEL] = 1,
|
||||
[WSA881X_IOPAD_CTL] = 1,
|
||||
[WSA881X_SPARE_0] = 1,
|
||||
[WSA881X_SPARE_1] = 1,
|
||||
[WSA881X_SPARE_2] = 1,
|
||||
|
|
|
@ -46,6 +46,22 @@ static void calculate_temp(long *temp_val, int dmeas,
|
|||
d2_msb = snd_soc_read(codec, dig_base_addr + WSA881X_OTP_REG_3);
|
||||
d2_lsb = snd_soc_read(codec, dig_base_addr + WSA881X_OTP_REG_4);
|
||||
|
||||
/*
|
||||
* Temperature register values are expected to be in the
|
||||
* following range.
|
||||
* d1_msb = 68 - 92 and d1_lsb = 0, 64, 128, 192
|
||||
* d2_msb = 185 -218 and d2_lsb = 0, 64, 128, 192
|
||||
*/
|
||||
if ((d1_msb < 68 || d1_msb > 92) ||
|
||||
(!(d1_lsb == 0 || d1_lsb == 64 || d1_lsb == 128 ||
|
||||
d1_lsb == 192)) ||
|
||||
(d2_msb < 185 || d2_msb > 218) ||
|
||||
(!(d2_lsb == 0 || d2_lsb == 64 || d2_lsb == 128 ||
|
||||
d2_lsb == 192))){
|
||||
printk_ratelimited("%s: Temperature registers[%d %d %d %d] are out of range\n",
|
||||
__func__, d1_msb, d1_lsb, d2_msb, d2_lsb);
|
||||
}
|
||||
|
||||
d1 = ((d1_msb << 0x8) | d1_lsb) >> 0x6;
|
||||
d2 = ((d2_msb << 0x8) | d2_lsb) >> 0x6;
|
||||
|
||||
|
@ -98,8 +114,9 @@ static int wsa881x_get_temp(struct thermal_zone_device *thermal,
|
|||
*temp = temp_val;
|
||||
if (temp_val <= LOW_TEMP_THRESHOLD ||
|
||||
temp_val >= HIGH_TEMP_THRESHOLD) {
|
||||
pr_err("%s: T0: %ld is out of range [%d, %d]\n", __func__,
|
||||
temp_val, LOW_TEMP_THRESHOLD, HIGH_TEMP_THRESHOLD);
|
||||
printk_ratelimited("%s: T0: %ld is out of range [%d, %d]\n",
|
||||
__func__, temp_val, LOW_TEMP_THRESHOLD,
|
||||
HIGH_TEMP_THRESHOLD);
|
||||
ret = -EAGAIN;
|
||||
goto rel;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,11 @@ struct swr_port {
|
|||
u8 num_ch;
|
||||
};
|
||||
|
||||
enum {
|
||||
WSA881X_DEV_DOWN,
|
||||
WSA881X_DEV_UP,
|
||||
};
|
||||
|
||||
/*
|
||||
* Private data Structure for wsa881x. All parameters related to
|
||||
* WSA881X codec needs to be defined here.
|
||||
|
@ -97,10 +102,12 @@ struct wsa881x_priv {
|
|||
struct wsa881x_tz_priv tz_pdata;
|
||||
int bg_cnt;
|
||||
int clk_cnt;
|
||||
int version;
|
||||
struct mutex bg_lock;
|
||||
struct mutex res_lock;
|
||||
struct snd_info_entry *entry;
|
||||
struct snd_info_entry *version_entry;
|
||||
int state;
|
||||
};
|
||||
|
||||
#define SWR_SLV_MAX_REG_ADDR 0x390
|
||||
|
@ -167,7 +174,12 @@ static ssize_t wsa881x_codec_version_read(struct snd_info_entry *entry,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = snprintf(buffer, sizeof(buffer), "WSA881X-SOUNDWIRE_1_0\n");
|
||||
if (WSA881X_IS_2_0(wsa881x->version))
|
||||
len = snprintf(buffer, sizeof(buffer),
|
||||
"WSA881X-SOUNDWIRE_2_0\n");
|
||||
else
|
||||
len = snprintf(buffer, sizeof(buffer),
|
||||
"WSA881X-SOUNDWIRE_1_0\n");
|
||||
|
||||
return simple_read_from_buffer(buf, count, &pos, buffer, len);
|
||||
}
|
||||
|
@ -398,6 +410,7 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
|
|||
u8 isense1_gain, u8 isense2_gain,
|
||||
u8 vsense_gain)
|
||||
{
|
||||
struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
u8 value = 0;
|
||||
dev_dbg(codec->dev,
|
||||
"%s: enable:%d, isense1 gain: %d, isense2 gain: %d, vsense_gain %d\n",
|
||||
|
@ -406,10 +419,15 @@ static int wsa881x_visense_txfe_ctrl(struct snd_soc_codec *codec, bool enable,
|
|||
if (enable) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_VSENSE_VCM,
|
||||
0x08, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x02, 0x02);
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x1C, 0x04);
|
||||
} else {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_ATEST2,
|
||||
0x02, 0x02);
|
||||
}
|
||||
value = ((isense2_gain << 6) | (isense1_gain << 4) |
|
||||
(vsense_gain << 3));
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PROT_FE_GAIN,
|
||||
|
@ -717,32 +735,48 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w,
|
|||
case SND_SOC_DAPM_PRE_PMU:
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_GAIN, 0xF0, 0x40);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
0x10, 0x10);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG, 0xE0, 0xA0);
|
||||
if (!WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
0x01, 0x01);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V,
|
||||
0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
0x10, 0x10);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG,
|
||||
0xE0, 0xA0);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
/*
|
||||
* 710us delay is needed after PA enable as per
|
||||
* HW requirement.
|
||||
*/
|
||||
usleep_range(710, 720);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG, 0xE0, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
0x10, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V, 0x02, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
0x01, 0x00);
|
||||
/*
|
||||
* 1ms delay is needed before change in gain as per
|
||||
* HW requirement.
|
||||
*/
|
||||
usleep_range(1000, 1010);
|
||||
wsa881x_ramp_pa_gain(codec, G_12DB, G_13P5DB, 1000);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_SEL_IBIAS, 0x70, 0x40);
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
/*
|
||||
* 1ms delay is needed before change in gain as per
|
||||
* HW requirement.
|
||||
*/
|
||||
usleep_range(1000, 1010);
|
||||
wsa881x_ramp_pa_gain(codec, G_13P5DB, G_18DB, 1000);
|
||||
} else {
|
||||
/*
|
||||
* 710us delay is needed after PA enable as per
|
||||
* HW requirement.
|
||||
*/
|
||||
usleep_range(710, 720);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PWRSTG_DBG,
|
||||
0xE0, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_V,
|
||||
0x10, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_MODU_V,
|
||||
0x02, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_EN_DET_TEST_I,
|
||||
0x01, 0x00);
|
||||
/*
|
||||
* 1ms delay is needed before change in gain as per
|
||||
* HW requirement.
|
||||
*/
|
||||
usleep_range(1000, 1010);
|
||||
wsa881x_ramp_pa_gain(codec, G_12DB, G_13P5DB, 1000);
|
||||
snd_soc_update_bits(codec, WSA881X_ADC_SEL_IBIAS,
|
||||
0x70, 0x40);
|
||||
}
|
||||
if (wsa881x->visense_enable) {
|
||||
wsa881x_visense_txfe_ctrl(codec, ENABLE,
|
||||
0x00, 0x03, 0x01);
|
||||
|
@ -813,26 +847,61 @@ EXPORT_SYMBOL(wsa881x_set_channel_map);
|
|||
|
||||
static void wsa881x_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
wsa881x->version = snd_soc_read(codec, WSA881X_CHIP_ID1);
|
||||
wsa881x_regmap_defaults(wsa881x->regmap, wsa881x->version);
|
||||
/* Bring out of analog reset */
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_RST_CTL, 0x02, 0x02);
|
||||
/* Bring out of digital reset */
|
||||
snd_soc_update_bits(codec, WSA881X_CDC_RST_CTL, 0x01, 0x01);
|
||||
/* Set DAC polarity to Rising */
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x02, 0x02);
|
||||
/* set Bias Ref ctrl to 1.225V */
|
||||
snd_soc_update_bits(codec, WSA881X_BIAS_REF_CTRL, 0x07, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BBM_CTL, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0xC0, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL2, 0x07, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_INT, 0x0F, 0x0F);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0xF0, 0x10);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0x0F, 0x0E);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PS_CTL, 0x80, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1, 0xF0, 0xB0);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT2, 0xF0, 0x30);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x0F, 0x0C);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_CURRENT_LIMIT, 0x0F, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_ZX_CTL, 0x20, 0x00);
|
||||
|
||||
if (WSA881X_IS_2_0(wsa881x->version)) {
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0xC0, 0x80);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0x06, 0x06);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0xF0, 0x20);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0x0E, 0x0E);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_LOOP_STABILITY,
|
||||
0x03, 0x03);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_MISC2_CTL, 0xFF, 0x14);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_START_CTL, 0x80, 0x80);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_START_CTL, 0x03, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
|
||||
0x0C, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
|
||||
0x03, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x08, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PS_CTL, 0x80, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_CURRENT_LIMIT,
|
||||
0x0F, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_OCP_CTL, 0x30, 0x30);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_OCP_CTL, 0x0C, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_OTP_REG_28, 0x3F, 0x3A);
|
||||
snd_soc_update_bits(codec, WSA881X_BONGO_RESRV_REG1,
|
||||
0xFF, 0xB2);
|
||||
snd_soc_update_bits(codec, WSA881X_BONGO_RESRV_REG2,
|
||||
0xFF, 0x05);
|
||||
} else {
|
||||
/* Set DAC polarity to Rising */
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DAC_CTL, 0x02, 0x02);
|
||||
/* set Bias Ref ctrl to 1.225V */
|
||||
snd_soc_update_bits(codec, WSA881X_BIAS_REF_CTRL, 0x07, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BBM_CTL, 0x02, 0x02);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL1, 0xC0, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_MISC_CTL2, 0x07, 0x04);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_BIAS_INT, 0x0F, 0x0F);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0xF0, 0x10);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_PA_INT, 0x0F, 0x0E);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PS_CTL, 0x80, 0x00);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT1,
|
||||
0xF0, 0xB0);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_PRESET_OUT2,
|
||||
0xF0, 0x30);
|
||||
snd_soc_update_bits(codec, WSA881X_SPKR_DRV_EN, 0x0F, 0x0C);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_CURRENT_LIMIT,
|
||||
0x0F, 0x08);
|
||||
snd_soc_update_bits(codec, WSA881X_BOOST_ZX_CTL, 0x20, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t wsa881x_resource_acquire(struct snd_soc_codec *codec,
|
||||
|
@ -843,6 +912,32 @@ static int32_t wsa881x_resource_acquire(struct snd_soc_codec *codec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t wsa881x_thermal_resource_acquire(struct snd_soc_codec *codec,
|
||||
bool enable)
|
||||
{
|
||||
struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
struct swr_device *dev;
|
||||
u8 devnum = 0;
|
||||
|
||||
if (!wsa881x) {
|
||||
dev_err(codec->dev, "%s: wsa881x is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
dev = wsa881x->swr_slave;
|
||||
if (dev && (wsa881x->state == WSA881X_DEV_DOWN)) {
|
||||
if (swr_get_logical_dev_num(dev, dev->addr, &devnum)) {
|
||||
dev_err(codec->dev,
|
||||
"%s get devnum %d for dev addr %lx failed\n",
|
||||
__func__, devnum, dev->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
regcache_sync(wsa881x->regmap);
|
||||
}
|
||||
wsa881x_resource_acquire(codec, enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa881x_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct wsa881x_priv *wsa881x = snd_soc_codec_get_drvdata(codec);
|
||||
|
@ -882,10 +977,12 @@ static int wsa881x_probe(struct snd_soc_codec *codec)
|
|||
"%s.%x", "wsatz", (u8)dev->addr);
|
||||
wsa881x->bg_cnt = 0;
|
||||
wsa881x->clk_cnt = 0;
|
||||
wsa881x->state = WSA881X_DEV_UP;
|
||||
wsa881x->tz_pdata.codec = codec;
|
||||
wsa881x->tz_pdata.dig_base = WSA881X_DIGITAL_BASE;
|
||||
wsa881x->tz_pdata.ana_base = WSA881X_ANALOG_BASE;
|
||||
wsa881x->tz_pdata.wsa_resource_acquire = wsa881x_resource_acquire;
|
||||
wsa881x->tz_pdata.wsa_resource_acquire =
|
||||
wsa881x_thermal_resource_acquire;
|
||||
wsa881x_init_thermal(&wsa881x->tz_pdata);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1090,6 +1187,8 @@ static int wsa881x_swr_up(struct swr_device *pdev)
|
|||
ret = wsa881x_gpio_ctrl(wsa881x, true);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "%s: Failed to enable gpio\n", __func__);
|
||||
else
|
||||
wsa881x->state = WSA881X_DEV_UP;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1108,6 +1207,8 @@ static int wsa881x_swr_down(struct swr_device *pdev)
|
|||
ret = wsa881x_gpio_ctrl(wsa881x, false);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "%s: Failed to disable gpio\n", __func__);
|
||||
else
|
||||
wsa881x->state = WSA881X_DEV_DOWN;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,14 @@
|
|||
|
||||
#define WSA881X_MAX_SWR_PORTS 4
|
||||
|
||||
enum {
|
||||
WSA881X_1_X = 0,
|
||||
WSA881X_2_0,
|
||||
};
|
||||
|
||||
#define WSA881X_IS_2_0(ver) \
|
||||
((ver == WSA881X_2_0) ? 1 : 0)
|
||||
|
||||
extern int wsa881x_set_channel_map(struct snd_soc_codec *codec, u8 *port,
|
||||
u8 num_port, unsigned int *ch_mask,
|
||||
unsigned int *ch_rate);
|
||||
|
@ -29,4 +37,6 @@ extern struct regmap_config wsa881x_regmap_config;
|
|||
extern int wsa881x_codec_info_create_codec_entry(
|
||||
struct snd_info_entry *codec_root,
|
||||
struct snd_soc_codec *codec);
|
||||
void wsa881x_regmap_defaults(struct regmap *regmap, u8 version);
|
||||
|
||||
#endif /* _WSA881X_H */
|
||||
|
|
|
@ -2012,6 +2012,8 @@ int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
|
|||
snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
|
||||
snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
|
||||
snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
|
||||
snd_soc_dapm_ignore_suspend(dapm, "HPHL");
|
||||
snd_soc_dapm_ignore_suspend(dapm, "HPHR");
|
||||
}
|
||||
|
||||
snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
|
||||
|
|
|
@ -1578,9 +1578,14 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol,
|
|||
msm_route_ec_ref_rx = 7;
|
||||
ec_ref_port_id = AFE_PORT_ID_SECONDARY_MI2S_RX;
|
||||
break;
|
||||
case 8:
|
||||
msm_route_ec_ref_rx = 8;
|
||||
case 9:
|
||||
msm_route_ec_ref_rx = 9;
|
||||
ec_ref_port_id = SLIMBUS_5_RX;
|
||||
break;
|
||||
case 10:
|
||||
msm_route_ec_ref_rx = 10;
|
||||
ec_ref_port_id = SLIMBUS_1_TX;
|
||||
break;
|
||||
default:
|
||||
msm_route_ec_ref_rx = 0; /* NONE */
|
||||
pr_err("%s EC ref rx %ld not valid\n",
|
||||
|
@ -1599,9 +1604,9 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol,
|
|||
static const char *const ec_ref_rx[] = { "None", "SLIM_RX", "I2S_RX",
|
||||
"PRI_MI2S_TX", "SEC_MI2S_TX",
|
||||
"TERT_MI2S_TX", "QUAT_MI2S_TX", "SEC_I2S_RX", "PROXY_RX",
|
||||
"SLIM_5_RX"};
|
||||
"SLIM_5_RX", "SLIM_1_TX"};
|
||||
static const struct soc_enum msm_route_ec_ref_rx_enum[] = {
|
||||
SOC_ENUM_SINGLE_EXT(9, ec_ref_rx),
|
||||
SOC_ENUM_SINGLE_EXT(11, ec_ref_rx),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new ext_ec_ref_mux_ul1 =
|
||||
|
@ -5760,6 +5765,7 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
{"VOC_EXT_EC MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"},
|
||||
{"VOC_EXT_EC MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"},
|
||||
{"VOC_EXT_EC MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"},
|
||||
{"VOC_EXT_EC MUX", "SLIM_1_TX" , "SLIMBUS_1_TX"},
|
||||
{"CS-VOICE_UL1", NULL, "VOC_EXT_EC MUX"},
|
||||
{"VOIP_UL", NULL, "VOC_EXT_EC MUX"},
|
||||
{"VoLTE_UL", NULL, "VOC_EXT_EC MUX"},
|
||||
|
@ -5771,6 +5777,7 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
{"AUDIO_REF_EC_UL1 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"},
|
||||
{"AUDIO_REF_EC_UL1 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"},
|
||||
{"AUDIO_REF_EC_UL1 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"},
|
||||
{"AUDIO_REF_EC_UL1 MUX", "SLIM_1_TX" , "SLIMBUS_1_TX"},
|
||||
|
||||
{"AUDIO_REF_EC_UL2 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"},
|
||||
{"AUDIO_REF_EC_UL2 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"},
|
||||
|
|
Loading…
Reference in New Issue