Merge "ASoC: msm: qdsp6v2: Update the topology if there is no ACDB"
diff --git a/Documentation/arm/msm/msm_smp2p.txt b/Documentation/arm/msm/msm_smp2p.txt
index 4f77614..77bfb50 100644
--- a/Documentation/arm/msm/msm_smp2p.txt
+++ b/Documentation/arm/msm/msm_smp2p.txt
@@ -128,8 +128,10 @@
| section. |
---------------------------------------------------------------------------
| Feature 3 Bytes Refer to Version |
- | flags and Feature Negotiation Must be set to zero. |
- | section. |
+ | flags and Feature Negotiation |
+ | section for details. |
+ | bit 0 SSR_ACK Feature Supported when set to 1 |
+ | bits 1:31 Reserved Must be set to 0. |
---------------------------------------------------------------------------
| Entries 2 Bytes Total number of Must be 0 or greater. |
| Total entries. |
@@ -137,7 +139,11 @@
| Entries 2 Bytes Number of valid Must be between 0 |
| Valid entries. and Entries Total. |
---------------------------------------------------------------------------
- | Reserved 4 Bytes Reserved Must be set to 0. |
+ | Flags 4 Bytes |
+ | bit 0 RESTART_DONE Toggle for every restart |
+ | bit 1 RESTART_ACK Toggle to ACK remote |
+ | RESTART_DONE |
+ | bits 2:31 Reserved Must be set to 0. |
---------------------------------------------------------------------------
Table 1 - SMEM Item Header
@@ -299,6 +305,12 @@
has changed.
2) Compare Entries Valid to cached value. If changed, initialize new entries.
+Security
+========
+Since the implementation resides in the kernel and does not expose interfaces
+to userspace, no security issues are anticipated. The usage of separate SMEM
+items allows for future security enhancements in SMEM.
+
Performance
===========
No performance issues are anticipated as the signaling rate is expected to be
@@ -311,19 +323,18 @@
To map an entry to the client, the client must add two nodes to the Device
Tree:
- 1) A node that matches "qcom,smp2pgpio" to create the entry
- 2) A node that matches the client driver to provide the GPIO pin mapping
+ 1) A node that matches "qcom,smp2pgpio" to create the entry
+ 2) A node that matches the client driver to provide the GPIO pin mapping
-The details of the device tree entries are contained in the file
-Documentionat/devicetree/bindings/arm/msm/smp2p.txt.
-
+The details of the device tree entries for the GPIO interface are contained in
+the file Documentation/devicetree/bindings/gpio/gpio-smp2p.txt.
/* SMP2P Test Driver for inbound entry. */
smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
qcom,remote-pid = <7>;
- qcom,is_inbound;
+ qcom,is-inbound;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -374,6 +385,48 @@
Please reference the unit test code for example usage.
+Subsystem Restart
+=================
+SMP2P is unaffected by SubSystem Restart (SSR) on the high-level OS side and is
+actually used as an underlying communication mechanism for SSR. On the
+peripheral system that is being restarted, SMP2P will zero out all existing
+state entries upon reboot as part of the SMP2P initialization process and if the
+SSR_ACK feature is enabled, then it waits for an acknowledgement as outlined in
+the following subsections.
+
+SSR_ACK Feature - Reboot Use Case (Non-HLOS Only)
+-------------------------------------------------
+If a remote system boots up after an SSR and sees that the remote and local
+version numbers and feature flags are equal, then it zeros out entry values. If
+the SSR_ACK feature is enabled, it will wait for an acknowledgement from the other
+processor that it has seen the zero entry before completing the negotiation
+sequence.
+
+ if remote and local version numbers and feature flags are equal
+ Zero out all entry values
+ if SSR_ACK feature is enabled
+ Set local RESTART_DONE flag to inverse of the remote RESTART_ACK
+ Send interrupt to remote system
+ Wait for interrupt and for remote RESTART_ACK to be equal to local
+ RESTART_DONE
+ Continue with normal negotiation sequence
+
+Interrupt Use Case
+------------------
+For every interrupt triggered by a remote change, SMP2P will notify the client
+of a change in state. In addition, if the SSR_ACK feature is enabled, the SSR
+handshaking will also be handled.
+
+ if SSR_ACK feature is enabled
+ if remote RESTART_DONE != local RESTART_ACK
+ Notify client of entry change (will be * -> 0 transition)
+ Toggle local RESTART_ACK
+ Send interrupt to remote system
+ else
+ Notify client of entry change as usual
+ else
+ Notify client of entry change as usual
+
Debug
=====
The state values and names for all entries accessible by the Apps are
@@ -395,12 +448,13 @@
Config options
==============
-Configuration of interrupts will be done using Device Tree. By default, the
-testing components will be enabled since it does not affect performance and has
-a minimal impact on kernel size. However, customers can disable the testing
-components for size optimization.
+Configuration of interrupts will be done using Device Tree per the format in
+Documentation/devicetree/bindings/arm/msm/smp2p.txt. By default, the testing
+components will be enabled since it does not affect performance and has a
+minimal impact on kernel size. However, customers can disable the testing
+component for size optimization.
- CONFIG_MSM_SMP2P - enables SMP2P core functionality
+ CONFIG_MSM_SMP2P - enables SMP2P
CONFIG_MSM_SMP2P_TEST - enables unit test support
Dependencies
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 4e3abc2..a0b2f6d 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -22,16 +22,12 @@
should be 1 for SVS corner
- regulator-max-microvolt: Maximum corner value as max constraint, which
should be 4 for SUPER_TURBO or 3 for TURBO
-- qcom,pvs-bin-process: A list of integers whose length is equal to 2 to
- the power of qcom,pvs-fuse[num-of-bits]. The location or
- 0-based index of an element in the list corresponds
- to the bin number. The value of each integer
- corresponds to the PVS process speed of the APC
- silicon for a chip with one of these cases:
- 1 = APC_PVS_SLOW
- 2 = APC_PVS_NOM
- 3 = APC_PVS_FAST
- 0 or other values = No PVS
+- qcom,pvs-init-voltage: A list of integers whose length is equal to 2
+ to the power of qcom,pvs-fuse[num-of-bits]. The
+ location or 0-based index of an element in the
+ list corresponds to the bin number. The value of
+ each integer corresponds to the initial voltage
+ of the PVS bin in turbo mode in microvolts.
- qcom,pvs-corner-ceiling-slow: Ceiling voltages of all corners for APC_PVS_SLOW
- qcom,pvs-corner-ceiling-nom: Ceiling voltages of all corners for APC_PVS_NOM
- qcom,pvs-corner-ceiling-fast: Ceiling voltages of all corners for APC_PVS_FAST
@@ -155,8 +151,14 @@
qcom,pvs-fuse-redun-sel = <22 24 3 2>;
qcom,pvs-fuse-redun = <22 27 5>;
- qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
- 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
+ qcom,pvs-init-voltage = <1330000 1330000 1330000 1320000
+ 1310000 1300000 1290000 1280000
+ 1270000 1260000 1250000 1240000
+ 1230000 1220000 1210000 1200000
+ 1190000 1180000 1170000 1160000
+ 1150000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1140000>;
qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index 7f7ee25..17ff3f0 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -95,16 +95,24 @@
- coresight-ctis : list of ctis that this component interacts with
- qcom,pc-save : program counter save implemented
- qcom,blk-size : block size for tmc-etr to usb transfers
+- qcom,memory-size : size of coherent memory to be allocated for tmc-etr buffer
- qcom,round-robin : indicates if per core etms are allowed round-robin access
by the funnel
- qcom,reset-flush-race : indicates if a race exists between flushing and ddr
being put into self-refresh during watchdog reset
- qcom,write-64bit : only 64bit data writes supported by stm
-- vdd-supply: phandle to the regulator device tree node. Used for tpiu component
-- qcom,vdd-voltage-level : specifies voltage level for vdd supply. Should be
- specified in pairs (min, max) with units being uV
-- qcom,vdd-current-level : specifies current load levels for vdd supply. Should
- be specified in paris (lpm, hpm) with units being uA
+- <supply-name>-supply: phandle to the regulator device tree node. The required
+ <supply-name> is "vdd" for SD card and "vdd-io" for SD
+ I/O supply. Used for tpiu component
+- qcom,<supply>-voltage-level : specifies voltage level for vdd supply. Should
+ be specified in pairs (min, max) with units
+ being uV. Here <supply> can be "vdd" for SD card
+ vdd supply or "vdd-io" for SD I/O vdd supply.
+- qcom,<supply>-current-level : specifies current load levels for vdd supply.
+ Should be specified in pairs (lpm, hpm) with
+ units being uA. Here <supply> can be "vdd" for
+ SD card vdd supply or "vdd-io" for SD I/O vdd
+ supply.
- qcom,seta-gpios : specifies gpios included in set A that are routed to the
mictor connector. Used for tpiu component
- qcom,seta-gpios-func : active function select for set A gpios
@@ -138,6 +146,7 @@
interrupt-names = "byte-cntr-irq";
qcom,byte-cntr-absent;
+ qcom,memory-size = <0x100000>;
coresight-id = <0>;
coresight-name = "coresight-tmc-etr";
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index 81dd825..7187908 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -44,6 +44,8 @@
- qcom,platform-enable-gpio: Specifies the panel lcd/display enable gpio.
- qcom,platform-reset-gpio: Specifies the panel reset gpio.
- qcom,platform-te-gpio: Specifies the gpio used for TE.
+- qcom,platform-mode-gpio: Select video/command mode of panel through gpio when it supports
+ both modes.
- qcom,platform-reset-sequence: An array that lists the
sequence of reset gpio values and sleeps
Each command will have the format defined
@@ -74,6 +76,7 @@
qcom,platform-reset-gpio = <&msmgpio 25 1>;
qcom,platform-te-gpio = <&msmgpio 24 0>;
qcom,platform-enable-gpio = <&msmgpio 58 1>;
+ qcom,platform-mode-gpio = <&msmgpio 7 0>;
qcom,platform-reset-sequence = <1 25 0 20 1 10>;
qcom,platform-supply-entry1 {
qcom,supply-name = "vdd";
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index fc162a4..9ad8abe 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -228,6 +228,10 @@
to the physical width in the framebuffer information.
- qcom,mdss-pan-physical-height-dimension: Specifies panel physical height in mm which corresponds
to the physical height in the framebuffer information.
+- qcom,mdss-dsi-panel-mode-gpio-state: String that specifies the mode state for panel if it is defined
+ in dsi controller.
+ "high" = Set GPIO to HIGH
+ "low" = Set GPIO to LOW
Note, if a given optional qcom,* binding is not present, then the driver will configure
@@ -316,5 +320,6 @@
qcom,mdss-dsi-pwm-gpio = <&pm8941_mpps 5 0>;
qcom,mdss-pan-physical-width-dimension = <60>;
qcom,mdss-pan-physical-height-dimension = <140>;
+ qcom,mdss-dsi-panel-mode-gpio-state = "low";
};
};
diff --git a/Documentation/devicetree/bindings/input/misc/stk-stk3x1x.txt b/Documentation/devicetree/bindings/input/misc/stk-stk3x1x.txt
index aa50140..59136ee 100644
--- a/Documentation/devicetree/bindings/input/misc/stk-stk3x1x.txt
+++ b/Documentation/devicetree/bindings/input/misc/stk-stk3x1x.txt
@@ -25,6 +25,10 @@
- stk,ps-thdl : Low threshold for proximity sensor, sensor will report
"far" if the proximity sensor reading is larger than this value.
+Optional properties:
+
+ - stk,use-fir : Boolean to enable light data jitter suppressing FIR filter.
+
Example:
i2c@f9925000 {
stk@48 {
@@ -43,4 +47,5 @@
stk,wait-reg = <0x07>;
stk,ps-thdh = <1700>;
stk,ps-thdl = <1500>;
+ stk,use-fir;
};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index 8fd813c..4f9307a 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -18,10 +18,14 @@
- synaptics,button-map : virtual key code mappings to be used
- synaptics,x-flip : modify orientation of the x axis
- synaptics,y-flip : modify orientation of the y axis
- - synaptics,panel-x : panel x dimension
- - synaptics,panel-y : panel y dimension
+ - synaptics,panel-coords : touch panel min x, min y, max x and
+ max y resolution
+ - synaptics,display-coords : display min x, min y, max x and
+ max y resolution
+ - synaptics,reset-delay : reset delay for controller (ms), default 100
- synaptics,fw-image-name : name of firmware .img file in /etc/firmware
- synaptics,power-down : fully power down regulators in suspend
+ - synaptics,do-lockdown : perform one time lockdown procedure
Example:
i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index cc2506d..6f6f68d 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -12,6 +12,7 @@
Optional properties:
- reg : offset and length of the register set for the device.
- interrupts : should contain the vidc interrupt.
+- vdd-supply : regulator to supply venus.
- qcom,vidc-cp-map : start and size of device virtual address range for
secure buffers. Video hardware uses this address range to identify if
the buffers are secure or non-secure.
@@ -66,6 +67,7 @@
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
interrupts = <0 44 0>;
+ vdd-supply = <&gdsc_venus>;
qcom,vidc-cp-map = <0x1000000 0x40000000>;
qcom,vidc-ns-map = <0x40000000 0x40000000>;
qcom,load-freq-tbl = <979200 410000000>,
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 1162298..b076475 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -13,7 +13,15 @@
to determine whether the BMS is using an internal or external
rsense to accumulate the Coulomb Counter and read current.
-Additionally, an optional subnode may be included:
+Additionally, optional subnodes may be included:
+- qcom,batt-pres-status : A subnode with a register address for the SMBB
+ battery interface's BATT_PRES_STATUS register. If this node is
+ added, then the BMS will try to detect offmode battery removal
+ via the battery interface's offmode battery removal circuit.
+- qcom,soc-storage-reg : A subnode with a register address to a spare PMIC
+ register. If this node is included, then the BMS will store its
+ shutdown SOC in the specified register instead of the default
+ BMS data register.
- qcom,battery-data : A phandle to a node containing the available batterydata
profiles. See the batterydata bindings documentation for more
details.
@@ -75,8 +83,8 @@
- qcom,min-fcc-learning-soc: An interger value which defines the minimum SOC
to start FCC learning. This is applicable only if
FCC learning is enabled.
-- qcom,min-fcc-ocv-pc: An interger value which defines the minimum PC-lookup(OCV)
- to start FCC learning. This is applicable only if
+- qcom,min-fcc-ocv-pc: An interger value which defines the minimum PC-lookup
+ (OCV) to start FCC learning. This is applicable only if
FCC learning is enabled.
- qcom,min-fcc-learning-samples: An interger value which defines the minimum
number of the FCC measurement cycles required to
@@ -103,14 +111,23 @@
- qcom,use-ocv-thresholds : A boolean that controls whether BMS will take
new OCVs only between the defined thresholds.
- qcom,enable-fcc-learning: A boolean that defines if FCC learning is enabled.
-- qcom,bms-adc_tm: Corresponding ADC_TM device's phandle to set recurring measurements
- and receive notifications for die_temperature, vbatt.
+- qcom,bms-adc_tm: Corresponding ADC_TM device's phandle to set recurring
+ measurements and receive notifications for
+ die_temperature and vbatt.
+qcom,batt-pres-status node required properties:
+- reg : offset and length of the PMIC SMBB battery interface BATT_PRES_STATUS
+ register.
-All sub node required properties:
+qcom,soc-storage-reg node required properties:
+- reg : address and length of the spare PMIC register that the BMS will store
+ shutdown SoC in.
+
+qcom,bms-iadc node required properties:
- reg : offset and length of the PMIC peripheral register map.
qcom,bms-bms node required properties:
+- reg : offset and length of the PMIC peripheral register map.
- interrupts : the interrupt mappings.
The format should be
<slave-id peripheral-id interrupt-number>.
@@ -156,6 +173,10 @@
qcom,bms-iadc = <&pm8941_iadc>;
qcom,bms-adc_tm = <&pm8941_adc_tm>;
+ qcom,batt-pres-status@1208 {
+ reg = <0x1208 0x1>;
+ }
+
qcom,bms-iadc@3800 {
reg = <0x3800 0x100>;
};
diff --git a/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt b/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
index 95be46c..3bb63de 100644
--- a/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
@@ -18,6 +18,8 @@
- qcom,channel-id: channel Id for the PWM.
Optional device bindings:
+- qcom,force-pwm-size: For certain LPG channels, PWM size can be forced.
+ Possible values 6, 7, 8 and 9.
- qcom,channel-owner: A string value to supply owner information.
- qcom,mode-select: 0 = PWM mode
1 = LPG mode
@@ -110,6 +112,7 @@
<0xb040 0x80>;
reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
qcom,channel-id = <1>;
+ qcom,force-pwm-size = <9>;
qcom,period = <6000000>;
status = "okay";
qcom,pwm {
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index ad1b5ad..44ed2dc 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -164,7 +164,8 @@
for DMA latency in microsecs.
- qcom,android-usb-cdrom : if this property is present then device creates
a new LUN as CD-ROM
-
+- qcom,android-usb-internal-ums : if this property is present then device
+ creates a new LUN as internal usb mass storage
Example Android USB device node :
android_usb@fc42b0c8 {
compatible = "qcom,android-usb";
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index f2a9940..53e912a 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -52,6 +52,10 @@
- qcom,dwc_usb3-adc_tm: Corresponding ADC_TM device's phandle to set recurring
measurements on USB_ID channel when using ADC and receive
notifications for set thresholds.
+- qcom,dwc-usb3-msm-tx-fifo-size: If present, represents RAM size available for
+ TX fifo allocation in bytes
+- qcom,dwc-usb3-msm-qdss-tx-fifo-size: If present, represent RAM size available
+ for TX fifo allocation in QDSS composition
Sub nodes:
- Sub node for "DWC3- USB3 controller".
@@ -76,6 +80,8 @@
qcom,vdd-voltage-level = <1 5 7>;
qcom,dwc-hsphy-init = <0x00D195A4>;
qcom,dwc_usb3-adc_tm = <&pm8941_adc_tm>;
+ qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
+ qcom,dwc-usb3-msm-qdss-tx-fifo-size = <16384>;
qcom,msm_bus,name = "usb3";
qcom,msm_bus,num_cases = <2>;
diff --git a/arch/arm/boot/dts/apq8026-v1-cdp.dts b/arch/arm/boot/dts/apq8026-v1-cdp.dts
index 7b40738..d7e283b 100644
--- a/arch/arm/boot/dts/apq8026-v1-cdp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-cdp.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026 CDP";
compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
- qcom,msm-id = <199 1 0>,
- <219 1 0>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v1-mtp.dts b/arch/arm/boot/dts/apq8026-v1-mtp.dts
index ccf1741..d24875c 100644
--- a/arch/arm/boot/dts/apq8026-v1-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-mtp.dts
@@ -18,8 +18,7 @@
/ {
model = "Qualcomm APQ 8026 MTP";
compatible = "qcom,apq8026-mtp", "qcom,apq8026", "qcom,mtp";
- qcom,msm-id = <199 8 0>,
- <219 8 0>;
+ qcom,board-id = <8 0>;
};
&cci {
diff --git a/arch/arm/boot/dts/apq8026-v1-xpm.dts b/arch/arm/boot/dts/apq8026-v1-xpm.dts
index 78ae609..f69511b 100644
--- a/arch/arm/boot/dts/apq8026-v1-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v1-xpm.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026 XPM";
compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
- qcom,msm-id = <199 14 0>,
- <219 14 0>;
+ qcom,board-id = <14 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v1.dtsi b/arch/arm/boot/dts/apq8026-v1.dtsi
index 7fbfcb5..eaea002 100644
--- a/arch/arm/boot/dts/apq8026-v1.dtsi
+++ b/arch/arm/boot/dts/apq8026-v1.dtsi
@@ -21,6 +21,8 @@
/ {
model = "Qualcomm APQ 8026";
compatible = "qcom,apq8026";
+ qcom,msm-id = <199 0>,
+ <219 0x20000>;
};
&tsens {
diff --git a/arch/arm/boot/dts/apq8026-v2-cdp.dts b/arch/arm/boot/dts/apq8026-v2-cdp.dts
index 3fb3c29..cb68779 100644
--- a/arch/arm/boot/dts/apq8026-v2-cdp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-cdp.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026v2 CDP";
compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
- qcom,msm-id = <199 1 0x20000>,
- <219 1 0x20000>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v2-mtp.dts b/arch/arm/boot/dts/apq8026-v2-mtp.dts
index e620859..40856c8 100644
--- a/arch/arm/boot/dts/apq8026-v2-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-mtp.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026v2 MTP";
compatible = "qcom,apq8026-mtp", "qcom,apq8026", "qcom,mtp";
- qcom,msm-id = <199 8 0x20000>,
- <219 8 0x20000>;
+ qcom,board-id = <8 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v2-xpm.dts b/arch/arm/boot/dts/apq8026-v2-xpm.dts
index 2848b2e..324516d 100644
--- a/arch/arm/boot/dts/apq8026-v2-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v2-xpm.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026v2 XPM";
compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
- qcom,msm-id = <199 14 0x20000>,
- <219 14 0x20000>;
+ qcom,board-id = <14 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v2.dtsi b/arch/arm/boot/dts/apq8026-v2.dtsi
index 4c0d3ce..3ee8d94 100644
--- a/arch/arm/boot/dts/apq8026-v2.dtsi
+++ b/arch/arm/boot/dts/apq8026-v2.dtsi
@@ -21,6 +21,8 @@
/ {
model = "Qualcomm APQ 8026";
compatible = "qcom,apq8026";
+ qcom,msm-id = <199 0x20000>,
+ <219 0x20000>;
};
&tsens {
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 943f2a3..8eed58e 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -75,8 +75,6 @@
compatible = "qcom,cache_dump";
qcom,l1-dump-size = <0x100000>;
qcom,l2-dump-size = <0x500000>;
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
};
rpm_bus: qcom,rpm-smd {
diff --git a/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
new file mode 100644
index 0000000..23091f0
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
@@ -0,0 +1,80 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_generic_720p_cmd: qcom,mdss_dsi_generic_720p_cmd {
+ qcom,mdss-dsi-panel-name = "generic 720p cmd mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <768>;
+ qcom,mdss-dsi-panel-height = <1280>;
+ qcom,mdss-dsi-h-front-porch = <26>;
+ qcom,mdss-dsi-h-back-porch = <26>;
+ qcom,mdss-dsi-h-pulse-width = <26>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <2>;
+ qcom,mdss-dsi-v-front-porch = <2>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [05 01 00 00 78 00 01 11
+ 15 01 00 00 0a 00 02 36 00
+ 05 01 00 00 0a 00 01 29
+ 15 01 00 00 0a 00 02 53 24
+ 15 01 00 00 0a 00 02 35 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 0a 00 01 34
+ 05 01 00 00 78 00 01 10
+ 05 01 00 00 78 00 01 28
+ 15 01 00 00 0a 00 02 53 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = <1>;
+ qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;
+ qcom,mdss-dsi-te-v-sync-continues-lines = <0x3c>;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-panel-timings = [6e 26 1b 00 35 34 20 28 17 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x20>;
+ qcom,mdss-dsi-t-clk-pre = <0x2a>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,mdss-dsi-bl-pmic-bank-select = <7>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
new file mode 100644
index 0000000..9d244d8
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
@@ -0,0 +1,122 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_hx8379a_wvga_vid: qcom,mdss_dsi_hx8379a_wvga_video {
+ qcom,mdss-dsi-panel-name = "HX8379A wvga video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <480>;
+ qcom,mdss-dsi-panel-height = <800>;
+ qcom,mdss-dsi-h-front-porch = <70>;
+ qcom,mdss-dsi-h-back-porch = <100>;
+ qcom,mdss-dsi-h-pulse-width = <40>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <6>;
+ qcom,mdss-dsi-v-front-porch = <6>;
+ qcom,mdss-dsi-v-pulse-width = <4>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 39 01 00 00 00 00 04
+ B9 FF 83 79
+ 39 01 00 00 00 00 03
+ BA 51 93
+ 39 01 00 00 00 00 14
+ B1 00 50 44
+ EA 8D 08 11
+ 11 11 27 2F
+ 9A 1A 42 0B
+ 6E F1 00 E6
+ 39 01 00 00 00 00 0E
+ B2 00 00 3C
+ 08 04 19 22
+ 00 FF 08 04
+ 19 20
+ 39 01 00 00 00 00 20
+ B4 82 08 00
+ 32 10 03 32
+ 13 70 32 10
+ 08 37 01 28
+ 07 37 08 3C
+ 08 44 44 08
+ 00 40 08 28
+ 08 30 30 04
+ 39 01 00 00 00 00 30
+ D5 00 00 0A
+ 00 01 05 00
+ 03 00 88 88
+ 88 88 23 01
+ 67 45 02 13
+ 88 88 88 88
+ 88 88 88 88
+ 88 88 54 76
+ 10 32 31 20
+ 88 88 88 88
+ 88 88 00 00
+ 00 00 00 00
+ 39 01 00 00 00 00 24
+ E0 79 05 0F
+ 14 26 29 3F
+ 2B 44 04 0E
+ 12 15 18 16
+ 16 12 15 05
+ 0F 14 26 29
+ 3F 2B 44 04
+ 0E 12 15 18
+ 16 16 12 15
+ 23 01 00 00 00 00 02
+ cc 02
+ 39 01 00 00 00 00 05
+ B6 00 9C 00 9C
+ 05 01 00 00 96 00 02
+ 11 00
+ 05 01 00 00 78 00 02
+ 29 00
+ ];
+ qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = <2>;
+ qcom,mdss-dsi-lane-map = <1>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-panel-timings = [75 1A 11 00 3D 45 15 1D 1C 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
index 357b024..829197a 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
@@ -242,13 +242,13 @@
29 01 00 00 00 00 03 E6 34 34
23 01 00 00 00 00 02 E7 05
29 01 00 00 00 00 06 F0 55 AA 52 00 00
- 05 01 00 00 32 00 02 11 00
- 05 01 00 00 96 00 02 29 00
+ 05 01 00 00 00 00 02 11 00
+ 05 01 00 00 14 00 02 29 00
29 01 00 00 00 00 06 F0 55 AA 52 08 01
29 01 00 00 00 00 06 F0 55 AA 52 00 00
29 01 00 00 00 00 02 53 2C];
- qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
- 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 00 00 02 28 00
+ 05 01 00 00 00 00 02 10 00];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
diff --git a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
new file mode 100644
index 0000000..89a5063
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
@@ -0,0 +1,266 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_otm8018b_fwvga_vid: qcom,mdss_dsi_otm8018b_fwvga_video {
+ qcom,mdss-dsi-panel-name = "OTM8018b fwvga video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <480>;
+ qcom,mdss-dsi-panel-height = <854>;
+ qcom,mdss-dsi-h-front-porch = <80>;
+ qcom,mdss-dsi-h-back-porch = <54>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <16>;
+ qcom,mdss-dsi-v-front-porch = <12>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 04
+ ff 80 09 01
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 03
+ ff 80 09
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 02
+ d6 48
+ 29 01 00 00 00 00 02
+ 00 03
+ 29 01 00 00 00 00 02
+ ff 01
+ 29 01 00 00 00 00 02
+ 00 B4
+ 29 01 00 00 00 00 02
+ C0 10
+ 29 01 00 00 00 00 02
+ 00 82
+ 29 01 00 00 00 00 02
+ C5 A3
+ 29 01 00 00 00 00 02
+ 00 90
+ 29 01 00 00 00 00 03
+ C5 96 87
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 03
+ D8 74 72
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 02
+ D9 56
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 11
+ E1 00 06 0A
+ 07 03 16 08
+ 0A 04 06 07
+ 08 0F 23 22
+ 05
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 11
+ E2 00 06 0A
+ 07 03 16 08
+ 0A 04 06 07
+ 08 0F 23 22
+ 05
+ 29 01 00 00 00 00 02
+ 00 81
+ 29 01 00 00 00 00 02
+ C1 77
+ 29 01 00 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 00 02
+ C1 EA
+ 29 01 00 00 00 00 02
+ 00 A1
+ 29 01 00 00 00 00 02
+ C1 08
+ 29 01 00 00 00 00 02
+ 00 89
+ 29 01 00 00 00 00 02
+ C4 08
+ 29 01 00 00 00 00 02
+ 00 81
+ 29 01 00 00 00 00 02
+ C4 83
+ 29 01 00 00 00 00 02
+ 00 92
+ 29 01 00 00 00 00 02
+ C5 01
+ 29 01 00 00 00 00 02
+ 00 B1
+ 29 01 00 00 00 00 02
+ C5 A9
+ 29 01 00 00 00 00 02
+ 00 92
+ 29 01 00 00 00 00 02
+ B3 45
+ 29 01 00 00 00 00 02
+ 00 90
+ 29 01 00 00 00 00 02
+ B3 02
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 06
+ C0 00 58 00
+ 14 16
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 02
+ C4 30
+ 29 01 00 00 00 00 02
+ 00 90
+ 29 01 00 00 00 00 07
+ C0 00 44 00
+ 00 00 03
+ 29 01 00 00 00 00 02
+ 00 A6
+ 29 01 00 00 00 00 04
+ C1 01 00 00
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 0D
+ CE 87 03 00
+ 85 03 00 86
+ 03 00 84 03
+ 00
+ 29 01 00 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 00 0f
+ CE 38 03 03
+ 58 00 00 00
+ 38 02 03 59
+ 00 00 00
+ 29 01 00 00 00 00 02
+ 00 B0
+ 29 01 00 00 00 00 0f
+ CE 38 01 03
+ 5A 00 00 00
+ 38 00 03 5B
+ 00 00 00
+ 29 01 00 00 00 00 02
+ 00 C0
+ 29 01 00 00 00 00 0f
+ CE 30 00 03
+ 5C 00 00 00
+ 30 01 03 5D
+ 00 00 00
+ 29 01 00 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 00 0f
+ CE 30 02 03
+ 5E 00 00 00
+ 30 03 03 5F
+ 00 00 00
+ 29 01 00 00 00 00 02
+ 00 C7
+ 29 01 00 00 00 00 02
+ CF 00
+ 29 01 00 00 00 00 02
+ 00 C9
+ 29 01 00 00 00 00 02
+ CF 00
+ 29 01 00 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 00 02
+ CF 00
+ 29 01 00 00 00 00 02
+ 00 C4
+ 29 01 00 00 00 00 07
+ CB 04 04 04
+ 04 04 04
+ 29 01 00 00 00 00 02
+ 00 D9
+ 29 01 00 00 00 00 07
+ CB 04 04 04
+ 04 04 04
+ 29 01 00 00 00 00 02
+ 00 84
+ 29 01 00 00 00 00 07
+ CC 0C 0A 10
+ 0E 03 04
+ 29 01 00 00 00 00 02
+ 00 9E
+ 29 01 00 00 00 00 02
+ CC 0B
+ 29 01 00 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 00 06
+ CC 09 0F 0D
+ 01 02
+ 29 01 00 00 00 00 02
+ 00 B4
+ 29 01 00 00 00 00 07
+ CC 0D 0F 09
+ 0B 02 01
+ 29 01 00 00 00 00 02
+ 00 CE
+ 29 01 00 00 00 00 02
+ CC 0E
+ 29 01 00 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 00 06
+ CC 10 0A 0C
+ 04 03
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 04
+ ff ff ff ff
+ 05 01 00 00 78 00 02
+ 11 00
+ 05 01 00 00 32 00 02
+ 29 00
+ ];
+ qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = <1>;
+ qcom,mdss-dsi-lane-map = <1>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-panel-timings = [8B 1F 14 00 45 4A 19 23 23 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
new file mode 100644
index 0000000..7bb414a
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
@@ -0,0 +1,119 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_ssd2080m_720_vid: qcom,mdss_dsi_ssd2080m_720p_video {
+ qcom,mdss-dsi-panel-name = "ssd2080m 720p video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <720>;
+ qcom,mdss-dsi-panel-height = <1280>;
+ qcom,mdss-dsi-h-front-porch = <80>;
+ qcom,mdss-dsi-h-back-porch = <24>;
+ qcom,mdss-dsi-h-pulse-width = <14>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <15>;
+ qcom,mdss-dsi-v-front-porch = <12>;
+ qcom,mdss-dsi-v-pulse-width = <10>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [15 01 00 00 00 00 02 FF 01
+ 29 01 00 00 00 00 05 C6 63 00 81 31
+ 29 01 00 00 00 00 05 CB E7 80 73 33
+ 29 01 00 00 00 00 02 EC D2
+ 29 01 00 00 00 00 03 B3 04 9F
+ 29 01 00 00 00 00 04 B2 16 1E 10
+ 29 01 00 00 00 00 02 B4 00
+ 29 01 00 00 00 00 02 C1 04
+ 29 01 00 00 00 00 04 C2 BE 00 58
+ 29 01 00 00 00 00 09 C3 01 22 11 21 0E 80 80 24
+ 29 01 00 00 00 00 08 B6 09 16 42 01 13 00 00
+ 29 01 00 00 00 00 04 B7 24 26 43
+ 29 01 00 00 00 00 06 B8 16 08 25 44 08
+ 29 01 00 00 00 00 09 B9 06 08 07 09 00 00 00 00
+ 29 01 00 00 00 00 09 BA 0E 10 0A 0C 16 05 00 00
+ 29 01 00 00 00 00 09 BB A1 A1 A1 A1 00 00 00 00
+ 29 01 00 00 00 00 09 BC 0F 11 0B 0D 16 05 00 00
+ 29 01 00 00 00 00 09 BD A1 A1 A1 A1 00 00 00 00
+ 29 01 00 00 00 00 04 E6 FF FF 0F
+ 29 01 00 00 00 00 02 C7 3F
+ 29 01 00 00 00 00 07 B5 47 00 00 08 00 01
+ 29 01 00 00 00 00 08 C4 DF 72 12 12 66 E3 99
+ 29 01 00 00 00 00 07 D0 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D1 28 27 14 02 01
+ 29 01 00 00 00 00 07 D2 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D3 28 27 14 02 01
+ 29 01 00 00 00 00 07 D4 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D5 28 27 14 02 01
+ 29 01 00 00 00 00 07 D6 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D7 28 27 14 02 01
+ 29 01 00 00 00 00 07 D8 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D9 28 27 14 02 01
+ 29 01 00 00 00 00 07 DA 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 DB 28 27 14 02 01
+ 29 01 00 00 00 00 03 CC 10 00
+ 29 01 00 00 00 00 04 CE 4E 55 A5
+ 29 01 00 00 00 00 04 E0 01 02 02
+ 29 01 00 00 00 00 05 F6 00 00 00 00
+ 29 01 00 00 00 00 05 F7 00 00 00 00
+ 29 01 00 00 00 00 03 E1 90 00
+ 29 01 00 00 00 00 03 DE 95 CF
+ 29 01 00 00 00 00 02 CF 46
+ 29 01 00 00 00 00 03 C5 77 47
+ 29 01 00 00 00 00 03 ED 00 20
+ 05 01 00 00 B4 00 02 11 00
+ 05 01 00 00 82 00 02 29 00
+ 15 01 00 00 00 00 02 53 2c];
+
+ qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 10 00
+ 05 01 00 00 32 00 02 53 00
+ 05 01 00 00 00 00 02 c2 00
+ 39 01 00 00 00 00 02 cf 40
+ 05 01 00 00 50 00 03 de 84 00
+ 39 01 00 00 00 00 02 cb 22
+ 05 01 00 00 00 00 02 c3 00];
+
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = <2>;
+ qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-panel-timings = [a8 1f 17 00 2f 2d 1c 21 29 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x20>;
+ qcom,mdss-dsi-t-clk-pre = <0x2f>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
new file mode 100644
index 0000000..f6e6df8
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
@@ -0,0 +1,170 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_truly_wvga_cmd: qcom,mdss_dsi_truly_wvga_cmd {
+ qcom,mdss-dsi-panel-name = "Truly WVGA command mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-mode-gpio-state = "low";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <480>;
+ qcom,mdss-dsi-panel-height = <800>;
+ qcom,mdss-dsi-h-front-porch = <160>;
+ qcom,mdss-dsi-h-back-porch = <40>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <10>;
+ qcom,mdss-dsi-v-front-porch = <12>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 05 01 00 00 00 00 02
+ 01 00
+ 23 01 00 00 00 00 02
+ b0 04
+ 29 01 00 00 00 00 03
+ b3 02 00
+ 29 01 00 00 00 00 03
+ b6 51 83
+ 29 01 00 00 00 00 05
+ b7 00 80 15 25
+ 29 01 00 00 00 00 14
+ b8 00 07 07 ff c8 c8 01 18 10 10
+ 37 5a 87 de ff 00 00 00 00
+ 29 01 00 00 00 00 05
+ b9 00 00 00 00
+ 23 01 00 00 00 00 02
+ bd 00
+ 29 01 00 00 00 00 03
+ c0 02 43
+ 29 01 00 00 00 00 10
+ c1 43 31 99 21 20 00 10 28 0c 0c
+ 00 00 00 21 01
+ 29 01 00 00 00 00 07
+ c2 28 06 06 01 03 00
+ 29 01 00 00 00 00 04
+ c3 40 00 03
+ 29 01 00 00 00 00 03
+ 6f 03 00
+ 29 01 00 00 00 00 03
+ c4 00 01
+ 29 01 00 00 00 00 03
+ c6 00 00
+ 29 01 00 00 00 00 06
+ c7 11 8d a0 f5 27
+ 29 01 00 00 00 00 19
+ c8 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 19
+ c9 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 19
+ ca 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 11
+ d0 99 03 ce a6 00 43 20 10 01 00
+ 01 01 00 03 01 00
+ 29 01 00 00 00 00 08
+ d1 18 0C 23 03 75 02 50
+ 23 01 00 00 00 00 02
+ d3 33
+ 29 01 00 00 00 00 03
+ d5 2a 2a
+ 29 01 00 00 00 00 02
+ d6 28
+ 29 01 00 00 00 00 10
+ d7 01 00 aa c0 2a 2c 22 12 71 0a 12 00 a0
+ 00 03
+ 29 01 00 00 00 00 09
+ d8 44 44 22 44 21 46 42 40
+ 29 01 00 00 00 00 04
+ d9 cf 2d 51
+ 29 01 00 00 00 00 02
+ da 01
+ 29 01 00 00 00 00 03
+ de 01 4f
+ 29 01 00 00 00 00 07
+ e1 00 00 00 00 00 00
+ 23 01 00 00 00 00 02
+ e6 4f
+ 29 01 00 00 00 00 06
+ f3 06 00 00 24 00
+ 29 01 00 00 00 00 02
+ f8 00
+ 23 01 00 00 00 00 02
+ fa 03
+ 29 01 00 00 00 00 04
+ fb 00 00 00
+ 29 01 00 00 00 00 06
+ fc 00 00 00 00 00
+ 29 01 00 00 00 00 05
+ fd 00 00 70 00
+ 39 01 00 00 00 00 05
+ 2a 00 00 01 df
+ 39 01 00 00 00 00 05
+ 2b 00 00 03 1f
+ 15 01 00 00 00 00 02
+ 35 00
+ 39 01 00 00 00 00 03
+ 44 00 50
+ 15 01 00 00 00 00 02
+ 36 41
+ 15 01 00 00 00 00 02
+ 3a 77
+ 05 01 00 00 7D 00 02
+ 11 00
+ 05 01 00 00 3c 00 02
+ 29 00
+ ];
+ qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = <1>;
+ qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;
+ qcom,mdss-dsi-te-v-sync-continues-lines = <0x3c>;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-panel-timings = [5D 12 0C 00 33 38 10 16 1E 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <2>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
new file mode 100644
index 0000000..fae4834
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
@@ -0,0 +1,168 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_truly_wvga_vid: qcom,mdss_dsi_truly_wvga_video {
+ qcom,mdss-dsi-panel-name = "Truly WVGA video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-mode-gpio-state = "high";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <480>;
+ qcom,mdss-dsi-panel-height = <800>;
+ qcom,mdss-dsi-h-front-porch = <160>;
+ qcom,mdss-dsi-h-back-porch = <40>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <10>;
+ qcom,mdss-dsi-v-front-porch = <12>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 05 01 00 00 00 00 02
+ 01 00
+ 23 01 00 00 00 00 02
+ b0 04
+ 29 01 00 00 00 00 03
+ b3 02 00
+ 29 01 00 00 00 00 03
+ b6 51 83
+ 29 01 00 00 00 00 05
+ b7 00 80 15 25
+ 29 01 00 00 00 00 14
+ b8 00 07 07 ff c8 c8 01 18 10 10
+ 37 5a 87 de ff 00 00 00 00
+ 29 01 00 00 00 00 05
+ b9 00 00 00 00
+ 23 01 00 00 00 00 02
+ bd 00
+ 29 01 00 00 00 00 03
+ c0 02 43
+ 29 01 00 00 00 00 10
+ c1 43 31 99 21 20 00 10 28 0c 0c
+ 00 00 00 21 01
+ 29 01 00 00 00 00 07
+ c2 28 06 06 01 03 00
+ 29 01 00 00 00 00 04
+ c3 40 00 03
+ 29 01 00 00 00 00 03
+ 6f 03 00
+ 29 01 00 00 00 00 03
+ c4 00 01
+ 29 01 00 00 00 00 03
+ c6 00 00
+ 29 01 00 00 00 00 06
+ c7 11 8d a0 f5 27
+ 29 01 00 00 00 00 19
+ c8 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 19
+ c9 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 19
+ ca 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 11
+ d0 99 03 ce a6 00 43 20 10 01 00
+ 01 01 00 03 01 00
+ 29 01 00 00 00 00 08
+ d1 18 0C 23 03 75 02 50
+ 23 01 00 00 00 00 02
+ d3 33
+ 29 01 00 00 00 00 03
+ d5 2a 2a
+ 29 01 00 00 00 00 02
+ d6 28
+ 29 01 00 00 00 00 10
+ d7 01 00 aa c0 2a 2c 22 12 71 0a 12 00 a0
+ 00 03
+ 29 01 00 00 00 00 09
+ d8 44 44 22 44 21 46 42 40
+ 29 01 00 00 00 00 04
+ d9 cf 2d 51
+ 29 01 00 00 00 00 02
+ da 01
+ 29 01 00 00 00 00 03
+ de 01 4f
+ 29 01 00 00 00 00 07
+ e1 00 00 00 00 00 00
+ 23 01 00 00 00 00 02
+ e6 4f
+ 29 01 00 00 00 00 06
+ f3 06 00 00 24 00
+ 29 01 00 00 00 00 02
+ f8 00
+ 23 01 00 00 00 00 02
+ fa 03
+ 29 01 00 00 00 00 04
+ fb 00 00 00
+ 29 01 00 00 00 00 06
+ fc 00 00 00 00 00
+ 29 01 00 00 00 00 05
+ fd 00 00 70 00
+ 39 01 00 00 00 00 05
+ 2a 00 00 01 df
+ 39 01 00 00 00 00 05
+ 2b 00 00 03 1f
+ 15 01 00 00 00 00 02
+ 35 00
+ 39 01 00 00 00 00 03
+ 44 00 50
+ 15 01 00 00 00 00 02
+ 36 c1
+ 15 01 00 00 00 00 02
+ 3a 77
+ 05 01 00 00 7D 00 02
+ 11 00
+ 05 01 00 00 3c 00 02
+ 29 00
+ ];
+ qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+ 05 01 00 00 78 00 02 10 00
+ 23 01 00 00 10 00 02
+ b0 04
+ 23 01 00 00 20 00 02
+ b1 01];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = <1>;
+ qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-panel-timings = [5D 12 0C 00 33 38 10 16 1E 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ };
+};
diff --git a/arch/arm/boot/dts/fsm9900.dtsi b/arch/arm/boot/dts/fsm9900.dtsi
index b74e58f..1c48bf0 100644
--- a/arch/arm/boot/dts/fsm9900.dtsi
+++ b/arch/arm/boot/dts/fsm9900.dtsi
@@ -78,8 +78,6 @@
compatible = "qcom,cache_dump";
qcom,l1-dump-size = <0x100000>;
qcom,l2-dump-size = <0x500000>;
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
};
qcom,ion {
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 1820dc7..6969940 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -315,7 +315,7 @@
qcom,v-cutoff-uv = <3400000>;
qcom,max-voltage-uv = <4200000>;
qcom,r-conn-mohm = <0>;
- qcom,shutdown-soc-valid-limit = <20>;
+ qcom,shutdown-soc-valid-limit = <100>;
qcom,adjust-soc-low-threshold = <15>;
qcom,ocv-voltage-high-threshold-uv = <3750000>;
qcom,ocv-voltage-low-threshold-uv = <3650000>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 5642d4d..5734b9c 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -189,7 +189,7 @@
qcom,v-cutoff-uv = <3400000>;
qcom,max-voltage-uv = <4200000>;
qcom,r-conn-mohm = <0>;
- qcom,shutdown-soc-valid-limit = <20>;
+ qcom,shutdown-soc-valid-limit = <100>;
qcom,adjust-soc-low-threshold = <15>;
qcom,ocv-voltage-high-threshold-uv = <3750000>;
qcom,ocv-voltage-low-threshold-uv = <3650000>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 583cd3c..98d2f5e 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -120,7 +120,7 @@
qcom,v-cutoff-uv = <3400000>;
qcom,max-voltage-uv = <4200000>;
qcom,r-conn-mohm = <0>;
- qcom,shutdown-soc-valid-limit = <20>;
+ qcom,shutdown-soc-valid-limit = <100>;
qcom,adjust-soc-low-threshold = <15>;
qcom,ocv-voltage-high-threshold-uv = <3750000>;
qcom,ocv-voltage-low-threshold-uv = <3650000>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index 5d7a7ec..fa5c739 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -31,6 +31,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6f {
compatible = "qcom,ov8825";
reg = <0x6f>;
@@ -75,6 +82,7 @@
qcom,slave-id = <0x20 0x0016 0x0135>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator1>;
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
cam_vdig-supply = <&pm8226_l5>;
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index cbfdfc9..ec3f248 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -19,8 +19,7 @@
interrupts = <0 166 0>;
interrupt-names = "byte-cntr-irq";
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+ qcom,memory-size = <0x100000>;
coresight-id = <0>;
coresight-name = "coresight-tmc-etr";
@@ -41,6 +40,11 @@
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <9000 800000>;
+
+ vdd-io-supply = <&pm8226_l21>;
+
+ qcom,vdd-io-voltage-level = <2950000 2950000>;
+ qcom,vdd-io-current-level = <6 22000>;
};
replicator: replicator@fc31c000 {
diff --git a/arch/arm/boot/dts/msm8226-mdss-panels.dtsi b/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
index 8194bf6..eeec175 100644
--- a/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
@@ -15,3 +15,4 @@
/include/ "dsi-panel-nt35521-720p-video.dtsi"
/include/ "dsi-panel-nt35596-1080p-video.dtsi"
/include/ "dsi-panel-nt35590-720p-cmd.dtsi"
+/include/ "dsi-panel-ssd2080m-720p-video.dtsi"
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 947cc93..2ec7b6c 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -67,7 +67,7 @@
vdd-supply = <&pm8226_l15>;
vddio-supply = <&pm8226_l8>;
vdda-supply = <&pm8226_l4>;
- qcom,platform-reset-gpio = <&msmgpio 25 1>;
+ qcom,platform-reset-gpio = <&msmgpio 25 0>;
qcom,platform-te-gpio = <&msmgpio 24 0>;
qcom,platform-strength-ctrl = [ff 06];
qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index c178dbf..53e0578 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -114,10 +114,10 @@
"MIC BIAS1 External", "Handset Mic",
"AMIC2", "MIC BIAS2 External",
"MIC BIAS2 External", "Headset Mic",
- "AMIC4", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCRight Headset Mic",
- "AMIC5", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCLeft Headset Mic";
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Analog Mic3",
+ "AMIC4", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Analog Mic4";
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
@@ -238,7 +238,7 @@
qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
- qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+ qcom,clk-rates = <400000 25000000 50000000>;
#address-cells = <0>;
interrupt-parent = <&sdhc_2>;
@@ -454,6 +454,7 @@
&slim_msm {
tapan_codec {
qcom,cdc-micbias1-ext-cap;
+ qcom,cdc-micbias3-ext-cap;
};
};
@@ -472,6 +473,7 @@
&android_usb {
qcom,android-usb-cdrom;
+ qcom,android-usb-internal-ums;
};
&mdss_mdp {
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 5b3da9b..838592c 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -41,9 +41,14 @@
qcom,pvs-fuse = <22 6 5>;
qcom,pvs-fuse-redun = <22 27 5>;
- qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
- 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
- qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
+ qcom,pvs-init-voltage = <1275000 1275000 1275000 1275000 1275000
+ 1275000 1260000 1245000 1230000 1215000
+ 1200000 1185000 1170000 1155000 1140000
+ 1140000 1140000 1140000 1140000 1140000
+ 1150000 1140000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1275000 1275000
+ 1275000 1275000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000>;
qcom,pvs-corner-ceiling-nom = <1050000 1075000 1200000>;
qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
diff --git a/arch/arm/boot/dts/msm8226-v1-cdp.dts b/arch/arm/boot/dts/msm8226-v1-cdp.dts
index c721df2..e426a97 100644
--- a/arch/arm/boot/dts/msm8226-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v1-cdp.dts
@@ -17,13 +17,5 @@
/ {
model = "Qualcomm MSM 8226 CDP";
compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
- qcom,msm-id = <145 1 0>,
- <158 1 0>,
- <159 1 0>,
- <198 1 0>,
- <205 1 0>,
- <220 1 0>,
- <221 1 0>,
- <222 1 0>,
- <223 1 0>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-v1-mtp.dts b/arch/arm/boot/dts/msm8226-v1-mtp.dts
index 95d88a7..08d7cec 100644
--- a/arch/arm/boot/dts/msm8226-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v1-mtp.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226 MTP";
compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
- qcom,msm-id = <145 8 0>,
- <158 8 0>,
- <159 8 0>,
- <198 8 0>,
- <205 8 0>,
- <220 8 0>,
- <221 8 0>,
- <222 8 0>,
- <223 8 0>;
+ qcom,board-id = <8 0>;
};
&cci {
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
index f8fd0c2..7e9f91b 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226 QRD";
compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
- qcom,msm-id = <145 0x2000b 0>,
- <158 0x2000b 0>,
- <159 0x2000b 0>,
- <198 0x2000b 0>,
- <205 0x2000b 0>,
- <220 0x2000b 0>,
- <221 0x2000b 0>,
- <222 0x2000b 0>,
- <223 0x2000b 0>;
+ qcom,board-id = <0x2000b 0>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
index bc5d8e7..c93d9db 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226 QRD";
compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
- qcom,msm-id = <145 11 0>,
- <158 11 0>,
- <159 11 0>,
- <198 11 0>,
- <205 11 0>,
- <220 11 0>,
- <221 11 0>,
- <222 11 0>,
- <223 11 0>;
+ qcom,board-id = <11 0>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-v2-cdp.dts b/arch/arm/boot/dts/msm8226-v2-cdp.dts
index 7c955dd..3d40180 100644
--- a/arch/arm/boot/dts/msm8226-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-cdp.dts
@@ -18,13 +18,5 @@
/ {
model = "Qualcomm MSM 8226v2 CDP";
compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
- qcom,msm-id = <145 1 0x20000>,
- <158 1 0x20000>,
- <159 1 0x20000>,
- <198 1 0x20000>,
- <205 1 0x20000>,
- <220 1 0x20000>,
- <221 1 0x20000>,
- <222 1 0x20000>,
- <223 1 0x20000>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-v2-mtp.dts b/arch/arm/boot/dts/msm8226-v2-mtp.dts
index dfdc5db..6034107 100644
--- a/arch/arm/boot/dts/msm8226-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-mtp.dts
@@ -18,13 +18,5 @@
/ {
model = "Qualcomm MSM 8226v2 MTP";
compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
- qcom,msm-id = <145 8 0x20000>,
- <158 8 0x20000>,
- <159 8 0x20000>,
- <198 8 0x20000>,
- <205 8 0x20000>,
- <220 8 0x20000>,
- <221 8 0x20000>,
- <222 8 0x20000>,
- <223 8 0x20000>;
+ qcom,board-id = <8 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index e492720..13402af 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226v2 QRD";
compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
- qcom,msm-id = <145 0x2000b 0x20000>,
- <158 0x2000b 0x20000>,
- <159 0x2000b 0x20000>,
- <198 0x2000b 0x20000>,
- <205 0x2000b 0x20000>,
- <220 0x2000b 0x20000>,
- <221 0x2000b 0x20000>,
- <222 0x2000b 0x20000>,
- <223 0x2000b 0x20000>;
+ qcom,board-id = <0x2000b 0>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
index 83c7034..b707d1c 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226v2 QRD";
compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
- qcom,msm-id = <145 11 0x20000>,
- <158 11 0x20000>,
- <159 11 0x20000>,
- <198 11 0x20000>,
- <205 11 0x20000>,
- <220 11 0x20000>,
- <221 11 0x20000>,
- <222 11 0x20000>,
- <223 11 0x20000>;
+ qcom,board-id = <11 0>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index c2ce546..a57adcd 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -33,28 +33,33 @@
&pm8226_l3 {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1337500>;
};
&pm8226_l3_ao {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1337500>;
};
&pm8226_l3_so {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1337500>;
};
&pm8226_s2 {
regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1280000>;
+ regulator-max-microvolt = <1330000>;
};
&apc_vreg_corner {
- qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
- 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
- qcom,pvs-corner-ceiling-slow = <1050000 1160000 1280000>;
+ qcom,pvs-init-voltage = <1330000 1330000 1330000 1320000 1310000
+ 1300000 1290000 1280000 1270000 1260000
+ 1250000 1240000 1230000 1220000 1210000
+ 1200000 1190000 1180000 1170000 1160000
+ 1150000 1140000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1140000 1140000
+ 1140000 1140000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1280000>;
qcom,pvs-corner-ceiling-nom = <1050000 1080000 1200000>;
qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
qcom,cpr-step-quotient = <30>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 0ae0fc6..483aad1 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -33,7 +33,7 @@
adsp_mem: adsp_region {
linux,contiguous-region;
- reg = <0 0x2000000>;
+ reg = <0 0x2a00000>;
label = "adsp_mem";
};
@@ -158,6 +158,7 @@
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
interrupts = <0 44 0>;
+ vdd-supply = <&gdsc_venus>;
qcom,load-freq-tbl = <352800 160000000>,
<244800 133330000>,
<108000 66700000>;
@@ -200,6 +201,12 @@
};
};
+ qcom,vidc {
+ compatible = "qcom,msm-vidc";
+ qcom,hfi = "q6";
+ qcom,max-hw-load = <108000>; /* 720p @ 30 * 1 */
+ };
+
qcom,wfd {
compatible = "qcom,msm-wfd";
};
@@ -437,6 +444,10 @@
qcom,msm-dai-q6-dev-id = <8>;
};
+ qcom,msm-lsm-client {
+ compatible = "qcom,msm-lsm-client";
+ };
+
qcom,msm-dai-q6 {
compatible = "qcom,msm-dai-q6";
qcom,msm-dai-q6-sb-0-rx {
@@ -479,6 +490,11 @@
qcom,msm-dai-q6-dev-id = <16393>;
};
+ qcom,msm-dai-q6-sb-5-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16395>;
+ };
+
qcom,msm-dai-q6-bt-sco-rx {
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <12288>;
diff --git a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
index 1b4a594..e133117 100644
--- a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
@@ -38,6 +38,78 @@
qcom,cci-master = <0>;
};
+ eeprom0: qcom,eeprom@6a {
+ cell-index = <0>;
+ reg = <0x6a 0x0>;
+ qcom,eeprom-name = "truly_cm7700";
+ compatible = "qcom,msm_eeprom";
+ qcom,slave-addr = <0x6c>;
+ qcom,num-blocks = <9>;
+ 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 0x3d84 2 0x8 1 1>;
+ qcom,pageen1 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll1 = <0 0x0 2 0 1 1>;
+ qcom,mem1 = <32 0x3d00 2 0 1 0>;
+ qcom,page2 = <1 0x3d84 2 0x9 1 1>;
+ qcom,pageen2 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll2 = <0 0x0 2 0 1 1>;
+ qcom,mem2 = <32 0x3d00 2 0 1 0>;
+ qcom,page3 = <1 0x3d84 2 0xa 1 1>;
+ qcom,pageen3 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll3 = <0 0x0 2 0 1 1>;
+ qcom,mem3 = <32 0x3d00 2 0 1 0>;
+ qcom,page4 = <1 0x3d84 2 0xb 1 1>;
+ qcom,pageen4 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll4 = <0 0x0 2 0 1 1>;
+ qcom,mem4 = <32 0x3d00 2 0 1 0>;
+ qcom,page5 = <1 0x3d84 2 0xc 1 1>;
+ qcom,pageen5 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll5 = <0 0x0 2 0 1 1>;
+ qcom,mem5 = <32 0x3d00 2 0 1 0>;
+ qcom,page6 = <1 0x3d84 2 0xd 1 1>;
+ qcom,pageen6 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll6 = <0 0x0 2 0 1 1>;
+ qcom,mem6 = <32 0x3d00 2 0 1 0>;
+ qcom,page7 = <1 0x3d84 2 0xe 1 1>;
+ qcom,pageen7 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll7 = <0 0x0 2 0 1 1>;
+ qcom,mem7 = <32 0x3d00 2 0 1 0>;
+ qcom,page8 = <1 0x3d84 2 0xf 1 1>;
+ qcom,pageen8 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll8 = <0 0x0 2 0 1 1>;
+ qcom,mem8 = <32 0x3d00 2 0 1 0>;
+
+ cam_vdig-supply = <&pm8110_l2>;
+ cam_vio-supply = <&pm8110_l14>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio";
+ qcom,cam-vreg-type = <0 0 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 1800000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000>;
+ qcom,cam-vreg-op-mode = <200000 8000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 13 0>,
+ <&msmgpio 21 0>,
+ <&msmgpio 20 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,cam-power-seq-type = "sensor_vreg",
+ "sensor_vreg", "sensor_clk",
+ "sensor_gpio", "sensor_gpio";
+ qcom,cam-power-seq-val = "cam_vdig",
+ "cam_vio", "sensor_cam_mclk",
+ "sensor_gpio_reset",
+ "sensor_gpio_standby";
+ qcom,cam-power-seq-cfg-val = <1 1 24000000 1 1>;
+ qcom,cam-power-seq-delay = <1 1 5 5 10>;
+ };
+
qcom,camera@6f {
compatible = "qcom,ov8825";
reg = <0x6f>;
@@ -46,6 +118,7 @@
qcom,csid-sd-index = <0>;
qcom,actuator-src = <&actuator0>;
qcom,led-flash-src = <&led_flash0>;
+ qcom,eeprom-src = <&eeprom0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov8825";
cam_vdig-supply = <&pm8110_l2>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dtsi b/arch/arm/boot/dts/msm8610-cdp.dtsi
index 8403dfd..f0d1715 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8610-cdp.dtsi
@@ -121,19 +121,16 @@
};
};
- sound {
- qcom,audio-routing =
- "RX_BIAS", "MCLK",
- "INT_LDO_H", "MCLK",
- "MIC BIAS External", "Handset Mic",
- "MIC BIAS Internal2", "Headset Mic",
- "AMIC1", "MIC BIAS External",
- "AMIC2", "MIC BIAS Internal2";
+ sound {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "MIC BIAS External", "Handset Mic",
+ "MIC BIAS Internal2", "Headset Mic",
+ "AMIC1", "MIC BIAS External",
+ "AMIC2", "MIC BIAS Internal2";
+ qcom,headset-jack-type-NC;
};
-
- qcom,dsi_v2_truly_wvga_video {
- qcom,cont-splash-enabled;
- };
};
&i2c_cdc {
@@ -399,3 +396,19 @@
qcom,setb-gpios-pull = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>;
qcom,setb-gpios-dir = <2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2>;
};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_truly_wvga_vid>;
+};
+
+&dsi_truly_wvga_vid {
+ qcom,cont-splash-enabled;
+};
+
+&dsi_truly_wvga_cmd {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 98a99a7..78a4b5a 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -19,8 +19,7 @@
interrupts = <0 166 0>;
interrupt-names = "byte-cntr-irq";
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+ qcom,memory-size = <0x100000>;
coresight-id = <0>;
coresight-name = "coresight-tmc-etr";
@@ -41,6 +40,11 @@
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <15000 400000>;
+
+ vdd-io-supply = <&pm8110_l21>;
+
+ qcom,vdd-io-voltage-level = <2950000 2950000>;
+ qcom,vdd-io-current-level = <200 50000>;
};
replicator: replicator@fc324000 {
diff --git a/arch/arm/boot/dts/msm8610-mdss-panels.dtsi b/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
new file mode 100644
index 0000000..243d7e8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
@@ -0,0 +1,17 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "dsi-panel-truly-wvga-video.dtsi"
+/include/ "dsi-panel-truly-wvga-cmd.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
+/include/ "dsi-panel-otm8018b-fwvga-video.dtsi"
+/include/ "dsi-panel-hx8379a-wvga-video.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index d0fc1dc..f37a42b 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -11,7 +11,7 @@
*/
&soc {
- qcom,mdss_mdp@fd900000 {
+ mdss_mdp: qcom,mdss_mdp@fd900000 {
compatible = "qcom,mdss_mdp3";
reg = <0xfd900000 0x100000>;
reg-names = "mdp_phys";
@@ -29,7 +29,62 @@
cell-index = <0>;
reg = <0xfdd00000 0x100000>;
interrupts = <0 30 0>;
- vdda-supply = <&pm8110_l4>;
+ vdd-supply = <&pm8110_l4>;
+ vdda-supply = <&pm8110_l19>;
+ vddio-supply = <&pm8110_l14>;
qcom,mdss-fb-map = <&mdss_fb0>;
+ qcom,mdss-mdp = <&mdss_mdp>;
+ qcom,platform-reset-gpio = <&msmgpio 41 0>;
+ qcom,platform-te-gpio = <&msmgpio 12 0>;
+ qcom,platform-mode-gpio = <&msmgpio 7 0>;
+
+ qcom,platform-reset-sequence = <1 20 0 2 1 20 2>;
+
+ qcom,platform-strength-ctrl = [ff 06];
+ qcom,platform-bist-ctrl = [03 03 00 00 0f 00];
+ qcom,platform-regulator-settings = [02 08 05 00 20 03];
+ qcom,platform-lane-config = [80 45 00 00 01 66
+ 80 45 00 00 01 66
+ 80 45 00 00 01 66
+ 80 45 00 00 01 66
+ 40 67 00 00 01 88];
+
+ qcom,platform-supply-entry1 {
+ qcom,supply-name = "vdd";
+ qcom,supply-min-voltage = <1200000>;
+ qcom,supply-max-voltage = <1200000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-pre-on-sleep = <0>;
+ qcom,supply-post-on-sleep = <20>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <20>;
+ };
+
+ qcom,platform-supply-entry2 {
+ qcom,supply-name = "vddio";
+ qcom,supply-min-voltage = <1800000>;
+ qcom,supply-max-voltage = <1800000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-pre-on-sleep = <0>;
+ qcom,supply-post-on-sleep = <0>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <0>;
+ };
+
+ qcom,platform-supply-entry3 {
+ qcom,supply-name = "vdda";
+ qcom,supply-min-voltage = <2850000>;
+ qcom,supply-max-voltage = <2850000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-pre-on-sleep = <0>;
+ qcom,supply-post-on-sleep = <0>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <0>;
+ };
};
};
+
+/include/ "msm8610-mdss-panels.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 798fab4..56ef7ca 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -187,10 +187,6 @@
"AMIC2", "MIC BIAS Internal2",
"AMIC3", "MIC BIAS External";
};
-
- qcom,dsi_v2_truly_wvga_video {
- qcom,cont-splash-enabled;
- };
};
&i2c_cdc {
@@ -414,3 +410,19 @@
&pm8110_bms {
status = "ok";
};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_truly_wvga_vid>;
+};
+
+&dsi_truly_wvga_vid {
+ qcom,cont-splash-enabled;
+};
+
+&dsi_truly_wvga_cmd {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
index ae28e2c..86f1210 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
@@ -28,10 +28,6 @@
qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
};
- qcom,dsi_v2_hx8379a_wvga_video {
- qcom,cont-splash-enabled;
- };
-
usb@f9a55000 {
qcom,hsusb-otg-phy-init-seq =
<0x44 0x80 0x6a 0x81 0x34 0x82 0x13 0x83 0xffffffff>;
@@ -62,3 +58,15 @@
qcom,scale-function = <7>;
};
};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_hx8379a_wvga_vid>;
+};
+
+&dsi_hx8379a_wvga_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
index 649bc71..17bf329 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
@@ -82,6 +82,7 @@
stk,wait-reg = <0x07>;
stk,ps-thdh = <150>;
stk,ps-thdl = <100>;
+ stk,use-fir;
};
};
@@ -89,10 +90,6 @@
qcom,hsusb-otg-phy-init-seq =
<0x44 0x80 0x6a 0x81 0x34 0x82 0x23 0x83 0xffffffff>;
};
-
- qcom,dsi_v2_otm8018b_fwvga_video {
- qcom,cont-splash-enabled;
- };
};
/ {
@@ -112,3 +109,15 @@
&pm8110_chg {
qcom,battery-data = <&qrd_batterydata>;
};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_otm8018b_fwvga_vid>;
+};
+
+&dsi_otm8018b_fwvga_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index df61ca6..3fb33e9 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -364,4 +364,5 @@
&android_usb {
qcom,android-usb-cdrom;
+ qcom,android-usb-internal-ums;
};
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 1929b50..eb69678 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -42,10 +42,15 @@
qcom,pvs-fuse = <23 6 5>;
qcom,pvs-fuse-redun = <61 47 5>;
- qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1>;
- qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000>;
- qcom,pvs-corner-ceiling-nom = <1050000 1075000 1200000>;
+ qcom,pvs-init-voltage = <1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000>;
+ qcom,pvs-corner-ceiling-slow = <1150000 1150000 1275000>;
+ qcom,pvs-corner-ceiling-nom = <1075000 1075000 1200000>;
qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
vdd-apc-supply = <&pm8110_s2>;
diff --git a/arch/arm/boot/dts/msm8610-v1-cdp.dts b/arch/arm/boot/dts/msm8610-v1-cdp.dts
index ba0851f..beb3976 100644
--- a/arch/arm/boot/dts/msm8610-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-v1-cdp.dts
@@ -14,7 +14,6 @@
/include/ "msm8610-v1.dtsi"
/include/ "msm8610-cdp.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
/ {
diff --git a/arch/arm/boot/dts/msm8610-v1-mtp.dts b/arch/arm/boot/dts/msm8610-v1-mtp.dts
index 010903f..82992a3 100644
--- a/arch/arm/boot/dts/msm8610-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-v1-mtp.dts
@@ -14,7 +14,6 @@
/include/ "msm8610-v1.dtsi"
/include/ "msm8610-mtp.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
/ {
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index 2a619db..4a2de1c 100644
--- a/arch/arm/boot/dts/msm8610-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
@@ -168,6 +168,7 @@
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
<2 216>, /* tsens_upper_lower_int */
+ <41 63>, /* dino_gen_purpose_irq35 */
<0xff 18>, /* APC_qgicQTmrSecPhysIrptReq */
<0xff 19>, /* APC_qgicQTmrNonSecPhysIrptReq */
<0xff 35>, /* WDT_barkInt */
diff --git a/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
index ba53acc..ec8c4c6 100644
--- a/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
@@ -14,7 +14,6 @@
/include/ "msm8610-v1.dtsi"
/include/ "msm8610-qrd-skuaa.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
/include/ "msm8610-qrd-camera-sensor.dtsi"
/ {
diff --git a/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
index 5e19997..b3350bb 100644
--- a/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
@@ -14,7 +14,6 @@
/include/ "msm8610-v1.dtsi"
/include/ "msm8610-qrd-skuab.dtsi"
-/include/ "dsi-v2-panel-otm8018b-fwvga-video.dtsi"
/include/ "msm8612-qrd-camera-sensor.dtsi"
/ {
diff --git a/arch/arm/boot/dts/msm8610-v2-cdp.dts b/arch/arm/boot/dts/msm8610-v2-cdp.dts
index 51ef7a2..a6d1d9c 100644
--- a/arch/arm/boot/dts/msm8610-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-v2-cdp.dts
@@ -14,7 +14,6 @@
/include/ "msm8610-v2.dtsi"
/include/ "msm8610-cdp.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
/ {
diff --git a/arch/arm/boot/dts/msm8610-v2-mtp.dts b/arch/arm/boot/dts/msm8610-v2-mtp.dts
index e1c9bb8..405a775 100644
--- a/arch/arm/boot/dts/msm8610-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-v2-mtp.dts
@@ -14,7 +14,6 @@
/include/ "msm8610-v2.dtsi"
/include/ "msm8610-mtp.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
/ {
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index e593b31..079f0b1 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -170,6 +170,7 @@
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
<2 216>, /* tsens_upper_lower_int */
+ <41 63>, /* dino_gen_purpose_irq35 */
<0xff 56>, /* q6_wdog_expired_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
@@ -212,45 +213,43 @@
qcom,gpio-parent = <&msmgpio>;
qcom,gpio-map = <3 1>,
- <4 4 >,
- <5 5 >,
- <6 9 >,
- <7 13>,
- <8 17>,
- <9 21>,
- <10 27>,
- <11 29>,
- <12 31>,
- <13 33>,
- <14 35>,
- <15 37>,
- <16 38>,
- <17 39>,
- <18 41>,
- <19 46>,
- <20 48>,
- <21 49>,
- <22 50>,
- <23 51>,
- <24 52>,
- <25 54>,
- <26 62>,
- <27 63>,
- <28 64>,
- <29 65>,
- <30 66>,
- <31 67>,
- <32 68>,
- <33 69>,
- <34 71>,
- <35 72>,
- <36 106>,
- <37 107>,
- <38 108>,
- <39 109>,
- <40 110>,
- <54 111>,
- <55 113>;
+ <4 5 >,
+ <5 9 >,
+ <6 14>,
+ <7 15>,
+ <8 32>,
+ <9 33>,
+ <10 34>,
+ <11 35>,
+ <12 41>,
+ <13 42>,
+ <14 72>,
+ <15 73>,
+ <16 74>,
+ <17 75>,
+ <18 76>,
+ <19 77>,
+ <20 78>,
+ <21 79>,
+ <22 80>,
+ <23 81>,
+ <24 82>,
+ <25 83>,
+ <26 84>,
+ <27 85>,
+ <28 87>,
+ <29 90>,
+ <30 91>,
+ <31 92>,
+ <32 93>,
+ <33 94>,
+ <34 95>,
+ <35 96>,
+ <36 97>,
+ <37 98>,
+ <38 99>,
+ <39 100>,
+ <40 101>;
};
qcom,pm-8x60@fe805664 {
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
index 677365f..44df025 100644
--- a/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
@@ -14,7 +14,6 @@
/include/ "msm8610-v2.dtsi"
/include/ "msm8610-qrd-skuaa.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
/include/ "msm8610-qrd-camera-sensor.dtsi"
/ {
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
index ccc38fc..92908fb 100644
--- a/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
@@ -14,7 +14,6 @@
/include/ "msm8610-v2.dtsi"
/include/ "msm8610-qrd-skuab.dtsi"
-/include/ "dsi-v2-panel-otm8018b-fwvga-video.dtsi"
/include/ "msm8612-qrd-camera-sensor.dtsi"
/ {
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 89a7cff..7dcb985 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -944,15 +944,11 @@
&gdsc_vfe {
qcom,clock-names = "core_clk", "iface_clk", "bus_clk";
- qcom,skip-logic-collapse;
- qcom,retain-periph;
- qcom,retain-mem;
status = "ok";
};
&gdsc_oxili_cx {
qcom,clock-names = "core_clk", "iface_clk", "mem_clk";
- qcom,skip-logic-collapse;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8926-cdp.dts b/arch/arm/boot/dts/msm8926-cdp.dts
index 677ca7e..7d8d6cf 100644
--- a/arch/arm/boot/dts/msm8926-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-cdp.dts
@@ -19,8 +19,7 @@
/ {
model = "Qualcomm MSM 8926 CDP";
compatible = "qcom,msm8926-cdp", "qcom,msm8926", "qcom,cdp";
- qcom,msm-id = <200 1 0>,
- <224 1 0>;
+ qcom,board-id = <1 0>;
};
&pm8226_chg {
diff --git a/arch/arm/boot/dts/msm8926-mtp.dts b/arch/arm/boot/dts/msm8926-mtp.dts
index 1c9b7dc..624781b 100644
--- a/arch/arm/boot/dts/msm8926-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-mtp.dts
@@ -19,6 +19,5 @@
/ {
model = "Qualcomm MSM 8926 MTP";
compatible = "qcom,msm8926-mtp", "qcom,msm8926", "qcom,mtp";
- qcom,msm-id = <200 8 0>,
- <224 8 0>;
+ qcom,board-id = <8 0>;
};
diff --git a/arch/arm/boot/dts/msm8926-qrd-skug.dts b/arch/arm/boot/dts/msm8926-qrd-skug.dts
index 8fb0878..b7826e5 100644
--- a/arch/arm/boot/dts/msm8926-qrd-skug.dts
+++ b/arch/arm/boot/dts/msm8926-qrd-skug.dts
@@ -34,3 +34,11 @@
&pm8226_chg {
qcom,battery-data = <&qrd_batterydata>;
};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_ssd2080m_720_vid>;
+};
+
+&dsi_ssd2080m_720_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-qrd.dts
index 6a66e4b..8ee8828 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-qrd.dts
@@ -17,6 +17,5 @@
/ {
model = "Qualcomm MSM 8926 QRD";
compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
- qcom,msm-id = <200 11 0>,
- <224 11 0>;
+ qcom,board-id = <11 0>;
};
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index e27e6d1..2ab272a 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -23,7 +23,9 @@
model = "Qualcomm MSM 8926";
compatible = "qcom,msm8926";
qcom,msm-id = <200 0>,
- <224 0>;
+ <224 0>,
+ <200 0x10001>,
+ <224 0x10001>;
};
&soc {
@@ -46,28 +48,33 @@
&pm8226_l3 {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1350000>;
};
&pm8226_l3_ao {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1350000>;
};
&pm8226_l3_so {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1350000>;
};
&pm8226_s2 {
regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1280000>;
+ regulator-max-microvolt = <1350000>;
};
&apc_vreg_corner {
- qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
- 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
- qcom,pvs-corner-ceiling-slow = <1050000 1160000 1280000>;
+ qcom,pvs-init-voltage = <1350000 1340000 1330000 1320000 1310000
+ 1300000 1290000 1280000 1270000 1260000
+ 1250000 1240000 1230000 1220000 1210000
+ 1200000 1190000 1180000 1170000 1160000
+ 1150000 1140000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1140000 1140000
+ 1140000 1140000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1280000>;
qcom,pvs-corner-ceiling-nom = <1050000 1080000 1200000>;
qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
qcom,cpr-step-quotient = <30>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index 26c5b8f..9948833 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -36,8 +36,6 @@
qcom,actuator-src = <&actuator0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "s5k3l1yx";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -79,8 +77,6 @@
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
qcom,actuator-src = <&actuator1>;
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -122,8 +118,6 @@
qcom,csid-sd-index = <2>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov2720";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -159,8 +153,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
qcom,sensor-name = "mt9m114";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index f61b83a..9cbd45c 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -37,8 +37,6 @@
qcom,led-flash-src = <&led_flash0>;
qcom,mount-angle = <270>;
qcom,sensor-name = "s5k3l1yx";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -80,8 +78,6 @@
qcom,mount-angle = <270>;
qcom,sensor-name = "imx135";
qcom,actuator-src = <&actuator1>;
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -123,8 +119,6 @@
qcom,csid-sd-index = <2>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov2720";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -160,8 +154,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
qcom,sensor-name = "mt9m114";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index cf968d2..bf7f492 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -37,8 +37,6 @@
qcom,mount-angle = <0>;
qcom,actuator-src = <&actuator0>;
qcom,sensor-name = "s5k3l1yx";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs2>;
@@ -79,8 +77,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
qcom,sensor-name = "imx135";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
@@ -123,8 +119,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <180>;
qcom,sensor-name = "ov2720";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs2>;
@@ -159,8 +153,6 @@
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
qcom,sensor-name = "mt9m114";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 6ad6213..68af4a6 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -37,8 +37,6 @@
qcom,led-flash-src = <&led_flash0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "s5k3l1yx";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -79,8 +77,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
@@ -124,8 +120,6 @@
qcom,csid-sd-index = <2>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov2720";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -161,8 +155,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
qcom,sensor-name = "mt9m114";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index 9fd0cd9..a809c2b 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -19,8 +19,7 @@
interrupts = <0 166 0>;
interrupt-names = "byte-cntr-irq";
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+ qcom,memory-size = <0x100000>;
coresight-id = <0>;
coresight-name = "coresight-tmc-etr";
@@ -41,6 +40,11 @@
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <9000 800000>;
+
+ vdd-io-supply = <&pm8941_l13>;
+
+ qcom,vdd-io-voltage-level = <2950000 2950000>;
+ qcom,vdd-io-current-level = <6 22000>;
};
replicator: replicator@fc31c000 {
diff --git a/arch/arm/boot/dts/msm8974-mdss-panels.dtsi b/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
index ab43834..00fc779 100644
--- a/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
@@ -13,3 +13,4 @@
/include/ "dsi-panel-orise-720p-video.dtsi"
/include/ "dsi-panel-toshiba-720p-video.dtsi"
/include/ "dsi-panel-sharp-qhd-video.dtsi"
+/include/ "dsi-panel-generic-720p-cmd.dtsi"
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 99c15af..24b5860 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -87,9 +87,10 @@
vdda-supply = <&pm8941_l2>;
qcom,mdss-fb-map = <&mdss_fb0>;
qcom,mdss-mdp = <&mdss_mdp>;
- qcom,platform-reset-gpio = <&pm8941_gpios 19 1>;
- qcom,platform-enable-gpio = <&msmgpio 58 1>;
+ qcom,platform-reset-gpio = <&pm8941_gpios 19 0>;
+ qcom,platform-enable-gpio = <&msmgpio 58 0>;
qcom,platform-reset-sequence = <1 20 0 200 1 20 2>;
+ qcom,platform-te-gpio = <&msmgpio 12 0>;
qcom,platform-strength-ctrl = [ff 06];
qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
qcom,platform-regulator-settings = [07 09 03 00 20 00 01];
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index af4030f..f2f73e9 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -184,3 +184,26 @@
status = "ok";
};
};
+
+&cci {
+
+ qcom,camera@6e {
+ qcom,vdd-cx-supply = <&pm8841_s2>;
+ qcom,vdd-cx-name = "qcom,vdd-cx";
+ };
+
+ qcom,camera@20 {
+ qcom,vdd-cx-supply = <&pm8841_s2>;
+ qcom,vdd-cx-name = "qcom,vdd-cx";
+ };
+
+ qcom,camera@6c {
+ qcom,vdd-cx-supply = <&pm8841_s2>;
+ qcom,vdd-cx-name = "qcom,vdd-cx";
+ };
+
+ qcom,camera@90 {
+ qcom,vdd-cx-supply = <&pm8841_s2>;
+ qcom,vdd-cx-name = "qcom,vdd-cx";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 1845e17..65307ae 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -211,6 +211,7 @@
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
interrupts = <0 44 0>;
+ vdd-supply = <&gdsc_venus>;
qcom,hfi = "venus";
qcom,has-ocmem;
qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/
@@ -911,6 +912,8 @@
qcom,dwc-hsphy-init = <0x00D191A4>;
qcom,misc-ref = <&pm8941_misc>;
dwc_usb3-adc_tm = <&pm8941_adc_tm>;
+ qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
+ qcom,dwc-usb3-msm-qdss-tx-fifo-size = <16384>;
qcom,msm-bus,name = "usb3";
qcom,msm-bus,num-cases = <2>;
@@ -924,6 +927,7 @@
interrupt-parent = <&intc>;
interrupts = <0 131 0>, <0 179 0>;
interrupt-names = "irq", "otg_irq";
+ tx-fifo-resize;
};
};
@@ -1391,8 +1395,6 @@
compatible = "qcom,cache_dump";
qcom,l1-dump-size = <0x100000>;
qcom,l2-dump-size = <0x500000>;
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
};
tsens: tsens@fc4a8000 {
@@ -1481,7 +1483,7 @@
qcom,src-bam-pipe-index = <0>;
qcom,dst-bam-physical-address = <0xf9304000>;
qcom,dst-bam-pipe-index = <2>;
- qcom,data-fifo-offset = <0xf0000>;
+ qcom,data-fifo-offset = <0xf2000>;
qcom,data-fifo-size = <0x1800>;
qcom,descriptor-fifo-offset = <0xf4000>;
qcom,descriptor-fifo-size = <0x1400>;
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
index 4c55169..f8a371d 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -46,6 +46,7 @@
tpiu@fc318000 {
vdd-supply = <&pma8084_l21>;
+ vdd-io-supply = <&pma8084_l13>;
};
qcom,mdss_dsi@fd922800 {
@@ -161,6 +162,9 @@
qcom,msm-thermal {
vdd-dig-supply = <&pma8084_s2_floor_corner>;
vdd-gfx-supply = <&pma8084_s7_floor_corner>;
+ /delete-property/ qcom,pmic-sw-mode-temp;
+ /delete-property/ qcom,pmic-sw-mode-temp-hysteresis;
+ /delete-property/ qcom,pmic-sw-mode-regs;
};
qcom,lpm-resources {
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 9b0638d..86f0058 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -33,6 +33,12 @@
compatible = "qcom,msm-imem";
reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
};
+
+ qcom,msm-thermal {
+ /delete-property/ qcom,pmic-sw-mode-temp;
+ /delete-property/ qcom,pmic-sw-mode-temp-hysteresis;
+ /delete-property/ qcom,pmic-sw-mode-regs;
+ };
};
/* GPU overrides */
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 4a903b7..4880f96 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -19,8 +19,7 @@
interrupts = <0 166 0>;
interrupt-names = "byte-cntr-irq";
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x20000>; /* 128K EBI1 buffer */
+ qcom,memory-size = <0x20000>;
coresight-id = <0>;
coresight-name = "coresight-tmc-etr";
@@ -121,13 +120,13 @@
coresight-child-ports = <7>;
};
- etm: etm@fc332000 {
+ etm0: etm@fc332000 {
compatible = "arm,coresight-etm";
reg = <0xfc332000 0x1000>;
reg-names = "etm-base";
coresight-id = <8>;
- coresight-name = "coresight-etm";
+ coresight-name = "coresight-etm0";
coresight-nr-inports = <0>;
coresight-outports = <0>;
coresight-child-list = <&funnel_in0>;
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index f4ad0c4..66d66fc 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -1,6 +1,7 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
@@ -129,6 +130,7 @@
CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
@@ -146,9 +148,11 @@
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -182,6 +186,7 @@
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -359,6 +364,7 @@
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -393,6 +399,10 @@
CONFIG_EARLY_PRINTK=y
CONFIG_PID_IN_CONTEXTIDR=y
CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_ARC4=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 8eb6b53..9535e05 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -1,6 +1,7 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
@@ -125,6 +126,7 @@
CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
@@ -142,10 +144,12 @@
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -183,6 +187,7 @@
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -405,6 +410,7 @@
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -423,6 +429,10 @@
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
CONFIG_CRYPTO_NULL=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_XCBC=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index be0c155..176a8a2 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -1,6 +1,7 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
@@ -126,6 +127,7 @@
CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
@@ -143,10 +145,12 @@
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -184,6 +188,7 @@
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -441,6 +446,7 @@
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -474,6 +480,10 @@
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
CONFIG_CRYPTO_NULL=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_XCBC=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 03ddb3a..1a197a3 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -2,6 +2,7 @@
CONFIG_EXPERIMENTAL=y
CONFIG_LOCALVERSION="-perf"
CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
@@ -121,6 +122,7 @@
CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
@@ -138,9 +140,11 @@
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -178,6 +182,7 @@
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -281,6 +286,7 @@
CONFIG_OV5648=y
CONFIG_MSM_CAMERA_SENSOR=y
# CONFIG_MSM_CPP is not set
+CONFIG_MSM_EEPROM=y
CONFIG_MSM_CCI=y
CONFIG_MSM_CSI22_HEADER=y
CONFIG_MSM_CSIPHY=y
@@ -365,6 +371,7 @@
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -381,11 +388,23 @@
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=y
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPPOE=y
+CONFIG_N_HDLC=y
+CONFIG_UNIX98_PTYS=y
CONFIG_INPUT_KXTJ9=y
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_SENSORS_STK3X1X=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index aad3540..8238414 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -1,6 +1,7 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
@@ -122,6 +123,7 @@
CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
@@ -139,9 +141,11 @@
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -179,6 +183,7 @@
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -281,6 +286,7 @@
CONFIG_HI256=y
CONFIG_OV12830=y
CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_EEPROM=y
CONFIG_MSM_CCI=y
CONFIG_MSM_CSIPHY=y
CONFIG_MSM_CSID=y
@@ -398,6 +404,7 @@
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -428,6 +435,10 @@
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_TWOFISH=y
@@ -435,6 +446,14 @@
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPPOE=y
+CONFIG_N_HDLC=y
+CONFIG_UNIX98_PTYS=y
CONFIG_INPUT_KXTJ9=y
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_SENSORS_STK3X1X=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 3bc159a..a9e39ed 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -2,6 +2,7 @@
CONFIG_EXPERIMENTAL=y
CONFIG_LOCALVERSION="-perf"
CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
@@ -139,6 +140,7 @@
CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
@@ -156,10 +158,12 @@
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -197,6 +201,7 @@
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -453,6 +458,7 @@
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -472,6 +478,10 @@
CONFIG_PID_IN_CONTEXTIDR=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 118fdd4..ee38cc8 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -1,6 +1,7 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
@@ -145,6 +146,7 @@
CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
@@ -162,10 +164,12 @@
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -203,6 +207,7 @@
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -472,6 +477,7 @@
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -507,6 +513,10 @@
CONFIG_PID_IN_CONTEXTIDR=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 32b5b26..5bca467 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -555,7 +555,7 @@
static DEFINE_RAW_SPINLOCK(stop_lock);
-static struct pt_regs __percpu regs_before_stop;
+DEFINE_PER_CPU(struct pt_regs, regs_before_stop);
/*
* ipi_cpu_stop - handle IPI from smp_send_stop()
*/
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 59c682f..9ea00c1 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -106,7 +106,23 @@
{ 1, 1305600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
{ 1, 1344000, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
{ 1, 1401600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- /* No support for 1p5 GHz yet */
+ { 1, 1497600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 0 }
+};
+
+static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p6[] = {
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 0, 4 },
+ { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_SVS, 0, 4 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 0, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 0, 7 },
+ { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1305600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1344000, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1401600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1497600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1593600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
{ 0 }
};
@@ -125,8 +141,9 @@
[6] = acpu_freq_tbl_8226_1p2,
[2] = acpu_freq_tbl_8226_1p4,
[5] = acpu_freq_tbl_8226_1p4,
- [3] = acpu_freq_tbl_8226_1p5,
[4] = acpu_freq_tbl_8226_1p5,
+ [7] = acpu_freq_tbl_8226_1p5,
+ [1] = acpu_freq_tbl_8226_1p6,
};
static struct acpuclk_drv_data drv_data = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 8410019..6d848d2 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -899,460 +899,38 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 780000, 120 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 790000, 139 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 159 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 180 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 200 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 221 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 242 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 264 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 865000, 287 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 875000, 308 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 333 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 356 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 915000, 380 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 925000, 404 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 430 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 955000, 456 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 970000, 482 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 985000, 510 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1000000, 538 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1015000, 565 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 596 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 627 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 659 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 691 },
+static struct acpu_level acpu_freq_tbl_pro_pvs0[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 999 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 999 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 999 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 805000, 999 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 815000, 999 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 825000, 999 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 835000, 999 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 845000, 999 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 855000, 999 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 865000, 999 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 999 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 890000, 999 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 900000, 999 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 915000, 999 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 925000, 999 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 940000, 999 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 999 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 965000, 999 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 980000, 999 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 995000, 999 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1010000, 999 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1025000, 999 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 999 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 999 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 999 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 999 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 999 },
+ /* higher frequencies aren't available for bring up */
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 785000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 795000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 805000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 815000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 825000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 835000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 885000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 895000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 905000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 920000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 935000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 950000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 965000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 980000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 760000, 139 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 770000, 159 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 180 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 200 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 221 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 242 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 264 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 287 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 308 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 333 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 865000, 356 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 875000, 380 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 885000, 404 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 900000, 430 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 915000, 456 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 930000, 482 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 945000, 510 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 955000, 538 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 565 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 980000, 596 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 627 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 659 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 691 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 755000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 765000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 785000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 795000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 805000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 815000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 825000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 835000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 885000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 925000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 935000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 945000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 970000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 755000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 765000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 785000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 795000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 805000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 815000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 825000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 835000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 845000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 855000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 895000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 905000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 925000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 935000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 950000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 960000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 735000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 745000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 755000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 765000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 785000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 795000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 805000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 815000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 825000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 835000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 845000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 855000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 865000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 875000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 885000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 895000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 905000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 915000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 930000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 950000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 725000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 735000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 745000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 755000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 765000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 785000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 795000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 805000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 815000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 825000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 835000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 845000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 850000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 860000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 870000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 880000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 890000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 895000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 905000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 915000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 925000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 805000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 815000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 825000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 835000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 845000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 855000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 885000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 915000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 945000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 960000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 980000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1000000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1020000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1040000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1060000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1080000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1100000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 805000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 815000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 825000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 835000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 845000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 855000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 900000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 915000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 930000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 945000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 975000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 995000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1015000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1035000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1055000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1075000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 780000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 790000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 800000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 810000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 820000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 830000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 840000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 850000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 865000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 880000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 895000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 910000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 925000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 955000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 970000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 990000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1010000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1030000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1050000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 780000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 790000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 800000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 810000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 820000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 830000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 840000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 850000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 865000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 880000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 895000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 910000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 925000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 940000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 955000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 970000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 985000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1005000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1025000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 760000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 770000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 780000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 790000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 800000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 810000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 820000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 830000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 840000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 850000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 865000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 880000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 895000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 910000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 925000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 955000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 970000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 985000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1000000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 750000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 760000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 770000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 780000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 790000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 800000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 810000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 820000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 830000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 840000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 850000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 860000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 870000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 885000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 900000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 915000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 930000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 945000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 960000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 975000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 725000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 725000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 725000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 725000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 725000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 735000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 745000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 755000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 765000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 775000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 785000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 795000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 805000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 815000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 825000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 835000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 845000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 855000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 865000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 875000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 890000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 905000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 920000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 935000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 950000, 800},
- { 0, { 0 } }
-};
static struct pvs_table pvs_v1[NUM_SPEED_BINS][NUM_PVS] __initdata = {
/* 8974v1 1.7GHz Parts */
@@ -1396,45 +974,45 @@
};
static struct pvs_table pvs_pro[NUM_SPEED_BINS][NUM_PVS] __initdata = {
- /* 2.0 GHz is not used on 8974Pro */
- [0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
- [0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
- [0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
- [0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
- [0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
- [0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
- [0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+ /* Not used by 8974Pro */
+ [0][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
- /* 8974Pro AB 2.3GHz */
- [1][0] = { acpu_ftbl_pro_2p3g_pvs0, sizeof(acpu_ftbl_pro_2p3g_pvs0) },
- [1][1] = { acpu_ftbl_pro_2p3g_pvs1, sizeof(acpu_ftbl_pro_2p3g_pvs1) },
- [1][2] = { acpu_ftbl_pro_2p3g_pvs2, sizeof(acpu_ftbl_pro_2p3g_pvs2) },
- [1][3] = { acpu_ftbl_pro_2p3g_pvs3, sizeof(acpu_ftbl_pro_2p3g_pvs3) },
- [1][4] = { acpu_ftbl_pro_2p3g_pvs4, sizeof(acpu_ftbl_pro_2p3g_pvs4) },
- [1][5] = { acpu_ftbl_pro_2p3g_pvs5, sizeof(acpu_ftbl_pro_2p3g_pvs5) },
- [1][6] = { acpu_ftbl_pro_2p3g_pvs6, sizeof(acpu_ftbl_pro_2p3g_pvs6) },
- [1][7] = { acpu_ftbl_pro_2p3g_pvs6, sizeof(acpu_ftbl_pro_2p3g_pvs6) },
+ /* 8974Pro AB Bringup */
+ [1][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
- /* 2.2GHz is not used on 8974Pro */
- [2][0] = { acpu_freq_tbl_2p2g_pvs0, sizeof(acpu_freq_tbl_2p2g_pvs0) },
- [2][1] = { acpu_freq_tbl_2p2g_pvs1, sizeof(acpu_freq_tbl_2p2g_pvs1) },
- [2][2] = { acpu_freq_tbl_2p2g_pvs2, sizeof(acpu_freq_tbl_2p2g_pvs2) },
- [2][3] = { acpu_freq_tbl_2p2g_pvs3, sizeof(acpu_freq_tbl_2p2g_pvs3) },
- [2][4] = { acpu_freq_tbl_2p2g_pvs4, sizeof(acpu_freq_tbl_2p2g_pvs4) },
- [2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
- [2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
- [2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+ /* Not used by 8974Pro */
+ [2][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
- /* 8974Pro AC 2.5GHz */
- [3][0] = { acpu_ftbl_pro_2p5g_pvs0, sizeof(acpu_ftbl_pro_2p5g_pvs0) },
- [3][1] = { acpu_ftbl_pro_2p5g_pvs1, sizeof(acpu_ftbl_pro_2p5g_pvs1) },
- [3][2] = { acpu_ftbl_pro_2p5g_pvs2, sizeof(acpu_ftbl_pro_2p5g_pvs2) },
- [3][3] = { acpu_ftbl_pro_2p5g_pvs3, sizeof(acpu_ftbl_pro_2p5g_pvs3) },
- [3][4] = { acpu_ftbl_pro_2p5g_pvs4, sizeof(acpu_ftbl_pro_2p5g_pvs4) },
- [3][5] = { acpu_ftbl_pro_2p5g_pvs5, sizeof(acpu_ftbl_pro_2p5g_pvs5) },
- [3][6] = { acpu_ftbl_pro_2p5g_pvs6, sizeof(acpu_ftbl_pro_2p5g_pvs6) },
- [3][7] = { acpu_ftbl_pro_2p5g_pvs6, sizeof(acpu_ftbl_pro_2p5g_pvs6) },
+ /* 8974Pro Bringup */
+ [3][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
};
static struct msm_bus_scale_pdata bus_scale_data __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock.c b/arch/arm/mach-msm/acpuclock.c
index 2c120da..42242d5 100644
--- a/arch/arm/mach-msm/acpuclock.c
+++ b/arch/arm/mach-msm/acpuclock.c
@@ -27,19 +27,10 @@
int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason)
{
- int ret;
-
if (!acpuclk_data || !acpuclk_data->set_rate)
return 0;
- trace_cpu_frequency_switch_start(acpuclk_get_rate(cpu), rate, cpu);
- ret = acpuclk_data->set_rate(cpu, rate, reason);
- if (!ret) {
- trace_cpu_frequency_switch_end(cpu);
- trace_cpu_frequency(rate, cpu);
- }
-
- return ret;
+ return acpuclk_data->set_rate(cpu, rate, reason);
}
uint32_t acpuclk_get_switch_time(void)
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 820bcf9..6281395 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -195,6 +195,7 @@
static struct sps_register_event rx_register_event;
static bool satellite_mode;
static uint32_t num_buffers;
+static unsigned long long last_rx_pkt_timestamp;
static struct bam_ch_info bam_ch[BAM_DMUX_NUM_CHANNELS];
static int bam_mux_initialized;
@@ -1117,6 +1118,29 @@
queue_work_on(0, bam_mux_rx_workqueue, &rx_timer_work);
}
+/**
+ * store_rx_timestamp() - store the current raw time as as a timestamp for when
+ * the last rx packet was processed
+ */
+static void store_rx_timestamp(void)
+{
+ last_rx_pkt_timestamp = sched_clock();
+}
+
+/**
+ * log_rx_timestamp() - Log the stored rx pkt timestamp in a human readable
+ * format
+ */
+static void log_rx_timestamp(void)
+{
+ unsigned long long t = last_rx_pkt_timestamp;
+ unsigned long nanosec_rem;
+
+ nanosec_rem = do_div(t, 1000000000U);
+ BAM_DMUX_LOG("Last rx pkt processed at [%6u.%09lu]\n", (unsigned)t,
+ nanosec_rem);
+}
+
static void rx_timer_work_func(struct work_struct *work)
{
struct sps_iovec iov;
@@ -1125,20 +1149,26 @@
int ret;
u32 buffs_unused, buffs_used;
+ BAM_DMUX_LOG("%s: polling start\n", __func__);
while (bam_connection_is_active) { /* timer loop */
++inactive_cycles;
while (bam_connection_is_active) { /* deplete queue loop */
- if (in_global_reset)
+ if (in_global_reset) {
+ BAM_DMUX_LOG(
+ "%s: polling exit, global reset detected\n",
+ __func__);
return;
+ }
ret = sps_get_iovec(bam_rx_pipe, &iov);
if (ret) {
- pr_err("%s: sps_get_iovec failed %d\n",
+ DMUX_LOG_KERR("%s: sps_get_iovec failed %d\n",
__func__, ret);
break;
}
if (iov.addr == 0)
break;
+ store_rx_timestamp();
inactive_cycles = 0;
mutex_lock(&bam_rx_pool_mutexlock);
if (unlikely(list_empty(&bam_rx_pool))) {
@@ -1171,6 +1201,7 @@
}
if (inactive_cycles >= POLLING_INACTIVITY) {
+ BAM_DMUX_LOG("%s: polling exit, no data\n", __func__);
rx_switch_to_interrupt_mode();
break;
}
@@ -1182,7 +1213,8 @@
&buffs_unused);
if (ret) {
- pr_err("%s: error getting num buffers unused after sleep\n",
+ DMUX_LOG_KERR(
+ "%s: error getting num buffers unused after sleep\n",
__func__);
break;
@@ -1768,6 +1800,7 @@
if (time_remaining == 0) {
DMUX_LOG_KERR("%s: shutdown completion timed out\n",
__func__);
+ log_rx_timestamp();
ssrestart_check();
}
}
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 300ac4f..5dd9bab 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -73,17 +73,22 @@
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting gpio_spi_config = {
+static struct gpiomux_setting gpio_spi_act_config = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting gpio_spi_cs_config = {
+static struct gpiomux_setting gpio_spi_cs_act_config = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_6MA,
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting gpio_spi_susp_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
static struct gpiomux_setting gpio_spi_cs_eth_config = {
.func = GPIOMUX_FUNC_4,
@@ -160,48 +165,56 @@
{
.gpio = 0, /* BLSP1 QUP1 SPI_DATA_MOSI */
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ [GPIOMUX_ACTIVE] = &gpio_spi_act_config,
+ [GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
},
},
{
.gpio = 1, /* BLSP1 QUP1 SPI_DATA_MISO */
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ [GPIOMUX_ACTIVE] = &gpio_spi_act_config,
+ [GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
},
},
{
.gpio = 2, /* BLSP1 QUP1 SPI_CS1 */
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+ [GPIOMUX_ACTIVE] = &gpio_spi_cs_act_config,
+ [GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
},
},
{
.gpio = 3, /* BLSP1 QUP1 SPI_CLK */
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ [GPIOMUX_ACTIVE] = &gpio_spi_act_config,
+ [GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
},
},
{
.gpio = 14, /* BLSP1 QUP4 I2C_SDA */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{
.gpio = 15, /* BLSP1 QUP4 I2C_SCL */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{
.gpio = 18, /* BLSP1 QUP5 I2C_SDA */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{
.gpio = 19, /* BLSP1 QUP5 I2C_SCL */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
@@ -214,12 +227,14 @@
{ /* NFC */
.gpio = 10, /* BLSP1 QUP3 I2C_DAT */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{ /* NFC */
.gpio = 11, /* BLSP1 QUP3 I2C_CLK */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
@@ -336,12 +351,14 @@
{
.gpio = 18, /* BLSP1 QUP5 I2C_SDA */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{
.gpio = 19, /* BLSP1 QUP5 I2C_SCL */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
@@ -410,12 +427,14 @@
{ /* NFC */
.gpio = 10, /* BLSP1 QUP3 I2C_DAT */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{ /* NFC */
.gpio = 11, /* BLSP1 QUP3 I2C_CLK */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index dc9c13d..e9ad86f 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -188,36 +188,42 @@
{
.gpio = 2, /* BLSP1 QUP1 I2C_SDA */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{
.gpio = 3, /* BLSP1 QUP1 I2C_SCL */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{
.gpio = 10, /* BLSP1 QUP3 I2C_SDA */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{
.gpio = 11, /* BLSP1 QUP3 I2C_SCL */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
{
.gpio = 16, /* BLSP1 QUP6 I2C_SDA */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_cam_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_cam_i2c_config,
},
},
{
.gpio = 17, /* BLSP1 QUP6 I2C_SCL */
.settings = {
+ [GPIOMUX_ACTIVE] = &gpio_cam_i2c_config,
[GPIOMUX_SUSPENDED] = &gpio_cam_i2c_config,
},
},
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 6165c32..f170b7b 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -1346,6 +1346,11 @@
return;
}
+ pr_err("%s:%d socinfo_get_version %x\n", __func__, __LINE__,
+ socinfo_get_version());
+ if (socinfo_get_version() >= 0x20000)
+ msm_tlmm_misc_reg_write(TLMM_SPARE_REG, 0xf);
+
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
if (!(of_board_is_dragonboard() && machine_is_apq8074()))
msm_gpiomux_install(msm_eth_configs, \
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index b72cdab..1999379 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -1603,7 +1603,15 @@
{ &gcc_ce1_axi_clk.c, GCC_BASE, 0x0139 },
{ &gcc_ce1_ahb_clk.c, GCC_BASE, 0x013a },
{ &gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160 },
- {&dummy_clk, N_BASES, 0x0000},
+ { &pnoc_clk.c, GCC_BASE, 0x010},
+ { &snoc_clk.c, GCC_BASE, 0x000},
+ { &cnoc_clk.c, GCC_BASE, 0x008},
+ /*
+ * measure the gcc_bimc_kpss_axi_clk instead to account for the DDR
+ * rate being gcc_bimc_clk/2.
+ */
+ { &bimc_clk.c, GCC_BASE, 0x155},
+ { &dummy_clk, N_BASES, 0x0000},
};
static struct pll_vote_clk mmpll0_pll = {
@@ -2725,6 +2733,7 @@
{ &camss_csi1rdi_clk.c, MMSS_BASE, 0x0049 },
{ &camss_csi1pix_clk.c, MMSS_BASE, 0x004a },
{ &camss_ispif_ahb_clk.c, MMSS_BASE, 0x0055 },
+ { &mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001 },
{&dummy_clk, N_BASES, 0x0000},
};
@@ -2820,6 +2829,8 @@
F_APCS_PLL(1305600000, 68, 0x0, 0x1, 0x0, 0x0, 0x0),
F_APCS_PLL(1344000000, 70, 0x0, 0x1, 0x0, 0x0, 0x0),
F_APCS_PLL(1401600000, 73, 0x0, 0x1, 0x0, 0x0, 0x0),
+ F_APCS_PLL(1497600000, 78, 0x0, 0x1, 0x0, 0x0, 0x0),
+ F_APCS_PLL(1593600000, 83, 0x0, 0x1, 0x0, 0x0, 0x0),
PLL_F_END
};
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 92dab97..33dcd9f 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3026,11 +3026,13 @@
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006d"),
CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "6-0078"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-0020"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006a"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006f"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-007d"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006d"),
CLK_LOOKUP("cam_clk", mclk1_clk.c, "6-0078"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-0020"),
+ CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006a"),
/* CSIPHY clocks */
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index cd6d582..654dbd3 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4897,10 +4897,29 @@
CLK_DUMMY("core_clk", NULL, "fdc84000.qcom,iommu", oFF),
};
-static struct clk_lookup msm_clocks_8974ac_only[] __initdata = {
+static struct clk_lookup msm_clocks_8974pro_only[] __initdata = {
CLK_LOOKUP("gpll4", gpll4_clk_src.c, ""),
CLK_LOOKUP("sleep_clk", gcc_sdcc1_cdccal_sleep_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("cal_clk", gcc_sdcc1_cdccal_ff_clk.c, "msm_sdcc.1"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "20.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk2_clk_src.c, "6c.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "90.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "20.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, "6c.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "90.qcom,camera"),
+};
+
+static struct clk_lookup msm_clocks_8974_only[] __initdata = {
+ CLK_LOOKUP("cam_src_clk", mmss_gp0_clk_src.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mmss_gp0_clk_src.c, "20.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", gp1_clk_src.c, "6c.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mmss_gp1_clk_src.c, "90.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_gp0_clk.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_gp0_clk.c, "20.qcom,camera"),
+ CLK_LOOKUP("cam_clk", gcc_gp1_clk.c, "6c.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_gp1_clk.c, "90.qcom,camera"),
};
static struct clk_lookup msm_clocks_8974_common[] __initdata = {
@@ -5076,22 +5095,16 @@
CLK_LOOKUP("core_clk_src", mdp_clk_src.c, "mdp.0"),
CLK_LOOKUP("vsync_clk", mdss_vsync_clk.c, "mdp.0"),
- /* MM sensor clocks */
- CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6e.qcom,camera"),
- CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "20.qcom,camera"),
- CLK_LOOKUP("cam_src_clk", mclk2_clk_src.c, "6c.qcom,camera"),
- CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "90.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6e.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "20.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, "6c.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "90.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, ""),
- CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, ""),
- CLK_LOOKUP("cam_clk", camss_mclk3_clk.c, ""),
- CLK_LOOKUP("cam_gp0_src_clk", mmss_gp0_clk_src.c, ""),
- CLK_LOOKUP("cam_gp1_src_clk", mmss_gp1_clk_src.c, ""),
- CLK_LOOKUP("cam_gp0_clk", camss_gp0_clk.c, ""),
- CLK_LOOKUP("cam_gp1_clk", camss_gp1_clk.c, ""),
+ /* MM sensor clocks placeholder */
+ CLK_LOOKUP("", camss_mclk0_clk.c, ""),
+ CLK_LOOKUP("", camss_mclk1_clk.c, ""),
+ CLK_LOOKUP("", camss_mclk2_clk.c, ""),
+ CLK_LOOKUP("", camss_mclk3_clk.c, ""),
+ CLK_LOOKUP("", mmss_gp0_clk_src.c, ""),
+ CLK_LOOKUP("", mmss_gp1_clk_src.c, ""),
+ CLK_LOOKUP("", camss_gp0_clk.c, ""),
+ CLK_LOOKUP("", camss_gp1_clk.c, ""),
+
/* CCI clocks */
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
"fda0c000.qcom,cci"),
@@ -5450,7 +5463,8 @@
};
static struct clk_lookup msm_clocks_8974[ARRAY_SIZE(msm_clocks_8974_common)
- + ARRAY_SIZE(msm_clocks_8974ac_only)];
+ + ARRAY_SIZE(msm_clocks_8974_only)
+ + ARRAY_SIZE(msm_clocks_8974pro_only)];
static struct pll_config_regs mmpll0_regs __initdata = {
.l_reg = (void __iomem *)MMPLL0_L_REG,
@@ -5797,18 +5811,26 @@
memcpy(msm_clocks_8974, msm_clocks_8974_common,
sizeof(msm_clocks_8974_common));
- msm8974_clock_init_data.size -= ARRAY_SIZE(msm_clocks_8974ac_only);
- /* version specific changes */
+ /* version specific clock changes */
if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2
|| cpu_is_msm8974pro())
msm8974_v2_clock_override();
- if (cpu_is_msm8974pro()) {
+ if (cpu_is_msm8974pro())
msm8974_pro_clock_override();
+
+ /* version specific lookup table changes */
+ if (cpu_is_msm8974()) {
memcpy(msm_clocks_8974 + ARRAY_SIZE(msm_clocks_8974_common),
- msm_clocks_8974ac_only, sizeof(msm_clocks_8974ac_only));
+ msm_clocks_8974_only, sizeof(msm_clocks_8974_only));
msm8974_clock_init_data.size +=
- ARRAY_SIZE(msm_clocks_8974ac_only);
+ ARRAY_SIZE(msm_clocks_8974_only);
+ } else if (cpu_is_msm8974pro()) {
+ memcpy(msm_clocks_8974 + ARRAY_SIZE(msm_clocks_8974_common),
+ msm_clocks_8974pro_only,
+ sizeof(msm_clocks_8974pro_only));
+ msm8974_clock_init_data.size +=
+ ARRAY_SIZE(msm_clocks_8974pro_only);
}
clk_ops_pixel_clock = clk_ops_pixel;
@@ -5841,7 +5863,7 @@
struct clock_init_data msm8974_clock_init_data __initdata = {
.table = msm_clocks_8974,
- .size = ARRAY_SIZE(msm_clocks_8974),
+ .size = ARRAY_SIZE(msm_clocks_8974_common),
.pre_init = msm8974_clock_pre_init,
.post_init = msm8974_clock_post_init,
};
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 47332a4..3bb4c57 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -31,8 +31,8 @@
#define DSS_REG_W(base, offset, data) REG_W((data), (base) + (offset))
#define DSS_REG_R(base, offset) REG_R((base) + (offset))
-#define GDSC_PHYS 0xFD8C2304
-#define GDSC_SIZE 0x4
+#define GDSC_PHYS 0xFD8C2300
+#define GDSC_SIZE 0x8
#define DSI_PHY_PHYS 0xFD922A00
#define DSI_PHY_SIZE 0x000000D4
@@ -163,7 +163,8 @@
if (!gdsc_base)
return 0;
- return !!(readl_relaxed(gdsc_base) & BIT(31));
+ return (readl_relaxed(gdsc_base + 0x4) & BIT(31)) &&
+ (!(readl_relaxed(gdsc_base) & BIT(0)));
}
void hdmi_pll_disable(void)
@@ -1140,6 +1141,11 @@
int i, rc = 0;
struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return -EPERM;
+ }
+
rc = clk_enable(mdss_ahb_clk);
if (rc) {
pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
@@ -1167,6 +1173,12 @@
{
int rc = 0;
+ if (!mdss_gdsc_enabled()) {
+ pr_warn("%s: mdss GDSC disabled before disabling DSI PLL\n",
+ __func__);
+ return;
+ }
+
rc = clk_enable(mdss_ahb_clk);
if (rc) {
pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index b69b155..59e0e2a 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -148,7 +148,7 @@
void __iomem *efuse_base;
/* Process voltage parameters */
- u32 pvs_bin_process[CPR_PVS_EFUSE_BINS_MAX];
+ u32 pvs_init_v[CPR_PVS_EFUSE_BINS_MAX];
u32 pvs_corner_v[NUM_APC_PVS][CPR_CORNER_MAX];
/* Process voltage variables */
u32 pvs_bin;
@@ -999,6 +999,7 @@
u64 efuse_bits;
int rc, process;
u32 pvs_fuse[3], pvs_fuse_redun_sel[4];
+ u32 init_v;
bool redundant;
size_t pvs_bins;
@@ -1034,25 +1035,35 @@
((1 << pvs_fuse[2]) - 1);
pvs_bins = 1 << pvs_fuse[2];
- rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
- cpr_vreg->pvs_bin_process,
- pvs_bins);
+
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-init-voltage",
+ cpr_vreg->pvs_init_v, pvs_bins);
if (rc < 0) {
- pr_err("pvs-bin-process missing: rc=%d\n", rc);
+ pr_err("pvs-init-voltage missing: rc=%d\n", rc);
return rc;
}
- process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
- pr_info("[row:%d] = 0x%llX, n_bits=%d, bin=%d (%d)\n",
- pvs_fuse[0], efuse_bits, pvs_fuse[2],
- cpr_vreg->pvs_bin, process);
+ init_v = cpr_vreg->pvs_init_v[cpr_vreg->pvs_bin];
+ for (process = NUM_APC_PVS - 1; process > APC_PVS_NO; process--) {
+ if (init_v <= cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO])
+ break;
+ }
- if (process == APC_PVS_NO || process >= NUM_APC_PVS) {
- pr_err("Bin=%d (%d) is out of spec. Assume SLOW.\n",
- cpr_vreg->pvs_bin, process);
+ if (process == APC_PVS_NO) {
+ process = APC_PVS_SLOW;
+ cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO] = init_v;
+ cpr_vreg->ceiling_max = init_v;
+ } else if (process == APC_PVS_FAST &&
+ init_v < cpr_vreg->pvs_corner_v[APC_PVS_FAST][CPR_CORNER_SVS]) {
process = APC_PVS_SLOW;
}
+ pr_info("[row:%d] = 0x%llX, n_bits=%d, bin=%d (%d)",
+ pvs_fuse[0], efuse_bits, pvs_fuse[2],
+ cpr_vreg->pvs_bin, process);
+ pr_info("pvs initial turbo voltage_= from %u to %u\n",
+ init_v, cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO]);
+
cpr_vreg->process = process;
return 0;
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index e02df3e..a6c86af 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -27,6 +27,7 @@
#include <linux/cpumask.h>
#include <linux/sched.h>
#include <linux/suspend.h>
+#include <trace/events/power.h>
#include <mach/socinfo.h>
#include <mach/cpufreq.h>
@@ -98,9 +99,12 @@
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ trace_cpu_frequency_switch_start(freqs.old, freqs.new, policy->cpu);
ret = acpuclk_set_rate(policy->cpu, new_freq, SETRATE_CPUFREQ);
- if (!ret)
+ if (!ret) {
+ trace_cpu_frequency_switch_end(policy->cpu);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
/* Restore priority after clock ramp-up */
if (freqs.new > freqs.old && saved_sched_policy >= 0) {
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
index 9aae3fb..bd1a4a2 100644
--- a/arch/arm/mach-msm/include/mach/gpiomux.h
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -113,6 +113,7 @@
enum msm_tlmm_misc_reg {
TLMM_ETM_MODE_REG = 0x2014,
TLMM_SDC2_HDRV_PULL_CTL = 0x2048,
+ TLMM_SPARE_REG = 0x2024,
};
void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h b/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
index 07be428..0a1cdd4 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011, 2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,31 @@
#define RTAC_CVS 1
#define RTAC_VOICE_MODES 2
+enum {
+ ADM_RTAC_CAL,
+ ASM_RTAC_CAL,
+ VOICE_RTAC_CAL,
+ MAX_RTAC_BLOCKS
+};
+
+struct rtac_cal_mem_map_data {
+ uint32_t map_size;
+ uint32_t map_handle;
+ struct ion_client *ion_client;
+ struct ion_handle *ion_handle;
+};
+
+struct rtac_cal_data {
+ uint32_t size;
+ uint32_t kvaddr;
+ uint32_t paddr;
+};
+
+struct rtac_cal_block_data {
+ struct rtac_cal_mem_map_data map_data;
+ struct rtac_cal_data cal_data;
+};
+
void rtac_add_adm_device(u32 port_id, u32 copp_id, u32 path_id, u32 popp_id);
void rtac_remove_adm_device(u32 port_id);
void rtac_remove_popp_from_adm_devices(u32 popp_id);
@@ -35,5 +60,6 @@
void rtac_set_voice_handle(u32 mode, void *handle);
bool rtac_make_voice_callback(u32 mode, uint32_t *payload, u32 payload_size);
void rtac_copy_voice_payload_to_user(void *payload, u32 payload_size);
+int rtac_clear_mapping(uint32_t cal_type);
#endif
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 87719e3..7e4a513 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -36,7 +36,8 @@
(((slv >= MSM_BUS_SLAVE_FIRST) && (slv <= MSM_BUS_SLAVE_LAST)) ? 1 : 0)
#define INTERLEAVED_BW(fab_pdata, bw, ports) \
- ((fab_pdata->il_flag) ? msm_bus_div64((ports), (bw)) : (bw))
+ ((fab_pdata->il_flag) ? ((bw < 0) \
+ ? -msm_bus_div64((ports), (-bw)) : msm_bus_div64((ports), (bw))) : (bw))
#define INTERLEAVED_VAL(fab_pdata, n) \
((fab_pdata->il_flag) ? (n) : 1)
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 94281b1..157dc01 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -482,6 +482,9 @@
if (ret)
return ret;
+ pil_info(desc, "loading from %pa to %pa\n", &priv->region_start,
+ &priv->region_end);
+
for (i = 0; i < mdt->hdr.e_phnum; i++) {
phdr = &mdt->phdr[i];
if (!segment_is_loadable(phdr))
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index a7ebbf7..e826a44 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -65,7 +65,7 @@
/* PIL proxy vote timeout */
-#define VENUS_PROXY_TIMEOUT 10000
+#define VENUS_PROXY_TIMEOUT 2000
/* Poll interval in uS */
#define POLL_INTERVAL_US 50
@@ -288,17 +288,6 @@
unsigned long iova;
u32 ver, cpa_start_addr, cpa_end_addr, fw_start_addr, fw_end_addr;
- /*
- * GDSC needs to remain on till Venus is shutdown. So, enable
- * the GDSC here again to make sure it remains on beyond the
- * expiry of the proxy vote timer.
- */
- rc = regulator_enable(drv->gdsc);
- if (rc) {
- dev_err(pil->dev, "GDSC enable failed\n");
- return rc;
- }
-
/* Get Venus version number */
if (!drv->hw_ver_checked) {
ver = readl_relaxed(wrapper_base + VENUS_WRAPPER_HW_VERSION);
@@ -344,7 +333,7 @@
rc = iommu_attach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
if (rc) {
dev_err(pil->dev, "venus fw iommu attach failed\n");
- goto err_iommu_attach;
+ return rc;
}
/* Map virtual addr space 0 - fw_sz to firmware physical addr space */
@@ -366,9 +355,6 @@
err_iommu_map:
iommu_detach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
-err_iommu_attach:
- regulator_disable(drv->gdsc);
-
return rc;
}
@@ -424,8 +410,6 @@
venus_clock_disable_unprepare(pil->dev);
- regulator_disable(drv->gdsc);
-
drv->is_booted = 0;
return 0;
@@ -454,22 +438,8 @@
static int pil_venus_reset_trusted(struct pil_desc *pil)
{
int rc;
- struct venus_data *drv = dev_get_drvdata(pil->dev);
-
- /*
- * GDSC needs to remain on till Venus is shutdown. So, enable
- * the GDSC here again to make sure it remains on beyond the
- * expiry of the proxy vote timer.
- */
- rc = regulator_enable(drv->gdsc);
- if (rc) {
- dev_err(pil->dev, "GDSC enable failed\n");
- return rc;
- }
rc = pas_auth_and_reset(PAS_VIDC);
- if (rc)
- regulator_disable(drv->gdsc);
return rc;
}
@@ -477,7 +447,6 @@
static int pil_venus_shutdown_trusted(struct pil_desc *pil)
{
int rc;
- struct venus_data *drv = dev_get_drvdata(pil->dev);
venus_clock_prepare_enable(pil->dev);
@@ -485,8 +454,6 @@
venus_clock_disable_unprepare(pil->dev);
- regulator_disable(drv->gdsc);
-
return rc;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
index 0c71659..0a50bcc 100644
--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -53,7 +53,11 @@
pr_debug("%s:probe is not done, deferred\n", __func__);
return -EPROBE_DEFER;
}
-
+ if (!name || !client || !handle || !paddr || !vaddr
+ || !bufsz || !pa_len) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
*client = msm_audio_ion_client_create(UINT_MAX, name);
if (IS_ERR_OR_NULL((void *)(*client))) {
pr_err("%s: ION create client for AUDIO failed\n", __func__);
@@ -102,9 +106,9 @@
err_ion_handle:
ion_free(*client, *handle);
- *handle = NULL;
err_ion_client:
msm_audio_ion_client_destroy(*client);
+ *handle = NULL;
*client = NULL;
err:
return -EINVAL;
@@ -116,10 +120,16 @@
ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
{
int rc = 0;
+ if (!name || !client || !handle || !paddr || !vaddr || !pa_len) {
+ pr_err("%s: Invalid params\n", __func__);
+ rc = -EINVAL;
+ goto err;
+ }
*client = msm_audio_ion_client_create(UINT_MAX, name);
if (IS_ERR_OR_NULL((void *)(*client))) {
pr_err("%s: ION create client for AUDIO failed\n", __func__);
+ rc = -EINVAL;
goto err;
}
@@ -132,8 +142,9 @@
if (IS_ERR_OR_NULL((void *) (*handle))) {
pr_err("%s: ion import dma buffer failed\n",
__func__);
- goto err_ion_handle;
- }
+ rc = -EINVAL;
+ goto err_destroy_client;
+ }
if (ionflag != NULL) {
rc = ion_handle_get_flags(*client, *handle, ionflag);
@@ -154,6 +165,7 @@
*vaddr = ion_map_kernel(*client, *handle);
if (IS_ERR_OR_NULL((void *)*vaddr)) {
pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ rc = -ENOMEM;
goto err_ion_handle;
}
pr_debug("%s: mapped address = %p, size=%d\n", __func__, *vaddr, bufsz);
@@ -162,13 +174,20 @@
err_ion_handle:
ion_free(*client, *handle);
+err_destroy_client:
msm_audio_ion_client_destroy(*client);
+ *client = NULL;
+ *handle = NULL;
err:
- return -EINVAL;
+ return rc;
}
int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle)
{
+ if (!client || !handle) {
+ pr_err("%s Invalid params\n", __func__);
+ return -EINVAL;
+ }
if (msm_audio_ion_data.smmu_enabled) {
/* Need to populate book kept infomation */
pr_debug("client=%p, domain=%p, domain_id=%d, group=%p",
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 1881607..65543a4 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011, 2013 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
@@ -42,6 +42,7 @@
void rtac_set_voice_handle(u32 mode, void *handle) {}
bool rtac_make_voice_callback(u32 mode, uint32_t *payload,
u32 payload_size) {return false; }
+int rtac_clear_mapping(uint32_t cal_type) {return false; }
#else
@@ -123,6 +124,8 @@
struct mutex rtac_voice_mutex;
struct mutex rtac_voice_apr_mutex;
+int rtac_clear_mapping(uint32_t cal_type) {return false; }
+
static int rtac_open(struct inode *inode, struct file *f)
{
pr_debug("%s\n", __func__);
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 2bae37a..ccab6e2 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -284,8 +284,10 @@
struct kvp *e, *n;
for_each_kvp(buf, n) {
+ bool found = false;
for_each_kvp(s->buf, e) {
if (n->k == e->k) {
+ found = true;
if (n->s == e->s) {
void *e_data = get_data(e);
void *n_data = get_data(n);
@@ -300,6 +302,11 @@
}
break;
}
+
+ }
+ if (!found) {
+ add_kvp(s->buf, n);
+ s->valid = true;
}
}
}
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index deb1cc7..d34bdf2 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -144,7 +144,7 @@
SMSM_APPS_DEM_I = 3,
};
-int msm_smd_debug_mask = MSM_SMx_POWER_INFO;
+int msm_smd_debug_mask = MSM_SMx_POWER_INFO | MSM_SMD_INFO;
module_param_named(debug_mask, msm_smd_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
void *smd_log_ctx;
@@ -825,7 +825,7 @@
}
}
-static void smd_channel_reset_state(struct smd_alloc_elm *shared,
+static void smd_channel_reset_state(struct smd_alloc_elm *shared, int table_id,
unsigned new_state, unsigned pid)
{
unsigned n;
@@ -834,6 +834,19 @@
void *local_ch;
void *remote_ch;
int is_word_access;
+ unsigned base_id;
+
+ switch (table_id) {
+ case PRI_ALLOC_TBL:
+ base_id = SMEM_SMD_BASE_ID;
+ break;
+ case SEC_ALLOC_TBL:
+ base_id = SMEM_SMD_BASE_ID_2;
+ break;
+ default:
+ SMD_INFO("%s: invalid table_id:%d\n", __func__, table_id);
+ return;
+ }
for (n = 0; n < SMD_CHANNELS; n++) {
if (!shared[n].ref_count)
@@ -844,10 +857,10 @@
type = SMD_CHANNEL_TYPE(shared[n].type);
is_word_access = is_word_access_ch(type);
if (is_word_access)
- shared2 = smem_alloc(SMEM_SMD_BASE_ID + n,
+ shared2 = smem_alloc(base_id + n,
sizeof(struct smd_shared_v2_word_access));
else
- shared2 = smem_alloc(SMEM_SMD_BASE_ID + n,
+ shared2 = smem_alloc(base_id + n,
sizeof(struct smd_shared_v2));
if (!shared2)
continue;
@@ -870,16 +883,19 @@
void smd_channel_reset(uint32_t restart_pid)
{
- struct smd_alloc_elm *shared;
+ struct smd_alloc_elm *shared_pri;
+ struct smd_alloc_elm *shared_sec;
unsigned long flags;
SMx_POWER_INFO("%s: starting reset\n", __func__);
- shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
- if (!shared) {
+ shared_pri = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared_pri) * 64);
+ if (!shared_pri) {
pr_err("%s: allocation table not initialized\n", __func__);
return;
}
+ shared_sec = smem_find(SMEM_CHANNEL_ALLOC_TBL_2,
+ sizeof(*shared_sec) * 64);
/* reset SMSM entry */
if (smsm_info.state) {
@@ -903,7 +919,11 @@
/* change all remote states to CLOSING */
mutex_lock(&smd_probe_lock);
spin_lock_irqsave(&smd_lock, flags);
- smd_channel_reset_state(shared, SMD_SS_CLOSING, restart_pid);
+ smd_channel_reset_state(shared_pri, PRI_ALLOC_TBL, SMD_SS_CLOSING,
+ restart_pid);
+ if (shared_sec)
+ smd_channel_reset_state(shared_sec, SEC_ALLOC_TBL,
+ SMD_SS_CLOSING, restart_pid);
spin_unlock_irqrestore(&smd_lock, flags);
mutex_unlock(&smd_probe_lock);
@@ -919,7 +939,11 @@
/* change all remote states to CLOSED */
mutex_lock(&smd_probe_lock);
spin_lock_irqsave(&smd_lock, flags);
- smd_channel_reset_state(shared, SMD_SS_CLOSED, restart_pid);
+ smd_channel_reset_state(shared_pri, PRI_ALLOC_TBL, SMD_SS_CLOSED,
+ restart_pid);
+ if (shared_sec)
+ smd_channel_reset_state(shared_sec, SEC_ALLOC_TBL,
+ SMD_SS_CLOSED, restart_pid);
spin_unlock_irqrestore(&smd_lock, flags);
mutex_unlock(&smd_probe_lock);
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 6df1da4..428d5b0 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -21,7 +21,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
-#include <linux/wakelock.h>
+#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
@@ -39,6 +39,7 @@
#define MODULE_NAME "msm_smdtty"
#define MAX_SMD_TTYS 37
#define MAX_TTY_BUF_SIZE 2048
+#define TTY_PUSH_WS_DELAY 500
#define MAX_RA_WAKE_LOCK_NAME_LEN 32
#define SMD_TTY_PROBE_WAIT_TIMEOUT 3000
#define SMD_TTY_LOG_PAGES 2
@@ -58,34 +59,65 @@
} while (0)
static void *smd_tty_log_ctx;
-static DEFINE_MUTEX(smd_tty_lock);
static struct delayed_work smd_tty_probe_work;
static int smd_tty_probe_done;
+/**
+ * struct smd_tty_info - context for an individual SMD TTY device
+ *
+ * @ch: SMD channel handle
+ * @port: TTY port context structure
+ * @device_ptr: TTY device pointer
+ * @pending_ws: pending-data wakeup source
+ * @tty_tsklt: read tasklet
+ * @buf_req_timer: RX buffer retry timer
+ * @ch_allocated: completion set when SMD channel is allocated
+ * @driver: SMD channel platform driver context structure
+ * @pil: Peripheral Image Loader handle
+ * @edge: SMD edge associated with port
+ * @ch_name: SMD channel name associated with port
+ * @dev_name: SMD platform device name associated with port
+ *
+ * @open_lock_lha1: open/close lock - used to serialize open/close operations
+ * @open_wait: Timeout in seconds to wait for SMD port to be created / opened
+ *
+ * @reset_lock_lha2: lock for reset and open state
+ * @in_reset: True if SMD channel is closed / in SSR
+ * @in_reset_updated: reset state changed
+ * @is_open: True if SMD port is open
+ * @ch_opened_wait_queue: SMD port open/close wait queue
+ *
+ * @ra_lock_lha3: Read-available lock - used to synchronize reads from SMD
+ * @ra_wakeup_source_name: Name of the read-available wakeup source
+ * @ra_wakeup_source: Read-available wakeup source
+ */
struct smd_tty_info {
smd_channel_t *ch;
struct tty_port port;
struct device *device_ptr;
- struct wake_lock wake_lock;
+ struct wakeup_source pending_ws;
struct tasklet_struct tty_tsklt;
struct timer_list buf_req_timer;
struct completion ch_allocated;
struct platform_driver driver;
void *pil;
- int in_reset;
- int in_reset_updated;
- int is_open;
- unsigned int open_wait;
- wait_queue_head_t ch_opened_wait_queue;
- spinlock_t reset_lock;
- spinlock_t ra_lock; /* Read Available Lock*/
- char ra_wake_lock_name[MAX_RA_WAKE_LOCK_NAME_LEN];
- struct wake_lock ra_wake_lock; /* Read Available Wakelock */
-
uint32_t edge;
char ch_name[SMD_MAX_CH_NAME_LEN];
char dev_name[SMD_MAX_CH_NAME_LEN];
+
+ struct mutex open_lock_lha1;
+ unsigned int open_wait;
+
+ spinlock_t reset_lock_lha2;
+ int in_reset;
+ int in_reset_updated;
+ int is_open;
+ wait_queue_head_t ch_opened_wait_queue;
+
+ spinlock_t ra_lock_lha3;
+ char ra_wakeup_source_name[MAX_RA_WAKE_LOCK_NAME_LEN];
+ struct wakeup_source ra_wakeup_source;
};
/**
@@ -140,13 +172,13 @@
struct smd_tty_info *info = (struct smd_tty_info *)param;
unsigned long flags;
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
if (info->is_open) {
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
tasklet_hi_schedule(&info->tty_tsklt);
return;
}
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
}
static ssize_t open_timeout_store(struct device *dev,
@@ -168,7 +200,9 @@
return -EINVAL;
}
if (!kstrtoul(buf, 10, &wait)) {
+ mutex_lock(&smd_tty[num_dev].open_lock_lha1);
smd_tty[num_dev].open_wait = wait;
+ mutex_unlock(&smd_tty[num_dev].open_lock_lha1);
return n;
} else {
SMD_TTY_INFO("[%s]: Unable to convert %s to an int",
@@ -181,6 +215,7 @@
struct device_attribute *attr, char *buf)
{
unsigned int num_dev;
+ unsigned int open_wait;
if (dev == NULL) {
SMD_TTY_INFO("%s: Invalid Device passed", __func__);
@@ -195,8 +230,11 @@
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE, "%d\n",
- smd_tty[num_dev].open_wait);
+ mutex_lock(&smd_tty[num_dev].open_lock_lha1);
+ open_wait = smd_tty[num_dev].open_wait;
+ mutex_unlock(&smd_tty[num_dev].open_lock_lha1);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", open_wait);
}
static DEVICE_ATTR
@@ -222,14 +260,14 @@
}
if (test_bit(TTY_THROTTLED, &tty->flags)) break;
- spin_lock_irqsave(&info->ra_lock, flags);
+ spin_lock_irqsave(&info->ra_lock_lha3, flags);
avail = smd_read_avail(info->ch);
if (avail == 0) {
- wake_unlock(&info->ra_wake_lock);
- spin_unlock_irqrestore(&info->ra_lock, flags);
+ __pm_relax(&info->ra_wakeup_source);
+ spin_unlock_irqrestore(&info->ra_lock_lha3, flags);
break;
}
- spin_unlock_irqrestore(&info->ra_lock, flags);
+ spin_unlock_irqrestore(&info->ra_lock_lha3, flags);
if (avail > MAX_TTY_BUF_SIZE)
avail = MAX_TTY_BUF_SIZE;
@@ -252,7 +290,13 @@
__func__, info->ch->name);
}
- wake_lock_timeout(&info->wake_lock, HZ / 2);
+ /*
+ * Keep system awake long enough to allow the TTY
+ * framework to pass the flip buffer to any waiting
+ * userspace clients.
+ */
+ __pm_wakeup_event(&info->pending_ws, TTY_PUSH_WS_DELAY);
+
tty_flip_buffer_push(tty);
}
@@ -269,12 +313,12 @@
switch (event) {
case SMD_EVENT_DATA:
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
if (!info->is_open) {
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
break;
}
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
/* There may be clients (tty framework) that are blocked
* waiting for space to write data, so if a possible read
* interrupt came in wake anyone waiting and disable the
@@ -287,37 +331,45 @@
wake_up_interruptible(&tty->write_wait);
tty_kref_put(tty);
}
- spin_lock_irqsave(&info->ra_lock, flags);
+ spin_lock_irqsave(&info->ra_lock_lha3, flags);
if (smd_read_avail(info->ch)) {
- wake_lock(&info->ra_wake_lock);
+ __pm_stay_awake(&info->ra_wakeup_source);
tasklet_hi_schedule(&info->tty_tsklt);
}
- spin_unlock_irqrestore(&info->ra_lock, flags);
+ spin_unlock_irqrestore(&info->ra_lock_lha3, flags);
break;
case SMD_EVENT_OPEN:
- spin_lock_irqsave(&info->reset_lock, flags);
+ tty = tty_port_tty_get(&info->port);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
+ if (tty)
+ clear_bit(TTY_OTHER_CLOSED, &tty->flags);
info->in_reset = 0;
info->in_reset_updated = 1;
info->is_open = 1;
wake_up_interruptible(&info->ch_opened_wait_queue);
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
+ tty_kref_put(tty);
break;
case SMD_EVENT_CLOSE:
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
info->in_reset = 1;
info->in_reset_updated = 1;
info->is_open = 0;
wake_up_interruptible(&info->ch_opened_wait_queue);
- spin_unlock_irqrestore(&info->reset_lock, flags);
- /* schedule task to send TTY_BREAK */
- tasklet_hi_schedule(&info->tty_tsklt);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
tty = tty_port_tty_get(&info->port);
- if (tty->index == LOOPBACK_IDX)
- schedule_delayed_work(&loopback_work,
- msecs_to_jiffies(1000));
+ if (tty) {
+ /* send TTY_BREAK through read tasklet */
+ set_bit(TTY_OTHER_CLOSED, &tty->flags);
+ tasklet_hi_schedule(&info->tty_tsklt);
+
+ if (tty->index == LOOPBACK_IDX)
+ schedule_delayed_work(&loopback_work,
+ msecs_to_jiffies(1000));
+ }
tty_kref_put(tty);
break;
}
@@ -346,7 +398,7 @@
info = smd_tty + n;
- mutex_lock(&smd_tty_lock);
+ mutex_lock(&info->open_lock_lha1);
tty->driver_data = info;
peripheral = smd_edge_to_subsystem(smd_tty[n].edge);
@@ -407,12 +459,11 @@
}
tasklet_init(&info->tty_tsklt, smd_tty_read, (unsigned long)info);
- wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
- info->ch_name);
- scnprintf(info->ra_wake_lock_name, MAX_RA_WAKE_LOCK_NAME_LEN,
+ wakeup_source_init(&info->pending_ws, info->ch_name);
+ scnprintf(info->ra_wakeup_source_name, MAX_RA_WAKE_LOCK_NAME_LEN,
"SMD_TTY_%s_RA", info->ch_name);
- wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
- info->ra_wake_lock_name);
+ wakeup_source_init(&info->ra_wakeup_source,
+ info->ra_wakeup_source_name);
res = smd_named_open_on_edge(info->ch_name,
smd_tty[n].edge, &info->ch, info,
@@ -435,7 +486,7 @@
SMD_TTY_INFO("%s with PID %u opened port %s",
current->comm, current->pid, info->ch_name);
smd_disable_read_intr(info->ch);
- mutex_unlock(&smd_tty_lock);
+ mutex_unlock(&info->open_lock_lha1);
return 0;
close_ch:
@@ -444,13 +495,13 @@
release_wl_tl:
tasklet_kill(&info->tty_tsklt);
- wake_lock_destroy(&info->wake_lock);
- wake_lock_destroy(&info->ra_wake_lock);
+ wakeup_source_trash(&info->pending_ws);
+ wakeup_source_trash(&info->ra_wakeup_source);
release_pil:
subsystem_put(info->pil);
out:
- mutex_unlock(&smd_tty_lock);
+ mutex_unlock(&info->open_lock_lha1);
return res;
}
@@ -467,15 +518,15 @@
return;
}
- mutex_lock(&smd_tty_lock);
+ mutex_lock(&info->open_lock_lha1);
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
info->is_open = 0;
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
tasklet_kill(&info->tty_tsklt);
- wake_lock_destroy(&info->wake_lock);
- wake_lock_destroy(&info->ra_wake_lock);
+ wakeup_source_trash(&info->pending_ws);
+ wakeup_source_trash(&info->ra_wakeup_source);
SMD_TTY_INFO("%s with PID %u closed port %s",
current->comm, current->pid,
@@ -487,7 +538,7 @@
info->ch = NULL;
subsystem_put(info->pil);
- mutex_unlock(&smd_tty_lock);
+ mutex_unlock(&info->open_lock_lha1);
tty_kref_put(tty);
}
@@ -550,13 +601,13 @@
struct smd_tty_info *info = tty->driver_data;
unsigned long flags;
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
if (info->is_open) {
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
tasklet_hi_schedule(&info->tty_tsklt);
return;
}
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
}
/*
@@ -573,7 +624,7 @@
tiocm = smd_tiocmget(info->ch);
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
tiocm |= (info->in_reset ? TIOCM_OUT1 : 0);
if (info->in_reset_updated) {
tiocm |= TIOCM_OUT2;
@@ -581,7 +632,7 @@
}
SMD_TTY_INFO("PID %u --> %s TIOCM is %x ",
current->pid, __func__, tiocm);
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
return tiocm;
}
@@ -707,23 +758,29 @@
/* TODO: For kernel >= 3.7 use tty_port_register_device */
smd_tty[idx].device_ptr = tty_register_device(smd_tty_driver, idx, 0);
init_completion(&smd_tty[idx].ch_allocated);
+ mutex_init(&smd_tty[idx].open_lock_lha1);
/* register platform device */
smd_tty[idx].driver.probe = smd_tty_dummy_probe;
smd_tty[idx].driver.driver.name = smd_tty[idx].dev_name;
smd_tty[idx].driver.driver.owner = THIS_MODULE;
- spin_lock_init(&smd_tty[idx].reset_lock);
- spin_lock_init(&smd_tty[idx].ra_lock);
+ spin_lock_init(&smd_tty[idx].reset_lock_lha2);
+ spin_lock_init(&smd_tty[idx].ra_lock_lha3);
smd_tty[idx].is_open = 0;
setup_timer(&smd_tty[idx].buf_req_timer, buf_req_retry,
(unsigned long)&smd_tty[idx]);
init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue);
ret = platform_driver_register(&smd_tty[idx].driver);
+ if (ret)
+ return ret;
+ if (device_create_file(smd_tty[idx].device_ptr, &dev_attr_open_timeout))
+ SMD_TTY_ERR("%s: Unable to create device attributes for %s",
+ __func__, smd_configs[idx].port_name);
return ret;
}
-static int __init smd_tty_core_init(void)
+static int smd_tty_core_init(void)
{
int ret;
int n;
@@ -771,12 +828,6 @@
}
ret = smd_tty_device_init(idx);
- if (device_create_file(smd_tty[idx].device_ptr,
- &dev_attr_open_timeout))
- SMD_TTY_ERR(
- "%s: Unable to create device attributes for %s",
- __func__, smd_configs[n].port_name);
-
if (ret) {
SMD_TTY_ERR(
"%s: init failed %d (%d)", __func__, idx, ret);
@@ -803,7 +854,7 @@
return ret;
}
-static int __init smd_tty_devicetree_init(struct platform_device *pdev)
+static int smd_tty_devicetree_init(struct platform_device *pdev)
{
int ret;
int idx;
diff --git a/arch/arm/mach-msm/smp2p.c b/arch/arm/mach-msm/smp2p.c
index 4b69cf0..df241f8 100644
--- a/arch/arm/mach-msm/smp2p.c
+++ b/arch/arm/mach-msm/smp2p.c
@@ -53,6 +53,9 @@
* @smem_edge_out: Pointer to outbound smem item.
* @smem_edge_state: State of the outbound edge.
* @ops_ptr: Pointer to internal version-specific SMEM item access functions.
+ *
+ * @feature_ssr_ack_enabled: SSR ACK Support Enabled
+ * @restart_ack: Current cached state of the local ack bit
*/
struct smp2p_out_list_item {
spinlock_t out_item_lock_lha1;
@@ -61,11 +64,14 @@
struct smp2p_smem __iomem *smem_edge_out;
enum msm_smp2p_edge_state smem_edge_state;
struct smp2p_version_if *ops_ptr;
+
+ bool feature_ssr_ack_enabled;
+ bool restart_ack;
};
static struct smp2p_out_list_item out_list[SMP2P_NUM_PROCS];
static void *log_ctx;
-static int smp2p_debug_mask = MSM_SMP2P_INFO;
+static int smp2p_debug_mask = MSM_SMP2P_INFO | MSM_SMP2P_DEBUG;
module_param_named(debug_mask, smp2p_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
@@ -115,6 +121,7 @@
*
* @is_supported: True if this version is supported by SMP2P
* @negotiate_features: Returns (sub)set of supported features
+ * @negotiation_complete: Called when negotiation has been completed
* @find_entry: Finds existing / next empty entry
* @create_entry: Creates a new entry
* @read_entry: Reads the value of an entry
@@ -128,6 +135,7 @@
/* common functions */
bool is_supported;
uint32_t (*negotiate_features)(uint32_t features);
+ void (*negotiation_complete)(struct smp2p_out_list_item *);
void (*find_entry)(struct smp2p_smem __iomem *item,
uint32_t entries_total, char *name,
uint32_t **entry_ptr, int *empty_spot);
@@ -148,6 +156,7 @@
/* v0 (uninitialized SMEM item) interface functions */
static uint32_t smp2p_negotiate_features_v0(uint32_t features);
+static void smp2p_negotiation_complete_v0(struct smp2p_out_list_item *out_item);
static void smp2p_find_entry_v0(struct smp2p_smem __iomem *item,
uint32_t entries_total, char *name, uint32_t **entry_ptr,
int *empty_spot);
@@ -160,6 +169,7 @@
/* v1 interface functions */
static uint32_t smp2p_negotiate_features_v1(uint32_t features);
+static void smp2p_negotiation_complete_v1(struct smp2p_out_list_item *out_item);
static void smp2p_find_entry_v1(struct smp2p_smem __iomem *item,
uint32_t entries_total, char *name, uint32_t **entry_ptr,
int *empty_spot);
@@ -174,6 +184,7 @@
static struct smp2p_version_if version_if[] = {
[0] = {
.negotiate_features = smp2p_negotiate_features_v0,
+ .negotiation_complete = smp2p_negotiation_complete_v0,
.find_entry = smp2p_find_entry_v0,
.create_entry = smp2p_out_create_v0,
.read_entry = smp2p_out_read_v0,
@@ -184,6 +195,7 @@
[1] = {
.is_supported = true,
.negotiate_features = smp2p_negotiate_features_v1,
+ .negotiation_complete = smp2p_negotiation_complete_v1,
.find_entry = smp2p_find_entry_v1,
.create_entry = smp2p_out_create_v1,
.read_entry = smp2p_out_read_v1,
@@ -399,15 +411,76 @@
}
/**
- * smp2p_negotiate_features_v0 - Initial feature negotiation.
+ * smp2p_ssr_ack_needed - Returns true if SSR ACK required
+ *
+ * @rpid: Remote processor ID
+ *
+ * Must be called with out_item_lock_lha1 and in_item_lock_lhb1 locked.
+ */
+static bool smp2p_ssr_ack_needed(uint32_t rpid)
+{
+ bool ssr_done;
+
+ if (!out_list[rpid].feature_ssr_ack_enabled)
+ return false;
+
+ ssr_done = SMP2P_GET_RESTART_DONE(in_list[rpid].smem_edge_in->flags);
+ if (ssr_done != out_list[rpid].restart_ack)
+ return true;
+
+ return false;
+}
+
+/**
+ * smp2p_do_ssr_ack - Handles SSR ACK
+ *
+ * @rpid: Remote processor ID
+ *
+ * Must be called with out_item_lock_lha1 and in_item_lock_lhb1 locked.
+ */
+static void smp2p_do_ssr_ack(uint32_t rpid)
+{
+ bool ack;
+
+ if (!smp2p_ssr_ack_needed(rpid))
+ return;
+
+ ack = !out_list[rpid].restart_ack;
+ SMP2P_INFO("%s: ssr ack pid %d: %d -> %d\n", __func__, rpid,
+ out_list[rpid].restart_ack, ack);
+ out_list[rpid].restart_ack = ack;
+ SMP2P_SET_RESTART_ACK(out_list[rpid].smem_edge_out->flags, ack);
+ smp2p_send_interrupt(rpid);
+}
+
+/**
+ * smp2p_negotiate_features_v1 - Initial feature negotiation.
*
* @features: Inbound feature set.
* @returns: Supported features (will be a same/subset of @features).
*/
static uint32_t smp2p_negotiate_features_v1(uint32_t features)
{
- /* no supported features */
- return 0;
+ return SMP2P_FEATURE_SSR_ACK;
+}
+
+/**
+ * smp2p_negotiation_complete_v1 - Negotiation completed
+ *
+ * @out_item: Pointer to the output item structure
+ *
+ * Can be used to do final configuration based upon the negotiated feature set.
+ *
+ * Must be called with out_item_lock_lha1 locked.
+ */
+static void smp2p_negotiation_complete_v1(struct smp2p_out_list_item *out_item)
+{
+ uint32_t features;
+
+ features = SMP2P_GET_FEATURES(out_item->smem_edge_out->feature_version);
+
+ if (features & SMP2P_FEATURE_SSR_ACK)
+ out_item->feature_ssr_ack_enabled = true;
}
/**
@@ -707,6 +780,20 @@
}
/**
+ * smp2p_negotiation_complete_v0 - Negotiation completed
+ *
+ * @out_item: Pointer to the output item structure
+ *
+ * Can be used to do final configuration based upon the negotiated feature set.
+ */
+static void smp2p_negotiation_complete_v0(struct smp2p_out_list_item *out_item)
+{
+ SMP2P_ERR("%s: invalid negotiation complete for v0 pid %d\n",
+ __func__,
+ SMP2P_GET_REMOTE_PID(out_item->smem_edge_out->rem_loc_proc_id));
+}
+
+/**
* smp2p_find_entry_v0 - Stub function.
*
* @item: Pointer to the smem item.
@@ -885,7 +972,7 @@
SMP2P_SET_FEATURES(header_ptr->feature_version, features);
SMP2P_SET_ENT_TOTAL(header_ptr->valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(header_ptr->valid_total_ent, 0);
- header_ptr->reserved = 0;
+ header_ptr->flags = 0;
/* ensure that all fields are valid before version is written */
wmb();
@@ -992,8 +1079,9 @@
struct msm_smp2p_out *pos;
/* negotiation complete */
- out_item->smem_edge_state = SMP2P_EDGE_STATE_OPENED;
out_item->ops_ptr = &version_if[l_version];
+ out_item->ops_ptr->negotiation_complete(out_item);
+ out_item->smem_edge_state = SMP2P_EDGE_STATE_OPENED;
SMP2P_INFO(
"%s: negotiation complete pid %d: State %d->%d F0x%08x\n",
__func__, remote_pid, prev_state,
@@ -1528,9 +1616,41 @@
smp2p_do_negotiation(remote_pid, &out_list[remote_pid]);
if (out_list[remote_pid].smem_edge_state == SMP2P_EDGE_STATE_OPENED) {
+ bool do_restart_ack;
+
+ /*
+ * Follow double-check pattern for restart ack since:
+ * 1) we must notify clients of the X->0 transition
+ * that is part of the restart
+ * 2) lock cannot be held during the
+ * smp2p_in_edge_notify() call because clients may do
+ * re-entrant calls into our APIs.
+ *
+ * smp2p_do_ssr_ack() will only do the ack if it is
+ * necessary to handle the race condition exposed by
+ * unlocking the spinlocks.
+ */
+ spin_lock(&in_list[remote_pid].in_item_lock_lhb1);
+ do_restart_ack = smp2p_ssr_ack_needed(remote_pid);
+ spin_unlock(&in_list[remote_pid].in_item_lock_lhb1);
spin_unlock_irqrestore(&out_list[remote_pid].out_item_lock_lha1,
flags);
+
smp2p_in_edge_notify(remote_pid);
+
+ if (do_restart_ack) {
+ spin_lock_irqsave(
+ &out_list[remote_pid].out_item_lock_lha1,
+ flags);
+ spin_lock(&in_list[remote_pid].in_item_lock_lhb1);
+
+ smp2p_do_ssr_ack(remote_pid);
+
+ spin_unlock(&in_list[remote_pid].in_item_lock_lhb1);
+ spin_unlock_irqrestore(
+ &out_list[remote_pid].out_item_lock_lha1,
+ flags);
+ }
} else {
spin_unlock_irqrestore(&out_list[remote_pid].out_item_lock_lha1,
flags);
@@ -1565,6 +1685,8 @@
out_list[rpid].smem_edge_out = NULL;
out_list[rpid].ops_ptr = &version_if[0];
out_list[rpid].smem_edge_state = SMP2P_EDGE_STATE_CLOSED;
+ out_list[rpid].feature_ssr_ack_enabled = false;
+ out_list[rpid].restart_ack = false;
in_list[rpid].smem_edge_in = NULL;
in_list[rpid].item_size = 0;
@@ -1699,6 +1821,8 @@
out_list[i].smem_edge_out = NULL;
out_list[i].smem_edge_state = SMP2P_EDGE_STATE_CLOSED;
out_list[i].ops_ptr = &version_if[0];
+ out_list[i].feature_ssr_ack_enabled = false;
+ out_list[i].restart_ack = false;
spin_lock_init(&in_list[i].in_item_lock_lhb1);
INIT_LIST_HEAD(&in_list[i].list);
diff --git a/arch/arm/mach-msm/smp2p_debug.c b/arch/arm/mach-msm/smp2p_debug.c
index a493cbe..f4ff42d 100644
--- a/arch/arm/mach-msm/smp2p_debug.c
+++ b/arch/arm/mach-msm/smp2p_debug.c
@@ -141,9 +141,11 @@
}
i += scnprintf(buf + i, max - i,
- "Entries Valid/Max: %d/%d",
+ "Entries #/Max: %d/%d Flags: %c%c",
SMP2P_GET_ENT_VALID(item_ptr->valid_total_ent),
- SMP2P_GET_ENT_TOTAL(item_ptr->valid_total_ent)
+ SMP2P_GET_ENT_TOTAL(item_ptr->valid_total_ent),
+ item_ptr->flags & SMP2P_FLAGS_RESTART_ACK_MASK ? 'A' : 'a',
+ item_ptr->flags & SMP2P_FLAGS_RESTART_DONE_MASK ? 'D' : 'd'
);
return i;
diff --git a/arch/arm/mach-msm/smp2p_gpio.c b/arch/arm/mach-msm/smp2p_gpio.c
index 2a85e5f..5f70e0c 100644
--- a/arch/arm/mach-msm/smp2p_gpio.c
+++ b/arch/arm/mach-msm/smp2p_gpio.c
@@ -420,7 +420,7 @@
spin_unlock_irqrestore(&chip->irq_lock, flags);
if (trigger_interrrupt) {
- SMP2P_GPIO(
+ SMP2P_INFO(
"'%s':%d GPIO bit %d virq %d (%s,%s) - edge %s triggering\n",
chip->name, chip->remote_pid, i,
chip->irq_base + i,
diff --git a/arch/arm/mach-msm/smp2p_private.h b/arch/arm/mach-msm/smp2p_private.h
index b9a5cfe..8e0d7a3 100644
--- a/arch/arm/mach-msm/smp2p_private.h
+++ b/arch/arm/mach-msm/smp2p_private.h
@@ -20,8 +20,7 @@
#include "smp2p_private_api.h"
#define SMP2P_MAX_ENTRY 16
-#define SMP2P_LOCAL_VERSION 1
-#define SMP2P_LOCAL_FEATURE 0x0
+#define SMP2P_FEATURE_SSR_ACK 0x1
/* SMEM Item Header Macros */
#define SMP2P_MAGIC 0x504D5324
@@ -37,6 +36,10 @@
#define SMP2P_ENT_TOTAL_BIT 0
#define SMP2P_ENT_VALID_MASK 0xffff0000
#define SMP2P_ENT_VALID_BIT 16
+#define SMP2P_FLAGS_RESTART_DONE_BIT 0
+#define SMP2P_FLAGS_RESTART_DONE_MASK 0x1
+#define SMP2P_FLAGS_RESTART_ACK_BIT 1
+#define SMP2P_FLAGS_RESTART_ACK_MASK 0x2
#define SMP2P_GET_BITS(hdr_val, mask, bit) \
(((hdr_val) & (mask)) >> (bit))
@@ -77,6 +80,20 @@
SMP2P_SET_BITS(hdr, SMP2P_ENT_VALID_MASK, SMP2P_ENT_VALID_BIT,\
entries)
+#define SMP2P_GET_RESTART_DONE(hdr) \
+ SMP2P_GET_BITS(hdr, SMP2P_FLAGS_RESTART_DONE_MASK, \
+ SMP2P_FLAGS_RESTART_DONE_BIT)
+#define SMP2P_SET_RESTART_DONE(hdr, value) \
+ SMP2P_SET_BITS(hdr, SMP2P_FLAGS_RESTART_DONE_MASK, \
+ SMP2P_FLAGS_RESTART_DONE_BIT, value)
+
+#define SMP2P_GET_RESTART_ACK(hdr) \
+ SMP2P_GET_BITS(hdr, SMP2P_FLAGS_RESTART_ACK_MASK, \
+ SMP2P_FLAGS_RESTART_ACK_BIT)
+#define SMP2P_SET_RESTART_ACK(hdr, value) \
+ SMP2P_SET_BITS(hdr, SMP2P_FLAGS_RESTART_ACK_MASK, \
+ SMP2P_FLAGS_RESTART_ACK_BIT, value)
+
/* Loopback Command Macros */
#define SMP2P_RMT_CMD_TYPE_MASK 0x80000000
#define SMP2P_RMT_CMD_TYPE_BIT 31
@@ -162,12 +179,21 @@
SMP2P_EDGE_STATE_FAILED = 0xff,
};
+/**
+ * struct smp2p_smem - SMP2P SMEM Item Header
+ *
+ * @magic: Set to "$SMP" -- used for identification / debug purposes
+ * @feature_version: Feature and version fields
+ * @rem_loc_proc_id: Remote (31:16) and Local (15:0) processor IDs
+ * @valid_total_ent: Valid (31:16) and total (15:0) entries
+ * @flags: Flags (bits 31:2 reserved)
+ */
struct smp2p_smem {
uint32_t magic;
uint32_t feature_version;
uint32_t rem_loc_proc_id;
uint32_t valid_total_ent;
- uint32_t reserved;
+ uint32_t flags;
};
struct smp2p_entry_v1 {
diff --git a/arch/arm/mach-msm/smp2p_test.c b/arch/arm/mach-msm/smp2p_test.c
index 18c9bfd..2f86df4 100644
--- a/arch/arm/mach-msm/smp2p_test.c
+++ b/arch/arm/mach-msm/smp2p_test.c
@@ -16,6 +16,7 @@
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/completion.h>
+#include <mach/subsystem_restart.h>
#include "smp2p_private.h"
#include "smp2p_test_common.h"
@@ -77,7 +78,7 @@
rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
rmp->tx_interrupt();
@@ -161,7 +162,7 @@
SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
@@ -251,7 +252,7 @@
rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(false);
UT_ASSERT_PTR(NULL, ==,
@@ -369,7 +370,7 @@
rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 1);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
/* Create test entry and attach loopback server */
@@ -794,7 +795,7 @@
rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
/* Create Max Entries in the remote mock object */
@@ -892,7 +893,7 @@
rmp->remote_item.header.valid_total_ent, 1);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
/* Create an Entry in the remote mock object */
@@ -953,6 +954,217 @@
}
}
+/**
+ * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature
+ *
+ * @s: pointer to output file
+ */
+static void smp2p_ut_local_ssr_ack(struct seq_file *s)
+{
+ int failed = 0;
+ struct msm_smp2p_remote_mock *rmp = NULL;
+ int ret;
+
+ seq_printf(s, "Running %s\n", __func__);
+ do {
+ struct smp2p_smem *rhdr;
+ struct smp2p_smem *lhdr;
+ int negotiation_state;
+
+ /* initialize v1 without SMP2P_FEATURE_SSR_ACK enabled */
+ ret = smp2p_reset_mock_edge();
+ UT_ASSERT_INT(ret, ==, 0);
+ rmp = msm_smp2p_get_remote_mock();
+ UT_ASSERT_PTR(rmp, !=, NULL);
+ rhdr = &rmp->remote_item.header;
+
+ rmp->rx_interrupt_count = 0;
+ memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item));
+ rhdr->magic = SMP2P_MAGIC;
+ SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id,
+ SMP2P_REMOTE_MOCK_PROC);
+ SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC);
+ SMP2P_SET_VERSION(rhdr->feature_version, 1);
+ SMP2P_SET_FEATURES(rhdr->feature_version, 0);
+ SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY);
+ SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0);
+ rhdr->flags = 0x0;
+ msm_smp2p_set_remote_mock_exists(true);
+ rmp->tx_interrupt();
+
+ /* verify edge is open */
+ lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC,
+ &negotiation_state);
+ UT_ASSERT_PTR(NULL, !=, lhdr);
+ UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED);
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
+
+ /* verify no response to ack feature */
+ rmp->rx_interrupt_count = 0;
+ SMP2P_SET_RESTART_DONE(rhdr->flags, 1);
+ rmp->tx_interrupt();
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0);
+
+ /* initialize v1 with SMP2P_FEATURE_SSR_ACK enabled */
+ ret = smp2p_reset_mock_edge();
+ UT_ASSERT_INT(ret, ==, 0);
+ rmp = msm_smp2p_get_remote_mock();
+ UT_ASSERT_PTR(rmp, !=, NULL);
+ rhdr = &rmp->remote_item.header;
+
+ rmp->rx_interrupt_count = 0;
+ memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item));
+ rhdr->magic = SMP2P_MAGIC;
+ SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id,
+ SMP2P_REMOTE_MOCK_PROC);
+ SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC);
+ SMP2P_SET_VERSION(rhdr->feature_version, 1);
+ SMP2P_SET_FEATURES(rhdr->feature_version,
+ SMP2P_FEATURE_SSR_ACK);
+ SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY);
+ SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0);
+ rmp->rx_interrupt_count = 0;
+ rhdr->flags = 0x0;
+ msm_smp2p_set_remote_mock_exists(true);
+ rmp->tx_interrupt();
+
+ /* verify edge is open */
+ lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC,
+ &negotiation_state);
+ UT_ASSERT_PTR(NULL, !=, lhdr);
+ UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED);
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
+
+ /* verify response to ack feature */
+ rmp->rx_interrupt_count = 0;
+ SMP2P_SET_RESTART_DONE(rhdr->flags, 1);
+ rmp->tx_interrupt();
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
+ UT_ASSERT_INT(1, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
+
+ rmp->rx_interrupt_count = 0;
+ SMP2P_SET_RESTART_DONE(rhdr->flags, 0);
+ rmp->tx_interrupt();
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
+
+ seq_puts(s, "\tOK\n");
+ } while (0);
+
+ if (failed) {
+ pr_err("%s: Failed\n", __func__);
+ seq_puts(s, "\tFailed\n");
+ }
+}
+
+/**
+ * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature
+ *
+ * @s: pointer to output file
+ * @rpid: Remote processor ID
+ * @int_cfg: Interrupt config
+ */
+static void smp2p_ut_remotesubsys_ssr_ack(struct seq_file *s, uint32_t rpid,
+ struct smp2p_interrupt_config *int_cfg)
+{
+ int failed = 0;
+
+ seq_printf(s, "Running %s\n", __func__);
+ do {
+ struct smp2p_smem *rhdr;
+ struct smp2p_smem *lhdr;
+ int negotiation_state;
+ bool ssr_ack_enabled;
+ uint32_t ssr_done_start;
+
+ lhdr = smp2p_get_out_item(rpid, &negotiation_state);
+ UT_ASSERT_PTR(NULL, !=, lhdr);
+ UT_ASSERT_INT(SMP2P_EDGE_STATE_OPENED, ==, negotiation_state);
+
+ rhdr = smp2p_get_in_item(rpid);
+ UT_ASSERT_PTR(NULL, !=, rhdr);
+
+ /* get initial state of SSR flags */
+ if (SMP2P_GET_FEATURES(rhdr->feature_version)
+ & SMP2P_FEATURE_SSR_ACK)
+ ssr_ack_enabled = true;
+ else
+ ssr_ack_enabled = false;
+
+ ssr_done_start = SMP2P_GET_RESTART_DONE(rhdr->flags);
+ UT_ASSERT_INT(ssr_done_start, ==,
+ SMP2P_GET_RESTART_ACK(lhdr->flags));
+
+ /* trigger restart */
+ seq_printf(s, "Restarting '%s'\n", int_cfg->name);
+ subsystem_restart(int_cfg->name);
+ msleep(10*1000);
+
+ /* verify ack signaling */
+ if (ssr_ack_enabled) {
+ ssr_done_start ^= 1;
+ UT_ASSERT_INT(ssr_done_start, ==,
+ SMP2P_GET_RESTART_ACK(lhdr->flags));
+ UT_ASSERT_INT(ssr_done_start, ==,
+ SMP2P_GET_RESTART_DONE(rhdr->flags));
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_DONE(lhdr->flags));
+ seq_puts(s, "\tSSR ACK Enabled and Toggled\n");
+ } else {
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_DONE(lhdr->flags));
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_ACK(lhdr->flags));
+
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_DONE(rhdr->flags));
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_ACK(rhdr->flags));
+ seq_puts(s, "\tSSR ACK Disabled\n");
+ }
+
+ seq_puts(s, "\tOK\n");
+ } while (0);
+
+ if (failed) {
+ pr_err("%s: Failed\n", __func__);
+ seq_puts(s, "\tFailed\n");
+ }
+}
+
+/**
+ * smp2p_ut_remote_ssr_ack - Verify SSR Done/ACK Feature
+ *
+ * @s: pointer to output file
+ *
+ * Triggers SSR for each subsystem.
+ */
+static void smp2p_ut_remote_ssr_ack(struct seq_file *s)
+{
+ struct smp2p_interrupt_config *int_cfg;
+ int pid;
+
+ int_cfg = smp2p_get_interrupt_config();
+ if (!int_cfg) {
+ seq_puts(s,
+ "Remote processor config unavailable\n");
+ return;
+ }
+
+ for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) {
+ if (!int_cfg[pid].is_configured)
+ continue;
+
+ msm_smp2p_deinit_rmt_lpb_proc(pid);
+ smp2p_ut_remotesubsys_ssr_ack(s, pid, &int_cfg[pid]);
+ msm_smp2p_init_rmt_lpb_proc(pid);
+ }
+}
+
static struct dentry *dent;
static int debugfs_show(struct seq_file *s, void *data)
@@ -1019,6 +1231,10 @@
smp2p_ut_remote_out_max_entries);
smp2p_debug_create("ut_local_in_multiple",
smp2p_ut_local_in_multiple);
+ smp2p_debug_create("ut_local_ssr_ack",
+ smp2p_ut_local_ssr_ack);
+ smp2p_debug_create("ut_remote_ssr_ack",
+ smp2p_ut_remote_ssr_ack);
return 0;
}
diff --git a/drivers/bif/bif-core.c b/drivers/bif/bif-core.c
index e11e6ba4..7bc9af2 100644
--- a/drivers/bif/bif-core.c
+++ b/drivers/bif/bif-core.c
@@ -2827,6 +2827,7 @@
struct bif_ctrl_dev *bdev = ERR_PTR(-EINVAL);
struct bif_slave_dev *sdev;
bool battery_present = false;
+ bool slaves_present = false;
int rc, rid_ohm;
if (!bif_desc) {
@@ -2901,12 +2902,21 @@
list_for_each_entry(sdev, &bif_sdev_list, list) {
if (sdev->present) {
battery_present = true;
+ slaves_present = true;
break;
}
}
BLOCKING_INIT_NOTIFIER_HEAD(&bdev->bus_change_notifier);
+ /* Disable the BIF bus master if no slaves are found. */
+ if (!slaves_present) {
+ rc = bdev->desc->ops->set_bus_state(bdev,
+ BIF_BUS_STATE_MASTER_DISABLED);
+ if (rc < 0)
+ pr_err("Could not disble BIF master, rc=%d\n", rc);
+ }
+
if (battery_present) {
bdev->battery_present = true;
rc = blocking_notifier_call_chain(&bdev->bus_change_notifier,
diff --git a/drivers/bif/qpnp-bsi.c b/drivers/bif/qpnp-bsi.c
index 9d0abd2..19a560a 100644
--- a/drivers/bif/qpnp-bsi.c
+++ b/drivers/bif/qpnp-bsi.c
@@ -1162,6 +1162,7 @@
+ QPNP_BSI_POWER_UP_LOW_DELAY_US);
break;
case BIF_BUS_STATE_POWER_DOWN:
+ case BIF_BUS_STATE_MASTER_DISABLED:
msleep(QPNP_BSI_MAX_SLAVE_POWER_UP_DELAY_MS);
break;
}
@@ -1180,13 +1181,34 @@
{
struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
int rc = 0;
+ u8 reg;
if (state == chip->state)
return 0;
+ if (chip->state == BIF_BUS_STATE_MASTER_DISABLED) {
+ /*
+ * Enable the BSI peripheral when transitioning from a disabled
+ * bus state to any of the active bus states so that BIF
+ * transactions can take place.
+ */
+ reg = QPNP_BSI_ENABLE;
+ rc = qpnp_bsi_write(chip, QPNP_BSI_REG_ENABLE, ®, 1);
+ if (rc) {
+ dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
switch (state) {
case BIF_BUS_STATE_MASTER_DISABLED:
- pr_info("master disable not yet supported.\n");
+ /* Disable the BSI peripheral. */
+ reg = QPNP_BSI_DISABLE;
+ rc = qpnp_bsi_write(chip, QPNP_BSI_REG_ENABLE, ®, 1);
+ if (rc)
+ dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ __func__, rc);
break;
case BIF_BUS_STATE_POWER_DOWN:
rc = qpnp_bsi_bus_transaction(bdev, BIF_TRANS_BC, BIF_CMD_PDWN);
@@ -1624,7 +1646,7 @@
struct device *dev = &spmi->dev;
struct qpnp_bsi_chip *chip;
int rc;
- u8 type[2], reg;
+ u8 type[2];
if (!spmi->dev.of_node) {
dev_err(dev, "%s: device node missing\n", __func__);
@@ -1655,7 +1677,7 @@
chip->spmi_dev = spmi;
chip->bdesc.ops = &qpnp_bsi_ops;
- chip->state = BIF_BUS_STATE_POWER_DOWN;
+ chip->state = BIF_BUS_STATE_MASTER_DISABLED;
chip->com_mode = QPNP_BSI_COM_MODE_IRQ;
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_TYPE, type, 2);
@@ -1691,15 +1713,6 @@
goto cleanup_irqs;
}
- /* Enable the BSI module. */
- reg = QPNP_BSI_ENABLE;
- rc = qpnp_bsi_write(chip, QPNP_BSI_REG_ENABLE, ®, 1);
- if (rc) {
- dev_err(dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
- __func__, rc);
- goto cleanup_irqs;
- }
-
chip->bdev = bif_ctrl_register(&chip->bdesc, dev, chip,
spmi->dev.of_node);
if (IS_ERR(chip->bdev)) {
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index a740be6..4507f80 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -232,7 +232,7 @@
buf->virt = 0;
heap = me->smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) :
ION_HEAP(ION_ADSP_HEAP_ID) | ION_HEAP(ION_AUDIO_HEAP_ID);
- buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, 0);
+ buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, ION_FLAG_CACHED);
VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle));
if (err)
goto bail;
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 9c27180..69e6250 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -368,7 +368,7 @@
driver->log_mask->status = DIAG_CTRL_MASK_INVALID;
}
- if (driver->msg_mask->status == DIAG_CTRL_MASK_INVALID) {
+ if (driver->log_mask->status == DIAG_CTRL_MASK_INVALID) {
mutex_unlock(&driver->diag_cntl_mutex);
return;
}
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 16338a9..6b20b20 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -94,7 +94,7 @@
csr_writel(drvdata, usbbamctrl, CSR_USBBAMCTRL);
usbflshctrl = csr_readl(drvdata, CSR_USBFLSHCTRL);
- usbflshctrl = (usbflshctrl & ~0x3FFFC) | (0x1000 << 2);
+ usbflshctrl = (usbflshctrl & ~0x3FFFC) | (0xFFFF << 2);
csr_writel(drvdata, usbflshctrl, CSR_USBFLSHCTRL);
usbflshctrl |= 0x2;
csr_writel(drvdata, usbflshctrl, CSR_USBFLSHCTRL);
diff --git a/drivers/coresight/coresight-cti.c b/drivers/coresight/coresight-cti.c
index 2a06f0a..6f7f743 100644
--- a/drivers/coresight/coresight-cti.c
+++ b/drivers/coresight/coresight-cti.c
@@ -295,6 +295,41 @@
}
EXPORT_SYMBOL(coresight_cti_unmap_trigout);
+static void __cti_reset(struct cti_drvdata *drvdata)
+{
+ int trig;
+
+ if (!drvdata->refcnt)
+ return;
+
+ CTI_UNLOCK(drvdata);
+
+ for (trig = 0; trig < CTI_MAX_TRIGGERS; trig++) {
+ cti_writel(drvdata, 0, CTIINEN(trig));
+ cti_writel(drvdata, 0, CTIOUTEN(trig));
+ }
+
+ CTI_LOCK(drvdata);
+
+ cti_disable(drvdata);
+ drvdata->refcnt = 0;
+}
+
+void coresight_cti_reset(struct coresight_cti *cti)
+{
+ struct cti_drvdata *drvdata;
+
+ if (IS_ERR_OR_NULL(cti))
+ return;
+
+ drvdata = to_cti_drvdata(cti);
+
+ mutex_lock(&drvdata->mutex);
+ __cti_reset(drvdata);
+ mutex_unlock(&drvdata->mutex);
+}
+EXPORT_SYMBOL(coresight_cti_reset);
+
struct coresight_cti *coresight_cti_get(const char *name)
{
struct coresight_cti *cti;
@@ -387,6 +422,24 @@
}
static DEVICE_ATTR(unmap_trigout, S_IWUSR, NULL, cti_store_unmap_trigout);
+static ssize_t cti_store_reset(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ if (!val)
+ return -EINVAL;
+
+ coresight_cti_reset(&drvdata->cti);
+ return size;
+}
+static DEVICE_ATTR(reset, S_IWUSR, NULL, cti_store_reset);
+
static ssize_t cti_show_trigin(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -395,6 +448,10 @@
uint32_t ctien;
ssize_t size = 0;
+ mutex_lock(&cti_lock);
+ if (!drvdata->refcnt)
+ goto err;
+
for (trig = 0; trig < CTI_MAX_TRIGGERS; trig++) {
ctien = cti_readl(drvdata, CTIINEN(trig));
for (ch = 0; ch < CTI_MAX_CHANNELS; ch++) {
@@ -415,6 +472,7 @@
}
err:
size += scnprintf(&buf[size], 2, "\n");
+ mutex_unlock(&cti_lock);
return size;
}
static DEVICE_ATTR(show_trigin, S_IRUGO, cti_show_trigin, NULL);
@@ -427,6 +485,10 @@
uint32_t ctien;
ssize_t size = 0;
+ mutex_lock(&cti_lock);
+ if (!drvdata->refcnt)
+ goto err;
+
for (trig = 0; trig < CTI_MAX_TRIGGERS; trig++) {
ctien = cti_readl(drvdata, CTIOUTEN(trig));
for (ch = 0; ch < CTI_MAX_CHANNELS; ch++) {
@@ -447,6 +509,7 @@
}
err:
size += scnprintf(&buf[size], 2, "\n");
+ mutex_unlock(&cti_lock);
return size;
}
static DEVICE_ATTR(show_trigout, S_IRUGO, cti_show_trigout, NULL);
@@ -456,6 +519,7 @@
&dev_attr_map_trigout.attr,
&dev_attr_unmap_trigin.attr,
&dev_attr_unmap_trigout.attr,
+ &dev_attr_reset.attr,
&dev_attr_show_trigin.attr,
&dev_attr_show_trigout.attr,
NULL,
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 3225817..8267293 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -22,7 +22,6 @@
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
-#include <linux/memory_alloc.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/clk.h>
@@ -35,7 +34,7 @@
#include <linux/interrupt.h>
#include <linux/cdev.h>
#include <linux/usb/usb_qdss.h>
-#include <mach/memory.h>
+#include <linux/dma-mapping.h>
#include <mach/sps.h>
#include <mach/usb_bam.h>
#include <mach/msm_memory_dump.h>
@@ -154,7 +153,7 @@
bool aborting;
char *reg_buf;
char *buf;
- unsigned long paddr;
+ dma_addr_t paddr;
void __iomem *vaddr;
uint32_t size;
struct mutex usb_lock;
@@ -273,9 +272,11 @@
axictl = (axictl & ~0x3) | 0x2;
tmc_writel(drvdata, axictl, TMC_AXICTL);
- tmc_writel(drvdata, bamdata->data_fifo.phys_base, TMC_DBALO);
- tmc_writel(drvdata, 0x0, TMC_DBAHI);
- tmc_writel(drvdata, 0x103, TMC_FFCR);
+ tmc_writel(drvdata, (uint32_t)bamdata->data_fifo.phys_base, TMC_DBALO);
+ tmc_writel(drvdata, (((uint64_t)bamdata->data_fifo.phys_base) >> 32)
+ & 0xFF, TMC_DBAHI);
+ /* Set FOnFlIn for periodic flush */
+ tmc_writel(drvdata, 0x133, TMC_FFCR);
tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
__tmc_enable(drvdata);
@@ -341,7 +342,6 @@
TMC_UNLOCK(drvdata);
tmc_wait_for_flush(drvdata);
- tmc_flush_and_stop(drvdata);
__tmc_disable(drvdata);
TMC_LOCK(drvdata);
@@ -470,8 +470,9 @@
axictl = (axictl & ~0x3) | 0x2;
tmc_writel(drvdata, axictl, TMC_AXICTL);
- tmc_writel(drvdata, drvdata->paddr, TMC_DBALO);
- tmc_writel(drvdata, 0x0, TMC_DBAHI);
+ tmc_writel(drvdata, (uint32_t)drvdata->paddr, TMC_DBALO);
+ tmc_writel(drvdata, (((uint64_t)drvdata->paddr) >> 32) & 0xFF,
+ TMC_DBAHI);
tmc_writel(drvdata, 0x1133, TMC_FFCR);
tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
__tmc_enable(drvdata);
@@ -1300,7 +1301,7 @@
return -EINVAL;
if ((drvdata->size / 8) < val)
return -EINVAL;
- if (drvdata->size % (val * 8) != 0)
+ if (val && drvdata->size % (val * 8) != 0)
return -EINVAL;
drvdata->byte_cntr_value = val;
@@ -1564,7 +1565,8 @@
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
if (pdev->dev.of_node) {
ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,memory-reservation-size", &drvdata->size);
+ "qcom,memory-size",
+ &drvdata->size);
if (ret) {
clk_disable_unprepare(drvdata->clk);
return ret;
@@ -1577,17 +1579,11 @@
clk_disable_unprepare(drvdata->clk);
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- drvdata->paddr = allocate_contiguous_ebi_nomap(drvdata->size,
- SZ_4K);
- if (!drvdata->paddr)
+ drvdata->vaddr = dma_zalloc_coherent(&pdev->dev, drvdata->size,
+ &drvdata->paddr,
+ GFP_KERNEL);
+ if (!drvdata->vaddr)
return -ENOMEM;
- drvdata->vaddr = devm_ioremap(dev, drvdata->paddr,
- drvdata->size);
- if (!drvdata->vaddr) {
- ret = -ENOMEM;
- goto err0;
- }
- memset(drvdata->vaddr, 0, drvdata->size);
drvdata->buf = drvdata->vaddr;
drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
if (pdev->dev.of_node)
@@ -1727,7 +1723,10 @@
err1:
tmc_etr_byte_cntr_exit(drvdata);
err0:
- free_contiguous_memory_by_paddr(drvdata->paddr);
+ if (drvdata->vaddr)
+ dma_free_coherent(&pdev->dev, drvdata->size,
+ drvdata->vaddr,
+ drvdata->paddr);
return ret;
}
@@ -1739,7 +1738,9 @@
misc_deregister(&drvdata->miscdev);
coresight_unregister(drvdata->csdev);
tmc_etr_bam_exit(drvdata);
- free_contiguous_memory_by_paddr(drvdata->paddr);
+ if (drvdata->vaddr)
+ dma_free_coherent(&pdev->dev, drvdata->size, drvdata->vaddr,
+ drvdata->paddr);
return 0;
}
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index 032327c..1121f57 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -88,6 +88,11 @@
unsigned int reg_high;
unsigned int reg_lpm;
unsigned int reg_hpm;
+ struct regulator *reg_io;
+ unsigned int reg_low_io;
+ unsigned int reg_high_io;
+ unsigned int reg_lpm_io;
+ unsigned int reg_hpm_io;
enum tpiu_set set;
unsigned int seta_gpiocnt;
unsigned int *seta_gpios;
@@ -240,7 +245,7 @@
{
int ret;
- if (!drvdata->reg)
+ if (!drvdata->reg || !drvdata->reg_io)
return -EINVAL;
ret = tpiu_reg_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
@@ -253,6 +258,20 @@
ret = regulator_enable(drvdata->reg);
if (ret)
goto err1;
+ ret = tpiu_reg_set_optimum_mode(drvdata->reg_io, drvdata->reg_hpm_io);
+ if (ret < 0)
+ goto err2;
+ ret = tpiu_reg_set_voltage(drvdata->reg_io, drvdata->reg_low_io,
+ drvdata->reg_high_io);
+ if (ret)
+ goto err3;
+ ret = regulator_enable(drvdata->reg_io);
+ if (ret)
+ goto err4;
+
+ ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_FIXED);
+ if (ret)
+ goto err5;
msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x16D);
msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);
@@ -265,6 +284,14 @@
TPIU_LOCK(drvdata);
return 0;
+err5:
+ regulator_disable(drvdata->reg_io);
+err4:
+ tpiu_reg_set_voltage(drvdata->reg_io, 0, drvdata->reg_high_io);
+err3:
+ tpiu_reg_set_optimum_mode(drvdata->reg_io, 0);
+err2:
+ regulator_disable(drvdata->reg);
err1:
tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
err0:
@@ -342,9 +369,15 @@
msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 0);
+ clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+
regulator_disable(drvdata->reg);
- tpiu_reg_set_optimum_mode(drvdata->reg, 0);
tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
+ tpiu_reg_set_optimum_mode(drvdata->reg, 0);
+
+ regulator_disable(drvdata->reg_io);
+ tpiu_reg_set_voltage(drvdata->reg_io, 0, drvdata->reg_high_io);
+ tpiu_reg_set_optimum_mode(drvdata->reg_io, 0);
}
static void tpiu_disable(struct coresight_device *csdev)
@@ -566,6 +599,33 @@
dev_err(dev, "sdc voltage supply not specified or available\n");
}
+ reg_node = of_parse_phandle(node, "vdd-io-supply", 0);
+ if (reg_node) {
+ drvdata->reg_io = devm_regulator_get(dev, "vdd-io");
+ if (IS_ERR(drvdata->reg_io))
+ return PTR_ERR(drvdata->reg_io);
+
+ prop = of_get_property(node, "qcom,vdd-io-voltage-level", &len);
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ dev_err(dev, "sdc io voltage levels not specified\n");
+ } else {
+ drvdata->reg_low_io = be32_to_cpup(&prop[0]);
+ drvdata->reg_high_io = be32_to_cpup(&prop[1]);
+ }
+
+ prop = of_get_property(node, "qcom,vdd-io-current-level", &len);
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ dev_err(dev, "sdc io current levels not specified\n");
+ } else {
+ drvdata->reg_lpm_io = be32_to_cpup(&prop[0]);
+ drvdata->reg_hpm_io = be32_to_cpup(&prop[1]);
+ }
+ of_node_put(reg_node);
+ } else {
+ dev_err(dev,
+ "sdc io voltage supply not specified or available\n");
+ }
+
drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
drvdata->set = TPIU_SET_B;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index dcaa4e1..cdf711c 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -805,6 +805,8 @@
int i;
unsigned int ttbr0, tlbiall, tlbstatus, tlbsync, mmu_ctrl;
+ cmds += adreno_add_idle_cmds(adreno_dev, cmds);
+
for (i = 0; i < num_iommu_units; i++) {
ttbr0_val = kgsl_mmu_get_default_ttbr0(&device->mmu,
i, KGSL_IOMMU_CONTEXT_USER);
@@ -892,8 +894,14 @@
KGSL_IOMMU_CTX_TLBSTATUS) >> 2;
cmds += adreno_wait_reg_eq(cmds, tlbstatus, 0,
KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF);
+ /* release all commands with wait_for_me */
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
+ *cmds++ = 0;
}
}
+
+ cmds += adreno_add_idle_cmds(adreno_dev, cmds);
+
return cmds - cmds_orig;
}
@@ -3107,6 +3115,7 @@
adreno_dev->fast_hang_detect = 1;
kgsl_pwrscale_enable(device);
} else {
+ kgsl_pwrctrl_wake(device);
device->pwrctrl.ctrl_flags = KGSL_PWR_ON;
adreno_dev->fast_hang_detect = 0;
kgsl_pwrscale_disable(device);
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9a070a6..6507852 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -658,9 +658,7 @@
*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
*cmds++ = 0;
- if ((adreno_dev->gpurev == ADRENO_REV_A305) ||
- (adreno_dev->gpurev == ADRENO_REV_A305C) ||
- (adreno_dev->gpurev == ADRENO_REV_A320)) {
+ if (adreno_is_a3xx(adreno_dev)) {
*cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
*cmds++ = 0;
}
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2781a34..7da0811 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -911,11 +911,7 @@
mutex_lock(&private->process_private_mutex);
- /*
- * If debug root initialized then it means the rest of the fields
- * are also initialized
- */
- if (private->debug_root)
+ if (test_bit(KGSL_PROCESS_INIT, &private->priv))
goto done;
private->mem_rb = RB_ROOT;
@@ -936,6 +932,8 @@
if (kgsl_process_init_debugfs(private))
goto error;
+ set_bit(KGSL_PROCESS_INIT, &private->priv);
+
done:
mutex_unlock(&private->process_private_mutex);
return private;
diff --git a/drivers/gpu/msm/kgsl_debugfs.h b/drivers/gpu/msm/kgsl_debugfs.h
index b2f137c..fe9bc76 100644
--- a/drivers/gpu/msm/kgsl_debugfs.h
+++ b/drivers/gpu/msm/kgsl_debugfs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2008-2011,2013, 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
@@ -35,7 +35,7 @@
static inline void kgsl_device_debugfs_init(struct kgsl_device *device) { }
static inline void kgsl_core_debugfs_close(void) { }
static inline struct dentry *kgsl_get_debugfs_dir(void) { return NULL; }
-static inline int kgsl_process_init_debugfs(struct kgsl_process_private *)
+static inline int kgsl_process_init_debugfs(struct kgsl_process_private *priv)
{
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 09a31c9..0b5fe52 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -315,8 +315,23 @@
unsigned int pagefault_ts;
};
+/**
+ * struct kgsl_process_private - Private structure for a KGSL process (across
+ * all devices)
+ * @priv: Internal flags, use KGSL_PROCESS_* values
+ * @pid: ID for the task owner of the process
+ * @mem_lock: Spinlock to protect the process memory lists
+ * @refcount: kref object for reference counting the process
+ * @process_private_mutex: Mutex to synchronize access to the process struct
+ * @mem_rb: RB tree node for the memory owned by this process
+ * @idr: Iterator for assigning IDs to memory allocations
+ * @pagetable: Pointer to the pagetable owned by this process
+ * @kobj: Pointer to a kobj for the sysfs directory for this process
+ * @debug_root: Pointer to the debugfs root for this process
+ * @stats: Memory allocation statistics for this process
+ */
struct kgsl_process_private {
- unsigned int refcnt;
+ unsigned long priv;
pid_t pid;
spinlock_t mem_lock;
@@ -338,6 +353,14 @@
} stats[KGSL_MEM_ENTRY_MAX];
};
+/**
+ * enum kgsl_process_priv_flags - Private flags for kgsl_process_private
+ * @KGSL_PROCESS_INIT: Set if the process structure has been set up
+ */
+enum kgsl_process_priv_flags {
+ KGSL_PROCESS_INIT = 0,
+};
+
struct kgsl_device_private {
struct kgsl_device *device;
struct kgsl_process_private *process_priv;
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index 8fc1753..7f8a6b1 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -159,11 +159,13 @@
(priv->bin.total_time < FLOOR))
return;
- /* If there is an extended block of busy processing,
- * increase frequency. Otherwise run the normal algorithm.
+ /* If there is an extended block of busy processing, set
+ * frequency to turbo. Otherwise run the normal algorithm.
*/
if (priv->bin.busy_time > CEILING) {
- val = -1;
+ val = 0;
+ kgsl_pwrctrl_pwrlevel_change(device,
+ KGSL_PWRLEVEL_TURBO);
} else if (priv->idle_dcvs) {
idle = priv->bin.total_time - priv->bin.busy_time;
idle = (idle > 0) ? idle : 0;
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 2d70faa..adaff41 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -1249,8 +1249,7 @@
GFP_KERNEL);
if (!adc_qpnp) {
dev_err(&spmi->dev, "Unable to allocate memory\n");
- rc = -ENOMEM;
- goto fail;
+ return -ENOMEM;
}
iadc->dev = &(spmi->dev);
@@ -1259,7 +1258,7 @@
rc = qpnp_adc_get_devicetree_data(spmi, iadc->adc);
if (rc) {
dev_err(&spmi->dev, "failed to read device tree\n");
- goto fail;
+ return rc;
}
iadc->vadc_dev = qpnp_get_vadc(&spmi->dev, "iadc");
@@ -1267,7 +1266,7 @@
rc = PTR_ERR(iadc->vadc_dev);
if (rc != -EPROBE_DEFER)
pr_err("vadc property missing, rc=%d\n", rc);
- goto fail;
+ return rc;
}
mutex_init(&iadc->adc->adc_lock);
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index e37f75a..b2b846a 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -1365,21 +1365,6 @@
}
mutex_init(&vadc->adc->adc_lock);
- vadc->vadc_poll_eoc = of_property_read_bool(node,
- "qcom,vadc-poll-eoc");
- if (!vadc->vadc_poll_eoc) {
- rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
- qpnp_vadc_isr, IRQF_TRIGGER_RISING,
- "qpnp_vadc_interrupt", vadc);
- if (rc) {
- dev_err(&spmi->dev,
- "failed to request adc irq with error %d\n", rc);
- return rc;
- } else {
- enable_irq_wake(vadc->adc->adc_irq_eoc);
- }
- }
-
rc = qpnp_vadc_init_hwmon(vadc, spmi);
if (rc) {
dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
@@ -1416,11 +1401,24 @@
}
INIT_WORK(&vadc->trigger_completion_work, qpnp_vadc_work);
- if (vadc->vadc_poll_eoc)
+
+ vadc->vadc_poll_eoc = of_property_read_bool(node,
+ "qcom,vadc-poll-eoc");
+ if (!vadc->vadc_poll_eoc) {
+ rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
+ qpnp_vadc_isr, IRQF_TRIGGER_RISING,
+ "qpnp_vadc_interrupt", vadc);
+ if (rc) {
+ dev_err(&spmi->dev,
+ "failed to request adc irq with error %d\n", rc);
+ goto err_setup;
+ } else {
+ enable_irq_wake(vadc->adc->adc_irq_eoc);
+ }
+ } else
device_init_wakeup(vadc->dev, 1);
vadc->vadc_iadc_sync_lock = false;
-
dev_set_drvdata(&spmi->dev, vadc);
list_add(&vadc->list, &qpnp_vadc_device_list);
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index 8775ab9..f49ff14 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -43,7 +43,7 @@
#define POLL_INTERVAL 100 /* msecs */
/* if sensor is standby ,set POLL_STOP_TIME to slow down the poll */
-#define POLL_STOP_TIME 200
+#define POLL_STOP_TIME 10000
#define INPUT_FUZZ 32
#define INPUT_FLAT 32
#define INPUT_DATA_DIVIDER 16
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 1537866..642975d 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -734,7 +734,6 @@
idev->name = "MPU3050";
idev->id.bustype = BUS_I2C;
- idev->dev.parent = &client->dev;
idev->open = mpu3050_input_open;
idev->close = mpu3050_input_close;
diff --git a/drivers/input/misc/stk3x1x.c b/drivers/input/misc/stk3x1x.c
index 61f3530..937bf6c 100644
--- a/drivers/input/misc/stk3x1x.c
+++ b/drivers/input/misc/stk3x1x.c
@@ -170,7 +170,7 @@
#define MIN_ALS_POLL_DELAY_NS 110000000
#define DEVICE_NAME "stk_ps"
-#define ALS_NAME "lightsensor-level"
+#define ALS_NAME "stk3x1x-ls"
#define PS_NAME "proximity"
/* POWER SUPPLY VOLTAGE RANGE */
@@ -179,6 +179,15 @@
#define STK3X1X_VIO_MIN_UV 1750000
#define STK3X1X_VIO_MAX_UV 1950000
+#define STK_FIR_LEN 16
+#define MAX_FIR_LEN 32
+struct data_filter {
+ u16 raw[MAX_FIR_LEN];
+ int sum;
+ int number;
+ int idx;
+};
+
struct stk3x1x_data {
struct i2c_client *client;
#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
@@ -218,6 +227,9 @@
struct regulator *vdd;
struct regulator *vio;
bool power_enabled;
+ bool use_fir;
+ struct data_filter fir;
+ atomic_t firlength;
};
#if( !defined(CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD))
@@ -387,6 +399,13 @@
printk(KERN_ERR "%s: write i2c error\n", __func__);
return ret;
}
+
+ ret = i2c_smbus_write_byte_data(ps_data->client, 0x87, 0x60);
+ if (ret < 0) {
+ dev_err(&ps_data->client->dev,
+ "%s: write i2c error\n", __func__);
+ return ret;
+ }
return 0;
}
@@ -708,9 +727,32 @@
return ret;
}
+static inline int32_t stk3x1x_filter_reading(struct stk3x1x_data *ps_data,
+ int32_t word_data)
+{
+ int index;
+ int firlen = atomic_read(&ps_data->firlength);
+
+ if (ps_data->fir.number < firlen) {
+ ps_data->fir.raw[ps_data->fir.number] = word_data;
+ ps_data->fir.sum += word_data;
+ ps_data->fir.number++;
+ ps_data->fir.idx++;
+ } else {
+ index = ps_data->fir.idx % firlen;
+ ps_data->fir.sum -= ps_data->fir.raw[index];
+ ps_data->fir.raw[index] = word_data;
+ ps_data->fir.sum += word_data;
+ ps_data->fir.idx++;
+ word_data = ps_data->fir.sum/firlen;
+ }
+ return word_data;
+}
+
static inline int32_t stk3x1x_get_als_reading(struct stk3x1x_data *ps_data)
{
int32_t word_data, tmp_word_data;
+
tmp_word_data = i2c_smbus_read_word_data(ps_data->client, STK_DATA1_ALS_REG);
if(tmp_word_data < 0)
{
@@ -718,6 +760,9 @@
return tmp_word_data;
}
word_data = ((tmp_word_data & 0xFF00) >> 8) | ((tmp_word_data & 0x00FF) << 8) ;
+ if (ps_data->use_fir)
+ word_data = stk3x1x_filter_reading(ps_data, word_data);
+
return word_data;
}
@@ -912,7 +957,12 @@
return scnprintf(buf, PAGE_SIZE, "%lld\n", ktime_to_ns(ps_data->als_poll_delay));
}
-
+static inline void stk_als_delay_store_fir(struct stk3x1x_data *ps_data)
+{
+ ps_data->fir.number = 0;
+ ps_data->fir.idx = 0;
+ ps_data->fir.sum = 0;
+}
static ssize_t stk_als_delay_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
uint64_t value = 0;
@@ -936,6 +986,10 @@
mutex_lock(&ps_data->io_lock);
if(value != ktime_to_ns(ps_data->als_poll_delay))
ps_data->als_poll_delay = ns_to_ktime(value);
+
+ if (ps_data->use_fir)
+ stk_als_delay_store_fir(ps_data);
+
mutex_unlock(&ps_data->io_lock);
return size;
}
@@ -948,6 +1002,77 @@
return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
}
+static ssize_t stk_als_firlen_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stk3x1x_data *ps_data = dev_get_drvdata(dev);
+ int len = atomic_read(&ps_data->firlength);
+
+ dev_dbg(dev, "%s: len = %2d, idx = %2d\n",
+ __func__, len, ps_data->fir.idx);
+ dev_dbg(dev, "%s: sum = %5d, ave = %5d\n",
+ __func__, ps_data->fir.sum, ps_data->fir.sum/len);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", len);
+}
+
+static ssize_t stk_als_firlen_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ uint64_t value = 0;
+ int ret;
+ struct stk3x1x_data *ps_data = dev_get_drvdata(dev);
+ ret = kstrtoull(buf, 10, &value);
+ if (ret < 0) {
+ dev_err(dev, "%s:strict_strtoull failed, ret=0x%x\n",
+ __func__, ret);
+ return ret;
+ }
+
+ if (value > MAX_FIR_LEN) {
+ dev_err(dev, "%s: firlen exceed maximum filter length\n",
+ __func__);
+ } else if (value < 1) {
+ atomic_set(&ps_data->firlength, 1);
+ memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
+ } else {
+ atomic_set(&ps_data->firlength, value);
+ memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
+ }
+ return size;
+}
+
+static ssize_t stk_als_fir_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stk3x1x_data *ps_data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", ps_data->use_fir);
+}
+
+static ssize_t stk_als_fir_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ uint64_t value = 0;
+ int ret;
+ struct stk3x1x_data *ps_data = dev_get_drvdata(dev);
+ ret = kstrtoull(buf, 10, &value);
+ if (ret < 0) {
+ dev_err(dev, "%s:strict_strtoull failed, ret=0x%x\n",
+ __func__, ret);
+ return ret;
+ }
+
+ if (value) {
+ ps_data->use_fir = true;
+ memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
+ } else {
+ ps_data->use_fir = false;
+ }
+ return size;
+}
static ssize_t stk_ps_code_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct stk3x1x_data *ps_data = dev_get_drvdata(dev);
@@ -1432,6 +1557,11 @@
static struct device_attribute als_poll_delay_attribute =
__ATTR(poll_delay, 0664, stk_als_delay_show, stk_als_delay_store);
static struct device_attribute als_ir_code_attribute = __ATTR(ircode,0444,stk_als_ir_code_show,NULL);
+static struct device_attribute als_firlen_attribute =
+ __ATTR(firlen, 0664, stk_als_firlen_show, stk_als_firlen_store);
+static struct device_attribute als_fir_enable_attribute =
+ __ATTR(fir_enable, 0664, stk_als_fir_enable_show,
+ stk_als_fir_enable_store);
static struct attribute *stk_als_attrs [] =
{
@@ -1441,6 +1571,8 @@
&als_transmittance_attribute.attr,
&als_poll_delay_attribute.attr,
&als_ir_code_attribute.attr,
+ &als_firlen_attribute.attr,
+ &als_fir_enable_attribute.attr,
NULL
};
@@ -1673,6 +1805,13 @@
return IRQ_HANDLED;
}
#endif /* #if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS)) */
+
+static inline void stk3x1x_init_fir(struct stk3x1x_data *ps_data)
+{
+ memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
+ atomic_set(&ps_data->firlength, STK_FIR_LEN);
+}
+
static int32_t stk3x1x_init_all_setting(struct i2c_client *client, struct stk3x1x_platform_data *plat_data)
{
int32_t ret;
@@ -1697,6 +1836,10 @@
#ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
stk_init_code_threshold_table(ps_data);
#endif
+
+ if (plat_data->use_fir)
+ stk3x1x_init_fir(ps_data);
+
return 0;
}
@@ -1993,6 +2136,8 @@
return rc;
}
+ pdata->use_fir = of_property_read_bool(np, "stk,use-fir");
+
return 0;
}
#else
@@ -2059,6 +2204,7 @@
}
ps_data->als_transmittance = plat_data->transmittance;
ps_data->int_pin = plat_data->int_pin;
+ ps_data->use_fir = plat_data->use_fir;
if (ps_data->als_transmittance == 0) {
dev_err(&client->dev,
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 9f326f1..0a92d51 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -32,7 +32,6 @@
#define SHOW_PROGRESS
#define MAX_FIRMWARE_ID_LEN 10
#define FORCE_UPDATE false
-#define DO_LOCKDOWN false
#define INSIDE_FIRMWARE_UPDATE
#define FW_IMAGE_OFFSET 0x100
@@ -1115,7 +1114,11 @@
if (retval < 0)
return retval;
- if (f01_device_status.flash_prog) {
+ if (force) {
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Force to enter flash prog mode\n",
+ __func__);
+ } else if (f01_device_status.flash_prog) {
dev_info(&fwu->rmi4_data->i2c_client->dev,
"%s: Already in flash prog mode\n",
__func__);
@@ -1475,6 +1478,9 @@
"%s: Erase all command written\n",
__func__);
+ if (fwu->polling_mode)
+ msleep(100);
+
retval = fwu_wait_for_idle(ERASE_WAIT_MS);
if (retval < 0)
return retval;
@@ -1757,7 +1763,7 @@
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
- fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->do_lockdown = rmi4_data->board->do_lockdown;
return retval;
}
@@ -1800,7 +1806,7 @@
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
- fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->do_lockdown = rmi4_data->board->do_lockdown;
return retval;
}
@@ -1835,7 +1841,7 @@
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
- fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->do_lockdown = rmi4_data->board->do_lockdown;
return retval;
}
@@ -2166,7 +2172,7 @@
fwu->initialized = true;
fwu->force_update = FORCE_UPDATE;
- fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->do_lockdown = rmi4_data->board->do_lockdown;
fwu->initialized = true;
fwu->polling_mode = false;
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index f8ab5f4..cf1c717 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -96,6 +96,8 @@
#define F12_FINGERS_TO_SUPPORT 10
#define MAX_F11_TOUCH_WIDTH 15
+#define RMI4_COORDS_ARR_SIZE 4
+
static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
unsigned short addr, unsigned char *data,
unsigned short length);
@@ -820,6 +822,32 @@
return retval;
}
+/**
+ * synaptics_rmi4_release_all()
+ *
+ * Called by synaptics_rmi4_suspend()
+ *
+ * Release all touch data during the touch device switch to suspend state.
+ */
+
+static void synaptics_rmi4_release_all(struct synaptics_rmi4_data *rmi4_data)
+{
+ int finger;
+ int max_num_fingers = rmi4_data->num_of_fingers;
+
+ for (finger = 0; finger < max_num_fingers; finger++) {
+ input_mt_slot(rmi4_data->input_dev, finger);
+ input_mt_report_slot_state(rmi4_data->input_dev,
+ MT_TOOL_FINGER, 0);
+ }
+
+ input_report_key(rmi4_data->input_dev, BTN_TOUCH, 0);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 0);
+
+ input_sync(rmi4_data->input_dev);
+}
+
/**
* synaptics_rmi4_f11_abs_report()
*
@@ -1027,9 +1055,9 @@
wy = finger_data->wy;
#endif
- if (rmi4_data->board->x_flip)
+ if (rmi4_data->flip_x)
x = rmi4_data->sensor_max_x - x;
- if (rmi4_data->board->y_flip)
+ if (rmi4_data->flip_y)
y = rmi4_data->sensor_max_y - y;
dev_dbg(&rmi4_data->i2c_client->dev,
@@ -1306,6 +1334,50 @@
}
#ifdef CONFIG_OF
+static int synaptics_rmi4_get_dt_coords(struct device *dev, char *name,
+ struct synaptics_rmi4_platform_data *pdata)
+{
+ u32 coords[RMI4_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != RMI4_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (strcmp(name, "synaptics,panel-coords") == 0) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (strcmp(name, "synaptics,display-coords") == 0) {
+ pdata->disp_minx = coords[0];
+ pdata->disp_miny = coords[1];
+ pdata->disp_maxx = coords[2];
+ pdata->disp_maxy = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int synaptics_rmi4_parse_dt(struct device *dev,
struct synaptics_rmi4_platform_data *rmi4_pdata)
{
@@ -1323,21 +1395,26 @@
"synaptics,disable-gpios");
rmi4_pdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
rmi4_pdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
+ rmi4_pdata->do_lockdown = of_property_read_bool(np,
+ "synaptics,do-lockdown");
- rc = of_property_read_u32(np, "synaptics,panel-x", &temp_val);
- if (rc && (rc != -EINVAL)) {
- dev_err(dev, "Unable to read panel X dimension\n");
+ rc = synaptics_rmi4_get_dt_coords(dev, "synaptics,display-coords",
+ rmi4_pdata);
+ if (rc && (rc != -EINVAL))
return rc;
- } else {
- rmi4_pdata->panel_x = temp_val;
- }
- rc = of_property_read_u32(np, "synaptics,panel-y", &temp_val);
- if (rc && (rc != -EINVAL)) {
- dev_err(dev, "Unable to read panel Y dimension\n");
+ rc = synaptics_rmi4_get_dt_coords(dev, "synaptics,panel-coords",
+ rmi4_pdata);
+ if (rc && (rc != -EINVAL))
return rc;
- } else {
- rmi4_pdata->panel_y = temp_val;
+
+ rmi4_pdata->reset_delay = RESET_DELAY;
+ rc = of_property_read_u32(np, "synaptics,reset-delay", &temp_val);
+ if (!rc)
+ rmi4_pdata->reset_delay = temp_val;
+ else if (rc != -EINVAL) {
+ dev_err(dev, "Unable to read reset delay\n");
+ return rc;
}
rc = of_property_read_string(np, "synaptics,fw-image-name",
@@ -1793,11 +1870,10 @@
const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board;
if (!pdata->capacitance_button_map) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: capacitance_button_map is" \
- "NULL in board file\n",
+ dev_info(&rmi4_data->i2c_client->dev,
+ "%s: capacitance_button_map not in use\n",
__func__);
- return -ENODEV;
+ return 0;
} else if (!pdata->capacitance_button_map->map) {
dev_err(&rmi4_data->i2c_client->dev,
"%s: Button map is missing in board file\n",
@@ -2232,7 +2308,7 @@
return retval;
}
- msleep(RESET_DELAY);
+ msleep(rmi4_data->board->reset_delay);
return retval;
};
@@ -2577,7 +2653,7 @@
gpio_set_value(rmi4_data->board->reset_gpio, 0);
usleep(RMI4_GPIO_SLEEP_LOW_US);
gpio_set_value(rmi4_data->board->reset_gpio, 1);
- msleep(RESET_DELAY);
+ msleep(rmi4_data->board->reset_delay);
} else
synaptics_rmi4_reset_command(rmi4_data);
@@ -2750,12 +2826,32 @@
goto err_free_gpios;
}
+ if (rmi4_data->board->disp_maxx)
+ rmi4_data->disp_maxx = rmi4_data->board->disp_maxx;
+ else
+ rmi4_data->disp_maxx = rmi4_data->sensor_max_x;
+
+ if (rmi4_data->board->disp_maxy)
+ rmi4_data->disp_maxy = rmi4_data->board->disp_maxy;
+ else
+ rmi4_data->disp_maxy = rmi4_data->sensor_max_y;
+
+ if (rmi4_data->board->disp_minx)
+ rmi4_data->disp_minx = rmi4_data->board->disp_minx;
+ else
+ rmi4_data->disp_minx = 0;
+
+ if (rmi4_data->board->disp_miny)
+ rmi4_data->disp_miny = rmi4_data->board->disp_miny;
+ else
+ rmi4_data->disp_miny = 0;
+
input_set_abs_params(rmi4_data->input_dev,
- ABS_MT_POSITION_X, 0,
- rmi4_data->sensor_max_x, 0, 0);
+ ABS_MT_POSITION_X, rmi4_data->disp_minx,
+ rmi4_data->disp_maxx, 0, 0);
input_set_abs_params(rmi4_data->input_dev,
- ABS_MT_POSITION_Y, 0,
- rmi4_data->sensor_max_y, 0, 0);
+ ABS_MT_POSITION_Y, rmi4_data->disp_miny,
+ rmi4_data->disp_maxy, 0, 0);
input_set_abs_params(rmi4_data->input_dev,
ABS_PRESSURE, 0, 255, 0, 0);
#ifdef REPORT_2D_W
@@ -3299,6 +3395,8 @@
synaptics_rmi4_sensor_sleep(rmi4_data);
}
+ synaptics_rmi4_release_all(rmi4_data);
+
retval = synaptics_rmi4_regulator_lpm(rmi4_data, true);
if (retval < 0) {
dev_err(dev, "failed to enter low power mode\n");
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index 677a2fe..ef39bb7 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -186,6 +186,10 @@
* @irq: attention interrupt
* @sensor_max_x: sensor maximum x value
* @sensor_max_y: sensor maximum y value
+ * @disp_maxx: max x value of display
+ * @disp_maxy: max y value of display
+ * @disp_minx: min x value of display
+ * @disp_miny: min y value of display
* @irq_enabled: flag for indicating interrupt enable status
* @touch_stopped: flag to stop interrupt thread processing
* @fingers_on_2d: flag to indicate presence of fingers in 2d area
@@ -230,6 +234,10 @@
int irq;
int sensor_max_x;
int sensor_max_y;
+ int disp_maxx;
+ int disp_maxy;
+ int disp_minx;
+ int disp_miny;
bool irq_enabled;
bool touch_stopped;
bool fingers_on_2d;
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 5a405be..ecab061 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -59,7 +59,7 @@
#define WLED_CTL_DLY_MAX 1400
#define WLED_MAX_CURR 25
#define WLED_MSB_MASK 0x0F
-#define WLED_MAX_CURR_MASK 0x19
+#define WLED_MAX_CURR_MASK 0x1F
#define WLED_OP_FDBCK_MASK 0x07
#define WLED_OP_FDBCK_BIT_SHFT 0x00
#define WLED_OP_FDBCK_DEFAULT 0x00
@@ -173,7 +173,8 @@
#define LED_MPP_EN_CTRL(base) (base + 0x46)
#define LED_MPP_SINK_CTRL(base) (base + 0x4C)
-#define LED_MPP_CURRENT_DEFAULT 5
+#define LED_MPP_CURRENT_MIN 5
+#define LED_MPP_CURRENT_MAX 40
#define LED_MPP_VIN_CTRL_DEFAULT 0
#define LED_MPP_CURRENT_PER_SETTING 5
#define LED_MPP_SOURCE_SEL_DEFAULT LED_MPP_MODE_ENABLE
@@ -625,6 +626,21 @@
if (led->mpp_cfg->pwm_mode != MANUAL_MODE)
pwm_enable(led->mpp_cfg->pwm_cfg->pwm_dev);
+ else {
+ if (led->cdev.brightness < LED_MPP_CURRENT_MIN)
+ led->cdev.brightness = LED_MPP_CURRENT_MIN;
+
+ val = (led->cdev.brightness / LED_MPP_CURRENT_MIN) - 1;
+
+ rc = qpnp_led_masked_write(led,
+ LED_MPP_SINK_CTRL(led->base),
+ LED_MPP_SINK_MASK, val);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write sink control reg\n");
+ return rc;
+ }
+ }
val = (led->mpp_cfg->source_sel & LED_MPP_SRC_MASK) |
(led->mpp_cfg->mode_ctrl & LED_MPP_MODE_CTRL_MASK);
@@ -1351,7 +1367,10 @@
led->cdev.max_brightness = RGB_MAX_LEVEL;
break;
case QPNP_ID_LED_MPP:
- led->cdev.max_brightness = MPP_MAX_LEVEL;
+ if (led->mpp_cfg->pwm_mode == MANUAL_MODE)
+ led->cdev.max_brightness = led->max_current;
+ else
+ led->cdev.max_brightness = MPP_MAX_LEVEL;
break;
case QPNP_ID_KPDBL:
led->cdev.max_brightness = KPDBL_MAX_LEVEL;
@@ -2332,6 +2351,14 @@
{
int rc, val;
+
+ if (led->max_current < LED_MPP_CURRENT_MIN ||
+ led->max_current > LED_MPP_CURRENT_MAX) {
+ dev_err(&led->spmi_dev->dev,
+ "max current for mpp is not valid\n");
+ return -EINVAL;
+ }
+
val = (led->mpp_cfg->current_setting / LED_MPP_CURRENT_PER_SETTING) - 1;
if (val < 0)
@@ -2349,7 +2376,7 @@
LED_MPP_SINK_MASK, val);
if (rc) {
dev_err(&led->spmi_dev->dev,
- "Failed to write led enable reg\n");
+ "Failed to write sink control reg\n");
return rc;
}
@@ -2954,11 +2981,16 @@
return -ENOMEM;
}
- led->mpp_cfg->current_setting = LED_MPP_CURRENT_DEFAULT;
+ led->mpp_cfg->current_setting = LED_MPP_CURRENT_MIN;
rc = of_property_read_u32(node, "qcom,current-setting", &val);
- if (!rc)
- led->mpp_cfg->current_setting = (u8) val;
- else if (rc != -EINVAL)
+ if (!rc) {
+ if (led->mpp_cfg->current_setting < LED_MPP_CURRENT_MIN)
+ led->mpp_cfg->current_setting = LED_MPP_CURRENT_MIN;
+ else if (led->mpp_cfg->current_setting > LED_MPP_CURRENT_MAX)
+ led->mpp_cfg->current_setting = LED_MPP_CURRENT_MAX;
+ else
+ led->mpp_cfg->current_setting = (u8) val;
+ } else if (rc != -EINVAL)
return rc;
led->mpp_cfg->source_sel = LED_MPP_SOURCE_SEL_DEFAULT;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index c188105..32d74ba 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -816,6 +816,7 @@
cci_client = msm_actuator_t->i2c_client.cci_client;
cci_client->cci_subdev = msm_cci_get_subdev();
+ cci_client->cci_i2c_master = MASTER_MAX;
v4l2_subdev_init(&msm_actuator_t->msm_sd.sd,
msm_actuator_t->act_v4l2_subdev_ops);
v4l2_set_subdevdata(&msm_actuator_t->msm_sd.sd, msm_actuator_t);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
index 591c464..059633b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
@@ -15,7 +15,7 @@
#define CCI_HW_VERSION_ADDR 0x00000000
#define CCI_RESET_CMD_ADDR 0x00000004
-#define CCI_RESET_CMD_RMSK 0xcf73f3f7
+#define CCI_RESET_CMD_RMSK 0x0f73f3f7
#define CCI_M0_RESET_RMSK 0x3F1
#define CCI_M1_RESET_RMSK 0x3F001
#define CCI_QUEUE_START_ADDR 0x00000008
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 17c5a14..d11798e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -628,21 +628,46 @@
{"cci_clk", -1},
};
-static int32_t msm_cci_init(struct v4l2_subdev *sd)
+static int32_t msm_cci_init(struct v4l2_subdev *sd,
+ struct msm_camera_cci_ctrl *c_ctrl)
{
int rc = 0;
struct cci_device *cci_dev;
+ enum cci_i2c_master_t master;
cci_dev = v4l2_get_subdevdata(sd);
- CDBG("%s line %d\n", __func__, __LINE__);
- if (!cci_dev) {
- pr_err("%s cci device NULL\n", __func__);
+ if (!cci_dev || !c_ctrl) {
+ pr_err("%s:%d failed: invalid params %p %p\n", __func__,
+ __LINE__, cci_dev, c_ctrl);
rc = -ENOMEM;
return rc;
}
if (cci_dev->ref_count++) {
CDBG("%s ref_count %d\n", __func__, cci_dev->ref_count);
+ master = c_ctrl->cci_info->cci_i2c_master;
+ CDBG("%s:%d master %d\n", __func__, __LINE__, master);
+ if (master < MASTER_MAX) {
+ mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ /* Set reset pending flag to TRUE */
+ cci_dev->cci_master_info[master].reset_pending = TRUE;
+ /* Set proper mask to RESET CMD address */
+ if (master == MASTER_0)
+ msm_camera_io_w(CCI_M0_RESET_RMSK,
+ cci_dev->base + CCI_RESET_CMD_ADDR);
+ else
+ msm_camera_io_w(CCI_M1_RESET_RMSK,
+ cci_dev->base + CCI_RESET_CMD_ADDR);
+ /* wait for reset done irq */
+ rc = wait_for_completion_interruptible_timeout(
+ &cci_dev->cci_master_info[master].
+ reset_complete,
+ CCI_TIMEOUT);
+ if (rc <= 0)
+ pr_err("%s:%d wait failed %d\n", __func__,
+ __LINE__, rc);
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ }
return 0;
}
@@ -685,6 +710,7 @@
cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
msm_camera_io_w(0x1, cci_dev->base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);
cci_dev->cci_state = CCI_STATE_ENABLED;
+
return 0;
reset_complete_failed:
@@ -695,6 +721,7 @@
msm_camera_request_gpio_table(cci_dev->cci_gpio_tbl,
cci_dev->cci_gpio_tbl_size, 0);
request_gpio_failed:
+ cci_dev->ref_count--;
return rc;
}
@@ -710,7 +737,7 @@
}
if (--cci_dev->ref_count) {
- CDBG("%s ref_count %d\n", __func__, cci_dev->ref_count);
+ CDBG("%s ref_count Exit %d\n", __func__, cci_dev->ref_count);
return 0;
}
@@ -723,6 +750,7 @@
cci_dev->cci_gpio_tbl_size, 0);
cci_dev->cci_state = CCI_STATE_DISABLED;
+
return 0;
}
@@ -734,7 +762,7 @@
cci_ctrl->cmd);
switch (cci_ctrl->cmd) {
case MSM_CCI_INIT:
- rc = msm_cci_init(sd);
+ rc = msm_cci_init(sd, cci_ctrl);
break;
case MSM_CCI_RELEASE:
rc = msm_cci_release(sd);
@@ -837,10 +865,7 @@
rc = msm_cci_config(sd, arg);
break;
case MSM_SD_SHUTDOWN: {
- struct msm_camera_cci_ctrl ctrl_cmd;
- ctrl_cmd.cmd = MSM_CCI_RELEASE;
- rc = msm_cci_config(sd, &ctrl_cmd);
- break;
+ return rc;
}
default:
rc = -ENOIOCTLCMD;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index 1407f12..7f13568 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -229,6 +229,88 @@
return rc;
}
+static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+ int rc = 0, i = 0;
+ struct msm_eeprom_board_info *eb_info;
+ struct msm_camera_power_ctrl_t *power_info =
+ &e_ctrl->eboard_info->power_info;
+ struct device_node *of_node = NULL;
+ struct msm_camera_gpio_conf *gconf = NULL;
+ uint16_t gpio_array_size = 0;
+ uint16_t *gpio_array = NULL;
+
+ eb_info = e_ctrl->eboard_info;
+ if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
+ of_node = e_ctrl->i2c_client.
+ spi_client->spi_master->dev.of_node;
+ else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+ of_node = e_ctrl->pdev->dev.of_node;
+ else if (e_ctrl->eeprom_device_type == MSM_CAMERA_I2C_DEVICE)
+ of_node = e_ctrl->i2c_client.client->dev.of_node;
+
+ rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
+ &power_info->num_vreg);
+ if (rc < 0)
+ return rc;
+
+ rc = msm_camera_get_dt_power_setting_data(of_node,
+ power_info->cam_vreg, power_info->num_vreg,
+ &power_info->power_setting, &power_info->power_setting_size);
+ if (rc < 0)
+ goto error1;
+
+ power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
+ GFP_KERNEL);
+ if (!power_info->gpio_conf) {
+ rc = -ENOMEM;
+ goto error2;
+ }
+ gconf = power_info->gpio_conf;
+ gpio_array_size = of_gpio_count(of_node);
+ CDBG("%s gpio count %d\n", __func__, gpio_array_size);
+
+ if (gpio_array_size) {
+ gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
+ GFP_KERNEL);
+ if (!gpio_array) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto error3;
+ }
+ for (i = 0; i < gpio_array_size; i++) {
+ gpio_array[i] = of_get_gpio(of_node, i);
+ CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+ gpio_array[i]);
+ }
+
+ rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto error4;
+ }
+
+ rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto error4;
+ }
+ kfree(gpio_array);
+ }
+
+ return rc;
+error4:
+ kfree(gpio_array);
+error3:
+ kfree(power_info->gpio_conf);
+error2:
+ kfree(power_info->cam_vreg);
+error1:
+ kfree(power_info->power_setting);
+ return rc;
+}
+
static int msm_eeprom_alloc_memory_map(struct msm_eeprom_ctrl_t *e_ctrl,
struct device_node *of)
{
@@ -320,10 +402,19 @@
int32_t msm_eeprom_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) {
int rc = 0;
+ int32_t j = 0;
+ uint32_t temp = 0;
struct msm_eeprom_ctrl_t *e_ctrl = NULL;
struct msm_camera_power_ctrl_t *power_info = NULL;
+ struct device_node *of_node = client->dev.of_node;
CDBG("%s E\n", __func__);
+
+ if (!of_node) {
+ pr_err("%s of_node NULL\n", __func__);
+ return -EINVAL;
+ }
+
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
pr_err("%s i2c_check_functionality failed\n", __func__);
goto probe_failure;
@@ -337,13 +428,23 @@
e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
CDBG("%s client = %x\n", __func__, (unsigned int)client);
- e_ctrl->eboard_info = (struct msm_eeprom_board_info *)(id->driver_data);
+ e_ctrl->eboard_info = kzalloc(sizeof(
+ struct msm_eeprom_board_info), GFP_KERNEL);
if (!e_ctrl->eboard_info) {
pr_err("%s:%d board info NULL\n", __func__, __LINE__);
return -EINVAL;
}
+
+ rc = of_property_read_u32(of_node, "qcom,slave-addr", &temp);
+ if (rc < 0) {
+ pr_err("%s failed rc %d\n", __func__, rc);
+ return rc;
+ }
+
power_info = &e_ctrl->eboard_info->power_info;
+ e_ctrl->eboard_info->i2c_slaveaddr = temp;
e_ctrl->i2c_client.client = client;
+ e_ctrl->is_supported = 0;
/* Set device type as I2C */
e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE;
@@ -356,6 +457,45 @@
power_info->clk_info_size = ARRAY_SIZE(cam_8960_clk_info);
power_info->dev = &client->dev;
+ rc = of_property_read_string(of_node, "qcom,eeprom-name",
+ &e_ctrl->eboard_info->eeprom_name);
+ CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__,
+ e_ctrl->eboard_info->eeprom_name, rc);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto board_free;
+ }
+
+ rc = msm_eeprom_get_dt_data(e_ctrl);
+ if (rc)
+ goto board_free;
+
+ rc = msm_eeprom_alloc_memory_map(e_ctrl, of_node);
+ if (rc)
+ goto board_free;
+
+ rc = msm_camera_power_up(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+ if (rc) {
+ pr_err("%s failed power up %d\n", __func__, __LINE__);
+ goto memdata_free;
+ }
+ rc = read_eeprom_memory(e_ctrl);
+ if (rc < 0) {
+ pr_err("%s read_eeprom_memory failed\n", __func__);
+ goto power_down;
+ }
+
+ for (j = 0; j < e_ctrl->num_bytes; j++)
+ CDBG("memory_data[%d] = 0x%X\n", j, e_ctrl->memory_data[j]);
+
+ rc = msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+ if (rc) {
+ pr_err("failed rc %d\n", rc);
+ goto power_down;
+ }
+
/*IMPLEMENT READING PART*/
/* Initialize sub device */
v4l2_i2c_subdev_init(&e_ctrl->msm_sd.sd,
@@ -368,9 +508,18 @@
e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM;
msm_sd_register(&e_ctrl->msm_sd);
+ e_ctrl->is_supported = 1;
CDBG("%s success result=%d X\n", __func__, rc);
return rc;
+power_down:
+ msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+memdata_free:
+ kfree(e_ctrl->memory_data);
+ kfree(e_ctrl->eboard_info->eeprom_map);
+board_free:
+ kfree(e_ctrl->eboard_info);
probe_failure:
pr_err("%s failed! rc = %d\n", __func__, rc);
return rc;
@@ -454,86 +603,6 @@
return 0;
}
-static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
-{
- int rc = 0, i = 0;
- struct msm_eeprom_board_info *eb_info;
- struct msm_camera_power_ctrl_t *power_info =
- &e_ctrl->eboard_info->power_info;
- struct device_node *of_node = NULL;
- struct msm_camera_gpio_conf *gconf = NULL;
- uint16_t gpio_array_size = 0;
- uint16_t *gpio_array = NULL;
-
- eb_info = e_ctrl->eboard_info;
- if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
- of_node = e_ctrl->i2c_client.
- spi_client->spi_master->dev.of_node;
- else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
- of_node = e_ctrl->pdev->dev.of_node;
-
- rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
- &power_info->num_vreg);
- if (rc < 0)
- return rc;
-
- rc = msm_camera_get_dt_power_setting_data(of_node,
- power_info->cam_vreg, power_info->num_vreg,
- &power_info->power_setting, &power_info->power_setting_size);
- if (rc < 0)
- goto ERROR1;
-
- power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
- GFP_KERNEL);
- if (!power_info->gpio_conf) {
- rc = -ENOMEM;
- goto ERROR2;
- }
- gconf = power_info->gpio_conf;
- gpio_array_size = of_gpio_count(of_node);
- CDBG("%s gpio count %d\n", __func__, gpio_array_size);
-
- if (gpio_array_size) {
- gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
- GFP_KERNEL);
- if (!gpio_array) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR3;
- }
- for (i = 0; i < gpio_array_size; i++) {
- gpio_array[i] = of_get_gpio(of_node, i);
- CDBG("%s gpio_array[%d] = %d\n", __func__, i,
- gpio_array[i]);
- }
-
- rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
- gpio_array, gpio_array_size);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR4;
- }
-
- rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
- gpio_array, gpio_array_size);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR4;
- }
- kfree(gpio_array);
- }
-
- return rc;
-ERROR4:
- kfree(gpio_array);
-ERROR3:
- kfree(power_info->gpio_conf);
-ERROR2:
- kfree(power_info->cam_vreg);
-ERROR1:
- kfree(power_info->power_setting);
- return rc;
-}
-
static int msm_eeprom_spi_setup(struct spi_device *spi)
{
struct msm_eeprom_ctrl_t *e_ctrl = NULL;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile b/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
index 62102cb..9fc3817 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_MSMB_CAMERA) += msm_led_trigger.o
obj-$(CONFIG_MSMB_CAMERA) += msm_led_i2c_trigger.o
obj-$(CONFIG_MSMB_CAMERA) += adp1660.o
+obj-$(CONFIG_MSMB_CAMERA) += msm_led_torch.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_i2c_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_i2c_trigger.c
index b5afa86..9caa270 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_i2c_trigger.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_i2c_trigger.c
@@ -19,6 +19,7 @@
#include "msm_camera_io_util.h"
#include "../msm_sensor.h"
#include "msm_led_flash.h"
+#include <linux/debugfs.h>
#define FLASH_NAME "camera-led-flash"
@@ -485,12 +486,44 @@
msm_camera_qup_i2c_write_table_w_microdelay,
};
+#ifdef CONFIG_DEBUG_FS
+static int set_led_status(void *data, u64 val)
+{
+ struct msm_led_flash_ctrl_t *fctrl =
+ (struct msm_led_flash_ctrl_t *)data;
+ int rc = -1;
+ pr_debug("set_led_status: Enter val: %llu", val);
+ if (!fctrl) {
+ pr_err("set_led_status: fctrl is NULL");
+ return rc;
+ }
+ if (!fctrl->func_tbl) {
+ pr_err("set_led_status: fctrl->func_tbl is NULL");
+ return rc;
+ }
+ if (val == 0) {
+ pr_debug("set_led_status: val is disable");
+ rc = msm_flash_led_off(fctrl);
+ } else {
+ pr_debug("set_led_status: val is enable");
+ rc = msm_flash_led_low(fctrl);
+ }
+
+ return rc;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(ledflashdbg_fops,
+ NULL, set_led_status, "%llu\n");
+#endif
+
int msm_flash_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int rc = 0;
struct msm_led_flash_ctrl_t *fctrl = NULL;
-
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dentry;
+#endif
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
pr_err("i2c_check_functionality failed\n");
goto probe_failure;
@@ -529,6 +562,12 @@
&msm_sensor_qup_func_tbl;
rc = msm_led_i2c_flash_create_v4lsubdev(fctrl);
+#ifdef CONFIG_DEBUG_FS
+ dentry = debugfs_create_file("ledflash", S_IRUGO, NULL, (void *)fctrl,
+ &ledflashdbg_fops);
+ if (!dentry)
+ pr_err("Failed to create the debugfs ledflash file");
+#endif
CDBG("%s:%d probe success\n", __func__, __LINE__);
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_torch.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_torch.c
new file mode 100644
index 0000000..ff63696
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_torch.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include "msm_led_flash.h"
+
+static struct led_trigger *torch_trigger;
+
+static void msm_led_torch_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (!torch_trigger) {
+ pr_err("No torch trigger found, can't set brightness\n");
+ return;
+ }
+
+ led_trigger_event(torch_trigger, value);
+};
+
+static struct led_classdev msm_torch_led = {
+ .name = "torch-light",
+ .brightness_set = msm_led_torch_brightness_set,
+ .brightness = LED_OFF,
+};
+
+int32_t msm_led_torch_create_classdev(struct platform_device *pdev,
+ void *data)
+{
+ int rc;
+ struct msm_led_flash_ctrl_t *fctrl =
+ (struct msm_led_flash_ctrl_t *)data;
+
+ if (!fctrl || !fctrl->torch_trigger) {
+ pr_err("Invalid fctrl or torch trigger\n");
+ return -EINVAL;
+ }
+
+ torch_trigger = fctrl->torch_trigger;
+ msm_led_torch_brightness_set(&msm_torch_led, LED_OFF);
+
+ rc = led_classdev_register(&pdev->dev, &msm_torch_led);
+ if (rc) {
+ pr_err("Failed to register led dev. rc = %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
index 1b0ec44..20905c9 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
@@ -26,6 +26,9 @@
#define CDBG(fmt, args...) do { } while (0)
#endif
+extern int32_t msm_led_torch_create_classdev(
+ struct platform_device *pdev, void *data);
+
static struct msm_led_flash_ctrl_t fctrl;
static int32_t msm_led_trigger_get_subdev_id(struct msm_led_flash_ctrl_t *fctrl,
@@ -209,7 +212,11 @@
of_node_put(flash_src_node);
}
}
+
rc = msm_led_flash_create_v4lsubdev(pdev, &fctrl);
+ if (!rc)
+ msm_led_torch_create_classdev(pdev, &fctrl);
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/imx135.c b/drivers/media/platform/msm/camera_v2/sensor/imx135.c
index 8368a4d..c26e4ff 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/imx135.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/imx135.c
@@ -68,7 +68,7 @@
{
.seq_type = SENSOR_CLK,
.seq_val = SENSOR_CAM_MCLK,
- .config_val = 0,
+ .config_val = 24000000,
.delay = 1,
},
{
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 0447159..0083378 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -957,7 +957,7 @@
};
static struct msm_cam_clk_info cam_8974_clk_info[] = {
- [SENSOR_CAM_MCLK] = {"cam_src_clk", 19200000},
+ [SENSOR_CAM_MCLK] = {"cam_src_clk", 24000000},
[SENSOR_CAM_CLK] = {"cam_clk", 0},
};
@@ -1272,9 +1272,10 @@
case VIDIOC_MSM_SENSOR_GET_AF_STATUS:
return msm_sensor_get_af_status(s_ctrl, argp);
case VIDIOC_MSM_SENSOR_RELEASE:
- case MSM_SD_SHUTDOWN:
msm_sensor_stop_stream(s_ctrl);
return 0;
+ case MSM_SD_SHUTDOWN:
+ return 0;
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 8350dde..2b6118a 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -78,7 +78,7 @@
return vidc_err;
}
-static int sanitize_session_pkt(struct list_head *sessions,
+static int validate_session_pkt(struct list_head *sessions,
struct hal_session *sess, struct mutex *session_lock)
{
struct hal_session *session;
@@ -184,8 +184,10 @@
}
static void hfi_process_event_notify(
msm_vidc_callback callback, u32 device_id,
- struct hfi_msg_event_notify_packet *pkt)
+ struct hfi_msg_event_notify_packet *pkt,
+ struct list_head *sessions, struct mutex *session_lock)
{
+ struct hal_session *sess = NULL;
dprintk(VIDC_DBG, "RECVD:EVENT_NOTIFY");
if (!callback || !pkt ||
@@ -193,6 +195,7 @@
dprintk(VIDC_ERR, "Invalid Params");
return;
}
+ sess = (struct hal_session *)pkt->session_id;
switch (pkt->event_id) {
case HFI_EVENT_SYS_ERROR:
@@ -202,11 +205,14 @@
break;
case HFI_EVENT_SESSION_ERROR:
dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR");
- hfi_process_session_error(callback, device_id, pkt);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_error(callback, device_id, pkt);
break;
case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED");
- hfi_process_sess_evt_seq_changed(callback, device_id, pkt);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_sess_evt_seq_changed(callback,
+ device_id, pkt);
break;
case HFI_EVENT_SESSION_PROPERTY_CHANGED:
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED");
@@ -1139,7 +1145,7 @@
struct list_head *sessions, struct mutex *session_lock)
{
u32 rc = 0;
- struct hal_session *sess;
+ struct hal_session *sess = NULL;
if (!callback || !msg_hdr || msg_hdr->size <
VIDC_IFACEQ_MIN_PKT_SIZE) {
dprintk(VIDC_ERR, "hal_process_msg_packet:bad"
@@ -1148,21 +1154,16 @@
return rc;
}
-#define SANITIZE_SESSION_PKT(msg_pkt) ({ \
- sess = (struct hal_session *) \
- (((struct vidc_hal_session_cmd_pkt *) \
- msg_pkt)->session_id); \
- if (sanitize_session_pkt(sessions, sess, session_lock)) \
- break; \
- })
-
dprintk(VIDC_INFO, "Received: 0x%x in ", msg_hdr->packet);
rc = (u32) msg_hdr->packet;
+ sess = (struct hal_session *)((struct
+ vidc_hal_session_cmd_pkt*) msg_hdr)->session_id;
+
switch (msg_hdr->packet) {
case HFI_MSG_EVENT_NOTIFY:
- SANITIZE_SESSION_PKT(msg_hdr);
hfi_process_event_notify(callback, device_id,
- (struct hfi_msg_event_notify_packet *) msg_hdr);
+ (struct hfi_msg_event_notify_packet *) msg_hdr,
+ sessions, session_lock);
break;
case HFI_MSG_SYS_INIT_DONE:
hfi_process_sys_init_done(callback, device_id,
@@ -1170,12 +1171,13 @@
msg_hdr);
break;
case HFI_MSG_SYS_IDLE:
+ case HFI_MSG_SYS_PC_PREP_DONE:
break;
case HFI_MSG_SYS_SESSION_INIT_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_init_done(callback, device_id,
- (struct hfi_msg_sys_session_init_done_packet *)
- msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_init_done(callback, device_id,
+ (struct hfi_msg_sys_session_init_done_packet *)
+ msg_hdr);
break;
case HFI_MSG_SYS_PROPERTY_INFO:
hfi_process_sys_property_info(
@@ -1183,85 +1185,85 @@
msg_hdr);
break;
case HFI_MSG_SYS_SESSION_END_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_end_done(callback, device_id,
- (struct hfi_msg_sys_session_end_done_packet *)
- msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_end_done(callback, device_id,
+ (struct hfi_msg_sys_session_end_done_packet *)
+ msg_hdr);
break;
case HFI_MSG_SESSION_LOAD_RESOURCES_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_load_res_done(callback, device_id,
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_load_res_done(callback, device_id,
(struct hfi_msg_session_load_resources_done_packet *)
- msg_hdr);
+ msg_hdr);
break;
case HFI_MSG_SESSION_START_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_start_done(callback, device_id,
- (struct hfi_msg_session_start_done_packet *)
- msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_start_done(callback, device_id,
+ (struct hfi_msg_session_start_done_packet *)
+ msg_hdr);
break;
case HFI_MSG_SESSION_STOP_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_stop_done(callback, device_id,
- (struct hfi_msg_session_stop_done_packet *)
- msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_stop_done(callback, device_id,
+ (struct hfi_msg_session_stop_done_packet *)
+ msg_hdr);
break;
case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_etb_done(callback, device_id,
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_etb_done(callback, device_id,
(struct hfi_msg_session_empty_buffer_done_packet *)
- msg_hdr);
+ msg_hdr);
break;
case HFI_MSG_SESSION_FILL_BUFFER_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_ftb_done(callback, device_id, msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_ftb_done(callback, device_id,
+ msg_hdr);
break;
case HFI_MSG_SESSION_FLUSH_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_flush_done(callback, device_id,
- (struct hfi_msg_session_flush_done_packet *)
- msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_flush_done(callback, device_id,
+ (struct hfi_msg_session_flush_done_packet *)
+ msg_hdr);
break;
case HFI_MSG_SESSION_PROPERTY_INFO:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_prop_info(callback, device_id,
- (struct hfi_msg_session_property_info_packet *)
- msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_prop_info(callback, device_id,
+ (struct hfi_msg_session_property_info_packet *)
+ msg_hdr);
break;
case HFI_MSG_SESSION_RELEASE_RESOURCES_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_rel_res_done(callback, device_id,
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_rel_res_done(callback, device_id,
(struct hfi_msg_session_release_resources_done_packet *)
- msg_hdr);
+ msg_hdr);
break;
case HFI_MSG_SYS_RELEASE_RESOURCE:
hfi_process_sys_rel_resource_done(callback, device_id,
(struct hfi_msg_sys_release_resource_done_packet *)
- msg_hdr);
+ msg_hdr);
break;
case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_get_seq_hdr_done(
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_get_seq_hdr_done(
callback, device_id, (struct
hfi_msg_session_get_sequence_header_done_packet*)
- msg_hdr);
+ msg_hdr);
break;
case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_rel_buf_done(
- callback, device_id, (struct
- hfi_msg_session_release_buffers_done_packet*)
- msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_rel_buf_done(callback, device_id,
+ (struct hfi_msg_session_release_buffers_done_packet *)
+ msg_hdr);
break;
case HFI_MSG_SYS_SESSION_ABORT_DONE:
- SANITIZE_SESSION_PKT(msg_hdr);
- hfi_process_session_abort_done(callback, device_id, (struct
- hfi_msg_sys_session_abort_done_packet*) msg_hdr);
+ if (!validate_session_pkt(sessions, sess, session_lock))
+ hfi_process_session_abort_done(callback, device_id,
+ (struct hfi_msg_sys_session_abort_done_packet *)
+ msg_hdr);
break;
default:
dprintk(VIDC_DBG, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
break;
}
-#undef SANITIZE_SESSION_PKT
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 50149dc..afd7200 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -36,6 +36,8 @@
struct msm_vidc_drv *vidc_driver;
+uint32_t msm_vidc_pwr_collapse_delay = 2000;
+
struct buffer_info {
struct list_head list;
int type;
@@ -512,6 +514,19 @@
b->m.planes[i].m.userptr = binfo->device_addr[i];
dprintk(VIDC_DBG, "Queueing device address = 0x%x\n",
binfo->device_addr[i]);
+
+ if ((vidc_inst->fmts[OUTPUT_PORT]->fourcc ==
+ V4L2_PIX_FMT_HEVC_HYBRID) && binfo->handle[i] &&
+ (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
+ rc = msm_smem_cache_operations(v4l2_inst->mem_client,
+ binfo->handle[i], SMEM_CACHE_INVALIDATE);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to INV caches: %d\n", rc);
+ goto err_invalid_buff;
+ }
+ }
+
if (binfo->handle[i] &&
(b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
rc = msm_smem_cache_operations(v4l2_inst->mem_client,
@@ -781,6 +796,31 @@
static DEVICE_ATTR(link_name, 0644, msm_vidc_link_name_show, NULL);
+static ssize_t store_pwr_collapse_delay(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long val = 0;
+ int rc = 0;
+ rc = kstrtoul(buf, 0, &val);
+ if (rc)
+ return rc;
+ else if (val == 0)
+ return -EINVAL;
+ msm_vidc_pwr_collapse_delay = val;
+ return count;
+}
+
+static ssize_t show_pwr_collapse_delay(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", msm_vidc_pwr_collapse_delay);
+}
+
+static DEVICE_ATTR(pwr_collapse_delay, 0644, show_pwr_collapse_delay,
+ store_pwr_collapse_delay);
+
static int __devinit msm_vidc_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -800,6 +840,12 @@
dprintk(VIDC_ERR, "Failed to init core\n");
goto err_v4l2_register;
}
+ rc = device_create_file(&pdev->dev, &dev_attr_pwr_collapse_delay);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to create pwr_collapse_delay sysfs node");
+ goto err_v4l2_register;
+ }
if (core->hfi_type == VIDC_HFI_Q6) {
dprintk(VIDC_ERR, "Q6 hfi device probe called\n");
nr += MSM_VIDC_MAX_DEVICES;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 73ff9fa..a3d88c5 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -363,6 +363,14 @@
.type = OUTPUT_PORT,
},
{
+ .name = "HEVC_HYBRID",
+ .description = "HEVC compressed format",
+ .fourcc = V4L2_PIX_FMT_HEVC_HYBRID,
+ .num_planes = 1,
+ .get_frame_size = get_frame_size_compressed,
+ .type = OUTPUT_PORT,
+ },
+ {
.name = "VP8",
.description = "VP8 compressed format",
.fourcc = V4L2_PIX_FMT_VP8,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 9d3afa1..fdc851c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -22,8 +22,6 @@
#include "msm_smem.h"
#include "msm_vidc_debug.h"
-#define HW_RESPONSE_TIMEOUT 1000
-
#define IS_ALREADY_IN_STATE(__p, __d) ({\
int __rc = (__p >= __d);\
__rc; \
@@ -362,7 +360,7 @@
int rc = 0;
rc = wait_for_completion_timeout(
&inst->completions[SESSION_MSG_INDEX(cmd)],
- msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+ msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
if (!rc) {
dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
msm_comm_recover_from_session_error(inst);
@@ -1128,7 +1126,7 @@
}
rc = wait_for_completion_timeout(
&core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)],
- msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+ msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
if (!rc) {
dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
rc = -EIO;
@@ -1150,7 +1148,7 @@
dprintk(VIDC_DBG, "Waiting for SYS_INIT_DONE\n");
rc = wait_for_completion_timeout(
&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)],
- msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+ msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
if (!rc) {
dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
rc = -EIO;
@@ -1339,7 +1337,9 @@
case V4L2_PIX_FMT_HEVC:
codec = HAL_VIDEO_CODEC_HEVC;
break;
-
+ case V4L2_PIX_FMT_HEVC_HYBRID:
+ codec = HAL_VIDEO_CODEC_HEVC_HYBRID;
+ break;
default:
dprintk(VIDC_ERR, "Wrong codec: %d\n", fourcc);
codec = HAL_UNUSED_CODEC;
@@ -2116,7 +2116,7 @@
}
rc = wait_for_completion_timeout(
&inst->completions[SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)],
- msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+ msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
if (!rc) {
dprintk(VIDC_ERR,
"Wait interrupted or timeout: %d\n", rc);
@@ -2703,7 +2703,7 @@
}
rc = wait_for_completion_timeout(
&inst->completions[SESSION_MSG_INDEX(SESSION_ABORT_DONE)],
- msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+ msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
if (!rc) {
dprintk(VIDC_ERR, "%s: Wait interrupted or timeout: %d\n",
__func__, rc);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index bea9070..03136ae 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -21,6 +21,7 @@
int msm_fw_debug_mode = 0x1;
int msm_fw_low_power_mode = 0x1;
int msm_vp8_low_tier = 0x1;
+int msm_vidc_hw_rsp_timeout = 1000;
struct debug_buffer {
char ptr[MAX_DBG_BUF_SIZE];
@@ -177,6 +178,11 @@
dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
goto failed_create_dir;
}
+ if (!debugfs_create_u32("hw_rsp_timeout", S_IRUGO | S_IWUSR,
+ parent, &msm_vidc_hw_rsp_timeout)) {
+ dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+ goto failed_create_dir;
+ }
failed_create_dir:
return dir;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index 5b572c9..c9ecc6f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
@@ -53,6 +53,7 @@
extern int msm_fw_debug_mode;
extern int msm_fw_low_power_mode;
extern int msm_vp8_low_tier;
+extern int msm_vidc_hw_rsp_timeout;
#define dprintk(__level, __fmt, arg...) \
do { \
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 8176ea5..e75b410 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -87,5 +87,7 @@
return 0;
}
+extern uint32_t msm_vidc_pwr_collapse_delay;
+
#endif
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 99c51bf..aaf1f50 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -62,6 +62,18 @@
int ret;
};
+#define TZBSP_VIDEO_SET_STATE 0xa
+
+enum tzbsp_video_state {
+ TZBSP_VIDEO_STATE_SUSPEND = 0,
+ TZBSP_VIDEO_STATE_RESUME
+};
+
+struct tzbsp_video_set_state_req {
+ u32 state; /*shoud be tzbsp_video_state enum value*/
+ u32 spare; /*reserved for future, should be zero*/
+};
+
static void venus_hfi_dump_packet(u8 *packet)
{
u32 c = 0, packet_size = *(u32 *)packet;
@@ -492,38 +504,320 @@
rmb();
return rc;
}
-static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
+
+static int venus_hfi_core_start_cpu(struct venus_hfi_device *device)
{
+ u32 ctrl_status = 0, count = 0, rc = 0;
+ int max_tries = 100;
+ venus_hfi_write_register(device,
+ VIDC_WRAPPER_INTR_MASK, 0x8, 0);
+ venus_hfi_write_register(device,
+ VIDC_CPU_CS_SCIACMDARG3, 1, 0);
+
+ while (!ctrl_status && count < max_tries) {
+ ctrl_status = venus_hfi_read_register(
+ device,
+ VIDC_CPU_CS_SCIACMDARG0);
+ if ((ctrl_status & 0xFE) == 0x4) {
+ dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
+ break;
+ }
+ usleep_range(500, 1000);
+ count++;
+ }
+ if (count >= max_tries)
+ rc = -ETIME;
+ return rc;
+}
+
+static int venus_hfi_iommu_attach(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ struct iommu_domain *domain;
int i;
- struct venus_core_clock *cl;
- if (!device) {
- dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ struct iommu_set *iommu_group_set;
+ struct iommu_group *group;
+ struct iommu_info *iommu_map;
+
+ if (!device || !device->res)
+ return -EINVAL;
+
+ iommu_group_set = &device->res->iommu_group_set;
+ for (i = 0; i < iommu_group_set->count; i++) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ group = iommu_map->group;
+ domain = msm_get_iommu_domain(iommu_map->domain);
+ if (IS_ERR_OR_NULL(domain)) {
+ dprintk(VIDC_ERR,
+ "Failed to get domain: %s\n", iommu_map->name);
+ rc = PTR_ERR(domain);
+ break;
+ }
+ rc = iommu_attach_group(domain, group);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "IOMMU attach failed: %s\n", iommu_map->name);
+ break;
+ }
+ }
+ if (i < iommu_group_set->count) {
+ i--;
+ for (; i >= 0; i--) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ group = iommu_map->group;
+ domain = msm_get_iommu_domain(iommu_map->domain);
+ if (group && domain)
+ iommu_detach_group(domain, group);
+ }
+ }
+ return rc;
+}
+
+static void venus_hfi_iommu_detach(struct venus_hfi_device *device)
+{
+ struct iommu_group *group;
+ struct iommu_domain *domain;
+ struct iommu_set *iommu_group_set;
+ struct iommu_info *iommu_map;
+ int i;
+
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
return;
}
- if (!device->clocks_enabled) {
- dprintk(VIDC_DBG, "Clocks are already disabled");
- goto already_disabled;
+
+ iommu_group_set = &device->res->iommu_group_set;
+ for (i = 0; i < iommu_group_set->count; i++) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ group = iommu_map->group;
+ domain = msm_get_iommu_domain(iommu_map->domain);
+ if (group && domain)
+ iommu_detach_group(domain, group);
}
- for (i = 0; i <= device->clk_gating_level; i++) {
- cl = &device->resources.clock[i];
- clk_disable(cl->clk);
- }
-already_disabled:
- device->clocks_enabled = 0;
}
-static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device)
+
+static int venus_hfi_unvote_bus(void *dev,
+ enum session_type type, enum mem_type mtype)
+{
+ int rc = 0;
+ u32 handle = 0;
+ struct venus_hfi_device *device = dev;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "%s invalid device handle %p",
+ __func__, device);
+ return -EINVAL;
+ }
+
+ if (mtype & DDR_MEM)
+ handle = device->resources.bus_info.ddr_handle[type];
+ if (mtype & OCMEM_MEM)
+ handle = device->resources.bus_info.ocmem_handle[type];
+
+ if (handle) {
+ rc = msm_bus_scale_client_update_request(
+ handle, 0);
+ if (rc)
+ dprintk(VIDC_ERR, "Failed to unvote bus: %d\n", rc);
+ } else {
+ dprintk(VIDC_ERR, "Failed to unvote bus, mtype: %d\n",
+ mtype);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+static void venus_hfi_unvote_buses(void *dev, enum mem_type mtype)
{
int i;
- struct venus_core_clock *cl;
+ struct venus_hfi_device *device = dev;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+ return;
+ }
+
+ for (i = 0; i < MSM_VIDC_MAX_DEVICES; i++) {
+ if ((mtype & DDR_MEM) &&
+ venus_hfi_unvote_bus(device, i, DDR_MEM))
+ dprintk(VIDC_WARN,
+ "Failed to unvote for DDR accesses\n");
+
+ if ((mtype & OCMEM_MEM) &&
+ venus_hfi_unvote_bus(device, i, OCMEM_MEM))
+ dprintk(VIDC_WARN,
+ "Failed to unvote for OCMEM accesses\n");
+ }
+}
+
+static const u32 venus_hfi_bus_table[] = {
+ 36000,
+ 110400,
+ 244800,
+ 489000,
+ 783360,
+ 979200,
+};
+
+static int venus_hfi_get_bus_vector(struct venus_hfi_device *device, int load,
+ enum session_type type, enum mem_type mtype)
+{
+ int num_rows = sizeof(venus_hfi_bus_table)/(sizeof(u32));
+ int i, j;
+ int idx = 0;
+
+ if (!device || (mtype != DDR_MEM && mtype != OCMEM_MEM) ||
+ (type != MSM_VIDC_ENCODER && type != MSM_VIDC_DECODER)) {
+ dprintk(VIDC_ERR, "%s invalid params", __func__);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_rows; i++) {
+ if (load <= venus_hfi_bus_table[i])
+ break;
+ }
+
+ if (type == MSM_VIDC_ENCODER)
+ idx = (mtype == DDR_MEM) ? BUS_IDX_ENC_DDR : BUS_IDX_ENC_OCMEM;
+ else
+ idx = (mtype == DDR_MEM) ? BUS_IDX_DEC_DDR : BUS_IDX_DEC_OCMEM;
+
+ j = clamp(i, 0, num_rows-1) + 1;
+
+ /* Ensure bus index remains within the supported range,
+ * as specified in the device dtsi file */
+ j = clamp(j, 0, device->res->bus_pdata[idx].num_usecases - 1);
+
+ dprintk(VIDC_DBG, "Required bus = %d\n", j);
+ return j;
+}
+
+static int venus_hfi_scale_bus(void *dev, int load,
+ enum session_type type, enum mem_type mtype)
+{
int rc = 0;
+ u32 handle = 0;
+ struct venus_hfi_device *device = dev;
+ int bus_vector = 0;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "%s invalid device handle %p",
+ __func__, device);
+ return -EINVAL;
+ }
+
+ if (mtype & DDR_MEM)
+ handle = device->resources.bus_info.ddr_handle[type];
+ if (mtype & OCMEM_MEM)
+ handle = device->resources.bus_info.ocmem_handle[type];
+
+ if (handle) {
+ bus_vector = venus_hfi_get_bus_vector(device, load,
+ type, mtype);
+ if (bus_vector < 0) {
+ dprintk(VIDC_ERR, "Failed to get bus vector\n");
+ return -EINVAL;
+ }
+ device->bus_load[type] = load;
+ rc = msm_bus_scale_client_update_request(handle, bus_vector);
+ if (rc)
+ dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
+ } else {
+ dprintk(VIDC_ERR, "Failed to scale bus, mtype: %d\n",
+ mtype);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static int venus_hfi_scale_buses(void *dev, enum mem_type mtype)
+{
+ int i, rc = 0;
+ struct venus_hfi_device *device = dev;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+ return -EINVAL;
+ }
+ for (i = 0; i < MSM_VIDC_MAX_DEVICES; i++) {
+ if (mtype & DDR_MEM) {
+ rc = venus_hfi_scale_bus(device, device->bus_load[i],
+ i, DDR_MEM);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to scale bus for DDR accesses, session type %d, load %u\n",
+ i, device->bus_load[i]);
+ goto err_scale_bus;
+ }
+ }
+
+ if (mtype & OCMEM_MEM) {
+ rc = venus_hfi_scale_bus(device, device->bus_load[i],
+ i, OCMEM_MEM);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to scale bus for OCMEM accesses, session type %d, load %u\n",
+ i, device->bus_load[i]);
+ goto err_scale_bus;
+ }
+ }
+ }
+err_scale_bus:
+ return rc;
+}
+
+static inline int venus_hfi_tzbsp_set_video_state(enum tzbsp_video_state state)
+{
+ struct tzbsp_video_set_state_req cmd = {0};
+ int tzbsp_rsp = 0;
+ int rc = 0;
+ cmd.state = state;
+ cmd.spare = 0;
+ rc = scm_call(SCM_SVC_BOOT, TZBSP_VIDEO_SET_STATE, &cmd, sizeof(cmd),
+ &tzbsp_rsp, sizeof(tzbsp_rsp));
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed scm_call %d\n", rc);
+ return rc;
+ }
+ dprintk(VIDC_DBG, "Set state %d, resp %d\n", state, tzbsp_rsp);
+ if (tzbsp_rsp) {
+ dprintk(VIDC_ERR,
+ "Failed to set video core state to suspend: %d\n",
+ tzbsp_rsp);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static inline int venus_hfi_reset_core(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ venus_hfi_write_register(device,
+ VIDC_CTRL_INIT, 0x1, 0);
+ rc = venus_hfi_core_start_cpu(device);
+ if (rc)
+ dprintk(VIDC_ERR, "Failed to start core");
+ return rc;
+}
+
+
+/*Calling function is responsible to acquire device->clk_pwr_lock*/
+static inline int venus_hfi_clk_enable(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ int i;
+ struct venus_core_clock *cl;
+
if (!device) {
dprintk(VIDC_ERR, "Invalid params: %p\n", device);
return -EINVAL;
}
if (device->clocks_enabled) {
- dprintk(VIDC_DBG, "Clocks are already enabled");
- goto already_enabled;
+ dprintk(VIDC_DBG, "Clocks already enabled");
+ return 0;
}
+
for (i = 0; i <= device->clk_gating_level; i++) {
cl = &device->resources.clock[i];
rc = clk_enable(cl->clk);
@@ -534,17 +828,180 @@
dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
}
}
-already_enabled:
device->clocks_enabled = 1;
- return rc;
+ return 0;
fail_clk_enable:
- for (; i >= 0; i--) {
+ for (i--; i >= 0; i--) {
cl = &device->resources.clock[i];
clk_disable(cl->clk);
}
return rc;
}
+/*Calling function is responsible to acquire device->clk_pwr_lock*/
+static inline void venus_hfi_clk_disable(struct venus_hfi_device *device)
+{
+ int i;
+ struct venus_core_clock *cl;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return;
+ }
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_DBG, "Clocks already disabled");
+ return;
+ }
+
+ for (i = 0; i <= device->clk_gating_level; i++) {
+ cl = &device->resources.clock[i];
+ clk_disable(cl->clk);
+ }
+ device->clocks_enabled = 0;
+}
+
+static DECLARE_COMPLETION(pc_prep_done);
+
+static inline int venus_hfi_power_off(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return -EINVAL;
+ }
+ if (!device->power_enabled) {
+ dprintk(VIDC_DBG, "Power already disabled");
+ goto already_disabled;
+ }
+
+ /*Temporarily enable clocks to make TZ call.*/
+ rc = venus_hfi_clk_enable(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to enable clocks before TZ call");
+ return rc;
+ }
+ rc = venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to suspend video core %d\n", rc);
+ venus_hfi_clk_disable(device);
+ return rc;
+ }
+ venus_hfi_clk_disable(device);
+ venus_hfi_iommu_detach(device);
+ rc = regulator_disable(device->gdsc);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to disable GDSC, %d", rc);
+ return rc;
+ }
+ if (device->res->has_ocmem)
+ venus_hfi_unvote_buses(device, DDR_MEM|OCMEM_MEM);
+ else
+ venus_hfi_unvote_buses(device, DDR_MEM);
+
+ device->power_enabled = 0;
+already_disabled:
+ return rc;
+}
+
+static inline int venus_hfi_power_on(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return -EINVAL;
+ }
+
+ if (device->res->has_ocmem)
+ rc = venus_hfi_scale_buses(device, DDR_MEM|OCMEM_MEM);
+ else
+ rc = venus_hfi_scale_buses(device, DDR_MEM);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to scale buses");
+ goto err_scale_buses;
+ }
+
+ rc = regulator_enable(device->gdsc);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to enable GDSC %d", rc);
+ goto err_enable_gdsc;
+ }
+
+ rc = venus_hfi_iommu_attach(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to attach iommu after power on");
+ goto err_iommu_attach;
+ }
+
+ rc = venus_hfi_clk_enable(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to enable clocks");
+ goto err_enable_clk;
+ }
+
+ rc = venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_RESUME);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to resume video core %d\n", rc);
+ goto err_set_video_state;
+ }
+ rc = venus_hfi_reset_core(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to reset venus core");
+ goto err_reset_core;
+ }
+ device->power_enabled = 1;
+ return rc;
+err_reset_core:
+ venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND);
+err_set_video_state:
+ venus_hfi_clk_disable(device);
+err_enable_clk:
+ venus_hfi_iommu_detach(device);
+err_iommu_attach:
+ regulator_disable(device->gdsc);
+err_enable_gdsc:
+ if (device->res->has_ocmem)
+ venus_hfi_unvote_buses(device, DDR_MEM|OCMEM_MEM);
+ else
+ venus_hfi_unvote_buses(device, DDR_MEM);
+err_scale_buses:
+ return rc;
+}
+
+static void venus_hfi_pm_hndlr(struct work_struct *work);
+static DECLARE_DELAYED_WORK(venus_hfi_pm_work, venus_hfi_pm_hndlr);
+
+static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return -EINVAL;
+ }
+ if (device->clocks_enabled) {
+ dprintk(VIDC_DBG, "Clocks are already enabled");
+ goto already_enabled;
+ }
+ cancel_delayed_work(&venus_hfi_pm_work);
+ if (!device->power_enabled) {
+ /*This will enable clocks as well*/
+ rc = venus_hfi_power_on(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed venus power on");
+ goto fail_clk_power_on;
+ }
+ } else {
+ rc = venus_hfi_clk_enable(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed venus clock enable");
+ goto fail_clk_power_on;
+ }
+ }
+already_enabled:
+ device->clocks_enabled = 1;
+fail_clk_power_on:
+ return rc;
+}
+
static unsigned long venus_hfi_get_clock_rate(struct venus_core_clock *clock,
int num_mbs_per_sec)
{
@@ -569,7 +1026,7 @@
dprintk(VIDC_ERR, "Invalid args: %p\n", device);
return -EINVAL;
}
- device->load = load;
+ device->clk_load = load;
rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
venus_hfi_get_clock_rate(&device->resources.clock[VCODEC_CLK],
load));
@@ -595,14 +1052,14 @@
dprintk(VIDC_ERR, "cannot write to shared Q's");
goto err_q_null;
}
- mutex_lock(&device->clock_lock);
+ mutex_lock(&device->clk_pwr_lock);
result = venus_hfi_clk_gating_off(device);
if (result) {
dprintk(VIDC_ERR, "%s : Clock enable failed\n",
__func__);
goto err_q_write;
}
- result = venus_hfi_scale_clocks(device, device->load);
+ result = venus_hfi_scale_clocks(device, device->clk_load);
if (result) {
dprintk(VIDC_ERR, "Clock scaling failed\n");
goto err_q_write;
@@ -618,7 +1075,7 @@
dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full");
}
err_q_write:
- mutex_unlock(&device->clock_lock);
+ mutex_unlock(&device->clk_pwr_lock);
err_q_null:
mutex_unlock(&device->write_lock);
return result;
@@ -642,7 +1099,7 @@
goto read_error_null;
}
q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
- mutex_lock(&device->clock_lock);
+ mutex_lock(&device->clk_pwr_lock);
rc = venus_hfi_clk_gating_off(device);
if (rc) {
dprintk(VIDC_ERR,
@@ -661,7 +1118,7 @@
rc = -ENODATA;
}
read_error:
- mutex_unlock(&device->clock_lock);
+ mutex_unlock(&device->clk_pwr_lock);
read_error_null:
mutex_unlock(&device->read_lock);
return rc;
@@ -684,7 +1141,7 @@
rc = -ENODATA;
goto dbg_error_null;
}
- mutex_lock(&device->clock_lock);
+ mutex_lock(&device->clk_pwr_lock);
rc = venus_hfi_clk_gating_off(device);
if (rc) {
dprintk(VIDC_ERR,
@@ -704,7 +1161,7 @@
rc = -ENODATA;
}
dbg_error:
- mutex_unlock(&device->clock_lock);
+ mutex_unlock(&device->clk_pwr_lock);
dbg_error_null:
mutex_unlock(&device->read_lock);
return rc;
@@ -954,31 +1411,6 @@
return -ENOMEM;
}
-static int venus_hfi_core_start_cpu(struct venus_hfi_device *device)
-{
- u32 ctrl_status = 0, count = 0, rc = 0;
- int max_tries = 100;
- venus_hfi_write_register(device,
- VIDC_WRAPPER_INTR_MASK, 0x8, 0);
- venus_hfi_write_register(device,
- VIDC_CPU_CS_SCIACMDARG3, 1, 0);
-
- while (!ctrl_status && count < max_tries) {
- ctrl_status = venus_hfi_read_register(
- device,
- VIDC_CPU_CS_SCIACMDARG0);
- if ((ctrl_status & 0xFE) == 0x4) {
- dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
- break;
- }
- usleep_range(500, 1000);
- count++;
- }
- if (count >= max_tries)
- rc = -ETIME;
- return rc;
-}
-
static void venus_hfi_set_registers(struct venus_hfi_device *device)
{
struct reg_set *reg_set;
@@ -1111,12 +1543,12 @@
return -ENODEV;
}
if (dev->hal_client) {
- mutex_lock(&dev->clock_lock);
+ mutex_lock(&dev->clk_pwr_lock);
rc = venus_hfi_clk_gating_off(device);
if (rc) {
dprintk(VIDC_ERR,
"%s : Clock enable failed\n", __func__);
- mutex_unlock(&dev->clock_lock);
+ mutex_unlock(&dev->clk_pwr_lock);
return -EIO;
}
venus_hfi_write_register(dev,
@@ -1124,38 +1556,12 @@
if (!(dev->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK))
disable_irq_nosync(dev->hal_data->irq);
dev->intr_status = 0;
- mutex_unlock(&dev->clock_lock);
+ mutex_unlock(&dev->clk_pwr_lock);
}
dprintk(VIDC_INFO, "HAL exited\n");
return 0;
}
-int venus_hfi_core_pc_prep(void *device)
-{
- struct hfi_cmd_sys_pc_prep_packet pkt;
- int rc = 0;
- struct venus_hfi_device *dev;
-
- if (device) {
- dev = device;
- } else {
- dprintk(VIDC_ERR, "invalid device");
- return -ENODEV;
- }
-
- rc = create_pkt_cmd_sys_pc_prep(&pkt);
- if (rc) {
- dprintk(VIDC_ERR, "Failed to create sys pc prep pkt");
- goto err_create_pkt;
- }
-
- if (venus_hfi_iface_cmdq_write(dev, &pkt))
- rc = -ENOTEMPTY;
-
-err_create_pkt:
- return rc;
-}
-
static void venus_hfi_core_clear_interrupt(struct venus_hfi_device *device)
{
u32 intr_status = 0;
@@ -1163,12 +1569,12 @@
if (!device->callback)
return;
- mutex_lock(&device->clock_lock);
+ mutex_lock(&device->clk_pwr_lock);
rc = venus_hfi_clk_gating_off(device);
if (rc) {
dprintk(VIDC_ERR,
"%s : Clock enable failed\n", __func__);
- mutex_unlock(&device->clock_lock);
+ mutex_unlock(&device->clk_pwr_lock);
return;
}
intr_status = venus_hfi_read_register(
@@ -1192,7 +1598,7 @@
VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
venus_hfi_write_register(device,
VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
- mutex_unlock(&device->clock_lock);
+ mutex_unlock(&device->clk_pwr_lock);
dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
}
@@ -1930,6 +2336,91 @@
return rc;
}
+static int venus_hfi_core_pc_prep(void *device)
+{
+ struct hfi_cmd_sys_pc_prep_packet pkt;
+ int rc = 0;
+ struct venus_hfi_device *dev;
+
+ if (device) {
+ dev = device;
+ } else {
+ dprintk(VIDC_ERR, "invalid device");
+ return -ENODEV;
+ }
+
+ rc = create_pkt_cmd_sys_pc_prep(&pkt);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to create sys pc prep pkt");
+ goto err_create_pkt;
+ }
+
+ if (venus_hfi_iface_cmdq_write(dev, &pkt))
+ rc = -ENOTEMPTY;
+
+err_create_pkt:
+ return rc;
+}
+
+
+static void venus_hfi_pm_hndlr(struct work_struct *work)
+{
+ int rc = 0;
+ struct venus_hfi_device *device = list_first_entry(
+ &hal_ctxt.dev_head, struct venus_hfi_device, list);
+ mutex_lock(&device->clk_pwr_lock);
+ if (device->clocks_enabled || !device->power_enabled) {
+ dprintk(VIDC_DBG,
+ "Clocks status: %d, Power status: %d, ignore power off\n",
+ device->clocks_enabled, device->power_enabled);
+ goto clks_enabled;
+ }
+ mutex_unlock(&device->clk_pwr_lock);
+ init_completion(&pc_prep_done);
+ rc = venus_hfi_core_pc_prep(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to prepare venus for power off");
+ return;
+ }
+ rc = wait_for_completion_timeout(&pc_prep_done,
+ msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
+ if (!rc) {
+ dprintk(VIDC_ERR, "Wait interrupted or timeout: %d", rc);
+ return;
+ }
+
+ mutex_lock(&device->clk_pwr_lock);
+ if (device->clocks_enabled) {
+ dprintk(VIDC_ERR,
+ "Clocks are still enabled after PC_PREP_DONE, ignore power off");
+ goto clks_enabled;
+ }
+
+ rc = venus_hfi_power_off(device);
+ if (rc)
+ dprintk(VIDC_ERR, "Failed venus power off");
+clks_enabled:
+ mutex_unlock(&device->clk_pwr_lock);
+}
+
+static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
+{
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return;
+ }
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_DBG, "Clocks are already disabled");
+ goto already_disabled;
+ }
+ venus_hfi_clk_disable(device);
+ if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work,
+ msecs_to_jiffies(msm_vidc_pwr_collapse_delay)))
+ dprintk(VIDC_DBG, "PM work already scheduled\n");
+already_disabled:
+ device->clocks_enabled = 0;
+}
+
static int venus_hfi_try_clk_gating(struct venus_hfi_device *device)
{
int rc = 0;
@@ -1939,15 +2430,21 @@
return -ENODEV;
}
mutex_lock(&device->write_lock);
- mutex_lock(&device->clock_lock);
+ mutex_lock(&device->clk_pwr_lock);
rc = venus_hfi_is_cmd_pending(device);
ctrl_status = venus_hfi_read_register(
device,
VIDC_CPU_CS_SCIACMDARG0);
+ dprintk(VIDC_DBG,
+ "venus_hfi_try_clk_gating - rc %d, ctrl_status 0x%x",
+ rc, ctrl_status);
if (((ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)
- != 0) && !rc)
+ || (ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY))
+ && !rc)
venus_hfi_clk_gating_on(device);
- mutex_unlock(&device->clock_lock);
+ else
+ dprintk(VIDC_DBG, "Ignore clock gating");
+ mutex_unlock(&device->clk_pwr_lock);
mutex_unlock(&device->write_lock);
return rc;
}
@@ -2006,6 +2503,14 @@
}
if (rc == HFI_MSG_SYS_IDLE)
rc = venus_hfi_try_clk_gating(device);
+ else if (rc == HFI_MSG_SYS_PC_PREP_DONE) {
+ dprintk(VIDC_DBG, "Received HFI_MSG_SYS_PC_PREP_DONE");
+ rc = venus_hfi_try_clk_gating(device);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "Failed clk gating after PC_PREP_DONE");
+ complete(&pc_prep_done);
+ }
} else {
dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
}
@@ -2380,118 +2885,6 @@
return -EINVAL;
}
-
-static const u32 venus_hfi_bus_table[] = {
- 36000,
- 110400,
- 244800,
- 489000,
- 783360,
- 979200,
-};
-
-static int venus_hfi_get_bus_vector(struct venus_hfi_device *device, int load,
- enum session_type type, enum mem_type mtype)
-{
- int num_rows = sizeof(venus_hfi_bus_table)/(sizeof(u32));
- int i, j;
- int idx = 0;
-
- if (!device || (mtype != DDR_MEM && mtype != OCMEM_MEM) ||
- (type != MSM_VIDC_ENCODER && type != MSM_VIDC_DECODER)) {
- dprintk(VIDC_ERR, "%s invalid params", __func__);
- return -EINVAL;
- }
-
- for (i = 0; i < num_rows; i++) {
- if (load <= venus_hfi_bus_table[i])
- break;
- }
-
- if (type == MSM_VIDC_ENCODER)
- idx = (mtype == DDR_MEM) ? BUS_IDX_ENC_DDR : BUS_IDX_ENC_OCMEM;
- else
- idx = (mtype == DDR_MEM) ? BUS_IDX_DEC_DDR : BUS_IDX_DEC_OCMEM;
-
- j = clamp(i, 0, num_rows-1) + 1;
-
- /* Ensure bus index remains within the supported range,
- * as specified in the device dtsi file */
- j = clamp(j, 0, device->res->bus_pdata[idx].num_usecases - 1);
-
- dprintk(VIDC_DBG, "Required bus = %d\n", j);
- return j;
-}
-
-static int venus_hfi_scale_bus(void *dev, int load,
- enum session_type type, enum mem_type mtype)
-{
- int rc = 0;
- u32 handle = 0;
- struct venus_hfi_device *device = dev;
- int bus_vector = 0;
-
- if (!device) {
- dprintk(VIDC_ERR, "%s invalid device handle %p",
- __func__, device);
- return -EINVAL;
- }
-
- if (mtype & DDR_MEM)
- handle = device->resources.bus_info.ddr_handle[type];
- if (mtype & OCMEM_MEM)
- handle = device->resources.bus_info.ocmem_handle[type];
-
- if (handle) {
- bus_vector = venus_hfi_get_bus_vector(device, load,
- type, mtype);
- if (bus_vector < 0) {
- dprintk(VIDC_ERR, "Failed to get bus vector\n");
- return -EINVAL;
- }
- rc = msm_bus_scale_client_update_request(handle, bus_vector);
- if (rc)
- dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
- } else {
- dprintk(VIDC_ERR, "Failed to scale bus, mtype: %d\n",
- mtype);
- rc = -EINVAL;
- }
-
- return rc;
-}
-
-static int venus_hfi_unvote_bus(void *dev,
- enum session_type type, enum mem_type mtype)
-{
- int rc = 0;
- u32 handle = 0;
- struct venus_hfi_device *device = dev;
-
- if (!device) {
- dprintk(VIDC_ERR, "%s invalid device handle %p",
- __func__, device);
- return -EINVAL;
- }
-
- if (mtype & DDR_MEM)
- handle = device->resources.bus_info.ddr_handle[type];
- if (mtype & OCMEM_MEM)
- handle = device->resources.bus_info.ocmem_handle[type];
-
- if (handle) {
- rc = msm_bus_scale_client_update_request(
- handle, 0);
- if (rc)
- dprintk(VIDC_ERR, "Failed to unvote bus: %d\n", rc);
- } else {
- dprintk(VIDC_ERR, "Failed to unvote bus, mtype: %d\n",
- mtype);
- rc = -EINVAL;
- }
- return rc;
-}
-
static int venus_hfi_set_ocmem(void *dev, struct ocmem_buf *ocmem)
{
struct vidc_resource_hdr rhdr;
@@ -2657,6 +3050,15 @@
int rc = 0;
device->res = res;
+ if (!res) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", res);
+ return -ENODEV;
+ }
+ device->gdsc = devm_regulator_get(&res->pdev->dev, "vdd");
+ if (IS_ERR(device->gdsc)) {
+ dprintk(VIDC_ERR, "Failed to get Venus GDSC\n");
+ return -ENODEV;
+ }
rc = venus_hfi_init_clocks(res, device);
if (rc) {
dprintk(VIDC_ERR, "Failed to init clocks\n");
@@ -2686,6 +3088,7 @@
err_init_bus:
venus_hfi_deinit_clocks(device);
err_init_clocks:
+ device->gdsc = NULL;
return rc;
}
@@ -2696,72 +3099,7 @@
venus_hfi_deregister_iommu_domains(device);
venus_hfi_deinit_bus(device);
venus_hfi_deinit_clocks(device);
-}
-
-static int venus_hfi_iommu_attach(struct venus_hfi_device *device)
-{
- int rc = 0;
- struct iommu_domain *domain;
- int i;
- struct iommu_set *iommu_group_set;
- struct iommu_group *group;
- struct iommu_info *iommu_map;
-
- if (!device || !device->res)
- return -EINVAL;
-
- iommu_group_set = &device->res->iommu_group_set;
- for (i = 0; i < iommu_group_set->count; i++) {
- iommu_map = &iommu_group_set->iommu_maps[i];
- group = iommu_map->group;
- domain = msm_get_iommu_domain(iommu_map->domain);
- if (IS_ERR_OR_NULL(domain)) {
- dprintk(VIDC_ERR,
- "Failed to get domain: %s\n", iommu_map->name);
- rc = PTR_ERR(domain);
- break;
- }
- rc = iommu_attach_group(domain, group);
- if (rc) {
- dprintk(VIDC_ERR,
- "IOMMU attach failed: %s\n", iommu_map->name);
- break;
- }
- }
- if (i < iommu_group_set->count) {
- i--;
- for (; i >= 0; i--) {
- iommu_map = &iommu_group_set->iommu_maps[i];
- group = iommu_map->group;
- domain = msm_get_iommu_domain(iommu_map->domain);
- if (group && domain)
- iommu_detach_group(domain, group);
- }
- }
- return rc;
-}
-
-static void venus_hfi_iommu_detach(struct venus_hfi_device *device)
-{
- struct iommu_group *group;
- struct iommu_domain *domain;
- struct iommu_set *iommu_group_set;
- struct iommu_info *iommu_map;
- int i;
-
- if (!device || !device->res) {
- dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
- return;
- }
-
- iommu_group_set = &device->res->iommu_group_set;
- for (i = 0; i < iommu_group_set->count; i++) {
- iommu_map = &iommu_group_set->iommu_maps[i];
- group = iommu_map->group;
- domain = msm_get_iommu_domain(iommu_map->domain);
- if (group && domain)
- iommu_detach_group(domain, group);
- }
+ device->gdsc = NULL;
}
static int venus_hfi_iommu_get_domain_partition(void *dev, u32 flags,
@@ -2833,12 +3171,12 @@
int rc = 0;
struct venus_hfi_device *device = dev;
- if (!device) {
+ if (!device || !device->gdsc) {
dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
__func__, device);
return -EINVAL;
}
- mutex_init(&device->clock_lock);
+ mutex_init(&device->clk_pwr_lock);
device->clk_gating_level = VCODEC_CLK;
rc = venus_hfi_iommu_attach(device);
if (rc) {
@@ -2846,14 +3184,21 @@
goto fail_iommu_attach;
}
- if (!device->resources.fw.cookie)
+ if (!device->resources.fw.cookie) {
+ rc = regulator_enable(device->gdsc);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to enable GDSC %d", rc);
+ goto fail_enable_gdsc;
+ }
device->resources.fw.cookie = subsystem_get("venus");
+ }
if (IS_ERR_OR_NULL(device->resources.fw.cookie)) {
dprintk(VIDC_ERR, "Failed to download firmware\n");
rc = -ENOMEM;
goto fail_load_fw;
}
+ device->power_enabled = 1;
/*Clocks can be enabled only after pil_get since
* gdsc is turned-on in pil_get*/
rc = venus_hfi_enable_clks(device);
@@ -2875,6 +3220,8 @@
subsystem_put(device->resources.fw.cookie);
fail_load_fw:
device->resources.fw.cookie = NULL;
+ regulator_disable(device->gdsc);
+fail_enable_gdsc:
venus_hfi_iommu_detach(device);
fail_iommu_attach:
return rc;
@@ -2890,8 +3237,10 @@
}
if (device->resources.fw.cookie) {
flush_workqueue(device->vidc_workq);
+ flush_workqueue(device->venus_pm_workq);
venus_hfi_disable_clks(device);
subsystem_put(device->resources.fw.cookie);
+ regulator_disable(device->gdsc);
venus_hfi_interface_queues_release(dev);
venus_hfi_iommu_detach(device);
device->resources.fw.cookie = NULL;
@@ -2992,9 +3341,15 @@
hdevice->vidc_workq = create_singlethread_workqueue(
"msm_vidc_workerq_venus");
if (!hdevice->vidc_workq) {
- dprintk(VIDC_ERR, ": create workq failed\n");
+ dprintk(VIDC_ERR, ": create vidc workq failed\n");
goto error_createq;
}
+ hdevice->venus_pm_workq = create_singlethread_workqueue(
+ "pm_workerq_venus");
+ if (!hdevice->venus_pm_workq) {
+ dprintk(VIDC_ERR, ": create pm workq failed\n");
+ goto error_createq_pm;
+ }
if (hal_ctxt.dev_count == 0)
INIT_LIST_HEAD(&hal_ctxt.dev_head);
@@ -3004,6 +3359,8 @@
hal_ctxt.dev_count++;
return (void *) hdevice;
+error_createq_pm:
+ destroy_workqueue(hdevice->vidc_workq);
error_createq:
err_init_regs:
kfree(hdevice);
@@ -3054,6 +3411,7 @@
free_irq(dev->hal_data->irq, close);
list_del(&close->list);
destroy_workqueue(close->vidc_workq);
+ destroy_workqueue(close->venus_pm_workq);
kfree(close->hal_data);
kfree(close);
break;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 44cdf31..f1d8694 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -182,12 +182,14 @@
struct list_head sess_head;
u32 intr_status;
u32 device_id;
- u32 load;
+ u32 clk_load;
+ u32 bus_load[MSM_VIDC_MAX_DEVICES];
u32 clocks_enabled;
+ u32 power_enabled;
enum vidc_clocks clk_gating_level;
struct mutex read_lock;
struct mutex write_lock;
- struct mutex clock_lock;
+ struct mutex clk_pwr_lock;
struct mutex session_lock;
msm_vidc_callback callback;
struct vidc_mem_addr iface_q_table;
@@ -198,6 +200,7 @@
struct smem_client *hal_client;
struct hal_data *hal_data;
struct workqueue_struct *vidc_workq;
+ struct workqueue_struct *venus_pm_workq;
int spur_count;
int reg_count;
u32 base_addr;
@@ -206,6 +209,7 @@
u32 irq;
struct venus_resources resources;
struct msm_vidc_platform_resources *res;
+ struct regulator *gdsc;
};
void venus_hfi_delete_device(void *device);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 890a5be..b600d64 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -202,6 +202,7 @@
HAL_VIDEO_CODEC_VP7 = 0x00000800,
HAL_VIDEO_CODEC_VP8 = 0x00001000,
HAL_VIDEO_CODEC_HEVC = 0x00002000,
+ HAL_VIDEO_CODEC_HEVC_HYBRID = 0x00004000,
HAL_UNUSED_CODEC = 0x10000000,
};
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index de312f4..b5c431e 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -80,6 +80,7 @@
#define HFI_VIDEO_CODEC_SPARK 0x00000200
#define HFI_VIDEO_CODEC_VP8 0x00001000
#define HFI_VIDEO_CODEC_HEVC 0x00002000
+#define HFI_VIDEO_CODEC_HEVC_HYBRID 0x00004000
#define HFI_H264_PROFILE_BASELINE 0x00000001
#define HFI_H264_PROFILE_MAIN 0x00000002
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
index eeffe35..6377fbf 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
@@ -49,6 +49,7 @@
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_SHFT 0x1
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_BMSK 0x1
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_SHFT 0x0
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY 0x100
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK 0x40000000
/* HFI_QTBL_INFO */
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index a4cf18e..5e056be 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -4122,6 +4122,7 @@
radio = video_get_drvdata(video_devdata(file));
strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
+ capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
radio->g_cap = capability;
return 0;
}
diff --git a/drivers/misc/isa1200.c b/drivers/misc/isa1200.c
index c6d08d1..8090b95 100644
--- a/drivers/misc/isa1200.c
+++ b/drivers/misc/isa1200.c
@@ -44,6 +44,7 @@
struct timed_output_dev dev;
struct work_struct work;
struct mutex lock;
+ struct mutex lock_clk;
unsigned int enable;
unsigned int period_ns;
bool is_len_gpio_valid;
@@ -120,16 +121,19 @@
}
}
+ mutex_lock(&haptic->lock_clk);
/* vote for clock */
if (haptic->pdata->need_pwm_clk && !haptic->clk_on) {
rc = clk_prepare_enable(haptic->pwm_clk);
if (rc < 0) {
pr_err("%s: clk enable failed\n",
__func__);
+ mutex_unlock(&haptic->lock_clk);
goto dis_clk_cb;
}
haptic->clk_on = true;
}
+ mutex_unlock(&haptic->lock_clk);
rc = isa1200_write_reg(haptic->client,
ISA1200_HCTRL5,
@@ -162,11 +166,13 @@
if (rc < 0)
pr_err("%s: stop vibartion fail\n", __func__);
+ mutex_lock(&haptic->lock_clk);
/* de-vote clock */
if (haptic->pdata->need_pwm_clk && haptic->clk_on) {
clk_disable_unprepare(haptic->pwm_clk);
haptic->clk_on = false;
}
+ mutex_unlock(&haptic->lock_clk);
/* check for board specific clk callback */
if (haptic->pdata->clk_enable) {
rc = haptic->pdata->clk_enable(false);
@@ -180,10 +186,12 @@
return;
dis_clk:
+ mutex_lock(&haptic->lock_clk);
if (haptic->pdata->need_pwm_clk && haptic->clk_on) {
clk_disable_unprepare(haptic->pwm_clk);
haptic->clk_on = false;
}
+ mutex_unlock(&haptic->lock_clk);
dis_clk_cb:
if (haptic->pdata->clk_enable) {
@@ -649,6 +657,7 @@
}
mutex_init(&haptic->lock);
+ mutex_init(&haptic->lock_clk);
INIT_WORK(&haptic->work, isa1200_chip_work);
haptic->clk_on = false;
@@ -787,6 +796,7 @@
/* destroy mutex */
mutex_destroy(&haptic->lock);
+ mutex_destroy(&haptic->lock_clk);
/* power-off the chip */
if (haptic->pdata->regulator_info) {
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index a4498d2..3648d88 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -26,6 +26,12 @@
#include "sd.h"
#include "sd_ops.h"
+#define UHS_SDR104_MIN_DTR (100 * 1000 * 1000)
+#define UHS_DDR50_MIN_DTR (50 * 1000 * 1000)
+#define UHS_SDR50_MIN_DTR (50 * 1000 * 1000)
+#define UHS_SDR25_MIN_DTR (25 * 1000 * 1000)
+#define UHS_SDR12_MIN_DTR (12.5 * 1000 * 1000)
+
static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
@@ -486,18 +492,22 @@
}
if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
- (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104) &&
+ (card->host->f_max > UHS_SDR104_MIN_DTR)) {
card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
} else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
- (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50) &&
+ (card->host->f_max > UHS_DDR50_MIN_DTR)) {
card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
- SD_MODE_UHS_SDR50)) {
+ SD_MODE_UHS_SDR50) &&
+ (card->host->f_max > UHS_SDR50_MIN_DTR)) {
card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
- (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25) &&
+ (card->host->f_max > UHS_SDR25_MIN_DTR)) {
card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index 44f86dd..9f06258 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -42,6 +42,11 @@
module_param_named(debug_enable, msm_rmnet_bam_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
+static unsigned long int msm_rmnet_bam_headroom_check_failure;
+module_param(msm_rmnet_bam_headroom_check_failure, ulong, S_IRUGO);
+MODULE_PARM_DESC(msm_rmnet_bam_headroom_check_failure,
+ "Number of packets with insufficient headroom");
+
#define DEBUG_MASK_LVL0 (1U << 0)
#define DEBUG_MASK_LVL1 (1U << 1)
#define DEBUG_MASK_LVL2 (1U << 2)
@@ -287,6 +292,23 @@
((struct net_device *)dev)->name, __func__);
}
+static struct sk_buff *_rmnet_add_headroom(struct sk_buff **skb,
+ struct net_device *dev)
+{
+ struct sk_buff *skbn;
+
+ if (skb_headroom(*skb) < dev->needed_headroom) {
+ msm_rmnet_bam_headroom_check_failure++;
+ skbn = skb_realloc_headroom(*skb, dev->needed_headroom);
+ kfree_skb(*skb);
+ *skb = skbn;
+ } else {
+ skbn = *skb;
+ }
+
+ return skbn;
+}
+
static int _rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rmnet_private *p = netdev_priv(dev);
@@ -295,6 +317,10 @@
u32 opmode;
unsigned long flags;
+ if (unlikely(!_rmnet_add_headroom(&skb, dev))) {
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
/* For QoS mode, prepend QMI header and assign flow ID from skb->mark */
spin_lock_irqsave(&p->lock, flags);
opmode = p->operation_mode;
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index aa29748..7d6e345 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -1797,6 +1797,7 @@
if (IS_ERR(penv->pil)) {
dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
ret = PTR_ERR(penv->pil);
+ wcnss_pronto_log_debug_regs();
penv->pil = NULL;
goto fail_pil;
}
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index b77c826..7d26bef 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -199,8 +199,15 @@
#define qpnp_check_gpled_lpg_channel(id) \
(id >= QPNP_GPLED_LPG_CHANNEL_RANGE_START && \
id <= QPNP_GPLED_LPG_CHANNEL_RANGE_END)
+
#define QPNP_PWM_LUT_NOT_SUPPORTED 0x1
+/* Supported PWM sizes */
+#define QPNP_PWM_SIZE_6_BIT 6
+#define QPNP_PWM_SIZE_7_BIT 7
+#define QPNP_PWM_SIZE_8_BIT 8
+#define QPNP_PWM_SIZE_9_BIT 9
+
/* LPG revisions */
enum qpnp_lpg_revision {
QPNP_LPG_REVISION_0 = 0x0,
@@ -301,6 +308,7 @@
int pwm_period;
int pwm_duty;
struct pwm_period_config period;
+ int force_pwm_size;
};
/* Public facing structure */
@@ -418,14 +426,16 @@
* (PWM Period / N) = (Pre-divide * Clock Period) * 2^m
*/
static void qpnp_lpg_calc_period(unsigned int period_us,
- struct qpnp_pwm_config *pwm_conf)
+ struct pwm_device *pwm)
{
int n, m, clk, div;
int best_m, best_div, best_clk;
unsigned int last_err, cur_err, min_err;
unsigned int tmp_p, period_n;
- int id = pwm_conf->channel_id;
- struct pwm_period_config *period = &pwm_conf->period;
+ int id = pwm->pwm_config.channel_id;
+ int force_pwm_size = pwm->pwm_config.force_pwm_size;
+ struct qpnp_lpg_chip *chip = pwm->chip;
+ struct pwm_period_config *period = &pwm->pwm_config.period;
/* PWM Period / N */
if (qpnp_check_gpled_lpg_channel(id))
@@ -443,6 +453,15 @@
period_n = (period_us >> n) * NSEC_PER_USEC;
}
+ if (force_pwm_size != 0) {
+ if (n < force_pwm_size)
+ period_n = period_n >> (force_pwm_size - n);
+ else
+ period_n = period_n << (n - force_pwm_size);
+ n = force_pwm_size;
+ pr_info("LPG channel '%d' pwm size is forced to=%d\n", id, n);
+ }
+
min_err = last_err = (unsigned)(-1);
best_m = 0;
best_clk = 0;
@@ -476,19 +495,20 @@
}
/* Adapt to optimal pwm size, the higher the resolution the better */
- if (qpnp_check_gpled_lpg_channel(id)) {
- if (n == 7 && best_m >= 1) {
- n += 1;
- best_m -= 1;
- }
- } else {
- if (n == 6 && best_m >= 3) {
- n += 3;
- best_m -= 3;
- } else {
- if (n == 6) {
- n += best_m;
- best_m -= best_m;
+ if (!force_pwm_size) {
+ if (qpnp_check_gpled_lpg_channel(id)) {
+ if (n == 7 && best_m >= 1) {
+ n += 1;
+ best_m -= 1;
+ }
+ } else if (n == 6) {
+ if (best_m >= 3) {
+ n += 3;
+ best_m -= 3;
+ } else if (best_m >= 1 &&
+ chip->sub_type != QPNP_PWM_MODE_ONLY_SUB_TYPE) {
+ n += 1;
+ best_m -= 1;
}
}
}
@@ -1075,7 +1095,7 @@
period = &pwm_config->period;
if (pwm_config->pwm_period != period_us) {
- qpnp_lpg_calc_period(period_us, pwm_config);
+ qpnp_lpg_calc_period(period_us, pwm);
qpnp_lpg_save_period(pwm);
pwm_config->pwm_period = period_us;
}
@@ -1131,7 +1151,7 @@
period = &pwm_config->period;
if (pwm_config->pwm_period != period_us) {
- qpnp_lpg_calc_period(period_us, pwm_config);
+ qpnp_lpg_calc_period(period_us, pwm);
qpnp_lpg_save_period(pwm);
pwm_config->pwm_period = period_us;
}
@@ -1715,6 +1735,7 @@
struct pwm_device *pwm_dev = &chip->pwm_dev;
struct qpnp_lpg_config *lpg_config = &chip->lpg_config;
struct qpnp_lut_config *lut_config = &lpg_config->lut_config;
+ int force_pwm_size = 0;
rc = of_property_read_u32(of_node, "qcom,channel-id",
&pwm_dev->pwm_config.channel_id);
@@ -1724,6 +1745,27 @@
goto out;
}
+ /*
+ * For cetrain LPG channels PWM size can be forced. So that
+ * for every requested pwm period closest pwm frequency is
+ * selected in qpnp_lpg_calc_period() for the forced pwm size.
+ */
+ rc = of_property_read_u32(of_node, "qcom,force-pwm-size",
+ &force_pwm_size);
+ if (qpnp_check_gpled_lpg_channel(pwm_dev->pwm_config.channel_id)) {
+ if (!(force_pwm_size == QPNP_PWM_SIZE_7_BIT ||
+ force_pwm_size == QPNP_PWM_SIZE_8_BIT))
+ force_pwm_size = 0;
+ } else if (chip->sub_type == QPNP_PWM_MODE_ONLY_SUB_TYPE) {
+ if (!(force_pwm_size == QPNP_PWM_SIZE_6_BIT ||
+ force_pwm_size == QPNP_PWM_SIZE_9_BIT))
+ force_pwm_size = 0;
+ } else if (!(force_pwm_size == QPNP_PWM_SIZE_6_BIT ||
+ force_pwm_size == QPNP_PWM_SIZE_7_BIT ||
+ force_pwm_size == QPNP_PWM_SIZE_9_BIT))
+ force_pwm_size = 0;
+
+ pwm_dev->pwm_config.force_pwm_size = force_pwm_size;
res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
QPNP_LPG_CHANNEL_BASE);
if (!res) {
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 8bb4f90..4be727f 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -356,7 +356,7 @@
/*
* Enable USB PRIVATE RAM to be used for BAM FIFOs
* HSUSB: Only RAM13 is used for BAM FIFOs
- * SSUSB: RAM11, 12, 13 are used for BAM FIFOs
+ * SSUSB: RAM12, 13 are used for BAM FIFOs
*/
bam = pipe_connect->bam_type;
if (bam < 0)
@@ -365,7 +365,7 @@
if (bam == HSUSB_BAM)
ram1_value = 0x4;
else
- ram1_value = 0x7;
+ ram1_value = 0x6;
pr_debug("Writing 0x%x to QSCRATCH_RAM1\n", ram1_value);
writel_relaxed(ram1_value, ctx.qscratch_ram1_reg);
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index ae13a06..49e57b9 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -83,7 +83,7 @@
#define IAVG_STEP_SIZE_MA 50
#define IAVG_START 600
#define IAVG_INVALID 0xFF
-#define SOC_INVALID 0xFF
+#define SOC_INVALID 0x7E
#define IAVG_SAMPLES 16
@@ -147,6 +147,8 @@
wait_queue_head_t bms_wait_queue;
u16 base;
u16 iadc_base;
+ u16 batt_pres_addr;
+ u16 soc_storage_addr;
u8 revision1;
u8 revision2;
@@ -188,6 +190,7 @@
struct mutex vbat_monitor_mutex;
struct mutex soc_invalidation_mutex;
struct mutex last_soc_mutex;
+ struct mutex status_lock;
bool use_external_rsense;
bool use_ocv_thresholds;
@@ -293,6 +296,7 @@
static enum power_supply_property msm_bms_power_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_RESISTANCE,
POWER_SUPPLY_PROP_CHARGE_COUNTER,
@@ -1510,24 +1514,6 @@
pr_debug("UUC = %uuAh\n", params->uuc_uah);
}
-static bool is_shutdown_soc_within_limits(struct qpnp_bms_chip *chip, int soc)
-{
- if (chip->shutdown_soc_invalid) {
- pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
- return 0;
- }
-
- if (abs(chip->shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
- pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
- chip->shutdown_soc, soc,
- chip->shutdown_soc_valid_limit);
- chip->shutdown_soc_invalid = true;
- return 0;
- }
-
- return 1;
-}
-
static int bound_soc(int soc)
{
soc = max(0, soc);
@@ -1614,6 +1600,7 @@
module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
+#define SOC_STORAGE_MASK 0xFE
static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
int soc)
{
@@ -1626,15 +1613,12 @@
else
temp = 0;
- rc = qpnp_write_wrapper(chip, &temp,
- chip->base + IAVG_STORAGE_REG, 1);
-
- temp = soc;
+ rc = qpnp_write_wrapper(chip, &temp, chip->base + IAVG_STORAGE_REG, 1);
/* don't store soc if temperature is below 5degC */
if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
- rc = qpnp_write_wrapper(chip, &temp,
- chip->base + SOC_STORAGE_REG, 1);
+ qpnp_masked_write_base(chip, chip->soc_storage_addr,
+ SOC_STORAGE_MASK, (soc + 1) << 1);
}
static int scale_soc_while_chg(struct qpnp_bms_chip *chip, int chg_time_sec,
@@ -1822,6 +1806,7 @@
int vbat_uv, int ibat_ua, int batt_temp)
{
int chg_soc, soc_ibat, batt_terminal_uv, weight_ibat, weight_cc;
+ int new_ocv_uv;
batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
@@ -1873,8 +1858,6 @@
/* always report a higher soc */
if (chg_soc > chip->prev_chg_soc) {
- int new_ocv_uv;
-
chip->prev_chg_soc = chg_soc;
find_ocv_for_soc(chip, params, batt_temp, chg_soc, &new_ocv_uv);
@@ -2186,37 +2169,22 @@
(uint16_t)ocv_raw);
}
-#define SLEEP_RECALC_INTERVAL 3
-static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
+static int calculate_raw_soc(struct qpnp_bms_chip *chip,
struct raw_soc_params *raw,
+ struct soc_params *params,
int batt_temp)
{
- int soc, new_ocv_uv, previous_soc;
- int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
- struct soc_params params;
+ int soc, new_ocv_uv;
+ int remaining_usable_charge_uah;
- if (!is_battery_present(chip)) {
- pr_debug("battery gone, reporting 100\n");
- new_calculated_soc = 100;
- goto done_calculating;
- }
- calculate_soc_params(chip, raw, ¶ms, batt_temp);
/* calculate remaining usable charge */
- remaining_usable_charge_uah = params.ocv_charge_uah
- - params.cc_uah
- - params.uuc_uah;
-
+ remaining_usable_charge_uah = params->ocv_charge_uah
+ - params->cc_uah
+ - params->uuc_uah;
pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
- if (params.fcc_uah - params.uuc_uah <= 0) {
- pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
- params.fcc_uah,
- params.uuc_uah);
- new_calculated_soc = 0;
- goto done_calculating;
- }
soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
- (params.fcc_uah - params.uuc_uah));
+ (params->fcc_uah - params->uuc_uah));
if (chip->first_time_calc_soc && soc < 0) {
/*
@@ -2224,16 +2192,16 @@
* in a bad soc. Adjust ocv to get 0 soc
*/
pr_debug("soc is %d, adjusting pon ocv to make it 0\n", soc);
- find_ocv_for_soc(chip, ¶ms, batt_temp, 0, &new_ocv_uv);
+ find_ocv_for_soc(chip, params, batt_temp, 0, &new_ocv_uv);
chip->last_ocv_uv = new_ocv_uv;
- remaining_usable_charge_uah = params.ocv_charge_uah
- - params.cc_uah
- - params.uuc_uah;
+ remaining_usable_charge_uah = params->ocv_charge_uah
+ - params->cc_uah
+ - params->uuc_uah;
soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
- (params.fcc_uah
- - params.uuc_uah));
+ (params->fcc_uah
+ - params->uuc_uah));
pr_debug("DONE for O soc is %d, pon ocv adjusted to %duV\n",
soc, chip->last_ocv_uv);
}
@@ -2244,20 +2212,49 @@
if (soc < 0) {
pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
remaining_usable_charge_uah,
- params.ocv_charge_uah,
- params.cc_uah, params.uuc_uah);
+ params->ocv_charge_uah,
+ params->cc_uah, params->uuc_uah);
pr_debug("for bad rem_usb_chg last_ocv_uv = %d batt_temp = %d fcc = %d soc =%d\n",
chip->last_ocv_uv, batt_temp,
- params.fcc_uah, soc);
+ params->fcc_uah, soc);
soc = 0;
}
+ return soc;
+}
+
+#define SLEEP_RECALC_INTERVAL 3
+static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
+ struct raw_soc_params *raw,
+ int batt_temp)
+{
+ struct soc_params params;
+ int soc, previous_soc, shutdown_soc, new_calculated_soc;
+ int remaining_usable_charge_uah, new_ocv_uv;
+
+ calculate_soc_params(chip, raw, ¶ms, batt_temp);
+ if (!is_battery_present(chip)) {
+ pr_debug("battery gone, reporting 100\n");
+ new_calculated_soc = 100;
+ goto done_calculating;
+ }
+
+ if (params.fcc_uah - params.uuc_uah <= 0) {
+ pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
+ params.fcc_uah,
+ params.uuc_uah);
+ new_calculated_soc = 0;
+ goto done_calculating;
+ }
+
+ soc = calculate_raw_soc(chip, raw, ¶ms, batt_temp);
+
mutex_lock(&chip->soc_invalidation_mutex);
shutdown_soc = chip->shutdown_soc;
if (chip->first_time_calc_soc && soc != shutdown_soc
- && is_shutdown_soc_within_limits(chip, soc)) {
+ && !chip->shutdown_soc_invalid) {
/*
* soc for the first time - use shutdown soc
* to adjust pon ocv since it is a small percent away from
@@ -2367,6 +2364,53 @@
return voltage_based_soc;
}
+static int recalculate_raw_soc(struct qpnp_bms_chip *chip)
+{
+ int batt_temp, rc, soc;
+ struct qpnp_vadc_result result;
+ struct raw_soc_params raw;
+ struct soc_params params;
+
+ bms_stay_awake(&chip->soc_wake_source);
+ if (chip->use_voltage_soc) {
+ soc = calculate_soc_from_voltage(chip);
+ } else {
+ if (!chip->batfet_closed)
+ qpnp_iadc_calibrate_for_trim(chip->iadc_dev, true);
+ rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM,
+ &result);
+ if (rc) {
+ pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
+ LR_MUX1_BATT_THERM, rc);
+ soc = chip->calculated_soc;
+ } else {
+ pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
+ result.physical,
+ result.measurement);
+ batt_temp = (int)result.physical;
+
+ mutex_lock(&chip->last_ocv_uv_mutex);
+ read_soc_params_raw(chip, &raw, batt_temp);
+ calculate_soc_params(chip, &raw, ¶ms, batt_temp);
+ if (!is_battery_present(chip)) {
+ pr_debug("battery gone\n");
+ soc = 0;
+ } else if (params.fcc_uah - params.uuc_uah <= 0) {
+ pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
+ params.fcc_uah,
+ params.uuc_uah);
+ soc = 0;
+ } else {
+ soc = calculate_raw_soc(chip, &raw,
+ ¶ms, batt_temp);
+ }
+ mutex_unlock(&chip->last_ocv_uv_mutex);
+ }
+ }
+ bms_relax(&chip->soc_wake_source);
+ return soc;
+}
+
static int recalculate_soc(struct qpnp_bms_chip *chip)
{
int batt_temp, rc, soc;
@@ -3068,6 +3112,7 @@
{
int status = get_battery_status(chip);
+ mutex_lock(&chip->status_lock);
if (chip->battery_status != status) {
pr_debug("status = %d, shadow status = %d\n",
status, chip->battery_status);
@@ -3084,6 +3129,7 @@
pr_debug("battery full\n");
enable_bms_irq(&chip->ocv_thr_irq);
enable_bms_irq(&chip->sw_cc_thr_irq);
+ recalculate_soc(chip);
} else if (chip->battery_status
== POWER_SUPPLY_STATUS_FULL) {
pr_debug("battery not full any more\n");
@@ -3096,6 +3142,7 @@
* recalculation to update the SoC */
schedule_work(&chip->recalc_work);
}
+ mutex_unlock(&chip->status_lock);
}
#define CALIB_WRKARND_DIG_MAJOR_MAX 0x03
@@ -3170,6 +3217,9 @@
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = get_prop_bms_capacity(chip);
break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = chip->battery_status;
+ break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
val->intval = get_prop_bms_current_now(chip);
break;
@@ -3234,61 +3284,120 @@
return 0;
}
-static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
+static int read_shutdown_iavg_ma(struct qpnp_bms_chip *chip)
{
+ u8 iavg;
int rc;
- u8 temp;
- if (chip->ignore_shutdown_soc) {
- chip->shutdown_soc_invalid = true;
- chip->shutdown_soc = 0;
- chip->shutdown_iavg_ma = 0;
+ rc = qpnp_read_wrapper(chip, &iavg, chip->base + IAVG_STORAGE_REG, 1);
+ if (rc) {
+ pr_err("failed to read addr = %d %d assuming %d\n",
+ chip->base + IAVG_STORAGE_REG, rc,
+ IAVG_START);
+ return IAVG_START;
+ } else if (iavg == IAVG_INVALID) {
+ pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
+ IAVG_START);
+ return IAVG_START;
} else {
- rc = qpnp_read_wrapper(chip, &temp,
- chip->base + IAVG_STORAGE_REG, 1);
- if (rc) {
- pr_err("failed to read addr = %d %d assuming %d\n",
- chip->base + IAVG_STORAGE_REG, rc,
- IAVG_START);
- chip->shutdown_iavg_ma = IAVG_START;
- } else if (temp == IAVG_INVALID) {
- pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
- IAVG_START);
- chip->shutdown_iavg_ma = IAVG_START;
- } else {
- if (temp == 0) {
- chip->shutdown_iavg_ma = IAVG_START;
- } else {
- chip->shutdown_iavg_ma = IAVG_START
- + IAVG_STEP_SIZE_MA * (temp + 1);
- }
- }
+ if (iavg == 0)
+ return IAVG_START;
+ else
+ return IAVG_START + IAVG_STEP_SIZE_MA * (iavg + 1);
+ }
+}
- rc = qpnp_read_wrapper(chip, &temp,
- chip->base + SOC_STORAGE_REG, 1);
- if (rc) {
- pr_err("failed to read addr = %d %d\n",
- chip->base + SOC_STORAGE_REG, rc);
- } else {
- chip->shutdown_soc = temp;
+static int read_shutdown_soc(struct qpnp_bms_chip *chip)
+{
+ u8 stored_soc;
+ int rc, shutdown_soc;
- if (chip->shutdown_soc == SOC_INVALID) {
- pr_debug("No shutdown soc available\n");
- chip->shutdown_soc_invalid = true;
- chip->shutdown_iavg_ma = 0;
- }
- }
+ /*
+ * The previous SOC is stored in the first 7 bits of the register as
+ * (Shutdown SOC + 1). This allows for register reset values of both
+ * 0x00 and 0x7F.
+ */
+ rc = qpnp_read_wrapper(chip, &stored_soc, chip->soc_storage_addr, 1);
+ if (rc) {
+ pr_err("failed to read addr = %d %d\n",
+ chip->soc_storage_addr, rc);
+ return SOC_INVALID;
}
- /* read the SOC storage to determine if there was a battery removal */
- rc = qpnp_read_wrapper(chip, &temp, chip->base + SOC_STORAGE_REG, 1);
- if (!rc) {
- if (temp == SOC_INVALID)
- chip->battery_removed = true;
+ if ((stored_soc >> 1) > 0)
+ shutdown_soc = (stored_soc >> 1) - 1;
+ else
+ shutdown_soc = SOC_INVALID;
+
+ pr_debug("stored soc = 0x%02x, shutdown_soc = %d\n",
+ stored_soc, shutdown_soc);
+ return shutdown_soc;
+}
+
+#define BAT_REMOVED_OFFMODE_BIT BIT(6)
+static bool is_battery_replaced_in_offmode(struct qpnp_bms_chip *chip)
+{
+ u8 batt_pres;
+ int rc;
+
+ if (chip->batt_pres_addr) {
+ rc = qpnp_read_wrapper(chip, &batt_pres,
+ chip->batt_pres_addr, 1);
+ pr_debug("offmode removed: %02x\n", batt_pres);
+ if (!rc && (batt_pres & BAT_REMOVED_OFFMODE_BIT))
+ return true;
+ }
+ return false;
+}
+
+static void load_shutdown_data(struct qpnp_bms_chip *chip)
+{
+ int calculated_soc, shutdown_soc;
+ bool invalid_stored_soc;
+ bool offmode_battery_replaced;
+ bool shutdown_soc_out_of_limit;
+
+ /*
+ * Read the saved shutdown SoC from the configured register and
+ * check if the value has been reset
+ */
+ shutdown_soc = read_shutdown_soc(chip);
+ invalid_stored_soc = (shutdown_soc == SOC_INVALID);
+
+ /*
+ * Do a quick run of SoC calculation to find whether the shutdown soc
+ * is close enough.
+ */
+ calculated_soc = recalculate_raw_soc(chip);
+ shutdown_soc_out_of_limit = (abs(shutdown_soc - calculated_soc)
+ > chip->shutdown_soc_valid_limit);
+ pr_debug("calculated_soc = %d, valid_limit = %d\n",
+ calculated_soc, chip->shutdown_soc_valid_limit);
+
+ /*
+ * Check if the battery has been replaced while the system was powered
+ * down.
+ */
+ offmode_battery_replaced = is_battery_replaced_in_offmode(chip);
+
+ /* Invalidate the shutdown SoC if any of these conditions hold true */
+ if (chip->ignore_shutdown_soc
+ || invalid_stored_soc
+ || offmode_battery_replaced
+ || shutdown_soc_out_of_limit) {
+ chip->battery_removed = true;
+ chip->shutdown_soc_invalid = true;
+ chip->shutdown_iavg_ma = 0;
+ pr_debug("Ignoring shutdown SoC: invalid = %d, offmode = %d, out_of_limit = %d\n",
+ invalid_stored_soc, offmode_battery_replaced,
+ shutdown_soc_out_of_limit);
+ } else {
+ chip->shutdown_iavg_ma = read_shutdown_iavg_ma(chip);
+ chip->shutdown_soc = shutdown_soc;
}
-
- pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
+ pr_debug("raw_soc = %d shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
+ calculated_soc,
chip->shutdown_soc,
chip->shutdown_iavg_ma,
chip->shutdown_soc_invalid,
@@ -3410,6 +3519,9 @@
if (batt_data->iterm_ua >= 0 && dt_data)
chip->chg_term_ua = batt_data->iterm_ua;
+ if (dt_data)
+ kfree(batt_data);
+
if (chip->pc_temp_ocv_lut == NULL) {
pr_err("temp ocv lut table is NULL\n");
return -EINVAL;
@@ -3643,6 +3755,18 @@
return -ENXIO;
}
+ pr_debug("Node name = %s\n", spmi_resource->of_node->name);
+
+ if (strcmp("qcom,batt-pres-status",
+ spmi_resource->of_node->name) == 0) {
+ chip->batt_pres_addr = resource->start;
+ continue;
+ } else if (strcmp("qcom,soc-storage-reg",
+ spmi_resource->of_node->name) == 0) {
+ chip->soc_storage_addr = resource->start;
+ continue;
+ }
+
rc = qpnp_read_wrapper(chip, &type,
resource->start + REG_OFFSET_PERP_TYPE, 1);
if (rc) {
@@ -3681,7 +3805,14 @@
dev_err(&spmi->dev, "BMS_IADC peripheral was not registered\n");
return -EINVAL;
}
+ if (chip->soc_storage_addr == 0) {
+ /* default to dvdd backed BMS data reg0 */
+ chip->soc_storage_addr = chip->base + SOC_STORAGE_REG;
+ }
+ pr_debug("bms-base = 0x%04x, iadc-base = 0x%04x, bat-pres-reg = 0x%04x, soc-storage-reg = 0x%04x\n",
+ chip->base, chip->iadc_base,
+ chip->batt_pres_addr, chip->soc_storage_addr);
return 0;
}
@@ -3866,6 +3997,7 @@
mutex_init(&chip->vbat_monitor_mutex);
mutex_init(&chip->soc_invalidation_mutex);
mutex_init(&chip->last_soc_mutex);
+ mutex_init(&chip->status_lock);
init_waitqueue_head(&chip->bms_wait_queue);
warm_reset = qpnp_pon_is_warm_reset();
@@ -3951,7 +4083,10 @@
INIT_WORK(&chip->recalc_work, recalculate_work);
INIT_WORK(&chip->batfet_open_work, batfet_open_work);
- read_shutdown_soc_and_iavg(chip);
+ dev_set_drvdata(&spmi->dev, chip);
+ device_init_wakeup(&spmi->dev, 1);
+
+ load_shutdown_data(chip);
if (chip->enable_fcc_learning) {
if (chip->battery_removed) {
@@ -3971,9 +4106,6 @@
}
}
- dev_set_drvdata(&spmi->dev, chip);
- device_init_wakeup(&spmi->dev, 1);
-
rc = setup_vbat_monitoring(chip);
if (rc < 0) {
pr_err("failed to set up voltage notifications: %d\n", rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 1a79ad5..6e9dc57 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -293,6 +293,7 @@
bool bat_is_cool;
bool bat_is_warm;
bool chg_done;
+ bool charger_monitor_checked;
bool usb_present;
bool dc_present;
bool batt_present;
@@ -341,6 +342,7 @@
struct delayed_work arb_stop_work;
struct delayed_work eoc_work;
struct work_struct soc_check_work;
+ struct delayed_work aicl_check_work;
struct qpnp_chg_regulator otg_vreg;
struct qpnp_chg_regulator boost_vreg;
struct qpnp_chg_regulator batfet_vreg;
@@ -1503,6 +1505,28 @@
return 0;
}
+static void
+qpnp_aicl_check_work(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct qpnp_chg_chip *chip = container_of(dwork,
+ struct qpnp_chg_chip, aicl_check_work);
+ union power_supply_propval ret = {0,};
+
+ if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
+ chip->usb_psy->get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
+ if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
+ pr_debug("no charger_monitor present set iusbmax %d\n",
+ ret.intval / 1000);
+ qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
+ }
+ } else {
+ pr_debug("charger_monitor is present\n");
+ }
+ chip->charger_monitor_checked = true;
+}
+
static int
get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
{
@@ -1669,7 +1693,7 @@
get_prop_capacity(struct qpnp_chg_chip *chip)
{
union power_supply_propval ret = {0,};
- int battery_status, charger_in;
+ int battery_status, bms_status, soc, charger_in;
if (chip->use_default_batt_values || !get_prop_batt_present(chip))
return DEFAULT_CAPACITY;
@@ -1677,28 +1701,32 @@
if (chip->bms_psy) {
chip->bms_psy->get_property(chip->bms_psy,
POWER_SUPPLY_PROP_CAPACITY, &ret);
+ soc = ret.intval;
battery_status = get_prop_batt_status(chip);
+ chip->bms_psy->get_property(chip->bms_psy,
+ POWER_SUPPLY_PROP_STATUS, &ret);
+ bms_status = ret.intval;
charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
qpnp_chg_is_dc_chg_plugged_in(chip);
if (battery_status != POWER_SUPPLY_STATUS_CHARGING
+ && bms_status != POWER_SUPPLY_STATUS_CHARGING
&& charger_in
&& !chip->resuming_charging
&& !chip->charging_disabled
&& chip->soc_resume_limit
- && ret.intval <= chip->soc_resume_limit) {
- pr_debug("resuming charging at %d%% soc\n",
- ret.intval);
+ && soc <= chip->soc_resume_limit) {
+ pr_debug("resuming charging at %d%% soc\n", soc);
chip->resuming_charging = true;
qpnp_chg_set_appropriate_vbatdet(chip);
qpnp_chg_charge_en(chip, !chip->charging_disabled);
}
- if (ret.intval == 0) {
+ if (soc == 0) {
if (!qpnp_chg_is_usb_chg_plugged_in(chip)
&& !qpnp_chg_is_usb_chg_plugged_in(chip))
pr_warn_ratelimited("Battery 0, CHG absent\n");
}
- return ret.intval;
+ return soc;
} else {
pr_debug("No BMS supply registered return 50\n");
}
@@ -1790,7 +1818,8 @@
} else {
qpnp_chg_usb_suspend_enable(chip, 0);
if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
- && (charger_monitor)) {
+ && (charger_monitor ||
+ !chip->charger_monitor_checked)) {
qpnp_chg_iusbmax_set(chip,
USB_WALL_THRESHOLD_MA);
} else {
@@ -3931,6 +3960,7 @@
INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
+ INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
if (chip->dc_chgpth_base) {
chip->dc_psy.name = "qpnp-dc";
@@ -4012,6 +4042,8 @@
if (qpnp_chg_is_usb_chg_plugged_in(chip))
power_supply_set_online(chip->usb_psy, 1);
+ schedule_delayed_work(&chip->aicl_check_work,
+ msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
pr_info("success chg_dis = %d, bpd = %d, usb = %d, dc = %d b_health = %d batt_present = %d\n",
chip->charging_disabled,
chip->bpd_detection,
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 0ebb944..450c4fb 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3357,14 +3357,6 @@
ret = set_supply(rdev, r);
if (ret < 0)
goto scrub;
-
- /* Enable supply if rail is enabled */
- if (rdev->desc->ops->is_enabled &&
- rdev->desc->ops->is_enabled(rdev)) {
- ret = regulator_enable(rdev->supply);
- if (ret < 0)
- goto scrub;
- }
}
/* add consumers devices */
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 467d89d..7dcd45f 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1611,26 +1611,6 @@
goto fail;
}
- rc = devm_request_irq(&spmi->dev, chip->adc->adc_high_thr_irq,
- qpnp_adc_tm_high_thr_isr,
- IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", chip);
- if (rc) {
- dev_err(&spmi->dev, "failed to request adc irq\n");
- goto fail;
- } else {
- enable_irq_wake(chip->adc->adc_high_thr_irq);
- }
-
- rc = devm_request_irq(&spmi->dev, chip->adc->adc_low_thr_irq,
- qpnp_adc_tm_low_thr_isr,
- IRQF_TRIGGER_RISING, "qpnp_adc_tm_low_interrupt", chip);
- if (rc) {
- dev_err(&spmi->dev, "failed to request adc irq\n");
- goto fail;
- } else {
- enable_irq_wake(chip->adc->adc_low_thr_irq);
- }
-
for_each_child_of_node(node, child) {
char name[25];
int btm_channel_num;
@@ -1677,8 +1657,6 @@
chip->max_channels_available = count_adc_channel_list;
INIT_WORK(&chip->trigger_high_thr_work, qpnp_adc_tm_high_thr_work);
INIT_WORK(&chip->trigger_low_thr_work, qpnp_adc_tm_low_thr_work);
- dev_set_drvdata(&spmi->dev, chip);
- list_add(&chip->list, &qpnp_adc_tm_device_list);
rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
thr_init);
@@ -1701,6 +1679,29 @@
goto fail;
}
+ rc = devm_request_irq(&spmi->dev, chip->adc->adc_high_thr_irq,
+ qpnp_adc_tm_high_thr_isr,
+ IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", chip);
+ if (rc) {
+ dev_err(&spmi->dev, "failed to request adc irq\n");
+ goto fail;
+ } else {
+ enable_irq_wake(chip->adc->adc_high_thr_irq);
+ }
+
+ rc = devm_request_irq(&spmi->dev, chip->adc->adc_low_thr_irq,
+ qpnp_adc_tm_low_thr_isr,
+ IRQF_TRIGGER_RISING, "qpnp_adc_tm_low_interrupt", chip);
+ if (rc) {
+ dev_err(&spmi->dev, "failed to request adc irq\n");
+ goto fail;
+ } else {
+ enable_irq_wake(chip->adc->adc_low_thr_irq);
+ }
+
+ dev_set_drvdata(&spmi->dev, chip);
+ list_add(&chip->list, &qpnp_adc_tm_device_list);
+
pr_debug("OK\n");
return 0;
fail:
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 94b6eda..8eb5573 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -81,20 +81,31 @@
}
/**
- * n_tty_set__room - receive space
+ * n_tty_set_room - receive space
* @tty: terminal
*
- * Called by the driver to find out how much data it is
- * permitted to feed to the line discipline without any being lost
- * and thus to manage flow control. Not serialized. Answers for the
- * "instant".
+ * Sets tty->receive_room to reflect the currently available space
+ * in the input buffer, and re-schedules the flip buffer work if space
+ * just became available.
+ *
+ * Locks: Concurrent update is protected with read_lock
*/
static void n_tty_set_room(struct tty_struct *tty)
{
- /* tty->read_cnt is not read locked ? */
- int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+ int left;
int old_left;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->read_lock, flags);
+
+ if (I_PARMRK(tty)) {
+ /* Multiply read_cnt by 3, since each byte might take up to
+ * three times as many spaces when PARMRK is set (depending on
+ * its flags, e.g. parity error). */
+ left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+ } else
+ left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
/*
* If we are doing input canonicalization, and there are no
@@ -107,6 +118,8 @@
old_left = tty->receive_room;
tty->receive_room = left;
+ spin_unlock_irqrestore(&tty->read_lock, flags);
+
/* Did this open up the receive buffer? We may need to flip */
if (left && !old_left)
schedule_work(&tty->buf.work);
@@ -1811,7 +1824,6 @@
retval = -ERESTARTSYS;
break;
}
- /* FIXME: does n_tty_set_room need locking ? */
n_tty_set_room(tty);
timeout = schedule_timeout(timeout);
BUG_ON(!tty->read_buf);
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 81bc0f0..24b18cb 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -463,8 +463,6 @@
int count;
char *char_buf;
unsigned char *flag_buf;
- unsigned int left = 0;
- unsigned int max_space;
count = head->commit - head->read;
if (!count) {
@@ -475,32 +473,10 @@
continue;
}
- /* update receive room */
- spin_lock(&tty->read_lock);
- if (tty->update_room_in_ldisc) {
- if ((tty->read_cnt == N_TTY_BUF_SIZE - 1) &&
- (tty->receive_room ==
- N_TTY_BUF_SIZE - 1))
- tty->rr_bug++;
- left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
- }
- spin_unlock(&tty->read_lock);
-
if (!tty->receive_room)
break;
-
- if (tty->update_room_in_ldisc && !left) {
- schedule_work(&tty->buf.work);
- break;
- }
-
- if (tty->update_room_in_ldisc)
- max_space = min(left, tty->receive_room);
- else
- max_space = tty->receive_room;
-
- if (count > max_space)
- count = max_space;
+ if (count > tty->receive_room)
+ count = tty->receive_room;
char_buf = head->char_buf_ptr + head->read;
flag_buf = head->flag_buf_ptr + head->read;
head->read += count;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 328f6f4..674efb3 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -693,6 +693,7 @@
* @mem: points to start of memory which is used for this struct.
* @hwparams: copy of hwparams registers
* @root: debugfs root folder pointer
+ * @tx_fifo_size: Available RAM size for TX fifo allocation
*/
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
@@ -778,6 +779,7 @@
/* Indicate if software connect was issued by the usb_gadget_driver */
bool softconnect;
void (*notify_event) (struct dwc3 *, unsigned);
+ int tx_fifo_size;
};
/* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index d7721dc..f43affb 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -223,6 +223,8 @@
unsigned int vdd_no_vol_level;
unsigned int vdd_low_vol_level;
unsigned int vdd_high_vol_level;
+ unsigned int tx_fifo_size;
+ unsigned int qdss_tx_fifo_size;
bool vbus_active;
bool ext_inuse;
enum dwc3_id_state id_state;
@@ -1028,6 +1030,19 @@
}
EXPORT_SYMBOL(msm_ep_unconfig);
+void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enabled)
+{
+ struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+ if (qdss_enabled)
+ dwc->tx_fifo_size = mdwc->qdss_tx_fifo_size;
+ else
+ dwc->tx_fifo_size = mdwc->tx_fifo_size;
+}
+EXPORT_SYMBOL(dwc3_tx_fifo_resize_request);
+
static void dwc3_restart_usb_work(struct work_struct *w)
{
struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
@@ -1490,6 +1505,7 @@
"DWC3_CONTROLLER_POST_RESET_EVENT received\n");
dwc3_msm_qscratch_reg_init(mdwc,
DWC3_CONTROLLER_POST_RESET_EVENT);
+ dwc->tx_fifo_size = mdwc->tx_fifo_size;
break;
default:
dev_dbg(mdwc->dev, "unknown dwc3 event\n");
@@ -2963,6 +2979,17 @@
ret = -ENODEV;
goto disable_hs_ldo;
}
+
+ if (of_property_read_u32(node, "qcom,dwc-usb3-msm-tx-fifo-size",
+ &mdwc->tx_fifo_size))
+ dev_err(&pdev->dev,
+ "unable to read platform data tx fifo size\n");
+
+ if (of_property_read_u32(node, "qcom,dwc-usb3-msm-qdss-tx-fifo-size",
+ &mdwc->qdss_tx_fifo_size))
+ dev_err(&pdev->dev,
+ "unable to read platform data qdss tx fifo size\n");
+
dwc3_set_notifier(&dwc3_msm_notify_event);
/* usb_psy required only for vbus_notifications or charging support */
if (mdwc->ext_xceiv.otg_capability ||
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8cf8a6d..aaa22f3 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -36,7 +36,6 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -58,11 +57,6 @@
#include "debug.h"
#include "io.h"
-static bool tx_fifo_resize_enable;
-module_param(tx_fifo_resize_enable, bool, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(tx_fifo_resize_enable,
- "Enable allocating Tx fifo for endpoints");
-
static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend);
static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend);
@@ -188,7 +182,7 @@
int mdwidth;
int num;
- if (!dwc->needs_fifo_resize && !tx_fifo_resize_enable)
+ if (!dwc->needs_fifo_resize)
return 0;
ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
@@ -233,6 +227,17 @@
* packets
*/
tmp = mult * (dep->endpoint.maxpacket + mdwidth);
+
+ if (dwc->tx_fifo_size &&
+ (usb_endpoint_xfer_bulk(dep->endpoint.desc)
+ || usb_endpoint_xfer_isoc(dep->endpoint.desc)))
+ /*
+ * Allocate 3KB fifo size for bulk and isochronous TX
+ * endpoints irrespective of speed. For interrupt
+ * endpoint, allocate fifo size of endpoint maxpacket.
+ */
+ tmp = 3 * (1024 + mdwidth);
+
tmp += mdwidth;
fifo_size = DIV_ROUND_UP(tmp, mdwidth);
@@ -242,10 +247,21 @@
dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
dep->name, last_fifo_depth, fifo_size & 0xffff);
+ last_fifo_depth += (fifo_size & 0xffff);
+ if (dwc->tx_fifo_size &&
+ (last_fifo_depth >= dwc->tx_fifo_size)) {
+ /*
+ * Fifo size allocated exceeded available RAM size.
+ * Hence return error.
+ */
+ dev_err(dwc->dev, "Fifosize(%d) > available RAM(%d)\n",
+ last_fifo_depth, dwc->tx_fifo_size);
+ return -ENOMEM;
+ }
+
dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
fifo_size);
- last_fifo_depth += (fifo_size & 0xffff);
}
return 0;
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 9b38ed3..bbb206d 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -1776,11 +1776,18 @@
config->fsg.nluns = 1;
name[0] = "lun";
if (dev->pdata && dev->pdata->cdrom) {
- config->fsg.nluns = 2;
- config->fsg.luns[1].cdrom = 1;
- config->fsg.luns[1].ro = 1;
- config->fsg.luns[1].removable = 0;
- name[1] = "lun0";
+ config->fsg.luns[config->fsg.nluns].cdrom = 1;
+ config->fsg.luns[config->fsg.nluns].ro = 1;
+ config->fsg.luns[config->fsg.nluns].removable = 0;
+ name[config->fsg.nluns] = "lun0";
+ config->fsg.nluns++;
+ }
+ if (dev->pdata && dev->pdata->internal_ums) {
+ config->fsg.luns[config->fsg.nluns].cdrom = 0;
+ config->fsg.luns[config->fsg.nluns].ro = 0;
+ config->fsg.luns[config->fsg.nluns].removable = 1;
+ name[config->fsg.nluns] = "lun1";
+ config->fsg.nluns++;
}
config->fsg.luns[0].removable = 1;
@@ -2899,6 +2906,8 @@
&pdata->swfi_latency);
pdata->cdrom = of_property_read_bool(pdev->dev.of_node,
"qcom,android-usb-cdrom");
+ pdata->internal_ums = of_property_read_bool(pdev->dev.of_node,
+ "qcom,android-usb-internal-ums");
} else {
pdata = pdev->dev.platform_data;
}
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index a4192ca..6d7dd3d 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -151,7 +151,7 @@
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* the following 2 values can be tweaked if necessary */
- /* .bMaxBurst = 0, */
+ .bMaxBurst = 2,
/* .bmAttributes = 0, */
};
@@ -168,7 +168,7 @@
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* the following 2 values can be tweaked if necessary */
- /* .bMaxBurst = 0, */
+ .bMaxBurst = 2,
/* .bmAttributes = 0, */
};
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index 3b94dd5..f649248 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -395,6 +395,7 @@
goto fail;
}
}
+ dwc3_tx_fifo_resize_request(qdss->data, true);
return 0;
fail:
@@ -406,8 +407,11 @@
static void qdss_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct f_qdss *qdss = func_to_qdss(f);
+
pr_debug("qdss_unbind\n");
+ dwc3_tx_fifo_resize_request(qdss->data, false);
clear_eps(f);
clear_desc(c->cdev->gadget, f);
}
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 1c8664c..ebe8c6e 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -516,7 +516,6 @@
/* explicitly set the driver mode to raw */
tty->raw = 1;
tty->real_raw = 1;
- tty->update_room_in_ldisc = 1;
set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
dbg("%s", __func__);
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 017fa8e..ba14d67 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -16,7 +16,7 @@
obj-$(CONFIG_DEBUG_FS) += mdss_debug.o
endif
-dsi-v2-objs = dsi_v2.o dsi_host_v2.o dsi_io_v2.o dsi_panel_v2.o
+dsi-v2-objs = dsi_v2.o dsi_host_v2.o dsi_io_v2.o
obj-$(CONFIG_FB_MSM_MDSS) += dsi-v2.o
mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 5554085..5264005 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -482,6 +482,8 @@
if (rc == 0) {
pr_err("DSI command transaction time out\n");
rc = -ETIME;
+ } else if (!IS_ERR_VALUE(rc)) {
+ rc = 0;
}
dma_unmap_single(&dsi_host_private->dis_dev, tp->dmap, size,
@@ -524,7 +526,7 @@
{
struct dsi_cmd_desc *cm;
u32 dsi_ctrl, ctrl;
- int i, video_mode;
+ int i, video_mode, rc = 0;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
/* turn on cmd mode
@@ -546,8 +548,13 @@
dsi_buf_init(tp);
dsi_cmd_dma_add(tp, cm);
msm_dsi_cmd_dma_tx(tp);
- if (cm->wait)
- msleep(cm->wait);
+ rc = msm_dsi_cmd_dma_tx(tp);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("%s: failed to call cmd_dma_tx\n", __func__);
+ break;
+ }
+ if (cm->dchdr.wait)
+ msleep(cm->dchdr.wait);
cm++;
}
@@ -555,15 +562,15 @@
if (video_mode)
MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
- return 0;
+ return rc;
}
/* MDSS_DSI_MRPS, Maximum Return Packet Size */
static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
static struct dsi_cmd_desc pkt_size_cmd[] = {
- {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
- sizeof(max_pktsize), max_pktsize}
+ {{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
+ sizeof(max_pktsize)}, max_pktsize}
};
/*
@@ -582,7 +589,7 @@
struct dsi_buf *tp, struct dsi_buf *rp,
struct dsi_cmd_desc *cmds, int rlen)
{
- int cnt, len, diff, pkt_size;
+ int cnt, len, diff, pkt_size, rc = 0;
char cmd;
if (pdata->panel_info.mipi.no_max_pkt_size)
@@ -594,8 +601,8 @@
if (len <= 2) {
cnt = 4; /* short read */
} else {
- if (len > DSI_LEN)
- len = DSI_LEN; /* 8 bytes at most */
+ if (len > MDSS_DSI_LEN)
+ len = MDSS_DSI_LEN; /* 8 bytes at most */
len = ALIGN(len, 4); /* len 4 bytes align */
diff = len - rlen;
@@ -618,7 +625,13 @@
max_pktsize[0] = pkt_size;
dsi_buf_init(tp);
dsi_cmd_dma_add(tp, pkt_size_cmd);
- msm_dsi_cmd_dma_tx(tp);
+ rc = msm_dsi_cmd_dma_tx(tp);
+ if (IS_ERR_VALUE(rc)) {
+ msm_dsi_disable_irq();
+ pr_err("%s: dma_tx failed\n", __func__);
+ rp->len = 0;
+ goto end;
+ }
pr_debug("%s: Max packet size sent\n", __func__);
}
@@ -627,6 +640,12 @@
/* transmit read comamnd to client */
msm_dsi_cmd_dma_tx(tp);
+ if (IS_ERR_VALUE(rc)) {
+ msm_dsi_disable_irq();
+ pr_err("%s: dma_tx failed\n", __func__);
+ rp->len = 0;
+ goto end;
+ }
/*
* once cmd_dma_done interrupt received,
* return data from client is ready and stored
@@ -680,6 +699,7 @@
break;
}
+end:
return rp->len;
}
@@ -743,12 +763,18 @@
u32 dummy_xres, dummy_yres;
u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
pr_debug("msm_dsi_on\n");
pinfo = &pdata->panel_info;
- ret = msm_dsi_regulator_enable();
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ ret = msm_dss_enable_vreg(
+ ctrl_pdata->power_data.vreg_config,
+ ctrl_pdata->power_data.num_vreg, 1);
if (ret) {
pr_err("%s: DSI power on failed\n", __func__);
return ret;
@@ -843,6 +869,16 @@
static int msm_dsi_off(struct mdss_panel_data *pdata)
{
int ret = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ ret = -EINVAL;
+ return ret;
+ }
+
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
pr_debug("msm_dsi_off\n");
msm_dsi_controller_cfg(0);
@@ -852,7 +888,9 @@
msm_dsi_phy_off(dsi_host_private->dsi_base);
msm_dsi_ahb_ctrl(0);
- ret = msm_dsi_regulator_disable();
+ ret = msm_dss_enable_vreg(
+ ctrl_pdata->power_data.vreg_config,
+ ctrl_pdata->power_data.num_vreg, 0);
if (ret) {
pr_err("%s: Panel power off failed\n", __func__);
return ret;
@@ -865,11 +903,24 @@
{
struct mdss_panel_info *pinfo;
int ret = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ ret = -EINVAL;
+ return ret;
+ }
+
pr_debug("%s:\n", __func__);
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
pinfo = &pdata->panel_info;
- ret = msm_dsi_regulator_enable();
+ ret = msm_dss_enable_vreg(
+ ctrl_pdata->power_data.vreg_config,
+ ctrl_pdata->power_data.num_vreg, 1);
if (ret) {
pr_err("%s: DSI power on failed\n", __func__);
return ret;
@@ -912,11 +963,109 @@
return rc;
}
+static int dsi_get_panel_cfg(char *panel_cfg)
+{
+ int rc;
+ struct mdss_panel_cfg *pan_cfg = NULL;
+
+ if (!panel_cfg)
+ return MDSS_PANEL_INTF_INVALID;
+
+ pan_cfg = mdp3_panel_intf_type(MDSS_PANEL_INTF_DSI);
+ if (IS_ERR(pan_cfg)) {
+ panel_cfg[0] = 0;
+ return PTR_ERR(pan_cfg);
+ } else if (!pan_cfg) {
+ panel_cfg[0] = 0;
+ return 0;
+ }
+
+ pr_debug("%s:%d: cfg:[%s]\n", __func__, __LINE__,
+ pan_cfg->arg_cfg);
+ rc = strlcpy(panel_cfg, pan_cfg->arg_cfg,
+ MDSS_MAX_PANEL_LEN);
+ return rc;
+}
+
+/**
+ * dsi_find_panel_of_node(): find device node of dsi panel
+ * @pdev: platform_device of the dsi ctrl node
+ * @panel_cfg: string containing intf specific config data
+ *
+ * Function finds the panel device node using the interface
+ * specific configuration data. This configuration data is
+ * could be derived from the result of bootloader's GCDB
+ * panel detection mechanism. If such config data doesn't
+ * exist then this panel returns the default panel configured
+ * in the device tree.
+ *
+ * returns pointer to panel node on success, NULL on error.
+ */
+static struct device_node *dsi_find_panel_of_node(
+ struct platform_device *pdev, char *panel_cfg)
+{
+ int l;
+ char *panel_name;
+ struct device_node *dsi_pan_node = NULL, *mdss_node = NULL;
+
+ if (!panel_cfg)
+ return NULL;
+
+ l = strlen(panel_cfg);
+ if (!l) {
+ /* no panel cfg chg, parse dt */
+ pr_debug("%s:%d: no cmd line cfg present\n",
+ __func__, __LINE__);
+ dsi_pan_node = of_parse_phandle(
+ pdev->dev.of_node,
+ "qcom,dsi-pref-prim-pan", 0);
+ if (!dsi_pan_node) {
+ pr_err("%s:can't find panel phandle\n",
+ __func__);
+ return NULL;
+ }
+ } else {
+ if (panel_cfg[0] != '0') {
+ pr_err("%s:%d:ctrl id=[%d] not supported\n",
+ __func__, __LINE__, panel_cfg[0]);
+ return NULL;
+ }
+ /*
+ * skip first two chars '<dsi_ctrl_id>' and
+ * ':' to get to the panel name
+ */
+ panel_name = panel_cfg + 2;
+ pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
+ panel_cfg, panel_name);
+
+ mdss_node = of_parse_phandle(pdev->dev.of_node,
+ "qcom,mdss-mdp", 0);
+
+ if (!mdss_node) {
+ pr_err("%s: %d: mdss_node null\n",
+ __func__, __LINE__);
+ return NULL;
+ }
+ dsi_pan_node = of_find_node_by_name(mdss_node,
+ panel_name);
+ if (!dsi_pan_node) {
+ pr_err("%s: invalid pan node\n",
+ __func__);
+ return NULL;
+ }
+ }
+ return dsi_pan_node;
+}
static int __devinit msm_dsi_probe(struct platform_device *pdev)
{
struct dsi_interface intf;
+ char panel_cfg[MDSS_MAX_PANEL_LEN];
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
int rc = 0;
+ struct device_node *dsi_pan_node = NULL;
+ bool cmd_cfg_cont_splash = false;
+ struct resource *mdss_dsi_mres;
pr_debug("%s\n", __func__);
@@ -924,61 +1073,103 @@
if (rc)
return rc;
- if (pdev->dev.of_node) {
- struct resource *mdss_dsi_mres;
- pdev->id = 0;
- mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mdss_dsi_mres) {
- pr_err("%s:%d unable to get the MDSS reg resources",
- __func__, __LINE__);
- return -ENOMEM;
- } else {
- dsi_host_private->dsi_reg_size =
- resource_size(mdss_dsi_mres);
- dsi_host_private->dsi_base = ioremap(
- mdss_dsi_mres->start,
- dsi_host_private->dsi_reg_size);
- if (!dsi_host_private->dsi_base) {
- pr_err("%s:%d unable to remap dsi resources",
- __func__, __LINE__);
- return -ENOMEM;
- }
- }
-
- mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!mdss_dsi_mres || mdss_dsi_mres->start == 0) {
- pr_err("%s:%d unable to get the MDSS irq resources",
- __func__, __LINE__);
- rc = -ENODEV;
- goto dsi_probe_error;
- } else {
- rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start);
- if (rc) {
- dev_err(&pdev->dev,
- "%s: failed to init irq, rc=%d\n",
- __func__, rc);
- goto dsi_probe_error;
- }
- }
-
- rc = msm_dsi_io_init(pdev);
- if (rc) {
- dev_err(&pdev->dev,
- "%s: failed to init DSI IO, rc=%d\n",
- __func__, rc);
- goto dsi_probe_error;
- }
-
- rc = of_platform_populate(pdev->dev.of_node,
- NULL, NULL, &pdev->dev);
- if (rc) {
- dev_err(&pdev->dev,
- "%s: failed to add child nodes, rc=%d\n",
- __func__, rc);
- goto dsi_probe_error;
- }
-
+ if (!pdev->dev.of_node) {
+ pr_err("%s: Device node is not accessible\n", __func__);
+ rc = -ENODEV;
+ goto error_no_mem;
}
+ pdev->id = 0;
+
+ ctrl_pdata = platform_get_drvdata(pdev);
+ if (!ctrl_pdata) {
+ ctrl_pdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
+ if (!ctrl_pdata) {
+ pr_err("%s: FAILED: cannot alloc dsi ctrl\n", __func__);
+ rc = -ENOMEM;
+ goto error_no_mem;
+ }
+ platform_set_drvdata(pdev, ctrl_pdata);
+ }
+
+ mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mdss_dsi_mres) {
+ pr_err("%s:%d unable to get the MDSS reg resources",
+ __func__, __LINE__);
+ rc = -ENOMEM;
+ goto error_io_resource;
+ } else {
+ dsi_host_private->dsi_reg_size = resource_size(mdss_dsi_mres);
+ dsi_host_private->dsi_base = ioremap(mdss_dsi_mres->start,
+ dsi_host_private->dsi_reg_size);
+ if (!dsi_host_private->dsi_base) {
+ pr_err("%s:%d unable to remap dsi resources",
+ __func__, __LINE__);
+ rc = -ENOMEM;
+ goto error_io_resource;
+ }
+ }
+
+ mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!mdss_dsi_mres || mdss_dsi_mres->start == 0) {
+ pr_err("%s:%d unable to get the MDSS irq resources",
+ __func__, __LINE__);
+ rc = -ENODEV;
+ goto error_irq_resource;
+ } else {
+ rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start);
+ if (rc) {
+ dev_err(&pdev->dev, "%s: failed to init irq, rc=%d\n",
+ __func__, rc);
+ goto error_irq_resource;
+ }
+ }
+
+ rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+ if (rc) {
+ dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n",
+ __func__, rc);
+ goto error_platform_pop;
+ }
+
+ /* DSI panels can be different between controllers */
+ rc = dsi_get_panel_cfg(panel_cfg);
+ if (!rc)
+ /* dsi panel cfg not present */
+ pr_warn("%s:%d:dsi specific cfg not present\n",
+ __func__, __LINE__);
+
+ /* find panel device node */
+ dsi_pan_node = dsi_find_panel_of_node(pdev, panel_cfg);
+ if (!dsi_pan_node) {
+ pr_err("%s: can't find panel node %s\n", __func__,
+ panel_cfg);
+ goto error_pan_node;
+ }
+
+ cmd_cfg_cont_splash = mdp3_panel_get_boot_cfg() ? true : false;
+
+ rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, cmd_cfg_cont_splash);
+ if (rc) {
+ pr_err("%s: dsi panel init failed\n", __func__);
+ goto error_pan_node;
+ }
+
+ rc = dsi_ctrl_config_init(pdev, ctrl_pdata);
+ if (rc) {
+ dev_err(&pdev->dev, "%s: failed to parse mdss dtsi rc=%d\n",
+ __func__, rc);
+ goto error_pan_node;
+ }
+
+ rc = msm_dsi_io_init(pdev, &(ctrl_pdata->power_data));
+ if (rc) {
+ dev_err(&pdev->dev, "%s: failed to init DSI IO, rc=%d\n",
+ __func__, rc);
+ goto error_io_init;
+ }
+
+ pr_debug("%s: Dsi Ctrl->0 initialized\n", __func__);
dsi_host_private->dis_dev = pdev->dev;
intf.on = msm_dsi_on;
@@ -992,25 +1183,51 @@
dsi_register_interface(&intf);
msm_dsi_debug_init();
+
+ rc = dsi_panel_device_register_v2(pdev, ctrl_pdata);
+ if (rc) {
+ pr_err("%s: dsi panel dev reg failed\n", __func__);
+ goto error_device_register;
+ }
pr_debug("%s success\n", __func__);
return 0;
-dsi_probe_error:
+error_device_register:
+ msm_dsi_io_deinit(pdev, &(ctrl_pdata->power_data));
+error_io_init:
+ dsi_ctrl_config_deinit(pdev, ctrl_pdata);
+error_pan_node:
+ of_node_put(dsi_pan_node);
+error_platform_pop:
+ msm_dsi_disable_irq();
+error_irq_resource:
if (dsi_host_private->dsi_base) {
iounmap(dsi_host_private->dsi_base);
dsi_host_private->dsi_base = NULL;
}
- msm_dsi_io_deinit();
+error_io_resource:
+ devm_kfree(&pdev->dev, ctrl_pdata);
+error_no_mem:
msm_dsi_deinit();
+
return rc;
}
static int __devexit msm_dsi_remove(struct platform_device *pdev)
{
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev);
+ if (!ctrl_pdata) {
+ pr_err("%s: no driver data\n", __func__);
+ return -ENODEV;
+ }
+
msm_dsi_disable_irq();
- msm_dsi_io_deinit();
+ msm_dsi_io_deinit(pdev, &(ctrl_pdata->power_data));
+ dsi_ctrl_config_deinit(pdev, ctrl_pdata);
iounmap(dsi_host_private->dsi_base);
dsi_host_private->dsi_base = NULL;
msm_dsi_deinit();
+ devm_kfree(&pdev->dev, ctrl_pdata);
+
return 0;
}
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
index 365c32f..2c2b3d1 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.c
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -24,7 +24,6 @@
#include "dsi_host_v2.h"
struct msm_dsi_io_private {
- struct regulator *vdda_vreg;
struct clk *dsi_byte_clk;
struct clk *dsi_esc_clk;
struct clk *dsi_pixel_clk;
@@ -51,7 +50,7 @@
}
}
-int msm_dsi_io_init(struct platform_device *dev)
+int msm_dsi_io_init(struct platform_device *pdev, struct dss_module_power *mp)
{
int rc;
@@ -64,25 +63,29 @@
}
}
- rc = msm_dsi_clk_init(dev);
+ rc = msm_dsi_clk_init(pdev);
if (rc) {
pr_err("fail to initialize DSI clock\n");
return rc;
}
- rc = msm_dsi_regulator_init(dev);
+ rc = msm_dss_config_vreg(&pdev->dev, mp->vreg_config,
+ mp->num_vreg, 1);
if (rc) {
pr_err("fail to initialize DSI regulator\n");
return rc;
}
+
return 0;
}
-void msm_dsi_io_deinit(void)
+void msm_dsi_io_deinit(struct platform_device *pdev,
+ struct dss_module_power *mp)
{
if (dsi_io_private) {
msm_dsi_clk_deinit();
- msm_dsi_regulator_deinit();
+ msm_dss_config_vreg(&pdev->dev, mp->vreg_config,
+ mp->num_vreg, 0);
kfree(dsi_io_private);
dsi_io_private = NULL;
}
@@ -242,61 +245,6 @@
return 0;
}
-int msm_dsi_regulator_init(struct platform_device *dev)
-{
- int ret = 0;
-
- dsi_io_private->vdda_vreg = devm_regulator_get(&dev->dev, "vdda");
- if (IS_ERR(dsi_io_private->vdda_vreg)) {
- ret = PTR_ERR(dsi_io_private->vdda_vreg);
- pr_err("could not get vdda 8110_l4, ret=%d\n", ret);
- return ret;
- }
-
- ret = regulator_set_voltage(dsi_io_private->vdda_vreg, DSI_VDDA_VOLTAGE,
- DSI_VDDA_VOLTAGE);
- if (ret)
- pr_err("vdd_io_vreg->set_voltage failed, ret=%d\n", ret);
-
- return ret;
-}
-
-void msm_dsi_regulator_deinit(void)
-{
- if (!IS_ERR(dsi_io_private->vdda_vreg)) {
- devm_regulator_put(dsi_io_private->vdda_vreg);
- dsi_io_private->vdda_vreg = NULL;
- }
-}
-
-int msm_dsi_regulator_enable(void)
-{
- int ret;
-
- ret = regulator_enable(dsi_io_private->vdda_vreg);
- if (ret) {
- pr_err("%s: Failed to enable regulator.\n", __func__);
- return ret;
- }
- msleep(20); /*per DSI controller spec*/
- return ret;
-}
-
-int msm_dsi_regulator_disable(void)
-{
- int ret;
-
- ret = regulator_disable(dsi_io_private->vdda_vreg);
- if (ret) {
- pr_err("%s: Failed to disable regulator.\n", __func__);
- return ret;
- }
- wmb();
- msleep(20); /*per DSI controller spec*/
-
- return ret;
-}
-
static void msm_dsi_phy_strength_init(unsigned char *ctrl_base,
struct mdss_dsi_phy_ctrl *pd)
{
@@ -362,12 +310,12 @@
for (ln = 0; ln < 5; ln++) {
unsigned char *off = ctrl_base + 0x0300 + (ln * 0x40);
index = ln * 6;
- MIPI_OUTP(off, pd->laneCfg[index]);
- MIPI_OUTP(off + 4, pd->laneCfg[index + 1]);
- MIPI_OUTP(off + 8, pd->laneCfg[index + 2]);
- MIPI_OUTP(off + 12, pd->laneCfg[index + 3]);
- MIPI_OUTP(off + 20, pd->laneCfg[index + 4]);
- MIPI_OUTP(off + 24, pd->laneCfg[index + 5]);
+ MIPI_OUTP(off, pd->lanecfg[index]);
+ MIPI_OUTP(off + 4, pd->lanecfg[index + 1]);
+ MIPI_OUTP(off + 8, pd->lanecfg[index + 2]);
+ MIPI_OUTP(off + 12, pd->lanecfg[index + 3]);
+ MIPI_OUTP(off + 20, pd->lanecfg[index + 4]);
+ MIPI_OUTP(off + 24, pd->lanecfg[index + 5]);
}
wmb();
}
@@ -386,9 +334,9 @@
static void msm_dsi_phy_bist_init(unsigned char *ctrl_base,
struct mdss_dsi_phy_ctrl *pd)
{
- MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL4, pd->bistCtrl[4]);
- MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL1, pd->bistCtrl[1]);
- MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL0, pd->bistCtrl[0]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL4, pd->bistctrl[4]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL1, pd->bistctrl[1]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL0, pd->bistctrl[0]);
MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL4, 0);
wmb();
}
@@ -398,7 +346,7 @@
{
struct mdss_dsi_phy_ctrl *pd;
- pd = pdata->panel_info.mipi.dsi_phy_db;
+ pd = &(pdata->panel_info.mipi.dsi_phy_db);
msm_dsi_phy_strength_init(ctrl_base, pd);
diff --git a/drivers/video/msm/mdss/dsi_io_v2.h b/drivers/video/msm/mdss/dsi_io_v2.h
index a7d43a0..fd1c41e 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.h
+++ b/drivers/video/msm/mdss/dsi_io_v2.h
@@ -17,9 +17,11 @@
void msm_dsi_ahb_ctrl(int enable);
-int msm_dsi_io_init(struct platform_device *dev);
+int msm_dsi_io_init(struct platform_device *dev,
+ struct dss_module_power *mp);
-void msm_dsi_io_deinit(void);
+void msm_dsi_io_deinit(struct platform_device *dev,
+ struct dss_module_power *mp);
int msm_dsi_clk_init(struct platform_device *dev);
@@ -38,14 +40,6 @@
int msm_dsi_clk_disable(void);
-int msm_dsi_regulator_init(struct platform_device *dev);
-
-void msm_dsi_regulator_deinit(void);
-
-int msm_dsi_regulator_enable(void);
-
-int msm_dsi_regulator_disable(void);
-
int msm_dsi_phy_init(unsigned char *ctrl_base,
struct mdss_panel_data *pdata);
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
deleted file mode 100644
index b1a4293..0000000
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/of_device.h>
-#include <linux/qpnp/pin.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/leds.h>
-#include <linux/err.h>
-#include <linux/regulator/consumer.h>
-
-#include "dsi_v2.h"
-
-#define DT_CMD_HDR 6
-
-struct dsi_panel_private {
- struct dsi_buf dsi_panel_tx_buf;
- struct dsi_buf dsi_panel_rx_buf;
-
- int rst_gpio;
- int disp_en_gpio;
- int video_mode_gpio;
- int te_gpio;
- char bl_ctrl;
-
- struct regulator *vddio_vreg;
- struct regulator *vdda_vreg;
-
- struct dsi_panel_cmds_list *on_cmds_list;
- struct dsi_panel_cmds_list *off_cmds_list;
- struct mdss_dsi_phy_ctrl phy_params;
-
- char *on_cmds;
- char *off_cmds;
-};
-
-static struct dsi_panel_private *panel_private;
-
-DEFINE_LED_TRIGGER(bl_led_trigger);
-
-int dsi_panel_init(void)
-{
- int rc;
-
- if (!panel_private) {
- panel_private = kzalloc(sizeof(struct dsi_panel_private),
- GFP_KERNEL);
- if (!panel_private) {
- pr_err("fail to alloc dsi panel private data\n");
- return -ENOMEM;
- }
- }
-
- rc = dsi_buf_alloc(&panel_private->dsi_panel_tx_buf,
- ALIGN(DSI_BUF_SIZE,
- SZ_4K));
- if (rc)
- return rc;
-
- rc = dsi_buf_alloc(&panel_private->dsi_panel_rx_buf,
- ALIGN(DSI_BUF_SIZE,
- SZ_4K));
- if (rc)
- return rc;
-
- return 0;
-}
-
-void dsi_panel_deinit(void)
-{
- if (!panel_private)
- return;
-
- kfree(panel_private->dsi_panel_tx_buf.start);
- kfree(panel_private->dsi_panel_rx_buf.start);
-
- if (!IS_ERR(panel_private->vddio_vreg))
- devm_regulator_put(panel_private->vddio_vreg);
-
- if (!IS_ERR(panel_private->vdda_vreg))
- devm_regulator_put(panel_private->vdda_vreg);
-
- if (panel_private->on_cmds_list) {
- kfree(panel_private->on_cmds_list->buf);
- kfree(panel_private->on_cmds_list);
- }
- if (panel_private->off_cmds_list) {
- kfree(panel_private->off_cmds_list->buf);
- kfree(panel_private->off_cmds_list);
- }
-
- kfree(panel_private->on_cmds);
- kfree(panel_private->off_cmds);
-
- kfree(panel_private);
- panel_private = NULL;
-
- if (bl_led_trigger) {
- led_trigger_unregister_simple(bl_led_trigger);
- bl_led_trigger = NULL;
- }
-}
-int dsi_panel_power(int enable)
-{
- int ret;
- if (enable) {
- ret = regulator_enable(panel_private->vddio_vreg);
- if (ret) {
- pr_err("dsi_panel_power regulator enable vddio fail\n");
- return ret;
- }
- ret = regulator_enable(panel_private->vdda_vreg);
- if (ret) {
- pr_err("dsi_panel_power regulator enable vdda fail\n");
- return ret;
- }
- } else {
- ret = regulator_disable(panel_private->vddio_vreg);
- if (ret) {
- pr_err("dsi_panel_power regulator disable vddio fail\n");
- return ret;
- }
- ret = regulator_disable(panel_private->vdda_vreg);
- if (ret) {
- pr_err("dsi_panel_power regulator dsiable vdda fail\n");
- return ret;
- }
- }
- return 0;
-}
-
-static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
-static struct dsi_cmd_desc backlight_cmd = {
- DTYPE_DCS_WRITE1, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
-
-static void dsi_panel_bklt_dcs(struct mdss_panel_data *pdata, int level)
-{
- struct mipi_panel_info *mipi;
-
- mipi = &pdata->panel_info.mipi;
-
- pr_debug("%s: dcs level=%d\n", __func__, level);
-
- led_pwm1[1] = (unsigned char)level;
-
- if (DSI_VIDEO_MODE == mipi->mode) {
- dsi_set_tx_power_mode(0);
- dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
- &backlight_cmd,
- 1);
- dsi_set_tx_power_mode(1);
- }
-}
-
-void dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
-{
- if (pdata == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
- return;
- }
-
- if (!gpio_is_valid(panel_private->disp_en_gpio)) {
- pr_debug("%s:%d, reset line not configured\n",
- __func__, __LINE__);
- }
-
- if (!gpio_is_valid(panel_private->rst_gpio)) {
- pr_debug("%s:%d, reset line not configured\n",
- __func__, __LINE__);
- return;
- }
-
- pr_debug("%s: enable = %d\n", __func__, enable);
-
- if (enable == 2) {
- dsi_panel_power(1);
- gpio_request(panel_private->rst_gpio, "panel_reset");
- gpio_set_value(panel_private->rst_gpio, 1);
- if (gpio_is_valid(panel_private->disp_en_gpio)) {
- gpio_request(panel_private->disp_en_gpio,
- "panel_enable");
- gpio_set_value(panel_private->disp_en_gpio, 1);
- }
- if (gpio_is_valid(panel_private->video_mode_gpio)) {
- gpio_request(panel_private->video_mode_gpio,
- "panel_video_mdoe");
- if (pdata->panel_info.mipi.mode == DSI_VIDEO_MODE)
- gpio_set_value(panel_private->video_mode_gpio,
- 1);
- else
- gpio_set_value(panel_private->video_mode_gpio,
- 0);
- }
- if (gpio_is_valid(panel_private->te_gpio))
- gpio_request(panel_private->te_gpio, "panel_te");
- } else if (enable == 1) {
- dsi_panel_power(1);
- gpio_request(panel_private->rst_gpio, "panel_reset");
- gpio_set_value(panel_private->rst_gpio, 1);
- /*
- * these delay values are by experiments currently, will need
- * to move to device tree late
- */
- msleep(20);
- gpio_set_value(panel_private->rst_gpio, 0);
- udelay(200);
- gpio_set_value(panel_private->rst_gpio, 1);
- msleep(20);
- if (gpio_is_valid(panel_private->disp_en_gpio)) {
- gpio_request(panel_private->disp_en_gpio,
- "panel_enable");
- gpio_set_value(panel_private->disp_en_gpio, 1);
- }
- if (gpio_is_valid(panel_private->video_mode_gpio)) {
- gpio_request(panel_private->video_mode_gpio,
- "panel_video_mdoe");
- if (pdata->panel_info.mipi.mode == DSI_VIDEO_MODE)
- gpio_set_value(panel_private->video_mode_gpio,
- 1);
- else
- gpio_set_value(panel_private->video_mode_gpio,
- 0);
- }
- if (gpio_is_valid(panel_private->te_gpio))
- gpio_request(panel_private->te_gpio, "panel_te");
- } else {
- gpio_set_value(panel_private->rst_gpio, 0);
- gpio_free(panel_private->rst_gpio);
-
- if (gpio_is_valid(panel_private->disp_en_gpio)) {
- gpio_set_value(panel_private->disp_en_gpio, 0);
- gpio_free(panel_private->disp_en_gpio);
- }
-
- if (gpio_is_valid(panel_private->video_mode_gpio))
- gpio_free(panel_private->video_mode_gpio);
-
- if (gpio_is_valid(panel_private->te_gpio))
- gpio_free(panel_private->te_gpio);
- dsi_panel_power(0);
- }
-}
-
-static void dsi_panel_bl_ctrl(struct mdss_panel_data *pdata,
- u32 bl_level)
-{
- if (panel_private->bl_ctrl) {
- switch (panel_private->bl_ctrl) {
- case BL_WLED:
- led_trigger_event(bl_led_trigger, bl_level);
- break;
-
- case BL_DCS_CMD:
- dsi_panel_bklt_dcs(pdata, bl_level);
- break;
-
- default:
- pr_err("%s: Unknown bl_ctrl configuration\n",
- __func__);
- break;
- }
- } else
- pr_err("%s:%d, bl_ctrl not configured", __func__, __LINE__);
-}
-
-static int dsi_panel_on(struct mdss_panel_data *pdata)
-{
- struct mipi_panel_info *mipi;
-
- mipi = &pdata->panel_info.mipi;
-
- pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
- mipi->mode);
-
-
- return dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
- panel_private->on_cmds_list->buf,
- panel_private->on_cmds_list->size);
-}
-
-static int dsi_panel_off(struct mdss_panel_data *pdata)
-{
- struct mipi_panel_info *mipi;
- mipi = &pdata->panel_info.mipi;
-
- pr_debug("%s:%d, debug info\n", __func__, __LINE__);
-
-
- return dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
- panel_private->off_cmds_list->buf,
- panel_private->off_cmds_list->size);
-}
-
-static int dsi_panel_parse_gpio(struct platform_device *pdev)
-{
- struct device_node *np = pdev->dev.of_node;
- panel_private->disp_en_gpio = of_get_named_gpio(np,
- "qcom,enable-gpio", 0);
- panel_private->rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
- panel_private->video_mode_gpio = of_get_named_gpio(np,
- "qcom,mode-selection-gpio", 0);
- panel_private->te_gpio = of_get_named_gpio(np,
- "qcom,te-gpio", 0);
- return 0;
-}
-
-static int dsi_panel_parse_regulator(struct platform_device *pdev)
-{
- int ret;
- panel_private->vddio_vreg = devm_regulator_get(&pdev->dev, "vddio");
- if (IS_ERR(panel_private->vddio_vreg)) {
- pr_err("%s: could not get vddio vreg, rc=%ld\n",
- __func__, PTR_ERR(panel_private->vddio_vreg));
- return PTR_ERR(panel_private->vddio_vreg);
- }
- ret = regulator_set_voltage(panel_private->vddio_vreg,
- 1800000,
- 1800000);
- if (ret) {
- pr_err("%s: set voltage failed on vddio_vreg, rc=%d\n",
- __func__, ret);
- return ret;
- }
- panel_private->vdda_vreg = devm_regulator_get(&pdev->dev, "vdda");
- if (IS_ERR(panel_private->vdda_vreg)) {
- pr_err("%s: could not get vdda_vreg , rc=%ld\n",
- __func__, PTR_ERR(panel_private->vdda_vreg));
- return PTR_ERR(panel_private->vdda_vreg);
- }
- ret = regulator_set_voltage(panel_private->vdda_vreg,
- 2850000,
- 2850000);
- if (ret) {
- pr_err("%s: set voltage failed on vdda_vreg, rc=%d\n",
- __func__, ret);
- return ret;
- }
- return 0;
-}
-
-static int dsi_panel_parse_timing(struct platform_device *pdev,
- struct dsi_panel_common_pdata *panel_data)
-{
- struct device_node *np = pdev->dev.of_node;
- u32 res[6], tmp;
- int rc;
-
- rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
- if (rc) {
- pr_err("%s:%d, panel resolution not specified\n",
- __func__, __LINE__);
- return -EINVAL;
- }
-
- panel_data->panel_info.xres = (!rc ? res[0] : 480);
- panel_data->panel_info.yres = (!rc ? res[1] : 800);
-
- rc = of_property_read_u32_array(np, "qcom,mdss-pan-active-res", res, 2);
- if (rc == 0) {
- panel_data->panel_info.lcdc.xres_pad =
- panel_data->panel_info.xres - res[0];
- panel_data->panel_info.lcdc.yres_pad =
- panel_data->panel_info.yres - res[1];
- }
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
- if (rc) {
- pr_err("%s:%d, panel bpp not specified\n",
- __func__, __LINE__);
- return -EINVAL;
- }
- panel_data->panel_info.bpp = (!rc ? tmp : 24);
-
- rc = of_property_read_u32_array(np,
- "qcom,mdss-pan-porch-values", res, 6);
- if (rc) {
- pr_err("%s:%d, panel porch not specified\n",
- __func__, __LINE__);
- return -EINVAL;
- }
-
- panel_data->panel_info.lcdc.h_back_porch = (!rc ? res[0] : 6);
- panel_data->panel_info.lcdc.h_pulse_width = (!rc ? res[1] : 2);
- panel_data->panel_info.lcdc.h_front_porch = (!rc ? res[2] : 6);
- panel_data->panel_info.lcdc.v_back_porch = (!rc ? res[3] : 6);
- panel_data->panel_info.lcdc.v_pulse_width = (!rc ? res[4] : 2);
- panel_data->panel_info.lcdc.v_front_porch = (!rc ? res[5] : 6);
-
- return 0;
-}
-
-static int dsi_panel_parse_phy(struct platform_device *pdev,
- struct dsi_panel_common_pdata *panel_data)
-{
- struct device_node *np = pdev->dev.of_node;
- int i, len;
- const char *data;
-
- data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
- if ((!data) || (len != 6)) {
- pr_err("%s:%d, Unable to read Phy regulator settings",
- __func__, __LINE__);
- return -EINVAL;
- }
- for (i = 0; i < len; i++)
- panel_private->phy_params.regulator[i] = data[i];
-
- data = of_get_property(np, "qcom,panel-phy-timingSettings", &len);
- if ((!data) || (len != 12)) {
- pr_err("%s:%d, Unable to read Phy timing settings",
- __func__, __LINE__);
- return -EINVAL;
- }
- for (i = 0; i < len; i++)
- panel_private->phy_params.timing[i] = data[i];
-
- data = of_get_property(np, "qcom,panel-phy-strengthCtrl", &len);
- if ((!data) || (len != 2)) {
- pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
- __func__, __LINE__);
- return -EINVAL;
- }
- panel_private->phy_params.strength[0] = data[0];
- panel_private->phy_params.strength[1] = data[1];
-
- data = of_get_property(np, "qcom,panel-phy-bistCtrl", &len);
- if ((!data) || (len != 6)) {
- pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
- __func__, __LINE__);
- return -EINVAL;
- }
- for (i = 0; i < len; i++)
- panel_private->phy_params.bistCtrl[i] = data[i];
-
- data = of_get_property(np, "qcom,panel-phy-laneConfig", &len);
- if ((!data) || (len != 30)) {
- pr_err("%s:%d, Unable to read Phy lane configure settings",
- __func__, __LINE__);
- return -EINVAL;
- }
- for (i = 0; i < len; i++)
- panel_private->phy_params.laneCfg[i] = data[i];
-
- panel_data->panel_info.mipi.dsi_phy_db = &panel_private->phy_params;
- return 0;
-}
-
-static int dsi_panel_parse_init_cmds(struct platform_device *pdev,
- struct dsi_panel_common_pdata *panel_data)
-{
- struct device_node *np = pdev->dev.of_node;
- int i, len;
- int cmd_plen, data_offset;
- const char *data;
- const char *on_cmds_state, *off_cmds_state;
- int num_of_on_cmds = 0, num_of_off_cmds = 0;
-
- data = of_get_property(np, "qcom,panel-on-cmds", &len);
- if (!data) {
- pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
- return -EINVAL;
- }
-
- panel_private->on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
- if (!panel_private->on_cmds)
- return -ENOMEM;
-
- memcpy(panel_private->on_cmds, data, len);
-
- data_offset = 0;
- cmd_plen = 0;
- while ((len - data_offset) >= DT_CMD_HDR) {
- data_offset += (DT_CMD_HDR - 1);
- cmd_plen = panel_private->on_cmds[data_offset++];
- data_offset += cmd_plen;
- num_of_on_cmds++;
- }
- if (!num_of_on_cmds) {
- pr_err("%s:%d, No ON cmds specified", __func__, __LINE__);
- return -EINVAL;
- }
-
- panel_private->on_cmds_list =
- kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
- if (!panel_private->on_cmds_list)
- return -ENOMEM;
-
- panel_private->on_cmds_list->buf =
- kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
- GFP_KERNEL);
- if (!panel_private->on_cmds_list->buf)
- return -ENOMEM;
-
- data_offset = 0;
- for (i = 0; i < num_of_on_cmds; i++) {
- panel_private->on_cmds_list->buf[i].dtype =
- panel_private->on_cmds[data_offset++];
- panel_private->on_cmds_list->buf[i].last =
- panel_private->on_cmds[data_offset++];
- panel_private->on_cmds_list->buf[i].vc =
- panel_private->on_cmds[data_offset++];
- panel_private->on_cmds_list->buf[i].ack =
- panel_private->on_cmds[data_offset++];
- panel_private->on_cmds_list->buf[i].wait =
- panel_private->on_cmds[data_offset++];
- panel_private->on_cmds_list->buf[i].dlen =
- panel_private->on_cmds[data_offset++];
- panel_private->on_cmds_list->buf[i].payload =
- &panel_private->on_cmds[data_offset];
- data_offset += (panel_private->on_cmds_list->buf[i].dlen);
- }
-
- if (data_offset != len) {
- pr_err("%s:%d, Incorrect ON command entries",
- __func__, __LINE__);
- return -EINVAL;
- }
-
- panel_private->on_cmds_list->size = num_of_on_cmds;
-
- on_cmds_state = of_get_property(pdev->dev.of_node,
- "qcom,on-cmds-dsi-state", NULL);
- if (!strncmp(on_cmds_state, "DSI_LP_MODE", 11)) {
- panel_private->on_cmds_list->ctrl_state = DSI_LP_MODE;
- } else if (!strncmp(on_cmds_state, "DSI_HS_MODE", 11)) {
- panel_private->on_cmds_list->ctrl_state = DSI_HS_MODE;
- } else {
- pr_debug("%s: ON cmds state not specified. Set Default\n",
- __func__);
- panel_private->on_cmds_list->ctrl_state = DSI_LP_MODE;
- }
-
- panel_data->dsi_panel_on_cmds = panel_private->on_cmds_list;
-
- data = of_get_property(np, "qcom,panel-off-cmds", &len);
- if (!data) {
- pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
- return -EINVAL;
- }
-
- panel_private->off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
- if (!panel_private->off_cmds)
- return -ENOMEM;
-
- memcpy(panel_private->off_cmds, data, len);
-
- data_offset = 0;
- cmd_plen = 0;
- while ((len - data_offset) >= DT_CMD_HDR) {
- data_offset += (DT_CMD_HDR - 1);
- cmd_plen = panel_private->off_cmds[data_offset++];
- data_offset += cmd_plen;
- num_of_off_cmds++;
- }
- if (!num_of_off_cmds) {
- pr_err("%s:%d, No OFF cmds specified", __func__, __LINE__);
- return -ENOMEM;
- }
-
- panel_private->off_cmds_list =
- kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
- if (!panel_private->off_cmds_list)
- return -ENOMEM;
-
- panel_private->off_cmds_list->buf = kzalloc(num_of_off_cmds
- * sizeof(struct dsi_cmd_desc),
- GFP_KERNEL);
- if (!panel_private->off_cmds_list->buf)
- return -ENOMEM;
-
- data_offset = 0;
- for (i = 0; i < num_of_off_cmds; i++) {
- panel_private->off_cmds_list->buf[i].dtype =
- panel_private->off_cmds[data_offset++];
- panel_private->off_cmds_list->buf[i].last =
- panel_private->off_cmds[data_offset++];
- panel_private->off_cmds_list->buf[i].vc =
- panel_private->off_cmds[data_offset++];
- panel_private->off_cmds_list->buf[i].ack =
- panel_private->off_cmds[data_offset++];
- panel_private->off_cmds_list->buf[i].wait =
- panel_private->off_cmds[data_offset++];
- panel_private->off_cmds_list->buf[i].dlen =
- panel_private->off_cmds[data_offset++];
- panel_private->off_cmds_list->buf[i].payload =
- &panel_private->off_cmds[data_offset];
- data_offset += (panel_private->off_cmds_list->buf[i].dlen);
- }
-
- if (data_offset != len) {
- pr_err("%s:%d, Incorrect OFF command entries",
- __func__, __LINE__);
- return -EINVAL;
- }
-
- panel_private->off_cmds_list->size = num_of_off_cmds;
- off_cmds_state = of_get_property(pdev->dev.of_node,
- "qcom,off-cmds-dsi-state", NULL);
- if (!strncmp(off_cmds_state, "DSI_LP_MODE", 11)) {
- panel_private->off_cmds_list->ctrl_state =
- DSI_LP_MODE;
- } else if (!strncmp(off_cmds_state, "DSI_HS_MODE", 11)) {
- panel_private->off_cmds_list->ctrl_state = DSI_HS_MODE;
- } else {
- pr_debug("%s: ON cmds state not specified. Set Default\n",
- __func__);
- panel_private->off_cmds_list->ctrl_state = DSI_LP_MODE;
- }
-
- panel_data->dsi_panel_off_cmds = panel_private->off_cmds_list;
-
- return 0;
-}
-
-static int dsi_panel_parse_backlight(struct platform_device *pdev,
- struct dsi_panel_common_pdata *panel_data,
- char *bl_ctrl)
-{
- int rc;
- u32 res[6];
- static const char *bl_ctrl_type;
-
- bl_ctrl_type = of_get_property(pdev->dev.of_node,
- "qcom,mdss-pan-bl-ctrl", NULL);
- if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12))) {
- led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
- pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
- *bl_ctrl = BL_WLED;
- } else if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type,
- "bl_ctrl_dcs", 11))) {
- pr_debug("%s: SUCCESS-> DCS COMMAND register\n", __func__);
- *bl_ctrl = BL_DCS_CMD;
- }
- rc = of_property_read_u32_array(pdev->dev.of_node,
- "qcom,mdss-pan-bl-levels", res, 2);
- panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
- panel_data->panel_info.bl_max = (!rc ? res[1] : 255);
- return rc;
-}
-
-static int dsi_panel_parse_other(struct platform_device *pdev,
- struct dsi_panel_common_pdata *panel_data)
-{
- const char *pdest;
- u32 tmp;
- int rc;
- bool cont_splash_enabled = false;
-
- pdest = of_get_property(pdev->dev.of_node,
- "qcom,mdss-pan-dest", NULL);
- if (strlen(pdest) != 9) {
- pr_err("%s: Unknown pdest specified\n", __func__);
- return -EINVAL;
- }
- if (!strncmp(pdest, "display_1", 9)) {
- panel_data->panel_info.pdest = DISPLAY_1;
- } else if (!strncmp(pdest, "display_2", 9)) {
- panel_data->panel_info.pdest = DISPLAY_2;
- } else {
- pr_debug("%s: pdest not specified. Set Default\n",
- __func__);
- panel_data->panel_info.pdest = DISPLAY_1;
- }
-
- rc = of_property_read_u32(pdev->dev.of_node,
- "qcom,mdss-pan-underflow-clr", &tmp);
- panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
-
- cont_splash_enabled = of_property_read_bool(pdev->dev.of_node,
- "qcom,cont-splash-enabled");
- if (!cont_splash_enabled) {
- pr_debug("%s:%d Continuous splash flag not found.\n",
- __func__, __LINE__);
- panel_data->panel_info.cont_splash_enabled = 0;
- } else {
- pr_debug("%s:%d Continuous splash flag enabled.\n",
- __func__, __LINE__);
- panel_data->panel_info.cont_splash_enabled = 1;
- }
- return rc;
-}
-
-static int dsi_panel_parse_host_cfg(struct platform_device *pdev,
- struct dsi_panel_common_pdata *panel_data)
-{
- struct device_node *np = pdev->dev.of_node;
- u32 res[6], tmp;
- int rc;
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
- panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
-
- rc = of_property_read_u32(np,
- "qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
- panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
-
- rc = of_property_read_u32_array(np,
- "qcom,mdss-pan-dsi-h-power-stop", res, 3);
- panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
- panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
- panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
-
- rc = of_property_read_u32_array(np,
- "qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
- panel_data->panel_info.mipi.bllp_power_stop =
- (!rc ? res[0] : false);
- panel_data->panel_info.mipi.eof_bllp_power_stop =
- (!rc ? res[1] : false);
-
- rc = of_property_read_u32(np,
- "qcom,mdss-pan-dsi-traffic-mode", &tmp);
- panel_data->panel_info.mipi.traffic_mode =
- (!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
-
- rc = of_property_read_u32(np,
- "qcom,mdss-pan-dsi-dst-format", &tmp);
- panel_data->panel_info.mipi.dst_format =
- (!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
- panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
- panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
-
- rc = of_property_read_u32_array(np,
- "qcom,mdss-pan-dsi-data-lanes", res, 4);
- panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
- panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
- panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
- panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
- panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
-
- rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
- panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
- panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
- panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-te-sel", &tmp);
- panel_data->panel_info.mipi.te_sel = (!rc ? tmp : 1);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-insert-dcs-cmd", &tmp);
- panel_data->panel_info.mipi.insert_dcs_cmd = (!rc ? tmp : 1);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-wr-mem-continue", &tmp);
- panel_data->panel_info.mipi.wr_mem_continue = (!rc ? tmp : 0x3c);
- rc = of_property_read_u32(np, "qcom,mdss-pan-wr-mem-start", &tmp);
- panel_data->panel_info.mipi.wr_mem_start = (!rc ? tmp : 0x2c);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
- panel_data->panel_info.mipi.mdp_trigger =
- (!rc ? tmp : DSI_CMD_TRIGGER_SW);
- if (panel_data->panel_info.mipi.mdp_trigger > 6) {
- pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
- __func__, __LINE__);
- panel_data->panel_info.mipi.mdp_trigger =
- DSI_CMD_TRIGGER_SW;
- }
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
- panel_data->panel_info.mipi.dma_trigger =
- (!rc ? tmp : DSI_CMD_TRIGGER_SW);
- if (panel_data->panel_info.mipi.dma_trigger > 6) {
- pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
- __func__, __LINE__);
- panel_data->panel_info.mipi.dma_trigger =
- DSI_CMD_TRIGGER_SW;
- }
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
- panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
- return rc;
-}
-
-static int dsi_panel_parse_dt(struct platform_device *pdev,
- struct dsi_panel_common_pdata *panel_data,
- char *bl_ctrl)
-{
- int rc;
-
- rc = dsi_panel_parse_gpio(pdev);
- if (rc) {
- pr_err("fail to parse panel GPIOs\n");
- return rc;
- }
-
- rc = dsi_panel_parse_regulator(pdev);
- if (rc) {
- pr_err("fail to parse panel regulators\n");
- return rc;
- }
-
- rc = dsi_panel_parse_timing(pdev, panel_data);
- if (rc) {
- pr_err("fail to parse panel timing\n");
- return rc;
- }
-
- rc = dsi_panel_parse_phy(pdev, panel_data);
- if (rc) {
- pr_err("fail to parse DSI PHY settings\n");
- return rc;
- }
-
- rc = dsi_panel_parse_backlight(pdev, panel_data, bl_ctrl);
- if (rc) {
- pr_err("fail to parse DSI backlight\n");
- return rc;
- }
-
- rc = dsi_panel_parse_other(pdev, panel_data);
- if (rc) {
- pr_err("fail to parse DSI panel destination\n");
- return rc;
- }
-
- rc = dsi_panel_parse_host_cfg(pdev, panel_data);
- if (rc) {
- pr_err("fail to parse DSI host configs\n");
- return rc;
- }
-
- rc = dsi_panel_parse_init_cmds(pdev, panel_data);
- if (rc) {
- pr_err("fail to parse DSI init commands\n");
- return rc;
- }
-
- return 0;
-}
-
-static int __devinit dsi_panel_probe(struct platform_device *pdev)
-{
- int rc = 0;
- static struct dsi_panel_common_pdata vendor_pdata;
- static const char *panel_name;
-
- pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
- if (!pdev->dev.of_node)
- return -ENODEV;
-
- panel_name = of_get_property(pdev->dev.of_node, "label", NULL);
- if (!panel_name)
- pr_debug("%s:%d, panel name not specified\n",
- __func__, __LINE__);
- else
- pr_debug("%s: Panel Name = %s\n", __func__, panel_name);
-
- rc = dsi_panel_init();
- if (rc) {
- pr_err("dsi_panel_init failed %d\n", rc);
- goto dsi_panel_probe_error;
-
- }
- rc = dsi_panel_parse_dt(pdev, &vendor_pdata, &panel_private->bl_ctrl);
- if (rc) {
- pr_err("dsi_panel_parse_dt failed %d\n", rc);
- goto dsi_panel_probe_error;
- }
-
- vendor_pdata.on = dsi_panel_on;
- vendor_pdata.off = dsi_panel_off;
- vendor_pdata.reset = dsi_panel_reset;
- vendor_pdata.bl_fnc = dsi_panel_bl_ctrl;
-
- rc = dsi_panel_device_register_v2(pdev, &vendor_pdata,
- panel_private->bl_ctrl);
-
- if (rc) {
- pr_err("dsi_panel_device_register_v2 failed %d\n", rc);
- goto dsi_panel_probe_error;
- }
-
- return 0;
-dsi_panel_probe_error:
- dsi_panel_deinit();
- return rc;
-}
-
-static int __devexit dsi_panel_remove(struct platform_device *pdev)
-{
- dsi_panel_deinit();
- return 0;
-}
-
-
-static const struct of_device_id dsi_panel_match[] = {
- {.compatible = "qcom,dsi-panel-v2"},
- {}
-};
-
-static struct platform_driver this_driver = {
- .probe = dsi_panel_probe,
- .remove = __devexit_p(dsi_panel_remove),
- .driver = {
- .name = "dsi_v2_panel",
- .of_match_table = dsi_panel_match,
- },
-};
-
-static int __init dsi_panel_module_init(void)
-{
- return platform_driver_register(&this_driver);
-}
-module_init(dsi_panel_module_init);
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 686ec01..9ca3461 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -16,12 +16,12 @@
#include <linux/slab.h>
#include <linux/iopoll.h>
#include <linux/of_device.h>
+#include <linux/of_gpio.h>
-#include "mdss_panel.h"
#include "dsi_v2.h"
-static struct dsi_panel_common_pdata *panel_common_data;
static struct dsi_interface dsi_intf;
+static struct dsi_buf dsi_panel_tx_buf;
static int dsi_off(struct mdss_panel_data *pdata)
{
@@ -52,20 +52,24 @@
}
return rc;
}
+
static int dsi_panel_handler(struct mdss_panel_data *pdata, int enable)
{
int rc = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
pr_debug("dsi_panel_handler enable=%d\n", enable);
- if (!panel_common_data || !pdata)
+ if (!pdata)
return -ENODEV;
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
if (enable) {
- if (panel_common_data->reset)
- panel_common_data->reset(pdata, 1);
+ mdss_dsi_panel_reset(pdata, 1);
- if (panel_common_data->on)
- rc = panel_common_data->on(pdata);
+ rc = dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
+ ctrl_pdata->on_cmds.cmds,
+ ctrl_pdata->on_cmds.cmd_cnt);
if (rc)
pr_err("dsi_panel_handler panel on failed %d\n", rc);
@@ -73,11 +77,11 @@
if (dsi_intf.op_mode_config)
dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
- if (panel_common_data->off)
- panel_common_data->off(pdata);
+ dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
+ ctrl_pdata->off_cmds.cmds,
+ ctrl_pdata->off_cmds.cmd_cnt);
- if (panel_common_data->reset)
- panel_common_data->reset(pdata, 0);
+ mdss_dsi_panel_reset(pdata, 0);
}
return rc;
}
@@ -88,9 +92,6 @@
pr_debug("%s:\n", __func__);
- if (panel_common_data->reset)
- panel_common_data->reset(pdata, 2);
-
if (dsi_intf.cont_on)
rc = dsi_intf.cont_on(pdata);
@@ -106,7 +107,7 @@
{
int rc = 0;
- if (!pdata || !panel_common_data) {
+ if (!pdata) {
pr_err("%s: Invalid input data\n", __func__);
return -ENODEV;
}
@@ -134,49 +135,399 @@
return rc;
}
-static struct platform_device *get_dsi_platform_device(
- struct platform_device *dev)
+static int dsi_parse_gpio(struct platform_device *pdev,
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
- struct device_node *dsi_ctrl_np;
- struct platform_device *ctrl_pdev;
+ struct device_node *np = pdev->dev.of_node;
+ int rc = 0, i = 0;
+ u32 tmp[9];
- dsi_ctrl_np = of_parse_phandle(dev->dev.of_node,
- "qcom,dsi-ctrl-phandle", 0);
+ ctrl_pdata->disp_en_gpio = of_get_named_gpio(np,
+ "qcom,platform-enable-gpio", 0);
- if (!dsi_ctrl_np)
- return NULL;
+ if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
+ pr_err("%s:%d, Disp_en gpio not specified\n",
+ __func__, __LINE__);
+ } else {
+ rc = gpio_request(ctrl_pdata->disp_en_gpio, "disp_enable");
+ if (rc) {
+ pr_err("request reset gpio failed, rc=%d\n",
+ rc);
+ gpio_free(ctrl_pdata->disp_en_gpio);
+ return -ENODEV;
+ }
+ }
- ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
- if (!ctrl_pdev)
- return NULL;
+ if (ctrl_pdata->panel_data.panel_info.mipi.mode == DSI_CMD_MODE) {
+ ctrl_pdata->disp_te_gpio = of_get_named_gpio(np,
+ "qcom,platform-te-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+ pr_err("%s:%d, Disp_te gpio not specified\n",
+ __func__, __LINE__);
+ } else {
+ rc = gpio_request(ctrl_pdata->disp_te_gpio, "disp_te");
+ if (rc) {
+ pr_err("request TE gpio failed, rc=%d\n",
+ rc);
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ return -ENODEV;
+ }
+ rc = gpio_tlmm_config(GPIO_CFG(
+ ctrl_pdata->disp_te_gpio, 1,
+ GPIO_CFG_INPUT,
+ GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_2MA),
+ GPIO_CFG_ENABLE);
- return ctrl_pdev;
+ if (rc) {
+ pr_err("%s: unable to config tlmm = %d\n",
+ __func__, ctrl_pdata->disp_te_gpio);
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ return -ENODEV;
+ }
+
+ rc = gpio_direction_input(ctrl_pdata->disp_te_gpio);
+ if (rc) {
+ pr_err("set_direction for disp_en gpio failed, rc=%d\n",
+ rc);
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+ gpio_free(ctrl_pdata->disp_en_gpio);
+ return -ENODEV;
+ }
+ pr_debug("%s: te_gpio=%d\n", __func__,
+ ctrl_pdata->disp_te_gpio);
+ }
+ }
+
+ rc = of_property_read_u32_array(np,
+ "qcom,platform-reset-sequence", tmp, MDSS_DSI_RST_SEQ_LEN);
+ if (rc)
+ pr_err("%s:%d, unable to read gpio reset sequence\n",
+ __func__, __LINE__);
+ else
+ for (i = 0; i < MDSS_DSI_RST_SEQ_LEN; ++i)
+ ctrl_pdata->rst_seq[i] = tmp[i];
+
+ ctrl_pdata->rst_gpio = of_get_named_gpio(np,
+ "qcom,platform-reset-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
+ pr_err("%s:%d, reset gpio not specified\n",
+ __func__, __LINE__);
+ } else {
+ rc = gpio_request(ctrl_pdata->rst_gpio, "disp_rst_n");
+ if (rc) {
+ pr_err("request reset gpio failed, rc=%d\n",
+ rc);
+ gpio_free(ctrl_pdata->rst_gpio);
+ if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+ gpio_free(ctrl_pdata->disp_en_gpio);
+ if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ return -ENODEV;
+ }
+ }
+
+ if (ctrl_pdata->panel_data.panel_info.mode_gpio_state !=
+ MODE_GPIO_NOT_VALID) {
+ ctrl_pdata->mode_gpio = of_get_named_gpio(np,
+ "qcom,platform-mode-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->mode_gpio)) {
+ pr_info("%s:%d, reset gpio not specified\n",
+ __func__, __LINE__);
+ } else {
+ rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
+ if (rc) {
+ pr_err("request panel mode gpio failed,rc=%d\n",
+ rc);
+ gpio_free(ctrl_pdata->mode_gpio);
+ if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+ gpio_free(ctrl_pdata->disp_en_gpio);
+ if (gpio_is_valid(ctrl_pdata->rst_gpio))
+ gpio_free(ctrl_pdata->rst_gpio);
+ if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ return -ENODEV;
+ }
+ }
+ }
+ return 0;
}
+void dsi_ctrl_config_deinit(struct platform_device *pdev,
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+ struct dss_module_power *module_power = &(ctrl_pdata->power_data);
+ if (!module_power) {
+ pr_err("%s: invalid input\n", __func__);
+ return;
+ }
+
+ if (module_power->vreg_config) {
+ devm_kfree(&(pdev->dev), module_power->vreg_config);
+ module_power->vreg_config = NULL;
+ }
+ module_power->num_vreg = 0;
+
+ if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+ gpio_free(ctrl_pdata->disp_en_gpio);
+ if (gpio_is_valid(ctrl_pdata->rst_gpio))
+ gpio_free(ctrl_pdata->rst_gpio);
+ if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ if (gpio_is_valid(ctrl_pdata->mode_gpio))
+ gpio_free(ctrl_pdata->mode_gpio);
+}
+
+static int dsi_parse_vreg(struct device *dev, struct dss_module_power *mp)
+{
+ int i = 0, rc = 0;
+ u32 tmp = 0;
+ struct device_node *supply_node = NULL;
+ struct device_node *np = NULL;
+
+ if (!dev || !mp) {
+ pr_err("%s: invalid input\n", __func__);
+ rc = -EINVAL;
+ goto error;
+ }
+
+ np = dev->of_node;
+
+ mp->num_vreg = 0;
+ for_each_child_of_node(np, supply_node) {
+ if (!strncmp(supply_node->name, "qcom,platform-supply-entry",
+ strlen("qcom,platform-supply-entry")))
+ ++mp->num_vreg;
+ }
+ if (mp->num_vreg == 0) {
+ pr_err("%s: no vreg\n", __func__);
+ goto novreg;
+ } else {
+ pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg);
+ }
+
+ mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) *
+ mp->num_vreg, GFP_KERNEL);
+ if (!mp->vreg_config) {
+ pr_err("%s: can't alloc vreg mem\n", __func__);
+ rc = -ENOMEM;
+ goto error;
+ }
+
+ for_each_child_of_node(np, supply_node) {
+ if (!strncmp(supply_node->name, "qcom,platform-supply-entry",
+ strlen("qcom,platform-supply-entry"))) {
+ const char *st = NULL;
+ /* vreg-name */
+ rc = of_property_read_string(supply_node,
+ "qcom,supply-name", &st);
+ if (rc) {
+ pr_err("%s: error reading name. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ strlcpy(mp->vreg_config[i].vreg_name, st,
+ sizeof(mp->vreg_config[i].vreg_name));
+ /* vreg-min-voltage */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-min-voltage", &tmp);
+ if (rc) {
+ pr_err("%s: error reading min volt. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ mp->vreg_config[i].min_voltage = tmp;
+
+ /* vreg-max-voltage */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-max-voltage", &tmp);
+ if (rc) {
+ pr_err("%s: error reading max volt. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ mp->vreg_config[i].max_voltage = tmp;
+
+ /* enable-load */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-enable-load", &tmp);
+ if (rc) {
+ pr_err("%s: error reading enable load. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ mp->vreg_config[i].enable_load = tmp;
+
+ /* disable-load */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-disable-load", &tmp);
+ if (rc) {
+ pr_err("%s: error reading disable load. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ mp->vreg_config[i].disable_load = tmp;
+
+ /* pre-sleep */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-pre-on-sleep", &tmp);
+ if (rc) {
+ pr_debug("%s: error reading supply pre sleep value. rc=%d\n",
+ __func__, rc);
+ }
+ mp->vreg_config[i].pre_on_sleep = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-pre-off-sleep", &tmp);
+ if (rc) {
+ pr_debug("%s: error reading supply pre sleep value. rc=%d\n",
+ __func__, rc);
+ }
+ mp->vreg_config[i].pre_off_sleep = (!rc ? tmp : 0);
+
+ /* post-sleep */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-post-on-sleep", &tmp);
+ if (rc) {
+ pr_debug("%s: error reading supply post sleep value. rc=%d\n",
+ __func__, rc);
+ }
+ mp->vreg_config[i].post_on_sleep = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-post-off-sleep", &tmp);
+ if (rc) {
+ pr_debug("%s: error reading supply post sleep value. rc=%d\n",
+ __func__, rc);
+ }
+ mp->vreg_config[i].post_off_sleep = (!rc ? tmp : 0);
+
+ pr_debug("%s: %s min=%d, max=%d, enable=%d, disable=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
+ __func__,
+ mp->vreg_config[i].vreg_name,
+ mp->vreg_config[i].min_voltage,
+ mp->vreg_config[i].max_voltage,
+ mp->vreg_config[i].enable_load,
+ mp->vreg_config[i].disable_load,
+ mp->vreg_config[i].pre_on_sleep,
+ mp->vreg_config[i].post_on_sleep,
+ mp->vreg_config[i].pre_off_sleep,
+ mp->vreg_config[i].post_off_sleep
+ );
+ ++i;
+ }
+ }
+
+ return 0;
+
+error:
+ if (mp->vreg_config) {
+ devm_kfree(dev, mp->vreg_config);
+ mp->vreg_config = NULL;
+ }
+novreg:
+ mp->num_vreg = 0;
+
+ return rc;
+}
+
+static int dsi_parse_phy(struct platform_device *pdev,
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int i, len;
+ const char *data;
+ struct mdss_dsi_phy_ctrl *phy_db
+ = &(ctrl_pdata->panel_data.panel_info.mipi.dsi_phy_db);
+
+ data = of_get_property(np, "qcom,platform-regulator-settings", &len);
+ if ((!data) || (len != 6)) {
+ pr_err("%s:%d, Unable to read Phy regulator settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++)
+ phy_db->regulator[i] = data[i];
+
+ data = of_get_property(np, "qcom,platform-strength-ctrl", &len);
+ if ((!data) || (len != 2)) {
+ pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ phy_db->strength[0] = data[0];
+ phy_db->strength[1] = data[1];
+
+ data = of_get_property(np, "qcom,platform-bist-ctrl", &len);
+ if ((!data) || (len != 6)) {
+ pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++)
+ phy_db->bistctrl[i] = data[i];
+
+ data = of_get_property(np, "qcom,platform-lane-config", &len);
+ if ((!data) || (len != 30)) {
+ pr_err("%s:%d, Unable to read Phy lane configure settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++)
+ phy_db->lanecfg[i] = data[i];
+
+ return 0;
+}
+
+int dsi_ctrl_config_init(struct platform_device *pdev,
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+ int rc;
+
+ rc = dsi_parse_vreg(&pdev->dev, &ctrl_pdata->power_data);
+ if (rc) {
+ pr_err("%s:%d unable to get the regulator resources",
+ __func__, __LINE__);
+ return rc;
+ }
+
+ rc = dsi_parse_gpio(pdev, ctrl_pdata);
+ if (rc) {
+ pr_err("fail to parse panel GPIOs\n");
+ return rc;
+ }
+
+ rc = dsi_parse_phy(pdev, ctrl_pdata);
+ if (rc) {
+ pr_err("fail to parse DSI PHY settings\n");
+ return rc;
+ }
+
+ return 0;
+}
int dsi_panel_device_register_v2(struct platform_device *dev,
- struct dsi_panel_common_pdata *panel_data,
- char backlight_ctrl)
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
struct mipi_panel_info *mipi;
- struct platform_device *ctrl_pdev;
int rc;
u8 lanes = 0, bpp;
u32 h_period, v_period;
- static struct mdss_panel_data dsi_panel_data;
+ struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
- h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
- + (panel_data->panel_info.lcdc.h_back_porch)
- + (panel_data->panel_info.xres)
- + (panel_data->panel_info.lcdc.h_front_porch));
+ h_period = ((pinfo->lcdc.h_pulse_width)
+ + (pinfo->lcdc.h_back_porch)
+ + (pinfo->xres)
+ + (pinfo->lcdc.h_front_porch));
- v_period = ((panel_data->panel_info.lcdc.v_pulse_width)
- + (panel_data->panel_info.lcdc.v_back_porch)
- + (panel_data->panel_info.yres)
- + (panel_data->panel_info.lcdc.v_front_porch));
+ v_period = ((pinfo->lcdc.v_pulse_width)
+ + (pinfo->lcdc.v_back_porch)
+ + (pinfo->yres)
+ + (pinfo->lcdc.v_front_porch));
- mipi = &panel_data->panel_info.mipi;
+ mipi = &pinfo->mipi;
- panel_data->panel_info.type =
+ pinfo->type =
((mipi->mode == DSI_VIDEO_MODE)
? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
@@ -189,7 +540,6 @@
if (mipi->data_lane0)
lanes += 1;
-
if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
|| (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB888)
|| (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB666_LOOSE))
@@ -200,39 +550,38 @@
else
bpp = 3; /* Default format set to RGB888 */
- if (panel_data->panel_info.type == MIPI_VIDEO_PANEL &&
- !panel_data->panel_info.clk_rate) {
- h_period += panel_data->panel_info.lcdc.xres_pad;
- v_period += panel_data->panel_info.lcdc.yres_pad;
+ if (pinfo->type == MIPI_VIDEO_PANEL &&
+ !pinfo->clk_rate) {
+ h_period += pinfo->lcdc.xres_pad;
+ v_period += pinfo->lcdc.yres_pad;
if (lanes > 0) {
- panel_data->panel_info.clk_rate =
+ pinfo->clk_rate =
((h_period * v_period * (mipi->frame_rate) * bpp * 8)
/ lanes);
} else {
pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
- panel_data->panel_info.clk_rate =
+ pinfo->clk_rate =
(h_period * v_period
* (mipi->frame_rate) * bpp * 8);
}
}
- ctrl_pdev = get_dsi_platform_device(dev);
- if (!ctrl_pdev)
- return -EPROBE_DEFER;
+ ctrl_pdata->panel_data.event_handler = dsi_event_handler;
- dsi_panel_data.event_handler = dsi_event_handler;
+ rc = dsi_buf_alloc(&dsi_panel_tx_buf,
+ ALIGN(DSI_BUF_SIZE,
+ SZ_4K));
+ if (rc)
+ return rc;
- dsi_panel_data.panel_info = panel_data->panel_info;
-
- dsi_panel_data.set_backlight = panel_data->bl_fnc;
- panel_common_data = panel_data;
/*
* register in mdp driver
*/
- rc = mdss_register_panel(ctrl_pdev, &dsi_panel_data);
+ rc = mdss_register_panel(dev, &(ctrl_pdata->panel_data));
if (rc) {
dev_err(&dev->dev, "unable to register MIPI DSI panel\n");
+ kfree(dsi_panel_tx_buf.start);
return rc;
}
@@ -340,15 +689,16 @@
char *bp;
u32 *hp;
int i, len;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
/* fill up payload */
if (cm->payload) {
- len = cm->dlen;
+ len = dchdr->dlen;
len += 3;
len &= ~0x03; /* multipled by 4 */
- for (i = 0; i < cm->dlen; i++)
+ for (i = 0; i < dchdr->dlen; i++)
*bp++ = cm->payload[i];
/* append 0xff to the end */
@@ -361,11 +711,11 @@
/* fill up header */
hp = dp->hdr;
*hp = 0;
- *hp = DSI_HDR_WC(cm->dlen);
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp = DSI_HDR_WC(dchdr->dlen);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_LONG_PKT;
*hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -380,8 +730,9 @@
{
u32 *hp;
int len;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
- if (cm->dlen && cm->payload == 0) {
+ if (dchdr->dlen && cm->payload == 0) {
pr_err("%s: NO payload error\n", __func__);
return 0;
}
@@ -389,11 +740,11 @@
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
- if (cm->last)
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
- len = (cm->dlen > 2) ? 2 : cm->dlen;
+ len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
if (len == 1) {
*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
@@ -421,8 +772,9 @@
{
u32 *hp;
int len;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
- if (cm->dlen && cm->payload == 0) {
+ if (dchdr->dlen && cm->payload == 0) {
pr_err("%s: NO payload error\n", __func__);
return 0;
}
@@ -430,12 +782,12 @@
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_BTA;
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
- len = (cm->dlen > 2) ? 2 : cm->dlen;
+ len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
if (len == 1) {
*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
@@ -463,6 +815,7 @@
char *bp;
u32 *hp;
int i, len;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
@@ -471,10 +824,10 @@
* dcs command byte (first byte) followed by payload
*/
if (cm->payload) {
- len = cm->dlen;
+ len = dchdr->dlen;
len += 3;
len &= ~0x03; /* multipled by 4 */
- for (i = 0; i < cm->dlen; i++)
+ for (i = 0; i < dchdr->dlen; i++)
*bp++ = cm->payload[i];
/* append 0xff to the end */
@@ -487,11 +840,11 @@
/* fill up header */
hp = dp->hdr;
*hp = 0;
- *hp = DSI_HDR_WC(cm->dlen);
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp = DSI_HDR_WC(dchdr->dlen);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_LONG_PKT;
*hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -506,6 +859,7 @@
{
u32 *hp;
int len;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
if (cm->payload == 0) {
pr_err("%s: NO payload error\n", __func__);
@@ -515,13 +869,13 @@
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
- if (cm->ack)
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ if (dchdr->ack)
*hp |= DSI_HDR_BTA;
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
- len = (cm->dlen > 1) ? 1 : cm->dlen;
+ len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
@@ -537,8 +891,9 @@
static int dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
- if (cm->dlen < 2 || cm->payload == 0) {
+ if (dchdr->dlen < 2 || cm->payload == 0) {
pr_err("%s: NO payload error\n", __func__);
return -EINVAL;
}
@@ -546,10 +901,10 @@
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
- if (cm->ack)
+ *hp |= DSI_HDR_VC(dchdr->vc);
+ if (dchdr->ack)
*hp |= DSI_HDR_BTA;
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
@@ -567,6 +922,7 @@
static int dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
if (cm->payload == 0) {
pr_err("%s: NO payload error\n", __func__);
@@ -576,10 +932,10 @@
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_BTA;
*hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
@@ -593,13 +949,14 @@
static int dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -610,13 +967,14 @@
static int dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -627,13 +985,14 @@
static int dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -644,13 +1003,14 @@
static int dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -661,6 +1021,7 @@
static int dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
if (cm->payload == 0) {
pr_err("%s: NO payload error\n", __func__);
@@ -670,9 +1031,9 @@
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
*hp |= DSI_HDR_DATA1(cm->payload[0]);
@@ -686,15 +1047,16 @@
static int dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp = DSI_HDR_WC(cm->dlen);
+ *hp = DSI_HDR_WC(dchdr->dlen);
*hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -705,15 +1067,16 @@
static int dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
u32 *hp;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
hp = dp->hdr;
*hp = 0;
- *hp = DSI_HDR_WC(cm->dlen);
+ *hp = DSI_HDR_WC(dchdr->dlen);
*hp |= DSI_HDR_LONG_PKT;
- *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_VC(dchdr->vc);
*hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
- if (cm->last)
+ if (dchdr->last)
*hp |= DSI_HDR_LAST;
dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -727,8 +1090,9 @@
int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
{
int len = 0;
+ struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
- switch (cm->dtype) {
+ switch (dchdr->dtype) {
case DTYPE_GEN_WRITE:
case DTYPE_GEN_WRITE1:
case DTYPE_GEN_WRITE2:
@@ -777,7 +1141,7 @@
break;
default:
pr_debug("%s: dtype=%x NOT supported\n",
- __func__, cm->dtype);
+ __func__, dchdr->dtype);
break;
}
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index 73df790..a554856 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -11,190 +11,18 @@
*
*/
-#ifndef MDSS_DSI_H
-#define MDSS_DSI_H
+#ifndef DSI_V2_H
+#define DSI_V2_H
#include <linux/list.h>
#include <mach/scm-io.h>
+#include "mdss_dsi.h"
#include "mdss_panel.h"
-#define MIPI_OUTP(addr, data) writel_relaxed((data), (addr))
-#define MIPI_INP(addr) readl_relaxed(addr)
-
-#define MIPI_DSI_PRIM 1
-#define MIPI_DSI_SECD 2
-
-#define MIPI_DSI_PANEL_VGA 0
-#define MIPI_DSI_PANEL_WVGA 1
-#define MIPI_DSI_PANEL_WVGA_PT 2
-#define MIPI_DSI_PANEL_FWVGA_PT 3
-#define MIPI_DSI_PANEL_WSVGA_PT 4
-#define MIPI_DSI_PANEL_QHD_PT 5
-#define MIPI_DSI_PANEL_WXGA 6
-#define MIPI_DSI_PANEL_WUXGA 7
-#define MIPI_DSI_PANEL_720P_PT 8
-#define DSI_PANEL_MAX 8
-
-enum {
- DSI_VIDEO_MODE,
- DSI_CMD_MODE,
-};
-
-enum {
- ST_DSI_CLK_OFF,
- ST_DSI_SUSPEND,
- ST_DSI_RESUME,
- ST_DSI_PLAYING,
- ST_DSI_NUM
-};
-
-enum {
- EV_DSI_UPDATE,
- EV_DSI_DONE,
- EV_DSI_TOUT,
- EV_DSI_NUM
-};
-
-enum {
- LANDSCAPE = 1,
- PORTRAIT = 2,
-};
-
-enum {
- DSI_CMD_MODE_DMA,
- DSI_CMD_MODE_MDP,
-};
-
-enum {
- BL_PWM,
- BL_WLED,
- BL_DCS_CMD,
- UNKNOWN_CTRL,
-};
-
-enum {
- DSI_LP_MODE,
- DSI_HS_MODE,
-};
-
-#define DSI_NON_BURST_SYNCH_PULSE 0
-#define DSI_NON_BURST_SYNCH_EVENT 1
-#define DSI_BURST_MODE 2
-
-#define DSI_RGB_SWAP_RGB 0
-#define DSI_RGB_SWAP_RBG 1
-#define DSI_RGB_SWAP_BGR 2
-#define DSI_RGB_SWAP_BRG 3
-#define DSI_RGB_SWAP_GRB 4
-#define DSI_RGB_SWAP_GBR 5
-
-#define DSI_VIDEO_DST_FORMAT_RGB565 0
-#define DSI_VIDEO_DST_FORMAT_RGB666 1
-#define DSI_VIDEO_DST_FORMAT_RGB666_LOOSE 2
-#define DSI_VIDEO_DST_FORMAT_RGB888 3
-
-#define DSI_CMD_DST_FORMAT_RGB111 0
-#define DSI_CMD_DST_FORMAT_RGB332 3
-#define DSI_CMD_DST_FORMAT_RGB444 4
-#define DSI_CMD_DST_FORMAT_RGB565 6
-#define DSI_CMD_DST_FORMAT_RGB666 7
-#define DSI_CMD_DST_FORMAT_RGB888 8
-
-#define DSI_CMD_TRIGGER_NONE 0x0 /* mdp trigger */
-#define DSI_CMD_TRIGGER_TE 0x02
-#define DSI_CMD_TRIGGER_SW 0x04
-#define DSI_CMD_TRIGGER_SW_SEOF 0x05 /* cmd dma only */
-#define DSI_CMD_TRIGGER_SW_TE 0x06
-
-#define DSI_HOST_HDR_SIZE 4
-#define DSI_HDR_LAST BIT(31)
-#define DSI_HDR_LONG_PKT BIT(30)
-#define DSI_HDR_BTA BIT(29)
-#define DSI_HDR_VC(vc) (((vc) & 0x03) << 22)
-#define DSI_HDR_DTYPE(dtype) (((dtype) & 0x03f) << 16)
-#define DSI_HDR_DATA2(data) (((data) & 0x0ff) << 8)
-#define DSI_HDR_DATA1(data) ((data) & 0x0ff)
-#define DSI_HDR_WC(wc) ((wc) & 0x0ffff)
-
#define DSI_BUF_SIZE 1024
#define DSI_MRPS 0x04 /* Maximum Return Packet Size */
-#define DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
-
-struct dsi_buf {
- u32 *hdr; /* dsi host header */
- char *start; /* buffer start addr */
- char *end; /* buffer end addr */
- int size; /* size of buffer */
- char *data; /* buffer */
- int len; /* data length */
- dma_addr_t dmap; /* mapped dma addr */
-};
-
-/* dcs read/write */
-#define DTYPE_DCS_WRITE 0x05 /* short write, 0 parameter */
-#define DTYPE_DCS_WRITE1 0x15 /* short write, 1 parameter */
-#define DTYPE_DCS_READ 0x06 /* read */
-#define DTYPE_DCS_LWRITE 0x39 /* long write */
-
-/* generic read/write */
-#define DTYPE_GEN_WRITE 0x03 /* short write, 0 parameter */
-#define DTYPE_GEN_WRITE1 0x13 /* short write, 1 parameter */
-#define DTYPE_GEN_WRITE2 0x23 /* short write, 2 parameter */
-#define DTYPE_GEN_LWRITE 0x29 /* long write */
-#define DTYPE_GEN_READ 0x04 /* long read, 0 parameter */
-#define DTYPE_GEN_READ1 0x14 /* long read, 1 parameter */
-#define DTYPE_GEN_READ2 0x24 /* long read, 2 parameter */
-
-#define DTYPE_TEAR_ON 0x35 /* set tear on */
-#define DTYPE_MAX_PKTSIZE 0x37 /* set max packet size */
-#define DTYPE_NULL_PKT 0x09 /* null packet, no data */
-#define DTYPE_BLANK_PKT 0x19 /* blankiing packet, no data */
-
-#define DTYPE_CM_ON 0x02 /* color mode off */
-#define DTYPE_CM_OFF 0x12 /* color mode on */
-#define DTYPE_PERIPHERAL_OFF 0x22
-#define DTYPE_PERIPHERAL_ON 0x32
-
-/*
- * dcs response
- */
-#define DTYPE_ACK_ERR_RESP 0x02
-#define DTYPE_EOT_RESP 0x08 /* end of tx */
-#define DTYPE_GEN_READ1_RESP 0x11 /* 1 parameter, short */
-#define DTYPE_GEN_READ2_RESP 0x12 /* 2 parameter, short */
-#define DTYPE_GEN_LREAD_RESP 0x1a
-#define DTYPE_DCS_LREAD_RESP 0x1c
-#define DTYPE_DCS_READ1_RESP 0x21 /* 1 parameter, short */
-#define DTYPE_DCS_READ2_RESP 0x22 /* 2 parameter, short */
-
-struct dsi_cmd_desc {
- int dtype;
- int last;
- int vc;
- int ack; /* ask ACK from peripheral */
- int wait;
- int dlen;
- char *payload;
-};
-
-struct dsi_panel_cmds_list {
- struct dsi_cmd_desc *buf;
- int size;
- char ctrl_state;
-};
-
-struct dsi_panel_common_pdata {
- struct mdss_panel_info panel_info;
- int (*on) (struct mdss_panel_data *pdata);
- int (*off) (struct mdss_panel_data *pdata);
- void (*reset)(struct mdss_panel_data *pdata, int enable);
- void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
- struct dsi_panel_cmds_list *dsi_panel_on_cmds;
- struct dsi_panel_cmds_list *dsi_panel_off_cmds;
-};
-
struct dsi_interface {
int (*on)(struct mdss_panel_data *pdata);
int (*off)(struct mdss_panel_data *pdata);
@@ -210,8 +38,7 @@
};
int dsi_panel_device_register_v2(struct platform_device *pdev,
- struct dsi_panel_common_pdata *panel_data,
- char bl_ctrl);
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata);
void dsi_register_interface(struct dsi_interface *intf);
@@ -237,4 +64,14 @@
void dsi_set_tx_power_mode(int mode);
-#endif /* MDSS_DSI_H */
+void dsi_ctrl_config_deinit(struct platform_device *pdev,
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+
+int dsi_ctrl_config_init(struct platform_device *pdev,
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+
+struct mdss_panel_cfg *mdp3_panel_intf_type(int intf_val);
+
+int mdp3_panel_get_boot_cfg(void);
+
+#endif /* DSI_V2_H */
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 66ad706..8a5f1ee 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -15,6 +15,7 @@
#include <linux/clk.h>
#include <linux/debugfs.h>
+#include <linux/dma-buf.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -92,6 +93,10 @@
static struct msm_bus_paths
mdp_bus_ppp_usecases[ARRAY_SIZE(mdp_bus_ppp_vectors)];
+static struct mdss_panel_intf pan_types[] = {
+ {"dsi", MDSS_PANEL_INTF_DSI},
+};
+
static struct msm_bus_scale_pdata mdp_bus_ppp_scale_table = {
.usecase = mdp_bus_ppp_usecases,
.num_usecases = ARRAY_SIZE(mdp_bus_ppp_usecases),
@@ -116,8 +121,19 @@
};
struct mdp3_iommu_domain_map mdp3_iommu_domains[MDP3_IOMMU_DOMAIN_MAX] = {
- [MDP3_IOMMU_DOMAIN] = {
- .domain_type = MDP3_IOMMU_DOMAIN,
+ [MDP3_PPP_IOMMU_DOMAIN] = {
+ .domain_type = MDP3_PPP_IOMMU_DOMAIN,
+ .client_name = "mdp_ppp",
+ .partitions = {
+ {
+ .start = SZ_128K,
+ .size = SZ_1G - SZ_128K,
+ },
+ },
+ .npartitions = 1,
+ },
+ [MDP3_DMA_IOMMU_DOMAIN] = {
+ .domain_type = MDP3_DMA_IOMMU_DOMAIN,
.client_name = "mdp_dma",
.partitions = {
{
@@ -132,27 +148,27 @@
struct mdp3_iommu_ctx_map mdp3_iommu_contexts[MDP3_IOMMU_CTX_MAX] = {
[MDP3_IOMMU_CTX_PPP_0] = {
.ctx_type = MDP3_IOMMU_CTX_PPP_0,
- .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .domain = &mdp3_iommu_domains[MDP3_PPP_IOMMU_DOMAIN],
.ctx_name = "mdpe_0",
.attached = 0,
},
[MDP3_IOMMU_CTX_PPP_1] = {
.ctx_type = MDP3_IOMMU_CTX_PPP_1,
- .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .domain = &mdp3_iommu_domains[MDP3_PPP_IOMMU_DOMAIN],
.ctx_name = "mdpe_1",
.attached = 0,
},
[MDP3_IOMMU_CTX_DMA_0] = {
.ctx_type = MDP3_IOMMU_CTX_DMA_0,
- .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .domain = &mdp3_iommu_domains[MDP3_DMA_IOMMU_DOMAIN],
.ctx_name = "mdps_0",
.attached = 0,
},
[MDP3_IOMMU_CTX_DMA_1] = {
.ctx_type = MDP3_IOMMU_CTX_DMA_1,
- .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .domain = &mdp3_iommu_domains[MDP3_DMA_IOMMU_DOMAIN],
.ctx_name = "mdps_1",
.attached = 0,
},
@@ -379,7 +395,7 @@
static int mdp3_clk_update(u32 clk_idx, u32 enable)
{
- int ret = -EINVAL;
+ int ret = 0;
struct clk *clk;
int count = 0;
@@ -681,6 +697,8 @@
{
int ret;
+ mutex_init(&mdp3_res->iommu_lock);
+
ret = mdp3_iommu_domain_init();
if (ret) {
pr_err("mdp3 iommu domain init fails\n");
@@ -807,9 +825,191 @@
devm_free_irq(&mdp3_res->pdev->dev, mdp3_res->irq, mdp3_res);
}
+static int mdp3_get_pan_intf(const char *pan_intf)
+{
+ int i, rc = MDSS_PANEL_INTF_INVALID;
+
+ if (!pan_intf)
+ return rc;
+
+ for (i = 0; i < ARRAY_SIZE(pan_types); i++) {
+ if (!strncmp(pan_intf, pan_types[i].name,
+ strlen(pan_types[i].name))) {
+ rc = pan_types[i].type;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static int mdp3_parse_dt_pan_intf(struct platform_device *pdev)
+{
+ int rc;
+ struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+ const char *prim_intf = NULL;
+
+ rc = of_property_read_string(pdev->dev.of_node,
+ "qcom,mdss-pref-prim-intf", &prim_intf);
+ if (rc)
+ return -ENODEV;
+
+ rc = mdp3_get_pan_intf(prim_intf);
+ if (rc < 0) {
+ mdata->pan_cfg.pan_intf = MDSS_PANEL_INTF_INVALID;
+ } else {
+ mdata->pan_cfg.pan_intf = rc;
+ rc = 0;
+ }
+ return rc;
+}
+
+static int mdp3_get_pan_cfg(struct mdss_panel_cfg *pan_cfg)
+{
+ char *t = NULL;
+ char pan_intf_str[MDSS_MAX_PANEL_LEN];
+ int rc, i;
+ char pan_name[MDSS_MAX_PANEL_LEN];
+
+ if (!pan_cfg)
+ return -EINVAL;
+
+ strlcpy(pan_name, &pan_cfg->arg_cfg[0], sizeof(pan_cfg->arg_cfg));
+ if (pan_name[0] == '0') {
+ pan_cfg->lk_cfg = false;
+ } else if (pan_name[0] == '1') {
+ pan_cfg->lk_cfg = true;
+ } else {
+ /* read from dt */
+ pan_cfg->lk_cfg = true;
+ pan_cfg->pan_intf = MDSS_PANEL_INTF_INVALID;
+ return -EINVAL;
+ }
+
+ /* skip lk cfg and delimiter; ex: "0:" */
+ strlcpy(pan_name, &pan_name[2], MDSS_MAX_PANEL_LEN);
+ t = strnstr(pan_name, ":", MDSS_MAX_PANEL_LEN);
+ if (!t) {
+ pr_err("%s: pan_name=[%s] invalid\n",
+ __func__, pan_name);
+ pan_cfg->pan_intf = MDSS_PANEL_INTF_INVALID;
+ return -EINVAL;
+ }
+
+ for (i = 0; ((pan_name + i) < t) && (i < 4); i++)
+ pan_intf_str[i] = *(pan_name + i);
+ pan_intf_str[i] = 0;
+ pr_debug("%s:%d panel intf %s\n", __func__, __LINE__, pan_intf_str);
+ /* point to the start of panel name */
+ t = t + 1;
+ strlcpy(&pan_cfg->arg_cfg[0], t, sizeof(pan_cfg->arg_cfg));
+ pr_debug("%s:%d: t=[%s] panel name=[%s]\n", __func__, __LINE__,
+ t, pan_cfg->arg_cfg);
+ rc = mdp3_get_pan_intf(pan_intf_str);
+ pan_cfg->pan_intf = (rc < 0) ? MDSS_PANEL_INTF_INVALID : rc;
+ return 0;
+}
+
+static int mdp3_parse_bootarg(struct platform_device *pdev)
+{
+ struct device_node *chosen_node;
+ static const char *cmd_line;
+ char *disp_idx, *end_idx;
+ int rc, len = 0, name_len, cmd_len;
+ int *intf_type;
+ char *panel_name;
+ struct mdss_panel_cfg *pan_cfg;
+ struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+
+ mdata->pan_cfg.arg_cfg[MDSS_MAX_PANEL_LEN] = 0;
+ pan_cfg = &mdata->pan_cfg;
+ panel_name = &pan_cfg->arg_cfg[0];
+ intf_type = &pan_cfg->pan_intf;
+
+ /* reads from dt by default */
+ pan_cfg->lk_cfg = true;
+
+ chosen_node = of_find_node_by_name(NULL, "chosen");
+ if (!chosen_node) {
+ pr_err("%s: get chosen node failed\n", __func__);
+ rc = -ENODEV;
+ goto get_dt_pan;
+ }
+
+ cmd_line = of_get_property(chosen_node, "bootargs", &len);
+ if (!cmd_line || len <= 0) {
+ pr_err("%s: get bootargs failed\n", __func__);
+ rc = -ENODEV;
+ goto get_dt_pan;
+ }
+
+ name_len = strlen("mdss_mdp.panel=");
+ cmd_len = strlen(cmd_line);
+ disp_idx = strnstr(cmd_line, "mdss_mdp.panel=", cmd_len);
+ if (!disp_idx) {
+ pr_err("%s:%d:cmdline panel not set disp_idx=[%p]\n",
+ __func__, __LINE__, disp_idx);
+ memset(panel_name, 0x00, MDSS_MAX_PANEL_LEN);
+ *intf_type = MDSS_PANEL_INTF_INVALID;
+ rc = MDSS_PANEL_INTF_INVALID;
+ goto get_dt_pan;
+ }
+
+ disp_idx += name_len;
+
+ end_idx = strnstr(disp_idx, " ", MDSS_MAX_PANEL_LEN);
+ pr_debug("%s:%d: pan_name=[%s] end=[%s]\n", __func__, __LINE__,
+ disp_idx, end_idx);
+ if (!end_idx) {
+ end_idx = disp_idx + strlen(disp_idx) + 1;
+ pr_warn("%s:%d: pan_name=[%s] end=[%s]\n", __func__,
+ __LINE__, disp_idx, end_idx);
+ }
+
+ if (end_idx <= disp_idx) {
+ pr_err("%s:%d:cmdline pan incorrect end=[%p] disp=[%p]\n",
+ __func__, __LINE__, end_idx, disp_idx);
+ memset(panel_name, 0x00, MDSS_MAX_PANEL_LEN);
+ *intf_type = MDSS_PANEL_INTF_INVALID;
+ rc = MDSS_PANEL_INTF_INVALID;
+ goto get_dt_pan;
+ }
+
+ *end_idx = 0;
+ len = end_idx - disp_idx + 1;
+ if (len <= 0) {
+ pr_warn("%s: panel name not rx", __func__);
+ rc = -EINVAL;
+ goto get_dt_pan;
+ }
+
+ strlcpy(panel_name, disp_idx, min(++len, MDSS_MAX_PANEL_LEN));
+ pr_debug("%s:%d panel:[%s]", __func__, __LINE__, panel_name);
+ of_node_put(chosen_node);
+
+ rc = mdp3_get_pan_cfg(pan_cfg);
+ if (!rc)
+ pan_cfg->init_done = true;
+
+ return rc;
+
+get_dt_pan:
+ rc = mdp3_parse_dt_pan_intf(pdev);
+ /* if pref pan intf is not present */
+ if (rc)
+ pr_err("%s:unable to parse device tree for pan intf\n",
+ __func__);
+ else
+ pan_cfg->init_done = true;
+
+ of_node_put(chosen_node);
+ return rc;
+}
+
static int mdp3_parse_dt(struct platform_device *pdev)
{
struct resource *res;
+ int rc;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdp_phys");
if (!res) {
@@ -836,20 +1036,345 @@
}
mdp3_res->irq = res->start;
+ rc = mdp3_parse_bootarg(pdev);
+ if (rc) {
+ pr_err("%s: Error in panel override:rc=[%d]\n",
+ __func__, rc);
+ return rc;
+ }
+
return 0;
}
-int mdp3_put_img(struct mdp3_img_data *data)
+static void mdp3_iommu_heap_unmap_iommu(struct mdp3_iommu_meta *meta)
+{
+ unsigned int domain_num;
+ unsigned int partition_num = 0;
+ struct iommu_domain *domain;
+
+ domain_num = (mdp3_res->domains + MDP3_PPP_IOMMU_DOMAIN)->domain_idx;
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ pr_err("Could not get domain %d. Corruption?\n", domain_num);
+ return;
+ }
+
+ iommu_unmap_range(domain, meta->iova_addr, meta->mapped_size);
+ msm_free_iova_address(meta->iova_addr, domain_num, partition_num,
+ meta->mapped_size);
+
+ return;
+}
+
+static void mdp3_iommu_meta_destroy(struct kref *kref)
+{
+ struct mdp3_iommu_meta *meta =
+ container_of(kref, struct mdp3_iommu_meta, ref);
+
+ rb_erase(&meta->node, &mdp3_res->iommu_root);
+ mdp3_iommu_heap_unmap_iommu(meta);
+ dma_buf_put(meta->dbuf);
+ kfree(meta);
+}
+
+
+static void mdp3_iommu_meta_put(struct mdp3_iommu_meta *meta)
+{
+ /* Need to lock here to prevent race against map/unmap */
+ mutex_lock(&mdp3_res->iommu_lock);
+ kref_put(&meta->ref, mdp3_iommu_meta_destroy);
+ mutex_unlock(&mdp3_res->iommu_lock);
+}
+
+static struct mdp3_iommu_meta *mdp3_iommu_meta_lookup(struct sg_table *table)
+{
+ struct rb_root *root = &mdp3_res->iommu_root;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct mdp3_iommu_meta *entry = NULL;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct mdp3_iommu_meta, node);
+
+ if (table < entry->table)
+ p = &(*p)->rb_left;
+ else if (table > entry->table)
+ p = &(*p)->rb_right;
+ else
+ return entry;
+ }
+ return NULL;
+}
+
+void mdp3_unmap_iommu(struct ion_client *client, struct ion_handle *handle)
+{
+ struct mdp3_iommu_meta *meta;
+ struct sg_table *table;
+
+ table = ion_sg_table(client, handle);
+
+ mutex_lock(&mdp3_res->iommu_lock);
+ meta = mdp3_iommu_meta_lookup(table);
+ if (!meta) {
+ WARN(1, "%s: buffer was never mapped for %p\n", __func__,
+ handle);
+ mutex_unlock(&mdp3_res->iommu_lock);
+ goto out;
+ }
+ mutex_unlock(&mdp3_res->iommu_lock);
+
+ mdp3_iommu_meta_put(meta);
+out:
+ return;
+}
+
+static void mdp3_iommu_meta_add(struct mdp3_iommu_meta *meta)
+{
+ struct rb_root *root = &mdp3_res->iommu_root;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct mdp3_iommu_meta *entry;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct mdp3_iommu_meta, node);
+
+ if (meta->table < entry->table) {
+ p = &(*p)->rb_left;
+ } else if (meta->table > entry->table) {
+ p = &(*p)->rb_right;
+ } else {
+ pr_err("%s: handle %p already exists\n", __func__,
+ entry->handle);
+ BUG();
+ }
+ }
+
+ rb_link_node(&meta->node, parent, p);
+ rb_insert_color(&meta->node, root);
+}
+
+static int mdp3_iommu_map_iommu(struct mdp3_iommu_meta *meta,
+ unsigned long align, unsigned long iova_length,
+ unsigned int padding, unsigned long flags)
+{
+ struct iommu_domain *domain;
+ int ret = 0;
+ unsigned long size;
+ unsigned long unmap_size;
+ struct sg_table *table;
+ int prot = IOMMU_WRITE | IOMMU_READ;
+ unsigned int domain_num = (mdp3_res->domains +
+ MDP3_PPP_IOMMU_DOMAIN)->domain_idx;
+ unsigned int partition_num = 0;
+
+ size = meta->size;
+ table = meta->table;
+
+ /* Use the biggest alignment to allow bigger IOMMU mappings.
+ * Use the first entry since the first entry will always be the
+ * biggest entry. To take advantage of bigger mapping sizes both the
+ * VA and PA addresses have to be aligned to the biggest size.
+ */
+ if (sg_dma_len(table->sgl) > align)
+ align = sg_dma_len(table->sgl);
+
+ ret = msm_allocate_iova_address(domain_num, partition_num,
+ meta->mapped_size, align, &meta->iova_addr);
+
+ if (ret)
+ goto out;
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ /* Adding padding to before buffer */
+ if (padding) {
+ unsigned long phys_addr = sg_phys(table->sgl);
+ ret = msm_iommu_map_extra(domain, meta->iova_addr, phys_addr,
+ padding, SZ_4K, prot);
+ if (ret)
+ goto out1;
+ }
+
+ /* Mapping actual buffer */
+ ret = iommu_map_range(domain, meta->iova_addr + padding,
+ table->sgl, size, prot);
+ if (ret) {
+ pr_err("%s: could not map %lx in domain %p\n",
+ __func__, meta->iova_addr, domain);
+ unmap_size = padding;
+ goto out2;
+ }
+
+ /* Adding padding to end of buffer */
+ if (padding) {
+ unsigned long phys_addr = sg_phys(table->sgl);
+ unsigned long extra_iova_addr = meta->iova_addr +
+ padding + size;
+ ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+ padding, SZ_4K, prot);
+ if (ret) {
+ unmap_size = padding + size;
+ goto out2;
+ }
+ }
+ return ret;
+
+out2:
+ iommu_unmap_range(domain, meta->iova_addr, unmap_size);
+out1:
+ msm_free_iova_address(meta->iova_addr, domain_num, partition_num,
+ iova_length);
+
+out:
+ return ret;
+}
+
+static struct mdp3_iommu_meta *mdp3_iommu_meta_create(struct ion_client *client,
+ struct ion_handle *handle, struct sg_table *table, unsigned long size,
+ unsigned long align, unsigned long iova_length, unsigned int padding,
+ unsigned long flags, unsigned long *iova)
+{
+ struct mdp3_iommu_meta *meta;
+ int ret;
+
+ meta = kzalloc(sizeof(*meta), GFP_KERNEL);
+
+ if (!meta)
+ return ERR_PTR(-ENOMEM);
+
+ meta->handle = handle;
+ meta->table = table;
+ meta->size = size;
+ meta->mapped_size = iova_length;
+ meta->dbuf = ion_share_dma_buf(client, handle);
+ kref_init(&meta->ref);
+
+ ret = mdp3_iommu_map_iommu(meta,
+ align, iova_length, padding, flags);
+ if (ret < 0) {
+ pr_err("%s: Unable to map buffer\n", __func__);
+ goto out;
+ }
+
+ *iova = meta->iova_addr;
+ mdp3_iommu_meta_add(meta);
+
+ return meta;
+out:
+ kfree(meta);
+ return ERR_PTR(ret);
+}
+
+/*
+ * PPP hw reads in tiles of 16 which might be outside mapped region
+ * need to map buffers ourseleve to add extra padding
+ */
+int mdp3_self_map_iommu(struct ion_client *client, struct ion_handle *handle,
+ unsigned long align, unsigned long padding, unsigned long *iova,
+ unsigned long *buffer_size, unsigned long flags,
+ unsigned long iommu_flags)
+{
+ struct mdp3_iommu_meta *iommu_meta = NULL;
+ struct sg_table *table;
+ struct scatterlist *sg;
+ unsigned long size = 0, iova_length = 0;
+ int ret = 0;
+ int i;
+
+ table = ion_sg_table(client, handle);
+ if (IS_ERR_OR_NULL(table))
+ return PTR_ERR(table);
+
+ for_each_sg(table->sgl, sg, table->nents, i)
+ size += sg_dma_len(sg);
+
+ padding = PAGE_ALIGN(padding);
+
+ /* Adding 16 lines padding before and after buffer */
+ iova_length = size + 2 * padding;
+
+ if (size & ~PAGE_MASK) {
+ pr_debug("%s: buffer size %lx is not aligned to %lx", __func__,
+ size, PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (iova_length & ~PAGE_MASK) {
+ pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
+ iova_length, PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ mutex_lock(&mdp3_res->iommu_lock);
+ iommu_meta = mdp3_iommu_meta_lookup(table);
+
+ if (!iommu_meta) {
+ iommu_meta = mdp3_iommu_meta_create(client, handle, table, size,
+ align, iova_length, padding, flags, iova);
+ if (!IS_ERR_OR_NULL(iommu_meta)) {
+ iommu_meta->flags = iommu_flags;
+ ret = 0;
+ } else {
+ ret = PTR_ERR(iommu_meta);
+ goto out_unlock;
+ }
+ } else {
+ if (iommu_meta->flags != iommu_flags) {
+ pr_err("%s: handle %p is already mapped with diff flag\n",
+ __func__, handle);
+ ret = -EINVAL;
+ goto out_unlock;
+ } else if (iommu_meta->mapped_size != iova_length) {
+ pr_err("%s: handle %p is already mapped with diff len\n",
+ __func__, handle);
+ ret = -EINVAL;
+ goto out_unlock;
+ } else {
+ kref_get(&iommu_meta->ref);
+ *iova = iommu_meta->iova_addr;
+ }
+ }
+ BUG_ON(iommu_meta->size != size);
+ mutex_unlock(&mdp3_res->iommu_lock);
+
+ *iova = *iova + padding;
+ *buffer_size = size;
+ return ret;
+
+out_unlock:
+ mutex_unlock(&mdp3_res->iommu_lock);
+out:
+ mdp3_iommu_meta_put(iommu_meta);
+ return ret;
+}
+
+int mdp3_put_img(struct mdp3_img_data *data, int client)
{
struct ion_client *iclient = mdp3_res->ion_client;
- int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+ int dom;
if (data->flags & MDP_MEMORY_ID_TYPE_FB) {
pr_info("mdp3_put_img fb mem buf=0x%x\n", data->addr);
fput_light(data->srcp_file, data->p_need);
data->srcp_file = NULL;
} else if (!IS_ERR_OR_NULL(data->srcp_ihdl)) {
- ion_unmap_iommu(iclient, data->srcp_ihdl, dom, 0);
+ if (client == MDP3_CLIENT_DMA_P) {
+ dom = (mdp3_res->domains +
+ MDP3_DMA_IOMMU_DOMAIN)->domain_idx;
+ ion_unmap_iommu(iclient, data->srcp_ihdl, dom, 0);
+ } else {
+ mdp3_unmap_iommu(iclient, data->srcp_ihdl);
+ }
ion_free(iclient, data->srcp_ihdl);
data->srcp_ihdl = NULL;
} else {
@@ -858,14 +1383,15 @@
return 0;
}
-int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data)
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data,
+ int client)
{
struct file *file;
int ret = -EINVAL;
int fb_num;
unsigned long *start, *len;
struct ion_client *iclient = mdp3_res->ion_client;
- int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+ int dom;
start = (unsigned long *) &data->addr;
len = (unsigned long *) &data->len;
@@ -907,10 +1433,15 @@
data->srcp_ihdl = NULL;
return ret;
}
-
- ret = ion_map_iommu(iclient, data->srcp_ihdl, dom,
- 0, SZ_4K, 0, start, len, 0, 0);
-
+ if (client == MDP3_CLIENT_DMA_P) {
+ dom = (mdp3_res->domains +
+ MDP3_DMA_IOMMU_DOMAIN)->domain_idx;
+ ret = ion_map_iommu(iclient, data->srcp_ihdl, dom,
+ 0, SZ_4K, 0, start, len, 0, 0);
+ } else {
+ ret = mdp3_self_map_iommu(iclient, data->srcp_ihdl,
+ SZ_4K, data->padding, start, len, 0, 0);
+ }
if (IS_ERR_VALUE(ret)) {
ion_free(iclient, data->srcp_ihdl);
pr_err("failed to map ion handle (%d)\n", ret);
@@ -925,7 +1456,7 @@
pr_debug("mem=%d ihdl=%p buf=0x%x len=0x%x\n", img->memory_id,
data->srcp_ihdl, data->addr, data->len);
} else {
- mdp3_put_img(data);
+ mdp3_put_img(data, client);
return -EINVAL;
}
@@ -1095,7 +1626,7 @@
{
if (!mdp3_res)
return -ENODEV;
- return mdp3_res->domains[MDP3_IOMMU_DOMAIN].domain_idx;
+ return mdp3_res->domains[MDP3_DMA_IOMMU_DOMAIN].domain_idx;
}
int mdp3_continuous_splash_copy(struct mdss_panel_data *pdata)
@@ -1210,7 +1741,8 @@
return 0;
splash_on_err:
- mdp3_clk_enable(0);
+ if (mdp3_clk_enable(0))
+ pr_err("%s: Unable to disable mdp3 clocks\n", __func__);
return rc;
}
@@ -1350,6 +1882,31 @@
return rc;
}
+struct mdss_panel_cfg *mdp3_panel_intf_type(int intf_val)
+{
+ if (!mdp3_res || !mdp3_res->pan_cfg.init_done)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ if (mdp3_res->pan_cfg.pan_intf == intf_val)
+ return &mdp3_res->pan_cfg;
+ else
+ return NULL;
+}
+EXPORT_SYMBOL(mdp3_panel_intf_type);
+
+int mdp3_panel_get_boot_cfg(void)
+{
+ int rc;
+
+ if (!mdp3_res || !mdp3_res->pan_cfg.init_done)
+ rc = -EPROBE_DEFER;
+ if (mdp3_res->pan_cfg.lk_cfg)
+ rc = 1;
+ else
+ rc = 0;
+ return rc;
+}
+
static int mdp3_suspend_sub(struct mdp3_hw_resource *mdata)
{
return 0;
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index bd1c03d..2f73c42 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -41,8 +41,9 @@
};
enum {
- MDP3_IOMMU_DOMAIN,
- MDP3_IOMMU_DOMAIN_MAX
+ MDP3_DMA_IOMMU_DOMAIN,
+ MDP3_PPP_IOMMU_DOMAIN,
+ MDP3_IOMMU_DOMAIN_MAX,
};
enum {
@@ -58,6 +59,12 @@
MDP3_CLIENT_PPP,
};
+enum {
+ DI_PARTITION_NUM = 0,
+ DI_DOMAIN_NUM = 1,
+ DI_MAX,
+};
+
struct mdp3_bus_handle_map {
struct msm_bus_vectors *bus_vector;
struct msm_bus_paths *usecases;
@@ -83,6 +90,19 @@
int attached;
};
+struct mdp3_iommu_meta {
+ struct rb_node node;
+ struct ion_handle *handle;
+ struct rb_root iommu_maps;
+ struct kref ref;
+ struct sg_table *table;
+ struct dma_buf *dbuf;
+ int mapped_size;
+ unsigned long size;
+ unsigned long iova_addr;
+ unsigned long flags;
+};
+
#define MDP3_MAX_INTR 28
struct mdp3_intr_cb {
@@ -111,6 +131,8 @@
struct mdp3_iommu_domain_map *domains;
struct mdp3_iommu_ctx_map *iommu_contexts;
struct ion_handle *ion_handle;
+ struct mutex iommu_lock;
+ struct rb_root iommu_root;
void *virt;
unsigned long phys;
size_t size;
@@ -126,11 +148,13 @@
int irq_registered;
struct early_suspend suspend_handler;
+ struct mdss_panel_cfg pan_cfg;
};
struct mdp3_img_data {
u32 addr;
u32 len;
+ u32 padding;
u32 flags;
int p_need;
struct file *srcp_file;
@@ -150,8 +174,9 @@
int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client);
int mdp3_clk_enable(int enable);
int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
-int mdp3_put_img(struct mdp3_img_data *data);
-int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
+int mdp3_put_img(struct mdp3_img_data *data, int client);
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data,
+ int client);
int mdp3_iommu_enable(int client);
int mdp3_iommu_disable(int client);
int mdp3_iommu_is_attached(int client);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index bb53f33..bf5b643 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -50,7 +50,7 @@
while (count--) {
struct mdp3_img_data *data = &bufq->img_data[bufq->pop_idx];
bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
- mdp3_put_img(data);
+ mdp3_put_img(data, MDP3_CLIENT_DMA_P);
}
bufq->count = 0;
bufq->push_idx = 0;
@@ -557,6 +557,88 @@
return 0;
}
+static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdp3_session_data *mdp3_session;
+ struct mdp3_dma *mdp3_dma;
+ struct mdss_panel_data *panel;
+ struct mdp3_vsync_notification vsync_client;
+
+ pr_debug("mdp3_ctrl_reset\n");
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+ !mdp3_session->intf) {
+ pr_err("mdp3_ctrl_reset no device");
+ return -ENODEV;
+ }
+
+ panel = mdp3_session->panel;
+ mdp3_dma = mdp3_session->dma;
+ mutex_lock(&mdp3_session->lock);
+
+ vsync_client = mdp3_dma->vsync_client;
+
+ rc = mdp3_dma->stop(mdp3_dma, mdp3_session->intf);
+ if (rc) {
+ pr_err("fail to stop the MDP3 dma\n");
+ goto reset_error;
+ }
+
+ rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
+ if (rc)
+ pr_err("fail to turn off panel\n");
+
+ rc = mdp3_ctrl_res_req_clk(mfd, 0);
+ if (rc) {
+ pr_err("fail to release mdp clocks\n");
+ goto reset_error;
+ }
+
+ rc = panel->event_handler(panel, MDSS_EVENT_BLANK, NULL);
+ if (rc) {
+ pr_err("fail to blank the panel\n");
+ goto reset_error;
+ }
+
+ rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+ if (rc) {
+ pr_err("fail to attach dma iommu\n");
+ goto reset_error;
+ }
+
+ rc = panel->event_handler(panel, MDSS_EVENT_UNBLANK, NULL);
+ if (rc) {
+ pr_err("fail to unblank the panel\n");
+ goto reset_error;
+ }
+
+ rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+ if (rc) {
+ pr_err("fail to turn on the panel\n");
+ goto reset_error;
+ }
+
+ rc = mdp3_ctrl_res_req_clk(mfd, 1);
+ if (rc) {
+ pr_err("fail to turn on mdp clks\n");
+ goto reset_error;
+ }
+
+ mdp3_ctrl_intf_init(mfd, mdp3_session->intf);
+ mdp3_ctrl_dma_init(mfd, mdp3_dma);
+
+ if (vsync_client.handler)
+ mdp3_dma->vsync_enable(mdp3_dma, &vsync_client);
+
+ if (mfd->fbi->screen_base)
+ rc = mdp3_dma->start(mdp3_dma, mdp3_session->intf);
+
+reset_error:
+ mutex_unlock(&mdp3_session->lock);
+ return rc;
+}
+
static int mdp3_overlay_get(struct msm_fb_data_type *mfd,
struct mdp_overlay *req)
{
@@ -583,15 +665,15 @@
mutex_lock(&mdp3_session->lock);
- if (mdp3_session->overlay.id == req->id) {
- mdp3_session->overlay = *req;
- if (req->id == MSMFB_NEW_REQUEST) {
- mdp3_session->overlay.id = 1;
- req->id = 1;
- }
- } else {
- rc = -EINVAL;
+ if (mdp3_session->overlay.id != req->id)
+ pr_err("overlay was not released, continue to recover\n");
+
+ mdp3_session->overlay = *req;
+ if (req->id == MSMFB_NEW_REQUEST) {
+ mdp3_session->overlay.id = 1;
+ req->id = 1;
}
+
mutex_unlock(&mdp3_session->lock);
return rc;
@@ -624,7 +706,7 @@
struct msmfb_data *img = &req->data;
struct mdp3_img_data data;
- rc = mdp3_get_img(img, &data);
+ rc = mdp3_get_img(img, &data, MDP3_CLIENT_DMA_P);
if (rc) {
pr_err("fail to get overlay buffer\n");
return rc;
@@ -633,7 +715,7 @@
rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data);
if (rc) {
pr_err("fail to queue the overlay buffer, buffer drop\n");
- mdp3_put_img(&data);
+ mdp3_put_img(&data, MDP3_CLIENT_DMA_P);
return rc;
}
return 0;
@@ -673,20 +755,20 @@
if (!mdp3_session || !mdp3_session->dma)
return -EINVAL;
- if (!mdp3_session->status) {
- pr_err("%s, display off!\n", __func__);
- return -EPERM;
- }
-
if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
pr_debug("continuous splash screen, IOMMU not attached\n");
- mdp3_ctrl_off(mfd);
- mdp3_ctrl_on(mfd);
+ mdp3_ctrl_reset(mfd);
mdp3_free();
}
mutex_lock(&mdp3_session->lock);
+ if (!mdp3_session->status) {
+ pr_err("%s, display off!\n", __func__);
+ mutex_unlock(&mdp3_session->lock);
+ return -EPERM;
+ }
+
data = mdp3_bufq_pop(&mdp3_session->bufq_in);
if (data) {
mdp3_session->dma->update(mdp3_session->dma,
@@ -697,7 +779,7 @@
if (mdp3_bufq_count(&mdp3_session->bufq_out) > 2) {
data = mdp3_bufq_pop(&mdp3_session->bufq_out);
- mdp3_put_img(data);
+ mdp3_put_img(data, MDP3_CLIENT_DMA_P);
}
mutex_unlock(&mdp3_session->lock);
@@ -721,11 +803,6 @@
if (!mdp3_session || !mdp3_session->dma)
return;
- if (!mdp3_session->status) {
- pr_err("mdp3_ctrl_pan_display, display off!\n");
- return;
- }
-
if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
pr_debug("continuous splash screen, IOMMU not attached\n");
mdp3_ctrl_off(mfd);
@@ -733,6 +810,12 @@
}
mutex_lock(&mdp3_session->lock);
+
+ if (!mdp3_session->status) {
+ pr_err("mdp3_ctrl_pan_display, display off!\n");
+ goto pan_error;
+ }
+
fbi = mfd->fbi;
bpp = fbi->var.bits_per_pixel / 8;
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 31b9deb..5874286 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -292,12 +292,7 @@
MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride);
MDP3_REG_WRITE(MDP3_REG_DMA_P_OUT_XY, dma_p_out_xy);
- /*
- * NOTE: MDP_DMA_P_FETCH_CFG: max_burst_size need to use value 4, not
- * the default 16 for MDP hang issue workaround
- */
- MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x20);
-
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x40);
dma->source_config = *source_config;
dma->output_config = *output_config;
@@ -831,6 +826,7 @@
MDP3_DMA_CALLBACK_TYPE_DMA_DONE);
init_completion(&dma->dma_comp);
+ dma->vsync_client.handler = NULL;
return ret;
}
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 8e1dd66..e1f2d10 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -119,11 +119,22 @@
struct mdp3_img_data *data)
{
struct msmfb_data fb_data;
+ uint32_t stride;
+ int bpp = ppp_bpp(img->format);
+
+ if (bpp <= 0) {
+ pr_err("%s incorrect format %d\n", __func__, img->format);
+ return -EINVAL;
+ }
+
fb_data.flags = img->priv;
fb_data.memory_id = img->memory_id;
fb_data.offset = 0;
- return mdp3_get_img(&fb_data, data);
+ stride = img->width * bpp;
+ data->padding = 16 * stride;
+
+ return mdp3_get_img(&fb_data, data, MDP3_CLIENT_PPP);
}
/* Check format */
@@ -346,6 +357,7 @@
struct mdss_panel_info *panel_info = mfd->panel_info;
uint64_t ab = 0, ib = 0;
int rate = 0;
+ int rc;
if (on_off) {
rate = MDP_BLIT_CLK_RATE;
@@ -357,8 +369,17 @@
ib = (ab * 3) / 2;
}
mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
- mdp3_clk_enable(on_off);
- mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
+ rc = mdp3_clk_enable(on_off);
+ if (rc < 0) {
+ pr_err("%s: mdp3_clk_enable failed\n", __func__);
+ return rc;
+ }
+ rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
+ if (rc < 0) {
+ mdp3_clk_enable(!on_off);
+ pr_err("%s: scale_set_quota failed\n", __func__);
+ return rc;
+ }
ppp_stat->bw_on = on_off;
return 0;
}
@@ -909,10 +930,14 @@
static void mdp3_free_bw_wq_handler(struct work_struct *work)
{
struct msm_fb_data_type *mfd = ppp_stat->mfd;
+ int rc;
+
mutex_lock(&ppp_stat->config_ppp_mutex);
if (ppp_stat->bw_on) {
mdp3_ppp_turnon(mfd, 0);
- mdp3_iommu_disable(MDP3_CLIENT_PPP);
+ rc = mdp3_iommu_disable(MDP3_CLIENT_PPP);
+ if (rc < 0)
+ WARN(1, "Unable to disable ppp iommu\n");
}
mutex_unlock(&ppp_stat->config_ppp_mutex);
}
@@ -931,8 +956,19 @@
}
if (!ppp_stat->bw_on) {
- mdp3_iommu_enable(MDP3_CLIENT_PPP);
+ rc = mdp3_iommu_enable(MDP3_CLIENT_PPP);
+ if (rc < 0) {
+ mutex_unlock(&ppp_stat->config_ppp_mutex);
+ pr_err("%s: mdp3_iommu_enable failed\n", __func__);
+ return;
+ }
mdp3_ppp_turnon(mfd, 1);
+ if (rc < 0) {
+ mdp3_iommu_disable(MDP3_CLIENT_PPP);
+ mutex_unlock(&ppp_stat->config_ppp_mutex);
+ pr_err("%s: Enable ppp resources failed\n", __func__);
+ return;
+ }
}
while (req) {
mdp3_ppp_wait_for_fence(req);
@@ -945,8 +981,10 @@
&req->src_data[i],
&req->dst_data[i]);
}
- mdp3_put_img(&req->src_data[i]);
- mdp3_put_img(&req->dst_data[i]);
+ mdp3_put_img(&req->src_data[i],
+ MDP3_CLIENT_PPP);
+ mdp3_put_img(&req->dst_data[i],
+ MDP3_CLIENT_PPP);
}
}
/* Signal to release fence */
@@ -1017,7 +1055,7 @@
rc = mdp3_ppp_get_img(&req->req_list[i].dst,
&req->req_list[i], &req->dst_data[i]);
if (rc < 0 || req->dst_data[i].len == 0) {
- mdp3_put_img(&req->src_data[i]);
+ mdp3_put_img(&req->src_data[i], MDP3_CLIENT_PPP);
pr_err("mdp_ppp: couldn't retrieve dest img from mem\n");
goto parse_err_1;
}
@@ -1060,8 +1098,8 @@
put_unused_fd(req->cur_rel_fen_fd);
parse_err_1:
for (i--; i >= 0; i--) {
- mdp3_put_img(&req->src_data[i]);
- mdp3_put_img(&req->dst_data[i]);
+ mdp3_put_img(&req->src_data[i], MDP3_CLIENT_PPP);
+ mdp3_put_img(&req->dst_data[i], MDP3_CLIENT_PPP);
}
mdp3_ppp_deinit_buf_sync(req);
mutex_unlock(&ppp_stat->req_mutex);
diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
index 199387f..a051037 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -361,38 +361,6 @@
return rgb;
}
-uint8_t *mdp_bg_adjust_rot_addr(struct ppp_blit_op *iBuf,
- uint8_t *addr, uint32_t bpp, uint32_t uv)
-{
- uint32_t dest_ystride = iBuf->bg.prop.width * bpp;
- uint32_t h_slice = 1, min_val;
-
- if (uv && ((iBuf->bg.color_fmt == MDP_Y_CBCR_H2V2) ||
- (iBuf->bg.color_fmt == MDP_Y_CRCB_H2V2)))
- h_slice = 2;
-
- if (((iBuf->mdp_op & MDPOP_ROT90) == MDPOP_ROT90) ^
- ((iBuf->mdp_op & MDPOP_LR) == MDPOP_LR)) {
- min_val = (iBuf->bg.roi.width + iBuf->bg.roi.x) % 16;
- if (!min_val)
- min_val = 16;
- addr +=
- (iBuf->bg.roi.width -
- MIN(min_val, iBuf->bg.roi.width)) * bpp;
- }
- if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
- min_val = (iBuf->bg.roi.height + iBuf->bg.roi.y) % 16;
- if (!min_val)
- min_val = 16;
- addr +=
- ((iBuf->bg.roi.height -
- MIN(min_val, iBuf->bg.roi.height))/h_slice) *
- dest_ystride;
- }
-
- return addr;
-}
-
uint8_t *mdp_dst_adjust_rot_addr(struct ppp_blit_op *iBuf,
uint8_t *addr, uint32_t bpp, uint32_t uv)
{
@@ -434,9 +402,7 @@
img->p0 += (x + y * ALIGN(width, 128)) * bpp;
else
img->p0 += (x + y * width) * bpp;
- if (layer == 1)
- img->p0 = mdp_bg_adjust_rot_addr(blit_op, img->p0, bpp, 0);
- else if (layer == 2)
+ if (layer != 0)
img->p0 = mdp_dst_adjust_rot_addr(blit_op, img->p0, bpp, 0);
if (img->p1) {
@@ -454,13 +420,9 @@
img->p1 += ((x / h_slice) * h_slice +
((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
- if (layer == 1) {
- img->p0 = mdp_bg_adjust_rot_addr(blit_op,
- img->p0, bpp, 0);
- } else if (layer == 2) {
+ if (layer != 0)
img->p0 = mdp_dst_adjust_rot_addr(blit_op,
img->p0, bpp, 0);
- }
}
}
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 24b53c7..dd1a95b 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -82,6 +82,7 @@
u32 has_bwc;
u32 has_decimation;
u8 has_wfd_blk;
+ u8 has_wb_ad;
u32 mdp_irq_mask;
u32 mdp_hist_irq_mask;
@@ -120,6 +121,7 @@
void *video_intf;
u32 nintf;
+ u32 pp_bus_hdl;
struct mdss_ad_info *ad_cfgs;
u32 nad_cfgs;
struct workqueue_struct *ad_calc_wq;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index c6b0cfd..e156116 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -743,7 +743,6 @@
char panel_cfg[MDSS_MAX_PANEL_LEN];
struct resource *mdss_dsi_mres;
const char *ctrl_name;
- static struct mdss_panel_common_pdata vendor_pdata;
bool cmd_cfg_cont_splash = true;
if (!mdss_is_ready()) {
@@ -843,14 +842,13 @@
cmd_cfg_cont_splash = mdss_panel_get_boot_cfg() ? true : false;
- rc = mdss_dsi_panel_init(dsi_pan_node, &vendor_pdata);
+ rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, cmd_cfg_cont_splash);
if (rc) {
pr_err("%s: dsi panel init failed\n", __func__);
goto error_pan_node;
}
- rc = dsi_panel_device_register(dsi_pan_node, &vendor_pdata,
- cmd_cfg_cont_splash);
+ rc = dsi_panel_device_register(dsi_pan_node, ctrl_pdata);
if (rc) {
pr_err("%s: dsi panel dev reg failed\n", __func__);
goto error_pan_node;
@@ -950,32 +948,31 @@
}
int dsi_panel_device_register(struct device_node *pan_node,
- struct mdss_panel_common_pdata *panel_data,
- bool cmd_cfg_cont_splash)
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
struct mipi_panel_info *mipi;
int rc, i, len;
u8 lanes = 0, bpp;
u32 h_period, v_period, dsi_pclk_rate, tmp[9];
- struct mdss_dsi_ctrl_pdata *ctrl_pdata;
struct device_node *dsi_ctrl_np = NULL;
struct platform_device *ctrl_pdev = NULL;
- bool cont_splash_enabled = false;
const char *data;
+ struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
- h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
- + (panel_data->panel_info.lcdc.h_back_porch)
- + (panel_data->panel_info.xres)
- + (panel_data->panel_info.lcdc.h_front_porch));
+ h_period = ((pinfo->lcdc.h_pulse_width)
+ + (pinfo->lcdc.h_back_porch)
+ + (pinfo->xres)
+ + (pinfo->lcdc.h_front_porch));
- v_period = ((panel_data->panel_info.lcdc.v_pulse_width)
- + (panel_data->panel_info.lcdc.v_back_porch)
- + (panel_data->panel_info.yres)
- + (panel_data->panel_info.lcdc.v_front_porch));
+ v_period = ((pinfo->lcdc.v_pulse_width)
+ + (pinfo->lcdc.v_back_porch)
+ + (pinfo->yres)
+ + (pinfo->lcdc.v_front_porch));
- mipi = &panel_data->panel_info.mipi;
+ mipi = &pinfo->mipi;
+ mipi = &(pinfo->mipi);
- panel_data->panel_info.type =
+ pinfo->type =
((mipi->mode == DSI_VIDEO_MODE)
? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
@@ -999,22 +996,22 @@
else
bpp = 3; /* Default format set to RGB888 */
- if (!panel_data->panel_info.clk_rate) {
- h_period += panel_data->panel_info.lcdc.xres_pad;
- v_period += panel_data->panel_info.lcdc.yres_pad;
+ if (!pinfo->clk_rate) {
+ h_period += pinfo->lcdc.xres_pad;
+ v_period += pinfo->lcdc.yres_pad;
if (lanes > 0) {
- panel_data->panel_info.clk_rate =
+ pinfo->clk_rate =
((h_period * v_period * (mipi->frame_rate) * bpp * 8)
/ lanes);
} else {
pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
- panel_data->panel_info.clk_rate =
+ pinfo->clk_rate =
(h_period * v_period
* (mipi->frame_rate) * bpp * 8);
}
}
- pll_divider_config.clk_rate = panel_data->panel_info.clk_rate;
+ pll_divider_config.clk_rate = pinfo->clk_rate;
rc = mdss_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
if (rc) {
@@ -1034,11 +1031,6 @@
}
ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
- ctrl_pdata = platform_get_drvdata(ctrl_pdev);
- if (!ctrl_pdata) {
- pr_err("%s: no dsi ctrl driver data\n", __func__);
- return -EINVAL;
- }
rc = mdss_dsi_regulator_init(ctrl_pdev);
if (rc) {
@@ -1054,8 +1046,8 @@
__func__, __LINE__);
return -EINVAL;
}
- (panel_data->panel_info.mipi.dsi_phy_db)->strength[0] = data[0];
- (panel_data->panel_info.mipi.dsi_phy_db)->strength[1] = data[1];
+ pinfo->mipi.dsi_phy_db.strength[0] = data[0];
+ pinfo->mipi.dsi_phy_db.strength[1] = data[1];
data = of_get_property(ctrl_pdev->dev.of_node,
"qcom,platform-regulator-settings", &len);
@@ -1065,7 +1057,7 @@
return -EINVAL;
}
for (i = 0; i < len; i++) {
- (panel_data->panel_info.mipi.dsi_phy_db)->regulator[i]
+ pinfo->mipi.dsi_phy_db.regulator[i]
= data[i];
}
@@ -1077,7 +1069,7 @@
return -EINVAL;
}
for (i = 0; i < len; i++) {
- (panel_data->panel_info.mipi.dsi_phy_db)->bistCtrl[i]
+ pinfo->mipi.dsi_phy_db.bistctrl[i]
= data[i];
}
@@ -1089,7 +1081,7 @@
return -EINVAL;
}
for (i = 0; i < len; i++) {
- (panel_data->panel_info.mipi.dsi_phy_db)->laneCfg[i] =
+ pinfo->mipi.dsi_phy_db.lanecfg[i] =
data[i];
}
@@ -1112,12 +1104,16 @@
}
}
- ctrl_pdata->disp_te_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+ if (pinfo->type == MIPI_CMD_PANEL) {
+ ctrl_pdata->disp_te_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
"qcom,platform-te-gpio", 0);
- if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
- pr_err("%s:%d, Disp_te gpio not specified\n",
+ if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+ pr_err("%s:%d, Disp_te gpio not specified\n",
__func__, __LINE__);
- } else {
+ }
+ }
+
+ if (gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
rc = gpio_request(ctrl_pdata->disp_te_gpio, "disp_te");
if (rc) {
pr_err("request TE gpio failed, rc=%d\n",
@@ -1176,13 +1172,38 @@
}
}
+ if (pinfo->mode_gpio_state != MODE_GPIO_NOT_VALID) {
+
+ ctrl_pdata->mode_gpio = of_get_named_gpio(
+ ctrl_pdev->dev.of_node,
+ "qcom,platform-mode-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->mode_gpio)) {
+ pr_info("%s:%d, mode gpio not specified\n",
+ __func__, __LINE__);
+ } else {
+ rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
+ if (rc) {
+ pr_err("request panel mode gpio failed,rc=%d\n",
+ rc);
+ gpio_free(ctrl_pdata->mode_gpio);
+ if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+ gpio_free(ctrl_pdata->disp_en_gpio);
+ if (gpio_is_valid(ctrl_pdata->rst_gpio))
+ gpio_free(ctrl_pdata->rst_gpio);
+ if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ return -ENODEV;
+ }
+ }
+ }
+
if (mdss_dsi_clk_init(ctrl_pdev, ctrl_pdata)) {
pr_err("%s: unable to initialize Dsi ctrl clks\n", __func__);
return -EPERM;
}
if (mdss_dsi_retrieve_ctrl_resources(ctrl_pdev,
- panel_data->panel_info.pdest,
+ pinfo->pdest,
ctrl_pdata)) {
pr_err("%s: unable to get Dsi controller res\n", __func__);
return -EPERM;
@@ -1190,20 +1211,6 @@
ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
- ctrl_pdata->on_cmds = panel_data->on_cmds;
- ctrl_pdata->off_cmds = panel_data->off_cmds;
-
- memcpy(&((ctrl_pdata->panel_data).panel_info),
- &(panel_data->panel_info),
- sizeof(struct mdss_panel_info));
-
- ctrl_pdata->panel_data.set_backlight = panel_data->bl_fnc;
- ctrl_pdata->bklt_ctrl = panel_data->panel_info.bklt_ctrl;
- ctrl_pdata->pwm_pmic_gpio = panel_data->panel_info.pwm_pmic_gpio;
- ctrl_pdata->pwm_period = panel_data->panel_info.pwm_period;
- ctrl_pdata->pwm_lpg_chan = panel_data->panel_info.pwm_lpg_chan;
- ctrl_pdata->bklt_max = panel_data->panel_info.bl_max;
-
if (ctrl_pdata->bklt_ctrl == BL_PWM)
mdss_dsi_panel_pwm_cfg(ctrl_pdata);
@@ -1213,27 +1220,14 @@
*/
ctrl_pdata->pclk_rate = dsi_pclk_rate;
- ctrl_pdata->byte_clk_rate = panel_data->panel_info.clk_rate / 8;
+ ctrl_pdata->byte_clk_rate = pinfo->clk_rate / 8;
pr_debug("%s: pclk=%d, bclk=%d\n", __func__,
ctrl_pdata->pclk_rate, ctrl_pdata->byte_clk_rate);
ctrl_pdata->ctrl_state = CTRL_STATE_UNKNOWN;
- if (cmd_cfg_cont_splash)
- cont_splash_enabled = of_property_read_bool(pan_node,
- "qcom,cont-splash-enabled");
- else
- cont_splash_enabled = false;
- if (!cont_splash_enabled) {
- pr_info("%s:%d Continuous splash flag not found.\n",
- __func__, __LINE__);
- ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 0;
- ctrl_pdata->panel_data.panel_info.panel_power_on = 0;
- } else {
- pr_info("%s:%d Continuous splash flag enabled.\n",
- __func__, __LINE__);
- ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 1;
- ctrl_pdata->panel_data.panel_info.panel_power_on = 1;
+ if (pinfo->cont_splash_enabled) {
+ pinfo->panel_power_on = 1;
rc = mdss_dsi_panel_power_on(&(ctrl_pdata->panel_data), 1);
if (rc) {
pr_err("%s: Panel power on failed\n", __func__);
@@ -1243,6 +1237,8 @@
mdss_dsi_clk_ctrl(ctrl_pdata, 1);
ctrl_pdata->ctrl_state |=
(CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
+ } else {
+ pinfo->panel_power_on = 0;
}
rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
@@ -1255,10 +1251,7 @@
return rc;
}
- ctrl_pdata->on = panel_data->on;
- ctrl_pdata->off = panel_data->off;
-
- if (panel_data->panel_info.pdest == DISPLAY_1) {
+ if (pinfo->pdest == DISPLAY_1) {
mdss_debug_register_base("dsi0",
ctrl_pdata->ctrl_base, ctrl_pdata->reg_size);
ctrl_pdata->ndx = 0;
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index fe60fec..2d63532 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -296,16 +296,6 @@
void *data;
};
-struct mdss_panel_common_pdata {
- struct mdss_panel_info panel_info;
- int (*on) (struct mdss_panel_data *pdata);
- int (*off) (struct mdss_panel_data *pdata);
- void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
-
- struct dsi_panel_cmds on_cmds;
- struct dsi_panel_cmds off_cmds;
-};
-
struct dsi_drv_cm_data {
struct regulator *vdd_vreg;
struct regulator *vdd_io_vreg;
@@ -333,11 +323,13 @@
struct clk *esc_clk;
struct clk *pixel_clk;
u8 ctrl_state;
+ int panel_mode;
int irq_cnt;
int mdss_dsi_clk_on;
int rst_gpio;
int disp_en_gpio;
int disp_te_gpio;
+ int mode_gpio;
int bklt_ctrl; /* backlight ctrl */
int pwm_period;
int pwm_pmic_gpio;
@@ -370,8 +362,7 @@
};
int dsi_panel_device_register(struct device_node *pan_node,
- struct mdss_panel_common_pdata *panel_data,
- bool cmd_cfg_cont_splash);
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata);
char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
char *mdss_dsi_buf_init(struct dsi_buf *dp);
@@ -430,5 +421,6 @@
void mdss_dsi_cmdlist_kickoff(int intf);
int mdss_dsi_panel_init(struct device_node *node,
- struct mdss_panel_common_pdata *vendor_pdata);
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata,
+ bool cmd_cfg_cont_splash);
#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index e48d0d2..62bc7e6 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -25,6 +25,8 @@
#include "mdss.h"
#include "mdss_dsi.h"
+#define VSYNC_PERIOD 17
+
static struct mdss_dsi_ctrl_pdata *left_ctrl_pdata;
static struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX];
@@ -766,6 +768,8 @@
pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
+ ctrl_pdata->panel_mode = pinfo->mode;
+
if (pinfo->mode == DSI_VIDEO_MODE) {
data = 0;
if (pinfo->pulse_mode_hsa_he)
@@ -1135,6 +1139,8 @@
return 4;
}
+static int mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl);
+
static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_buf *tp);
@@ -1147,7 +1153,7 @@
struct dsi_buf *tp;
struct dsi_cmd_desc *cm;
struct dsi_ctrl_hdr *dchdr;
- int len, tot = 0;
+ int len, wait, tot = 0;
tp = &ctrl->tx_buf;
mdss_dsi_buf_init(tp);
@@ -1164,6 +1170,9 @@
tot += len;
if (dchdr->last) {
tp->data = tp->start; /* begin of buf */
+
+ wait = mdss_dsi_wait4video_eng_busy(ctrl);
+
mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
len = mdss_dsi_cmd_dma_tx(ctrl, tp);
if (IS_ERR_VALUE(len)) {
@@ -1172,7 +1181,8 @@
__func__, cmds->payload[0]);
return -EINVAL;
}
- if (dchdr->wait)
+
+ if (!wait || dchdr->wait > VSYNC_PERIOD)
usleep(dchdr->wait * 1000);
mdss_dsi_buf_init(tp);
@@ -1357,6 +1367,9 @@
rp->len = 0;
goto end;
}
+
+ mdss_dsi_wait4video_eng_busy(ctrl);
+
mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
if (IS_ERR_VALUE(ret)) {
@@ -1377,6 +1390,8 @@
goto end;
}
+ mdss_dsi_wait4video_eng_busy(ctrl);
+
mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
/* transmit read comamnd to client */
ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
@@ -1541,7 +1556,6 @@
return rlen;
}
-#define VSYNC_PERIOD 17
void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
{
@@ -1567,11 +1581,21 @@
MIPI_OUTP((ctrl->ctrl_base) + 0x0110, data);
}
-static void mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
+static int mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
{
- mdss_dsi_wait4video_done(ctrl);
- /* delay 4 ms to skip BLLP */
- usleep(4000);
+ int ret = 0;
+
+ if (ctrl->panel_mode == DSI_CMD_MODE)
+ return ret;
+
+ if (ctrl->ctrl_state & CTRL_STATE_MDP_ACTIVE) {
+ mdss_dsi_wait4video_done(ctrl);
+ /* delay 4 ms to skip BLLP */
+ usleep(4000);
+ ret = 1;
+ }
+
+ return ret;
}
void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl)
@@ -1638,7 +1662,6 @@
void mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
{
struct dcs_cmd_req *req;
- u32 data;
mutex_lock(&ctrl->cmd_mutex);
req = mdss_dsi_cmdlist_get(ctrl);
@@ -1646,26 +1669,14 @@
/* make sure dsi_cmd_mdp is idle */
mdss_dsi_cmd_mdp_busy(ctrl);
+ pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
+
if (req == NULL)
goto need_lock;
pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
mdss_dsi_clk_ctrl(ctrl, 1);
- data = MIPI_INP((ctrl->ctrl_base) + 0x0004);
- if (data & 0x02) {
- /* video mode, make sure video engine is busy
- * so dcs command will be sent at start of BLLP
- */
- mdss_dsi_wait4video_eng_busy(ctrl);
- } else {
- /* command mode */
- if (!from_mdp) { /* cmdlist_put */
- /* make sure dsi_cmd_mdp is idle */
- mdss_dsi_cmd_mdp_busy(ctrl);
- }
- }
-
if (req->flags & CMD_REQ_RX)
mdss_dsi_cmdlist_rx(ctrl, req);
else
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 29898db..203900c 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -28,8 +28,6 @@
DEFINE_LED_TRIGGER(bl_led_trigger);
-static struct mdss_dsi_phy_ctrl phy_params;
-
void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl)
{
int ret;
@@ -158,6 +156,7 @@
void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ struct mdss_panel_info *pinfo = NULL;
int i;
if (pdata == NULL) {
@@ -180,6 +179,7 @@
}
pr_debug("%s: enable = %d\n", __func__, enable);
+ pinfo = &(ctrl_pdata->panel_data.panel_info);
if (enable) {
for (i = 0; i < MDSS_DSI_RST_SEQ_LEN; ++i) {
@@ -189,6 +189,13 @@
}
if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
gpio_set_value((ctrl_pdata->disp_en_gpio), 1);
+
+ if (gpio_is_valid(ctrl_pdata->mode_gpio)) {
+ if (pinfo->mode_gpio_state == MODE_GPIO_HIGH)
+ gpio_set_value((ctrl_pdata->mode_gpio), 1);
+ else if (pinfo->mode_gpio_state == MODE_GPIO_LOW)
+ gpio_set_value((ctrl_pdata->mode_gpio), 0);
+ }
if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
pr_debug("%s: Panel Not properly turned OFF\n",
__func__);
@@ -486,12 +493,13 @@
static int mdss_panel_parse_dt(struct device_node *np,
- struct mdss_panel_common_pdata *panel_data)
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
u32 tmp;
int rc, i, len;
const char *data;
static const char *pdest;
+ struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-width", &tmp);
if (rc) {
@@ -499,7 +507,7 @@
__func__, __LINE__);
return -EINVAL;
}
- panel_data->panel_info.xres = (!rc ? tmp : 640);
+ pinfo->xres = (!rc ? tmp : 640);
rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-height", &tmp);
if (rc) {
@@ -507,43 +515,43 @@
__func__, __LINE__);
return -EINVAL;
}
- panel_data->panel_info.yres = (!rc ? tmp : 480);
+ pinfo->yres = (!rc ? tmp : 480);
rc = of_property_read_u32(np,
"qcom,mdss-pan-physical-width-dimension", &tmp);
- panel_data->panel_info.physical_width = (!rc ? tmp : 0);
+ pinfo->physical_width = (!rc ? tmp : 0);
rc = of_property_read_u32(np,
"qcom,mdss-pan-physical-height-dimension", &tmp);
- panel_data->panel_info.physical_height = (!rc ? tmp : 0);
+ pinfo->physical_height = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp);
- panel_data->panel_info.lcdc.xres_pad = (!rc ? tmp : 0);
+ pinfo->lcdc.xres_pad = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-right-border", &tmp);
if (!rc)
- panel_data->panel_info.lcdc.xres_pad += tmp;
+ pinfo->lcdc.xres_pad += tmp;
rc = of_property_read_u32(np, "qcom,mdss-dsi-v-top-border", &tmp);
- panel_data->panel_info.lcdc.yres_pad = (!rc ? tmp : 0);
+ pinfo->lcdc.yres_pad = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-v-bottom-border", &tmp);
if (!rc)
- panel_data->panel_info.lcdc.yres_pad += tmp;
+ pinfo->lcdc.yres_pad += tmp;
rc = of_property_read_u32(np, "qcom,mdss-dsi-bpp", &tmp);
if (rc) {
pr_err("%s:%d, bpp not specified\n", __func__, __LINE__);
return -EINVAL;
}
- panel_data->panel_info.bpp = (!rc ? tmp : 24);
- panel_data->panel_info.mipi.mode = DSI_VIDEO_MODE;
+ pinfo->bpp = (!rc ? tmp : 24);
+ pinfo->mipi.mode = DSI_VIDEO_MODE;
data = of_get_property(np, "qcom,mdss-dsi-panel-type", NULL);
if (data && !strncmp(data, "dsi_cmd_mode", 12))
- panel_data->panel_info.mipi.mode = DSI_CMD_MODE;
+ pinfo->mipi.mode = DSI_CMD_MODE;
rc = of_property_read_u32(np, "qcom,mdss-dsi-pixel-packing", &tmp);
tmp = (!rc ? tmp : 0);
- rc = mdss_panel_dt_get_dst_fmt(panel_data->panel_info.bpp,
- panel_data->panel_info.mipi.mode, tmp,
- &(panel_data->panel_info.mipi.dst_format));
+ rc = mdss_panel_dt_get_dst_fmt(pinfo->bpp,
+ pinfo->mipi.mode, tmp,
+ &(pinfo->mipi.dst_format));
if (rc) {
pr_debug("%s: problem determining dst format. Set Default\n",
__func__);
- panel_data->panel_info.mipi.dst_format =
+ pinfo->mipi.dst_format =
DSI_VIDEO_DST_FORMAT_RGB888;
}
pdest = of_get_property(np,
@@ -554,35 +562,35 @@
return -EINVAL;
}
if (!strncmp(pdest, "display_1", 9))
- panel_data->panel_info.pdest = DISPLAY_1;
+ pinfo->pdest = DISPLAY_1;
else if (!strncmp(pdest, "display_2", 9))
- panel_data->panel_info.pdest = DISPLAY_2;
+ pinfo->pdest = DISPLAY_2;
else {
pr_debug("%s: pdest not specified. Set Default\n",
__func__);
- panel_data->panel_info.pdest = DISPLAY_1;
+ pinfo->pdest = DISPLAY_1;
}
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-front-porch", &tmp);
- panel_data->panel_info.lcdc.h_front_porch = (!rc ? tmp : 6);
+ pinfo->lcdc.h_front_porch = (!rc ? tmp : 6);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-back-porch", &tmp);
- panel_data->panel_info.lcdc.h_back_porch = (!rc ? tmp : 6);
+ pinfo->lcdc.h_back_porch = (!rc ? tmp : 6);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-pulse-width", &tmp);
- panel_data->panel_info.lcdc.h_pulse_width = (!rc ? tmp : 2);
+ pinfo->lcdc.h_pulse_width = (!rc ? tmp : 2);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-sync-skew", &tmp);
- panel_data->panel_info.lcdc.hsync_skew = (!rc ? tmp : 0);
+ pinfo->lcdc.hsync_skew = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-v-back-porch", &tmp);
- panel_data->panel_info.lcdc.v_back_porch = (!rc ? tmp : 6);
+ pinfo->lcdc.v_back_porch = (!rc ? tmp : 6);
rc = of_property_read_u32(np, "qcom,mdss-dsi-v-front-porch", &tmp);
- panel_data->panel_info.lcdc.v_front_porch = (!rc ? tmp : 6);
+ pinfo->lcdc.v_front_porch = (!rc ? tmp : 6);
rc = of_property_read_u32(np, "qcom,mdss-dsi-v-pulse-width", &tmp);
- panel_data->panel_info.lcdc.v_pulse_width = (!rc ? tmp : 2);
+ pinfo->lcdc.v_pulse_width = (!rc ? tmp : 2);
rc = of_property_read_u32(np,
"qcom,mdss-dsi-underflow-color", &tmp);
- panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
+ pinfo->lcdc.underflow_clr = (!rc ? tmp : 0xff);
rc = of_property_read_u32(np,
"qcom,mdss-dsi-border-color", &tmp);
- panel_data->panel_info.lcdc.border_clr = (!rc ? tmp : 0);
- panel_data->panel_info.bklt_ctrl = UNKNOWN_CTRL;
+ pinfo->lcdc.border_clr = (!rc ? tmp : 0);
+ pinfo->bklt_ctrl = UNKNOWN_CTRL;
data = of_get_property(np, "qcom,mdss-dsi-bl-pmic-control-type", NULL);
if (data) {
if (!strncmp(data, "bl_ctrl_wled", 12)) {
@@ -590,9 +598,9 @@
&bl_led_trigger);
pr_debug("%s: SUCCESS-> WLED TRIGGER register\n",
__func__);
- panel_data->panel_info.bklt_ctrl = BL_WLED;
+ ctrl_pdata->bklt_ctrl = BL_WLED;
} else if (!strncmp(data, "bl_ctrl_pwm", 11)) {
- panel_data->panel_info.bklt_ctrl = BL_PWM;
+ ctrl_pdata->bklt_ctrl = BL_PWM;
rc = of_property_read_u32(np,
"qcom,mdss-dsi-bl-pmic-pwm-frequency", &tmp);
if (rc) {
@@ -600,7 +608,7 @@
__func__, __LINE__);
return -EINVAL;
}
- panel_data->panel_info.pwm_period = tmp;
+ ctrl_pdata->pwm_period = tmp;
rc = of_property_read_u32(np,
"qcom,mdss-dsi-bl-pmic-bank-select", &tmp);
if (rc) {
@@ -608,108 +616,119 @@
__func__, __LINE__);
return -EINVAL;
}
- panel_data->panel_info.pwm_lpg_chan = tmp;
+ ctrl_pdata->pwm_lpg_chan = tmp;
tmp = of_get_named_gpio(np,
"qcom,mdss-dsi-pwm-gpio", 0);
- panel_data->panel_info.pwm_pmic_gpio = tmp;
+ ctrl_pdata->pwm_pmic_gpio = tmp;
} else if (!strncmp(data, "bl_ctrl_dcs", 11)) {
- panel_data->panel_info.bklt_ctrl = BL_DCS_CMD;
+ ctrl_pdata->bklt_ctrl = BL_DCS_CMD;
}
}
rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp);
- panel_data->panel_info.bl_min = (!rc ? tmp : 0);
+ pinfo->bl_min = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-max-level", &tmp);
- panel_data->panel_info.bl_max = (!rc ? tmp : 255);
+ pinfo->bl_max = (!rc ? tmp : 255);
+ ctrl_pdata->bklt_max = pinfo->bl_max;
rc = of_property_read_u32(np, "qcom,mdss-dsi-interleave-mode", &tmp);
- panel_data->panel_info.mipi.interleave_mode = (!rc ? tmp : 0);
+ pinfo->mipi.interleave_mode = (!rc ? tmp : 0);
- panel_data->panel_info.mipi.vsync_enable = of_property_read_bool(np,
+ pinfo->mipi.vsync_enable = of_property_read_bool(np,
"qcom,mdss-dsi-te-check-enable");
- panel_data->panel_info.mipi.hw_vsync_mode = of_property_read_bool(np,
+ pinfo->mipi.hw_vsync_mode = of_property_read_bool(np,
"qcom,mdss-dsi-te-using-te-pin");
rc = of_property_read_u32(np,
"qcom,mdss-dsi-h-sync-pulse", &tmp);
- panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
+ pinfo->mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
- panel_data->panel_info.mipi.hfp_power_stop = of_property_read_bool(np,
+ pinfo->mipi.hfp_power_stop = of_property_read_bool(np,
"qcom,mdss-dsi-hfp-power-mode");
- panel_data->panel_info.mipi.hsa_power_stop = of_property_read_bool(np,
+ pinfo->mipi.hsa_power_stop = of_property_read_bool(np,
"qcom,mdss-dsi-hsa-power-mode");
- panel_data->panel_info.mipi.hbp_power_stop = of_property_read_bool(np,
+ pinfo->mipi.hbp_power_stop = of_property_read_bool(np,
"qcom,mdss-dsi-hbp-power-mode");
- panel_data->panel_info.mipi.bllp_power_stop = of_property_read_bool(np,
+ pinfo->mipi.bllp_power_stop = of_property_read_bool(np,
"qcom,mdss-dsi-bllp-power-mode");
- panel_data->panel_info.mipi.eof_bllp_power_stop = of_property_read_bool(
+ pinfo->mipi.eof_bllp_power_stop = of_property_read_bool(
np, "qcom,mdss-dsi-bllp-eof-power-mode");
rc = of_property_read_u32(np,
"qcom,mdss-dsi-traffic-mode", &tmp);
- panel_data->panel_info.mipi.traffic_mode =
+ pinfo->mipi.traffic_mode =
(!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
rc = of_property_read_u32(np,
"qcom,mdss-dsi-te-dcs-command", &tmp);
- panel_data->panel_info.mipi.insert_dcs_cmd =
+ pinfo->mipi.insert_dcs_cmd =
(!rc ? tmp : 1);
rc = of_property_read_u32(np,
"qcom,mdss-dsi-te-v-sync-continue-lines", &tmp);
- panel_data->panel_info.mipi.wr_mem_continue =
+ pinfo->mipi.wr_mem_continue =
(!rc ? tmp : 0x3c);
rc = of_property_read_u32(np,
"qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line", &tmp);
- panel_data->panel_info.mipi.wr_mem_start =
+ pinfo->mipi.wr_mem_start =
(!rc ? tmp : 0x2c);
rc = of_property_read_u32(np,
"qcom,mdss-dsi-te-pin-select", &tmp);
- panel_data->panel_info.mipi.te_sel =
+ pinfo->mipi.te_sel =
(!rc ? tmp : 1);
rc = of_property_read_u32(np, "qcom,mdss-dsi-virtual-channel-id", &tmp);
- panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
+ pinfo->mipi.vc = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-color-order", &tmp);
- panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
- panel_data->panel_info.mipi.data_lane0 = of_property_read_bool(np,
+ pinfo->mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+ pinfo->mipi.data_lane0 = of_property_read_bool(np,
"qcom,mdss-dsi-lane-0-state");
- panel_data->panel_info.mipi.data_lane1 = of_property_read_bool(np,
+ pinfo->mipi.data_lane1 = of_property_read_bool(np,
"qcom,mdss-dsi-lane-1-state");
- panel_data->panel_info.mipi.data_lane2 = of_property_read_bool(np,
+ pinfo->mipi.data_lane2 = of_property_read_bool(np,
"qcom,mdss-dsi-lane-2-state");
- panel_data->panel_info.mipi.data_lane3 = of_property_read_bool(np,
+ pinfo->mipi.data_lane3 = of_property_read_bool(np,
"qcom,mdss-dsi-lane-3-state");
rc = of_property_read_u32(np, "qcom,mdss-dsi-lane-map", &tmp);
- panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
+ pinfo->mipi.dlane_swap = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-pre", &tmp);
- panel_data->panel_info.mipi.t_clk_pre = (!rc ? tmp : 0x24);
+ pinfo->mipi.t_clk_pre = (!rc ? tmp : 0x24);
rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-post", &tmp);
- panel_data->panel_info.mipi.t_clk_post = (!rc ? tmp : 0x03);
+ pinfo->mipi.t_clk_post = (!rc ? tmp : 0x03);
rc = of_property_read_u32(np, "qcom,mdss-dsi-stream", &tmp);
- panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
+ pinfo->mipi.stream = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-mdp-trigger", &tmp);
- panel_data->panel_info.mipi.mdp_trigger =
+ pinfo->mipi.mdp_trigger =
(!rc ? tmp : DSI_CMD_TRIGGER_SW);
- if (panel_data->panel_info.mipi.mdp_trigger > 6) {
+ if (pinfo->mipi.mdp_trigger > 6) {
pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
__func__, __LINE__);
- panel_data->panel_info.mipi.mdp_trigger =
+ pinfo->mipi.mdp_trigger =
DSI_CMD_TRIGGER_SW;
}
rc = of_property_read_u32(np, "qcom,mdss-dsi-dma-trigger", &tmp);
- panel_data->panel_info.mipi.dma_trigger =
+ pinfo->mipi.dma_trigger =
(!rc ? tmp : DSI_CMD_TRIGGER_SW);
- if (panel_data->panel_info.mipi.dma_trigger > 6) {
+ if (pinfo->mipi.dma_trigger > 6) {
pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
__func__, __LINE__);
- panel_data->panel_info.mipi.dma_trigger =
+ pinfo->mipi.dma_trigger =
DSI_CMD_TRIGGER_SW;
}
+ data = of_get_property(np, "qcom,mdss-dsi-panel-mode-gpio-state", &tmp);
+ if (data) {
+ if (!strcmp(data, "high"))
+ pinfo->mode_gpio_state = MODE_GPIO_HIGH;
+ else if (!strcmp(data, "low"))
+ pinfo->mode_gpio_state = MODE_GPIO_LOW;
+ } else {
+ pinfo->mode_gpio_state = MODE_GPIO_NOT_VALID;
+ }
+
rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-frame-rate", &tmp);
- panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+ pinfo->mipi.frame_rate = (!rc ? tmp : 60);
rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-clock-rate", &tmp);
- panel_data->panel_info.clk_rate = (!rc ? tmp : 0);
+ pinfo->clk_rate = (!rc ? tmp : 0);
data = of_get_property(np, "qcom,mdss-dsi-panel-timings", &len);
if ((!data) || (len != 12)) {
pr_err("%s:%d, Unable to read Phy timing settings",
@@ -717,16 +736,14 @@
goto error;
}
for (i = 0; i < len; i++)
- phy_params.timing[i] = data[i];
+ pinfo->mipi.dsi_phy_db.timing[i] = data[i];
- panel_data->panel_info.mipi.dsi_phy_db = &phy_params;
+ mdss_dsi_parse_fbc_params(np, pinfo);
- mdss_dsi_parse_fbc_params(np, &panel_data->panel_info);
-
- mdss_dsi_parse_dcs_cmds(np, &panel_data->on_cmds,
+ mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->on_cmds,
"qcom,mdss-dsi-on-command", "qcom,mdss-dsi-on-command-state");
- mdss_dsi_parse_dcs_cmds(np, &panel_data->off_cmds,
+ mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds,
"qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state");
return 0;
@@ -736,10 +753,12 @@
}
int mdss_dsi_panel_init(struct device_node *node,
- struct mdss_panel_common_pdata *vendor_pdata)
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata,
+ bool cmd_cfg_cont_splash)
{
int rc = 0;
static const char *panel_name;
+ bool cont_splash_enabled;
if (!node) {
pr_err("%s: no panel node\n", __func__);
@@ -754,15 +773,31 @@
else
pr_info("%s: Panel Name = %s\n", __func__, panel_name);
- rc = mdss_panel_parse_dt(node, vendor_pdata);
+ rc = mdss_panel_parse_dt(node, ctrl_pdata);
if (rc) {
pr_err("%s:%d panel dt parse failed\n", __func__, __LINE__);
return rc;
}
- vendor_pdata->on = mdss_dsi_panel_on;
- vendor_pdata->off = mdss_dsi_panel_off;
- vendor_pdata->bl_fnc = mdss_dsi_panel_bl_ctrl;
+ if (cmd_cfg_cont_splash)
+ cont_splash_enabled = of_property_read_bool(node,
+ "qcom,cont-splash-enabled");
+ else
+ cont_splash_enabled = false;
+ if (!cont_splash_enabled) {
+ pr_info("%s:%d Continuous splash flag not found.\n",
+ __func__, __LINE__);
+ ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 0;
+ } else {
+ pr_info("%s:%d Continuous splash flag enabled.\n",
+ __func__, __LINE__);
+
+ ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 1;
+ }
+
+ ctrl_pdata->on = mdss_dsi_panel_on;
+ ctrl_pdata->off = mdss_dsi_panel_off;
+ ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index a4a2af4..17280ed 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -242,12 +242,28 @@
return ret;
}
+static ssize_t mdss_mdp_show_blank_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+ int ret;
+
+ pr_debug("fb%d panel_power_on = %d\n", mfd->index, mfd->panel_power_on);
+ ret = scnprintf(buf, PAGE_SIZE, "panel_power_on = %d\n",
+ mfd->panel_power_on);
+
+ return ret;
+}
+
static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
static DEVICE_ATTR(msm_fb_split, S_IRUGO, mdss_fb_get_split, NULL);
+static DEVICE_ATTR(show_blank_event, S_IRUGO, mdss_mdp_show_blank_event, NULL);
static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_type.attr,
&dev_attr_msm_fb_split.attr,
+ &dev_attr_show_blank_event.attr,
NULL,
};
@@ -313,6 +329,7 @@
mfd->index = fbi_list_index;
mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
+ mfd->ext_ad_ctrl = -1;
mfd->bl_level = 0;
mfd->bl_scale = 1024;
mfd->bl_min_lvl = 30;
@@ -703,11 +720,8 @@
mfd->op_enable = false;
curr_pwr_state = mfd->panel_power_on;
- mutex_lock(&mfd->bl_lock);
- mdss_fb_set_backlight(mfd, 0);
mfd->panel_power_on = false;
bl_updated = 0;
- mutex_unlock(&mfd->bl_lock);
ret = mfd->mdp.off_fnc(mfd);
if (ret)
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 65218c0..fd96e63 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -118,6 +118,7 @@
unsigned long cursor_buf_phys;
unsigned long cursor_buf_iova;
+ int ext_ad_ctrl;
u32 ext_bl_ctrl;
u32 calib_mode;
u32 bl_level;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 86a2e45..3107e38 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1105,8 +1105,8 @@
probe_done:
if (IS_ERR_VALUE(rc)) {
mdss_mdp_hw.ptr = NULL;
- mdss_res = NULL;
mdss_mdp_pp_term(&pdev->dev);
+ mdss_res = NULL;
}
return rc;
@@ -1821,6 +1821,9 @@
if (mdata->nad_cfgs > mdata->nmixers_intf)
return -EINVAL;
+ mdata->has_wb_ad = of_property_read_bool(pdev->dev.of_node,
+ "qcom,mdss-has-wb-ad");
+
ad_offsets = kzalloc(sizeof(u32) * mdata->nad_cfgs, GFP_KERNEL);
if (!ad_offsets) {
pr_err("no mem assigned: kzalloc fail\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 70d9107..351d52b 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -116,6 +116,7 @@
struct mdss_mdp_vsync_handler {
bool enabled;
+ bool cmd_post_flush;
mdp_vsync_handler_t vsync_handler;
struct list_head list;
};
@@ -272,6 +273,7 @@
struct mutex lock;
struct work_struct calc_work;
struct msm_fb_data_type *mfd;
+ struct msm_fb_data_type *bl_mfd;
struct mdss_mdp_vsync_handler handle;
struct completion comp;
u32 last_str;
@@ -384,6 +386,7 @@
struct mdss_mdp_data free_list[MAX_FREE_LIST_SIZE];
int free_list_size;
+ int ad_state;
};
struct mdss_mdp_perf_params {
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 176d0df..7b36f2c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -420,6 +420,7 @@
ctl->read_line_cnt_fnc = NULL;
ctl->add_vsync_handler = NULL;
ctl->remove_vsync_handler = NULL;
+ ctl->panel_data = NULL;
mutex_unlock(&mdss_mdp_ctl_lock);
return 0;
@@ -428,7 +429,7 @@
static struct mdss_mdp_mixer *mdss_mdp_mixer_alloc(
struct mdss_mdp_ctl *ctl, u32 type, int mux)
{
- struct mdss_mdp_mixer *mixer = NULL;
+ struct mdss_mdp_mixer *mixer = NULL, *alt_mixer = NULL;
u32 nmixers_intf;
u32 nmixers_wb;
u32 i;
@@ -446,6 +447,16 @@
case MDSS_MDP_MIXER_TYPE_INTF:
mixer_pool = ctl->mdata->mixer_intf;
nmixers = nmixers_intf;
+
+ /*
+ * try to reserve first layer mixer for write back if
+ * assertive display needs to be supported through wfd
+ */
+ if (ctl->mdata->has_wb_ad && ctl->intf_num) {
+ alt_mixer = mixer_pool;
+ mixer_pool++;
+ nmixers--;
+ }
break;
case MDSS_MDP_MIXER_TYPE_WRITEBACK:
@@ -484,6 +495,9 @@
}
mixer = NULL;
}
+
+ if (!mixer && alt_mixer && (alt_mixer->ref_cnt == 0))
+ mixer = alt_mixer;
mutex_unlock(&mdss_mdp_ctl_lock);
return mixer;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index cb4c1f2..920c231 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -34,7 +34,7 @@
u8 ref_cnt;
struct completion pp_comp;
struct completion stop_comp;
- mdp_vsync_handler_t send_vsync;
+ struct list_head vsync_handlers;
int panel_on;
int koff_cnt;
int clk_enabled;
@@ -232,6 +232,7 @@
{
struct mdss_mdp_ctl *ctl = arg;
struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
+ struct mdss_mdp_vsync_handler *tmp;
ktime_t vsync_time;
if (!ctx) {
@@ -243,8 +244,10 @@
ctl->vsync_cnt++;
spin_lock(&ctx->clk_lock);
- if (ctx->send_vsync)
- ctx->send_vsync(ctl, vsync_time);
+ list_for_each_entry(tmp, &ctx->vsync_handlers, list) {
+ if (tmp->enabled && !tmp->cmd_post_flush)
+ tmp->vsync_handler(ctl, vsync_time);
+ }
if (!ctx->vsync_enabled) {
if (ctx->rdptr_enabled)
@@ -265,6 +268,8 @@
{
struct mdss_mdp_ctl *ctl = arg;
struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
+ struct mdss_mdp_vsync_handler *tmp;
+ ktime_t vsync_time;
if (!ctx) {
pr_err("%s: invalid ctx\n", __func__);
@@ -272,6 +277,10 @@
}
spin_lock(&ctx->clk_lock);
+ list_for_each_entry(tmp, &ctx->vsync_handlers, list) {
+ if (tmp->enabled && tmp->cmd_post_flush)
+ tmp->vsync_handler(ctl, vsync_time);
+ }
mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
complete_all(&ctx->pp_comp);
@@ -318,15 +327,16 @@
}
spin_lock_irqsave(&ctx->clk_lock, flags);
- if (ctx->vsync_enabled) {
- spin_unlock_irqrestore(&ctx->clk_lock, flags);
- return 0;
+ if (!handle->enabled) {
+ handle->enabled = true;
+ list_add(&handle->list, &ctx->vsync_handlers);
+ if (!handle->cmd_post_flush)
+ ctx->vsync_enabled = 1;
}
- ctx->vsync_enabled = 1;
- ctx->send_vsync = handle->vsync_handler;
spin_unlock_irqrestore(&ctx->clk_lock, flags);
- mdss_mdp_cmd_clk_on(ctx);
+ if (!handle->cmd_post_flush)
+ mdss_mdp_cmd_clk_on(ctx);
return 0;
}
@@ -337,6 +347,8 @@
struct mdss_mdp_cmd_ctx *ctx;
unsigned long flags;
+ struct mdss_mdp_vsync_handler *tmp;
+ int num_rdptr_vsync = 0;
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
if (!ctx) {
@@ -346,13 +358,18 @@
spin_lock_irqsave(&ctx->clk_lock, flags);
- if (!ctx->vsync_enabled) {
- spin_unlock_irqrestore(&ctx->clk_lock, flags);
- return 0;
+ if (handle->enabled) {
+ handle->enabled = false;
+ list_del_init(&handle->list);
}
- ctx->vsync_enabled = 0;
- ctx->send_vsync = NULL;
- ctx->rdptr_enabled = VSYNC_EXPIRE_TICK;
+ list_for_each_entry(tmp, &ctx->vsync_handlers, list) {
+ if (!tmp->cmd_post_flush)
+ num_rdptr_vsync++;
+ }
+ if (!num_rdptr_vsync) {
+ ctx->vsync_enabled = 0;
+ ctx->rdptr_enabled = VSYNC_EXPIRE_TICK;
+ }
spin_unlock_irqrestore(&ctx->clk_lock, flags);
return 0;
}
@@ -455,6 +472,7 @@
{
struct mdss_mdp_cmd_ctx *ctx;
unsigned long flags;
+ struct mdss_mdp_vsync_handler *tmp, *handle;
int need_wait = 0;
int ret = 0;
@@ -468,10 +486,6 @@
INIT_COMPLETION(ctx->stop_comp);
need_wait = 1;
}
- if (ctx->vsync_enabled) {
- pr_err("%s: vsync should be disabled\n", __func__);
- ctx->vsync_enabled = 0;
- }
spin_unlock_irqrestore(&ctx->clk_lock, flags);
if (need_wait)
@@ -486,6 +500,9 @@
ctx->panel_on = 0;
+ list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
+ mdss_mdp_cmd_remove_vsync_handler(ctl, handle);
+
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
NULL, NULL);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
@@ -550,6 +567,7 @@
spin_lock_init(&ctx->clk_lock);
mutex_init(&ctx->clk_mtx);
INIT_WORK(&ctx->clk_work, clk_ctrl_work);
+ INIT_LIST_HEAD(&ctx->vsync_handlers);
pr_debug("%s: ctx=%p num=%d mixer=%d\n", __func__,
ctx, ctx->pp_num, mixer->num);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index ff977a9..2b07428 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -48,6 +48,8 @@
void (*callback_fnc) (void *arg);
void *callback_arg;
+ spinlock_t wb_lock;
+ struct list_head vsync_handlers;
};
static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = {
@@ -293,16 +295,75 @@
return mdss_mdp_writeback_format_setup(ctx, format);
}
+static int mdss_mdp_wb_add_vsync_handler(struct mdss_mdp_ctl *ctl,
+ struct mdss_mdp_vsync_handler *handle)
+{
+ struct mdss_mdp_writeback_ctx *ctx;
+ unsigned long flags;
+ int ret = 0;
+
+ if (!handle || !(handle->vsync_handler)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
+ if (!ctx) {
+ pr_err("invalid ctx for ctl=%d\n", ctl->num);
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ spin_lock_irqsave(&ctx->wb_lock, flags);
+ if (!handle->enabled) {
+ handle->enabled = true;
+ list_add(&handle->list, &ctx->vsync_handlers);
+ }
+ spin_unlock_irqrestore(&ctx->wb_lock, flags);
+exit:
+ return ret;
+}
+
+static int mdss_mdp_wb_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
+ struct mdss_mdp_vsync_handler *handle)
+{
+ struct mdss_mdp_writeback_ctx *ctx;
+ unsigned long flags;
+ int ret = 0;
+ if (!handle || !(handle->vsync_handler)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
+ if (!ctx) {
+ pr_err("invalid ctx for ctl=%d\n", ctl->num);
+ ret = -ENODEV;
+ goto exit;
+ }
+ spin_lock_irqsave(&ctx->wb_lock, flags);
+ if (handle->enabled) {
+ handle->enabled = false;
+ list_del_init(&handle->list);
+ }
+ spin_unlock_irqrestore(&ctx->wb_lock, flags);
+exit:
+ return ret;
+}
+
static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_writeback_ctx *ctx;
+ struct mdss_mdp_vsync_handler *t, *handle;
pr_debug("stop ctl=%d\n", ctl->num);
ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
if (ctx) {
+ list_for_each_entry_safe(handle, t, &ctx->vsync_handlers, list)
+ mdss_mdp_wb_remove_vsync_handler(ctl, handle);
+
mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
- NULL, NULL);
+ NULL, NULL);
ctl->priv_data = NULL;
ctx->ref_cnt--;
@@ -313,13 +374,16 @@
static void mdss_mdp_writeback_intr_done(void *arg)
{
- struct mdss_mdp_writeback_ctx *ctx;
+ struct mdss_mdp_ctl *ctl = arg;
+ struct mdss_mdp_writeback_ctx *ctx = ctl->priv_data;
+ struct mdss_mdp_vsync_handler *tmp;
+ ktime_t vsync_time;
- ctx = (struct mdss_mdp_writeback_ctx *) arg;
if (!ctx) {
pr_err("invalid ctx\n");
return;
}
+ vsync_time = ktime_get();
pr_debug("intr wb_num=%d\n", ctx->wb_num);
@@ -328,6 +392,12 @@
if (ctx->callback_fnc)
ctx->callback_fnc(ctx->callback_arg);
+ spin_lock(&ctx->wb_lock);
+ list_for_each_entry(tmp, &ctx->vsync_handlers, list) {
+ tmp->vsync_handler(ctl, vsync_time);
+ }
+ spin_unlock(&ctx->wb_lock);
+
complete_all(&ctx->wb_comp);
}
@@ -393,7 +463,7 @@
}
mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
- mdss_mdp_writeback_intr_done, ctx);
+ mdss_mdp_writeback_intr_done, ctl);
ctx->callback_fnc = wb_args->callback_fnc;
ctx->callback_arg = wb_args->priv_data;
@@ -439,6 +509,8 @@
ctx->base = ctl->wb_base;
ctx->initialized = false;
init_completion(&ctx->wb_comp);
+ spin_lock_init(&ctx->wb_lock);
+ INIT_LIST_HEAD(&ctx->vsync_handlers);
if (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR)
ctl->prepare_fnc = mdss_mdp_writeback_prepare_rot;
@@ -447,6 +519,8 @@
ctl->stop_fnc = mdss_mdp_writeback_stop;
ctl->display_fnc = mdss_mdp_writeback_display;
ctl->wait_fnc = mdss_mdp_wb_wait4comp;
+ ctl->add_vsync_handler = mdss_mdp_wb_add_vsync_handler;
+ ctl->remove_vsync_handler = mdss_mdp_wb_remove_vsync_handler;
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 55889da..8e805da 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -25,6 +25,7 @@
#include <mach/iommu_domains.h>
#include <mach/event_timer.h>
+#include <mach/msm_bus.h>
#include "mdss.h"
#include "mdss_debug.h"
@@ -37,6 +38,9 @@
#define CHECK_BOUNDS(offset, size, max_size) \
(((size) > (max_size)) || ((offset) > ((max_size) - (size))))
+#define PP_CLK_CFG_OFF 0
+#define PP_CLK_CFG_ON 1
+
static atomic_t ov_active_panels = ATOMIC_INIT(0);
static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd);
@@ -1495,15 +1499,81 @@
return ret;
}
-static DEVICE_ATTR(vsync_event, S_IRUGO, mdss_mdp_vsync_show_event, NULL);
+static inline int mdss_mdp_ad_is_supported(struct msm_fb_data_type *mfd)
+{
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+ struct mdss_mdp_mixer *mixer;
-static struct attribute *vsync_fs_attrs[] = {
+ if (!ctl) {
+ pr_debug("there is no ctl attached to fb\n");
+ return 0;
+ }
+
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
+ if (mixer && (mixer->num > ctl->mdata->nad_cfgs)) {
+ if (!mixer)
+ pr_warn("there is no mixer attached to fb\n");
+ else
+ pr_debug("mixer attached (%d) doesnt support ad\n",
+ mixer->num);
+ return 0;
+ }
+
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT);
+ if (mixer && (mixer->num > ctl->mdata->nad_cfgs))
+ return 0;
+
+ return 1;
+}
+
+static ssize_t mdss_mdp_ad_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = fbi->par;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ int ret, state;
+
+ state = mdss_mdp_ad_is_supported(mfd) ? mdp5_data->ad_state : -1;
+
+ ret = scnprintf(buf, PAGE_SIZE, "%d", state);
+
+ return ret;
+}
+
+static ssize_t mdss_mdp_ad_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = fbi->par;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ int ret, ad;
+
+ ret = kstrtoint(buf, 10, &ad);
+ if (ret) {
+ pr_err("Invalid input for ad\n");
+ return -EINVAL;
+ }
+
+ mdp5_data->ad_state = ad;
+ sysfs_notify(&dev->kobj, NULL, "ad");
+
+ return count;
+}
+
+
+static DEVICE_ATTR(vsync_event, S_IRUGO, mdss_mdp_vsync_show_event, NULL);
+static DEVICE_ATTR(ad, S_IRUGO | S_IWUSR | S_IWGRP, mdss_mdp_ad_show,
+ mdss_mdp_ad_store);
+
+static struct attribute *mdp_overlay_sysfs_attrs[] = {
&dev_attr_vsync_event.attr,
+ &dev_attr_ad.attr,
NULL,
};
-static struct attribute_group vsync_fs_attr_group = {
- .attrs = vsync_fs_attrs,
+static struct attribute_group mdp_overlay_sysfs_group = {
+ .attrs = mdp_overlay_sysfs_attrs,
};
static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
@@ -1779,12 +1849,20 @@
struct mdp_histogram_start_req hist_req;
u32 block;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ u32 pp_bus_handle;
+ static int req = -1;
switch (cmd) {
case MSMFB_HISTOGRAM_START:
if (!mfd->panel_power_on)
return -EPERM;
+ pp_bus_handle = mdss_mdp_get_mdata()->pp_bus_hdl;
+ req = msm_bus_scale_client_update_request(pp_bus_handle,
+ PP_CLK_CFG_ON);
+ if (req)
+ pr_err("Updated pp_bus_scale failed, ret = %d", req);
+
ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
if (ret)
return ret;
@@ -1798,6 +1876,17 @@
return ret;
ret = mdss_mdp_histogram_stop(mdp5_data->ctl, block);
+ if (ret)
+ return ret;
+
+ if (!req) {
+ pp_bus_handle = mdss_mdp_get_mdata()->pp_bus_hdl;
+ req = msm_bus_scale_client_update_request(pp_bus_handle,
+ PP_CLK_CFG_OFF);
+ if (req)
+ pr_err("Updated pp_bus_scale failed, ret = %d",
+ req);
+ }
break;
case MSMFB_HISTOGRAM:
@@ -2051,6 +2140,7 @@
}
ctl->vsync_handler.vsync_handler =
mdss_mdp_overlay_handle_vsync;
+ ctl->vsync_handler.cmd_post_flush = false;
if (mfd->split_display && pdata->next) {
/* enable split display */
@@ -2063,10 +2153,11 @@
mdp5_data->ctl = ctl;
}
- if (!mfd->panel_info->cont_splash_enabled) {
+ if (!mfd->panel_info->cont_splash_enabled &&
+ (mfd->panel_info->type != DTV_PANEL) &&
+ (mfd->panel_info->type != WRITEBACK_PANEL)) {
rc = mdss_mdp_overlay_start(mfd);
- if (!IS_ERR_VALUE(rc) && (mfd->panel_info->type != DTV_PANEL) &&
- (mfd->panel_info->type != WRITEBACK_PANEL))
+ if (!IS_ERR_VALUE(rc))
rc = mdss_mdp_overlay_kickoff(mfd);
} else {
rc = mdss_mdp_ctl_setup(mdp5_data->ctl);
@@ -2201,7 +2292,7 @@
if (rc)
return rc;
- rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
+ rc = sysfs_create_group(&dev->kobj, &mdp_overlay_sysfs_group);
if (rc) {
pr_err("vsync sysfs group creation failed, ret=%d\n", rc);
goto init_fail;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 95eb381..0b64870 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -19,6 +19,8 @@
#include <linux/uaccess.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
struct mdp_csc_cfg mdp_csc_convert[MDSS_MDP_MAX_CSC] = {
[MDSS_MDP_CSC_RGB2RGB] = {
@@ -226,6 +228,27 @@
#define SHARP_SMOOTH_THR_DEFAULT 8
#define SHARP_NOISE_THR_DEFAULT 2
+#define MDP_PP_BUS_VECTOR_ENTRY(ab_val, ib_val) \
+ { \
+ .src = MSM_BUS_MASTER_SPDM, \
+ .dst = MSM_BUS_SLAVE_IMEM_CFG, \
+ .ab = (ab_val), \
+ .ib = (ib_val), \
+ }
+
+#define SZ_37_5M (37500000 * 8)
+
+static struct msm_bus_vectors mdp_pp_bus_vectors[] = {
+ MDP_PP_BUS_VECTOR_ENTRY(0, 0),
+ MDP_PP_BUS_VECTOR_ENTRY(0, SZ_37_5M),
+};
+static struct msm_bus_paths mdp_pp_bus_usecases[ARRAY_SIZE(mdp_pp_bus_vectors)];
+static struct msm_bus_scale_pdata mdp_pp_bus_scale_table = {
+ .usecase = mdp_pp_bus_usecases,
+ .num_usecases = ARRAY_SIZE(mdp_pp_bus_usecases),
+ .name = "mdss_pp",
+};
+
struct mdss_pp_res_type {
/* logical info */
u32 pp_disp_flags[MDSS_BLOCK_DISP_NUM];
@@ -266,7 +289,8 @@
static void pp_update_igc_lut(struct mdp_igc_lut_data *cfg,
u32 offset, u32 blk_idx);
static void pp_update_gc_one_lut(u32 offset,
- struct mdp_ar_gc_lut_data *lut_data);
+ struct mdp_ar_gc_lut_data *lut_data,
+ uint8_t num_stages);
static void pp_update_argc_lut(u32 offset,
struct mdp_pgc_lut_data *config);
static void pp_update_hist_lut(char __iomem *base,
@@ -1008,8 +1032,7 @@
flags = 0;
mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
- if (dspp_num < mdata->nad_cfgs && (mixer_cnt != 2) &&
- ctl->mfd->panel_info->type != MIPI_CMD_PANEL) {
+ if (dspp_num < mdata->nad_cfgs && (mixer_cnt != 2)) {
ret = mdss_mdp_ad_setup(ctl->mfd);
if (ret < 0)
pr_warn("ad_setup(dspp%d) returns %d", dspp_num, ret);
@@ -1188,7 +1211,7 @@
if (PP_AD_STATE_INIT & ad->state)
pp_ad_init_write(ad);
if (PP_AD_STATE_DATA & ad->state) {
- bl = ctl->mfd->bl_level;
+ bl = ad->bl_mfd->bl_level;
ad->last_bl = bl;
if (ad->state & PP_AD_STATE_BL_LIN) {
bl = ad->bl_lin[bl >> ad->bl_bright_shift];
@@ -1268,6 +1291,7 @@
int i, ret = 0;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdss_mdp_pipe *vig;
+ struct msm_bus_scale_pdata *pp_bus_pdata;
mutex_lock(&mdss_pp_mutex);
if (!mdss_pp_res) {
@@ -1289,12 +1313,34 @@
mutex_init(&vig[i].pp_res.hist.hist_mutex);
spin_lock_init(&vig[i].pp_res.hist.hist_lock);
}
+ if (!mdata->pp_bus_hdl) {
+ pp_bus_pdata = &mdp_pp_bus_scale_table;
+ for (i = 0; i < pp_bus_pdata->num_usecases; i++) {
+ mdp_pp_bus_usecases[i].num_paths = 1;
+ mdp_pp_bus_usecases[i].vectors =
+ &mdp_pp_bus_vectors[i];
+ }
+
+ mdata->pp_bus_hdl =
+ msm_bus_scale_register_client(pp_bus_pdata);
+ if (!mdata->pp_bus_hdl) {
+ pr_err("not able to register pp_bus_scale\n");
+ ret = -ENOMEM;
+ }
+ pr_debug("register pp_bus_hdl=%x\n", mdata->pp_bus_hdl);
+ }
+
}
mutex_unlock(&mdss_pp_mutex);
return ret;
}
void mdss_mdp_pp_term(struct device *dev)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ if (mdata->pp_bus_hdl) {
+ msm_bus_scale_unregister_client(mdata->pp_bus_hdl);
+ mdata->pp_bus_hdl = 0;
+ }
if (!mdss_pp_res) {
mutex_lock(&mdss_pp_mutex);
devm_kfree(dev, mdss_pp_res);
@@ -1707,35 +1753,48 @@
return ret;
}
static void pp_update_gc_one_lut(u32 offset,
- struct mdp_ar_gc_lut_data *lut_data)
+ struct mdp_ar_gc_lut_data *lut_data,
+ uint8_t num_stages)
{
- int i, start_idx;
+ int i, start_idx, idx;
start_idx = (MDSS_MDP_REG_READ(offset) >> 16) & 0xF;
- for (i = start_idx; i < GC_LUT_SEGMENTS; i++)
- MDSS_MDP_REG_WRITE(offset, lut_data[i].x_start);
- for (i = 0; i < start_idx; i++)
- MDSS_MDP_REG_WRITE(offset, lut_data[i].x_start);
+ for (i = start_idx; i < GC_LUT_SEGMENTS; i++) {
+ idx = min((uint8_t)i, (uint8_t)(num_stages-1));
+ MDSS_MDP_REG_WRITE(offset, lut_data[idx].x_start);
+ }
+ for (i = 0; i < start_idx; i++) {
+ idx = min((uint8_t)i, (uint8_t)(num_stages-1));
+ MDSS_MDP_REG_WRITE(offset, lut_data[idx].x_start);
+ }
offset += 4;
start_idx = (MDSS_MDP_REG_READ(offset) >> 16) & 0xF;
- for (i = start_idx; i < GC_LUT_SEGMENTS; i++)
- MDSS_MDP_REG_WRITE(offset, lut_data[i].slope);
- for (i = 0; i < start_idx; i++)
- MDSS_MDP_REG_WRITE(offset, lut_data[i].slope);
+ for (i = start_idx; i < GC_LUT_SEGMENTS; i++) {
+ idx = min((uint8_t)i, (uint8_t)(num_stages-1));
+ MDSS_MDP_REG_WRITE(offset, lut_data[idx].slope);
+ }
+ for (i = 0; i < start_idx; i++) {
+ idx = min((uint8_t)i, (uint8_t)(num_stages-1));
+ MDSS_MDP_REG_WRITE(offset, lut_data[idx].slope);
+ }
offset += 4;
start_idx = (MDSS_MDP_REG_READ(offset) >> 16) & 0xF;
- for (i = start_idx; i < GC_LUT_SEGMENTS; i++)
- MDSS_MDP_REG_WRITE(offset, lut_data[i].offset);
- for (i = 0; i < start_idx; i++)
- MDSS_MDP_REG_WRITE(offset, lut_data[i].offset);
+ for (i = start_idx; i < GC_LUT_SEGMENTS; i++) {
+ idx = min((uint8_t)i, (uint8_t)(num_stages-1));
+ MDSS_MDP_REG_WRITE(offset, lut_data[idx].offset);
+ }
+ for (i = 0; i < start_idx; i++) {
+ idx = min((uint8_t)i, (uint8_t)(num_stages-1));
+ MDSS_MDP_REG_WRITE(offset, lut_data[idx].offset);
+ }
}
static void pp_update_argc_lut(u32 offset, struct mdp_pgc_lut_data *config)
{
- pp_update_gc_one_lut(offset, config->r_data);
+ pp_update_gc_one_lut(offset, config->r_data, config->num_r_stages);
offset += 0x10;
- pp_update_gc_one_lut(offset, config->g_data);
+ pp_update_gc_one_lut(offset, config->g_data, config->num_g_stages);
offset += 0x10;
- pp_update_gc_one_lut(offset, config->b_data);
+ pp_update_gc_one_lut(offset, config->b_data, config->num_b_stages);
}
static void pp_read_gc_one_lut(u32 offset,
struct mdp_ar_gc_lut_data *gc_data)
@@ -1813,7 +1872,7 @@
u32 argc_offset = 0, disp_num, dspp_num = 0;
struct mdp_pgc_lut_data local_cfg;
struct mdp_pgc_lut_data *pgc_ptr;
- u32 tbl_size;
+ u32 tbl_size, r_size, g_size, b_size;
if (!ctl)
return -EINVAL;
@@ -1884,18 +1943,35 @@
*copyback = 1;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
} else {
+ r_size = config->num_r_stages *
+ sizeof(struct mdp_ar_gc_lut_data);
+ g_size = config->num_g_stages *
+ sizeof(struct mdp_ar_gc_lut_data);
+ b_size = config->num_b_stages *
+ sizeof(struct mdp_ar_gc_lut_data);
+ if (r_size > tbl_size ||
+ g_size > tbl_size ||
+ b_size > tbl_size ||
+ r_size == 0 ||
+ g_size == 0 ||
+ b_size == 0) {
+ ret = -EINVAL;
+ pr_warn("%s, number of rgb stages invalid",
+ __func__);
+ goto argc_config_exit;
+ }
if (copy_from_user(&mdss_pp_res->gc_lut_r[disp_num][0],
- config->r_data, tbl_size)) {
+ config->r_data, r_size)) {
ret = -EFAULT;
goto argc_config_exit;
}
if (copy_from_user(&mdss_pp_res->gc_lut_g[disp_num][0],
- config->g_data, tbl_size)) {
+ config->g_data, g_size)) {
ret = -EFAULT;
goto argc_config_exit;
}
if (copy_from_user(&mdss_pp_res->gc_lut_b[disp_num][0],
- config->b_data, tbl_size)) {
+ config->b_data, b_size)) {
ret = -EFAULT;
goto argc_config_exit;
}
@@ -2537,13 +2613,13 @@
if (ret)
goto hist_collect_exit;
}
+ if (hist->bin_cnt != HIST_V_SIZE) {
+ pr_err("User not expecting size %d output",
+ HIST_V_SIZE);
+ ret = -EINVAL;
+ goto hist_collect_exit;
+ }
if (hist_cnt > 1) {
- if (hist->bin_cnt != HIST_V_SIZE) {
- pr_err("User not expecting size %d output",
- HIST_V_SIZE);
- ret = -EINVAL;
- goto hist_collect_exit;
- }
hist_concat = kmalloc(HIST_V_SIZE * sizeof(u32),
GFP_KERNEL);
if (!hist_concat) {
@@ -2607,13 +2683,14 @@
if (ret)
goto hist_collect_exit;
}
+ if (pipe_cnt != 0 &&
+ (hist->bin_cnt != (HIST_V_SIZE * pipe_cnt))) {
+ pr_err("User not expecting size %d output",
+ pipe_cnt * HIST_V_SIZE);
+ ret = -EINVAL;
+ goto hist_collect_exit;
+ }
if (pipe_cnt > 1) {
- if (hist->bin_cnt != (HIST_V_SIZE * pipe_cnt)) {
- pr_err("User not expecting size %d output",
- pipe_cnt * HIST_V_SIZE);
- ret = -EINVAL;
- goto hist_collect_exit;
- }
hist_concat = kmalloc(HIST_V_SIZE * pipe_cnt *
sizeof(u32), GFP_KERNEL);
if (!hist_concat) {
@@ -2716,6 +2793,22 @@
};
}
+static struct msm_fb_data_type *mdss_get_mfd_from_index(int index)
+{
+ struct msm_fb_data_type *out = NULL;
+ struct mdss_mdp_ctl *ctl;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ int i;
+
+ for (i = 0; i < mdata->nctl; i++) {
+ ctl = mdata->ctl_off + i;
+ if ((ctl->power_on) && (ctl->mfd)
+ && (ctl->mfd->index == index))
+ out = ctl->mfd;
+ }
+ return out;
+}
+
#define MDSS_AD_MAX_MIXERS 1
static int mdss_ad_init_checks(struct msm_fb_data_type *mfd)
{
@@ -2724,8 +2817,12 @@
u32 ret = -EINVAL;
int i = 0;
struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+ struct msm_fb_data_type *ad_mfd = mfd;
- if (!mfd || !mdata)
+ if (ad_mfd->ext_ad_ctrl >= 0)
+ ad_mfd = mdss_get_mfd_from_index(ad_mfd->ext_ad_ctrl);
+
+ if (!ad_mfd || !mdata)
return ret;
if (mdata->nad_cfgs == 0) {
@@ -2733,12 +2830,7 @@
return -ENODEV;
}
- if (mfd->panel_info->type == MIPI_CMD_PANEL) {
- pr_debug("Command panel not supported");
- return -EINVAL;
- }
-
- mixer_num = mdss_mdp_get_ctl_mixers(mfd->index, mixer_id);
+ mixer_num = mdss_mdp_get_ctl_mixers(ad_mfd->index, mixer_id);
if (!mixer_num) {
pr_debug("no mixers connected, %d", mixer_num);
return -EHOSTDOWN;
@@ -2811,12 +2903,20 @@
{
struct mdss_ad_info *ad;
struct mdss_mdp_ctl *ctl;
+ struct msm_fb_data_type *bl_mfd;
int lin_ret = -1, inv_ret = -1, ret = 0;
u32 ratio_temp, shift = 0;
ret = mdss_mdp_get_ad(mfd, &ad);
if (ret)
return ret;
+ if (mfd->panel_info->type == WRITEBACK_PANEL) {
+ bl_mfd = mdss_get_mfd_from_index(0);
+ if (!bl_mfd)
+ return ret;
+ } else {
+ bl_mfd = mfd;
+ }
mutex_lock(&ad->lock);
if (init_cfg->ops & MDP_PP_AD_INIT) {
@@ -2853,7 +2953,7 @@
* TODO: specify panel independent range of input from cfg,
* scale input backlight_scale to panel bl_max's range
*/
- ad->cfg.backlight_scale = mfd->panel_info->bl_max;
+ ad->cfg.backlight_scale = bl_mfd->panel_info->bl_max;
ad->sts |= PP_AD_STS_DIRTY_CFG;
}
@@ -2863,9 +2963,11 @@
cancel_work_sync(&ad->calc_work);
mutex_lock(&ad->lock);
ad->mfd = NULL;
+ ad->bl_mfd = NULL;
} else if (!ret && (init_cfg->ops & MDP_PP_OPS_ENABLE)) {
ad->sts |= PP_STS_ENABLE;
ad->mfd = mfd;
+ ad->bl_mfd = bl_mfd;
}
mutex_unlock(&ad->lock);
ctl = mfd_to_ctl(mfd);
@@ -2902,7 +3004,7 @@
goto error;
}
ad->ad_data_mode = MDSS_AD_INPUT_AMBIENT;
-
+ pr_debug("ambient = %d", input->in.amb_light);
ad->ad_data = input->in.amb_light;
ad->calc_itr = ad->cfg.stab_itr;
ad->sts |= PP_AD_STS_DIRTY_VSYNC;
@@ -2916,6 +3018,7 @@
goto error;
}
ad->ad_data_mode = MDSS_AD_INPUT_STRENGTH;
+ pr_debug("strength = %d", input->in.strength);
ad->ad_data = input->in.strength;
ad->calc_itr = ad->cfg.stab_itr;
ad->sts |= PP_AD_STS_DIRTY_VSYNC;
@@ -3090,12 +3193,21 @@
int ret = 0;
struct mdss_ad_info *ad;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+ struct msm_fb_data_type *bl_mfd;
char __iomem *base;
u32 bypass = MDSS_PP_AD_BYPASS_DEF, bl;
ret = mdss_mdp_get_ad(mfd, &ad);
if (ret)
return ret;
+ if (mfd->panel_info->type == WRITEBACK_PANEL) {
+ bl_mfd = mdss_get_mfd_from_index(0);
+ if (!bl_mfd)
+ return ret;
+ } else {
+ bl_mfd = mfd;
+ }
+
base = ad->base;
@@ -3115,21 +3227,21 @@
*/
ad->sts &= ~PP_AD_STS_DIRTY_DATA;
ad->state |= PP_AD_STATE_DATA;
- bl = 0;
- if (MDSS_AD_RUNNING_AUTO_STR(ad) || ad->last_bl == 0) {
- mutex_lock(&mfd->bl_lock);
- bl = mfd->bl_level;
- if (bl != ad->last_bl) {
- ad->last_bl = bl;
- ad->calc_itr = ad->cfg.stab_itr;
- ad->sts |= PP_AD_STS_DIRTY_VSYNC;
- }
+ mutex_lock(&bl_mfd->bl_lock);
+ bl = bl_mfd->bl_level;
+ pr_debug("dirty data, last_bl = %d ", ad->last_bl);
+ if ((ad->cfg.mode == MDSS_AD_MODE_AUTO_STR) &&
+ (ad->last_bl != bl)) {
+ ad->last_bl = bl;
+ ad->calc_itr = ad->cfg.stab_itr;
+ ad->sts |= PP_AD_STS_DIRTY_VSYNC;
if (ad->state & PP_AD_STATE_BL_LIN) {
bl = ad->bl_lin[bl >> ad->bl_bright_shift];
bl = bl << ad->bl_bright_shift;
}
- mutex_unlock(&mfd->bl_lock);
+ mutex_unlock(&bl_mfd->bl_lock);
}
+ mutex_unlock(&mfd->bl_lock);
pp_ad_input_write(ad, bl);
}
@@ -3155,10 +3267,12 @@
bypass = 0;
ret = 1;
ad->state |= PP_AD_STATE_RUN;
- mutex_lock(&mfd->bl_lock);
- mfd->mdp.update_ad_input = pp_update_ad_input;
- mfd->ext_bl_ctrl = ad->cfg.bl_ctrl_mode;
- mutex_unlock(&mfd->bl_lock);
+ mutex_lock(&bl_mfd->bl_lock);
+ if (bl_mfd != mfd)
+ bl_mfd->ext_ad_ctrl = mfd->index;
+ bl_mfd->mdp.update_ad_input = pp_update_ad_input;
+ bl_mfd->ext_bl_ctrl = ad->cfg.bl_ctrl_mode;
+ mutex_unlock(&bl_mfd->bl_lock);
} else {
if (ad->state & PP_AD_STATE_RUN) {
@@ -3173,6 +3287,7 @@
ad->bl_bright_shift = 0;
ad->ad_data = 0;
ad->ad_data_mode = 0;
+ ad->last_bl = 0;
ad->calc_itr = 0;
memset(&ad->bl_lin, 0, sizeof(uint32_t) *
AD_BL_LIN_LEN);
@@ -3180,10 +3295,11 @@
AD_BL_LIN_LEN);
memset(&ad->init, 0, sizeof(struct mdss_ad_init));
memset(&ad->cfg, 0, sizeof(struct mdss_ad_cfg));
- mutex_lock(&mfd->bl_lock);
- mfd->mdp.update_ad_input = NULL;
- mfd->ext_bl_ctrl = 0;
- mutex_unlock(&mfd->bl_lock);
+ mutex_lock(&bl_mfd->bl_lock);
+ bl_mfd->mdp.update_ad_input = NULL;
+ bl_mfd->ext_bl_ctrl = 0;
+ bl_mfd->ext_ad_ctrl = -1;
+ mutex_unlock(&bl_mfd->bl_lock);
}
ad->state &= ~PP_AD_STATE_RUN;
}
@@ -3218,18 +3334,24 @@
{
struct mdss_ad_info *ad;
struct mdss_mdp_ctl *ctl;
- struct msm_fb_data_type *mfd;
+ struct msm_fb_data_type *mfd, *bl_mfd;
u32 bl, calc_done = 0;
ad = container_of(work, struct mdss_ad_info, calc_work);
mutex_lock(&ad->lock);
- if (!ad->mfd || !(ad->sts & PP_STS_ENABLE)) {
+ if (!ad->mfd || !ad->bl_mfd || !(ad->sts & PP_STS_ENABLE)) {
mutex_unlock(&ad->lock);
return;
}
mfd = ad->mfd;
+ bl_mfd = ad->bl_mfd;
ctl = mfd_to_ctl(ad->mfd);
+ if ((ad->cfg.mode == MDSS_AD_MODE_AUTO_STR) && (ad->last_bl == 0)) {
+ mutex_unlock(&ad->lock);
+ return;
+ }
+
if (PP_AD_STATE_RUN & ad->state) {
/* Kick off calculation */
ad->calc_itr--;
@@ -3257,9 +3379,10 @@
}
pr_debug("calc bl = %d", bl);
ad->last_str |= bl << 16;
- mutex_lock(&ad->mfd->bl_lock);
- mdss_fb_set_backlight(ad->mfd, bl);
- mutex_unlock(&ad->mfd->bl_lock);
+ mutex_lock(&ad->bl_mfd->bl_lock);
+ if (ad->bl_mfd->bl_level)
+ mdss_fb_set_backlight(ad->bl_mfd, bl);
+ mutex_unlock(&ad->bl_mfd->bl_lock);
}
pr_debug("calc_str = %d, calc_itr %d",
ad->last_str & 0xFF,
@@ -3280,7 +3403,7 @@
mutex_unlock(&mfd->lock);
/* Trigger update notify to wake up those waiting for display updates */
- mdss_fb_update_notify_update(mfd);
+ mdss_fb_update_notify_update(bl_mfd);
}
#define PP_AD_LUT_LEN 33
@@ -3318,8 +3441,10 @@
mdata->ad_cfgs[i].num = i;
mdata->ad_cfgs[i].calc_itr = 0;
mdata->ad_cfgs[i].last_str = 0xFFFFFFFF;
+ mdata->ad_cfgs[i].last_bl = 0;
mutex_init(&mdata->ad_cfgs[i].lock);
mdata->ad_cfgs[i].handle.vsync_handler = pp_ad_vsync_handler;
+ mdata->ad_cfgs[i].handle.cmd_post_flush = true;
INIT_WORK(&mdata->ad_cfgs[i].calc_work, pp_ad_calc_worker);
}
return rc;
@@ -3376,7 +3501,7 @@
ret = 1;
else if (ptr >= 0x3220 && ptr <= 0x3228)
ret = 1;
- else if (ptr >= 0x3200 || ptr == 0x100)
+ else if (ptr == 0x3200 || ptr == 0x100)
ret = 1;
else if (ptr == 0x104 || ptr == 0x614 || ptr == 0x714 ||
ptr == 0x814 || ptr == 0x914 || ptr == 0xa14)
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 833bf14..d05ca66 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -64,11 +64,16 @@
MDSS_PANEL_INTF_HDMI,
};
+enum {
+ MODE_GPIO_NOT_VALID = 0,
+ MODE_GPIO_HIGH,
+ MODE_GPIO_LOW,
+};
+
#define MDSS_MAX_PANEL_LEN 256
#define MDSS_INTF_MAX_NAME_LEN 5
struct mdss_panel_intf {
char name[MDSS_INTF_MAX_NAME_LEN];
- u8 len;
int type;
};
@@ -155,9 +160,9 @@
uint32_t timing[12];
uint32_t ctrl[4];
uint32_t strength[2];
- char bistCtrl[6];
+ char bistctrl[6];
uint32_t pll[21];
- char laneCfg[45];
+ char lanecfg[45];
};
struct mipi_panel_info {
@@ -180,7 +185,7 @@
char t_clk_post; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
char t_clk_pre; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
char vc; /* virtual channel */
- struct mdss_dsi_phy_ctrl *dsi_phy_db;
+ struct mdss_dsi_phy_ctrl dsi_phy_db;
/* video mode */
char pulse_mode_hsa_he;
char hfp_power_stop;
@@ -263,6 +268,7 @@
int pwm_pmic_gpio;
int pwm_lpg_chan;
int pwm_period;
+ u32 mode_gpio_state;
u32 cont_splash_enabled;
struct ion_handle *splash_ihdl;
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 7b89eff..d24daab 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -504,7 +504,7 @@
return;
}
- pd = ((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db;
+ pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
/* Strength ctrl 0 */
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, pd->strength[0]);
@@ -564,7 +564,7 @@
for (i = 0; i < 9; i++) {
offset = i + (ln * 9);
MIPI_OUTP((ctrl_pdata->ctrl_base) + off,
- pd->laneCfg[offset]);
+ pd->lanecfg[offset]);
wmb();
off += 4;
}
@@ -583,7 +583,7 @@
off = 0x04b4; /* phy BIST ctrl 0 - 5 */
for (i = 0; i < 6; i++) {
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->bistCtrl[i]);
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->bistctrl[i]);
wmb();
off += 4;
}
diff --git a/include/linux/coresight-cti.h b/include/linux/coresight-cti.h
index 7f2da3f..c3dce9f 100644
--- a/include/linux/coresight-cti.h
+++ b/include/linux/coresight-cti.h
@@ -34,6 +34,7 @@
struct coresight_cti *cti, int trig, int ch);
extern void coresight_cti_unmap_trigout(
struct coresight_cti *cti, int trig, int ch);
+extern void coresight_cti_reset(struct coresight_cti *cti);
#else
static inline struct coresight_cti *coresight_cti_get(const char *name)
{
@@ -54,6 +55,7 @@
struct coresight_cti *cti, int trig, int ch) {}
static inline void coresight_cti_unmap_trigout(
struct coresight_cti *cti, int trig, int ch) {}
+static inline void coresight_cti_reset(struct coresight_cti *cti) {}
#endif
#endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 5b69884..fbd5fb0 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -41,6 +41,7 @@
CORESIGHT_CLK_RATE_OFF,
CORESIGHT_CLK_RATE_TRACE = 1000,
CORESIGHT_CLK_RATE_HSTRACE = 2000,
+ CORESIGHT_CLK_RATE_FIXED = 3000,
};
enum coresight_dev_type {
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 5df022e..6716ce3 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -43,6 +43,15 @@
* @reset_gpio: reset gpio
* @panel_x: panel maximum values on the x
* @panel_y: panel maximum values on the y
+ * @disp_maxx: display panel maximum values on the x
+ * @disp_maxy: display panel maximum values on the y
+ * @disp_minx: display panel minimum values on the x
+ * @disp_miny: display panel minimum values on the y
+ * @panel_maxx: touch panel maximum values on the x
+ * @panel_maxy: touch panel maximum values on the y
+ * @panel_minx: touch panel minimum values on the x
+ * @panel_miny: touch panel minimum values on the y
+ * @reset_delay: reset delay
* @gpio_config: pointer to gpio configuration function
* @capacitance_button_map: pointer to 0d button map
*/
@@ -52,12 +61,20 @@
bool i2c_pull_up;
bool power_down_enable;
bool disable_gpios;
+ bool do_lockdown;
unsigned irq_gpio;
u32 irq_flags;
u32 reset_flags;
unsigned reset_gpio;
- unsigned panel_x;
- unsigned panel_y;
+ unsigned panel_minx;
+ unsigned panel_miny;
+ unsigned panel_maxx;
+ unsigned panel_maxy;
+ unsigned disp_minx;
+ unsigned disp_miny;
+ unsigned disp_maxx;
+ unsigned disp_maxy;
+ unsigned reset_delay;
const char *fw_image_name;
int (*gpio_config)(unsigned gpio, bool configure);
struct synaptics_rmi4_capacitance_button_map *capacitance_button_map;
diff --git a/include/linux/stk3x1x.h b/include/linux/stk3x1x.h
index d9d2cf6..6dd446c 100644
--- a/include/linux/stk3x1x.h
+++ b/include/linux/stk3x1x.h
@@ -24,6 +24,7 @@
int int_pin;
uint32_t transmittance;
uint32_t int_flags;
+ bool use_fir;
};
#endif /* __STK3X1X_H__ */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 6fcafa8..6a0259d 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -282,10 +282,8 @@
struct winsize winsize; /* termios mutex */
unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
unsigned char low_latency:1, warned:1;
- unsigned char update_room_in_ldisc:1;
unsigned char ctrl_status; /* ctrl_lock */
unsigned int receive_room; /* Bytes free for queue */
- unsigned int rr_bug;
struct tty_struct *link;
struct fasync_struct *fasync;
diff --git a/include/linux/usb/android.h b/include/linux/usb/android.h
index 0b11fdaf..e17e978 100644
--- a/include/linux/usb/android.h
+++ b/include/linux/usb/android.h
@@ -24,6 +24,7 @@
u32 swfi_latency;
u8 usb_core_id;
bool cdrom;
+ bool internal_ums;
};
#ifndef CONFIG_TARGET_CORE
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index ac8d7f8..f462b64 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -563,6 +563,7 @@
#ifdef CONFIG_USB_DWC3_MSM
int msm_ep_config(struct usb_ep *ep);
int msm_ep_unconfig(struct usb_ep *ep);
+void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enable);
int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
u8 dst_pipe_idx);
@@ -586,6 +587,12 @@
return -ENODEV;
}
+static inline void dwc3_tx_fifo_resize_request(
+ struct usb_ep *ep, bool qdss_enable)
+{
+ return;
+}
+
static inline void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
{
return;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 38877cc..e1c096b 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -403,6 +403,7 @@
#define V4L2_PIX_FMT_DIVX v4l2_fourcc('D', 'I', 'V', 'X') /* DIVX */
#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* ON2 VP8 stream */
#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') /* for HEVC stream */
+#define V4L2_PIX_FMT_HEVC_HYBRID v4l2_fourcc('H', 'V', 'C', 'H')
/* Vendor-specific formats */
#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -705,6 +706,7 @@
#define V4L2_QCOM_BUF_DATA_CORRUPT 0x80000
#define V4L2_QCOM_BUF_DROP_FRAME 0x100000
#define V4L2_QCOM_BUF_INPUT_UNSUPPORTED 0x200000
+#define V4L2_QCOM_BUF_FLAG_EOS 0x2000
/*
* O V E R L A Y P R E V I E W
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index e07f634..6f121b3 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -16,6 +16,7 @@
#define ADM_PATH_PLAYBACK 0x1
#define ADM_PATH_LIVE_REC 0x2
#define ADM_PATH_NONLIVE_REC 0x3
+#include <mach/qdsp6v2/rtac.h>
#include <sound/q6afe-v2.h>
#include <sound/q6audio-v2.h>
@@ -41,11 +42,16 @@
int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
int topology, bool perf_mode, uint16_t bits_per_sample);
+int adm_unmap_cal_blocks(void);
+
+int adm_map_rtac_block(struct rtac_cal_block_data *cal_block);
+
+int adm_unmap_rtac_block(uint32_t *mem_map_handle);
+
int adm_memory_map_regions(int port_id, uint32_t *buf_add, uint32_t mempool_id,
uint32_t *bufsz, uint32_t bufcnt);
-int adm_memory_unmap_regions(int port_id, uint32_t *buf_add, uint32_t *bufsz,
- uint32_t bufcnt);
+int adm_memory_unmap_regions(int port_id);
int adm_close(int port, bool perf_mode);
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 12934aa..3fc85b2 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -92,7 +92,8 @@
MAD_HW_NONE = 0x00,
MAD_HW_AUDIO = 0x01,
MAD_HW_BEACON = 0x02,
- MAD_HW_ULTRASOUND = 0x04
+ MAD_HW_ULTRASOUND = 0x04,
+ MAD_SW_AUDIO = 0x05,
};
struct afe_audio_buffer {
@@ -148,6 +149,7 @@
int afe_start_pseudo_port(u16 port_id);
int afe_stop_pseudo_port(u16 port_id);
uint32_t afe_req_mmap_handle(struct afe_audio_client *ac);
+int afe_unmap_cal_blocks(void);
int afe_memory_map(u32 dma_addr_p, u32 dma_buf_sz, struct afe_audio_client *ac);
int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz);
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index bd4cddf..0dd1f1c 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -13,6 +13,7 @@
#define __Q6_ASM_V2_H__
#include <mach/qdsp6v2/apr.h>
+#include <mach/qdsp6v2/rtac.h>
#include <sound/apr_audio-v2.h>
#include <linux/list.h>
#include <linux/msm_ion.h>
@@ -76,7 +77,8 @@
#define SOFT_PAUSE_ENABLE 1
#define SOFT_PAUSE_DISABLE 0
-#define SESSION_MAX 0x08
+#define SESSION_MAX 0x08
+#define ASM_CONTROL_SESSION 0x0F
/* payload structure bytes */
#define READDONE_IDX_STATUS 0
@@ -224,6 +226,12 @@
int q6asm_memory_unmap(struct audio_client *ac, uint32_t buf_add,
int dir);
+int q6asm_unmap_cal_blocks(void);
+
+int q6asm_map_rtac_block(struct rtac_cal_block_data *cal_block);
+
+int q6asm_unmap_rtac_block(uint32_t *mem_map_handle);
+
int q6asm_run(struct audio_client *ac, uint32_t flags,
uint32_t msw_ts, uint32_t lsw_ts);
diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h
index d7a01a0..34eba81 100644
--- a/include/sound/q6lsm.h
+++ b/include/sound/q6lsm.h
@@ -19,7 +19,7 @@
#include <sound/lsm_params.h>
#include <mach/qdsp6v2/apr.h>
-typedef void (*app_cb)(uint32_t opcode, uint32_t token,
+typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
uint32_t *payload, void *priv);
struct lsm_sound_model {
@@ -34,7 +34,7 @@
struct lsm_client {
int session;
- app_cb cb;
+ lsm_app_cb cb;
atomic_t cmd_state;
void *priv;
struct apr_svc *apr;
@@ -118,7 +118,7 @@
uint32_t mem_map_handle;
} __packed;
-struct lsm_client *q6lsm_client_alloc(app_cb cb, void *priv);
+struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv);
void q6lsm_client_free(struct lsm_client *client);
int q6lsm_open(struct lsm_client *client);
int q6lsm_start(struct lsm_client *client, bool wait);
@@ -126,6 +126,7 @@
int q6lsm_snd_model_buf_alloc(struct lsm_client *client, uint32_t len);
int q6lsm_snd_model_buf_free(struct lsm_client *client);
int q6lsm_close(struct lsm_client *client);
+int q6lsm_unmap_cal_blocks(void);
int q6lsm_register_sound_model(struct lsm_client *client,
enum lsm_detection_mode mode, u16 minkeyword,
u16 minuser, bool detectfailure);
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 0131170..3db5820 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -154,7 +154,7 @@
* down, but we are still initializing the system. Pages are given directly
* to the page allocator, no bootmem metadata is updated because it is gone.
*/
-void __init free_bootmem_late(unsigned long addr, unsigned long size)
+void free_bootmem_late(unsigned long addr, unsigned long size)
{
unsigned long cursor, end;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 9cc2f45..46ccd2f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -745,7 +745,7 @@
local_irq_restore(flags);
}
-void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
+void __free_pages_bootmem(struct page *page, unsigned int order)
{
unsigned int nr_pages = 1 << order;
unsigned int loop;
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index bd4f926..fb115e7 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -1910,6 +1910,13 @@
{"EAR PA", NULL, "DAC1"},
{"DAC1", NULL, "CP"},
+ /* Clocks for playback path */
+ {"DAC1", NULL, "EAR CLK"},
+ {"HPHL DAC", NULL, "HPHL CLK"},
+ {"HPHR DAC", NULL, "HPHR CLK"},
+ {"SPK DAC", NULL, "SPK CLK"},
+ {"LINEOUT DAC", NULL, "LINEOUT CLK"},
+
/* Headset (RX MIX1 and RX MIX2) */
{"HEADPHONE", NULL, "HPHL"},
{"HEADPHONE", NULL, "HPHR"},
@@ -2336,6 +2343,17 @@
SND_SOC_DAPM_MIXER("RX3 CHAIN", MSM8X10_WCD_A_CDC_RX3_B6_CTL,
5, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("HPHR CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("HPHL CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("EAR CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 2, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("LINEOUT CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 3, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SPK CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 4, 0, NULL, 0),
+
SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
&rx_mix1_inp1_mux),
SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index c509b08..4e07d7f 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -45,6 +45,15 @@
#define TAPAN_VDD_CX_OPTIMAL_UA 10000
#define TAPAN_VDD_CX_SLEEP_UA 2000
+/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
+#define TAPAN_WG_TIME_FACTOR_US 240
+
+#define TAPAN_SB_PGD_PORT_RX_BASE 0x40
+#define TAPAN_SB_PGD_PORT_TX_BASE 0x50
+#define TAPAN_REGISTER_START_OFFSET 0x800
+
+#define CODEC_REG_CFG_MINOR_VER 1
+
static struct regulator *tapan_codec_find_regulator(
struct snd_soc_codec *codec,
const char *name);
@@ -97,6 +106,60 @@
static enum tapan_codec_type codec_ver;
+/*
+ * Multiplication factor to compute impedance on Tapan
+ * This is computed from (Vx / (m*Ical)) = (10mV/(180*30uA))
+ */
+#define TAPAN_ZDET_MUL_FACTOR 1852
+
+static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_SB_PGD_PORT_TX_BASE),
+ SB_PGD_PORT_TX_WATERMARK_N, 0x1E, 8, 0x1
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_SB_PGD_PORT_TX_BASE),
+ SB_PGD_PORT_TX_ENABLE_N, 0x1, 8, 0x1
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_SB_PGD_PORT_RX_BASE),
+ SB_PGD_PORT_RX_WATERMARK_N, 0x1E, 8, 0x1
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_SB_PGD_PORT_RX_BASE),
+ SB_PGD_PORT_RX_ENABLE_N, 0x1, 8, 0x1
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_A_CDC_ANC1_IIR_B1_CTL),
+ AANC_FF_GAIN_ADAPTIVE, 0x4, 8, 0
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_A_CDC_ANC1_IIR_B1_CTL),
+ AANC_FFGAIN_ADAPTIVE_EN, 0x8, 8, 0
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_A_CDC_ANC1_GAIN_CTL),
+ AANC_GAIN_CONTROL, 0xFF, 8, 0
+ },
+};
+
+static struct afe_param_cdc_reg_cfg_data tapan_audio_reg_cfg = {
+ .num_registers = ARRAY_SIZE(audio_reg_cfg),
+ .reg_data = audio_reg_cfg,
+};
+
+static struct afe_param_id_cdc_aanc_version tapan_cdc_aanc_version = {
+ .cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
+ .aanc_hw_version = AANC_HW_BLOCK_VERSION_2,
+};
+
enum {
AIF1_PB = 0,
AIF1_CAP,
@@ -241,6 +304,8 @@
bool spkr_pa_widget_on;
+ struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
+
/* resmgr module */
struct wcd9xxx_resmgr resmgr;
/* mbhc module */
@@ -251,6 +316,15 @@
/* pointers to regulators required for chargepump */
struct regulator *cp_regulators[CP_REG_MAX];
+
+ /*
+ * list used to save/restore registers at start and
+ * end of impedance measurement
+ */
+ struct list_head reg_save_restore;
+
+ int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
+ enum wcd9xxx_codec_event);
};
static const u32 comp_shift[] = {
@@ -2949,6 +3023,9 @@
static int tapan_volatile(struct snd_soc_codec *ssc, unsigned int reg)
{
+
+ int i = 0;
+
/* Registers lower than 0x100 are top level registers which can be
* written by the Tapan core driver.
*/
@@ -2982,6 +3059,11 @@
if (reg == TAPAN_A_MBHC_INSERT_DET_STATUS)
return 1;
+ for (i = 0; i < ARRAY_SIZE(audio_reg_cfg); i++)
+ if (audio_reg_cfg[i].reg_logical_addr -
+ TAPAN_REGISTER_START_OFFSET == reg)
+ return 1;
+
return 0;
}
@@ -4807,6 +4889,46 @@
{TAPAN_A_RX_HPH_CHOP_CTL, 0xFF, 0x24},
};
+void *tapan_get_afe_config(struct snd_soc_codec *codec,
+ enum afe_config_type config_type)
+{
+ struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ switch (config_type) {
+ case AFE_SLIMBUS_SLAVE_CONFIG:
+ return &priv->slimbus_slave_cfg;
+ case AFE_CDC_REGISTERS_CONFIG:
+ return &tapan_audio_reg_cfg;
+ case AFE_AANC_VERSION:
+ return &tapan_cdc_aanc_version;
+ default:
+ pr_err("%s: Unknown config_type 0x%x\n", __func__, config_type);
+ return NULL;
+ }
+}
+
+static void tapan_init_slim_slave_cfg(struct snd_soc_codec *codec)
+{
+ struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct afe_param_cdc_slimbus_slave_cfg *cfg;
+ struct wcd9xxx *wcd9xxx = codec->control_data;
+ uint64_t eaddr = 0;
+
+ pr_debug("%s\n", __func__);
+ cfg = &priv->slimbus_slave_cfg;
+ cfg->minor_version = 1;
+ cfg->tx_slave_port_offset = 0;
+ cfg->rx_slave_port_offset = 16;
+
+ memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
+ /* e-addr is 6-byte elemental address of the device */
+ WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
+ cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
+ cfg->device_enum_addr_msw = eaddr >> 32;
+
+ pr_debug("%s: slimbus logical address 0x%llx\n", __func__, eaddr);
+}
+
static void tapan_codec_init_reg(struct snd_soc_codec *codec)
{
u32 i;
@@ -4917,6 +5039,255 @@
return WCD9XXX_CDC_TYPE_TAPAN;
}
+static void wcd9xxx_prepare_hph_pa(struct wcd9xxx_mbhc *mbhc,
+ struct list_head *lh)
+{
+ int i;
+ struct snd_soc_codec *codec = mbhc->codec;
+ u32 delay;
+
+ const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
+ {WCD9XXX_A_CDC_CLSH_B1_CTL, 0x0F, 0x00},
+ {WCD9XXX_A_RX_HPH_CHOP_CTL, 0xFF, 0xA4},
+ {WCD9XXX_A_RX_HPH_OCP_CTL, 0xFF, 0x67},
+ {WCD9XXX_A_RX_HPH_L_TEST, 0x1, 0x0},
+ {WCD9XXX_A_RX_HPH_R_TEST, 0x1, 0x0},
+ {WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xFF, 0x1A},
+ {WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDB},
+ {WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xFF, 0x2A},
+ {TAPAN_A_CDC_CONN_RX2_B2_CTL, 0xFF, 0x10},
+ {WCD9XXX_A_CDC_CLK_OTHR_CTL, 0xFF, 0x05},
+ {WCD9XXX_A_CDC_RX1_B6_CTL, 0xFF, 0x81},
+ {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x03, 0x03},
+ {WCD9XXX_A_RX_HPH_L_GAIN, 0xFF, 0x2C},
+ {WCD9XXX_A_CDC_RX2_B6_CTL, 0xFF, 0x81},
+ {WCD9XXX_A_RX_HPH_R_GAIN, 0xFF, 0x2C},
+ {WCD9XXX_A_BUCK_CTRL_CCL_4, 0xFF, 0x50},
+ {WCD9XXX_A_BUCK_CTRL_VCL_1, 0xFF, 0x08},
+ {WCD9XXX_A_BUCK_CTRL_CCL_1, 0xFF, 0x5B},
+ {WCD9XXX_A_NCP_CLK, 0xFF, 0x9C},
+ {WCD9XXX_A_NCP_CLK, 0xFF, 0xFC},
+ {WCD9XXX_A_BUCK_MODE_3, 0xFF, 0xCE},
+ {WCD9XXX_A_BUCK_CTRL_CCL_3, 0xFF, 0x6B},
+ {WCD9XXX_A_BUCK_CTRL_CCL_3, 0xFF, 0x6F},
+ {TAPAN_A_RX_BUCK_BIAS1, 0xFF, 0x62},
+ {TAPAN_A_RX_HPH_BIAS_PA, 0xFF, 0x7A},
+ {TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL, 0xFF, 0x02},
+ {TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL, 0xFF, 0x06},
+ {WCD9XXX_A_RX_COM_BIAS, 0xFF, 0x80},
+ {WCD9XXX_A_BUCK_MODE_3, 0xFF, 0xC6},
+ {WCD9XXX_A_BUCK_MODE_4, 0xFF, 0xE6},
+ {WCD9XXX_A_BUCK_MODE_5, 0xFF, 0x02},
+ {WCD9XXX_A_BUCK_MODE_1, 0xFF, 0xA1},
+ /* Delay 1ms */
+ {WCD9XXX_A_NCP_EN, 0xFF, 0xFF},
+ /* Delay 1ms */
+ {WCD9XXX_A_BUCK_MODE_5, 0xFF, 0x03},
+ {WCD9XXX_A_BUCK_MODE_5, 0xFF, 0x7B},
+ {WCD9XXX_A_CDC_CLSH_B1_CTL, 0xFF, 0xE6},
+ {WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xFF, 0x40},
+ {WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xFF, 0xC0},
+ {WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xFF, 0x40},
+ {WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xFF, 0xC0},
+ {WCD9XXX_A_NCP_STATIC, 0xFF, 0x08},
+ {WCD9XXX_A_RX_HPH_L_DAC_CTL, 0x03, 0x01},
+ {WCD9XXX_A_RX_HPH_R_DAC_CTL, 0x03, 0x01},
+ };
+
+ /*
+ * Configure PA in class-AB, -18dB gain,
+ * companding off, OCP off, Chopping ON
+ */
+ for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++) {
+ /*
+ * Some of the codec registers like BUCK_MODE_1
+ * and NCP_EN requires 1ms wait time for them
+ * to take effect. Other register writes for
+ * PA configuration do not require any wait time.
+ */
+ if (reg_set_paon[i].reg == WCD9XXX_A_BUCK_MODE_1 ||
+ reg_set_paon[i].reg == WCD9XXX_A_NCP_EN)
+ delay = 1000;
+ else
+ delay = 0;
+ wcd9xxx_soc_update_bits_push(codec, lh,
+ reg_set_paon[i].reg,
+ reg_set_paon[i].mask,
+ reg_set_paon[i].val, delay);
+ }
+ pr_debug("%s: PAs are prepared\n", __func__);
+ return;
+}
+
+static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
+{
+ struct snd_soc_codec *codec = mbhc->codec;
+ int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
+ TAPAN_WG_TIME_FACTOR_US;
+ /*
+ * Tapan requires additional time to enable PA.
+ * It is observed during experiments that we need
+ * an additional wait time about 0.35 times of
+ * the WG_TIME
+ */
+ wg_time += (int) (wg_time * 35) / 100;
+
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
+ enable ? 0x30 : 0x0);
+ /* Wait for wave gen time to avoid pop noise */
+ usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
+ enable ? "enabled" : "disabled", wg_time);
+ return 0;
+}
+
+static int tapan_setup_zdet(struct wcd9xxx_mbhc *mbhc,
+ enum mbhc_impedance_detect_stages stage)
+{
+
+ int ret = 0;
+ struct snd_soc_codec *codec = mbhc->codec;
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ const int mux_wait_us = 25;
+
+ switch (stage) {
+
+ case PRE_MEAS:
+ INIT_LIST_HEAD(&tapan->reg_save_restore);
+ /* Configure PA */
+ wcd9xxx_prepare_hph_pa(mbhc, &tapan->reg_save_restore);
+
+#define __wr(reg, mask, value) \
+ do { \
+ ret = wcd9xxx_soc_update_bits_push(codec, \
+ &tapan->reg_save_restore, \
+ reg, mask, value, 0); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+ /* Setup MBHC */
+ __wr(WCD9XXX_A_MBHC_SCALING_MUX_1, 0x7F, 0x40);
+ __wr(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
+ __wr(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xFF, 0x78);
+ __wr(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0xEC);
+ __wr(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0xFF, 0x45);
+ __wr(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x80);
+
+ __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
+ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
+ __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
+
+ /* Enable Impedance Detection */
+ __wr(WCD9XXX_A_MBHC_HPH, 0xFF, 0xC8);
+
+ /*
+ * CnP setup for 0mV
+ * Route static data as input to noise shaper
+ */
+ __wr(TAPAN_A_CDC_RX1_B3_CTL, 0xFF, 0x02);
+ __wr(TAPAN_A_CDC_RX2_B3_CTL, 0xFF, 0x02);
+
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_TEST,
+ 0x02, 0x00);
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_TEST,
+ 0x02, 0x00);
+
+ /* Reset the HPHL static data pointer */
+ __wr(TAPAN_A_CDC_RX1_B2_CTL, 0xFF, 0x00);
+ /* Four consecutive writes to set 0V as static data input */
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+
+ /* Reset the HPHR static data pointer */
+ __wr(TAPAN_A_CDC_RX2_B2_CTL, 0xFF, 0x00);
+ /* Four consecutive writes to set 0V as static data input */
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+
+ /* Enable the HPHL and HPHR PA */
+ wcd9xxx_enable_static_pa(mbhc, true);
+ break;
+ case POST_MEAS:
+ /* Turn off ICAL */
+ snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_2, 0xF0);
+
+ wcd9xxx_enable_static_pa(mbhc, false);
+
+ /*
+ * Setup CnP wavegen to ramp to the desired
+ * output using a 40ms ramp
+ */
+
+ /* CnP wavegen current to 0.5uA */
+ snd_soc_write(codec, WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0x1A);
+ /* Set the current division ratio to 2000 */
+ snd_soc_write(codec, WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xDF);
+ /* Set the wavegen timer to max (60msec) */
+ snd_soc_write(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xA0);
+ /* Set the CnP reference current to sc_bias */
+ snd_soc_write(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x6D);
+
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B2_CTL, 0x00);
+ /* Four consecutive writes to set -10mV as static data input */
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x1F);
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x19);
+ snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0xAA);
+
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B2_CTL, 0x00);
+ /* Four consecutive writes to set -10mV as static data input */
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x1F);
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x19);
+ snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0xAA);
+
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_TEST,
+ 0x02, 0x02);
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_TEST,
+ 0x02, 0x02);
+ /* Enable the HPHL and HPHR PA and wait for 60mS */
+ wcd9xxx_enable_static_pa(mbhc, true);
+
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x7F, 0x40);
+ usleep_range(mux_wait_us,
+ mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ break;
+ case PA_DISABLE:
+ wcd9xxx_enable_static_pa(mbhc, false);
+ wcd9xxx_restore_registers(codec, &tapan->reg_save_restore);
+ break;
+ }
+#undef __wr
+
+ return ret;
+}
+
+static void tapan_compute_impedance(s16 *l, s16 *r, uint32_t *zl, uint32_t *zr)
+{
+ int zln, zld;
+ int zrn, zrd;
+ int rl = 0, rr = 0;
+
+ zln = (l[1] - l[0]) * TAPAN_ZDET_MUL_FACTOR;
+ zld = (l[2] - l[0]);
+ if (zld)
+ rl = zln / zld;
+
+ zrn = (r[1] - r[0]) * TAPAN_ZDET_MUL_FACTOR;
+ zrd = (r[2] - r[0]);
+ if (zrd)
+ rr = zrn / zrd;
+
+ *zl = rl;
+ *zr = rr;
+}
+
static const struct wcd9xxx_mbhc_cb mbhc_cb = {
.enable_mux_bias_block = tapan_enable_mux_bias_block,
.cfilt_fast_mode = tapan_put_cfilt_fast_mode,
@@ -4926,6 +5297,8 @@
.select_cfilt = tapan_select_cfilt,
.free_irq = tapan_free_irq,
.get_cdc_type = tapan_get_cdc_type,
+ .setup_zdet = tapan_setup_zdet,
+ .compute_impedance = tapan_compute_impedance,
};
int tapan_hs_detect(struct snd_soc_codec *codec,
@@ -4943,6 +5316,16 @@
}
EXPORT_SYMBOL(tapan_hs_detect_exit);
+void tapan_event_register(
+ int (*machine_event_cb)(struct snd_soc_codec *codec,
+ enum wcd9xxx_codec_event),
+ struct snd_soc_codec *codec)
+{
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ tapan->machine_codec_event_cb = machine_event_cb;
+}
+EXPORT_SYMBOL(tapan_event_register);
+
static int tapan_device_down(struct wcd9xxx *wcd9xxx)
{
struct snd_soc_codec *codec;
@@ -5000,7 +5383,8 @@
rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
- &mbhc_cb, rco_clk_rate, false);
+ &mbhc_cb, rco_clk_rate,
+ TAPAN_CDC_ZDET_SUPPORTED);
if (ret)
pr_err("%s: mbhc init failed %d\n", __func__, ret);
else
@@ -5011,6 +5395,8 @@
if (ret)
pr_err("%s: Failed to setup irq: %d\n", __func__, ret);
+ tapan->machine_codec_event_cb(codec, WCD9XXX_CODEC_EVENT_CODEC_UP);
+
mutex_unlock(&codec->mutex);
return ret;
}
@@ -5203,7 +5589,8 @@
rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
- &mbhc_cb, rco_clk_rate, false);
+ &mbhc_cb, rco_clk_rate,
+ TAPAN_CDC_ZDET_SUPPORTED);
if (ret) {
pr_err("%s: mbhc init failed %d\n", __func__, ret);
@@ -5255,6 +5642,7 @@
INIT_LIST_HEAD(&tapan->dai[i].wcd9xxx_ch_list);
init_waitqueue_head(&tapan->dai[i].dai_wait);
}
+ tapan_init_slim_slave_cfg(codec);
}
if (codec_ver == WCD9306) {
diff --git a/sound/soc/codecs/wcd9306.h b/sound/soc/codecs/wcd9306.h
index fdd62d1..07b2175 100644
--- a/sound/soc/codecs/wcd9306.h
+++ b/sound/soc/codecs/wcd9306.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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,9 +14,11 @@
#include <sound/soc.h>
#include <sound/jack.h>
+#include <sound/apr_audio-v2.h>
#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
#include "wcd9xxx-mbhc.h"
#include "wcd9xxx-resmgr.h"
+#include "wcd9xxx-common.h"
#define TAPAN_NUM_REGISTERS 0x400
#define TAPAN_MAX_REGISTER (TAPAN_NUM_REGISTERS-1)
@@ -24,6 +26,8 @@
#define TAPAN_REG_VAL(reg, val) {reg, 0, val}
+#define TAPAN_CDC_ZDET_SUPPORTED true
+
extern const u8 tapan_reg_readable[TAPAN_CACHE_SIZE];
extern const u8 tapan_reset_reg_defaults[TAPAN_CACHE_SIZE];
struct tapan_codec_dai_data {
@@ -75,5 +79,10 @@
bool dapm);
extern int tapan_hs_detect(struct snd_soc_codec *codec,
struct wcd9xxx_mbhc_config *mbhc_cfg);
-
+extern void *tapan_get_afe_config(struct snd_soc_codec *codec,
+ enum afe_config_type config_type);
+extern void tapan_event_register(
+ int (*machine_event_cb)(struct snd_soc_codec *codec,
+ enum wcd9xxx_codec_event),
+ struct snd_soc_codec *codec);
#endif
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 3621879..4ce9b4a 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -49,6 +49,9 @@
#define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone"
+/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
+#define TAIKO_WG_TIME_FACTOR_US 240
+
static atomic_t kp_taiko_priv;
static int spkr_drv_wrnd_param_set(const char *val,
const struct kernel_param *kp);
@@ -69,63 +72,6 @@
.num_channels = 1
};
-enum {
- RESERVED = 0,
- AANC_LPF_FF_FB = 1,
- AANC_LPF_COEFF_MSB,
- AANC_LPF_COEFF_LSB,
- HW_MAD_AUDIO_ENABLE,
- HW_MAD_ULTR_ENABLE,
- HW_MAD_BEACON_ENABLE,
- HW_MAD_AUDIO_SLEEP_TIME,
- HW_MAD_ULTR_SLEEP_TIME,
- HW_MAD_BEACON_SLEEP_TIME,
- HW_MAD_TX_AUDIO_SWITCH_OFF,
- HW_MAD_TX_ULTR_SWITCH_OFF,
- HW_MAD_TX_BEACON_SWITCH_OFF,
- MAD_AUDIO_INT_DEST_SELECT_REG,
- MAD_ULT_INT_DEST_SELECT_REG,
- MAD_BEACON_INT_DEST_SELECT_REG,
- MAD_CLIP_INT_DEST_SELECT_REG,
- MAD_VBAT_INT_DEST_SELECT_REG,
- MAD_AUDIO_INT_MASK_REG,
- MAD_ULT_INT_MASK_REG,
- MAD_BEACON_INT_MASK_REG,
- MAD_CLIP_INT_MASK_REG,
- MAD_VBAT_INT_MASK_REG,
- MAD_AUDIO_INT_STATUS_REG,
- MAD_ULT_INT_STATUS_REG,
- MAD_BEACON_INT_STATUS_REG,
- MAD_CLIP_INT_STATUS_REG,
- MAD_VBAT_INT_STATUS_REG,
- MAD_AUDIO_INT_CLEAR_REG,
- MAD_ULT_INT_CLEAR_REG,
- MAD_BEACON_INT_CLEAR_REG,
- MAD_CLIP_INT_CLEAR_REG,
- MAD_VBAT_INT_CLEAR_REG,
- SB_PGD_PORT_TX_WATERMARK_n,
- SB_PGD_PORT_TX_ENABLE_n,
- SB_PGD_PORT_RX_WATERMARK_n,
- SB_PGD_PORT_RX_ENABLE_n,
- SB_PGD_TX_PORTn_MULTI_CHNL_0,
- SB_PGD_TX_PORTn_MULTI_CHNL_1,
- SB_PGD_RX_PORTn_MULTI_CHNL_0,
- SB_PGD_RX_PORTn_MULTI_CHNL_1,
- AANC_FF_GAIN_ADAPTIVE,
- AANC_FFGAIN_ADAPTIVE_EN,
- AANC_GAIN_CONTROL,
- SPKR_CLIP_PIPE_BANK_SEL,
- SPKR_CLIPDET_VAL0,
- SPKR_CLIPDET_VAL1,
- SPKR_CLIPDET_VAL2,
- SPKR_CLIPDET_VAL3,
- SPKR_CLIPDET_VAL4,
- SPKR_CLIPDET_VAL5,
- SPKR_CLIPDET_VAL6,
- SPKR_CLIPDET_VAL7,
- MAX_CFG_REGISTERS,
-};
-
static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
{
1,
@@ -165,22 +111,22 @@
{
1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
- SB_PGD_PORT_TX_WATERMARK_n, 0x1E, 8, 0x1
+ SB_PGD_PORT_TX_WATERMARK_N, 0x1E, 8, 0x1
},
{
1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
- SB_PGD_PORT_TX_ENABLE_n, 0x1, 8, 0x1
+ SB_PGD_PORT_TX_ENABLE_N, 0x1, 8, 0x1
},
{
1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
- SB_PGD_PORT_RX_WATERMARK_n, 0x1E, 8, 0x1
+ SB_PGD_PORT_RX_WATERMARK_N, 0x1E, 8, 0x1
},
{
1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
- SB_PGD_PORT_RX_ENABLE_n, 0x1, 8, 0x1
+ SB_PGD_PORT_RX_ENABLE_N, 0x1, 8, 0x1
},
{ 1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_IIR_B1_CTL),
@@ -509,6 +455,12 @@
int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
enum wcd9xxx_codec_event);
+
+ /*
+ * list used to save/restore registers at start and
+ * end of impedance measurement
+ */
+ struct list_head reg_save_restore;
};
static const u32 comp_shift[] = {
@@ -6239,6 +6191,198 @@
return 0;
}
+static int wcd9xxx_prepare_static_pa(struct wcd9xxx_mbhc *mbhc,
+ struct list_head *lh)
+{
+ int i;
+ struct snd_soc_codec *codec = mbhc->codec;
+
+ const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
+ {WCD9XXX_A_RX_HPH_OCP_CTL, 0x18, 0x00},
+ {WCD9XXX_A_RX_HPH_L_TEST, 0x1, 0x0},
+ {WCD9XXX_A_RX_HPH_R_TEST, 0x1, 0x0},
+ {WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xff, 0x1A},
+ {WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xff, 0xDB},
+ {WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xff, 0x15},
+ {WCD9XXX_A_CDC_RX1_B6_CTL, 0xff, 0x81},
+ {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x01, 0x01},
+ {WCD9XXX_A_RX_HPH_CHOP_CTL, 0xff, 0xA4},
+ {WCD9XXX_A_RX_HPH_L_GAIN, 0xff, 0x2C},
+ {WCD9XXX_A_CDC_RX2_B6_CTL, 0xff, 0x81},
+ {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x02, 0x02},
+ {WCD9XXX_A_RX_HPH_R_GAIN, 0xff, 0x2C},
+ {WCD9XXX_A_NCP_CLK, 0xff, 0xFC},
+ {WCD9XXX_A_BUCK_CTRL_CCL_3, 0xff, 0x60},
+ {WCD9XXX_A_RX_COM_BIAS, 0xff, 0x80},
+ {WCD9XXX_A_BUCK_MODE_3, 0xff, 0xC6},
+ {WCD9XXX_A_BUCK_MODE_4, 0xff, 0xE6},
+ {WCD9XXX_A_BUCK_MODE_5, 0xff, 0x02},
+ {WCD9XXX_A_BUCK_MODE_1, 0xff, 0xA1},
+ {WCD9XXX_A_NCP_EN, 0xff, 0xFF},
+ {WCD9XXX_A_BUCK_MODE_5, 0xff, 0x7B},
+ {WCD9XXX_A_CDC_CLSH_B1_CTL, 0xff, 0xE6},
+ {WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xff, 0xC0},
+ {WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xff, 0xC0},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++)
+ wcd9xxx_soc_update_bits_push(codec, lh,
+ reg_set_paon[i].reg,
+ reg_set_paon[i].mask,
+ reg_set_paon[i].val, 0);
+ pr_debug("%s: PAs are prepared\n", __func__);
+
+ return 0;
+}
+
+static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
+{
+ struct snd_soc_codec *codec = mbhc->codec;
+ const int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
+ TAIKO_WG_TIME_FACTOR_US;
+
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
+ enable ? 0x30 : 0x0);
+ /* Wait for wave gen time to avoid pop noise */
+ usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
+ enable ? "enabled" : "disabled", wg_time);
+ return 0;
+}
+
+static int taiko_setup_zdet(struct wcd9xxx_mbhc *mbhc,
+ enum mbhc_impedance_detect_stages stage)
+{
+ int ret = 0;
+ struct snd_soc_codec *codec = mbhc->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ const int ramp_wait_us = 18 * 1000;
+
+#define __wr(reg, mask, value) \
+ do { \
+ ret = wcd9xxx_soc_update_bits_push(codec, \
+ &taiko->reg_save_restore, \
+ reg, mask, value, 0); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+ switch (stage) {
+
+ case PRE_MEAS:
+ INIT_LIST_HEAD(&taiko->reg_save_restore);
+ wcd9xxx_prepare_static_pa(mbhc, &taiko->reg_save_restore);
+ wcd9xxx_enable_static_pa(mbhc, true);
+
+ /*
+ * save old value of registers and write the new value to
+ * restore old value back, WCD9XXX_A_CDC_PA_RAMP_B{1,2,3,4}_CTL
+ * registers don't need to be restored as those are solely used
+ * by impedance detection.
+ */
+ /* Phase 1 */
+ /* Reset the PA Ramp */
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1C);
+ /*
+ * Connect the PA Ramp to PA chain and release reset with
+ * keep it connected.
+ */
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1F);
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
+ /*
+ * Program the PA Ramp to FS_48K, L shift 1 and sample
+ * num to 24
+ */
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL,
+ 0x3 << 4 | 0x6);
+ /* 0x56 for 10mv. 0xC0 is for 50mv */
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0xC0);
+ /* Enable MBHC MUX, Set MUX current to 37.5uA and ADC7 */
+ __wr(WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xC0);
+ __wr(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
+ __wr(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xFF, 0x78);
+ __wr(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0x8C);
+ /* Change NSA and NAVG */
+ __wr(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0x4 << 4, 0x4 << 4);
+ __wr(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x10);
+ /* Reset MBHC and set it up for STA */
+ __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
+ __wr(WCD9XXX_A_CDC_MBHC_EN_CTL, 0xFF, 0x02);
+ __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
+
+ /* Set HPH_MBHC for zdet */
+ __wr(WCD9XXX_A_MBHC_HPH, 0xB3, 0x80);
+ break;
+ case POST_MEAS:
+ /* Phase 2 */
+ /* Start the PA ramp on HPH L and R */
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x05);
+ /* Ramp generator takes ~17ms */
+ usleep_range(ramp_wait_us,
+ ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+
+ /* Disable Ical */
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
+ /* Ramp generator takes ~17ms */
+ usleep_range(ramp_wait_us,
+ ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ break;
+ case PA_DISABLE:
+ /* Ramp HPH L & R back to Zero */
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x0A);
+ /* Ramp generator takes ~17ms */
+ usleep_range(ramp_wait_us,
+ ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
+
+ /* Clean up starts */
+ /* Turn off PA ramp generator */
+ snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x0);
+ wcd9xxx_enable_static_pa(mbhc, false);
+ wcd9xxx_restore_registers(codec, &taiko->reg_save_restore);
+ break;
+ }
+#undef __wr
+
+ return ret;
+}
+
+static void taiko_compute_impedance(s16 *l, s16 *r, uint32_t *zl, uint32_t *zr)
+{
+
+ int64_t rl, rr = 0; /* milliohm */
+ const int alphal = 364; /* 0.005555 * 65536 = 364.05 */
+ const int alphar = 364; /* 0.005555 * 65536 = 364.05 */
+ const int beta = 3855; /* 0.011765 * 5 * 65536 = 3855.15 */
+ const int rref = 11333; /* not scaled up */
+ const int shift = 16;
+
+ rl = (int)(l[0] - l[1]) * 1000 / (l[0] - l[2]);
+ rl = rl * rref * alphal;
+ rl = rl >> shift;
+ rl = rl * beta;
+ rl = rl >> shift;
+ *zl = rl;
+
+ rr = (int)(r[0] - r[1]) * 1000 / (r[0] - r[2]);
+ rr = rr * rref * alphar;
+ rr = rr >> shift;
+ rr = rr * beta;
+ rr = rr >> shift;
+ *zr = rr;
+}
+
+static enum wcd9xxx_cdc_type taiko_get_cdc_type(void)
+{
+ return WCD9XXX_CDC_TYPE_TAIKO;
+}
+
+static const struct wcd9xxx_mbhc_cb mbhc_cb = {
+ .get_cdc_type = taiko_get_cdc_type,
+ .setup_zdet = taiko_setup_zdet,
+ .compute_impedance = taiko_compute_impedance,
+};
+
static int taiko_post_reset_cb(struct wcd9xxx *wcd9xxx)
{
int ret = 0;
@@ -6284,7 +6428,7 @@
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
taiko_enable_mbhc_micbias,
- NULL, rco_clk_rate, true);
+ &mbhc_cb, rco_clk_rate, true);
if (ret)
pr_err("%s: mbhc init failed %d\n", __func__, ret);
else
@@ -6473,7 +6617,7 @@
/* init and start mbhc */
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
taiko_enable_mbhc_micbias,
- NULL, rco_clk_rate, true);
+ &mbhc_cb, rco_clk_rate, true);
if (ret) {
pr_err("%s: mbhc init failed %d\n", __func__, ret);
goto err_init;
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index d00b843..05f2191 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
+#include <linux/slab.h>
#include <sound/soc.h>
#include <linux/kernel.h>
#include <linux/delay.h>
@@ -32,6 +33,8 @@
#define MAX_IMPED_PARAMS 13
+#define USLEEP_RANGE_MARGIN_US 100
+
struct wcd9xxx_imped_val {
u32 imped_val;
u8 index;
@@ -614,6 +617,46 @@
}
}
+
+int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
+ struct list_head *list,
+ uint16_t reg, uint8_t mask,
+ uint8_t value, int delay)
+{
+ int rc;
+ struct wcd9xxx_register_save_node *node;
+
+ node = kmalloc(sizeof(*node), GFP_KERNEL);
+ if (unlikely(!node)) {
+ pr_err("%s: Not enough memory\n", __func__);
+ return -ENOMEM;
+ }
+ node->reg = reg;
+ node->value = snd_soc_read(codec, reg);
+ list_add(&node->lh, list);
+ if (mask == 0xFF)
+ rc = snd_soc_write(codec, reg, value);
+ else
+ rc = snd_soc_update_bits(codec, reg, mask, value);
+ if (delay)
+ usleep_range(delay, delay + USLEEP_RANGE_MARGIN_US);
+ return rc;
+}
+EXPORT_SYMBOL(wcd9xxx_soc_update_bits_push);
+
+void wcd9xxx_restore_registers(struct snd_soc_codec *codec,
+ struct list_head *lh)
+{
+ struct wcd9xxx_register_save_node *node, *nodetmp;
+
+ list_for_each_entry_safe(node, nodetmp, lh, lh) {
+ snd_soc_write(codec, node->reg, node->value);
+ list_del(&node->lh);
+ kfree(node);
+ }
+}
+EXPORT_SYMBOL(wcd9xxx_restore_registers);
+
static void wcd9xxx_enable_buck_mode(struct snd_soc_codec *codec,
u8 buck_vref)
{
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 654964e..e63d36a 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -81,4 +81,73 @@
WCD9XXX_CODEC_EVENT_CODEC_UP = 0,
};
+struct wcd9xxx_register_save_node {
+ struct list_head lh;
+ u16 reg;
+ u16 value;
+};
+
+extern int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
+ struct list_head *lh,
+ uint16_t reg, uint8_t mask,
+ uint8_t value, int delay);
+extern void wcd9xxx_restore_registers(struct snd_soc_codec *codec,
+ struct list_head *lh);
+enum {
+ RESERVED = 0,
+ AANC_LPF_FF_FB = 1,
+ AANC_LPF_COEFF_MSB,
+ AANC_LPF_COEFF_LSB,
+ HW_MAD_AUDIO_ENABLE,
+ HW_MAD_ULTR_ENABLE,
+ HW_MAD_BEACON_ENABLE,
+ HW_MAD_AUDIO_SLEEP_TIME,
+ HW_MAD_ULTR_SLEEP_TIME,
+ HW_MAD_BEACON_SLEEP_TIME,
+ HW_MAD_TX_AUDIO_SWITCH_OFF,
+ HW_MAD_TX_ULTR_SWITCH_OFF,
+ HW_MAD_TX_BEACON_SWITCH_OFF,
+ MAD_AUDIO_INT_DEST_SELECT_REG,
+ MAD_ULT_INT_DEST_SELECT_REG,
+ MAD_BEACON_INT_DEST_SELECT_REG,
+ MAD_CLIP_INT_DEST_SELECT_REG,
+ MAD_VBAT_INT_DEST_SELECT_REG,
+ MAD_AUDIO_INT_MASK_REG,
+ MAD_ULT_INT_MASK_REG,
+ MAD_BEACON_INT_MASK_REG,
+ MAD_CLIP_INT_MASK_REG,
+ MAD_VBAT_INT_MASK_REG,
+ MAD_AUDIO_INT_STATUS_REG,
+ MAD_ULT_INT_STATUS_REG,
+ MAD_BEACON_INT_STATUS_REG,
+ MAD_CLIP_INT_STATUS_REG,
+ MAD_VBAT_INT_STATUS_REG,
+ MAD_AUDIO_INT_CLEAR_REG,
+ MAD_ULT_INT_CLEAR_REG,
+ MAD_BEACON_INT_CLEAR_REG,
+ MAD_CLIP_INT_CLEAR_REG,
+ MAD_VBAT_INT_CLEAR_REG,
+ SB_PGD_PORT_TX_WATERMARK_N,
+ SB_PGD_PORT_TX_ENABLE_N,
+ SB_PGD_PORT_RX_WATERMARK_N,
+ SB_PGD_PORT_RX_ENABLE_N,
+ SB_PGD_TX_PORTn_MULTI_CHNL_0,
+ SB_PGD_TX_PORTn_MULTI_CHNL_1,
+ SB_PGD_RX_PORTn_MULTI_CHNL_0,
+ SB_PGD_RX_PORTn_MULTI_CHNL_1,
+ AANC_FF_GAIN_ADAPTIVE,
+ AANC_FFGAIN_ADAPTIVE_EN,
+ AANC_GAIN_CONTROL,
+ SPKR_CLIP_PIPE_BANK_SEL,
+ SPKR_CLIPDET_VAL0,
+ SPKR_CLIPDET_VAL1,
+ SPKR_CLIPDET_VAL2,
+ SPKR_CLIPDET_VAL3,
+ SPKR_CLIPDET_VAL4,
+ SPKR_CLIPDET_VAL5,
+ SPKR_CLIPDET_VAL6,
+ SPKR_CLIPDET_VAL7,
+ MAX_CFG_REGISTERS,
+};
+
#endif
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index acb86416..a9e0c43 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -142,12 +142,6 @@
enum wcd9xxx_mbhc_plug_type _type;
};
-struct wcd9xxx_register_save_node {
- struct list_head lh;
- u16 reg;
- u16 value;
-};
-
enum meas_type {
STA = 0,
DCE,
@@ -182,6 +176,8 @@
uint32_t *zr);
static s16 wcd9xxx_get_current_v(struct wcd9xxx_mbhc *mbhc,
const enum wcd9xxx_current_v_idx idx);
+static void wcd9xxx_get_z(struct wcd9xxx_mbhc *mbhc, s16 *dce_z, s16 *sta_z);
+static void wcd9xxx_mbhc_calc_thres(struct wcd9xxx_mbhc *mbhc);
static bool wcd9xxx_mbhc_polling(struct wcd9xxx_mbhc *mbhc)
{
@@ -973,6 +969,7 @@
if (noreldetection)
wcd9xxx_turn_onoff_rel_detection(codec, false);
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x0);
/* Turn on the override */
if (!override_bypass)
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
@@ -982,6 +979,8 @@
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
0x0);
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2,
+ 0x2);
usleep_range(mbhc->mbhc_data.t_sta_dce,
mbhc->mbhc_data.t_sta_dce);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4);
@@ -993,6 +992,8 @@
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
0x0);
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2,
+ 0x2);
usleep_range(mbhc->mbhc_data.t_sta_dce,
mbhc->mbhc_data.t_sta_dce);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
@@ -1055,6 +1056,10 @@
struct snd_soc_codec *codec = mbhc->codec;
short bias_value;
u8 cfilt_mode;
+ s16 reg;
+ int change;
+ struct wcd9xxx_mbhc_btn_detect_cfg *btn_det;
+ s16 sta_z = 0, dce_z = 0;
WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
@@ -1064,6 +1069,8 @@
return -ENODEV;
}
+ btn_det = WCD9XXX_MBHC_CAL_BTN_DET_PTR(mbhc->mbhc_cfg->calibration);
+
/*
* Request BG and clock.
* These will be released by wcd9xxx_cleanup_hs_polling
@@ -1102,14 +1109,48 @@
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
- if (!is_cs_enable)
- wcd9xxx_calibrate_hs_polling(mbhc);
-
/* don't flip override */
bias_value = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
snd_soc_write(codec, mbhc->mbhc_bias_regs.cfilt_ctl, cfilt_mode);
snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
+ /* recalibrate dce_z and sta_z */
+ reg = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_CTL);
+ change = snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x78,
+ btn_det->mbhc_nsc << 3);
+ wcd9xxx_get_z(mbhc, &dce_z, &sta_z);
+ if (change)
+ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, reg);
+ if (dce_z && sta_z) {
+ pr_debug("%s: sta_z 0x%x -> 0x%x, dce_z 0x%x -> 0x%x\n",
+ __func__,
+ mbhc->mbhc_data.sta_z, sta_z & 0xffff,
+ mbhc->mbhc_data.dce_z, dce_z & 0xffff);
+ mbhc->mbhc_data.dce_z = dce_z;
+ mbhc->mbhc_data.sta_z = sta_z;
+ wcd9xxx_mbhc_calc_thres(mbhc);
+ wcd9xxx_calibrate_hs_polling(mbhc);
+ } else {
+ pr_warn("%s: failed get new dce_z/sta_z 0x%x/0x%x\n", __func__,
+ dce_z, sta_z);
+ }
+
+ if (is_cs_enable) {
+ /* recalibrate dce_nsc_cs_z */
+ reg = snd_soc_read(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL);
+ snd_soc_update_bits(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
+ 0x78, WCD9XXX_MBHC_NSC_CS << 3);
+ wcd9xxx_get_z(mbhc, &dce_z, NULL);
+ snd_soc_write(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL, reg);
+ if (dce_z) {
+ pr_debug("%s: dce_nsc_cs_z 0x%x -> 0x%x\n", __func__,
+ mbhc->mbhc_data.dce_nsc_cs_z, dce_z & 0xffff);
+ mbhc->mbhc_data.dce_nsc_cs_z = dce_z;
+ } else {
+ pr_debug("%s: failed get new dce_nsc_cs_z\n", __func__);
+ }
+ }
+
return bias_value;
}
@@ -1859,7 +1900,7 @@
0);
}
- if (mbhc->resmgr->reg_addr->micb_4_mbhc)
+ if (mbhc->resmgr->reg_addr && mbhc->resmgr->reg_addr->micb_4_mbhc)
snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc,
0x3, mbhc->mbhc_cfg->micbias);
@@ -2946,9 +2987,10 @@
return mask;
}
-void wcd9xxx_get_z(struct wcd9xxx_mbhc *mbhc, s16 *dce_z, s16 *sta_z)
+static void wcd9xxx_get_z(struct wcd9xxx_mbhc *mbhc, s16 *dce_z, s16 *sta_z)
{
s16 reg0, reg1;
+ int change;
struct snd_soc_codec *codec = mbhc->codec;
WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
@@ -2959,16 +3001,21 @@
snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 1 << 7, 0);
/* Disconnect override from micbias */
- snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4, 1 << 0);
+ change = snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4,
+ 1 << 0);
usleep_range(1000, 1000 + 1000);
- *sta_z = wcd9xxx_codec_sta_dce(mbhc, 0, false);
- *dce_z = wcd9xxx_codec_sta_dce(mbhc, 1, false);
+ if (sta_z)
+ *sta_z = wcd9xxx_codec_sta_dce(mbhc, 0, false);
+ if (dce_z)
+ *dce_z = wcd9xxx_codec_sta_dce(mbhc, 1, false);
pr_debug("%s: sta_z 0x%x, dce_z 0x%x\n", __func__, *sta_z & 0xFFFF,
*dce_z & 0xFFFF);
/* Connect override from micbias */
- snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4, 1 << 4);
+ if (change)
+ snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4,
+ 1 << 4);
/* Disable pull down micbias to ground */
snd_soc_write(codec, mbhc->mbhc_bias_regs.mbhc_reg, reg1);
snd_soc_write(codec, mbhc->mbhc_bias_regs.ctl_reg, reg0);
@@ -3740,6 +3787,11 @@
p->dce_z, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_z));
n += scnprintf(buffer + n, size - n, "dce_mb = %x(%dmv)\n",
p->dce_mb, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_mb));
+ n += scnprintf(buffer + n, size - n, "dce_nsc_cs_z = %x(%dmv)\n",
+ p->dce_nsc_cs_z,
+ __wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_nsc_cs_z,
+ p->dce_nsc_cs_z,
+ VDDIO_MICBIAS_MV));
n += scnprintf(buffer + n, size - n, "sta_z = %x(%dmv)\n",
p->sta_z, wcd9xxx_codec_sta_dce_v(mbhc, 0, p->sta_z));
n += scnprintf(buffer + n, size - n, "sta_mb = %x(%dmv)\n",
@@ -4158,107 +4210,6 @@
return ret;
}
-static int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
- struct list_head *list,
- uint16_t reg, uint8_t mask,
- uint8_t value)
-{
- int rc;
- struct wcd9xxx_register_save_node *node;
-
- node = kmalloc(sizeof(*node), GFP_KERNEL);
- if (unlikely(!node)) {
- pr_err("%s: Not enough memory\n", __func__);
- return -ENOMEM;
- }
- node->reg = reg;
- node->value = snd_soc_read(codec, reg);
- list_add(&node->lh, list);
- if (mask == 0xFF)
- rc = snd_soc_write(codec, reg, value);
- else
- rc = snd_soc_update_bits(codec, reg, mask, value);
- return rc;
-}
-
-static int wcd9xxx_prepare_static_pa(struct wcd9xxx_mbhc *mbhc,
- struct list_head *lh)
-{
- int i;
- struct snd_soc_codec *codec = mbhc->codec;
-
- const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
- {WCD9XXX_A_RX_HPH_OCP_CTL, 0x18, 0x00},
- {WCD9XXX_A_RX_HPH_L_TEST, 0x1, 0x0},
- {WCD9XXX_A_RX_HPH_R_TEST, 0x1, 0x0},
- {WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xff, 0x1A},
- {WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xff, 0xDB},
- {WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xff, 0x15},
- {WCD9XXX_A_CDC_RX1_B6_CTL, 0xff, 0x81},
- {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x01, 0x01},
- {WCD9XXX_A_RX_HPH_CHOP_CTL, 0xff, 0xA4},
- {WCD9XXX_A_RX_HPH_L_GAIN, 0xff, 0x2C},
- {WCD9XXX_A_CDC_RX2_B6_CTL, 0xff, 0x81},
- {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x02, 0x02},
- {WCD9XXX_A_RX_HPH_R_GAIN, 0xff, 0x2C},
- {WCD9XXX_A_NCP_CLK, 0xff, 0xFC},
- {WCD9XXX_A_BUCK_CTRL_CCL_3, 0xff, 0x60},
- {WCD9XXX_A_RX_COM_BIAS, 0xff, 0x80},
- {WCD9XXX_A_BUCK_MODE_3, 0xff, 0xC6},
- {WCD9XXX_A_BUCK_MODE_4, 0xff, 0xE6},
- {WCD9XXX_A_BUCK_MODE_5, 0xff, 0x02},
- {WCD9XXX_A_BUCK_MODE_1, 0xff, 0xA1},
- {WCD9XXX_A_NCP_EN, 0xff, 0xFF},
- {WCD9XXX_A_BUCK_MODE_5, 0xff, 0x7B},
- {WCD9XXX_A_CDC_CLSH_B1_CTL, 0xff, 0xE6},
- {WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xff, 0xC0},
- {WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xff, 0xC0},
- };
-
- for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++)
- wcd9xxx_soc_update_bits_push(codec, lh,
- reg_set_paon[i].reg,
- reg_set_paon[i].mask,
- reg_set_paon[i].val);
- pr_debug("%s: PAs are prepared\n", __func__);
-
- return 0;
-}
-
-static void wcd9xxx_restore_registers(struct wcd9xxx_mbhc *mbhc,
- struct list_head *lh)
-{
- struct wcd9xxx_register_save_node *node, *nodetmp;
- struct snd_soc_codec *codec = mbhc->codec;
-
- list_for_each_entry_safe(node, nodetmp, lh, lh) {
- snd_soc_write(codec, node->reg, node->value);
- list_del(&node->lh);
- kfree(node);
- }
-}
-
-static void wcd9xxx_unprepare_static_pa(struct wcd9xxx_mbhc *mbhc,
- struct list_head *lh)
-{
- wcd9xxx_restore_registers(mbhc, lh);
-}
-
-static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
-{
- struct snd_soc_codec *codec = mbhc->codec;
- const int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
- WCD9XXX_WG_TIME_FACTOR_US;
-
- snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
- enable ? 0x30 : 0x0);
- /* Wait for wave gen time to avoid pop noise */
- usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
- pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
- enable ? "enabled" : "disabled", wg_time);
- return 0;
-}
-
static int wcd9xxx_detect_impedance(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
uint32_t *zr)
{
@@ -4268,17 +4219,8 @@
s16 *z[] = {
&l[0], &r[0], &r[1], &l[1], &l[2], &r[2],
};
- LIST_HEAD(lh);
- LIST_HEAD(lhpa);
struct snd_soc_codec *codec = mbhc->codec;
- const int ramp_wait_us = 18 * 1000;
const int mux_wait_us = 25;
- const int alphal = 364; /* 0.005555 * 65536 = 364.05 */
- const int alphar = 364; /* 0.005555 * 65536 = 364.05 */
- const int beta = 3855; /* 0.011765 * 5 * 65536 = 3855.15 */
- const int rref = 11333; /* not scaled up */
- const int shift = 16;
- int64_t rl, rr = 0; /* milliohm */
const struct wcd9xxx_reg_mask_val reg_set_mux[] = {
/* Phase 1 */
/* Set MBHC_MUX for HPHL without ical */
@@ -4299,6 +4241,11 @@
pr_debug("%s: enter\n", __func__);
WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
+ if (!mbhc->mbhc_cb || !mbhc->mbhc_cb->setup_zdet ||
+ !mbhc->mbhc_cb->compute_impedance || !zl ||
+ !zr)
+ return -EINVAL;
+
/*
* Impedance detection is an intrusive function as it mutes RX paths,
* enable PAs and etc. Therefore codec drvier including ALSA
@@ -4317,127 +4264,66 @@
wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
+ wcd9xxx_turn_onoff_override(codec, true);
pr_debug("%s: Setting impedance detection\n", __func__);
- wcd9xxx_prepare_static_pa(mbhc, &lhpa);
- wcd9xxx_enable_static_pa(mbhc, true);
- /*
- * save old value of registers and write the new value to restore old
- * value back, WCD9XXX_A_CDC_PA_RAMP_B{1,2,3,4}_CTL registers don't
- * need to be restored as those are solely used by impedance detection.
- */
-#define __w(reg, mask, value) \
- do { \
- ret = wcd9xxx_soc_update_bits_push(codec, &lh, reg, mask, \
- value); \
- if (ret < 0) \
- return ret; \
- } while (0)
-
- /* Reset the PA Ramp */
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1C);
- /*
- * Connect the PA Ramp to PA chain and release reset with keep it
- * connected.
- */
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1F);
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
- /* Program the PA Ramp to FS_48K, L shift 1 and sample num to 24 */
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL, 0x3 << 4 | 0x6);
- /* 0x56 for 10mv. 0xC0 is for 50mv */
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0xC0);
- /* Enable MBHC MUX, Set MUX current to 37.5uA and ADC7 */
- __w(WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xC0);
- __w(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
- __w(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xFF, 0x78);
- __w(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0x8C);
- /* Change NSA and NAVG */
- __w(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0x4 << 4, 0x4 << 4);
- __w(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x10);
- /* Reset MBHC and set it up for STA */
- __w(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
- __w(WCD9XXX_A_CDC_MBHC_EN_CTL, 0xFF, 0x02);
- __w(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
-
- /* Set HPH_MBHC for zdet */
- __w(WCD9XXX_A_MBHC_HPH, 0xB3, 0x80);
+ /* Codec specific setup for L0, R0, L1 and R1 measurements */
+ mbhc->mbhc_cb->setup_zdet(mbhc, PRE_MEAS);
pr_debug("%s: Performing impedance detection\n", __func__);
- /* Phase 1 */
for (i = 0; i < ARRAY_SIZE(reg_set_mux) - 2; i++) {
- __w(reg_set_mux[i].reg, reg_set_mux[i].mask,
- reg_set_mux[i].val);
+ snd_soc_update_bits(codec, reg_set_mux[i].reg,
+ reg_set_mux[i].mask,
+ reg_set_mux[i].val);
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+ mbhc->mbhc_cb->enable_mux_bias_block(codec);
+ else
+ snd_soc_update_bits(codec,
+ WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x80);
/* 25us is required after mux change to settle down */
usleep_range(mux_wait_us,
mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
- *(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, false, false);
+ *(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, true, false);
}
- /* Phase 2 */
- /* Start the PA ramp on HPH L and R */
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x05);
- /* Ramp generator takes ~17ms */
- usleep_range(ramp_wait_us,
- ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ /* Codec specific setup for L2 and R2 measurements */
+ mbhc->mbhc_cb->setup_zdet(mbhc, POST_MEAS);
- /* Disable Ical */
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
- /* Ramp generator takes ~17ms */
- usleep_range(ramp_wait_us,
- ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
for (; i < ARRAY_SIZE(reg_set_mux); i++) {
- __w(reg_set_mux[i].reg, reg_set_mux[i].mask,
- reg_set_mux[i].val);
+ snd_soc_update_bits(codec, reg_set_mux[i].reg,
+ reg_set_mux[i].mask,
+ reg_set_mux[i].val);
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+ mbhc->mbhc_cb->enable_mux_bias_block(codec);
+ else
+ snd_soc_update_bits(codec,
+ WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x80);
/* 25us is required after mux change to settle down */
usleep_range(mux_wait_us,
mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
- *(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, false, false);
+ *(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, true, false);
}
- /* Ramp HPH L & R back to Zero */
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x0A);
- /* Ramp generator takes ~17ms */
- usleep_range(ramp_wait_us,
- ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
-#undef __w
-
- /* Clean up starts */
- /* Turn off PA ramp generator */
- snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x0);
- wcd9xxx_enable_static_pa(mbhc, false);
- wcd9xxx_restore_registers(mbhc, &lh);
- wcd9xxx_unprepare_static_pa(mbhc, &lhpa);
+ mbhc->mbhc_cb->setup_zdet(mbhc, PA_DISABLE);
mutex_unlock(&codec->mutex);
WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
- wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_MBHC_MODE);
+ wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE);
wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
- rl = (int)(l[0] - l[1]) * 1000 / (l[0] - l[2]);
- rl = rl * rref * alphal;
- rl = rl >> shift;
- rl = rl * beta;
- rl = rl >> shift;
- *zl = rl;
+ wcd9xxx_turn_onoff_override(codec, false);
+ mbhc->mbhc_cb->compute_impedance(l, r, zl, zr);
- rr = (int)(r[0] - r[1]) * 1000 / (r[0] - r[2]);
- rr = rr * rref * alphar;
- rr = rr >> shift;
- rr = rr * beta;
- rr = rr >> shift;
- *zr = rr;
-
- pr_debug("%s: L0: 0x%x(%d), L1: 0x%x(%d), L2: 0x%x(%d), rl: %lld\n",
+ pr_debug("%s: L0: 0x%x(%d), L1: 0x%x(%d), L2: 0x%x(%d)\n",
__func__,
- l[0] & 0xffff, l[0], l[1] & 0xffff, l[1], l[2] & 0xffff, l[2],
- rl);
- pr_debug("%s: R0: 0x%x(%d), R1: 0x%x(%d), R2: 0x%x(%d), rr: %lld\n",
+ l[0] & 0xffff, l[0], l[1] & 0xffff, l[1], l[2] & 0xffff, l[2]);
+ pr_debug("%s: R0: 0x%x(%d), R1: 0x%x(%d), R2: 0x%x(%d)\n",
__func__,
- r[0] & 0xffff, r[0], r[1] & 0xffff, r[1], r[2] & 0xffff, r[2],
- rr);
+ r[0] & 0xffff, r[0], r[1] & 0xffff, r[1], r[2] & 0xffff, r[2]);
pr_debug("%s: RL %d milliohm, RR %d milliohm\n", __func__, *zl, *zr);
pr_debug("%s: Impedance detection completed\n", __func__);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 3040bc4..e5259c3 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -19,6 +19,8 @@
#define WCD9XXX_CFILT_EXT_PRCHG_EN 0x30
#define WCD9XXX_CFILT_EXT_PRCHG_DSBL 0x00
+#define WCD9XXX_USLEEP_RANGE_MARGIN_US 100
+
struct mbhc_micbias_regs {
u16 cfilt_val;
u16 cfilt_ctl;
@@ -40,6 +42,12 @@
MBHC_CAL_NUM,
};
+enum mbhc_impedance_detect_stages {
+ PRE_MEAS,
+ POST_MEAS,
+ PA_DISABLE,
+};
+
/* Data used by MBHC */
struct mbhc_internal_cal_data {
u16 dce_z;
@@ -239,6 +247,9 @@
void (*free_irq) (struct wcd9xxx_mbhc *);
enum wcd9xxx_cdc_type (*get_cdc_type) (void);
void (*enable_clock_gate) (struct snd_soc_codec *, bool);
+ int (*setup_zdet) (struct wcd9xxx_mbhc *,
+ enum mbhc_impedance_detect_stages stage);
+ void (*compute_impedance) (s16 *, s16 *, uint32_t *, uint32_t *);
};
struct wcd9xxx_mbhc {
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 40661ff..86dd840 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -215,6 +215,7 @@
select SND_SOC_MSM_HOSTLESS_PCM
select SND_SOC_WCD9306
select SND_DYNAMIC_MINORS
+ select DOLBY_DAP
help
To add support for SoC audio on MSM8226.
This will enable sound soc drivers which
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 55a5e57..9460ec0 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -17,16 +17,20 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/io.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include <sound/jack.h>
+#include <sound/q6afe-v2.h>
#include <asm/mach-types.h>
#include <mach/socinfo.h>
+#include <mach/subsystem_notif.h>
#include <qdsp6v2/msm-pcm-routing-v2.h>
+#include "qdsp6v2/q6core.h"
+#include "../codecs/wcd9xxx-common.h"
#include "../codecs/wcd9306.h"
-#include <linux/io.h>
#define DRV_NAME "msm8226-asoc-tapan"
@@ -50,6 +54,10 @@
#define LO_1_SPK_AMP 0x1
#define LO_2_SPK_AMP 0x2
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+
+static void *adsp_state_notifier;
+
static int msm8226_auxpcm_rate = 8000;
static atomic_t auxpcm_rsc_ref;
static const char *const auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
@@ -336,6 +344,9 @@
SND_SOC_DAPM_MIC("Digital Mic5", NULL),
SND_SOC_DAPM_MIC("Digital Mic6", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic3", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic4", NULL),
+
SND_SOC_DAPM_SPK("Lineout_1 amp", msm8226_ext_spkramp_event),
SND_SOC_DAPM_SPK("Lineout_2 amp", msm8226_ext_spkramp_event),
@@ -696,6 +707,107 @@
msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
};
+static int msm_afe_set_config(struct snd_soc_codec *codec)
+{
+ int rc;
+ void *config_data;
+
+ pr_debug("%s: enter\n", __func__);
+ config_data = tapan_get_afe_config(codec, AFE_CDC_REGISTERS_CONFIG);
+ rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set codec registers config %d\n",
+ __func__, rc);
+ return rc;
+ }
+ config_data = tapan_get_afe_config(codec, AFE_SLIMBUS_SLAVE_CONFIG);
+ rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set slimbus slave config %d\n", __func__,
+ rc);
+ return rc;
+ }
+ config_data = tapan_get_afe_config(codec, AFE_AANC_VERSION);
+ rc = afe_set_config(AFE_AANC_VERSION, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set AANC version %d\n", __func__,
+ rc);
+ return rc;
+ }
+ return 0;
+}
+
+static void msm_afe_clear_config(void)
+{
+ afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
+ afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
+ afe_clear_config(AFE_AANC_VERSION);
+}
+
+static int msm8226_adsp_state_callback(struct notifier_block *nb,
+ unsigned long value, void *priv)
+{
+ if (value == SUBSYS_BEFORE_SHUTDOWN) {
+ pr_debug("%s: ADSP is about to shutdown. Clearing AFE config\n",
+ __func__);
+ msm_afe_clear_config();
+ } else if (value == SUBSYS_AFTER_POWERUP) {
+ pr_debug("%s: ADSP is up\n", __func__);
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+ .notifier_call = msm8226_adsp_state_callback,
+ .priority = -INT_MAX,
+};
+
+static int msm8226_tapan_codec_up(struct snd_soc_codec *codec)
+{
+ int err;
+ unsigned long timeout;
+ int adsp_ready = 0;
+
+ pr_debug("%s\n", __func__);
+ timeout = jiffies +
+ msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+
+ do {
+ if (!q6core_is_adsp_ready()) {
+ pr_err("%s: ADSP Audio isn't ready\n", __func__);
+ } else {
+ pr_debug("%s: ADSP Audio is ready\n", __func__);
+ adsp_ready = 1;
+ break;
+ }
+ } while (time_after(timeout, jiffies));
+
+ if (!adsp_ready) {
+ pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ err = msm_afe_set_config(codec);
+ if (err)
+ pr_err("%s: Failed to set AFE config. err %d\n",
+ __func__, err);
+ return err;
+}
+
+static int msm8226_tapan_event_cb(struct snd_soc_codec *codec,
+ enum wcd9xxx_codec_event codec_event)
+{
+ switch (codec_event) {
+ case WCD9XXX_CODEC_EVENT_CODEC_UP:
+ return msm8226_tapan_codec_up(codec);
+ default:
+ pr_err("%s: UnSupported codec event %d\n",
+ __func__, codec_event);
+ return -EINVAL;
+ }
+}
+
static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int err;
@@ -736,13 +848,37 @@
snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+ err = msm_afe_set_config(codec);
+ if (err) {
+ pr_err("%s: Failed to set AFE config %d\n",
+ __func__, err);
+ return err;
+ }
+
/* start mbhc */
mbhc_cfg.calibration = def_tapan_mbhc_cal();
- if (mbhc_cfg.calibration)
+ if (mbhc_cfg.calibration) {
err = tapan_hs_detect(codec, &mbhc_cfg);
- else
+ } else {
err = -ENOMEM;
+ goto out;
+ }
+ adsp_state_notifier =
+ subsys_notif_register_notifier("adsp",
+ &adsp_state_notifier_block);
+
+ if (!adsp_state_notifier) {
+ pr_err("%s: Failed to register adsp state notifier\n",
+ __func__);
+ err = -EFAULT;
+ goto out;
+ }
+
+ tapan_event_register(msm8226_tapan_event_cb, rtd->codec);
+ return 0;
+
+out:
return err;
}
@@ -1165,6 +1301,38 @@
.codec_name = "snd-soc-dummy",
.be_id = MSM_FRONTEND_DAI_VOLTE,
},
+ {
+ .name = "QCHAT",
+ .stream_name = "QCHAT",
+ .cpu_dai_name = "QCHAT",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_QCHAT,
+ },
+ /* LSM FE */
+ {
+ .name = "Listen Audio Service",
+ .stream_name = "Listen Audio Service",
+ .cpu_dai_name = "LSM",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM1,
+ },
/* Backend BT/FM DAI Links */
{
.name = LPASS_BE_INT_BT_SCO_RX,
@@ -1457,6 +1625,19 @@
.ops = &msm8226_be_ops,
.ignore_suspend = 1,
},
+ {
+ .name = LPASS_BE_SLIMBUS_5_TX,
+ .stream_name = "Slimbus5 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16395",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
+ },
};
static struct snd_soc_dai_link msm8226_9302_dai[] = {
@@ -1573,6 +1754,19 @@
.ops = &msm8226_be_ops,
.ignore_suspend = 1,
},
+ {
+ .name = LPASS_BE_SLIMBUS_5_TX,
+ .stream_name = "Slimbus5 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16395",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
+ },
};
static struct snd_soc_dai_link msm8226_9306_dai_links[
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index dfde85c..23577ed 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -817,6 +817,22 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
+ {/* hw:x,14 */
+ .name = "QCHAT",
+ .stream_name = "QCHAT",
+ .cpu_dai_name = "QCHAT",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_QCHAT,
+ },
/* Backend I2S DAI Links */
{
.name = LPASS_BE_SEC_MI2S_RX,
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 2836b87..c9e38e0 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -22,6 +22,11 @@
#include "audio_acdb.h"
#include "q6voice.h"
+#include <sound/q6adm-v2.h>
+#include <sound/q6afe-v2.h>
+#include <sound/q6asm-v2.h>
+#include <sound/q6lsm.h>
+
#define MAX_NETWORKS 15
#define MAX_IOCTL_DATA (MAX_NETWORKS * 2)
@@ -996,12 +1001,64 @@
return result;
}
+static int unmap_cal_tables(void)
+{
+ int result = 0;
+ int result2 = 0;
+
+ result2 = adm_unmap_cal_blocks();
+ if (result2 < 0) {
+ pr_err("%s: adm_unmap_cal_blocks failed, err = %d\n",
+ __func__, result2);
+ result = result2;
+ }
+
+ result2 = afe_unmap_cal_blocks();
+ if (result2 < 0) {
+ pr_err("%s: afe_unmap_cal_blocks failed, err = %d\n",
+ __func__, result2);
+ result = result2;
+ }
+
+ result2 = q6lsm_unmap_cal_blocks();
+ if (result2 < 0) {
+ pr_err("%s: lsm_unmap_cal_blocks failed, err = %d\n",
+ __func__, result2);
+ result = result2;
+ }
+
+ result2 = q6asm_unmap_cal_blocks();
+ if (result2 < 0) {
+ pr_err("%s: asm_unmap_cal_blocks failed, err = %d\n",
+ __func__, result2);
+ result = result2;
+ }
+
+ result2 = voc_unmap_cal_blocks();
+ if (result2 < 0) {
+ pr_err("%s: voice_unmap_cal_blocks failed, err = %d\n",
+ __func__, result2);
+ result = result2;
+ }
+
+ return result;
+}
+
static int deregister_memory(void)
{
- int i;
+ int result = 0;
+ int i;
+ pr_debug("%s\n", __func__);
if (atomic64_read(&acdb_data.mem_len)) {
mutex_lock(&acdb_data.acdb_mutex);
+ /* unmap all cal data */
+ result = unmap_cal_tables();
+ if (result < 0)
+ pr_err("%s: unmap_cal_tables failed, err = %d\n",
+ __func__, result);
+
+
atomic64_set(&acdb_data.mem_len, 0);
for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
@@ -1009,9 +1066,11 @@
acdb_data.col_data[i] = NULL;
}
msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+ acdb_data.ion_client = NULL;
+ acdb_data.ion_handle = NULL;
mutex_unlock(&acdb_data.acdb_mutex);
}
- return 0;
+ return result;
}
static int register_memory(void)
@@ -1022,6 +1081,7 @@
void *kvptr;
unsigned long kvaddr;
unsigned long mem_len;
+ pr_debug("%s\n", __func__);
mutex_lock(&acdb_data.acdb_mutex);
for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
@@ -1056,8 +1116,6 @@
return result;
err_ion_handle:
- msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
-
atomic64_set(&acdb_data.mem_len, 0);
mutex_unlock(&acdb_data.acdb_mutex);
return result;
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index f76d455..3f57078 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -252,7 +252,8 @@
return -ENOMEM;
}
prtd->substream = substream;
- prtd->lsm_client = q6lsm_client_alloc((app_cb)lsm_event_handler, prtd);
+ prtd->lsm_client = q6lsm_client_alloc(
+ (lsm_app_cb)lsm_event_handler, prtd);
if (!prtd->lsm_client) {
pr_err("%s: Could not allocate memory\n", __func__);
kfree(prtd);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index cf9b926..9d4257f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -48,7 +48,6 @@
unsigned int sample_rate;
unsigned int channel;
unsigned int format;
- unsigned long perf_mode;
};
#define INVALID_SESSION -1
@@ -69,7 +68,8 @@
MADNONE,
MADAUDIO,
MADBEACON,
- MADULTRASOUND
+ MADULTRASOUND,
+ MADSWAUDIO,
};
#define SLIMBUS_0_TX_TEXT "SLIMBUS_0_TX"
@@ -265,6 +265,11 @@
{INVALID_SESSION, INVALID_SESSION},
};
+/* Track performance mode of all front-end multimedia sessions.
+ * Performance mode is only valid when session is valid.
+ */
+static bool fe_dai_perf_mode[MSM_FRONTEND_DAI_MM_SIZE][2];
+
static uint8_t is_be_dai_extproc(int be_dai)
{
if (be_dai == MSM_BACKEND_DAI_EXTPROC_RX ||
@@ -366,17 +371,13 @@
payload.num_copps = 0; /* only RX needs to use payload */
fe_dai_map[fedai_id][session_type] = dspst_id;
+ fe_dai_perf_mode[fedai_id][session_type] = perf_mode;
+
/* re-enable EQ if active */
if (eq_data[fedai_id].enable)
msm_send_eq_values(fedai_id);
topology = get_topology(path_type);
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
- if (test_bit(fedai_id, &msm_bedais[i].fe_sessions)) {
- if (perf_mode)
- set_bit(fedai_id, &msm_bedais[i].perf_mode);
- else
- clear_bit(fedai_id, &msm_bedais[i].perf_mode);
- }
if (!is_be_dai_extproc(i) &&
(afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
(msm_bedais[i].active) &&
@@ -399,8 +400,7 @@
path_type,
msm_bedais[i].sample_rate,
msm_bedais[i].channel,
- topology,
- test_bit(fedai_id, &msm_bedais[i].perf_mode),
+ topology, perf_mode,
bits_per_sample);
else
adm_open(msm_bedais[i].port_id,
@@ -457,9 +457,9 @@
(msm_bedais[i].active) &&
(test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
adm_close(msm_bedais[i].port_id,
- test_bit(fedai_id, &msm_bedais[i].perf_mode));
+ fe_dai_perf_mode[fedai_id][session_type]);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (!test_bit(fedai_id, &msm_bedais[i].perf_mode)))
+ (fe_dai_perf_mode[fedai_id][session_type] == false))
dolby_dap_deinit(msm_bedais[i].port_id);
}
}
@@ -491,7 +491,6 @@
int session_type, path_type, port_id, topology;
u32 channels;
uint16_t bits_per_sample = 16;
- bool perf_mode = false;
pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
@@ -531,14 +530,12 @@
if ((session_type == SESSION_TYPE_RX) &&
(channels > 0)) {
- perf_mode = test_bit(val,
- &msm_bedais[reg].perf_mode);
adm_multi_ch_copp_open(msm_bedais[reg].port_id,
path_type,
msm_bedais[reg].sample_rate,
channels,
topology,
- perf_mode,
+ fe_dai_perf_mode[val][session_type],
bits_per_sample);
} else
adm_open(msm_bedais[reg].port_id,
@@ -548,11 +545,11 @@
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type,
- perf_mode);
+ fe_dai_perf_mode[val][session_type]);
port_id = srs_port_id = msm_bedais[reg].port_id;
srs_send_params(srs_port_id, 1, 0);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (!perf_mode))
+ (fe_dai_perf_mode[val][session_type] == false))
if (dolby_dap_init(port_id, channels) < 0)
pr_err("%s: Err init dolby dap\n",
__func__);
@@ -565,14 +562,14 @@
clear_bit(val, &msm_bedais[reg].fe_sessions);
if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
INVALID_SESSION) {
- perf_mode = test_bit(val, &msm_bedais[reg].perf_mode);
- adm_close(msm_bedais[reg].port_id, perf_mode);
+ adm_close(msm_bedais[reg].port_id,
+ fe_dai_perf_mode[val][session_type]);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (!perf_mode))
+ (fe_dai_perf_mode[val][session_type] == false))
dolby_dap_deinit(msm_bedais[reg].port_id);
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type,
- perf_mode);
+ fe_dai_perf_mode[val][session_type]);
}
}
if ((msm_bedais[reg].port_id == VOICE_RECORD_RX)
@@ -886,6 +883,9 @@
case MAD_HW_ULTRASOUND:
ucontrol->value.integer.value[0] = MADULTRASOUND;
break;
+ case MAD_SW_AUDIO:
+ ucontrol->value.integer.value[0] = MADSWAUDIO;
+ break;
default:
WARN(1, "Unknown\n");
return -EINVAL;
@@ -925,6 +925,9 @@
case MADULTRASOUND:
mad_type = MAD_HW_ULTRASOUND;
break;
+ case MADSWAUDIO:
+ mad_type = MAD_SW_AUDIO;
+ break;
default:
WARN(1, "Unknown\n");
return -EINVAL;
@@ -2431,7 +2434,7 @@
msm_routing_lsm_mux_put);
static const char * const lsm_func_text[] = {
- "None", "AUDIO", "BEACON", "ULTRASOUND"
+ "None", "AUDIO", "BEACON", "ULTRASOUND", "SWAUDIO",
};
static const struct soc_enum lsm_func_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lsm_func_text), lsm_func_text);
@@ -3729,12 +3732,11 @@
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
if (fe_dai_map[i][session_type] != INVALID_SESSION) {
adm_close(bedai->port_id,
- test_bit(i, &(bedai->perf_mode)));
+ fe_dai_perf_mode[i][session_type]);
srs_port_id = -1;
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (!test_bit(i, &(bedai->perf_mode))))
+ (fe_dai_perf_mode[i][session_type] == false))
dolby_dap_deinit(bedai->port_id);
- clear_bit(i, &(bedai->perf_mode));
}
}
@@ -3755,7 +3757,6 @@
u32 channels;
bool playback, capture;
uint16_t bits_per_sample = 16;
- bool perf_mode = false;
if (be_id >= MSM_BACKEND_DAI_MAX) {
pr_err("%s: unexpected be_id %d\n", __func__, be_id);
@@ -3798,13 +3799,12 @@
topology = DEFAULT_COPP_TOPOLOGY;
if ((playback) && (channels > 0)) {
- perf_mode = test_bit(i, &(bedai->perf_mode));
adm_multi_ch_copp_open(bedai->port_id,
path_type,
bedai->sample_rate,
channels,
topology,
- perf_mode,
+ fe_dai_perf_mode[i][session_type],
bits_per_sample);
} else if (capture) {
adm_open(bedai->port_id,
@@ -3817,11 +3817,11 @@
msm_pcm_routing_build_matrix(i,
fe_dai_map[i][session_type], path_type,
- perf_mode);
+ fe_dai_perf_mode[i][session_type]);
port_id = srs_port_id = bedai->port_id;
srs_send_params(srs_port_id, 1, 0);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (!perf_mode))
+ (fe_dai_perf_mode[i][session_type] == false))
if (dolby_dap_init(port_id, channels) < 0)
pr_err("%s: Err init dolby dap\n",
__func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 4a829fd..6cfc2ef 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -46,6 +46,7 @@
#define MODE_AMR 0x5
#define MODE_AMR_WB 0xD
#define MODE_PCM 0xC
+#define MODE_4GV_NW 0xE
enum format {
FORMAT_S16_LE = 2,
@@ -79,12 +80,16 @@
VOIP_STARTED,
};
-struct voip_frame {
+struct voip_frame_hdr {
+ uint32_t timestamp;
union {
- uint32_t frame_type;
- uint32_t packet_rate;
- } header;
- uint32_t len;
+ uint32_t frame_type;
+ uint32_t packet_rate;
+ };
+};
+struct voip_frame {
+ struct voip_frame_hdr frm_hdr;
+ uint32_t pktlen;
uint8_t voc_pkt[VOIP_MAX_VOC_PKT_SIZE];
};
@@ -136,6 +141,9 @@
unsigned int pcm_capture_count;
unsigned int pcm_capture_irq_pos; /* IRQ position */
unsigned int pcm_capture_buf_pos; /* position in buffer */
+
+ uint32_t evrc_min_rate;
+ uint32_t evrc_max_rate;
};
static int voip_get_media_type(uint32_t mode,
@@ -144,10 +152,15 @@
static int voip_get_rate_type(uint32_t mode,
uint32_t rate,
uint32_t *rate_type);
+static int voip_config_vocoder(struct snd_pcm_substream *substream);
static int msm_voip_mode_rate_config_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
static int msm_voip_mode_rate_config_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
+static int msm_voip_evrc_min_max_rate_config_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+static int msm_voip_evrc_min_max_rate_config_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
static struct voip_drv_info voip_info;
@@ -257,6 +270,9 @@
SOC_SINGLE_MULTI_EXT("Voip Mode Rate Config", SND_SOC_NOPM, 0, 23850,
0, 2, msm_voip_mode_rate_config_get,
msm_voip_mode_rate_config_put),
+ SOC_SINGLE_MULTI_EXT("Voip Evrc Min Max Rate Config", SND_SOC_NOPM,
+ 0, 4, 0, 2, msm_voip_evrc_min_max_rate_config_get,
+ msm_voip_evrc_min_max_rate_config_put),
SOC_SINGLE_EXT("Voip Dtx Mode", SND_SOC_NOPM, 0, 1, 0,
msm_voip_dtx_mode_get, msm_voip_dtx_mode_put),
};
@@ -275,6 +291,7 @@
/* capture path */
static void voip_process_ul_pkt(uint8_t *voc_pkt,
uint32_t pkt_len,
+ uint32_t timestamp,
void *private_data)
{
struct voip_buf_node *buf_node = NULL;
@@ -299,44 +316,50 @@
* Bits 0-3: Frame rate
* Bits 4-7: Frame type
*/
- buf_node->frame.header.frame_type =
+ buf_node->frame.frm_hdr.timestamp = timestamp;
+ buf_node->frame.frm_hdr.frame_type =
((*voc_pkt) & 0xF0) >> 4;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
- buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+ buf_node->frame.pktlen = pkt_len - DSP_FRAME_HDR_LEN;
memcpy(&buf_node->frame.voc_pkt[0],
voc_pkt,
- buf_node->frame.len);
+ buf_node->frame.pktlen);
+
list_add_tail(&buf_node->list, &prtd->out_queue);
break;
}
case MODE_IS127:
case MODE_4GV_NB:
- case MODE_4GV_WB: {
+ case MODE_4GV_WB:
+ case MODE_4GV_NW: {
/* Remove the DSP frame info header.
* Header format:
* Bits 0-3: frame rate
*/
- buf_node->frame.header.packet_rate = (*voc_pkt) & 0x0F;
+ buf_node->frame.frm_hdr.timestamp = timestamp;
+ buf_node->frame.frm_hdr.packet_rate = (*voc_pkt) & 0x0F;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
- buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+ buf_node->frame.pktlen = pkt_len - DSP_FRAME_HDR_LEN;
memcpy(&buf_node->frame.voc_pkt[0],
voc_pkt,
- buf_node->frame.len);
+ buf_node->frame.pktlen);
list_add_tail(&buf_node->list, &prtd->out_queue);
break;
}
default: {
- buf_node->frame.len = pkt_len;
+ buf_node->frame.frm_hdr.timestamp = timestamp;
+ buf_node->frame.pktlen = pkt_len;
memcpy(&buf_node->frame.voc_pkt[0],
voc_pkt,
- buf_node->frame.len);
+ buf_node->frame.pktlen);
list_add_tail(&buf_node->list, &prtd->out_queue);
}
}
- pr_debug("ul_pkt: pkt_len =%d, frame.len=%d\n", pkt_len,
- buf_node->frame.len);
+ pr_debug("%s: pkt_len =%d, frame.pktlen=%d, timestamp=%d\n",
+ __func__, pkt_len, buf_node->frame.pktlen, timestamp);
+
prtd->pcm_capture_irq_pos += prtd->pcm_capture_count;
spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
snd_pcm_period_elapsed(prtd->capture_substream);
@@ -367,7 +390,7 @@
switch (prtd->mode) {
case MODE_AMR:
case MODE_AMR_WB: {
- *((uint32_t *)voc_pkt) = buf_node->frame.len +
+ *((uint32_t *)voc_pkt) = buf_node->frame.pktlen +
DSP_FRAME_HDR_LEN;
/* Advance to the header of voip packet */
voc_pkt = voc_pkt + sizeof(uint32_t);
@@ -376,19 +399,20 @@
* Bits 0-3: Frame rate
* Bits 4-7: Frame type
*/
- *voc_pkt = ((buf_node->frame.header.frame_type &
+ *voc_pkt = ((buf_node->frame.frm_hdr.frame_type &
0x0F) << 4) | (prtd->rate_type & 0x0F);
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
memcpy(voc_pkt,
&buf_node->frame.voc_pkt[0],
- buf_node->frame.len);
+ buf_node->frame.pktlen);
list_add_tail(&buf_node->list, &prtd->free_in_queue);
break;
}
case MODE_IS127:
case MODE_4GV_NB:
- case MODE_4GV_WB: {
- *((uint32_t *)voc_pkt) = buf_node->frame.len +
+ case MODE_4GV_WB:
+ case MODE_4GV_NW: {
+ *((uint32_t *)voc_pkt) = buf_node->frame.pktlen +
DSP_FRAME_HDR_LEN;
/* Advance to the header of voip packet */
voc_pkt = voc_pkt + sizeof(uint32_t);
@@ -396,22 +420,22 @@
* Add the DSP frame info header. Header format:
* Bits 0-3 : Frame rate
*/
- *voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
+ *voc_pkt = buf_node->frame.frm_hdr.packet_rate & 0x0F;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
memcpy(voc_pkt,
&buf_node->frame.voc_pkt[0],
- buf_node->frame.len);
+ buf_node->frame.pktlen);
list_add_tail(&buf_node->list, &prtd->free_in_queue);
break;
}
default: {
- *((uint32_t *)voc_pkt) = buf_node->frame.len;
+ *((uint32_t *)voc_pkt) = buf_node->frame.pktlen;
voc_pkt = voc_pkt + sizeof(uint32_t);
memcpy(voc_pkt,
&buf_node->frame.voc_pkt[0],
- buf_node->frame.len);
+ buf_node->frame.pktlen);
list_add_tail(&buf_node->list, &prtd->free_in_queue);
}
}
@@ -559,7 +583,7 @@
if (prtd->mode == MODE_PCM) {
ret = copy_from_user(&buf_node->frame.voc_pkt,
buf, count);
- buf_node->frame.len = count;
+ buf_node->frame.pktlen = count;
} else
ret = copy_from_user(&buf_node->frame,
buf, count);
@@ -759,13 +783,137 @@
return ret;
}
-static int msm_pcm_prepare(struct snd_pcm_substream *substream)
+
+static int voip_config_vocoder(struct snd_pcm_substream *substream)
{
int ret = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct voip_drv_info *prtd = runtime->private_data;
uint32_t media_type = 0;
uint32_t rate_type = 0;
+ uint32_t evrc_min_rate_type = 0;
+ uint32_t evrc_max_rate_type = 0;
+
+ if ((runtime->format != FORMAT_SPECIAL) &&
+ ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB) ||
+ (prtd->mode == MODE_IS127) || (prtd->mode == MODE_4GV_NB) ||
+ (prtd->mode == MODE_4GV_WB) || (prtd->mode == MODE_4GV_NW))) {
+ pr_err("%s(): mode:%d and format:%u are not mached\n",
+ __func__, prtd->mode, (uint32_t)runtime->format);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if ((runtime->format != FORMAT_S16_LE) &&
+ (prtd->mode == MODE_PCM)) {
+ pr_err("%s(): mode:%d and format:%u are not mached\n",
+ __func__, prtd->mode, (uint32_t)runtime->format);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = voip_get_media_type(prtd->mode,
+ prtd->play_samp_rate,
+ &media_type);
+ if (ret < 0) {
+ pr_err("%s(): fail at getting media_type, ret=%d\n",
+ __func__, ret);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ pr_debug("%s(): media_type=%d\n", __func__, media_type);
+
+ if ((prtd->mode == MODE_PCM) ||
+ (prtd->mode == MODE_AMR) ||
+ (prtd->mode == MODE_AMR_WB)) {
+ ret = voip_get_rate_type(prtd->mode,
+ prtd->rate,
+ &rate_type);
+ if (ret < 0) {
+ pr_err("%s(): fail at getting rate_type, ret=%d\n",
+ __func__, ret);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ prtd->rate_type = rate_type;
+ pr_debug("rate_type=%d\n", rate_type);
+
+ } else if ((prtd->mode == MODE_IS127) ||
+ (prtd->mode == MODE_4GV_NB) ||
+ (prtd->mode == MODE_4GV_WB) ||
+ (prtd->mode == MODE_4GV_NW)) {
+ ret = voip_get_rate_type(prtd->mode,
+ prtd->evrc_min_rate,
+ &evrc_min_rate_type);
+ if (ret < 0) {
+ pr_err("%s(): fail at getting min rate, ret=%d\n",
+ __func__, ret);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ if (evrc_min_rate_type == VOC_0_RATE)
+ evrc_min_rate_type = VOC_8_RATE;
+
+ ret = voip_get_rate_type(prtd->mode,
+ prtd->evrc_max_rate,
+ &evrc_max_rate_type);
+ if (ret < 0) {
+ pr_err("%s(): fail at getting max rate, ret=%d\n",
+ __func__, ret);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ if (evrc_max_rate_type == VOC_0_RATE)
+ evrc_max_rate_type = VOC_1_RATE;
+
+ if (evrc_max_rate_type < evrc_min_rate_type) {
+ pr_err("%s(): Invalid EVRC min max rates: %d, %d\n",
+ __func__, evrc_min_rate_type,
+ evrc_max_rate_type);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ pr_debug("%s(): min rate=%d, max rate=%d\n",
+ __func__, evrc_min_rate_type, evrc_max_rate_type);
+ }
+ if ((prtd->play_samp_rate == 8000) &&
+ (prtd->cap_samp_rate == 8000))
+ voc_config_vocoder(media_type, rate_type,
+ VSS_NETWORK_ID_VOIP_NB,
+ voip_info.dtx_mode,
+ evrc_min_rate_type,
+ evrc_max_rate_type);
+ else if ((prtd->play_samp_rate == 16000) &&
+ (prtd->cap_samp_rate == 16000))
+ voc_config_vocoder(media_type, rate_type,
+ VSS_NETWORK_ID_VOIP_WB,
+ voip_info.dtx_mode,
+ evrc_min_rate_type,
+ evrc_max_rate_type);
+ else {
+ pr_debug("%s: Invalid rate playback %d, capture %d\n",
+ __func__, prtd->play_samp_rate,
+ prtd->cap_samp_rate);
+
+ ret = -EINVAL;
+ }
+done:
+
+ return ret;
+}
+
+static int msm_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct voip_drv_info *prtd = runtime->private_data;
mutex_lock(&prtd->lock);
@@ -774,63 +922,19 @@
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
ret = msm_pcm_capture_prepare(substream);
- if ((runtime->format != FORMAT_SPECIAL) &&
- ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB) ||
- (prtd->mode == MODE_IS127) || (prtd->mode == MODE_4GV_NB) ||
- (prtd->mode == MODE_4GV_WB))) {
- pr_err("mode:%d and format:%u are not mached\n",
- prtd->mode, (uint32_t)runtime->format);
- ret = -EINVAL;
- goto done;
- }
-
- if ((runtime->format != FORMAT_S16_LE) &&
- (prtd->mode == MODE_PCM)) {
- pr_err("mode:%d and format:%u are not mached\n",
- prtd->mode, (uint32_t)runtime->format);
- ret = -EINVAL;
- goto done;
- }
-
if (prtd->playback_instance && prtd->capture_instance
- && (prtd->state != VOIP_STARTED)) {
+ && (prtd->state != VOIP_STARTED)) {
+ ret = voip_config_vocoder(substream);
+ if (ret < 0) {
+ pr_err("%s(): fail at configuring vocoder for voip, ret=%d\n",
+ __func__, ret);
- ret = voip_get_rate_type(prtd->mode,
- prtd->rate,
- &rate_type);
- if (ret < 0) {
- pr_err("fail at getting rate_type\n");
- ret = -EINVAL;
goto done;
}
- prtd->rate_type = rate_type;
- ret = voip_get_media_type(prtd->mode,
- prtd->play_samp_rate,
- &media_type);
- if (ret < 0) {
- pr_err("fail at getting media_type\n");
- goto done;
- }
- pr_debug(" media_type=%d, rate_type=%d\n", media_type,
- rate_type);
- if ((prtd->play_samp_rate == 8000) &&
- (prtd->cap_samp_rate == 8000))
- voc_config_vocoder(media_type, rate_type,
- VSS_NETWORK_ID_VOIP_NB,
- voip_info.dtx_mode);
- else if ((prtd->play_samp_rate == 16000) &&
- (prtd->cap_samp_rate == 16000))
- voc_config_vocoder(media_type, rate_type,
- VSS_NETWORK_ID_VOIP_WB,
- voip_info.dtx_mode);
- else {
- pr_debug("%s: Invalid rate playback %d, capture %d\n",
- __func__, prtd->play_samp_rate,
- prtd->cap_samp_rate);
- goto done;
- }
+
voc_register_mvs_cb(voip_process_ul_pkt,
- voip_process_dl_pkt, prtd);
+ voip_process_dl_pkt, prtd);
+
ret = voc_start_voice_call(
voc_get_session_id(VOIP_SESSION_NAME));
@@ -976,6 +1080,35 @@
return 0;
}
+static int msm_voip_evrc_min_max_rate_config_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ mutex_lock(&voip_info.lock);
+
+ ucontrol->value.integer.value[0] = voip_info.evrc_min_rate;
+ ucontrol->value.integer.value[1] = voip_info.evrc_max_rate;
+
+ mutex_unlock(&voip_info.lock);
+
+ return 0;
+}
+
+static int msm_voip_evrc_min_max_rate_config_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ mutex_lock(&voip_info.lock);
+
+ voip_info.evrc_min_rate = ucontrol->value.integer.value[0];
+ voip_info.evrc_max_rate = ucontrol->value.integer.value[1];
+
+ pr_debug("%s(): evrc_min_rate=%d,evrc_max_rate=%d\n", __func__,
+ voip_info.evrc_min_rate, voip_info.evrc_max_rate);
+
+ mutex_unlock(&voip_info.lock);
+
+ return 0;
+}
+
static int voip_get_rate_type(uint32_t mode, uint32_t rate,
uint32_t *rate_type)
{
@@ -1073,6 +1206,23 @@
}
break;
}
+ case MODE_4GV_NW: {
+ switch (rate) {
+ case VOC_0_RATE:
+ case VOC_8_RATE:
+ case VOC_4_RATE:
+ case VOC_2_RATE:
+ case VOC_1_RATE:
+ case VOC_8_RATE_NC:
+ *rate_type = rate;
+ break;
+ default:
+ pr_err("wrong rate for 4GV_NW.\n");
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ }
default:
pr_err("wrong mode type.\n");
ret = -EINVAL;
@@ -1112,6 +1262,9 @@
case MODE_4GV_WB: /* EVRC-WB */
*media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
break;
+ case MODE_4GV_NW: /* EVRC-NW */
+ *media_type = VSS_MEDIA_ID_4GV_NW_MODEM;
+ break;
default:
pr_debug(" input mode is not supported\n");
ret = -EINVAL;
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index d99812f..bba4c14 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -18,8 +18,6 @@
#include <linux/atomic.h>
#include <linux/wait.h>
-#include <mach/qdsp6v2/rtac.h>
-
#include <sound/apr_audio-v2.h>
#include <mach/qdsp6v2/apr.h>
#include <sound/q6adm-v2.h>
@@ -33,8 +31,11 @@
#define RESET_COPP_ID 99
#define INVALID_COPP_ID 0xFF
-#define ADM_GET_PARAMETER_LENGTH 350
+/* Used for inband payload copy, max size is 4k */
+/* 2 is to account for module & param ID in payload */
+#define ADM_GET_PARAMETER_LENGTH (4096 - APR_HDR_SIZE - 2 * sizeof(uint32_t))
+#define ULL_SUPPORTED_SAMPLE_RATE 48000
enum {
ADM_RX_AUDPROC_CAL,
@@ -42,6 +43,7 @@
ADM_RX_AUDVOL_CAL,
ADM_TX_AUDVOL_CAL,
ADM_CUSTOM_TOP_CAL,
+ ADM_RTAC,
ADM_MAX_CAL_TYPES
};
@@ -469,6 +471,10 @@
this_adm.apr = NULL;
reset_custom_topology_flags();
this_adm.set_custom_topology = 1;
+ for (i = 0; i < ADM_MAX_CAL_TYPES; i++)
+ atomic_set(&this_adm.mem_map_cal_handles[i],
+ 0);
+ rtac_clear_mapping(ADM_RTAC_CAL);
}
pr_debug("Resetting calibration blocks");
for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
@@ -525,7 +531,8 @@
if (payload[1] != 0) {
pr_err("%s: ADM map error, resuming\n",
__func__);
- atomic_set(&this_adm.copp_stat[0], 1);
+ atomic_set(&this_adm.copp_stat[index],
+ 1);
wake_up(&this_adm.wait[index]);
}
break;
@@ -580,13 +587,18 @@
if (payload[0] != 0)
pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS_V5 returned error = 0x%x\n",
__func__, payload[0]);
- rtac_make_adm_callback(payload,
- data->payload_size);
- adm_get_parameters[0] = payload[3];
- pr_debug("GET_PP PARAM:received parameter length: %x\n",
- adm_get_parameters[0]);
- for (i = 0; i < payload[3]; i++)
- adm_get_parameters[1+i] = payload[4+i];
+ if (rtac_make_adm_callback(payload,
+ data->payload_size))
+ break;
+
+ if (data->payload_size > (4 * sizeof(uint32_t))) {
+ adm_get_parameters[0] = payload[3];
+ pr_debug("GET_PP PARAM:received parameter length: %x\n",
+ adm_get_parameters[0]);
+ /* storing param size then params */
+ for (i = 0; i < payload[3]; i++)
+ adm_get_parameters[1+i] = payload[4+i];
+ }
atomic_set(&this_adm.copp_stat[index], 1);
wake_up(&this_adm.wait[index]);
break;
@@ -596,7 +608,7 @@
atomic_set(&this_adm.mem_map_cal_handles[
atomic_read(&this_adm.mem_map_cal_index)],
*payload);
- atomic_set(&this_adm.copp_stat[0], 1);
+ atomic_set(&this_adm.copp_stat[index], 1);
wake_up(&this_adm.wait[index]);
break;
default:
@@ -637,8 +649,8 @@
/* Only call this once */
this_adm.set_custom_topology = 0;
- result = adm_memory_map_regions(port_id, &cal_block.cal_paddr,
- 0, &size, 1);
+ result = adm_memory_map_regions(port_id,
+ &cal_block.cal_paddr, 0, &size, 1);
if (result < 0) {
pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
__func__, cal_block.cal_paddr,
@@ -760,11 +772,15 @@
int result = 0;
s32 acdb_path;
struct acdb_cal_block aud_cal;
- int size = 4096;
+ int size;
pr_debug("%s\n", __func__);
/* Maps audio_dev_ctrl path definition to ACDB definition */
acdb_path = path - 1;
+ if (acdb_path == TX_CAL)
+ size = 4096 * 4;
+ else
+ size = 4096;
pr_debug("%s: Sending audproc cal\n", __func__);
get_audproc_cal(acdb_path, &aud_cal);
@@ -777,9 +793,7 @@
this_adm.mem_addr_audproc[acdb_path].cal_size)) {
if (this_adm.mem_addr_audproc[acdb_path].cal_paddr != 0)
- adm_memory_unmap_regions(port_id,
- &this_adm.mem_addr_audproc[acdb_path].
- cal_paddr, &size, 1);
+ adm_memory_unmap_regions(port_id);
result = adm_memory_map_regions(port_id, &aud_cal.cal_paddr,
0, &size, 1);
@@ -813,9 +827,7 @@
this_adm.mem_addr_audvol[acdb_path].cal_size)) {
if (this_adm.mem_addr_audvol[acdb_path].cal_paddr != 0)
- adm_memory_unmap_regions(port_id,
- &this_adm.mem_addr_audvol[acdb_path].cal_paddr,
- &size, 1);
+ adm_memory_unmap_regions(port_id);
result = adm_memory_map_regions(port_id, &aud_cal.cal_paddr,
0, &size, 1);
@@ -838,6 +850,133 @@
__func__, port_id, acdb_path);
}
+int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
+{
+ int result = 0;
+ pr_debug("%s\n", __func__);
+
+ if (cal_block == NULL) {
+ pr_err("%s: cal_block is NULL!\n",
+ __func__);
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (cal_block->cal_data.paddr == 0) {
+ pr_debug("%s: No address to map!\n",
+ __func__);
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (cal_block->map_data.map_size == 0) {
+ pr_debug("%s: map size is 0!\n",
+ __func__);
+ result = -EINVAL;
+ goto done;
+ }
+
+ /* valid port ID needed for callback use primary I2S */
+ atomic_set(&this_adm.mem_map_cal_index, ADM_RTAC);
+ result = adm_memory_map_regions(PRIMARY_I2S_RX,
+ &cal_block->cal_data.paddr, 0,
+ &cal_block->map_data.map_size, 1);
+ if (result < 0) {
+ pr_err("%s: RTAC mmap did not work! addr = 0x%x, size = %d\n",
+ __func__, cal_block->cal_data.paddr,
+ cal_block->map_data.map_size);
+ goto done;
+ }
+
+ cal_block->map_data.map_handle = atomic_read(
+ &this_adm.mem_map_cal_handles[ADM_RTAC]);
+done:
+ return result;
+}
+
+int adm_unmap_rtac_block(uint32_t *mem_map_handle)
+{
+ int result = 0;
+ pr_debug("%s\n", __func__);
+
+ if (mem_map_handle == NULL) {
+ pr_debug("%s: Map handle is NULL, nothing to unmap\n",
+ __func__);
+ goto done;
+ }
+
+ if (*mem_map_handle == 0) {
+ pr_debug("%s: Map handle is 0, nothing to unmap\n",
+ __func__);
+ goto done;
+ }
+
+ if (*mem_map_handle != atomic_read(
+ &this_adm.mem_map_cal_handles[ADM_RTAC])) {
+ pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
+ __func__, *mem_map_handle, atomic_read(
+ &this_adm.mem_map_cal_handles[ADM_RTAC]));
+
+ /* if mismatch use handle passed in to unmap */
+ atomic_set(&this_adm.mem_map_cal_handles[ADM_RTAC],
+ *mem_map_handle);
+ }
+
+ /* valid port ID needed for callback use primary I2S */
+ atomic_set(&this_adm.mem_map_cal_index, ADM_RTAC);
+ result = adm_memory_unmap_regions(PRIMARY_I2S_RX);
+ if (result < 0) {
+ pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
+ __func__, result);
+ } else {
+ atomic_set(&this_adm.mem_map_cal_handles[ADM_RTAC], 0);
+ *mem_map_handle = 0;
+ }
+done:
+ return result;
+}
+
+int adm_unmap_cal_blocks(void)
+{
+ int i;
+ int result = 0;
+ int result2 = 0;
+
+ for (i = 0; i < ADM_MAX_CAL_TYPES; i++) {
+ if (atomic_read(&this_adm.mem_map_cal_handles[i]) != 0) {
+
+ if (i <= ADM_TX_AUDPROC_CAL) {
+ this_adm.mem_addr_audproc[i].cal_paddr = 0;
+ this_adm.mem_addr_audproc[i].cal_size = 0;
+ } else if (i <= ADM_TX_AUDVOL_CAL) {
+ this_adm.mem_addr_audvol
+ [(i - ADM_RX_AUDVOL_CAL)].cal_paddr
+ = 0;
+ this_adm.mem_addr_audvol
+ [(i - ADM_RX_AUDVOL_CAL)].cal_size
+ = 0;
+ } else if (i == ADM_CUSTOM_TOP_CAL) {
+ this_adm.set_custom_topology = 1;
+ } else {
+ continue;
+ }
+
+ /* valid port ID needed for callback use primary I2S */
+ atomic_set(&this_adm.mem_map_cal_index, i);
+ result2 = adm_memory_unmap_regions(PRIMARY_I2S_RX);
+ if (result2 < 0) {
+ pr_err("%s: adm_memory_unmap_regions failed, err %d\n",
+ __func__, result2);
+ result = result2;
+ } else {
+ atomic_set(&this_adm.mem_map_cal_handles[i],
+ 0);
+ }
+ }
+ }
+ return result;
+}
+
int adm_connect_afe_port(int mode, int session_id, int port_id)
{
struct adm_cmd_connect_afe_port_v5 cmd;
@@ -986,11 +1125,14 @@
(open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
rate = 16000;
- if (perf_mode)
+ if (perf_mode) {
open.topology_id = NULL_COPP_TOPOLOGY;
+ rate = ULL_SUPPORTED_SAMPLE_RATE;
+ }
open.dev_num_channel = channel_mode & 0x00FF;
open.bit_width = bits_per_sample;
+ WARN_ON(perf_mode && (rate != 48000));
open.sample_rate = rate;
memset(open.dev_channel_mapping, 0, 8);
@@ -1294,7 +1436,7 @@
++mregions;
}
- atomic_set(&this_adm.copp_stat[0], 0);
+ atomic_set(&this_adm.copp_stat[index], 0);
ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
if (ret < 0) {
pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
@@ -1304,7 +1446,7 @@
}
ret = wait_event_timeout(this_adm.wait[index],
- atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
+ atomic_read(&this_adm.copp_stat[index]), 5 * HZ);
if (!ret) {
pr_err("%s: timeout. waited for memory_map\n", __func__);
ret = -EINVAL;
@@ -1315,8 +1457,7 @@
return ret;
}
-int adm_memory_unmap_regions(int32_t port_id, uint32_t *buf_add,
- uint32_t *bufsz, uint32_t bufcnt)
+int adm_memory_unmap_regions(int32_t port_id)
{
struct avs_cmd_shared_mem_unmap_regions unmap_regions;
int ret = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 6dfe5b3..f7be34c 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -357,7 +357,8 @@
{
int ret;
- atomic_set(&this_afe.state, 1);
+ if (wait)
+ atomic_set(&this_afe.state, 1);
atomic_set(&this_afe.status, 0);
ret = apr_send_pkt(this_afe.apr, data);
if (ret > 0) {
@@ -469,6 +470,35 @@
return;
}
+int afe_unmap_cal_blocks(void)
+{
+ int i;
+ int result = 0;
+ int result2 = 0;
+
+ for (i = 0; i < MAX_AFE_CAL_TYPES; i++) {
+ if (atomic_read(&this_afe.mem_map_cal_handles[i]) != 0) {
+
+ atomic_set(&this_afe.mem_map_cal_index, i);
+ result2 = afe_cmd_memory_unmap(atomic_read(
+ &this_afe.mem_map_cal_handles[i]));
+ if (result2 < 0) {
+ pr_err("%s: unmap failed, err %d\n",
+ __func__, result2);
+ result = result2;
+ } else {
+ atomic_set(&this_afe.mem_map_cal_handles[i],
+ 0);
+ }
+ atomic_set(&this_afe.mem_map_cal_index, -1);
+
+ this_afe.afe_cal_addr[i].cal_paddr = 0;
+ this_afe.afe_cal_addr[i].cal_size = 0;
+ }
+ }
+ return result;
+}
+
static int afe_spk_prot_prepare(int port, int param_id,
union afe_spkr_prot_config *prot_config)
{
@@ -1223,7 +1253,13 @@
mad_type = afe_port_get_mad_type(port_id);
pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
mad_type);
- if (mad_type != MAD_HW_NONE) {
+ if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
+ if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
+ !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
+ pr_err("%s: AFE isn't configured yet for HW MAD\n",
+ __func__);
+ return -EINVAL;
+ }
ret = afe_turn_onoff_hw_mad(mad_type, true);
if (ret) {
pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
@@ -2006,7 +2042,6 @@
goto fail_cmd;
}
- pr_debug("%s: mmap handle 0x%x\n", __func__, this_afe.mmap_handle);
kfree(mmap_region_cmd);
return 0;
fail_cmd:
@@ -2090,7 +2125,6 @@
cnt = port->max_buf_cnt - 1;
if (port->buf[0].data) {
- msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
__func__,
(void *)port->buf[0].data,
@@ -2098,6 +2132,9 @@
(void *)&port->buf[0].phys,
(void *)port->buf[0].client,
(void *)port->buf[0].handle);
+ msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
+ port->buf[0].client = NULL;
+ port->buf[0].handle = NULL;
}
while (cnt >= 0) {
@@ -2817,7 +2854,7 @@
mad_type = afe_port_get_mad_type(port_id);
pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
mad_type);
- if (mad_type != MAD_HW_NONE) {
+ if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
pr_debug("%s: Turn off MAD\n", __func__);
ret = afe_turn_onoff_hw_mad(mad_type, false);
if (ret) {
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 5ad8e2d..9b74eea 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -36,7 +36,6 @@
#include <mach/memory.h>
#include <mach/debug_mm.h>
-#include <mach/qdsp6v2/rtac.h>
#include <sound/apr_audio-v2.h>
#include <sound/q6asm-v2.h>
@@ -72,11 +71,11 @@
static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
uint32_t bufsz, uint32_t bufcnt,
bool is_contiguous);
-static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
- uint32_t bufsz, uint32_t bufcnt);
+static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir);
static void q6asm_reset_buf_state(struct audio_client *ac);
static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels);
+void *q6asm_mmap_apr_reg(void);
#ifdef CONFIG_DEBUG_FS
@@ -96,9 +95,28 @@
static int out_cold_index;
static char *out_buffer;
static char *in_buffer;
+static struct audio_buffer common_buf[2];
+static struct audio_client common_client;
static int set_custom_topology;
static int topology_map_handle;
+
+int q6asm_mmap_apr_dereg(void)
+{
+ int c;
+
+ c = atomic_sub_return(1, &this_mmap.ref_cnt);
+ if (c == 0) {
+ apr_deregister(this_mmap.apr);
+ pr_debug("%s: APR De-Register common port\n", __func__);
+ } else if (c < 0) {
+ pr_err("%s: APR Common Port Already Closed\n", __func__);
+ atomic_set(&this_mmap.ref_cnt, 0);
+ }
+
+ return 0;
+}
+
static int audio_output_latency_dbgfs_open(struct inode *inode,
struct file *file)
{
@@ -340,7 +358,6 @@
{
struct acdb_cal_block cal_block;
struct cmd_set_topologies asm_top;
- struct audio_buffer *buf;
struct asm_buffer_node *buf_node = NULL;
struct list_head *ptr, *next;
int result;
@@ -354,20 +371,29 @@
}
if (set_custom_topology) {
+ if (common_client.mmap_apr == NULL) {
+ common_client.mmap_apr = q6asm_mmap_apr_reg();
+ common_client.apr = common_client.mmap_apr;
+ if (common_client.mmap_apr == NULL) {
+ pr_err("%s: q6asm_mmap_apr_reg failed\n",
+ __func__);
+ result = -EPERM;
+ goto done;
+ }
+ }
/* Only call this once */
set_custom_topology = 0;
/* Use first asm buf to map memory */
- buf = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL);
- if (!buf) {
- pr_debug("%s: could not allocate temp memory\n",
+ if (common_client.port[IN].buf == NULL) {
+ pr_err("%s: common buf is NULL\n",
__func__);
goto done;
}
- buf[0].phys = cal_block.cal_paddr;
- ac->port[0].buf = buf;
+ common_client.port[IN].buf->phys = cal_block.cal_paddr;
- result = q6asm_memory_map_regions(ac, 0, size, 1, 1);
+ result = q6asm_memory_map_regions(&common_client,
+ IN, size, 1, 1);
if (result < 0) {
pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
__func__, cal_block.cal_paddr,
@@ -375,7 +401,8 @@
goto done;
}
- list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
+ list_for_each_safe(ptr, next,
+ &common_client.port[IN].mem_map_handle) {
buf_node = list_entry(ptr, struct asm_buffer_node,
list);
if (buf_node->buf_addr_lsw == cal_block.cal_paddr) {
@@ -384,7 +411,13 @@
}
}
- kfree(buf);
+ result = q6asm_mmap_apr_dereg();
+ if (result < 0) {
+ pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
+ __func__, result);
+ } else {
+ common_client.mmap_apr = NULL;
+ }
}
q6asm_add_hdr(ac, &asm_top.hdr, APR_PKT_SIZE(APR_HDR_SIZE,
@@ -415,11 +448,181 @@
goto done;
}
-
done:
return;
}
+int q6asm_map_rtac_block(struct rtac_cal_block_data *cal_block)
+{
+ int result = 0;
+ struct asm_buffer_node *buf_node = NULL;
+ struct list_head *ptr, *next;
+ pr_debug("%s\n", __func__);
+
+ if (cal_block == NULL) {
+ pr_err("%s: cal_block is NULL!\n",
+ __func__);
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (cal_block->cal_data.paddr == 0) {
+ pr_debug("%s: No address to map!\n",
+ __func__);
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (common_client.mmap_apr == NULL) {
+ common_client.mmap_apr = q6asm_mmap_apr_reg();
+ if (common_client.mmap_apr == NULL) {
+ pr_err("%s: q6asm_mmap_apr_reg failed\n",
+ __func__);
+ result = -EPERM;
+ goto done;
+ }
+ }
+
+ if (cal_block->map_data.map_size == 0) {
+ pr_debug("%s: map size is 0!\n",
+ __func__);
+ result = -EINVAL;
+ goto done;
+ }
+
+ /* Use second asm buf to map memory */
+ if (common_client.port[OUT].buf == NULL) {
+ pr_err("%s: common buf is NULL\n",
+ __func__);
+ result = -EINVAL;
+ goto done;
+ }
+
+ common_client.port[OUT].buf->phys = cal_block->cal_data.paddr;
+
+ result = q6asm_memory_map_regions(&common_client,
+ OUT, cal_block->map_data.map_size, 1, 1);
+ if (result < 0) {
+ pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
+ __func__, cal_block->cal_data.paddr,
+ cal_block->map_data.map_size);
+ goto done;
+ }
+
+ list_for_each_safe(ptr, next,
+ &common_client.port[OUT].mem_map_handle) {
+ buf_node = list_entry(ptr, struct asm_buffer_node,
+ list);
+ if (buf_node->buf_addr_lsw == cal_block->cal_data.paddr) {
+ cal_block->map_data.map_handle = buf_node->mmap_hdl;
+ break;
+ }
+ }
+
+ result = q6asm_mmap_apr_dereg();
+ if (result < 0) {
+ pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
+ __func__, result);
+ } else {
+ common_client.mmap_apr = NULL;
+ }
+done:
+ return result;
+}
+
+int q6asm_unmap_rtac_block(uint32_t *mem_map_handle)
+{
+ int result = 0;
+ int result2 = 0;
+ pr_debug("%s\n", __func__);
+
+ if (mem_map_handle == NULL) {
+ pr_debug("%s: Map handle is NULL, nothing to unmap\n",
+ __func__);
+ goto done;
+ }
+
+ if (*mem_map_handle == 0) {
+ pr_debug("%s: Map handle is 0, nothing to unmap\n",
+ __func__);
+ goto done;
+ }
+
+ if (common_client.mmap_apr == NULL) {
+ common_client.mmap_apr = q6asm_mmap_apr_reg();
+ if (common_client.mmap_apr == NULL) {
+ pr_err("%s: q6asm_mmap_apr_reg failed\n",
+ __func__);
+ result = -EPERM;
+ goto done;
+ }
+ }
+
+
+ result2 = q6asm_memory_unmap_regions(&common_client, OUT);
+ if (result2 < 0) {
+ pr_err("%s: unmap failed, err %d\n",
+ __func__, result2);
+ result = result2;
+ } else {
+ mem_map_handle = 0;
+ }
+
+ result2 = q6asm_mmap_apr_dereg();
+ if (result2 < 0) {
+ pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
+ __func__, result2);
+ result = result2;
+ } else {
+ common_client.mmap_apr = NULL;
+ }
+done:
+ return result;
+}
+
+int q6asm_unmap_cal_blocks(void)
+{
+ int result = 0;
+ int result2 = 0;
+ pr_debug("%s\n", __func__);
+
+ if (topology_map_handle == 0)
+ goto done;
+
+ if (common_client.mmap_apr == NULL) {
+ common_client.mmap_apr = q6asm_mmap_apr_reg();
+ if (common_client.mmap_apr == NULL) {
+ pr_err("%s: q6asm_mmap_apr_reg failed\n",
+ __func__);
+ result = -EPERM;
+ goto done;
+ }
+ }
+
+ result2 = q6asm_memory_unmap_regions(&common_client, IN);
+ if (result2 < 0) {
+ pr_err("%s: unmap failed, err %d\n",
+ __func__, result2);
+ result = result2;
+ } else {
+ topology_map_handle = 0;
+ }
+
+ result2 = q6asm_mmap_apr_dereg();
+ if (result2 < 0) {
+ pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
+ __func__, result2);
+ result = result2;
+ } else {
+ common_client.mmap_apr = NULL;
+ }
+
+ set_custom_topology = 0;
+
+done:
+ return result;
+}
+
int q6asm_audio_client_buf_free(unsigned int dir,
struct audio_client *ac)
{
@@ -437,9 +640,7 @@
cnt = port->max_buf_cnt - 1;
if (cnt >= 0) {
- rc = q6asm_memory_unmap_regions(ac, dir,
- port->buf[0].size,
- port->max_buf_cnt);
+ rc = q6asm_memory_unmap_regions(ac, dir);
if (rc < 0)
pr_err("%s CMD Memory_unmap_regions failed\n",
__func__);
@@ -449,6 +650,8 @@
if (port->buf[cnt].data) {
msm_audio_ion_free(port->buf[cnt].client,
port->buf[cnt].handle);
+ port->buf[cnt].client = NULL;
+ port->buf[cnt].handle = NULL;
port->buf[cnt].data = NULL;
port->buf[cnt].phys = 0;
--(port->max_buf_cnt);
@@ -485,7 +688,6 @@
}
if (port->buf[0].data) {
- msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
__func__,
(void *)port->buf[0].data,
@@ -493,6 +695,9 @@
(void *)&port->buf[0].phys,
(void *)port->buf[0].client,
(void *)port->buf[0].handle);
+ msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
+ port->buf[0].client = NULL;
+ port->buf[0].handle = NULL;
}
while (cnt >= 0) {
@@ -507,23 +712,6 @@
return 0;
}
-int q6asm_mmap_apr_dereg(void)
-{
- int c;
-
- c = atomic_sub_return(1, &this_mmap.ref_cnt);
- if (c == 0) {
- apr_deregister(this_mmap.apr);
- pr_debug("%s: APR De-Register common port\n", __func__);
- } else if (c < 0) {
- pr_err("%s: APR Common Port Already Closed\n", __func__);
- atomic_set(&this_mmap.ref_cnt, 0);
- }
-
- return 0;
-}
-
-
void q6asm_audio_client_free(struct audio_client *ac)
{
int loopcnt;
@@ -662,6 +850,10 @@
struct audio_client *q6asm_get_audio_client(int session_id)
{
+ if (session_id == ASM_CONTROL_SESSION) {
+ return &common_client;
+ }
+
if ((session_id <= 0) || (session_id > SESSION_MAX)) {
pr_err("%s: invalid session: %d\n", __func__, session_id);
goto err;
@@ -871,6 +1063,8 @@
this_mmap.apr = NULL;
reset_custom_topology_flags();
set_custom_topology = 1;
+ topology_map_handle = 0;
+ rtac_clear_mapping(ASM_RTAC_CAL);
return 0;
}
sid = (data->token >> 8) & 0x0F;
@@ -891,7 +1085,7 @@
case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:
if (payload[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n",
- __func__, payload[0], payload[1], sid);
+ __func__, payload[0], payload[1], sid);
}
if (atomic_read(&ac->cmd_state)) {
@@ -1005,8 +1199,6 @@
(uint32_t *)data->payload, ac->priv);
apr_reset(ac->apr);
ac->apr = NULL;
- reset_custom_topology_flags();
- set_custom_topology = 1;
return 0;
}
@@ -2602,7 +2794,7 @@
int rc = 0;
int cmd_size = 0;
- if (!ac || ac->apr == NULL || ac->mmap_apr == NULL) {
+ if (!ac || ac->mmap_apr == NULL) {
pr_err("APR handle NULL\n");
return -EINVAL;
}
@@ -2679,7 +2871,7 @@
int rc = 0;
- if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
+ if (!ac || this_mmap.apr == NULL) {
pr_err("APR handle NULL\n");
return -EINVAL;
}
@@ -2749,7 +2941,7 @@
uint32_t bufcnt_t;
uint32_t bufsz_t;
- if (!ac || ac->apr == NULL || ac->mmap_apr == NULL) {
+ if (!ac || ac->mmap_apr == NULL) {
pr_err("APR handle NULL\n");
return -EINVAL;
}
@@ -2848,8 +3040,7 @@
return rc;
}
-static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
- uint32_t bufsz, uint32_t bufcnt)
+static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
{
struct avs_cmd_shared_mem_unmap_regions mem_unmap;
struct audio_port_data *port = NULL;
@@ -2859,7 +3050,7 @@
int rc = 0;
int cmd_size = 0;
- if (!ac || ac->apr == NULL || ac->mmap_apr == NULL) {
+ if (!ac || ac->mmap_apr == NULL) {
pr_err("APR handle NULL\n");
return -EINVAL;
}
@@ -3849,7 +4040,7 @@
{
pr_debug("%s\n", __func__);
- if (session_id < 0 || session_id > SESSION_MAX) {
+ if (session_id <= 0 || session_id > SESSION_MAX) {
pr_err("%s: invalid session_id = %d\n", __func__, session_id);
return -EINVAL;
}
@@ -3860,10 +4051,29 @@
static int __init q6asm_init(void)
{
+ int lcnt;
pr_debug("%s\n", __func__);
+
memset(session, 0, sizeof(session));
set_custom_topology = 1;
+ /*setup common client used for cal mem map */
+ common_client.session = ASM_CONTROL_SESSION;
+ common_client.port[0].buf = &common_buf[0];
+ common_client.port[1].buf = &common_buf[1];
+ init_waitqueue_head(&common_client.cmd_wait);
+ init_waitqueue_head(&common_client.time_wait);
+ atomic_set(&common_client.time_flag, 1);
+ INIT_LIST_HEAD(&common_client.port[0].mem_map_handle);
+ INIT_LIST_HEAD(&common_client.port[1].mem_map_handle);
+ mutex_init(&common_client.cmd_lock);
+ for (lcnt = 0; lcnt <= OUT; lcnt++) {
+ mutex_init(&common_client.port[lcnt].lock);
+ spin_lock_init(&common_client.port[lcnt].dsp_lock);
+ }
+ atomic_set(&common_client.cmd_state, 0);
+ atomic_set(&common_client.nowait_cmd_cnt, 0);
+
config_debug_fs_init();
return 0;
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
index aec048e..9227b23 100644
--- a/sound/soc/msm/qdsp6v2/q6lsm.c
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -45,6 +45,7 @@
LSM_INVALID_SESSION_ID = 0,
LSM_MIN_SESSION_ID = 1,
LSM_MAX_SESSION_ID = 8,
+ LSM_CONTROL_SESSION = 0x0F,
};
struct lsm_common {
@@ -53,6 +54,7 @@
uint32_t lsm_cal_addr;
uint32_t lsm_cal_size;
uint32_t mmap_handle_for_cal;
+ struct lsm_client common_client;
struct mutex apr_lock;
};
@@ -191,7 +193,7 @@
return 0;
}
-struct lsm_client *q6lsm_client_alloc(app_cb cb, void *priv)
+struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv)
{
struct lsm_client *client;
int n;
@@ -269,7 +271,7 @@
mmap_handle_p = mmap_p;
}
atomic_set(&client->cmd_state, CMD_STATE_WAIT_RESP);
- ret = apr_send_pkt(client->apr, data);
+ ret = apr_send_pkt(handle, data);
if (mmap_p)
spin_unlock_irqrestore(&mmap_lock, flags);
@@ -318,13 +320,6 @@
int rc;
struct lsm_stream_cmd_open_tx open;
- if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
- !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
- pr_err("%s: AFE isn't configured yet\n", __func__);
- rc = -EAGAIN;
- goto exit;
- }
-
memset(&open, 0, sizeof(open));
q6lsm_add_hdr(client, &open.hdr, sizeof(open), true);
@@ -337,8 +332,6 @@
pr_err("%s: Open failed opcode 0x%x, rc %d\n",
__func__, open.hdr.opcode, rc);
-exit:
- pr_debug("%s: leave %d\n", __func__, rc);
return rc;
}
@@ -607,6 +600,7 @@
}
lsm_common.lsm_cal_addr = lsm_cal.cal_paddr;
lsm_common.lsm_cal_size = LSM_CAL_SIZE;
+ lsm_common.common_client.session = client->session;
}
q6lsm_add_hdr(client, ¶ms.hdr, sizeof(params), true);
@@ -626,6 +620,51 @@
return rc;
}
+int q6lsm_unmap_cal_blocks(void)
+{
+ int result = 0;
+ int result2 = 0;
+
+ if (lsm_common.mmap_handle_for_cal == 0)
+ goto done;
+
+ if (lsm_common.common_client.mmap_apr == NULL) {
+ lsm_common.common_client.mmap_apr = q6lsm_mmap_apr_reg();
+ if (lsm_common.common_client.mmap_apr == NULL) {
+ pr_err("%s: q6lsm_mmap_apr_reg failed\n",
+ __func__);
+ result = -EPERM;
+ goto done;
+ }
+ }
+
+ result2 = q6lsm_memory_unmap_regions(
+ &lsm_common.common_client,
+ lsm_common.mmap_handle_for_cal);
+ if (result2 < 0) {
+ pr_err("%s: unmap failed, err %d\n",
+ __func__, result2);
+ result = result2;
+ } else {
+ lsm_common.mmap_handle_for_cal = 0;
+ }
+
+ result2 = q6lsm_mmap_apr_dereg();
+ if (result2 < 0) {
+ pr_err("%s: q6lsm_mmap_apr_dereg failed, err %d\n",
+ __func__, result2);
+ result = result2;
+ } else {
+ lsm_common.common_client.mmap_apr = NULL;
+ }
+
+ lsm_common.lsm_cal_addr = 0;
+ lsm_common.lsm_cal_size = 0;
+
+done:
+ return result;
+}
+
int q6lsm_snd_model_buf_free(struct lsm_client *client)
{
int rc;
@@ -655,6 +694,11 @@
unsigned long flags;
struct lsm_client *client = NULL;
+ if (session_id == LSM_CONTROL_SESSION) {
+ client = &lsm_common.common_client;
+ goto done;
+ }
+
spin_lock_irqsave(&lsm_session_lock, flags);
if (session_id < LSM_MIN_SESSION_ID || session_id > LSM_MAX_SESSION_ID)
pr_err("%s: Invalid session %d\n", __func__, session_id);
@@ -663,7 +707,7 @@
else
client = lsm_session[session_id];
spin_unlock_irqrestore(&lsm_session_lock, flags);
-
+done:
return client;
}
@@ -842,6 +886,12 @@
spin_lock_init(&lsm_session_lock);
spin_lock_init(&mmap_lock);
mutex_init(&lsm_common.apr_lock);
+
+ lsm_common.common_client.session = LSM_CONTROL_SESSION;
+ init_waitqueue_head(&lsm_common.common_client.cmd_wait);
+ mutex_init(&lsm_common.common_client.cmd_lock);
+ atomic_set(&lsm_common.common_client.cmd_state, CMD_STATE_CLEARED);
+
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index c863497..c16b14c 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -19,7 +19,6 @@
#include <linux/msm_audio_ion.h>
#include <asm/mach-types.h>
-#include <mach/qdsp6v2/rtac.h>
#include <mach/socinfo.h>
#include <mach/qdsp6v2/apr_tal.h>
@@ -45,6 +44,7 @@
VOC_TOKEN_NONE,
VOIP_MEM_MAP_TOKEN,
VOC_CAL_MEM_MAP_TOKEN,
+ VOC_RTAC_MEM_MAP_TOKEN
};
static struct common_data common;
@@ -88,6 +88,7 @@
static int is_cal_memory_allocated(void);
static int is_voip_memory_allocated(void);
static int voice_alloc_cal_mem_map_table(void);
+static int voice_alloc_rtac_mem_map_table(void);
static int voice_alloc_oob_shared_mem(void);
static int voice_free_oob_shared_mem(void);
static int voice_alloc_oob_mem_table(void);
@@ -1404,6 +1405,63 @@
return ret;
}
+
+static int free_cal_map_table(void)
+{
+ int ret = 0;
+
+ if ((common.cal_mem_map_table.client == NULL) ||
+ (common.cal_mem_map_table.handle == NULL))
+ goto done;
+
+ ret = msm_audio_ion_free(common.cal_mem_map_table.client,
+ common.cal_mem_map_table.handle);
+ if (ret < 0) {
+ pr_err("%s: msm_audio_ion_free failed:\n", __func__);
+ ret = -EPERM;
+ }
+
+done:
+ common.cal_mem_map_table.client = NULL;
+ common.cal_mem_map_table.handle = NULL;
+ return ret;
+}
+
+static int is_rtac_memory_allocated(void)
+{
+ bool ret;
+
+ if (common.rtac_mem_map_table.client != NULL &&
+ common.rtac_mem_map_table.handle != NULL)
+ ret = true;
+ else
+ ret = false;
+
+ return ret;
+}
+
+static int free_rtac_map_table(void)
+{
+ int ret = 0;
+
+ if ((common.rtac_mem_map_table.client == NULL) ||
+ (common.rtac_mem_map_table.handle == NULL))
+ goto done;
+
+ ret = msm_audio_ion_free(common.rtac_mem_map_table.client,
+ common.rtac_mem_map_table.handle);
+ if (ret < 0) {
+ pr_err("%s: msm_audio_ion_free failed:\n", __func__);
+ ret = -EPERM;
+ }
+
+done:
+ common.rtac_mem_map_table.client = NULL;
+ common.rtac_mem_map_table.handle = NULL;
+ return ret;
+}
+
+
static int is_voip_memory_allocated(void)
{
bool ret;
@@ -1486,7 +1544,8 @@
switch (common.mvs_info.media_type) {
case VSS_MEDIA_ID_EVRC_MODEM:
case VSS_MEDIA_ID_4GV_NB_MODEM:
- case VSS_MEDIA_ID_4GV_WB_MODEM: {
+ case VSS_MEDIA_ID_4GV_WB_MODEM:
+ case VSS_MEDIA_ID_4GV_NW_MODEM: {
struct cvs_set_cdma_enc_minmax_rate_cmd cvs_set_cdma_rate;
pr_debug("Setting EVRC min-max rate\n");
@@ -1503,8 +1562,10 @@
cvs_set_cdma_rate.hdr.token = 0;
cvs_set_cdma_rate.hdr.opcode =
VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE;
- cvs_set_cdma_rate.cdma_rate.min_rate = common.mvs_info.rate;
- cvs_set_cdma_rate.cdma_rate.max_rate = common.mvs_info.rate;
+ cvs_set_cdma_rate.cdma_rate.min_rate =
+ common.mvs_info.evrc_min_rate;
+ cvs_set_cdma_rate.cdma_rate.max_rate =
+ common.mvs_info.evrc_max_rate;
v->cvs_state = CMD_STATUS_FAIL;
@@ -1522,6 +1583,13 @@
goto fail;
}
+
+ if (common.mvs_info.media_type != VSS_MEDIA_ID_EVRC_MODEM) {
+ ret = voice_set_dtx(v);
+ if (ret < 0)
+ goto fail;
+ }
+
break;
}
case VSS_MEDIA_ID_AMR_NB_MODEM: {
@@ -2439,72 +2507,6 @@
return ret;
}
-int voc_register_vocproc_vol_table(void)
-{
- int result = 0;
- int result2 = 0;
- int i;
- struct voice_data *v = NULL;
- pr_debug("%s\n", __func__);
-
- mutex_lock(&common.common_lock);
- for (i = 0; i < MAX_VOC_SESSIONS; i++) {
- v = &common.voice[i];
-
- mutex_lock(&v->lock);
- if (is_voc_state_active(v->voc_state)) {
- result2 = voice_send_cvp_register_vol_cal_cmd(v);
- if (result2 < 0) {
- pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
- __func__, v->session_id);
- result = result2;
- /* Still try to register other sessions */
- }
- }
- mutex_unlock(&v->lock);
- }
-
- mutex_unlock(&common.common_lock);
- return result;
-}
-
-int voc_deregister_vocproc_vol_table(void)
-{
- int result = 0;
- int success = 0;
- int i;
- struct voice_data *v = NULL;
- pr_debug("%s\n", __func__);
-
- mutex_lock(&common.common_lock);
- for (i = 0; i < MAX_VOC_SESSIONS; i++) {
- v = &common.voice[i];
-
- mutex_lock(&v->lock);
- if (is_voc_state_active(v->voc_state)) {
- result = voice_send_cvp_deregister_vol_cal_cmd(v);
- if (result < 0) {
- pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
- __func__, v->session_id);
- mutex_unlock(&v->lock);
- mutex_unlock(&common.common_lock);
- if (success) {
- pr_err("%s: Try to re-register all deregistered sessions!\n",
- __func__);
- voc_register_vocproc_vol_table();
- }
- goto done;
- } else {
- success = 1;
- }
- }
- mutex_unlock(&v->lock);
- }
- mutex_unlock(&common.common_lock);
-done:
- return result;
-}
-
static int voice_map_memory_physical_cmd(struct voice_data *v,
struct mem_map_table *table_info,
dma_addr_t phys,
@@ -2642,6 +2644,313 @@
return ret;
}
+static int voice_pause_voice_call(struct voice_data *v)
+{
+ struct apr_hdr mvm_pause_voice_cmd;
+ void *apr_mvm;
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+
+ if (v == NULL) {
+ pr_err("%s: Voice data is NULL\n", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ apr_mvm = common.apr_q6_mvm;
+ if (!apr_mvm) {
+ pr_err("%s: apr_mvm is NULL.\n", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ mvm_pause_voice_cmd.hdr_field =
+ APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ mvm_pause_voice_cmd.pkt_size =
+ APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(mvm_pause_voice_cmd) - APR_HDR_SIZE);
+ mvm_pause_voice_cmd.src_port =
+ voice_get_idx_for_session(v->session_id);
+ mvm_pause_voice_cmd.dest_port = voice_get_mvm_handle(v);
+ mvm_pause_voice_cmd.token = 0;
+ mvm_pause_voice_cmd.opcode = VSS_IMVM_CMD_PAUSE_VOICE;
+ v->mvm_state = CMD_STATUS_FAIL;
+
+ pr_debug("%s: send mvm_pause_voice_cmd pkt size = %d\n",
+ __func__, mvm_pause_voice_cmd.pkt_size);
+
+ ret = apr_send_pkt(apr_mvm,
+ (uint32_t *)&mvm_pause_voice_cmd);
+ if (ret < 0) {
+ pr_err("Fail in sending VSS_IMVM_CMD_PAUSE_VOICE\n");
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = wait_event_timeout(v->mvm_wait,
+ (v->mvm_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: Command timeout\n", __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+done:
+ return ret;
+}
+
+int voc_register_vocproc_vol_table(void)
+{
+ int result = 0;
+ int result2 = 0;
+ int i;
+ struct voice_data *v = NULL;
+
+ pr_debug("%s\n", __func__);
+
+ mutex_lock(&common.common_lock);
+ for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+ v = &common.voice[i];
+
+ mutex_lock(&v->lock);
+ if (is_voc_state_active(v->voc_state)) {
+ result2 = voice_send_cvp_register_vol_cal_cmd(v);
+ if (result2 < 0) {
+ pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
+ __func__, v->session_id);
+
+ result = result2;
+ /* Still try to register other sessions */
+ }
+ }
+ mutex_unlock(&v->lock);
+ }
+
+ mutex_unlock(&common.common_lock);
+ return result;
+}
+
+int voc_deregister_vocproc_vol_table(void)
+{
+ int result = 0;
+ int success = 0;
+ int i;
+ struct voice_data *v = NULL;
+
+ pr_debug("%s\n", __func__);
+
+ mutex_lock(&common.common_lock);
+ for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+ v = &common.voice[i];
+
+ mutex_lock(&v->lock);
+ if (is_voc_state_active(v->voc_state)) {
+ result = voice_send_cvp_deregister_vol_cal_cmd(v);
+ if (result < 0) {
+ pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
+ __func__, v->session_id);
+
+ mutex_unlock(&v->lock);
+ mutex_unlock(&common.common_lock);
+ if (success) {
+ pr_err("%s: Try to re-register all deregistered sessions!\n",
+ __func__);
+
+ voc_register_vocproc_vol_table();
+ }
+ goto done;
+ } else {
+ success = 1;
+ }
+ }
+ mutex_unlock(&v->lock);
+ }
+ mutex_unlock(&common.common_lock);
+done:
+ return result;
+}
+
+int voc_map_rtac_block(struct rtac_cal_block_data *cal_block)
+{
+ int result = 0;
+ struct voice_data *v = NULL;
+
+ pr_debug("%s\n", __func__);
+
+ if (cal_block == NULL) {
+ pr_err("%s: cal_block is NULL!\n",
+ __func__);
+
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (cal_block->cal_data.paddr == 0) {
+ pr_debug("%s: No address to map!\n",
+ __func__);
+
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (cal_block->map_data.map_size == 0) {
+ pr_debug("%s: map size is 0!\n",
+ __func__);
+
+ result = -EINVAL;
+ goto done;
+ }
+
+ mutex_lock(&common.common_lock);
+ /* use first session */
+ v = &common.voice[0];
+ mutex_lock(&v->lock);
+
+ if (!is_rtac_memory_allocated()) {
+ result = voice_alloc_rtac_mem_map_table();
+ if (result < 0) {
+ pr_err("%s: RTAC alloc mem map table did not work! addr = 0x%x, size = %d\n",
+ __func__, cal_block->cal_data.paddr,
+ cal_block->map_data.map_size);
+
+ goto err;
+ }
+ }
+
+ result = voice_map_memory_physical_cmd(v,
+ &common.rtac_mem_map_table,
+ (dma_addr_t)cal_block->cal_data.paddr,
+ cal_block->map_data.map_size,
+ VOC_RTAC_MEM_MAP_TOKEN);
+ if (result < 0) {
+ pr_err("%s: RTAC mmap did not work! addr = 0x%x, size = %d\n",
+ __func__, cal_block->cal_data.paddr,
+ cal_block->map_data.map_size);
+
+ free_rtac_map_table();
+ goto err;
+ }
+
+ cal_block->map_data.map_handle = common.rtac_mem_handle;
+err:
+ mutex_unlock(&v->lock);
+ mutex_unlock(&common.common_lock);
+done:
+ return result;
+}
+
+int voc_unmap_rtac_block(uint32_t *mem_map_handle)
+{
+ int result = 0;
+ struct voice_data *v = NULL;
+
+ pr_debug("%s\n", __func__);
+
+ if (mem_map_handle == NULL) {
+ pr_debug("%s: Map handle is NULL, nothing to unmap\n",
+ __func__);
+
+ goto done;
+ }
+
+ if (*mem_map_handle == 0) {
+ pr_debug("%s: Map handle is 0, nothing to unmap\n",
+ __func__);
+
+ goto done;
+ }
+
+ mutex_lock(&common.common_lock);
+ /* use first session */
+ v = &common.voice[0];
+ mutex_lock(&v->lock);
+
+ result = voice_send_mvm_unmap_memory_physical_cmd(
+ v, *mem_map_handle);
+ if (result) {
+ pr_err("%s: voice_send_mvm_unmap_memory_physical_cmd Failed for session 0x%x!\n",
+ __func__, v->session_id);
+ } else {
+ *mem_map_handle = 0;
+ common.rtac_mem_handle = 0;
+ free_rtac_map_table();
+ }
+ mutex_unlock(&v->lock);
+ mutex_unlock(&common.common_lock);
+done:
+ return result;
+}
+
+int voc_unmap_cal_blocks(void)
+{
+ int result = 0;
+ int result2 = 0;
+ int i;
+ struct voice_data *v = NULL;
+
+ pr_debug("%s\n", __func__);
+
+ mutex_lock(&common.common_lock);
+
+ if (common.cal_mem_handle == 0)
+ goto done;
+
+ for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+ v = &common.voice[i];
+
+ mutex_lock(&v->lock);
+ if (is_voc_state_active(v->voc_state)) {
+ result2 = voice_pause_voice_call(v);
+ if (result2 < 0) {
+ pr_err("%s: voice_pause_voice_call failed for session 0x%x, err %d!\n",
+ __func__, v->session_id, result2);
+
+ result = result2;
+ }
+
+ voice_send_cvp_deregister_vol_cal_cmd(v);
+ voice_send_cvp_deregister_cal_cmd(v);
+ voice_send_cvp_deregister_dev_cfg_cmd(v);
+ voice_send_cvs_deregister_cal_cmd(v);
+
+ result2 = voice_send_start_voice_cmd(v);
+ if (result2) {
+ pr_err("%s: voice_send_start_voice_cmd failed for session 0x%x, err %d!\n",
+ __func__, v->session_id, result2);
+
+ result = result2;
+ }
+ }
+
+ if ((common.cal_mem_handle != 0) &&
+ (!is_other_session_active(v->session_id))) {
+
+ result2 = voice_send_mvm_unmap_memory_physical_cmd(
+ v, common.cal_mem_handle);
+ if (result2) {
+ pr_err("%s: voice_send_mvm_unmap_memory_physical_cmd failed for session 0x%x, err %d!\n",
+ __func__, v->session_id, result2);
+
+ result = result2;
+ } else {
+ common.cal_mem_handle = 0;
+ free_cal_map_table();
+ }
+ }
+ mutex_unlock(&v->lock);
+ }
+done:
+ mutex_unlock(&common.common_lock);
+ return result;
+}
+
static int voice_setup_vocproc(struct voice_data *v)
{
struct cvp_create_full_ctl_session_cmd cvp_session_cmd;
@@ -3112,7 +3421,6 @@
voice_send_cvp_deregister_vol_cal_cmd(v);
voice_send_cvp_deregister_cal_cmd(v);
voice_send_cvp_deregister_dev_cfg_cmd(v);
-
voice_send_cvs_deregister_cal_cmd(v);
/* destrop cvp session */
@@ -3324,7 +3632,8 @@
return -EINVAL;
}
-static int voice_send_stream_mute_cmd(struct voice_data *v)
+static int voice_send_stream_mute_cmd(struct voice_data *v, uint16_t direction,
+ uint16_t mute_flag, uint32_t ramp_duration)
{
struct cvs_set_mute_cmd cvs_mute_cmd;
int ret = 0;
@@ -3352,10 +3661,9 @@
cvs_mute_cmd.hdr.dest_port = voice_get_cvs_handle(v);
cvs_mute_cmd.hdr.token = 0;
cvs_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
- cvs_mute_cmd.cvs_set_mute.direction = VSS_IVOLUME_DIRECTION_TX;
- cvs_mute_cmd.cvs_set_mute.mute_flag = v->stream_tx.stream_mute;
- cvs_mute_cmd.cvs_set_mute.ramp_duration_ms =
- v->stream_tx.stream_mute_ramp_duration_ms;
+ cvs_mute_cmd.cvs_set_mute.direction = direction;
+ cvs_mute_cmd.cvs_set_mute.mute_flag = mute_flag;
+ cvs_mute_cmd.cvs_set_mute.ramp_duration_ms = ramp_duration;
v->cvs_state = CMD_STATUS_FAIL;
ret = apr_send_pkt(common.apr_q6_cvs, (uint32_t *) &cvs_mute_cmd);
@@ -4011,6 +4319,13 @@
VSS_IVOLUME_DIRECTION_RX,
VSS_IVOLUME_MUTE_ON,
DEFAULT_MUTE_RAMP_DURATION);
+ /* Send unmute cmd as the TX stream
+ * might be muted previously
+ */
+ voice_send_stream_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ VSS_IVOLUME_MUTE_OFF,
+ DEFAULT_MUTE_RAMP_DURATION);
} else if (v->lch_mode == VOICE_LCH_STOP) {
pr_debug("%s: TX and RX mute OFF\n", __func__);
@@ -4025,7 +4340,10 @@
/* Reset lch mode when VOICE_LCH_STOP is recieved */
v->lch_mode = 0;
/* Apply cached mute setting */
- voice_send_stream_mute_cmd(v);
+ voice_send_stream_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ v->stream_tx.stream_mute,
+ v->stream_tx.stream_mute_ramp_duration_ms);
} else {
pr_debug("%s: Mute commands not sent for lch_mode=%d\n",
__func__, v->lch_mode);
@@ -4105,7 +4423,10 @@
ramp_duration;
if (is_voc_state_active(v->voc_state) &&
(v->lch_mode == 0))
- ret = voice_send_stream_mute_cmd(v);
+ ret = voice_send_stream_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ v->stream_tx.stream_mute,
+ v->stream_tx.stream_mute_ramp_duration_ms);
mutex_unlock(&v->lock);
} else {
pr_err("%s: invalid session_id 0x%x\n", __func__,
@@ -4591,7 +4912,10 @@
if (ret < 0)
pr_err("voice volume failed\n");
- ret = voice_send_stream_mute_cmd(v);
+ ret = voice_send_stream_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ v->stream_tx.stream_mute,
+ v->stream_tx.stream_mute_ramp_duration_ms);
if (ret < 0)
pr_err("voice mute failed\n");
@@ -4631,14 +4955,18 @@
}
void voc_config_vocoder(uint32_t media_type,
- uint32_t rate,
- uint32_t network_type,
- uint32_t dtx_mode)
+ uint32_t rate,
+ uint32_t network_type,
+ uint32_t dtx_mode,
+ uint32_t evrc_min_rate,
+ uint32_t evrc_max_rate)
{
common.mvs_info.media_type = media_type;
common.mvs_info.rate = rate;
common.mvs_info.network_type = network_type;
common.mvs_info.dtx_mode = dtx_mode;
+ common.mvs_info.evrc_min_rate = evrc_min_rate;
+ common.mvs_info.evrc_max_rate = evrc_max_rate;
}
static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
@@ -4671,6 +4999,8 @@
/* clean up memory handle */
c->cal_mem_handle = 0;
+ c->rtac_mem_handle = 0;
+ rtac_clear_mapping(VOICE_RTAC_CAL);
/* Sub-system restart is applicable to all sessions. */
for (i = 0; i < MAX_VOC_SESSIONS; i++) {
@@ -4729,6 +5059,7 @@
case VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE:
case VSS_IMEMORY_CMD_MAP_PHYSICAL:
case VSS_IMEMORY_CMD_UNMAP:
+ case VSS_IMVM_CMD_PAUSE_VOICE:
case VSS_IMVM_CMD_STANDBY_VOICE:
pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
v->mvm_state = CMD_STATUS_SUCCESS;
@@ -4764,6 +5095,18 @@
v->mvm_state = CMD_STATUS_SUCCESS;
wake_up(&v->mvm_wait);
}
+ } else if (data->payload_size &&
+ data->token == VOC_RTAC_MEM_MAP_TOKEN) {
+ ptr = data->payload;
+ if (ptr[0]) {
+ c->rtac_mem_handle = ptr[0];
+
+ pr_debug("%s: cal mem handle 0x%x\n",
+ __func__, c->rtac_mem_handle);
+
+ v->mvm_state = CMD_STATUS_SUCCESS;
+ wake_up(&v->mvm_wait);
+ }
} else {
pr_err("%s: Unknown mem map token %d\n",
__func__, data->token);
@@ -4921,8 +5264,10 @@
cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data;
if (cvs_voc_pkt != NULL && common.mvs_info.ul_cb != NULL) {
+ /* cvs_voc_pkt[0] contains tx timestamp */
common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3],
cvs_voc_pkt[2],
+ cvs_voc_pkt[0],
common.mvs_info.private_data);
} else
pr_err("%s: cvs_voc_pkt or ul_cb is NULL\n", __func__);
@@ -5172,6 +5517,8 @@
rc = msm_audio_ion_free(v->shmem_info.sh_buf.client,
v->shmem_info.sh_buf.handle);
+ v->shmem_info.sh_buf.client = NULL;
+ v->shmem_info.sh_buf.handle = NULL;
if (rc < 0) {
pr_err("%s: Error:%d freeing memory\n", __func__, rc);
@@ -5316,6 +5663,33 @@
return ret;
}
+static int voice_alloc_rtac_mem_map_table(void)
+{
+ int ret = 0;
+ int len;
+
+ ret = msm_audio_ion_alloc("voc_rtac_cal",
+ &(common.rtac_mem_map_table.client),
+ &(common.rtac_mem_map_table.handle),
+ sizeof(struct vss_imemory_table_t),
+ (ion_phys_addr_t *)&common.rtac_mem_map_table.phys,
+ (size_t *) &len,
+ &(common.rtac_mem_map_table.data));
+ if (ret < 0) {
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ common.rtac_mem_map_table.size = sizeof(struct vss_imemory_table_t);
+ pr_debug("%s: data 0x%x phys 0x%x\n", __func__,
+ (unsigned int) common.rtac_mem_map_table.data,
+ common.rtac_mem_map_table.phys);
+
+done:
+ return ret;
+}
+
static int voice_alloc_and_map_cal_mem(struct voice_data *v)
{
int ret = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 20f2857..39f0986 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -13,6 +13,7 @@
#define __QDSP6VOICE_H__
#include <mach/qdsp6v2/apr.h>
+#include <mach/qdsp6v2/rtac.h>
#include <linux/msm_ion.h>
#include <sound/voice_params.h>
@@ -186,6 +187,9 @@
#define VSS_IMVM_CMD_STOP_VOICE 0x00011192
/**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
+#define VSS_IMVM_CMD_PAUSE_VOICE 0x0001137D
+/* No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
+
#define VSS_ISTREAM_CMD_ATTACH_VOCPROC 0x000110F8
/**< Wait for APRV2_IBASIC_RSP_RESULT response. */
@@ -213,7 +217,8 @@
VOC_8_RATE, /* 1/8 rate */
VOC_4_RATE, /* 1/4 rate */
VOC_2_RATE, /* 1/2 rate */
- VOC_1_RATE /* Full rate */
+ VOC_1_RATE, /* Full rate */
+ VOC_8_RATE_NC /* Noncritical 1/8 rate */
};
struct vss_istream_cmd_set_tty_mode_t {
@@ -977,6 +982,8 @@
/*CDMA EVRC-B vocoder modem format */
#define VSS_MEDIA_ID_4GV_WB_MODEM 0x00010FC4
/*CDMA EVRC-WB vocoder modem format */
+#define VSS_MEDIA_ID_4GV_NW_MODEM 0x00010FC5
+/*CDMA EVRC-NW vocoder modem format */
#define VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2 0x000112BF
@@ -1207,6 +1214,7 @@
/* CB for up-link packets. */
typedef void (*ul_cb_fn)(uint8_t *voc_pkt,
uint32_t pkt_len,
+ uint32_t timestamp,
void *private_data);
/* CB for down-link packets. */
@@ -1226,6 +1234,8 @@
ul_cb_fn ul_cb;
dl_cb_fn dl_cb;
void *private_data;
+ uint32_t evrc_min_rate;
+ uint32_t evrc_max_rate;
};
struct dtmf_driver_info {
@@ -1328,6 +1338,10 @@
struct mem_map_table cal_mem_map_table;
uint32_t cal_mem_handle;
+
+ struct mem_map_table rtac_mem_map_table;
+ uint32_t rtac_mem_handle;
+
struct cal_mem cvp_cal;
struct cal_mem cvs_cal;
@@ -1357,7 +1371,9 @@
void voc_config_vocoder(uint32_t media_type,
uint32_t rate,
uint32_t network_type,
- uint32_t dtx_mode);
+ uint32_t dtx_mode,
+ uint32_t evrc_min_rate,
+ uint32_t evrc_max_rate);
enum {
DEV_RX = 0,
@@ -1437,6 +1453,10 @@
int voc_register_vocproc_vol_table(void);
int voc_deregister_vocproc_vol_table(void);
+int voc_unmap_cal_blocks(void);
+int voc_map_rtac_block(struct rtac_cal_block_data *cal_block);
+int voc_unmap_rtac_block(uint32_t *mem_map_handle);
+
uint32_t voc_get_session_id(char *name);
int voc_start_playback(uint32_t set, uint16_t port_id);
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index a4983d3..ee21112 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -20,6 +20,7 @@
#include <linux/sched.h>
#include <linux/msm_audio_acdb.h>
#include <linux/atomic.h>
+#include <linux/msm_audio_ion.h>
#include <mach/qdsp6v2/rtac.h>
#include <sound/q6asm-v2.h>
#include <sound/q6afe-v2.h>
@@ -53,10 +54,26 @@
#define RTAC_MAX_ACTIVE_DEVICES 4
#define RTAC_MAX_ACTIVE_VOICE_COMBOS 2
#define RTAC_MAX_ACTIVE_POPP 8
-#define RTAC_BUF_SIZE 4096
+#define RTAC_BUF_SIZE 8192
#define TIMEOUT_MS 1000
+struct rtac_cal_block_data rtac_cal[MAX_RTAC_BLOCKS] = {
+/* ADM_RTAC_CAL */
+ {{RTAC_BUF_SIZE, 0, 0, 0}, {0, 0, 0} },
+/* ASM_RTAC_CAL */
+ {{RTAC_BUF_SIZE, 0, 0, 0}, {0, 0, 0} },
+/* VOICE_RTAC_CAL */
+ {{RTAC_BUF_SIZE, 0, 0, 0}, {0, 0, 0} }
+};
+
+struct rtac_common_data {
+ atomic_t usage_count;
+ atomic_t apr_err_code;
+};
+
+static struct rtac_common_data rtac_common;
+
/* APR data */
struct rtac_apr_data {
void *apr_handle;
@@ -83,15 +100,11 @@
struct rtac_adm_data device[RTAC_MAX_ACTIVE_DEVICES];
};
static struct rtac_adm rtac_adm_data;
-static u32 rtac_adm_payload_size;
-static u32 rtac_adm_user_buf_size;
-static u8 *rtac_adm_buffer;
+static u32 *rtac_adm_buffer;
/* ASM APR */
-static u32 rtac_asm_payload_size;
-static u32 rtac_asm_user_buf_size;
-static u8 *rtac_asm_buffer;
+static u32 *rtac_asm_buffer;
/* Voice info & APR */
@@ -110,9 +123,7 @@
};
static struct rtac_voice rtac_voice_data;
-static u32 rtac_voice_payload_size;
-static u32 rtac_voice_user_buf_size;
-static u8 *rtac_voice_buffer;
+static u32 *rtac_voice_buffer;
static u32 voice_session_id[RTAC_MAX_ACTIVE_VOICE_COMBOS];
@@ -122,16 +133,227 @@
struct mutex rtac_voice_mutex;
struct mutex rtac_voice_apr_mutex;
+int rtac_clear_mapping(uint32_t cal_type)
+{
+ int result = 0;
+ pr_debug("%s\n", __func__);
+
+ if (cal_type >= MAX_RTAC_BLOCKS) {
+ pr_debug("%s: invalid cal type %d\n", __func__, cal_type);
+ result = -EINVAL;
+ goto done;
+ }
+
+ rtac_cal[cal_type].map_data.map_handle = 0;
+done:
+ return result;
+}
+
+int rtac_allocate_cal_buffer(uint32_t cal_type)
+{
+ int result = 0;
+ int len;
+ pr_debug("%s\n", __func__);
+
+ if (cal_type >= MAX_RTAC_BLOCKS) {
+ pr_err("%s: cal_type %d is invalid!\n",
+ __func__, cal_type);
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (rtac_cal[cal_type].cal_data.paddr != 0) {
+ pr_err("%s: memory already allocated! cal_type %d, paddr 0x%x\n",
+ __func__, cal_type, rtac_cal[cal_type].cal_data.paddr);
+ result = -EPERM;
+ goto done;
+ }
+
+ result = msm_audio_ion_alloc("rtac_client",
+ &rtac_cal[cal_type].map_data.ion_client,
+ &rtac_cal[cal_type].map_data.ion_handle,
+ rtac_cal[cal_type].map_data.map_size,
+ (ion_phys_addr_t *)&rtac_cal[cal_type].cal_data.paddr,
+ (size_t *)&len,
+ (void **)&rtac_cal[cal_type].cal_data.kvaddr);
+ if (result < 0) {
+ pr_err("%s: ION create client for RTAC failed\n",
+ __func__);
+ goto done;
+ }
+
+ pr_debug("%s: cal_type %d, paddr 0x%x, kvaddr 0x%x, map_size 0x%x\n",
+ __func__, cal_type,
+ rtac_cal[cal_type].cal_data.paddr,
+ rtac_cal[cal_type].cal_data.kvaddr,
+ rtac_cal[cal_type].map_data.map_size);
+done:
+ return result;
+}
+
+int rtac_free_cal_buffer(uint32_t cal_type)
+{
+ int result = 0;
+ pr_debug("%s\n", __func__);
+
+ if (cal_type >= MAX_RTAC_BLOCKS) {
+ pr_err("%s: cal_type %d is invalid!\n",
+ __func__, cal_type);
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (rtac_cal[cal_type].map_data.ion_client == NULL) {
+ pr_debug("%s: cal_type %d not allocated!\n",
+ __func__, cal_type);
+ goto done;
+ }
+
+ result = msm_audio_ion_free(rtac_cal[cal_type].map_data.ion_client,
+ rtac_cal[cal_type].map_data.ion_handle);
+ if (result < 0) {
+ pr_err("%s: ION free for RTAC failed! cal_type %d, paddr 0x%x\n",
+ __func__, cal_type, rtac_cal[cal_type].cal_data.paddr);
+ goto done;
+ }
+
+ rtac_cal[cal_type].map_data.map_handle = 0;
+ rtac_cal[cal_type].map_data.ion_client = NULL;
+ rtac_cal[cal_type].map_data.ion_handle = NULL;
+ rtac_cal[cal_type].cal_data.size = 0;
+ rtac_cal[cal_type].cal_data.kvaddr = 0;
+ rtac_cal[cal_type].cal_data.paddr = 0;
+done:
+ return result;
+}
+
+int rtac_map_cal_buffer(uint32_t cal_type)
+{
+ int result = 0;
+ pr_debug("%s\n", __func__);
+
+ if (cal_type >= MAX_RTAC_BLOCKS) {
+ pr_err("%s: cal_type %d is invalid!\n",
+ __func__, cal_type);
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (rtac_cal[cal_type].map_data.map_handle != 0) {
+ pr_err("%s: already mapped cal_type %d\n",
+ __func__, cal_type);
+ result = -EPERM;
+ goto done;
+ }
+
+ if (rtac_cal[cal_type].cal_data.paddr == 0) {
+ pr_err("%s: physical address is NULL cal_type %d\n",
+ __func__, cal_type);
+ result = -EPERM;
+ goto done;
+ }
+
+ switch (cal_type) {
+ case ADM_RTAC_CAL:
+ result = adm_map_rtac_block(&rtac_cal[cal_type]);
+ break;
+ case ASM_RTAC_CAL:
+ result = q6asm_map_rtac_block(&rtac_cal[cal_type]);
+ break;
+ case VOICE_RTAC_CAL:
+ result = voc_map_rtac_block(&rtac_cal[cal_type]);
+ break;
+ }
+ if (result < 0) {
+ pr_err("%s: map RTAC failed! cal_type %d\n",
+ __func__, cal_type);
+ goto done;
+ }
+done:
+ return result;
+}
+
+int rtac_unmap_cal_buffer(uint32_t cal_type)
+{
+ int result = 0;
+ pr_debug("%s\n", __func__);
+
+ if (cal_type >= MAX_RTAC_BLOCKS) {
+ pr_err("%s: cal_type %d is invalid!\n",
+ __func__, cal_type);
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (rtac_cal[cal_type].map_data.map_handle == 0) {
+ pr_debug("%s: nothing to unmap cal_type %d\n",
+ __func__, cal_type);
+ goto done;
+ }
+
+ switch (cal_type) {
+ case ADM_RTAC_CAL:
+ result = adm_unmap_rtac_block(
+ &rtac_cal[cal_type].map_data.map_handle);
+ break;
+ case ASM_RTAC_CAL:
+ result = q6asm_unmap_rtac_block(
+ &rtac_cal[cal_type].map_data.map_handle);
+ break;
+ case VOICE_RTAC_CAL:
+ result = voc_unmap_rtac_block(
+ &rtac_cal[cal_type].map_data.map_handle);
+ break;
+ }
+ if (result < 0) {
+ pr_err("%s: unmap RTAC failed! cal_type %d\n",
+ __func__, cal_type);
+ goto done;
+ }
+done:
+ return result;
+}
+
static int rtac_open(struct inode *inode, struct file *f)
{
+ int result = 0;
pr_debug("%s\n", __func__);
- return 0;
+
+ atomic_inc(&rtac_common.usage_count);
+ return result;
}
static int rtac_release(struct inode *inode, struct file *f)
{
+ int result = 0;
+ int result2 = 0;
+ int i;
pr_debug("%s\n", __func__);
- return 0;
+
+ atomic_dec(&rtac_common.usage_count);
+ pr_debug("%s: ref count %d!\n", __func__,
+ atomic_read(&rtac_common.usage_count));
+
+ if (atomic_read(&rtac_common.usage_count) > 0)
+ goto done;
+
+ for (i = 0; i < MAX_RTAC_BLOCKS; i++) {
+ result2 = rtac_unmap_cal_buffer(i);
+ if (result2 < 0) {
+ pr_err("%s: unmap buffer failed! error %d!\n",
+ __func__, result2);
+ result = result2;
+ }
+
+ result2 = rtac_free_cal_buffer(i);
+ if (result2 < 0) {
+ pr_err("%s: free buffer failed! error %d!\n",
+ __func__, result2);
+ result = result2;
+ }
+ }
+done:
+ return result;
}
/* ADM Info */
@@ -412,52 +634,56 @@
if (atomic_read(&rtac_adm_apr_data.cmd_state) != 1)
return false;
- /* Offset data for in-band payload */
- rtac_copy_adm_payload_to_user(payload, payload_size);
+ pr_debug("%s\n", __func__);
+ if (payload_size == sizeof(uint32_t))
+ atomic_set(&rtac_common.apr_err_code, payload[0]);
+ else if (payload_size == (2*sizeof(uint32_t)))
+ atomic_set(&rtac_common.apr_err_code, payload[1]);
+
atomic_set(&rtac_adm_apr_data.cmd_state, 0);
wake_up(&rtac_adm_apr_data.cmd_wait);
return true;
}
-void rtac_copy_adm_payload_to_user(void *payload, u32 payload_size)
-{
- pr_debug("%s\n", __func__);
- rtac_adm_payload_size = payload_size;
-
- memcpy(rtac_adm_buffer, &payload_size, sizeof(u32));
- if (payload_size != 0) {
- if (payload_size > rtac_adm_user_buf_size) {
- pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
- __func__, rtac_adm_user_buf_size, payload_size);
- rtac_adm_payload_size = 0;
- goto done;
- }
- memcpy(rtac_adm_buffer + sizeof(u32), payload, payload_size);
- }
-done:
- return;
-}
-
u32 send_adm_apr(void *buf, u32 opcode)
{
s32 result;
- u32 count = 0;
+ u32 user_buf_size = 0;
u32 bytes_returned = 0;
u32 port_index = 0;
u32 copp_id;
u32 payload_size;
+ u32 data_size = 0;
struct apr_hdr adm_params;
pr_debug("%s\n", __func__);
- if (copy_from_user(&count, (void *)buf, sizeof(count))) {
- pr_err("%s: Copy to user failed! buf = 0x%x\n",
- __func__, (unsigned int)buf);
- result = -EFAULT;
- goto done;
+ if (rtac_cal[ADM_RTAC_CAL].map_data.ion_handle == NULL) {
+ result = rtac_allocate_cal_buffer(ADM_RTAC_CAL);
+ if (result < 0) {
+ pr_err("%s: allocate buffer failed!",
+ __func__);
+ goto done;
+ }
}
- if (count <= 0) {
- pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+ if (rtac_cal[ADM_RTAC_CAL].map_data.map_handle == 0) {
+ result = rtac_map_cal_buffer(ADM_RTAC_CAL);
+ if (result < 0) {
+ pr_err("%s: map buffer failed!",
+ __func__);
+ goto done;
+ }
+ }
+
+ if (copy_from_user(&user_buf_size, (void *)buf,
+ sizeof(user_buf_size))) {
+ pr_err("%s: Copy from user failed! buf = 0x%x\n",
+ __func__, (unsigned int)buf);
+ goto done;
+ }
+ if (user_buf_size <= 0) {
+ pr_err("%s: Invalid buffer size = %d\n",
+ __func__, user_buf_size);
goto done;
}
@@ -467,13 +693,6 @@
goto done;
}
-
- if (payload_size > MAX_PAYLOAD_SIZE) {
- pr_err("%s: Invalid payload size = %d\n",
- __func__, payload_size);
- goto done;
- }
-
if (copy_from_user(&copp_id, buf + 2 * sizeof(u32), sizeof(u32))) {
pr_err("%s: Could not copy port id from user buffer\n",
__func__);
@@ -496,15 +715,42 @@
goto err;
}
- /* Set globals for copy of returned payload */
- rtac_adm_user_buf_size = count;
+ if (opcode == ADM_CMD_SET_PP_PARAMS_V5) {
+ /* set payload size to in-band payload */
+ /* set data size to actual out of band payload size */
+ data_size = payload_size - 4 * sizeof(u32);
+ if (data_size > rtac_cal[ADM_RTAC_CAL].map_data.map_size) {
+ pr_err("%s: Invalid data size = %d\n",
+ __func__, data_size);
+ goto done;
+ }
+ payload_size = 4 * sizeof(u32);
- /* Copy buffer to in-band payload */
- if (copy_from_user(rtac_adm_buffer + sizeof(adm_params),
- buf + 3 * sizeof(u32), payload_size)) {
- pr_err("%s: Could not copy payload from user buffer\n",
- __func__);
- goto err;
+ /* Copy buffer to out-of-band payload */
+ if (copy_from_user((void *)
+ rtac_cal[ADM_RTAC_CAL].cal_data.kvaddr,
+ buf + 7 * sizeof(u32), data_size)) {
+ pr_err("%s: Could not copy payload from user buffer\n",
+ __func__);
+ goto err;
+ }
+ /* set payload size in packet */
+ rtac_adm_buffer[8] = data_size;
+ } else {
+ if (payload_size > MAX_PAYLOAD_SIZE) {
+ pr_err("%s: Invalid payload size = %d\n",
+ __func__, payload_size);
+ goto done;
+ }
+
+ /* Copy buffer to in-band payload */
+ if (copy_from_user(rtac_adm_buffer +
+ sizeof(adm_params)/sizeof(u32),
+ buf + 3 * sizeof(u32), payload_size)) {
+ pr_err("%s: Could not copy payload from user buffer\n",
+ __func__);
+ goto err;
+ }
}
/* Pack header */
@@ -521,14 +767,20 @@
adm_params.token = copp_id;
adm_params.opcode = opcode;
+ /* fill for out-of-band */
+ rtac_adm_buffer[5] = rtac_cal[ADM_RTAC_CAL].cal_data.paddr;
+ rtac_adm_buffer[6] = 0;
+ rtac_adm_buffer[7] = rtac_cal[ADM_RTAC_CAL].map_data.map_handle;
+
memcpy(rtac_adm_buffer, &adm_params, sizeof(adm_params));
atomic_set(&rtac_adm_apr_data.cmd_state, 1);
- pr_debug("%s: Sending RTAC command size = %d\n",
- __func__, adm_params.pkt_size);
+ pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%x\n",
+ __func__, opcode,
+ rtac_cal[ADM_RTAC_CAL].cal_data.paddr);
result = apr_send_pkt(rtac_adm_apr_data.apr_handle,
- (uint32_t *)rtac_adm_buffer);
+ (uint32_t *)rtac_adm_buffer);
if (result < 0) {
pr_err("%s: Set params failed port = %d, copp = %d\n",
__func__, port_index, copp_id);
@@ -544,21 +796,34 @@
__func__, port_index, copp_id);
goto done;
}
-
- if (rtac_adm_payload_size != 0) {
- if (copy_to_user(buf, rtac_adm_buffer,
- rtac_adm_payload_size + sizeof(u32))) {
- pr_err("%s: Could not copy buffer to user,size = %d\n",
- __func__, payload_size);
- goto done;
- }
+ if (atomic_read(&rtac_common.apr_err_code)) {
+ pr_err("%s: DSP returned error code = %d, opcode = 0x%x\n",
+ __func__, atomic_read(&rtac_common.apr_err_code),
+ opcode);
+ goto done;
}
- /* Return data written for SET & data read for GET */
- if (opcode == ADM_CMD_GET_PP_PARAMS_V5)
- bytes_returned = rtac_adm_payload_size;
- else
- bytes_returned = payload_size;
+ if (opcode == ADM_CMD_GET_PP_PARAMS_V5) {
+ bytes_returned = ((u32 *)rtac_cal[ADM_RTAC_CAL].cal_data.
+ kvaddr)[2] + 3 * sizeof(u32);
+
+ if (bytes_returned > user_buf_size) {
+ pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
+ __func__, user_buf_size, bytes_returned);
+ goto done;
+ }
+
+ if (copy_to_user(buf, (void *)
+ rtac_cal[ADM_RTAC_CAL].cal_data.kvaddr,
+ bytes_returned)) {
+ pr_err("%s: Could not copy buffer to user,size = %d\n",
+ __func__, bytes_returned);
+ goto done;
+ }
+ } else {
+ bytes_returned = data_size;
+ }
+
done:
return bytes_returned;
err:
@@ -584,51 +849,54 @@
return false;
pr_debug("%s\n", __func__);
- /* Offset data for in-band payload */
- rtac_copy_asm_payload_to_user(payload, payload_size);
+ if (payload_size == sizeof(uint32_t))
+ atomic_set(&rtac_common.apr_err_code, payload[0]);
+ else if (payload_size == (2*sizeof(uint32_t)))
+ atomic_set(&rtac_common.apr_err_code, payload[1]);
+
atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 0);
wake_up(&rtac_asm_apr_data[session_id].cmd_wait);
return true;
}
-void rtac_copy_asm_payload_to_user(void *payload, u32 payload_size)
-{
- pr_debug("%s\n", __func__);
- rtac_asm_payload_size = payload_size;
-
- memcpy(rtac_asm_buffer, &payload_size, sizeof(u32));
- if (payload_size) {
- if (payload_size > rtac_asm_user_buf_size) {
- pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
- __func__, rtac_asm_user_buf_size, payload_size);
- rtac_asm_payload_size = 0;
- goto done;
- }
- memcpy(rtac_asm_buffer + sizeof(u32), payload, payload_size);
- }
-done:
- return;
-}
-
u32 send_rtac_asm_apr(void *buf, u32 opcode)
{
s32 result;
- u32 count = 0;
+ u32 user_buf_size = 0;
u32 bytes_returned = 0;
u32 session_id = 0;
u32 payload_size;
+ u32 data_size = 0;
struct apr_hdr asm_params;
pr_debug("%s\n", __func__);
- if (copy_from_user(&count, (void *)buf, sizeof(count))) {
- pr_err("%s: Copy to user failed! buf = 0x%x\n",
- __func__, (unsigned int)buf);
- result = -EFAULT;
- goto done;
+ if (rtac_cal[ASM_RTAC_CAL].map_data.ion_handle == NULL) {
+ result = rtac_allocate_cal_buffer(ASM_RTAC_CAL);
+ if (result < 0) {
+ pr_err("%s: allocate buffer failed!",
+ __func__);
+ goto done;
+ }
}
- if (count <= 0) {
- pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+ if (rtac_cal[ASM_RTAC_CAL].map_data.map_handle == 0) {
+ result = rtac_map_cal_buffer(ASM_RTAC_CAL);
+ if (result < 0) {
+ pr_err("%s: map buffer failed!",
+ __func__);
+ goto done;
+ }
+ }
+
+ if (copy_from_user(&user_buf_size, (void *)buf,
+ sizeof(user_buf_size))) {
+ pr_err("%s: Copy from user failed! buf = 0x%x\n",
+ __func__, (unsigned int)buf);
+ goto done;
+ }
+ if (user_buf_size <= 0) {
+ pr_err("%s: Invalid buffer size = %d\n",
+ __func__, user_buf_size);
goto done;
}
@@ -638,40 +906,59 @@
goto done;
}
- if (payload_size > MAX_PAYLOAD_SIZE) {
- pr_err("%s: Invalid payload size = %d\n",
- __func__, payload_size);
- goto done;
- }
-
if (copy_from_user(&session_id, buf + 2 * sizeof(u32), sizeof(u32))) {
pr_err("%s: Could not copy session id from user buffer\n",
__func__);
goto done;
}
-
- if (session_id > (SESSION_MAX + 1)) {
+ if (session_id >= (SESSION_MAX + 1)) {
pr_err("%s: Invalid Session = %d\n", __func__, session_id);
goto done;
}
mutex_lock(&rtac_asm_apr_mutex);
- if (session_id < SESSION_MAX+1) {
- if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
- pr_err("%s: APR not initialized\n", __func__);
- goto err;
- }
+ if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
+ pr_err("%s: APR not initialized\n", __func__);
+ goto err;
}
- /* Set globals for copy of returned payload */
- rtac_asm_user_buf_size = count;
+ if (opcode == ASM_STREAM_CMD_SET_PP_PARAMS_V2) {
+ /* set payload size to in-band payload */
+ /* set data size to actual out of band payload size */
+ data_size = payload_size - 4 * sizeof(u32);
+ if (data_size > rtac_cal[ASM_RTAC_CAL].map_data.map_size) {
+ pr_err("%s: Invalid data size = %d\n",
+ __func__, data_size);
+ goto done;
+ }
+ payload_size = 4 * sizeof(u32);
- /* Copy buffer to in-band payload */
- if (copy_from_user(rtac_asm_buffer + sizeof(asm_params),
- buf + 3 * sizeof(u32), payload_size)) {
- pr_err("%s: Could not copy payload from user buffer\n",
- __func__);
- goto err;
+ /* Copy buffer to out-of-band payload */
+ if (copy_from_user((void *)
+ rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr,
+ buf + 7 * sizeof(u32), data_size)) {
+ pr_err("%s: Could not copy payload from user buffer\n",
+ __func__);
+ goto err;
+ }
+ /* set payload size in packet */
+ rtac_asm_buffer[8] = data_size;
+
+ } else {
+ if (payload_size > MAX_PAYLOAD_SIZE) {
+ pr_err("%s: Invalid payload size = %d\n",
+ __func__, payload_size);
+ goto done;
+ }
+
+ /* Copy buffer to in-band payload */
+ if (copy_from_user(rtac_asm_buffer +
+ sizeof(asm_params)/sizeof(u32),
+ buf + 3 * sizeof(u32), payload_size)) {
+ pr_err("%s: Could not copy payload from user buffer\n",
+ __func__);
+ goto err;
+ }
}
/* Pack header */
@@ -688,12 +975,17 @@
asm_params.token = session_id;
asm_params.opcode = opcode;
- memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params));
- if (session_id < SESSION_MAX+1)
- atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);
+ /* fill for out-of-band */
+ rtac_asm_buffer[5] = rtac_cal[ASM_RTAC_CAL].cal_data.paddr;
+ rtac_asm_buffer[6] = 0;
+ rtac_asm_buffer[7] = rtac_cal[ASM_RTAC_CAL].map_data.map_handle;
- pr_debug("%s: Sending RTAC command size = %d, session_id=%d\n",
- __func__, asm_params.pkt_size, session_id);
+ memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params));
+ atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);
+
+ pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%x\n",
+ __func__, opcode,
+ rtac_cal[ASM_RTAC_CAL].cal_data.paddr);
result = apr_send_pkt(rtac_asm_apr_data[session_id].apr_handle,
(uint32_t *)rtac_asm_buffer);
@@ -713,21 +1005,33 @@
__func__, session_id);
goto done;
}
-
- if (rtac_asm_payload_size != 0) {
- if (copy_to_user(buf, rtac_asm_buffer,
- rtac_asm_payload_size + sizeof(u32))) {
- pr_err("%s: Could not copy buffer to user,size = %d\n",
- __func__, payload_size);
- goto done;
- }
+ if (atomic_read(&rtac_common.apr_err_code)) {
+ pr_err("%s: DSP returned error code = %d, opcode = 0x%x\n",
+ __func__, atomic_read(&rtac_common.apr_err_code),
+ opcode);
+ goto done;
}
- /* Return data written for SET & data read for GET */
- if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS_V2)
- bytes_returned = rtac_asm_payload_size;
- else
- bytes_returned = payload_size;
+ if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS_V2) {
+ bytes_returned = ((u32 *)rtac_cal[ASM_RTAC_CAL].cal_data.
+ kvaddr)[2] + 3 * sizeof(u32);
+
+ if (bytes_returned > user_buf_size) {
+ pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
+ __func__, user_buf_size, bytes_returned);
+ goto done;
+ }
+
+ if (copy_to_user(buf, (void *)
+ rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr,
+ bytes_returned)) {
+ pr_err("%s: Could not copy buffer to user,size = %d\n",
+ __func__, bytes_returned);
+ goto done;
+ }
+ } else {
+ bytes_returned = data_size;
+ }
done:
return bytes_returned;
err:
@@ -753,51 +1057,54 @@
return false;
pr_debug("%s\n", __func__);
- /* Offset data for in-band payload */
- rtac_copy_voice_payload_to_user(payload, payload_size);
+ if (payload_size == sizeof(uint32_t))
+ atomic_set(&rtac_common.apr_err_code, payload[0]);
+ else if (payload_size == (2*sizeof(uint32_t)))
+ atomic_set(&rtac_common.apr_err_code, payload[1]);
+
atomic_set(&rtac_voice_apr_data[mode].cmd_state, 0);
wake_up(&rtac_voice_apr_data[mode].cmd_wait);
return true;
}
-void rtac_copy_voice_payload_to_user(void *payload, u32 payload_size)
-{
- pr_debug("%s\n", __func__);
- rtac_voice_payload_size = payload_size;
-
- memcpy(rtac_voice_buffer, &payload_size, sizeof(u32));
- if (payload_size) {
- if (payload_size > rtac_voice_user_buf_size) {
- pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
- __func__, rtac_voice_user_buf_size, payload_size);
- rtac_voice_payload_size = 0;
- goto done;
- }
- memcpy(rtac_voice_buffer + sizeof(u32), payload, payload_size);
- }
-done:
- return;
-}
-
u32 send_voice_apr(u32 mode, void *buf, u32 opcode)
{
s32 result;
- u32 count = 0;
+ u32 user_buf_size = 0;
u32 bytes_returned = 0;
u32 payload_size;
u32 dest_port;
+ u32 data_size = 0;
struct apr_hdr voice_params;
pr_debug("%s\n", __func__);
- if (copy_from_user(&count, (void *)buf, sizeof(count))) {
- pr_err("%s: Copy to user failed! buf = 0x%x\n",
- __func__, (unsigned int)buf);
- result = -EFAULT;
- goto done;
+ if (rtac_cal[VOICE_RTAC_CAL].map_data.ion_handle == NULL) {
+ result = rtac_allocate_cal_buffer(VOICE_RTAC_CAL);
+ if (result < 0) {
+ pr_err("%s: allocate buffer failed!",
+ __func__);
+ goto done;
+ }
}
- if (count <= 0) {
- pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+ if (rtac_cal[VOICE_RTAC_CAL].map_data.map_handle == 0) {
+ result = rtac_map_cal_buffer(VOICE_RTAC_CAL);
+ if (result < 0) {
+ pr_err("%s: map buffer failed!",
+ __func__);
+ goto done;
+ }
+ }
+
+ if (copy_from_user(&user_buf_size, (void *)buf,
+ sizeof(user_buf_size))) {
+ pr_err("%s: Copy from user failed! buf = 0x%x\n",
+ __func__, (unsigned int)buf);
+ goto done;
+ }
+ if (user_buf_size <= 0) {
+ pr_err("%s: Invalid buffer size = %d\n",
+ __func__, user_buf_size);
goto done;
}
@@ -807,12 +1114,6 @@
goto done;
}
- if (payload_size > MAX_PAYLOAD_SIZE) {
- pr_err("%s: Invalid payload size = %d\n",
- __func__, payload_size);
- goto done;
- }
-
if (copy_from_user(&dest_port, buf + 2 * sizeof(u32), sizeof(u32))) {
pr_err("%s: Could not copy port id from user buffer\n",
__func__);
@@ -831,15 +1132,42 @@
goto err;
}
- /* Set globals for copy of returned payload */
- rtac_voice_user_buf_size = count;
+ if (opcode == VOICE_CMD_SET_PARAM) {
+ /* set payload size to in-band payload */
+ /* set data size to actual out of band payload size */
+ data_size = payload_size - 4 * sizeof(u32);
+ if (data_size > rtac_cal[VOICE_RTAC_CAL].map_data.map_size) {
+ pr_err("%s: Invalid data size = %d\n",
+ __func__, data_size);
+ goto done;
+ }
+ payload_size = 4 * sizeof(u32);
- /* Copy buffer to in-band payload */
- if (copy_from_user(rtac_voice_buffer + sizeof(voice_params),
- buf + 3 * sizeof(u32), payload_size)) {
- pr_err("%s: Could not copy payload from user buffer\n",
- __func__);
- goto err;
+ /* Copy buffer to out-of-band payload */
+ if (copy_from_user((void *)
+ rtac_cal[VOICE_RTAC_CAL].cal_data.kvaddr,
+ buf + 7 * sizeof(u32), data_size)) {
+ pr_err("%s: Could not copy payload from user buffer\n",
+ __func__);
+ goto err;
+ }
+ /* set payload size in packet */
+ rtac_voice_buffer[8] = data_size;
+ } else {
+ if (payload_size > MAX_PAYLOAD_SIZE) {
+ pr_err("%s: Invalid payload size = %d\n",
+ __func__, payload_size);
+ goto done;
+ }
+
+ /* Copy buffer to in-band payload */
+ if (copy_from_user(rtac_voice_buffer +
+ sizeof(voice_params)/sizeof(u32),
+ buf + 3 * sizeof(u32), payload_size)) {
+ pr_err("%s: Could not copy payload from user buffer\n",
+ __func__);
+ goto err;
+ }
}
/* Pack header */
@@ -856,11 +1184,17 @@
voice_params.token = 0;
voice_params.opcode = opcode;
+ /* fill for out-of-band */
+ rtac_voice_buffer[5] = rtac_cal[VOICE_RTAC_CAL].map_data.map_handle;
+ rtac_voice_buffer[6] = rtac_cal[VOICE_RTAC_CAL].cal_data.paddr;
+ rtac_voice_buffer[7] = 0;
+
memcpy(rtac_voice_buffer, &voice_params, sizeof(voice_params));
atomic_set(&rtac_voice_apr_data[mode].cmd_state, 1);
- pr_debug("%s: Sending RTAC command size = %d, opcode = %x\n",
- __func__, voice_params.pkt_size, opcode);
+ pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%x\n",
+ __func__, opcode,
+ rtac_cal[VOICE_RTAC_CAL].cal_data.paddr);
result = apr_send_pkt(rtac_voice_apr_data[mode].apr_handle,
(uint32_t *)rtac_voice_buffer);
@@ -879,21 +1213,33 @@
__func__, opcode);
goto done;
}
-
- if (rtac_voice_payload_size != 0) {
- if (copy_to_user(buf, rtac_voice_buffer,
- rtac_voice_payload_size + sizeof(u32))) {
- pr_err("%s: Could not copy buffer to user, size = %d\n",
- __func__, payload_size);
- goto done;
- }
+ if (atomic_read(&rtac_common.apr_err_code)) {
+ pr_err("%s: DSP returned error code = %d, opcode = 0x%x\n",
+ __func__, atomic_read(&rtac_common.apr_err_code),
+ opcode);
+ goto done;
}
- /* Return data written for SET & data read for GET */
- if (opcode == VOICE_CMD_GET_PARAM)
- bytes_returned = rtac_voice_payload_size;
- else
- bytes_returned = payload_size;
+ if (opcode == VOICE_CMD_GET_PARAM) {
+ bytes_returned = ((u32 *)rtac_cal[VOICE_RTAC_CAL].cal_data.
+ kvaddr)[2] + 3 * sizeof(u32);
+
+ if (bytes_returned > user_buf_size) {
+ pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
+ __func__, user_buf_size, bytes_returned);
+ goto done;
+ }
+
+ if (copy_to_user(buf, (void *)
+ rtac_cal[VOICE_RTAC_CAL].cal_data.kvaddr,
+ bytes_returned)) {
+ pr_err("%s: Could not copy buffer to user, size = %d\n",
+ __func__, bytes_returned);
+ goto done;
+ }
+ } else {
+ bytes_returned = data_size;
+ }
done:
return bytes_returned;
err:
@@ -987,6 +1333,10 @@
int i = 0;
pr_debug("%s\n", __func__);
+ /* Driver */
+ atomic_set(&rtac_common.usage_count, 0);
+ atomic_set(&rtac_common.apr_err_code, 0);
+
/* ADM */
memset(&rtac_adm_data, 0, sizeof(rtac_adm_data));
rtac_adm_apr_data.apr_handle = NULL;
@@ -995,10 +1345,11 @@
mutex_init(&rtac_adm_mutex);
mutex_init(&rtac_adm_apr_mutex);
- rtac_adm_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+ rtac_adm_buffer = kzalloc(
+ rtac_cal[ADM_RTAC_CAL].map_data.map_size, GFP_KERNEL);
if (rtac_adm_buffer == NULL) {
pr_err("%s: Could not allocate payload of size = %d\n",
- __func__, RTAC_BUF_SIZE);
+ __func__, rtac_cal[ADM_RTAC_CAL].map_data.map_size);
goto nomem;
}
@@ -1010,10 +1361,11 @@
}
mutex_init(&rtac_asm_apr_mutex);
- rtac_asm_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+ rtac_asm_buffer = kzalloc(
+ rtac_cal[ASM_RTAC_CAL].map_data.map_size, GFP_KERNEL);
if (rtac_asm_buffer == NULL) {
pr_err("%s: Could not allocate payload of size = %d\n",
- __func__, RTAC_BUF_SIZE);
+ __func__, rtac_cal[ASM_RTAC_CAL].map_data.map_size);
kzfree(rtac_adm_buffer);
goto nomem;
}
@@ -1028,10 +1380,11 @@
mutex_init(&rtac_voice_mutex);
mutex_init(&rtac_voice_apr_mutex);
- rtac_voice_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+ rtac_voice_buffer = kzalloc(
+ rtac_cal[VOICE_RTAC_CAL].map_data.map_size, GFP_KERNEL);
if (rtac_voice_buffer == NULL) {
pr_err("%s: Could not allocate payload of size = %d\n",
- __func__, RTAC_BUF_SIZE);
+ __func__, rtac_cal[VOICE_RTAC_CAL].map_data.map_size);
kzfree(rtac_adm_buffer);
kzfree(rtac_asm_buffer);
goto nomem;