Merge "Merge 79477f89b2 on remote branch."

This commit is contained in:
Linux Build Service Account 2015-08-27 16:40:45 -07:00 committed by Gerrit - the friendly Code Review server
commit ebf8b93373
88 changed files with 3737 additions and 543 deletions

View File

@ -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"

View File

@ -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>;
};
};

View File

@ -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 {

View File

@ -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

View File

@ -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>;
};

View File

@ -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 {

View File

@ -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>;

View File

@ -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;
};

View File

@ -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;

View File

@ -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>;

View File

@ -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>;

View File

@ -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";

View File

@ -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;
};
};
};

View File

@ -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 {

View File

@ -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>;

View File

@ -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";

View File

@ -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>;

View File

@ -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;
};
};
};

View File

@ -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>;

View File

@ -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>;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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) {

View File

@ -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", &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;
}

View File

@ -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[] = {

View File

@ -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

View File

@ -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)

View File

@ -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(&notifier_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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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;
};

View File

@ -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,
};
/*****************************************************************************\

View File

@ -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

View File

@ -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",

View File

@ -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",

View File

@ -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();
}
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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, &reg,
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, &reg,
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, &reg, 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 */

View File

@ -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)

View File

@ -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

View File

@ -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

1322
drivers/soc/qcom/vsens.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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

View File

@ -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__);
}

View File

@ -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 = {

View File

@ -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__);
}

View File

@ -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,

View File

@ -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 */

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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");

View File

@ -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"},