Merge "ASoC: msm: qdsp6v2: Add session specific control for slowtalk"
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index 195a98d..f57d928 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -3,10 +3,8 @@
The application processor in MSM can do a variety of C-States for low power
management. These C-States are invoked by the CPUIdle framework when the core
becomes idle. But based on the time available until the next scheduled wakeup,
-the system can do a combination of low power modes of different resources -
-L2, XO, Vdd Dig and Vdd Mem. The combination is captured in the device tree as
-lpm-level. The units for voltage are dependent on the PMIC used on the target
-and are in uV.
+the system can do several low power modes. The combination is captured in the
+device tree as lpm-level.
The required nodes for lpm-levels are:
@@ -20,20 +18,11 @@
"retention" - Retention
"pc_suspend" - Suspended Power Collapse
"pc_no_xo_shutdown" - Power Collapse with no XO shutdown
-- qcom,xo: The state of XO clock. Values are "xo_on" and "xo_off"
- qcom,l2: The state of L2 cache. Values are:
"l2_cache_pc" - L2 cache in power collapse
"l2_cache_retenetion" - L2 cache in retention
"l2_cache_gdhs" - L2 cache in GDHS
"l2_cache_active" - L2 cache in active mode
-- qcom,vdd-mem-upper-bound: The upper bound value of mem voltage in uV
-- qcom,vdd-mem-lower-bound: The lower bound value of mem voltage in uV
-- qcom,vdd-dig-upper-bound: The upper bound value of dig voltage in uV
- or an RBCPR (Rapid Bridge Core Power Reduction)
- corner voltage.
-- qcom,vdd-dig-lower-bound: The lower bound value of dig voltage in uV
- or an RBCPR (Rapid Bridge Core Power Reduction)
- corner voltage.
- qcom,latency-us: The latency in handling the interrupt if this level was
chosen, in uSec
- qcom,ss-power: The steady state power expelled when the processor is in this
@@ -42,29 +31,18 @@
in mWatts.uSec
- qcom,time-overhead: The time spent in entering and exiting this level in uS
-Optional properties
-- qcom,irqs-detectable: The field indicates whether the IRQs are detectable by
- the GIC controller when entering a low power mode.
-- qcom,gpio-detectable: The field indicates whether the GPIOs can be detected
- by the GPIO interrupt controller during a given low
- power mode.
-- qcom,use-qtimer: Indicates whether the target uses the synchronized QTimer.
+The optional nodes for lpm-levels are :
+- qcom,no-l2-saw: Indicates if this target has an L2 SAW (SPM and AVS wrapper).
+- qcom,default-l2-state: Indicates what the default low power state of the L2 SAW should be. This property is used only when there is an L2 SAW.
Example:
qcom,lpm-levels {
- qcom,use-qtimer;
+ qcom,no-l2-saw;
qcom,lpm-level@0 {
reg = <0>;
qcom,mode = "wfi";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <100>;
qcom,ss-power = <650>;
qcom,energy-overhead = <801>;
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
deleted file mode 100644
index 7b5fda3..0000000
--- a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-* Low Power Management Resources
-
-The application processor in the MSM can enter several different low power
-states depending on the sleep time and on the required system resources. The
-MSM cannot enter a given low power state if that state involves turning off
-some shared resources which are required by some components of the
-system.The lpm-resources device tree node represents the shared resources
-that need to be monitored for usage requirement to check if a given low power
-state can be entered.Each resource is identified by a combination of the name,
-id,type and key which is also used by the RPM to identify a shared resource.
-The name and resource-type are required nodes; the type, id and key are
-optional nodes which are needed if the resource type is RPM shared resource
-(MSM_LPM_RPM_RS_TYPE).
-
-The nodes for lpm-resources are:
-
-Required Nodes:
-
-- compatible: "qcom,lpm-resources"
-- reg: The numeric level id
-- qcom,name: The name of the low power resource represented
- as a string.
-- qcom,init-value: Initialization value of the LPM resource represented as
- decimal value for vdd-dig and vdd-mem resources and
- as string for pxo and l2 resources.
-
-
-Optional Nodes:
-
-- qcom,type: The type of resource used like smps or pxo
- represented as a hex value.
-- qcom,id: The id representing a device within a resource type.
-- qcom,key: The key is the specific attribute of the resource being
- monitored represented as a hex value.
-- qcom,local-resource-type: The property exists only for locally managed
- resource and is represented as a bool.
-
-Example:
- qcom,lpm-resources@0 {
- reg = <0x0>;
- qcom,name = "vdd-dig";
- qcom,type = <0x62706d73>; /* "smpb" */
- qcom,id = <0x02>;
- qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value= <5>; /* Active Corner*/
- };
-
diff --git a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
index 6dac1b7..bf5e544 100644
--- a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
+++ b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
@@ -26,12 +26,13 @@
add the appropriate binding:
Required parameters:
-- qcom,memblock-remove: base and size of block to be removed
+- qcom,memblock-remove: array of the base and size of blocks to be removed
qcom,a-driver {
compatible = "qcom,a-driver";
- /* Remove 4MB at 0x200000*/
- qcom,memblock-remove = <0x200000 0x400000>;
+ /* Remove 4MB at 0x200000 and 2MB at 0x800000*/
+ qcom,memblock-remove = <0x200000 0x400000
+ 0x800000 0x200000>;
};
In order to ensure memory is only reserved when a driver is actually enabled,
diff --git a/Documentation/devicetree/bindings/batterydata/batterydata.txt b/Documentation/devicetree/bindings/batterydata/batterydata.txt
new file mode 100644
index 0000000..985fb4c
--- /dev/null
+++ b/Documentation/devicetree/bindings/batterydata/batterydata.txt
@@ -0,0 +1,163 @@
+Battery Profile Data
+
+Battery Data is a collection of battery profile data made available to
+the QPNP Charger and BMS drivers via device tree.
+
+qcom,battery-data node required properties:
+- qcom,rpull-up-kohm : The vadc pullup resistor's resistance value in kOhms.
+- qcom,vref-batt-therm-uv : The vadc voltage used to make readings.
+ For Qualcomm VADCs this should be 1800000uV.
+
+qcom,battery-data can also include any number of children nodes. These children
+nodes will be treated as battery profile data nodes.
+
+Profile data node required properties:
+- qcom,fcc-mah : Full charge count of the battery in milliamp-hours
+- qcom,default-rbatt-mohm : The nominal battery resistance value
+- qcom,rbatt-capacitive-mohm : The capacitive resistance of the battery.
+- qcom,flat-ocv-threshold-uv : The threshold under which the battery can be
+ considered to be in the flat portion of the discharge
+ curve.
+- qcom,max-voltage-uv : The maximum rated voltage of the battery
+- qcom,v-cutoff-uv : The cutoff voltage of the battery at which the device
+ should shutdown gracefully.
+- qcom,chg-term-ua : The termination charging current of the battery.
+- qcom,batt-id-kohm : The battery id resistance of the battery.
+
+Profile data node required subnodes:
+- qcom,fcc-temp-lut : An 1-dimensional lookup table node that encodes
+ temperature to fcc lookup. The units for this lookup
+ table should be degrees celsius to milliamp-hours.
+- qcom,pc-temp-ocv-lut : A 2-dimensional lookup table node that encodes
+ temperature and percent charge to open circuit voltage
+ lookup. The units for this lookup table should be
+ degrees celsius and percent to millivolts.
+- qcom,rbatt-sf-lut : A 2-dimentional lookup table node that encodes
+ temperature and percent charge to battery internal
+ resistance lookup. The units for this lookup table
+ should be degrees celsius and percent to milliohms.
+
+Lookup table required properties:
+- qcom,lut-col-legend : An array that encodes the legend of the lookup table's
+ columns. The length of this array will determine the
+ lookup table's width.
+- qcom,lut-data : An array that encodes the lookup table's data. The size of this
+ array should be equal to the size of qcom,lut-col-legend
+ multiplied by 1 if it's a 1-dimensional table, or
+ the size of qcom,lut-row-legend if it's a 2-dimensional
+ table. The data should be in a flattened row-major
+ representation.
+
+Lookup table optional properties:
+- qcom,lut-row-legend : An array that encodes the legend of the lookup table's rows.
+ If this property exists, then it is assumed that the
+ lookup table is a 2-dimensional table.
+
+Example:
+
+In msm8974-mtp.dtsi:
+
+mtp_batterydata: qcom,battery-data {
+ qcom,rpull-up-kohm = <100>;
+ qcom,vref-batt-therm-uv = <1800000>;
+
+ /include/ "batterydata-palladium.dtsi"
+ /include/ "batterydata-mtp-3000mah.dtsi"
+};
+
+&pm8941_bms {
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+In batterydata-palladium.dtsi:
+
+qcom,palladium-batterydata {
+ qcom,fcc-mah = <1500>;
+ qcom,default-rbatt-mohm = <236>;
+ qcom,rbatt-capacitive-mohm = <50>;
+ qcom,flat-ocv-threshold-uv = <3800000>;
+ qcom,max-voltage-uv = <4200000>;
+ qcom,v-cutoff-uv = <3400000>;
+ qcom,chg-term-ua = <100000>;
+ qcom,batt-id-kohm = <75>;
+
+ qcom,fcc-temp-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 65>;
+ qcom,lut-data = <1492 1492 1493 1483 1502>;
+ };
+
+ qcom,pc-temp-ocv-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 65>;
+ qcom,lut-row-legend = <100 95 90 85 80 75 70>,
+ <65 60 55 50 45 40 35>,
+ <30 25 20 15 10 9 8>,
+ <7 6 5 4 3 2 1 0>;
+ qcom,lut-data = <4173 4167 4163 4156 4154>,
+ <4104 4107 4108 4102 4104>,
+ <4057 4072 4069 4061 4060>,
+ <3973 4009 4019 4016 4020>,
+ <3932 3959 3981 3982 3983>,
+ <3899 3928 3954 3950 3950>,
+ <3868 3895 3925 3921 3920>,
+ <3837 3866 3898 3894 3892>,
+ <3812 3841 3853 3856 3862>,
+ <3794 3818 3825 3823 3822>,
+ <3780 3799 3804 3804 3803>,
+ <3768 3787 3790 3788 3788>,
+ <3757 3779 3778 3775 3776>,
+ <3747 3772 3771 3766 3765>,
+ <3736 3763 3766 3760 3746>,
+ <3725 3749 3756 3747 3729>,
+ <3714 3718 3734 3724 3706>,
+ <3701 3703 3696 3689 3668>,
+ <3675 3695 3682 3675 3662>,
+ <3670 3691 3680 3673 3661>,
+ <3661 3686 3679 3672 3656>,
+ <3649 3680 3676 3669 3641>,
+ <3633 3669 3667 3655 3606>,
+ <3610 3647 3640 3620 3560>,
+ <3580 3607 3596 3572 3501>,
+ <3533 3548 3537 3512 3425>,
+ <3457 3468 3459 3429 3324>,
+ <3328 3348 3340 3297 3172>,
+ <3000 3000 3000 3000 3000>;
+ };
+
+ qcom,rbatt-sf-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 65>;
+ qcom,lut-row-legend = <100 95 90 85 80 75 70>,
+ <65 60 55 50 45 40 35>,
+ <30 25 20 15 10 9 8>,
+ <7 6 5 4 3 2 1 0>;
+ qcom,lut-data = <357 187 100 91 91>,
+ <400 208 105 94 94>,
+ <390 204 106 95 96>,
+ <391 201 108 98 98>,
+ <391 202 110 98 100>,
+ <390 200 110 99 102>,
+ <389 200 110 99 102>,
+ <393 202 101 93 100>,
+ <407 205 99 89 94>,
+ <428 208 100 91 96>,
+ <455 212 102 92 98>,
+ <495 220 104 93 101>,
+ <561 232 107 95 102>,
+ <634 245 112 98 98>,
+ <714 258 114 98 98>,
+ <791 266 114 97 100>,
+ <871 289 108 95 97>,
+ <973 340 124 108 105>,
+ <489 241 109 96 99>,
+ <511 246 110 96 99>,
+ <534 252 111 95 98>,
+ <579 263 112 96 96>,
+ <636 276 111 95 97>,
+ <730 294 109 96 99>,
+ <868 328 112 98 104>,
+ <1089 374 119 101 115>,
+ <1559 457 128 105 213>,
+ <12886 1026 637 422 3269>,
+ <170899 127211 98968 88907 77102>;
+ };
+};
+
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index d24e671..7f7ee25 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -118,6 +118,12 @@
- qcom,setb-gpios-pull : active pull configuration for set B gpios
- qcom,setb-gpios-dir : active direction for set B gpios
- qcom,hwevent-clks : list of clocks required by hardware event driver
+- qcom,byte-cntr-absent : specifies if the byte counter feature is absent on
+ the device. Only relevant in case of tmc-etr device.
+- interrupts : <a b c> where a is 0 or 1 depending on if the interrupt is
+ spi/ppi, b is the interrupt number and c is the mask,
+- interrupt-names : a list of strings that map in order to the list of
+ interrupts specified in the 'interrupts' property.
Examples:
@@ -128,6 +134,11 @@
<0xfc37c000 0x3000>;
reg-names = "tmc-base", "bam-base";
+ interrupts = <0 166 0>;
+ interrupt-names = "byte-cntr-irq";
+
+ qcom,byte-cntr-absent;
+
coresight-id = <0>;
coresight-name = "coresight-tmc-etr";
coresight-nr-inports = <1>;
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index ce4972a..4cec0cd 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -12,21 +12,41 @@
- vdda-supply: Phandle for vreg regulator device node.
- qcom,mdss-fb-map: pHandle that specifies the framebuffer to which the
interface is mapped.
+- qcom,platform-regulator-settings: An array of length 7 that specifies the PHY
+ regulator settings.
+- qcom,platform-strength-ctrl: An array of length 2 that specifies the PHY
+ strengthCtrl settings.
+- qcom,platform-bist-ctrl: An array of length 6 that specifies the PHY
+ BIST ctrl settings.
+- qcom,platform-lane-config: An array of length 45 that specifies the PHY
+ lane configuration settings.
Optional properties:
- label: A string used to describe the controller used.
-- qcom,supply-names: A list of strings that lists the names of the
- regulator supplies.
-- qcom,supply-min-voltage-level: A list that specifies minimum voltage level
- of supply(ies) mentioned above. This list maps
- in the order of the supply names listed above.
-- qcom,supply-max-voltage-level: A list that specifies maximum voltage level of
- supply(ies) mentioned above. This list maps in
- the order of the supply names listed above.
-- qcom,supply-peak-current: A list that specifies the peak current that will
- be drawn from the supply(ies) mentioned above. This
- list maps in the order of the supply names listed above.
+- qcom,platform-supply-entry<1..n>: A node that lists the elements of the supply. There
+ can be more than one instance of this binding,
+ in which case the entry would be appended with
+ the supply entry index.
+ e.g. qcom,platform-supply-entry1
+ -- qcom,supply-name: name of the supply (vdd/vdda/vddio)
+ -- qcom,supply-min-voltage: minimum voltage level (uV)
+ -- qcom,supply-max-voltage: maximum voltage level (uV)
+ -- qcom,supply-enable-load: load drawn (uA) from enabled supply
+ -- qcom,supply-disable-load: load drawn (uA) from disabled supply
+ -- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on
+ -- qcom,supply-post-on-sleep: time to sleep (ms) after turning on
+ -- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off
+ -- qcom,supply-post-off-sleep: time to sleep (ms) after turning off
+- 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-reset-sequence: An array that lists the
+ sequence of reset gpio values and sleeps
+ Each command will have the format defined
+ as below:
+ --> Reset GPIO value
+ --> Sleep value (in ms)
Example:
mdss_dsi0: qcom,mdss_dsi@fd922800 {
@@ -37,9 +57,50 @@
vdd-supply = <&pm8226_l15>;
vddio-supply = <&pm8226_l8>;
vdda-supply = <&pm8226_l4>;
- qcom,supply-names = "vdd", "vddio", "vdda";
- qcom,supply-min-voltage-level = <2800000 1800000 1200000>;
- qcom,supply-max-voltage-level = <2800000 1800000 1200000>;
- qcom,supply-peak-current = <150000 100000 100000>;
+ 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];
+ qcom,platform-lane-config = [00 00 00 00 00 00 00 01 97
+ 00 00 00 00 05 00 00 01 97
+ 00 00 00 00 0a 00 00 01 97
+ 00 00 00 00 0f 00 00 01 97
+ 00 c0 00 00 00 00 00 01 bb];
qcom,mdss-fb-map = <&mdss_fb0>;
+ qcom,platform-reset-gpio = <&msmgpio 25 1>;
+ qcom,platform-te-gpio = <&msmgpio 24 0>;
+ qcom,platform-enable-gpio = <&msmgpio 58 1>;
+ qcom,platform-reset-sequence = <1 25 0 20 1 10>;
+ qcom,platform-supply-entry1 {
+ qcom,supply-name = "vdd";
+ qcom,supply-min-voltage = <2800000>;
+ qcom,supply-max-voltage = <2800000>;
+ 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 = <30>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <30>;
+ };
+ qcom,platform-supply-entry3 {
+ qcom,supply-name = "vdda";
+ 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 = <30>;
+ };
};
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 8c87eac..44134f8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -12,140 +12,173 @@
the panel driver. By default this property will be
set to "disable". Will be set to "ok/okay" status
for specific platforms.
-- qcom,dsi-ctrl-phandle: Specifies the phandle for the DSI controller that
+- qcom,mdss-dsi-panel-controller: Specifies the phandle for the DSI controller that
this panel will be mapped to.
-- qcom,mdss-pan-res: A two dimensional array that specifies the panel
- resolution.
-- qcom,mdss-pan-bpp: Specifies the panel bits per pixel. Default value is 24(rgb888).
- 18 = for rgb666
+- qcom,mdss-dsi-panel-width: Specifies panel width in pixels.
+- qcom,mdss-dsi-panel-height: Specifies panel height in pixels.
+- qcom,mdss-dsi-bpp: Specifies the panel bits per pixel.
+ 3 = for rgb111
+ 8 = for rgb332
+ 12 = for rgb444
16 = for rgb565
-- qcom,mdss-pan-dest: A string that specifies the destination display for the panel.
- Default is "display_1".
+ 18 = for rgb666
+ 24 = for rgb888
+- qcom,mdss-dsi-panel-destination: A string that specifies the destination display for the panel.
"display_1" = DISPLAY_1
"display_2" = DISPLAY_2
-- qcom,panel-phy-regulatorSettings: An array of length 7 that specifies the PHY
- regulator settings for the panel.
-- qcom,panel-phy-timingSettings: An array of length 12 that specifies the PHY
+- qcom,mdss-dsi-panel-timings: An array of length 12 that specifies the PHY
timing settings for the panel.
-- qcom,panel-phy-strengthCtrl: An array of length 2 that specifies the PHY
- strengthCtrl settings for the panel.
-- qcom,panel-phy-bistCtrl: An array of length 6 that specifies the PHY
- BIST ctrl settings for the panel.
-- qcom,panel-phy-laneConfig: An array of length 45 that specifies the PHY
- lane configuration settings for the panel.
-- qcom,mdss-panel-on-cmds: An array of variable length that lists the init commands
- of the panel. Each command will have the format specified
- as below:
- --> data type of the command
- --> specifies whether this command packet is last.
- --> virtual channel
- --> Needs acknowledge from the panel or not.
- --> wait time after the command is transmitter.
- --> size of payload
- --> payload.
-- qcom,mdss-panel-off-cmds: An array of variable length that lists the panel off
- commands. Each command will have the format specified
- as below:
- --> data type of the command
- --> specifies whether this command packet is last.
- --> virtual channel
- --> Needs acknowledge from the panel or not.
- --> wait time after the command is transmitter.
- --> size of payload
- --> payload.
+- qcom,mdss-dsi-on-command: A byte stream formed by multiple dcs packets base on
+ qcom dsi controller protocol.
+ byte 0: dcs data type
+ byte 1: set to indicate this is an individual packet
+ (no chain)
+ byte 2: virtual channel number
+ byte 3: expect ack from client (dcs read command)
+ byte 4: wait number of specified ms after dcs command
+ transmitted
+ byte 5, 6: 16 bits length in network byte order
+ byte 7 and beyond: number byte of payload
+- qcom,mdss-dsi-off-command: A byte stream formed by multiple dcs packets base on
+ qcom dsi controller protocol.
+ byte 0: dcs data type
+ byte 1: set to indicate this is an individual packet
+ (no chain)
+ byte 2: virtual channel number
+ byte 3: expect ack from client (dcs read command)
+ byte 4: wait number of specified ms after dcs command
+ transmitted
+ byte 5, 6: 16 bits length in network byte order
+ byte 7 and beyond: number byte of payload
Optional properties:
-- label: A string used as a descriptive name of the panel
-- qcom,enable-gpio: Specifies the panel lcd/display enable gpio.
-- qcom,rst-gpio: Specifies the panel reset gpio.
-- qcom,te-gpio: Specifies the gpio used for TE.
-- qcom,pwm-lpg-channel: LPG channel for backlight.
-- qcom,pwm-period: PWM period in microseconds.
-- qcom,pwm-pmic-gpio: PMIC gpio binding to backlight.
-- qcom,mdss-pan-broadcast-mode: Boolean used to enable broadcast mode.
+- qcom,mdss-dsi-panel-name: A string used as a descriptive name of the panel
- qcom,cont-splash-enabled: Boolean used to enable continuous splash mode.
-- qcom,fbc-enabled: Boolean used to enable frame buffer compression mode.
-- qcom,fbc-mode-select: An array of length 7 that specifies the fbc mode supported
- by the panel. FBC enabled panels may or may not support
- the modes specified here. Each entry will
- have the format specified below:
- --> compressed bpp supported by the panel
- --> component packing
- --> enable/disable quantization error calculation
- --> Bias for CD
- --> enable/disable PAT mode
- --> enable/disable VLC mode
- --> enable/disable BFLC mode
-- qcom,fbc-budget-ctl: An array of length 3 that specifies the budget control settings
- supported by the fbc enabled panel. Each entry will have the format
- specified below:
- --> per line extra budget
- --> extra budget level
- --> per block budget
-- qcom,fbc-lossy-mode: An array of 3 that specifies the lossy mode settings
- supported by the fbc enabled panel. Each entry will
- have the format specified below:
- --> lossless mode threshold
- --> lossy mode threshold
- --> lossy RGB threshold
-- qcom,mdss-pan-porch-values: An array of size 6 that specifies the panel blanking values.
-- qcom,mdss-pan-underflow-clr: Specifies the controller settings for the panel underflow clear
- settings. Default value is 0xff.
-- qcom,mdss-pan-bl-ctrl: A string that specifies the implementation of backlight
+- qcom,mdss-dsi-panel-broadcast-mode: Boolean used to enable broadcast mode.
+- qcom,mdss-dsi-fbc-enable: Boolean used to enable frame buffer compression mode.
+- qcom,mdss-dsi-fbc-bpp: Compressed bpp supported by the panel.
+ Specified color order is used as default value.
+- qcom,mdss-dsi-fbc-packing: Component packing.
+ 0 = default value.
+- qcom,mdss-dsi-fbc-quant-error: Boolean used to enable quantization error calculation.
+- qcom,mdss-dsi-fbc-bias: Bias for CD.
+ 0 = default value.
+- qcom,mdss-dsi-fbc-pat-mode: Boolean used to enable PAT mode.
+- qcom,mdss-dsi-fbc-vlc-mode: Boolean used to enable VLC mode.
+- qcom,mdss-dsi-fbc-bflc-mode: Boolean used to enable BFLC mode.
+- qcom,mdss-dsi-fbc-h-line-budget: Per line extra budget.
+ 0 = default value.
+- qcom,mdss-dsi-fbc-budget-ctrl: Extra budget level.
+ 0 = default value.
+- qcom,mdss-dsi-fbc-block-budget: Per block budget.
+ 0 = default value.
+- qcom,mdss-dsi-fbc-lossless-threshold: Lossless mode threshold.
+ 0 = default value.
+- qcom,mdss-dsi-fbc-lossy-threshold: Lossy mode threshold.
+ 0 = default value.
+- qcom,mdss-dsi-fbc-rgb-threshold: Lossy RGB threshold.
+ 0 = default value.
+- qcom,mdss-dsi-fbc-lossy-mode-idx: Lossy mode index value.
+ 0 = default value.
+- qcom,mdss-dsi-h-back-porch: Horizontal back porch value in pixel.
+ 6 = default value.
+- qcom,mdss-dsi-h-front-porch: Horizontal front porch value in pixel.
+ 6 = default value.
+- qcom,mdss-dsi-h-pulse-width: Horizontal pulse width.
+ 2 = default value.
+- qcom,mdss-dsi-h-sync-skew: Horizontal sync skew value.
+ 0 = default value.
+- qcom,mdss-dsi-v-back-porch: Vertical back porch value in pixel.
+ 6 = default value.
+- qcom,mdss-dsi-v-front-porch: Vertical front porch value in pixel.
+ 6 = default value.
+- qcom,mdss-dsi-v-pulse-width: Vertical pulse width.
+ 2 = default value.
+- qcom,mdss-dsi-h-left-border: Horizontal left border in pixel.
+ 0 = default value
+- qcom,mdss-dsi-h-right-border: Horizontal right border in pixel.
+ 0 = default value
+- qcom,mdss-dsi-v-top-border: Vertical top border in pixel.
+ 0 = default value
+- qcom,mdss-dsi-v-bottom-border: Vertical bottom border in pixel.
+ 0 = default value
+- qcom,mdss-dsi-underflow-color: Specifies the controller settings for the
+ panel under flow color.
+ 0xff = default value.
+- qcom,mdss-dsi-border-color: Defines the border color value if border is present.
+ 0 = default value.
+- qcom,mdss-dsi-bl-pmic-control-type: A string that specifies the implementation of backlight
control for this panel.
"bl_ctrl_pwm" = Backlight controlled by PWM gpio.
"bl_ctrl_wled" = Backlight controlled by WLED.
- "bl_ctrl_dcs_cmds" = Backlight controlled by DCS commands.
-- qcom,mdss-pan-bl-levels: Specifies the backlight levels supported by the panel.
- Default range is 1 to 255.
-
-- qcom,mdss-pan-dsi-mode: Specifies the panel operating mode.
- 0 = enable video mode(default mode).
- 1 = enable command mode.
-- qcom,mdss-vsync-enable: Specifies Tear Check configuration.
- 0 = TE disable.
- 1 = TE enable.
-- qcom,mdss-hw-vsync-mode: Specifies TE type.
- 0 = software vsync.
- 1 = hardware vsync (TE gpio pin).
-- qcom,mdss-pan-te-sel: Specifies TE operating mode.
+ "bl_ctrl_dcs" = Backlight controlled by DCS commands.
+ other: Unknown backlight control. (default)
+- qcom,mdss-dsi-bl-pmic-bank-select: LPG channel for backlight.
+ Requred if blpmiccontroltype is PWM
+- qcom,mdss-dsi-bl-pmic-pwm-frequency: PWM period in microseconds.
+ Requred if blpmiccontroltype is PWM
+- qcom,mdss-dsi-pwm-gpio: PMIC gpio binding to backlight.
+ Requred if blpmiccontroltype is PWM
+- qcom,mdss-dsi-bl-min-level: Specifies the min backlight level supported by the panel.
+ 0 = default value.
+- qcom,mdss-dsi-bl-max-level: Specifies the max backlight level supported by the panel.
+ 255 = default value.
+- qcom,mdss-dsi-interleave-mode: Specifies interleave mode.
+ 0 = default value.
+- qcom,mdss-dsi-panel-type: Specifies the panel operating mode.
+ "dsi_video_mode" = enable video mode (default).
+ "dsi_cmd_mode" = enable command mode.
+- qcom,mdss-dsi-te-check-enable: Boolean to enable Tear Check configuration.
+- qcom,mdss-dsi-te-using-te-pin: Boolean to specify whether using hardware vsync.
+- qcom,mdss-dsi-te-pin-select: Specifies TE operating mode.
0 = TE through embedded dcs command
- 1 = TE through TE gpio pin.
-- qcom,mdss-pan-dsi-h-pulse-mode: Specifies the pulse mode option for the panel.
+ 1 = TE through TE gpio pin. (default)
+- qcom,mdss-dsi-te-dcs-command: Inserts the dcs command.
+ 1 = default value.
+- qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line: Configures the scan line number that the dsi
+ pixel transfer will start on. Rasing this number
+ will result in delaying the start of the pixel
+ transfer.
+ 0x2c = default value.
+- qcom,mdss-dsi-te-v-sync-continue-lines: Represents the difference in number of lines
+ between estimated read pointer and write pointer
+ to allow the updating of all the lines except
+ the first line of the frame.
+ 0x3c = default value.
+- qcom,mdss-dsi-h-sync-pulse: Specifies the pulse mode option for the panel.
0 = Don't send hsa/he following vs/ve packet(default)
1 = Send hsa/he following vs/ve packet
-- qcom,mdss-pan-dsi-h-power-stop: An Array of size 3 that specifies the power mode
- during horizontal porch and sync periods of the panel.
- 0 = high speed mode(default mode).
- 1 = Low power mode for horizontal porches and sync pulse.
-- qcom,mdss-pan-dsi-bllp-power-stop: An Array of size 2 that specifies the power mode
- during blanking period and after EOF(end of frame).
- 0 = high speed mode(default mode).
- 1 = Low power mode during blanking and EOF.
-- qcom,mdss-pan-dsi-traffic-mode: Specifies the panel traffic mode.
+- qcom,mdss-dsi-hfp-power-mode: Boolean to determine DSI lane state during
+ horizontal front porch (HFP) blanking period.
+- qcom,mdss-dsi-hbp-power-mode: Boolean to determine DSI lane state during
+ horizontal back porch (HBP) blanking period.
+- qcom,mdss-dsi-hsa-power-mode: Boolean to determine DSI lane state during
+ horizontal sync active (HSA) mode.
+- qcom,mdss-dsi-bllp-eof-power-mode: Boolean to determine DSI lane state during
+ blanking low power period (BLLP) EOF mode.
+- qcom,mdss-dsi-bllp-power-mode: Boolean to determine DSI lane state during
+ blanking low power period (BLLP) mode.
+- qcom,mdss-dsi-traffic-mode: Specifies the panel traffic mode.
0 = non burst with sync pulses (default mode).
1 = non burst with sync start event.
2 = burst mode.
-- qcom,mdss-pan-dsi-dst-format: Specifies the destination format.
- 0 = DSI_VIDEO_DST_FORMAT_RGB565.
- 1 = DSI_VIDEO_DST_FORMAT_RGB666.
- 2 = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE.
- 3 = DSI_VIDEO_DST_FORMAT_RGB888 (Default format)
- 6 = DSI_CMD_DST_FORMAT_RGB565
- 7 = DSI_CMD_DST_FORMAT_RGB666
- 8 = DSI_CMD_DST_FORMAT_RGB888
-- qcom,mdss-pan-dsi-vc: Specifies the virtual channel identefier.
+- qcom,mdss-dsi-pixel-packing: Specifies if pixel packing is used (in case of RGB666).
+ 0 = Tight packing (default value).
+ 1 = Loose packing.
+- qcom,mdss-dsi-virtual-channel-id: Specifies the virtual channel identefier.
0 = default value.
-- qcom,mdss-pan-dsi-rgb-swap: Specifies the R, G and B channel ordering.
+- qcom,mdss-dsi-color-order: Specifies the R, G and B channel ordering.
0 = DSI_RGB_SWAP_RGB (default value)
1 = DSI_RGB_SWAP_RBG
2 = DSI_RGB_SWAP_BGR
3 = DSI_RGB_SWAP_BRG
4 = DSI_RGB_SWAP_GRB
5 = DSI_RGB_SWAP_GBR
-- qcom,mdss-pan-dsi-data-lanes: An array that specifies the data lanes enabled.
- <1 1 0 0> = data lanes 1 and 2 are enabled.(default).
-- qcom,mdss-pan-dsi-dlane-swap: Specifies the data lane swap configuration.
+- qcom,mdss-dsi-lane-0-state: Boolean that specifies whether data lane 0 is enabled.
+- qcom,mdss-dsi-lane-1-state: Boolean that specifies whether data lane 1 is enabled.
+- qcom,mdss-dsi-lane-2-state: Boolean that specifies whether data lane 2 is enabled.
+- qcom,mdss-dsi-lane-3-state: Boolean that specifies whether data lane 3 is enabled.
+- qcom,mdss-dsi-lane-map: Specifies the data lane swap configuration.
0 = <0 1 2 3> (default value)
1 = <3 0 1 2>
2 = <2 3 0 1>
@@ -154,79 +187,121 @@
5 = <1 0 3 2>
6 = <2 1 0 3>
7 = <3 2 1 0>
-- qcom,mdss-pan-dsi-t-clk: An array that specifies the byte clock cycles
- before and after each mode switch.
-- qcom,mdss-pan-dsi-stream: Specifies the packet stream to be used.
+- qcom,mdss-dsi-t-clk-post: Specifies the byte clock cycles after mode switch.
+ 0x03 = default value.
+- qcom,mdss-dsi-t-clk-pre: Specifies the byte clock cycles before mode switch.
+ 0x24 = default value.
+- qcom,mdss-dsi-stream: Specifies the packet stream to be used.
0 = stream 0 (default)
1 = stream 1
-- qcom,mdss-pan-dsi-mdp-tr: Specifies the trigger mechanism to be used for MDP path.
+- qcom,mdss-dsi-mdp-trigger: Specifies the trigger mechanism to be used for MDP path.
0 = no trigger
2 = Tear check signal line used for trigger
- 4 = Triggered by software (default mode)
+ 4 = Triggered by software (default)
6 = Software trigger and TE
-- qcom,mdss-pan-dsi-dma-tr: Specifies the trigger mechanism to be used for DMA path.
+- qcom,mdss-dsi-dma-trigger: Specifies the trigger mechanism to be used for DMA path.
0 = no trigger
2 = Tear check signal line used for trigger
- 4 = Triggered by software (default mode)
+ 4 = Triggered by software (default)
5 = Software trigger and start/end of frame trigger.
6 = Software trigger and TE
-- qcom,mdss-pan-dsi-frame-rate: Specifies the frame rate for the panel.
+- qcom,mdss-dsi-panel-framerate: Specifies the frame rate for the panel.
60 = 60 frames per second (default)
-- qcom,on-cmds-dsi-state: A string that Specifies the ctrl state for sending ON commands.
- Supported modes are "DSI_LP_MODE" and "DSI_HS_MODE".
-- qcom,off-cmds-dsi-state: A string that Specifies the ctrl state for sending ON commands.
- Supported modes are "DSI_LP_MODE" and "DSI_HS_MODE".
+- qcom,mdss-dsi-panel-clockrate: Specifies the panel clock speed in Hz.
+ 0 = default value.
+- qcom,mdss-dsi-on-command-state: String that specifies the ctrl state for sending ON commands.
+ "dsi_lp_mode" = DSI low power mode (default)
+ "dsi_hs_mode" = DSI high speed mode
+- qcom,mdss-dsi-off-command-state: String that specifies the ctrl state for sending OFF commands.
+ "dsi_lp_mode" = DSI low power mode (default)
+ "dsi_hs_mode" = DSI high speed mode
-- qcom,panel-on-cmds: A byte stream formed by multiple dcs packets base on
- qcom dsi controller protocol.
- byte 0 : dcs data type
- byte 1 : set to indicate this is an individual packet
- (no chain).
- byte 2 : virtual channel number
- byte 3 : expect ack from client (dcs read command)
- byte 4 : wait number of specified ms after dcs command
- transmitted
- byte 5, 6: 16 bits length in network byte order
- byte 7 and beyond: number byte of payload
-
Note, if a given optional qcom,* binding is not present, then the driver will configure
the default values specified.
Example:
-/ {
+&soc {
qcom,mdss_dsi_sim_video {
compatible = "qcom,mdss-dsi-panel";
- label = "simulator video mode dsi panel";
+ qcom,mdss-dsi-panel-name = "simulator video mode dsi panel";
status = "disable";
- qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
- qcom,mdss-pan-res = <640 480>;
- qcom,mdss-pan-bpp = <24>;
- qcom,mdss-pan-dest = "display_1";
- qcom,mdss-pan-porch-values = <6 2 6 6 2 6>;
- qcom,mdss-pan-underflow-clr = <0xff>;
- qcom,mdss-pan-bl-levels = <1 15>;
- qcom,mdss-pan-dsi-mode = <0>;
- qcom,mdss-pan-dsi-h-pulse-mode = <1>;
- qcom,mdss-pan-dsi-h-power-stop = <1 1 1>;
- qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
- qcom,mdss-pan-dsi-traffic-mode = <0>;
- qcom,mdss-pan-dsi-dst-format = <3>;
- qcom,mdss-pan-dsi-vc = <0>;
- qcom,mdss-pan-dsi-rgb-swap = <0>;
- qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
- qcom,mdss-pan-dsi-t-clk = <0x24 0x03>;
- qcom,mdss-pan-dsi-stream = <0>;
- qcom,mdss-pan-dsi-mdp-tr = <0x04>;
- qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-frame-rate = <60>;
- qcom,panel-on-cmds = [32 01 00 00 00 00 02 00 00];
- qcom,on-cmds-dsi-state = "DSI_LP_MODE";
- qcom,panel-off-cmds = [22 01 00 00 00 00 00];
- qcom,off-cmds-dsi-state = "DSI LP MODE";
- qcom,fbc-enabled;
- qcom,fbc-mode = <12 0 1 2 1 1 1>;
- qcom,fbc-budget-ctl = <675 5 91>;
- qcom,fbc-lossy-mode = <0 0xc0 0 3>;
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-height = <1280>;
+ qcom,mdss-dsi-panel-width = <720>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-pixel-packing = <0>;
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-broadcast-mode;
+ qcom,mdss-dsi-fbc-enable;
+ qcom,mdss-dsi-fbc-bpp = <0>;
+ qcom,mdss-dsi-fbc-packing = <0>;
+ qcom,mdss-dsi-fbc-quant-error;
+ qcom,mdss-dsi-fbc-bias = <0>;
+ qcom,mdss-dsi-fbc-pat-mode;
+ qcom,mdss-dsi-fbc-vlc-mode;
+ qcom,mdss-dsi-fbc-bflc-mode;
+ qcom,mdss-dsi-fbc-h-line-budget = <0>;
+ qcom,mdss-dsi-fbc-budget-ctrl = <0>;
+ qcom,mdss-dsi-fbc-block-budget = <0>;
+ qcom,mdss-dsi-fbc-lossless-threshold = <0>;
+ qcom,mdss-dsi-fbc-lossy-threshold = <0>;
+ qcom,mdss-dsi-fbc-rgb-threshold = <0>;
+ qcom,mdss-dsi-fbc-lossy-mode-idx = <0>;
+ qcom,mdss-dsi-h-front-porch = <140>;
+ qcom,mdss-dsi-h-back-porch = <164>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <6>;
+ qcom,mdss-dsi-v-front-porch = <1>;
+ qcom,mdss-dsi-v-pulse-width = <1>;
+ 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-border-color = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = < 15>;
+ qcom,mdss-dsi-interleave-mode = <0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-v-sync-continue-lines = <0x3c>;
+ qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-hfp-power-mode;
+ qcom,mdss-dsi-hbp-power-mode;
+ qcom,mdss-dsi-hsa-power-mode;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-traffic-mode = <0>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-color-order = <0>;
+ 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-lane-map = <0>;
+ qcom,mdss-dsi-t-clk-post = <0x20>;
+ qcom,mdss-dsi-t-clk-pre = <0x2c>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-dma-trigger = <0>;
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-panel-clockrate = <424000000>;
+ qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33
+ 22 27 1e 03 04 00];
+ qcom,mdss-dsi-on-command = [32 01 00 00 00 00 02 00 00
+ 29 01 00 00 10 00 02 FF 99];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command = [22 01 00 00 00 00 00];
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <0>;
+ qcom,mdss-dsi-pwm-gpio = <&pm8941_mpps 5 0>;
};
};
diff --git a/Documentation/devicetree/bindings/fb/mdss-edp.txt b/Documentation/devicetree/bindings/fb/mdss-edp.txt
index 578b07c..3d7e5a2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-edp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-edp.txt
@@ -20,6 +20,7 @@
specific platforms.
- qcom,mdss-fb-map: pHandle that specifies the framebuffer to which the
interface is mapped.
+- gpio-panel-hpd : gpio pin use for edp hpd
Example:
mdss_edp: qcom,mdss_edp@fd923400 {
@@ -32,6 +33,8 @@
qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
qcom,panel-pwm-period = <53>;
status = "disable";
+ qcom,mdss-fb-map = <&mdss_fb0>;
+ gpio-panel-hpd = <&msmgpio 102 0>;
};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index 0f35e73..3720172 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -20,6 +20,7 @@
- synaptics,panel-x : panel x dimension
- synaptics,panel-y : panel y dimension
- synaptics,fw-image-name : name of firmware .img file in /etc/firmware
+ - synaptics,power-down : fully power down regulators in suspend
Example:
i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index e9c5061..b60760e 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -107,10 +107,13 @@
- qcom,mode: mode the led should operate in, options "pwm" and "lpg"
- qcom,pwm-channel: pwm channel the led will operate on
- qcom,pwm-us: time the pwm device will modulate at (us)
-- qcom,row-src-sel-val: select source for rows. One bit is used for each row.
- Specify 0 for vph_pwr and 1 for vbst for each row.
-- qcom,row-scan-val: select rows for scanning
-- qcom,row-scan-en: row scan enable
+- qcom,row-id: specify the id of the row. Supported values are 0 to 3.
+
+Optional properties for keypad backlight:
+- qcom,row-src-vbst: select source for rows. Specify for vbst and ignore it
+ for vph_pwr.
+- qcom,row-src-en: specify to enable row source
+- qcom,always-on: specify if the module has to be always on
Required properties for PWM mode only:
- qcom,pwm-us: time the pwm device will modulate at (us)
@@ -259,16 +262,33 @@
qcom,leds@e200 {
status = "okay";
- qcom,kpdbl {
+
+ qcom,kpdbl1 {
label = "kpdbl";
- linux,name = "button-backlight";
+ linux,name = "kpdbl-pwm-1";
qcom,mode = <0>;
qcom,pwm-channel = <8>;
qcom,pwm-us = <1000>;
qcom,id = <7>;
qcom,max-current = <20>;
- qcom,row-src-sel-val = <0x00>;
- qcom,row-scan-en = <0x01>;
- qcom,row-scan-val = <0x01>;
+ qcom,row-id = <0>;
+ qcom,row-src-en;
+ qcom,always-on;
};
+
+ qcom,kpdbl2 {
+ label = "kpdbl";
+ linux,name = "kpdbl-lut-2";
+ qcom,mode = <1>;
+ qcom,pwm-channel = <9>;
+ qcom,pwm-us = <1000>;
+ qcom,start-idx = <1>;
+ qcom,duty-pcts = [00 00 00 00 64
+ 64 00 00 00 00];
+ qcom,id = <7>;
+ qcom,max-current = <20>;
+ qcom,row-id = <1>;
+ qcom,row-src-en;
+ };
+
};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 8e988be..b8156c3 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -18,6 +18,17 @@
qcom,gpio-req-tbl-num property (in the same order)
- qcom,gpio-req-tbl-label : should contain name of gpios present in
qcom,gpio-req-tbl-num property (in the same order)
+
+Optional properties:
+- master0: qcom,cci-master0 - node should contain clock settings for
+ cci master 0 bus
+- master1: qcom,cci-master1 - node should contain clock settings for
+ cci master 1 bus
+
+[Second level nodes]
+* Qualcomm CCI clock settings
+
+Optional properties:
- qcom,hw-thigh : should contain high period of the SCL clock in terms of CCI
clock cycle
- qcom,hw-tlow : should contain high period of the SCL clock in terms of CCI
@@ -31,7 +42,6 @@
- qcom,hw-trdhld : should contain internal hold time for SDA
- qcom,hw-tsp : should contain filtering of glitches
-[Second level nodes]
* Qualcomm MSM Sensor
MSM sensor node contains properties of camera sensor
@@ -175,16 +185,12 @@
"CCI_I2C_CLK0",
"CCI_I2C_DATA1",
"CCI_I2C_CLK1";
- qcom,hw-thigh = <78>;
- qcom,hw-tlow = <114>;
- qcom,hw-tsu-sto = <28>;
- qcom,hw-tsu-sta = <28>;
- qcom,hw-thd-dat = <10>;
- qcom,hw-thd-sta = <77>;
- qcom,hw-tbuf = <118>;
- qcom,hw-scl-stretch-en = <0>;
- qcom,hw-trdhld = <6>;
- qcom,hw-tsp = <1>;
+ master0: qcom,cci-master0 {
+ status = "disabled";
+ };
+ master1: qcom,cci-master1 {
+ status = "disabled";
+ };
actuator0: qcom,actuator@18 {
cell-index = <0>;
@@ -235,3 +241,31 @@
qcom,sensor-mode = <1>;
};
};
+
+ &master0 {
+ qcom,hw-thigh = <78>;
+ qcom,hw-tlow = <114>;
+ qcom,hw-tsu-sto = <28>;
+ qcom,hw-tsu-sta = <28>;
+ qcom,hw-thd-dat = <10>;
+ qcom,hw-thd-sta = <77>;
+ qcom,hw-tbuf = <118>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <1>;
+ status = "ok";
+ };
+
+ &master1 {
+ qcom,hw-thigh = <78>;
+ qcom,hw-tlow = <114>;
+ qcom,hw-tsu-sto = <28>;
+ qcom,hw-tsu-sta = <28>;
+ qcom,hw-thd-dat = <10>;
+ qcom,hw-thd-sta = <77>;
+ qcom,hw-tbuf = <118>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <1>;
+ status = "ok";
+ };
diff --git a/Documentation/devicetree/bindings/pil/pil-pronto.txt b/Documentation/devicetree/bindings/pil/pil-pronto.txt
index de54b24..2cbf22c 100644
--- a/Documentation/devicetree/bindings/pil/pil-pronto.txt
+++ b/Documentation/devicetree/bindings/pil/pil-pronto.txt
@@ -13,12 +13,12 @@
- interrupts: WCNSS to Apps watchdog bite interrupt
- vdd_pronto_pll-supply: regulator to supply pronto pll.
- qcom,firmware-name: Base name of the firmware image. Ex. "wcnss"
-- qcom,gpio-proxy-unvote: GPIO used by the wcnss to trigger proxy unvoting in
- the Apps
Optional properties:
- qcom,gpio-err-fatal: GPIO used by the wcnss to indicate error fatal to the Apps.
- qcom,gpio-err-ready: GPIO used by the wcnss to indicate error ready to the Apps.
+- qcom,gpio-proxy-unvote: GPIO used by the wcnss to trigger proxy unvoting in
+ the Apps
- qcom,gpio-force-stop: GPIO used by the Apps to force the wcnss to shutdown.
Example:
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
index f421d1b..d32279d 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -14,13 +14,13 @@
- interrupts: The lpass watchdog interrupt
- vdd_cx-supply: Reference to the regulator that supplies the vdd_cx domain.
- qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
-- qcom,gpio-proxy-unvote: GPIO used by the lpass to indicate apps clock is ready.
Optional properties:
- vdd_pll-supply: Reference to the regulator that supplies the PLL's rail.
- qcom,vdd_pll: Voltage to be set for the PLL's rail.
- qcom,gpio-err-fatal: GPIO used by the lpass to indicate error fatal to the apps.
- qcom,gpio-err-ready: GPIO used by the lpass to indicate apps error service is ready.
+- qcom,gpio-proxy-unvote: GPIO used by the lpass to indicate apps clock is ready.
- qcom,gpio-force-stop: GPIO used by the apps to force the lpass to shutdown.
Example:
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 596e590..0a3789a 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -15,8 +15,6 @@
- vdd_cx-supply: Reference to the regulator that supplies the vdd_cx domain.
- vdd_mx-supply: Reference to the regulator that supplies the memory rail.
- qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
-- qcom,gpio-proxy-unvote: GPIO used by the modem to trigger proxy unvoting in
- the apps.
Optional properties:
- vdd_mss-supply: Reference to the regulator that supplies the processor.
@@ -32,6 +30,8 @@
- qcom,pil-self-auth: Boolean- True if authentication is required.
- qcom,gpio-err-fatal: GPIO used by the modem to indicate error fatal to the apps.
- qcom,gpio-err-ready: GPIO used by the modem to indicate error ready to the apps.
+- qcom,gpio-proxy-unvote: GPIO used by the modem to trigger proxy unvoting in
+ the apps.
- qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
- qcom,gpio-stop-ack: GPIO used by the modem to ack force stop or a graceful stop
to the apps.
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 3e7a578..0672f14 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -13,6 +13,11 @@
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:
+- qcom,battery-data : A phandle to a node containing the available batterydata
+ profiles. See the batterydata bindings documentation for more
+ details.
+
Parent node required properties:
- compatible : should be "qcom,qpnp-bms" for the BM driver.
- qcom,r-sense-uohm : sensor resistance in in micro-ohms.
@@ -142,6 +147,7 @@
qcom,high-ocv-correction-limit-uv = <50>;
qcom,hold-soc-est = <3>;
qcom,tm-temp-margin = <5000>;
+ qcom,battery-data = <&mtp_batterydata>;
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 83ce3f8..95be46c 100644
--- a/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
@@ -11,17 +11,10 @@
Required device bindings:
- compatible: should be "qcom,qpnp-pwm"
-- reg: Offset and length of the controller's LPG channel register,
- and LPG look-up table (LUT). The LPG look-up table is a
- contiguous address space that is populated with PWM values.
- The size of PWM value is 9 bit and the size of each
- entry of the table is 8 bit. Thus, two entries are used
- to fill each PWM value. The lower entry is used for PWM
- LSB byte and higher entry is used for PWM MSB bit.
-- reg-names: Names for the above registers.
+- reg: Offset and length of the controller's LPG channel register.
+- reg-names: Name for the above register.
"qpnp-lpg-channel-base" = physical base address of the
controller's LPG channel register.
- "qpnp-lpg-lut-base" = physical base address of LPG LUT.
- qcom,channel-id: channel Id for the PWM.
Optional device bindings:
@@ -52,12 +45,20 @@
duty cycle percentages is populated. The size of the list cannot exceed
the size of the LPG look-up table.
-- qcom,period: PWM period time in microseconds.
-- qcom,duty-percents: List of entries for look-up table
-- cell-index: Index of look-up table that should be used to start
- filling up the duty-pct list. start-idx + size of list
- cannot exceed the size of look-up table.
-- label: "lpg"
+- reg: Offset and length of LPG look-up table (LUT). The LPG look-up table is a
+ contiguous address space that is populated with PWM values.
+ The size of PWM value is 9 bit and the size of each
+ entry of the table is 8 bit. Thus, two entries are used
+ to fill each PWM value. The lower entry is used for PWM
+ LSB byte and higher entry is used for PWM MSB bit.
+- reg-names: Name for the above register.
+ "qpnp-lpg-lut-base" = physical base address of LPG LUT.
+- qcom,period: PWM period time in microseconds.
+- qcom,duty-percents: List of entries for look-up table
+- cell-index: Index of look-up table that should be used to start
+ filling up the duty-pct list. start-idx + size of list
+ cannot exceed the size of look-up table.
+- label: "lpg"
Optional bindings to support LPG feature:
diff --git a/arch/arm/boot/dts/apq8026-v1-cdp.dts b/arch/arm/boot/dts/apq8026-v1-cdp.dts
new file mode 100644
index 0000000..8c6daa6
--- /dev/null
+++ b/arch/arm/boot/dts/apq8026-v1-cdp.dts
@@ -0,0 +1,22 @@
+/* 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.
+ */
+
+
+/dts-v1/;
+/include/ "apq8026-v1.dtsi"
+/include/ "msm8226-cdp.dtsi"
+
+/ {
+ model = "Qualcomm APQ 8026 CDP";
+ compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
+ qcom,msm-id = <199 1 0>;
+};
diff --git a/arch/arm/boot/dts/apq8026-v2-cdp.dts b/arch/arm/boot/dts/apq8026-v2-cdp.dts
new file mode 100644
index 0000000..74608dd
--- /dev/null
+++ b/arch/arm/boot/dts/apq8026-v2-cdp.dts
@@ -0,0 +1,22 @@
+/* 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.
+ */
+
+
+/dts-v1/;
+/include/ "apq8026-v2.dtsi"
+/include/ "msm8226-cdp.dtsi"
+
+/ {
+ model = "Qualcomm APQ 8026v2 CDP";
+ compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
+ qcom,msm-id = <199 1 0x20000>;
+};
diff --git a/arch/arm/boot/dts/apq8084-mdss.dtsi b/arch/arm/boot/dts/apq8084-mdss.dtsi
index 07dffe1..5c5cd1b 100644
--- a/arch/arm/boot/dts/apq8084-mdss.dtsi
+++ b/arch/arm/boot/dts/apq8084-mdss.dtsi
@@ -19,6 +19,8 @@
interrupts = <0 72 0>;
vdd-supply = <&gdsc_mdss>;
+ status = "disabled";
+
qcom,max-clk-rate = <320000000>;
qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 3014813..aca42b6 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -164,6 +164,37 @@
qcom,scl-gpio = <&msmgpio 11 0>;
};
+ qcom,usbbam@f9304000 {
+ compatible = "qcom,usb-bam-msm";
+ reg = <0xf9304000 0x5000>,
+ <0xf92f880c 0x4>;
+ reg-names = "ssusb", "qscratch_ram1_reg";
+ interrupts = <0 132 0>;
+ interrupt-names = "ssusb";
+ qcom,usb-bam-num-pipes = <16>;
+ qcom,usb-bam-fifo-baseaddr = <0x00000000 0xf9200000>;
+ qcom,ignore-core-reset-ack;
+ qcom,disable-clk-gating;
+
+ qcom,pipe0 {
+ label = "ssusb-qdss-in-0";
+ qcom,usb-bam-mem-type = <1>;
+ qcom,bam-type = <0>;
+ qcom,dir = <1>;
+ qcom,pipe-num = <0>;
+ qcom,peer-bam = <1>;
+ qcom,src-bam-physical-address = <0xfc37C000>;
+ 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-size = <0x1800>;
+ qcom,descriptor-fifo-offset = <0xf4000>;
+ qcom,descriptor-fifo-size = <0x1400>;
+ qcom,reset-bam-on-connect;
+ };
+ };
+
usb3: qcom,ssusb@f9200000 {
compatible = "qcom,dwc-usb3-msm";
reg = <0xf9200000 0xfc000>,
diff --git a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
index 25c1851..c8d150a 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
@@ -10,98 +10,76 @@
* 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"
+ *---------------------------------------------------------------------------*/
&soc {
qcom,mdss_dsi_hx8394a_720p_video {
compatible = "qcom,mdss-dsi-panel";
- label = "hx8394a 720p video mode dsi panel";
status = "disable";
- qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
- qcom,rst-gpio = <&msmgpio 25 0>;
- qcom,mdss-pan-res = <720 1280>;
- qcom,mdss-pan-bpp = <24>;
- qcom,mdss-pan-dest = "display_1";
- qcom,mdss-pan-porch-values = <59 60 79 10 2 7>;
- qcom,mdss-pan-underflow-clr = <0xff>;
- qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
- qcom,mdss-pan-bl-levels = <1 4095>;
- qcom,mdss-pan-dsi-mode = <0>;
- qcom,mdss-pan-dsi-h-pulse-mode = <1>;
- qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
- qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
- qcom,mdss-pan-dsi-traffic-mode = <2>;
- qcom,mdss-pan-dsi-dst-format = <3>;
- qcom,mdss-pan-dsi-vc = <0>;
- qcom,mdss-pan-dsi-rgb-swap = <0>;
- qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
- qcom,mdss-pan-dsi-dlane-swap = <0>;
- qcom,mdss-pan-dsi-t-clk = <0x2d 0x1f>;
- qcom,mdss-pan-dsi-stream = <0>;
- qcom,mdss-pan-dsi-mdp-tr = <0x0>;
- qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-dsi-frame-rate = <60>;
- qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regualotor settings */
- 20 00 01];
- qcom,panel-phy-timingSettings = [8d 24 19 00 34 34
- 1d 26 2a 03 04 00];
- qcom,panel-phy-strengthCtrl = [ff 06];
- qcom,panel-phy-bistCtrl = [00 00 b1 ff /* BIST Ctrl settings */
- 00 00];
- qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
- 00 00 00 00 05 00 00 01 97 /* lane1 config */
- 00 00 00 00 0a 00 00 01 97 /* lane2 config */
- 00 00 00 00 0f 00 00 01 97 /* lane3 config */
- 00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
- qcom,panel-on-cmds = [39 01 00 00 00 00 04
- b9 ff 83 94
- 39 01 00 00 00 00 05
- c7 00 10 00 10
- 39 01 00 00 00 00 02
- bc 07
- 39 01 00 00 00 00 02
- ba 13
- 39 01 00 00 00 00 10
- b1 01 00 07 83 01
- 12 0f 32 38 29 29
- 50 02 00 00
- 39 01 00 00 00 00 07
- b2 00 c8 09 05 00
- 71
- 39 01 00 00 00 00 02
- cc 05
- 05 01 00 00 00 00 02 00 00
- 39 01 00 00 00 00 35
- d5 00 00 00 00 0a
- 00 01 00 00 00 33
- 00 23 45 67 01 01
- 23 88 88 88 88 88
- 88 88 99 99 99 88
- 88 99 88 54 32 10
- 76 32 10 88 88 88
- 88 88 88 88 99 99
- 99 88 88 88 99
- 39 01 00 00 00 00 17
- b4 80 08 32 10 00
- 32 15 08 32 12 20
- 33 05 4c 05 37 05
- 3f 1e 5f 5f 06
- 39 01 00 00 00 00 02
- b6 00
- 39 01 00 00 00 00 23
- e0 01 05 07 25 35
- 3f 0b 32 04 09 0e
- 10 13 10 14 16 1b
- 01 05 07 25 35 3f
- 0b 32 04 09 0e 10
- 13 10 14 16 1b
- 05 01 00 00 00 00 02 00 00
- 39 01 00 00 00 00 04
- bf 06 00 10
- 05 01 00 00 c8 00 02 11 00
- 05 01 00 00 32 00 02 29 00];
+ qcom,mdss-dsi-panel-name = "hx8394a 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 = <79>;
+ qcom,mdss-dsi-h-back-porch = <59>;
+ qcom,mdss-dsi-h-pulse-width = <60>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <10>;
+ qcom,mdss-dsi-v-front-porch = <7>;
+ 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 = [39 01 00 00 00 00 04 b9 ff 83 94
+ 39 01 00 00 00 00 05 c7 00 10 00 10
+ 39 01 00 00 00 00 02 bc 07
+ 39 01 00 00 00 00 02 ba 13
+ 39 01 00 00 00 00 10 b1 01 00 07 83 01 12 0f 32 38 29 29 50 02 00 00
+ 39 01 00 00 00 00 07 b2 00 c8 09 05 00 71
+ 39 01 00 00 00 00 02 cc 05
+ 05 01 00 00 00 00 02 00 00
+ 39 01 00 00 00 00 35 d5 00 00 00 00 0a 00 01 00 00 00 33 00 23 45 67 01 01 23 88 88 88 88 88 88 88 99 99 99 88 88 99 88 54 32 10 76 32 10 88 88 88 88 88 88 88 99 99 99 88 88 88 99
+ 39 01 00 00 00 00 17 b4 80 08 32 10 00 32 15 08 32 12 20 33 05 4c 05 37 05 3f 1e 5f 5f 06
+ 39 01 00 00 00 00 02 b6 00
+ 39 01 00 00 00 00 23 e0 01 05 07 25 35 3f 0b 32 04 09 0e 10 13 10 14 16 1b 01 05 07 25 35 3f 0b 32 04 09 0e 10 13 10 14 16 1b
+ 05 01 00 00 00 00 02 00 00
+ 39 01 00 00 00 00 04 bf 06 00 10
+ 05 01 00 00 c8 00 02 11 00
+ 05 01 00 00 32 00 02 29 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 0a 00 02 28 00
+ 05 01 00 00 96 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>;
+ qcom,mdss-dsi-traffic-mode = <2>;
+ 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-panel-timings = [8d 24 19 00 34 34 1d 26 2a 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x1f>;
+ qcom,mdss-dsi-t-clk-pre = <0x2d>;
+ 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";
- qcom,on-cmds-dsi-state = "DSI_LP_MODE";
- qcom,panel-off-cmds = [05 01 00 00 0a 00 02 28 00
- 05 01 00 00 96 00 02 10 00];
- qcom,off-cmds-dsi-state = "DSI_HS_MODE";
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
index 2a6bbf9..d0b4da8 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
@@ -10,55 +10,40 @@
* 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"
+ *---------------------------------------------------------------------------*/
&soc {
qcom,mdss_dsi_nt35590_720p_cmd {
compatible = "qcom,mdss-dsi-panel";
- label = "nt35590 720p command mode dsi panel";
status = "disable";
- qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
- qcom,rst-gpio = <&msmgpio 25 0>;
- qcom,te-gpio = <&msmgpio 24 0>;
- qcom,mdss-pan-res = <720 1280>;
- qcom,mdss-pan-bpp = <24>;
- qcom,mdss-pan-dest = "display_1";
- qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
- qcom,mdss-pan-underflow-clr = <0xff>;
- qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
- qcom,mdss-pan-bl-levels = <1 4095>;
- qcom,mdss-pan-dsi-mode = <1>;
- qcom,mdss-vsync-enable = <1>;
- qcom,mdss-hw-vsync-mode = <1>;
- qcom,mdss-pan-dsi-h-pulse-mode = <1>;
- qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
- qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
- qcom,mdss-pan-dsi-traffic-mode = <2>;
- qcom,mdss-pan-dsi-dst-format = <8>;
- qcom,mdss-pan-insert-dcs-cmd = <1>;
- qcom,mdss-pan-wr-mem-continue = <0x3c>;
- qcom,mdss-pan-wr-mem-start = <0x2c>;
- qcom,mdss-pan-te-sel = <1>;
- qcom,mdss-pan-dsi-vc = <0>;
- qcom,mdss-pan-dsi-rgb-swap = <0>;
- qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
- qcom,mdss-pan-dsi-dlane-swap = <0>;
- qcom,mdss-pan-dsi-t-clk = <0x2c 0x20>;
- qcom,mdss-pan-dsi-stream = <0>;
- qcom,mdss-pan-dsi-mdp-tr = <0x0>;
- qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-dsi-frame-rate = <60>;
- qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regualotor settings */
- 20 00 01];
- qcom,panel-phy-timingSettings = [7d 25 1d 00 37 33
- 22 27 1e 03 04 00];
- qcom,panel-phy-strengthCtrl = [ff 06];
- qcom,panel-phy-bistCtrl = [00 00 b1 ff /* BIST Ctrl settings */
- 00 00];
- qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
- 00 00 00 00 05 00 00 01 97 /* lane1 config */
- 00 00 00 00 0a 00 00 01 97 /* lane2 config */
- 00 00 00 00 0f 00 00 01 97 /* lane3 config */
- 00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
- qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+ qcom,mdss-dsi-panel-name = "nt35590 720p 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-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 = <140>;
+ qcom,mdss-dsi-h-back-porch = <164>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <1>;
+ qcom,mdss-dsi-v-front-porch = <6>;
+ qcom,mdss-dsi-v-pulse-width = <1>;
+ 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 FF EE
29 01 00 00 00 00 02 26 08
29 01 00 00 00 00 02 26 00
29 01 00 00 10 00 02 FF 00
@@ -522,10 +507,32 @@
29 01 00 00 00 00 02 6A 60
29 01 00 00 00 00 02 FF 00
29 01 00 00 78 00 02 29 00];
-
- qcom,on-cmds-dsi-state = "DSI_LP_MODE";
- qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 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,off-cmds-dsi-state = "DSI_HS_MODE";
+ 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-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-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 22 27 1e 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x20>;
+ qcom,mdss-dsi-t-clk-pre = <0x2c>;
+ 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-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index d742b30..a171a5c 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -10,48 +10,40 @@
* 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"
+ *---------------------------------------------------------------------------*/
&soc {
qcom,mdss_dsi_nt35590_720p_video {
compatible = "qcom,mdss-dsi-panel";
- label = "nt35590 720p video mode dsi panel";
status = "disable";
- qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
- qcom,rst-gpio = <&msmgpio 25 0>;
- qcom,mdss-pan-res = <720 1280>;
- qcom,mdss-pan-bpp = <24>;
- qcom,mdss-pan-dest = "display_1";
- qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
- qcom,mdss-pan-underflow-clr = <0xff>;
- qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
- qcom,mdss-pan-bl-levels = <1 4095>;
- qcom,mdss-pan-dsi-mode = <0>;
- qcom,mdss-pan-dsi-h-pulse-mode = <1>;
- qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
- qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
- qcom,mdss-pan-dsi-traffic-mode = <2>;
- qcom,mdss-pan-dsi-dst-format = <3>;
- qcom,mdss-pan-dsi-vc = <0>;
- qcom,mdss-pan-dsi-rgb-swap = <0>;
- qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
- qcom,mdss-pan-dsi-dlane-swap = <0>;
- qcom,mdss-pan-dsi-t-clk = <0x2c 0x20>;
- qcom,mdss-pan-dsi-stream = <0>;
- qcom,mdss-pan-dsi-mdp-tr = <0x0>;
- qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-dsi-frame-rate = <60>;
- qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regualotor settings */
- 20 00 01];
- qcom,panel-phy-timingSettings = [7d 25 1d 00 37 33
- 22 27 1e 03 04 00];
- qcom,panel-phy-strengthCtrl = [ff 06];
- qcom,panel-phy-bistCtrl = [00 00 b1 ff /* BIST Ctrl settings */
- 00 00];
- qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
- 00 00 00 00 05 00 00 01 97 /* lane1 config */
- 00 00 00 00 0a 00 00 01 97 /* lane2 config */
- 00 00 00 00 0f 00 00 01 97 /* lane3 config */
- 00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
- qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+ qcom,mdss-dsi-panel-name = "nt35590 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 = <140>;
+ qcom,mdss-dsi-h-back-porch = <164>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <1>;
+ qcom,mdss-dsi-v-front-porch = <6>;
+ qcom,mdss-dsi-v-pulse-width = <1>;
+ 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 FF EE
29 01 00 00 00 00 02 26 08
29 01 00 00 00 00 02 26 00
29 01 00 00 10 00 02 FF 00
@@ -516,10 +508,27 @@
29 01 00 00 00 00 02 FF 00
29 01 00 00 78 00 02 29 00
29 01 00 00 78 00 02 53 2C];
-
- qcom,on-cmds-dsi-state = "DSI_LP_MODE";
- qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 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,off-cmds-dsi-state = "DSI_HS_MODE";
+ 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-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-panel-timings = [7d 25 1d 00 37 33 22 27 1e 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x20>;
+ qcom,mdss-dsi-t-clk-pre = <0x2c>;
+ 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-nt35596-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
index 1ecad71..998799a 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
@@ -10,48 +10,40 @@
* 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"
+ *---------------------------------------------------------------------------*/
&soc {
qcom,mdss_dsi_nt35596_1080p_video {
compatible = "qcom,mdss-dsi-panel";
- label = "nt35596 1080p video mode dsi panel";
status = "disable";
- qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
- qcom,rst-gpio = <&msmgpio 25 0>;
- qcom,mdss-pan-res = <1080 1920>;
- qcom,mdss-pan-bpp = <24>;
- qcom,mdss-pan-dest = "display_1";
- qcom,mdss-pan-porch-values = <32 8 32 18 2 2>;
- qcom,mdss-pan-underflow-clr = <0xff>;
- qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
- qcom,mdss-pan-bl-levels = <1 4095>;
- qcom,mdss-pan-dsi-mode = <0>;
- qcom,mdss-pan-dsi-h-pulse-mode = <1>;
- qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
- qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
- qcom,mdss-pan-dsi-traffic-mode = <2>;
- qcom,mdss-pan-dsi-dst-format = <3>;
- qcom,mdss-pan-dsi-vc = <0>;
- qcom,mdss-pan-dsi-rgb-swap = <0>;
- qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
- qcom,mdss-pan-dsi-dlane-swap = <0>;
- qcom,mdss-pan-dsi-t-clk = <0x38 0x1e>;
- qcom,mdss-pan-dsi-stream = <0>;
- qcom,mdss-pan-dsi-mdp-tr = <0x0>;
- qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-dsi-frame-rate = <60>;
- qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regualotor settings */
- 20 00 01];
- qcom,panel-phy-timingSettings = [f9 3d 34 00 58 4d
- 36 3f 53 03 04 00];
- qcom,panel-phy-strengthCtrl = [ff 06];
- qcom,panel-phy-bistCtrl = [00 00 b1 ff /* BIST Ctrl settings */
- 00 00];
- qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
- 00 00 00 00 05 00 00 01 97 /* lane1 config */
- 00 00 00 00 0a 00 00 01 97 /* lane2 config */
- 00 00 00 00 0f 00 00 01 97 /* lane3 config */
- 00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
- qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+ qcom,mdss-dsi-panel-name = "nt35596 1080p 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 = <1080>;
+ qcom,mdss-dsi-panel-height = <1920>;
+ qcom,mdss-dsi-h-front-porch = <32>;
+ qcom,mdss-dsi-h-back-porch = <32>;
+ qcom,mdss-dsi-h-pulse-width = <8>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <18>;
+ 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 = [29 01 00 00 00 00 02 FF EE
29 01 00 00 00 00 02 FB 01
29 01 00 00 00 00 02 1F 45
29 01 00 00 00 00 02 24 4F
@@ -571,10 +563,27 @@
29 01 00 00 00 00 02 FF 00
29 01 00 00 00 00 02 35 00
29 01 00 00 78 00 02 29 00];
-
- qcom,on-cmds-dsi-state = "DSI_LP_MODE";
- qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 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,off-cmds-dsi-state = "DSI_HS_MODE";
+ 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-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-panel-timings = [f9 3d 34 00 58 4d 36 3f 53 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x1e>;
+ qcom,mdss-dsi-t-clk-pre = <0x38>;
+ 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-sharp-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
index 45d396c..7fe0f7f 100644
--- a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -10,58 +10,65 @@
* 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"
+ *---------------------------------------------------------------------------*/
&soc {
qcom,mdss_dsi_sharp_qhd_video {
compatible = "qcom,mdss-dsi-panel";
- label = "sharp QHD LS043T1LE01 video mode dsi panel";
status = "disable";
- qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
- qcom,enable-gpio = <&msmgpio 58 0>;
- qcom,rst-gpio = <&pm8941_gpios 19 0>;
- qcom,mdss-pan-res = <540 960>;
- qcom,mdss-pan-bpp = <24>;
- qcom,mdss-pan-dest = "display_1";
- qcom,mdss-pan-porch-values = <80 32 48 15 10 3>; /* HBP, HPW, HFP, VBP, VPW, VFP */
- qcom,mdss-pan-underflow-clr = <0xff>;
- qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
- qcom,mdss-pan-bl-levels = <1 4095>;
- qcom,mdss-pan-dsi-mode = <0>;
- qcom,mdss-pan-dsi-h-pulse-mode = <1>;
- qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
- qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
- qcom,mdss-pan-dsi-traffic-mode = <0>;
- qcom,mdss-pan-dsi-dst-format = <3>;
- qcom,mdss-pan-dsi-vc = <0>;
- qcom,mdss-pan-dsi-rgb-swap = <2>;
- qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
- qcom,mdss-pan-dsi-dlane-swap = <0>;
- qcom,mdss-pan-dsi-t-clk = <0x1c 0x04>;
- qcom,mdss-pan-dsi-stream = <0>;
- qcom,mdss-pan-dsi-mdp-tr = <0x04>;
- qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-frame-rate = <60>;
- qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regulator settings */
- 20 00 01];
- qcom,panel-phy-timingSettings = [46 1d 20 00 39 3a
- 21 21 32 03 04 00];
- qcom,panel-phy-strengthCtrl = [ff 06];
- qcom,panel-phy-bistCtrl = [00 00 b1 ff /* BIST Ctrl settings */
- 00 00];
- qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
- 00 00 00 00 05 00 00 01 97 /* lane1 config */
- 00 00 00 00 0a 00 00 01 97 /* lane2 config */
- 00 00 00 00 0f 00 00 01 97 /* lane3 config */
- 00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
- qcom,panel-on-cmds = [05 01 00 00 32 00 02 01 00 /* sw reset */
- 05 01 00 00 0a 00 02 11 00 /* exit sleep */
- 15 01 00 00 0a 00 02 53 2c /* backlight on */
- 15 01 00 00 0a 00 02 51 ff /* brightness max */
- 05 01 00 00 0a 00 02 29 00 /* display on */
- 15 01 00 00 0a 00 02 ae 03 /* set num of lanes */
- 15 01 00 00 0a 00 02 3a 77 /* rgb_888 */];
- qcom,on-cmds-dsi-state = "DSI_LP_MODE";
- qcom,panel-off-cmds = [05 01 00 00 0a 00 02 28 00 /* display off */
- 05 01 00 00 78 00 02 10 00 /* enter sleep */];
- qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+ qcom,mdss-dsi-panel-name = "sharp QHD LS043T1LE01 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 = <540>;
+ qcom,mdss-dsi-panel-height = <960>;
+ qcom,mdss-dsi-h-front-porch = <48>;
+ qcom,mdss-dsi-h-back-porch = <80>;
+ qcom,mdss-dsi-h-pulse-width = <32>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <15>;
+ qcom,mdss-dsi-v-front-porch = <3>;
+ 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 = <2>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [05 01 00 00 32 00 02 01 00
+ 05 01 00 00 0a 00 02 11 00
+ 15 01 00 00 0a 00 02 53 2c
+ 15 01 00 00 0a 00 02 51 ff
+ 05 01 00 00 0a 00 02 29 00
+ 15 01 00 00 0a 00 02 ae 03
+ 15 01 00 00 0a 00 02 3a 77];
+ qcom,mdss-dsi-off-command = [05 01 00 00 0a 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_hs_mode";
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = <0>;
+ 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 = [46 1d 20 00 39 3a 21 21 32 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1c>;
+ 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 = <4>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
index 5c37cf8..a824d45 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -10,115 +10,88 @@
* 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"
+ *---------------------------------------------------------------------------*/
&soc {
-
qcom,mdss_dsi_toshiba_720p_video {
compatible = "qcom,mdss-dsi-panel";
- label = "toshiba 720p video mode dsi panel";
status = "disable";
- qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
- qcom,enable-gpio = <&msmgpio 58 0>;
- qcom,rst-gpio = <&pm8941_gpios 19 0>;
- qcom,mdss-pan-res = <720 1280>;
- qcom,mdss-pan-bpp = <24>;
- qcom,mdss-pan-dest = "display_1";
- qcom,mdss-pan-porch-values = <32 12 144 3 4 9>;
- qcom,mdss-pan-underflow-clr = <0xff>;
- qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
- qcom,mdss-pan-bl-levels = <1 4095>;
- qcom,mdss-pan-dsi-mode = <0>;
- qcom,mdss-pan-dsi-h-pulse-mode = <0>;
- qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
- qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
- qcom,mdss-pan-dsi-traffic-mode = <1>;
- qcom,mdss-pan-dsi-dst-format = <3>;
- qcom,mdss-pan-dsi-vc = <0>;
- qcom,mdss-pan-dsi-rgb-swap = <0>;
- qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>;
- qcom,mdss-pan-dsi-dlane-swap = <0>;
- qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
- qcom,mdss-pan-dsi-stream = <0>;
- qcom,mdss-pan-dsi-mdp-tr = <0x0>;
- qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-dsi-frame-rate = <60>;
- qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regualotor settings */
- 20 00 01];
- qcom,panel-phy-timingSettings = [b0 23 1b 00 94 93
- 1e 25 15 03 04 00];
- qcom,panel-phy-strengthCtrl = [ff 06];
- qcom,panel-phy-bistCtrl = [00 00 b1 ff /* BIST Ctrl settings */
- 00 00];
- qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
- 00 00 00 00 05 00 00 01 97 /* lane1 config */
- 00 00 00 00 0a 00 00 01 97 /* lane2 config */
- 00 00 00 00 0f 00 00 01 97 /* lane3 config */
- 00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
+ qcom,mdss-dsi-panel-name = "toshiba 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 = <144>;
+ qcom,mdss-dsi-h-back-porch = <32>;
+ qcom,mdss-dsi-h-pulse-width = <12>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <3>;
+ qcom,mdss-dsi-v-front-porch = <9>;
+ 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 = [23 01 00 00 0a 00 02 b0 00
+ 23 01 00 00 0a 00 02 b2 00
+ 23 01 00 00 0a 00 02 b3 0c
+ 23 01 00 00 0a 00 02 b4 02
+ 29 01 00 00 00 00 06 c0 40 02 7f c8 08
+ 29 01 00 00 00 00 10 c1 00 a8 00 00 00 00 00 9d 08 27 00 00 00 00 00
+ 29 01 00 00 00 00 06 c2 00 00 09 00 00
+ 23 01 00 00 0a 00 02 c3 04
+ 29 01 00 00 00 00 04 c4 4d 83 00
+ 29 01 00 00 00 00 0b c6 12 00 08 71 00 00 00 80 00 04
+ 23 01 00 00 0a 00 02 c7 22
+ 29 01 00 00 00 00 05 c8 4c 0c 0c 0c
+ 29 01 00 00 00 00 0e c9 00 40 00 16 32 2e 3a 43 3e 3c 45 79 3f
+ 29 01 00 00 00 00 0e ca 00 46 1a 23 21 1c 25 31 2d 49 5f 7f 3f
+ 29 01 00 00 00 00 0e cb 00 4c 20 3a 42 40 47 4b 42 3e 46 7e 3f
+ 29 01 00 00 00 00 0e cc 00 41 19 21 1d 14 18 1f 1d 25 3f 73 3f
+ 29 01 00 00 00 00 0e cd 23 79 5a 5f 57 4c 51 51 45 3f 4b 7f 3f
+ 29 01 00 00 00 00 0e ce 00 40 14 20 1a 0e 0e 13 08 00 05 46 1c
+ 29 01 00 00 00 00 04 d0 6a 64 01
+ 29 01 00 00 00 00 03 d1 77 d4
+ 23 01 00 00 0a 00 02 d3 33
+ 29 01 00 00 00 00 03 d5 0f 0f
+ 29 01 00 00 00 00 07 d8 34 64 23 25 62 32
+ 29 01 00 00 00 00 0c de 10 7b 11 0a 00 00 00 00 00 00 00
+ 29 01 00 00 00 00 09 fd 04 55 53 00 70 ff 10 73
+ 23 01 00 00 0a 00 02 e2 00
+ 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_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-panel-timings = [b0 23 1b 00 94 93 1e 25 15 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 = <4095>;
+ qcom,mdss-dsi-dma-trigger = <0x04>;
+ qcom,mdss-dsi-mdp-trigger = <0x0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
- qcom,panel-on-cmds = [23 01 00 00 0a 00 02 b0 00
- 23 01 00 00 0a 00 02 b2 00
- 23 01 00 00 0a 00 02 b3 0c
- 23 01 00 00 0a 00 02 b4 02
- 29 01 00 00 00 00 06
- c0 40 02 7f c8 08
- 29 01 00 00 00 00 10
- c1 00 a8 00 00 00
- 00 00 9d 08 27 00
- 00 00 00 00
- 29 01 00 00 00 00 06
- c2 00 00 09 00 00
- 23 01 00 00 0a 00 02 c3 04
- 29 01 00 00 00 00 04
- c4 4d 83 00
- 29 01 00 00 00 00 0b
- c6 12 00 08 71 00
- 00 00 80 00 04
- 23 01 00 00 0a 00 02 c7 22
- 29 01 00 00 00 00 05
- c8 4c 0c 0c 0c
- 29 01 00 00 00 00 0e
- c9 00 40 00 16 32
- 2e 3a 43 3e 3c 45
- 79 3f
- 29 01 00 00 00 00 0e
- ca 00 46 1a 23 21
- 1c 25 31 2d 49 5f
- 7f 3f
- 29 01 00 00 00 00 0e
- cb 00 4c 20 3a 42
- 40 47 4b 42 3e 46
- 7e 3f
- 29 01 00 00 00 00 0e
- cc 00 41 19 21 1d
- 14 18 1f 1d 25 3f
- 73 3f
- 29 01 00 00 00 00 0e
- cd 23 79 5a 5f 57
- 4c 51 51 45 3f 4b
- 7f 3f
- 29 01 00 00 00 00 0e
- ce 00 40 14 20 1a
- 0e 0e 13 08 00 05
- 46 1c
- 29 01 00 00 00 00 04
- d0 6a 64 01
- 29 01 00 00 00 00 03 d1 77 d4
- 23 01 00 00 0a 00 02 d3 33
- 29 01 00 00 00 00 03 d5 0f 0f
- 29 01 00 00 00 00 07
- d8 34 64 23 25 62
- 32
- 29 01 00 00 00 00 0c
- de 10 7b 11 0a 00
- 00 00 00 00 00 00
- 29 01 00 00 00 00 09
- fd 04 55 53 00 70
- ff 10 73
- 23 01 00 00 0a 00 02 e2 00
- 05 01 00 00 78 00 02 11 00
- 05 01 00 00 32 00 02 29 00];
- qcom,on-cmds-dsi-state = "DSI_LP_MODE";
- qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
- 05 01 00 00 78 00 02 10 00];
- qcom,off-cmds-dsi-state = "DSI_HS_MODE";
};
};
diff --git a/arch/arm/boot/dts/dsi-v2-panel-otm8018b-fwvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-otm8018b-fwvga-video.dtsi
new file mode 100644
index 0000000..c2c64da
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-v2-panel-otm8018b-fwvga-video.dtsi
@@ -0,0 +1,261 @@
+/* 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.
+ */
+
+/ {
+ qcom,dsi_v2_otm8018b_fwvga_video {
+ compatible = "qcom,dsi-panel-v2";
+ label = "OTM8018B FWVGA video mode dsi panel";
+ qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+ qcom,rst-gpio = <&msmgpio 41 0>;
+ vdda-supply = <&pm8110_l19>;
+ vddio-supply=<&pm8110_l14>;
+ qcom,mdss-pan-res = <480 854>;
+ qcom,mdss-pan-bpp = <24>;
+ qcom,mdss-pan-dest = "display_1";
+ qcom,mdss-pan-porch-values = <54 8 80 16 2 12>;
+ qcom,mdss-pan-underflow-clr = <0xff>;
+ qcom,mdss-pan-bl-levels = <1 255>;
+ qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+ qcom,mdss-pan-dsi-mode = <0>;
+ qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+ qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+ qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+ qcom,mdss-pan-dsi-traffic-mode = <1>;
+ qcom,mdss-pan-dsi-dst-format = <3>;
+ qcom,mdss-pan-dsi-vc = <0>;
+ qcom,mdss-pan-dsi-rgb-swap = <0>;
+ qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+ qcom,mdss-pan-dsi-dlane-swap = <1>;
+ qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+ qcom,mdss-pan-dsi-stream = <0>;
+ qcom,mdss-pan-dsi-mdp-tr = <0x0>;/*todo*/
+ qcom,mdss-pan-dsi-dma-tr = <0x04>;
+ qcom,mdss-pan-dsi-frame-rate = <60>;
+ qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
+ qcom,panel-phy-timingSettings = [8B 1F 14 00 45 4A
+ 19 23 23 03 04 00];
+ qcom,panel-phy-strengthCtrl = [ff 06];
+ qcom,panel-phy-bistCtrl = [03 03 00 00 0f 00];
+ qcom,panel-phy-laneConfig =
+ [80 45 00 00 01 66 /*lane0**/
+ 80 45 00 00 01 66 /*lane1*/
+ 80 45 00 00 01 66 /*lane2*/
+ 80 45 00 00 01 66 /*lane3*/
+ 40 67 00 00 01 88]; /*Clk*/
+
+ qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+ qcom,panel-on-cmds = [
+ 29 01 00 00 00 02
+ 00 00
+ 29 01 00 00 00 04
+ ff 80 09 01
+ 29 01 00 00 00 02
+ 00 80
+ 29 01 00 00 00 03
+ ff 80 09
+ 29 01 00 00 00 02
+ 00 80
+ 29 01 00 00 00 02
+ d6 48
+ 29 01 00 00 00 02
+ 00 03
+ 29 01 00 00 00 02
+ ff 01
+ 29 01 00 00 00 02
+ 00 B4
+ 29 01 00 00 00 02
+ C0 10
+ 29 01 00 00 00 02
+ 00 82
+ 29 01 00 00 00 02
+ C5 A3
+ 29 01 00 00 00 02
+ 00 90
+ 29 01 00 00 00 03
+ C5 96 87
+ 29 01 00 00 00 02
+ 00 00
+ 29 01 00 00 00 03
+ D8 74 72
+ 29 01 00 00 00 02
+ 00 00
+ 29 01 00 00 00 02
+ D9 56
+ 29 01 00 00 00 02
+ 00 00
+ 29 01 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 02
+ 00 00
+ 29 01 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 02
+ 00 81
+ 29 01 00 00 00 02
+ C1 77
+ 29 01 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 02
+ C1 EA
+ 29 01 00 00 00 02
+ 00 A1
+ 29 01 00 00 00 02
+ C1 08
+ 29 01 00 00 00 02
+ 00 89
+ 29 01 00 00 00 02
+ C4 08
+ 29 01 00 00 00 02
+ 00 81
+ 29 01 00 00 00 02
+ C4 83
+ 29 01 00 00 00 02
+ 00 92
+ 29 01 00 00 00 02
+ C5 01
+ 29 01 00 00 00 02
+ 00 B1
+ 29 01 00 00 00 02
+ C5 A9
+ 29 01 00 00 00 02
+ 00 92
+ 29 01 00 00 00 02
+ B3 45
+ 29 01 00 00 00 02
+ 00 90
+ 29 01 00 00 00 02
+ B3 02
+ 29 01 00 00 00 02
+ 00 80
+ 29 01 00 00 00 06
+ C0 00 58 00
+ 14 16
+ 29 01 00 00 00 02
+ 00 80
+ 29 01 00 00 00 02
+ C4 30
+ 29 01 00 00 00 02
+ 00 90
+ 29 01 00 00 00 07
+ C0 00 44 00
+ 00 00 03
+ 29 01 00 00 00 02
+ 00 A6
+ 29 01 00 00 00 04
+ C1 01 00 00
+ 29 01 00 00 00 02
+ 00 80
+ 29 01 00 00 00 0D
+ CE 87 03 00
+ 85 03 00 86
+ 03 00 84 03
+ 00
+ 29 01 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 0f
+ CE 38 03 03
+ 58 00 00 00
+ 38 02 03 59
+ 00 00 00
+ 29 01 00 00 00 02
+ 00 B0
+ 29 01 00 00 00 0f
+ CE 38 01 03
+ 5A 00 00 00
+ 38 00 03 5B
+ 00 00 00
+ 29 01 00 00 00 02
+ 00 C0
+ 29 01 00 00 00 0f
+ CE 30 00 03
+ 5C 00 00 00
+ 30 01 03 5D
+ 00 00 00
+ 29 01 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 0f
+ CE 30 02 03
+ 5E 00 00 00
+ 30 03 03 5F
+ 00 00 00
+ 29 01 00 00 00 02
+ 00 C7
+ 29 01 00 00 00 02
+ CF 00
+ 29 01 00 00 00 02
+ 00 C9
+ 29 01 00 00 00 02
+ CF 00
+ 29 01 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 02
+ CF 00
+ 29 01 00 00 00 02
+ 00 C4
+ 29 01 00 00 00 07
+ CB 04 04 04
+ 04 04 04
+ 29 01 00 00 00 02
+ 00 D9
+ 29 01 00 00 00 07
+ CB 04 04 04
+ 04 04 04
+ 29 01 00 00 00 02
+ 00 84
+ 29 01 00 00 00 07
+ CC 0C 0A 10
+ 0E 03 04
+ 29 01 00 00 00 02
+ 00 9E
+ 29 01 00 00 00 02
+ CC 0B
+ 29 01 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 06
+ CC 09 0F 0D
+ 01 02
+ 29 01 00 00 00 02
+ 00 B4
+ 29 01 00 00 00 07
+ CC 0D 0F 09
+ 0B 02 01
+ 29 01 00 00 00 02
+ 00 CE
+ 29 01 00 00 00 02
+ CC 0E
+ 29 01 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 06
+ CC 10 0A 0C
+ 04 03
+ 29 01 00 00 00 02
+ 00 00
+ 29 01 00 00 00 04
+ ff ff ff ff
+ 05 01 00 00 78 02
+ 11 00
+ 05 01 00 00 32 02
+ 29 00
+ ];
+ qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+ 05 01 00 00 78 02 10 00];
+ qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+ };
+};
diff --git a/arch/arm/boot/dts/mpq8092-iommu-domains.dtsi b/arch/arm/boot/dts/mpq8092-iommu-domains.dtsi
new file mode 100644
index 0000000..25fca2a
--- /dev/null
+++ b/arch/arm/boot/dts/mpq8092-iommu-domains.dtsi
@@ -0,0 +1,31 @@
+/* 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.
+ */
+
+&soc {
+ qcom,iommu-domains {
+ compatible = "qcom,iommu-domains";
+
+ venus_domain_ns: qcom,iommu-domain1 {
+ label = "venus_ns";
+ qcom,iommu-contexts = <&venus_ns>;
+ qcom,virtual-addr-pool = <0x40000000 0x3f000000
+ 0x7f000000 0x1000000>;
+ };
+
+ venus_domain_cp: qcom,iommu-domain2 {
+ label = "venus_cp";
+ qcom,iommu-contexts = <&venus_cp>;
+ qcom,virtual-addr-pool = <0x1000000 0x3f000000>;
+ qcom,secure-domain;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
index 3a86814..baec2d5 100644
--- a/arch/arm/boot/dts/mpq8092-iommu.dtsi
+++ b/arch/arm/boot/dts/mpq8092-iommu.dtsi
@@ -215,4 +215,17 @@
&vpu_iommu {
status = "ok";
+
+ interrupts = <0 300 0>;
+ vpu_cb_0: qcom,iommu-ctx@fdeec000 {
+ interrupts = <0 302 0>;
+ };
+
+ vpu_cb_1: qcom,iommu-ctx@fdeed000 {
+ interrupts = <0 302 0>;
+ };
+
+ vpu_cb_2: qcom,iommu-ctx@fdeee000 {
+ interrupts = <0 302 0>;
+ };
};
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 04f0945..2f67f3e 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -21,6 +21,7 @@
};
/include/ "mpq8092-iommu.dtsi"
+/include/ "mpq8092-iommu-domains.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "mpq8092-ion.dtsi"
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 54fce8f..4f3e461 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -610,5 +610,12 @@
label = "vibrator";
status = "disabled";
};
+
+ pwm@bc00 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xbc00 0x100>;
+ reg-names = "qpnp-lpg-channel-base";
+ qcom,channel-id = <0>;
+ };
};
};
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index 3935dbb..fb24a25 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -68,6 +68,57 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@18 {
+ cell-index = <4>;
+ reg = <0x18>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6c {
+ compatible = "qcom,ov12830";
+ reg = <0x6c>;
+ qcom,slave-id = <0x20 0x300a 0xc830>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator1>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "skuf_ov12830_p12v01c";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vaf-supply = <&pm8226_l15>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-op-mode = <120000 0 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 36 0>,
+ <&msmgpio 22 0>,
+ <&msmgpio 34 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-vdig = <3>;
+ qcom,gpio-af-pwdm = <4>;
+ qcom,gpio-req-tbl-num = <0 1 2 3 4>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY",
+ "CAM_VDIG",
+ "CAM_AF_PWDM";
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1f>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6d {
compatible = "qcom,ov9724";
reg = <0x6d>;
@@ -105,4 +156,45 @@
qcom,cci-master = <0>;
status = "ok";
};
+
+ qcom,camera@6a {
+ compatible = "qcom,ov5648";
+ reg = <0x6a>;
+ qcom,slave-id = <0x6c 0x300a 0x5648>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "skuf_ov5648_p5v23c";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 35 0>,
+ <&msmgpio 21 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-vdig = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY",
+ "CAM_VDIG";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
};
diff --git a/arch/arm/boot/dts/msm8226-camera.dtsi b/arch/arm/boot/dts/msm8226-camera.dtsi
index ec0092d..617d738 100644
--- a/arch/arm/boot/dts/msm8226-camera.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera.dtsi
@@ -125,15 +125,39 @@
qcom,gpio-tbl-flags = <1 1>;
qcom,gpio-tbl-label = "CCI_I2C_DATA0",
"CCI_I2C_CLK0";
- qcom,hw-thigh = <78>;
- qcom,hw-tlow = <114>;
- qcom,hw-tsu-sto = <28>;
- qcom,hw-tsu-sta = <28>;
- qcom,hw-thd-dat = <10>;
- qcom,hw-thd-sta = <77>;
- qcom,hw-tbuf = <118>;
- qcom,hw-scl-stretch-en = <0>;
- qcom,hw-trdhld = <6>;
- qcom,hw-tsp = <1>;
+ master0: qcom,cci-master0 {
+ status = "disabled";
+ };
+ master1: qcom,cci-master1 {
+ status = "disabled";
+ };
};
};
+
+&master0 {
+ qcom,hw-thigh = <78>;
+ qcom,hw-tlow = <114>;
+ qcom,hw-tsu-sto = <28>;
+ qcom,hw-tsu-sta = <28>;
+ qcom,hw-thd-dat = <10>;
+ qcom,hw-thd-sta = <77>;
+ qcom,hw-tbuf = <118>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <1>;
+ status = "ok";
+};
+
+&master1 {
+ qcom,hw-thigh = <78>;
+ qcom,hw-tlow = <114>;
+ qcom,hw-tsu-sto = <28>;
+ qcom,hw-tsu-sta = <28>;
+ qcom,hw-thd-dat = <10>;
+ qcom,hw-thd-sta = <77>;
+ qcom,hw-tbuf = <118>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <1>;
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index 7acb1fe..d94b41d 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -35,6 +35,7 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
+ synaptics,power-down;
};
};
@@ -75,7 +76,7 @@
compatible = "micrel,ks8851";
reg = <3>;
interrupt-parent = <&msmgpio>;
- interrupts = <0 115 0>;
+ interrupts = <115 0x8>;
spi-max-frequency = <4800000>;
rst-gpio = <&msmgpio 114 0>;
vdd-io-supply = <&pm8226_lvs1>;
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 11f6369..cbfdfc9 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -16,6 +16,8 @@
reg = <0xfc322000 0x1000>,
<0xfc37c000 0x3000>;
reg-names = "tmc-base", "bam-base";
+ interrupts = <0 166 0>;
+ interrupt-names = "byte-cntr-irq";
qcom,memory-reservation-type = "EBI1";
qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index b895c64..5f991fb 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -62,14 +62,54 @@
label = "MDSS DSI CTRL->0";
cell-index = <0>;
reg = <0xfd922800 0x600>;
+ qcom,mdss-fb-map = <&mdss_fb0>;
vdd-supply = <&pm8226_l15>;
vddio-supply = <&pm8226_l8>;
vdda-supply = <&pm8226_l4>;
- qcom,supply-names = "vdd", "vddio", "vdda";
- qcom,supply-min-voltage-level = <2800000 1800000 1200000>;
- qcom,supply-max-voltage-level = <2800000 1800000 1200000>;
- qcom,supply-peak-current = <150000 100000 100000>;
- qcom,mdss-fb-map = <&mdss_fb0>;
+ qcom,platform-reset-gpio = <&msmgpio 25 1>;
+ qcom,platform-te-gpio = <&msmgpio 24 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];
+ qcom,platform-lane-config = [00 00 00 00 00 00 00 01 97
+ 00 00 00 00 05 00 00 01 97
+ 00 00 00 00 0a 00 00 01 97
+ 00 00 00 00 0f 00 00 01 97
+ 00 c0 00 00 00 00 00 01 bb];
+ qcom,platform-reset-sequence = <1 20 0 1 1 20>;
+ qcom,platform-supply-entry1 {
+ qcom,supply-name = "vdd";
+ qcom,supply-min-voltage = <2800000>;
+ qcom,supply-max-voltage = <2800000>;
+ 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-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 = <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 = <0>;
+ };
};
qcom,mdss_wb_panel {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index ddb61bc..825e853 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -35,6 +35,7 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
+ synaptics,power-down;
};
};
@@ -86,7 +87,7 @@
compatible = "micrel,ks8851";
reg = <3>;
interrupt-parent = <&msmgpio>;
- interrupts = <0 115 0>;
+ interrupts = <115 0x8>;
spi-max-frequency = <4800000>;
rst-gpio = <&msmgpio 114 0>;
vdd-io-supply = <&pm8226_lvs1>;
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 0fc6af4..ef0a55e 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -101,62 +101,16 @@
50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
};
- qcom,lpm-resources {
- compatible = "qcom,lpm-resources";
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,lpm-resources@0 {
- reg = <0x0>;
- qcom,name = "vdd-dig";
- qcom,type = <0x61706d73>; /* "smpa" */
- qcom,id = <0x01>;
- qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <3>; /* SVS SOC */
- };
-
- qcom,lpm-resources@1 {
- reg = <0x1>;
- qcom,name = "vdd-mem";
- qcom,type = <0x616F646C>; /* "ldoa" */
- qcom,id = <0x03>;
- qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <3>; /* SVS SOC */
- };
-
- qcom,lpm-resources@2 {
- reg = <0x2>;
- qcom,name = "pxo";
- qcom,type = <0x306b6c63>; /* "clk0" */
- qcom,id = <0x00>;
- qcom,key = <0x62616e45>; /* "Enab" */
- qcom,init-value = "xo_on";
- };
-
- qcom,lpm-resources@3 {
- reg = <0x3>;
- qcom,name = "l2";
- qcom,local-resource-type;
- qcom,init-value = "l2_cache_active";
- };
- };
-
qcom,lpm-levels {
compatible = "qcom,lpm-levels";
+ qcom,default-l2-state = "l2_cache_active";
#address-cells = <1>;
#size-cells = <0>;
qcom,lpm-level@0 {
reg = <0x0>;
qcom,mode = "wfi";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <1>;
qcom,ss-power = <784>;
qcom,energy-overhead = <190000>;
@@ -166,14 +120,7 @@
qcom,lpm-level@1 {
reg = <0x1>;
qcom,mode = "standalone_pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <3000>;
qcom,ss-power = <725>;
qcom,energy-overhead = <99500>;
@@ -183,15 +130,8 @@
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_retention";
- qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <8000>;
+ qcom,latency-us = <20000>;
qcom,ss-power = <138>;
qcom,energy-overhead = <1208400>;
qcom,time-overhead = <9200>;
@@ -200,64 +140,12 @@
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <4>; /* NORMAL */
- qcom,vdd-mem-lower-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <9000>;
+ qcom,latency-us = <30000>;
qcom,ss-power = <110>;
qcom,energy-overhead = <1250300>;
qcom,time-overhead = <9500>;
};
-
- qcom,lpm-level@4 {
- reg = <0x4>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,latency-us = <16300>;
- qcom,ss-power = <63>;
- qcom,energy-overhead = <2128000>;
- qcom,time-overhead = <24200>;
- };
-
- qcom,lpm-level@5 {
- reg = <0x5>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <4>; /* NORMAL */
- qcom,vdd-mem-lower-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,latency-us = <24000>;
- qcom,ss-power = <10>;
- qcom,energy-overhead = <3202600>;
- qcom,time-overhead = <33000>;
- };
-
- qcom,lpm-level@6 {
- reg = <0x6>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <3>; /* SVS SOC */
- qcom,vdd-mem-lower-bound = <1>; /* RETENTION */
- qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
- qcom,latency-us = <26000>;
- qcom,ss-power = <2>;
- qcom,energy-overhead = <4252000>;
- qcom,time-overhead = <38000>;
- };
};
qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 669f54a..55d8691 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -31,6 +31,7 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
+ synaptics,power-down;
};
focaltech@38 {
compatible = "focaltech,5x06";
@@ -98,7 +99,7 @@
compatible = "micrel,ks8851";
reg = <3>;
interrupt-parent = <&msmgpio>;
- interrupts = <0 115 0>;
+ interrupts = <115 0x8>;
spi-max-frequency = <4800000>;
rst-gpio = <&msmgpio 114 0>;
vdd-io-supply = <&pm8226_lvs1>;
@@ -427,5 +428,17 @@
tapan_codec {
qcom,cdc-micbias1-ext-cap;
};
+};
+&pm8226_vadc {
+ chan@30 {
+ label = "batt_therm";
+ reg = <0x30>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <6>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 571ddc3..d587b77 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -43,7 +43,7 @@
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 = <1155000 1160000 1275000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1160000 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-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
index d36e93e..45c26c5 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
@@ -27,5 +27,6 @@
&soc {
qcom,mdss_dsi_hx8394a_720p_video {
status = "ok";
+ qcom,cont-splash-enabled;
};
};
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index cb5e299..936f87f 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -56,3 +56,60 @@
qcom,cdc-us-euro-gpios;
};
};
+
+&spmi_bus {
+ qcom,pm8226@0 {
+ qcom,leds@a300 {
+ status = "disabled";
+ };
+
+ qcom,leds@a500 {
+ status = "disabled";
+ };
+ };
+};
+
+&pm8226_mpps {
+ mpp@a300 { /* MPP 4 */
+ /* camera2_id */
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ /* camera_id */
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <1>; /* AMUX 6 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ };
+
+};
+
+&pm8226_vadc {
+ chan@13 {
+ label = "camera2_id";
+ reg = <0x13>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@15 {
+ label = "camera_id";
+ reg = <0x15>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8226-v1.dtsi b/arch/arm/boot/dts/msm8226-v1.dtsi
index 1db1f12..2833673 100644
--- a/arch/arm/boot/dts/msm8226-v1.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1.dtsi
@@ -22,3 +22,33 @@
qcom,sensors = <4>;
qcom,slope = <2901 2846 3038 2955>;
};
+
+&gdsc_venus {
+ qcom,skip-logic-collapse;
+ qcom,retain-periph;
+ qcom,retain-mem;
+};
+
+&gdsc_mdss {
+ qcom,skip-logic-collapse;
+ qcom,retain-periph;
+ qcom,retain-mem;
+};
+
+&gdsc_jpeg {
+ qcom,skip-logic-collapse;
+ qcom,retain-periph;
+ qcom,retain-mem;
+};
+
+&gdsc_vfe {
+ qcom,skip-logic-collapse;
+ qcom,retain-periph;
+ qcom,retain-mem;
+};
+
+&gdsc_oxili_cx {
+ qcom,skip-logic-collapse;
+ qcom,retain-periph;
+ qcom,retain-mem;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index f35e2e4..4cdbada 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -29,5 +29,6 @@
&soc {
qcom,mdss_dsi_hx8394a_720p_video {
status = "ok";
+ qcom,cont-splash-enabled;
};
};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index ac8b437..b34fb94 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -57,3 +57,60 @@
qcom,cdc-us-euro-gpios;
};
};
+
+&spmi_bus {
+ qcom,pm8226@0 {
+ qcom,leds@a300 {
+ status = "disabled";
+ };
+
+ qcom,leds@a500 {
+ status = "disabled";
+ };
+ };
+};
+
+&pm8226_mpps {
+ mpp@a300 { /* MPP 4 */
+ /* camera2_id */
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ /* camera_id */
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <1>; /* AMUX 6 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ };
+
+};
+
+&pm8226_vadc {
+ chan@13 {
+ label = "camera2_id";
+ reg = <0x13>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@15 {
+ label = "camera_id";
+ reg = <0x15>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index b44cb681..1dab78a 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -42,7 +42,7 @@
&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 = <1160000 1160000 1280000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1160000 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/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index ce4ada5..b0c0191 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -42,6 +42,7 @@
atmel,display-coords = <0 0 480 800>;
atmel,i2c-pull-up;
atmel,no-force-update;
+ atmel,no-lpm-support;
atmel,cfg_1 {
atmel,family-id = <0x81>;
atmel,variant-id = <0x15>;
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index c531740..d31a65c 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -101,62 +101,16 @@
50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
};
- qcom,lpm-resources {
- compatible = "qcom,lpm-resources";
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,lpm-resources@0 {
- reg = <0x0>;
- qcom,name = "vdd-dig";
- qcom,type = <0x61706d73>; /* "smpa" */
- qcom,id = <0x01>;
- qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <3>; /* SVS SOC */
- };
-
- qcom,lpm-resources@1 {
- reg = <0x1>;
- qcom,name = "vdd-mem";
- qcom,type = <0x616F646C>; /* "ldoa" */
- qcom,id = <0x03>;
- qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <3>; /* SVS SOC */
- };
-
- qcom,lpm-resources@2 {
- reg = <0x2>;
- qcom,name = "pxo";
- qcom,type = <0x306b6c63>; /* "clk0" */
- qcom,id = <0x00>;
- qcom,key = <0x62616e45>; /* "Enab" */
- qcom,init-value = "xo_on";
- };
-
- qcom,lpm-resources@3 {
- reg = <0x3>;
- qcom,name = "l2";
- qcom,local-resource-type;
- qcom,init-value = "l2_cache_active";
- };
- };
-
qcom,lpm-levels {
compatible = "qcom,lpm-levels";
+ qcom,default-l2-state = "l2_cache_active";
#address-cells = <1>;
#size-cells = <0>;
qcom,lpm-level@0 {
reg = <0x0>;
qcom,mode = "wfi";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <1>;
qcom,ss-power = <784>;
qcom,energy-overhead = <190000>;
@@ -166,14 +120,7 @@
qcom,lpm-level@1 {
reg = <0x1>;
qcom,mode = "standalone_pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <3000>;
qcom,ss-power = <725>;
qcom,energy-overhead = <99500>;
@@ -183,15 +130,8 @@
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_retention";
- qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <8000>;
+ qcom,latency-us = <20000>;
qcom,ss-power = <138>;
qcom,energy-overhead = <1208400>;
qcom,time-overhead = <9200>;
@@ -200,64 +140,12 @@
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <4>; /* NORMAL */
- qcom,vdd-mem-lower-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <9000>;
+ qcom,latency-us = <30000>;
qcom,ss-power = <110>;
qcom,energy-overhead = <1250300>;
qcom,time-overhead = <9500>;
};
-
- qcom,lpm-level@4 {
- reg = <0x4>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <4>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,latency-us = <16300>;
- qcom,ss-power = <63>;
- qcom,energy-overhead = <2128000>;
- qcom,time-overhead = <24200>;
- };
-
- qcom,lpm-level@5 {
- reg = <0x5>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <4>; /* NORMAL */
- qcom,vdd-mem-lower-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,latency-us = <24000>;
- qcom,ss-power = <10>;
- qcom,energy-overhead = <3202600>;
- qcom,time-overhead = <33000>;
- };
-
- qcom,lpm-level@6 {
- reg = <0x6>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <3>; /* SVS SOC */
- qcom,vdd-mem-lower-bound = <1>; /* RETENTION */
- qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
- qcom,latency-us = <26000>;
- qcom,ss-power = <2>;
- qcom,energy-overhead = <4252000>;
- qcom,time-overhead = <38000>;
- };
};
qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
index 220f642..aeaf8ca 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
@@ -40,3 +40,8 @@
qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
};
};
+
+&pm8110_bms {
+ status = "ok";
+ qcom,batt-type = <5>;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
index 24c2490..c435038 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8610-qrd.dtsi"
+/include/ "dsi-v2-panel-otm8018b-fwvga-video.dtsi"
/include/ "msm8612-qrd-camera-sensor.dtsi"
/ {
@@ -78,4 +79,8 @@
fsl,sensors-position = <5>;
};
};
+
+ qcom,dsi_v2_otm8018b_fwvga_video {
+ status = "ok";
+ };
};
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index cf54098..34cbd99 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -43,9 +43,9 @@
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 = <1150000 1150000 1275000>;
- qcom,pvs-corner-ceiling-nom = <1075000 1075000 1200000>;
- qcom,pvs-corner-ceiling-fast = <1000000 1000000 1140000>;
+ 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 = <&pm8110_s2>;
vdd-mx-supply = <&pm8110_l3_ao>;
@@ -54,12 +54,12 @@
qcom,cpr-ref-clk = <19200>;
qcom,cpr-timer-delay = <5000>;
- qcom,cpr-timer-cons-up = <1>;
+ qcom,cpr-timer-cons-up = <0>;
qcom,cpr-timer-cons-down = <2>;
qcom,cpr-irq-line = <0>;
qcom,cpr-step-quotient = <15>;
- qcom,cpr-up-threshold = <1>;
- qcom,cpr-down-threshold = <2>;
+ qcom,cpr-up-threshold = <0>;
+ qcom,cpr-down-threshold = <10>;
qcom,cpr-idle-clocks = <5>;
qcom,cpr-gcnt-time = <1>;
qcom,vdd-apc-step-up-limit = <1>;
@@ -77,6 +77,8 @@
qcom,cpr-fuse-redun-bp-scheme = <25>;
qcom,cpr-fuse-redun-target-quot = <32 12 0>;
qcom,cpr-fuse-redun-ro-sel = <44 26 29>;
+
+ qcom,cpr-enable;
};
};
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 456b079..4be2b38 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -196,18 +196,42 @@
qcom,gpio-tbl-num = <0 1 2 3>;
qcom,gpio-tbl-flags = <1 1 1 1>;
qcom,gpio-tbl-label = "CCI_I2C_DATA0",
- "CCI_I2C_CLK0",
- "CCI_I2C_DATA1",
- "CCI_I2C_CLK1";
- qcom,hw-thigh = <78>;
- qcom,hw-tlow = <114>;
- qcom,hw-tsu-sto = <28>;
- qcom,hw-tsu-sta = <28>;
- qcom,hw-thd-dat = <10>;
- qcom,hw-thd-sta = <77>;
- qcom,hw-tbuf = <118>;
- qcom,hw-scl-stretch-en = <0>;
- qcom,hw-trdhld = <6>;
- qcom,hw-tsp = <1>;
+ "CCI_I2C_CLK0",
+ "CCI_I2C_DATA1",
+ "CCI_I2C_CLK1";
+ master0: qcom,cci-master0 {
+ status = "disabled";
+ };
+ master1: qcom,cci-master1 {
+ status = "disabled";
+ };
};
};
+
+&master0 {
+ qcom,hw-thigh = <78>;
+ qcom,hw-tlow = <114>;
+ qcom,hw-tsu-sto = <28>;
+ qcom,hw-tsu-sta = <28>;
+ qcom,hw-thd-dat = <10>;
+ qcom,hw-thd-sta = <77>;
+ qcom,hw-tbuf = <118>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <1>;
+ status = "ok";
+};
+
+&master1 {
+ qcom,hw-thigh = <78>;
+ qcom,hw-tlow = <114>;
+ qcom,hw-tsu-sto = <28>;
+ qcom,hw-tsu-sta = <28>;
+ qcom,hw-thd-dat = <10>;
+ qcom,hw-thd-sta = <77>;
+ qcom,hw-tbuf = <118>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <1>;
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index e41adac..9fd0cd9 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -16,6 +16,8 @@
reg = <0xfc322000 0x1000>,
<0xfc37c000 0x3000>;
reg-names = "tmc-base", "bam-base";
+ interrupts = <0 166 0>;
+ interrupt-names = "byte-cntr-irq";
qcom,memory-reservation-type = "EBI1";
qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 46bb71a..f8a8fa6 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -86,6 +86,50 @@
vddio-supply = <&pm8941_l12>;
vdda-supply = <&pm8941_l2>;
qcom,mdss-fb-map = <&mdss_fb0>;
+ qcom,platform-reset-gpio = <&pm8941_gpios 19 1>;
+ qcom,platform-enable-gpio = <&msmgpio 58 1>;
+ qcom,platform-reset-sequence = <1 20 0 200 1 20 2>;
+ 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];
+ qcom,platform-lane-config = [00 00 00 00 00 00 00 01 97
+ 00 00 00 00 05 00 00 01 97
+ 00 00 00 00 0a 00 00 01 97
+ 00 00 00 00 0f 00 00 01 97
+ 00 c0 00 00 00 00 00 01 bb];
+ qcom,platform-supply-entry1 {
+ qcom,supply-name = "vdd";
+ qcom,supply-min-voltage = <3000000>;
+ qcom,supply-max-voltage = <3000000>;
+ 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 = <0>;
+ };
+ 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 = <20>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <0>;
+ };
+ qcom,platform-supply-entry3 {
+ qcom,supply-name = "vdda";
+ 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 = <0>;
+ qcom,supply-pre-off-sleep = <0>;
+ qcom,supply-post-off-sleep = <0>;
+ };
};
mdss_dsi1: qcom,mdss_dsi@fd922e00 {
@@ -145,5 +189,6 @@
qcom,panel-pwm-period = <53>;
status = "disable";
qcom,mdss-fb-map = <&mdss_fb0>;
+ gpio-panel-hpd = <&msmgpio 102 0>;
};
};
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index 288a703..7362b64 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -129,64 +129,16 @@
50 02 32 50 0f];
};
- qcom,lpm-resources {
- compatible = "qcom,lpm-resources";
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,lpm-resources@0 {
- reg = <0x0>;
- qcom,name = "vdd-dig";
- qcom,type = <0x62706d73>; /* "smpb" */
- qcom,id = <0x02>;
- qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <6>; /* Super Turbo */
- };
-
- qcom,lpm-resources@1 {
- reg = <0x1>;
- qcom,name = "vdd-mem";
- qcom,type = <0x62706d73>; /* "smpb" */
- qcom,id = <0x01>;
- qcom,key = <0x7675>; /* "uv" */
- qcom,init-value = <1050000>; /* Super Turbo */
- };
-
- qcom,lpm-resources@2 {
- reg = <0x2>;
- qcom,name = "pxo";
- qcom,type = <0x306b6c63>; /* "clk0" */
- qcom,id = <0x00>;
- qcom,key = <0x62616e45>; /* "Enab" */
- qcom,init-value = "xo_on";
- };
-
- qcom,lpm-resources@3 {
- reg = <0x3>;
- qcom,name = "l2";
- qcom,local-resource-type;
- qcom,init-value = "l2_cache_retention";
- };
- };
-
qcom,lpm-levels {
compatible = "qcom,lpm-levels";
+ qcom,default-l2-state = "l2_cache_retention";
#address-cells = <1>;
#size-cells = <0>;
- qcom,use-qtimer;
-
qcom,lpm-level@0 {
reg = <0x0>;
qcom,mode = "wfi";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <1>;
qcom,ss-power = <784>;
qcom,energy-overhead = <190000>;
@@ -196,14 +148,7 @@
qcom,lpm-level@1 {
reg = <0x1>;
qcom,mode = "retention";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <75>;
qcom,ss-power = <735>;
qcom,energy-overhead = <77341>;
@@ -214,14 +159,7 @@
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "standalone_pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <95>;
qcom,ss-power = <725>;
qcom,energy-overhead = <99500>;
@@ -231,15 +169,8 @@
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <2000>;
+ qcom,latency-us = <20000>;
qcom,ss-power = <138>;
qcom,energy-overhead = <1208400>;
qcom,time-overhead = <3200>;
@@ -248,79 +179,12 @@
qcom,lpm-level@4 {
reg = <0x4>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <3000>;
+ qcom,latency-us = <30000>;
qcom,ss-power = <110>;
qcom,energy-overhead = <1250300>;
qcom,time-overhead = <3500>;
};
-
- qcom,lpm-level@5 {
- reg = <0x5>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,latency-us = <3000>;
- qcom,ss-power = <68>;
- qcom,energy-overhead = <1350200>;
- qcom,time-overhead = <4000>;
- };
-
- qcom,lpm-level@6 {
- reg = <0x6>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,latency-us = <10300>;
- qcom,ss-power = <63>;
- qcom,energy-overhead = <2128000>;
- qcom,time-overhead = <18200>;
- };
-
- qcom,lpm-level@7 {
- reg = <0x7>;
- qcom,mode= "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
- qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,latency-us = <18000>;
- qcom,ss-power = <10>;
- qcom,energy-overhead = <3202600>;
- qcom,time-overhead = <27000>;
- };
-
- qcom,lpm-level@8 {
- reg = <0x8>;
- qcom,mode= "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
- qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
- qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
- qcom,latency-us = <20000>;
- qcom,ss-power = <2>;
- qcom,energy-overhead = <4252000>;
- qcom,time-overhead = <32000>;
- };
};
qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index cfacac6..7b801da 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -65,6 +65,7 @@
/* CoreSight */
&tmc_etr {
qcom,reset-flush-race;
+ qcom,byte-cntr-absent;
};
&stm {
diff --git a/arch/arm/boot/dts/msm8974-v2-iommu.dtsi b/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
index 03f7e80..5efa17d 100644
--- a/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
@@ -42,14 +42,14 @@
0x2034
0x2038>;
- qcom,iommu-bfb-data = <0xFFFFFFFF
- 0xFFFFFFFF
- 0x00000004
- 0x00000008
- 0x00000000
- 0x00013205
- 0x00004000
- 0x00014020
+ qcom,iommu-bfb-data = <0xffffffff
+ 0xffffffff
+ 0x4
+ 0x8
+ 0x0
+ 0x13205
+ 0x4000
+ 0x14020
0x0
0x94
0x114
@@ -116,8 +116,8 @@
0x2010
0x2014>;
- qcom,iommu-bfb-data = <0x3FFF
- 0x00000000
+ qcom,iommu-bfb-data = <0xffff
+ 0x0
0x4
0x4
0x0
@@ -125,8 +125,8 @@
0x10
0x50
0x0
- 0x00002804
- 0x00009614
+ 0x2804
+ 0x9614
0x0
0x0
0x0
@@ -157,14 +157,14 @@
0x201c
0x2020>;
- qcom,iommu-bfb-data = <0xFFFFF
- 0x00000000
- 0x00000004
- 0x00000010
- 0x00000000
- 0x00006800
- 0x00006221
- 0x00016231
+ qcom,iommu-bfb-data = <0xffffffff
+ 0x0
+ 0x4
+ 0x10
+ 0x0
+ 0x6800
+ 0x6221
+ 0x16231
0x0
0x34
0x74
@@ -197,14 +197,14 @@
0x2414
0x2008>;
- qcom,iommu-bfb-data = <0x00000003
+ qcom,iommu-bfb-data = <0x3
0x0
- 0x00000004
- 0x00000010
- 0x00000000
- 0x00000000
- 0x00000000
- 0x00000020
+ 0x4
+ 0x10
+ 0x0
+ 0x0
+ 0x0
+ 0x20
0x0
0x1
0x81
@@ -236,7 +236,7 @@
0x2020>;
qcom,iommu-bfb-data = <0xffffffff
- 0x00000000
+ 0x0
0x4
0x8
0x0
@@ -244,8 +244,8 @@
0x20
0x78
0x0
- 0x00003c08
- 0x0000b41e
+ 0x3c08
+ 0xb41e
0x0
0x0
0x0
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index a162bb7..1235c6e 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -125,64 +125,16 @@
50 02 32 50 0f];
};
- qcom,lpm-resources {
- compatible = "qcom,lpm-resources";
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,lpm-resources@0 {
- reg = <0x0>;
- qcom,name = "vdd-dig";
- qcom,type = <0x62706d73>; /* "smpb" */
- qcom,id = <0x02>;
- qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <6>; /* Super Turbo */
- };
-
- qcom,lpm-resources@1 {
- reg = <0x1>;
- qcom,name = "vdd-mem";
- qcom,type = <0x62706d73>; /* "smpb" */
- qcom,id = <0x01>;
- qcom,key = <0x7675>; /* "uv" */
- qcom,init-value = <1050000>; /* Super Turbo */
- };
-
- qcom,lpm-resources@2 {
- reg = <0x2>;
- qcom,name = "pxo";
- qcom,type = <0x306b6c63>; /* "clk0" */
- qcom,id = <0x00>;
- qcom,key = <0x62616e45>; /* "Enab" */
- qcom,init-value = "xo_on";
- };
-
- qcom,lpm-resources@3 {
- reg = <0x3>;
- qcom,name = "l2";
- qcom,local-resource-type;
- qcom,init-value = "l2_cache_retention";
- };
- };
-
qcom,lpm-levels {
compatible = "qcom,lpm-levels";
+ qcom,default-l2-state = "l2_cache_retention";
#address-cells = <1>;
#size-cells = <0>;
- qcom,use-qtimer;
-
qcom,lpm-level@0 {
reg = <0x0>;
qcom,mode = "wfi";
- qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
+ qcom,l2 = "l2_cache_retention";
qcom,latency-us = <1>;
qcom,ss-power = <715>;
qcom,energy-overhead = <17700>;
@@ -192,14 +144,7 @@
qcom,lpm-level@1 {
reg = <0x1>;
qcom,mode = "retention";
- qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
+ qcom,l2 = "l2_cache_retention";
qcom,latency-us = <35>;
qcom,ss-power = <542>;
qcom,energy-overhead = <34920>;
@@ -210,14 +155,7 @@
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "standalone_pc";
- qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
+ qcom,l2 = "l2_cache_retention";
qcom,latency-us = <300>;
qcom,ss-power = <476>;
qcom,energy-overhead = <225300>;
@@ -227,32 +165,19 @@
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "standalone_pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <300>;
+ qcom,latency-us = <320>;
qcom,ss-power = <476>;
qcom,energy-overhead = <225300>;
- qcom,time-overhead = <350>;
+ qcom,time-overhead = <375>;
};
qcom,lpm-level@4 {
reg = <0x4>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
qcom,gpio-detectable;
- qcom,latency-us = <2817>;
+ qcom,latency-us = <20000>;
qcom,ss-power = <163>;
qcom,energy-overhead = <1577736>;
qcom,time-overhead = <5067>;
@@ -261,64 +186,12 @@
qcom,lpm-level@5 {
reg = <0x5>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <3922>;
+ qcom,latency-us = <30000>;
qcom,ss-power = <83>;
qcom,energy-overhead = <2274420>;
qcom,time-overhead = <6605>;
};
-
- qcom,lpm-level@6 {
- reg = <0x6>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,latency-us = <4922>;
- qcom,ss-power = <68>;
- qcom,energy-overhead = <2568180>;
- qcom,time-overhead = <8812>;
- };
-
- qcom,lpm-level@7 {
- reg = <0x7>;
- qcom,mode= "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
- qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,latency-us = <5890>;
- qcom,ss-power = <60>;
- qcom,energy-overhead = <2675900>;
- qcom,time-overhead = <10140>;
- };
-
- qcom,lpm-level@8 {
- reg = <0x8>;
- qcom,mode= "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
- qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
- qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
- qcom,latency-us = <8500>;
- qcom,ss-power = <18>;
- qcom,energy-overhead = <3286600>;
- qcom,time-overhead = <15760>;
- };
};
qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 60472c8..4a903b7 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -16,6 +16,8 @@
reg = <0xfc322000 0x1000>,
<0xfc37c000 0x3000>;
reg-names = "tmc-base", "bam-base";
+ interrupts = <0 166 0>;
+ interrupt-names = "byte-cntr-irq";
qcom,memory-reservation-type = "EBI1";
qcom,memory-reservation-size = <0x20000>; /* 128K EBI1 buffer */
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index e18e143..7989f2b 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -28,57 +28,16 @@
3e 0f];
};
- qcom,lpm-resources {
- compatible = "qcom,lpm-resources";
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,lpm-resources@0 {
- reg = <0x0>;
- qcom,name = "vdd-dig";
- qcom,type = <0x616F646C>; /* "ldoa" */
- qcom,id = <0x0A>;
- qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <5>; /* Super Turbo */
- };
-
- qcom,lpm-resources@1 {
- reg = <0x1>;
- qcom,name = "vdd-mem";
- qcom,type = <0x616F646C>; /* "ldoa" */
- qcom,id = <0x0C>;
- qcom,key = <0x7675>; /* "uv" */
- qcom,init-value = <1050000>; /* Super Turbo */
- };
-
- qcom,lpm-resources@2 {
- reg = <0x2>;
- qcom,name = "pxo";
- qcom,type = <0x306b6c63>; /* "clk0" */
- qcom,id = <0x00>;
- qcom,key = <0x62616e45>; /* "Enab" */
- qcom,init-value = "xo_on";
- };
- };
-
qcom,lpm-levels {
compatible = "qcom,lpm-levels";
+ qcom,no-l2-saw;
#address-cells = <1>;
#size-cells = <0>;
- qcom,use-qtimer;
-
qcom,lpm-level@0 {
reg = <0x0>;
qcom,mode = "wfi";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <100>;
qcom,ss-power = <8000>;
qcom,energy-overhead = <100000>;
@@ -88,14 +47,7 @@
qcom,lpm-level@1 {
reg = <0x1>;
qcom,mode = "standalone_pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
qcom,latency-us = <2000>;
qcom,ss-power = <5000>;
qcom,energy-overhead = <60100000>;
@@ -105,15 +57,8 @@
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <3500>;
+ qcom,latency-us = <20000>;
qcom,ss-power = <5000>;
qcom,energy-overhead = <60350000>;
qcom,time-overhead = <6300>;
@@ -122,66 +67,12 @@
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,irqs-detectable;
- qcom,gpio-detectable;
- qcom,latency-us = <4500>;
+ qcom,latency-us = <30000>;
qcom,ss-power = <5000>;
qcom,energy-overhead = <60350000>;
qcom,time-overhead = <7300>;
};
-
- qcom,lpm-level@4 {
- reg = <0x4>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
- qcom,irqs-detectable;
- qcom,latency-us = <6800>;
- qcom,ss-power = <2000>;
- qcom,energy-overhead = <71850000>;
- qcom,time-overhead = <13300>;
- };
-
- qcom,lpm-level@5 {
- reg = <0x5>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
- qcom,irqs-detectable;
- qcom,latency-us = <8000>;
- qcom,ss-power = <1800>;
- qcom,energy-overhead = <71950000>;
- qcom,time-overhead = <15300>;
- };
-
- qcom,lpm-level@6 {
- reg = <0x6>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
- qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
- qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
- qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
- qcom,latency-us = <9800>;
- qcom,ss-power = <0>;
- qcom,energy-overhead = <76350000>;
- qcom,time-overhead = <28300>;
- };
};
qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm9625-regulator.dtsi b/arch/arm/boot/dts/msm9625-regulator.dtsi
index ee48b7f..eb56d1c 100644
--- a/arch/arm/boot/dts/msm9625-regulator.dtsi
+++ b/arch/arm/boot/dts/msm9625-regulator.dtsi
@@ -194,6 +194,15 @@
qcom,use-voltage-corner;
status = "okay";
};
+ pm8019_l10_floor_corner: regulator-l10-floor-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8019_l10_floor_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-floor-corner;
+ qcom,always-send-voltage;
+ };
};
rpm-regulator-ldoa11 {
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index b238ba5..daf774b 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -48,6 +48,7 @@
/* CoreSight */
&tmc_etr {
qcom,reset-flush-race;
+ qcom,byte-cntr-absent;
};
&stm {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 5520401..59d7ba0 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -529,10 +529,10 @@
qcom,freq-control-mask = <0x0>;
qcom,vdd-restriction-temp = <5>;
qcom,vdd-restriction-temp-hysteresis = <10>;
- vdd_dig-supply = <&pm8019_l10_corner>;
+ vdd-dig-supply = <&pm8019_l10_floor_corner>;
qcom,vdd-dig-rstr{
- qcom,vdd-rstr-reg = "vdd_dig";
+ qcom,vdd-rstr-reg = "vdd-dig";
qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
qcom,min-level = <1>; /* No Request */
};
diff --git a/arch/arm/boot/dts/msmkrypton-smp2p.dtsi b/arch/arm/boot/dts/msmkrypton-smp2p.dtsi
new file mode 100644
index 0000000..fcd2880
--- /dev/null
+++ b/arch/arm/boot/dts/msmkrypton-smp2p.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.
+ */
+&soc {
+ qcom,smp2p-modem {
+ compatible = "qcom,smp2p";
+ reg = <0xf9011008 0x4>;
+ qcom,remote-pid = <1>;
+ qcom,irq-bitmask = <0x4000>;
+ interrupts = <0 27 1>;
+ };
+
+ qcom,smp2p-adsp {
+ compatible = "qcom,smp2p";
+ reg = <0xf9011008 0x4>;
+ qcom,remote-pid = <2>;
+ qcom,irq-bitmask = <0x400>;
+ interrupts = <0 158 1>;
+ };
+
+ smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <7>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_7_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_7_in";
+ gpios = <&smp2pgpio_smp2p_7_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <7>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_7_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_7_out";
+ gpios = <&smp2pgpio_smp2p_7_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+ gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+ gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+ gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+ gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+ };
+
+};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 3743c54..dd5b7a0 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -20,6 +20,8 @@
soc: soc { };
};
+/include/ "msmkrypton-smp2p.dtsi"
+
&soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -151,4 +153,61 @@
<&msmgpio 20 0>; /* MOSI */
cs-gpios = <&msmgpio 22 0>;
};
+
+ qcom,ipc-spinlock@fd484000 {
+ compatible = "qcom,ipc-spinlock-sfpb";
+ reg = <0xfd484000 0x400>;
+ qcom,num-locks = <8>;
+ };
+
+ qcom,smem@2200000 {
+ compatible = "qcom,smem";
+ reg = <0x2200000 0x100000>,
+ <0xf9011000 0x1000>,
+ <0xfc428000 0x4000>;
+ reg-names = "smem", "irq-reg-base", "aux-mem1";
+
+ qcom,smd-modem {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <0>;
+ qcom,smd-irq-offset = <0x8>;
+ qcom,smd-irq-bitmask = <0x1000>;
+ qcom,pil-string = "modem";
+ interrupts = <0 25 1>;
+ };
+
+ qcom,smsm-modem {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <0>;
+ qcom,smsm-irq-offset = <0x8>;
+ qcom,smsm-irq-bitmask = <0x2000>;
+ interrupts = <0 26 1>;
+ };
+
+ qcom,smd-adsp {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <1>;
+ qcom,smd-irq-offset = <0x8>;
+ qcom,smd-irq-bitmask = <0x100>;
+ qcom,pil-string = "adsp";
+ interrupts = <0 156 1>;
+ };
+
+ qcom,smsm-adsp {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <1>;
+ qcom,smsm-irq-offset = <0x8>;
+ qcom,smsm-irq-bitmask = <0x200>;
+ interrupts = <0 157 1>;
+ };
+
+ qcom,smd-rpm {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <15>;
+ qcom,smd-irq-offset = <0x8>;
+ qcom,smd-irq-bitmask = <0x1>;
+ interrupts = <0 168 1>;
+ qcom,irq-no-suspend;
+ };
+ };
};
diff --git a/arch/arm/common/cpaccess.c b/arch/arm/common/cpaccess.c
index 3572e5a..cca0b39 100644
--- a/arch/arm/common/cpaccess.c
+++ b/arch/arm/common/cpaccess.c
@@ -385,6 +385,12 @@
}
sema_init(&cp_sem, 1);
+
+ /*
+ * Make the target instruction writeable when built as a module
+ */
+ set_memory_rw((unsigned long)&cpaccess_dummy_inst & PAGE_MASK, 1);
+
return 0;
exit1:
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 2965607..fef6543 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -52,6 +52,8 @@
CONFIG_MSM_RPM_REGULATOR_SMD=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_VENUS=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
@@ -404,3 +406,4 @@
CONFIG_CORESIGHT_FUNNEL=y
CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
+CONFIG_USB_BAM=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 452cd8a..f49b5f7 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -56,6 +56,7 @@
CONFIG_MSM_PIL_VENUS=y
CONFIG_MSM_PIL_PRONTO=y
CONFIG_MSM_TZ_LOG=y
+CONFIG_MSM_SMCMOD=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
@@ -222,6 +223,7 @@
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_KS8851=y
# CONFIG_MSM_RMNET is not set
CONFIG_MSM_RMNET_BAM=y
CONFIG_PPP=y
@@ -287,6 +289,7 @@
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_MSM_CAMERA is not set
CONFIG_OV8825=y
+CONFIG_OV12830=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CPP=y
CONFIG_MSM_CCI=y
@@ -297,6 +300,7 @@
CONFIG_MSMB_CAMERA=y
CONFIG_OV9724=y
CONFIG_MT9M114=y
+CONFIG_OV5648=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_WFD=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 6c59c38..aced8f2 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -56,6 +56,7 @@
CONFIG_MSM_PIL_VENUS=y
CONFIG_MSM_PIL_PRONTO=y
CONFIG_MSM_TZ_LOG=y
+CONFIG_MSM_SMCMOD=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
@@ -224,6 +225,7 @@
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
+CONFIG_KS8851=y
# CONFIG_MSM_RMNET is not set
CONFIG_MSM_RMNET_BAM=y
CONFIG_PPP=y
@@ -291,6 +293,7 @@
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_MSM_CAMERA is not set
CONFIG_OV8825=y
+CONFIG_OV12830=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CPP=y
CONFIG_MSM_CCI=y
@@ -301,6 +304,7 @@
CONFIG_MSMB_CAMERA=y
CONFIG_OV9724=y
CONFIG_MT9M114=y
+CONFIG_OV5648=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_WFD=y
@@ -455,6 +459,7 @@
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_LL=y
CONFIG_EARLY_PRINTK=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 8307622..0db08db 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -278,6 +278,8 @@
CONFIG_OV8825=y
CONFIG_s5k4e1=y
CONFIG_HI256=y
+CONFIG_OV12830=y
+CONFIG_OV5648=y
CONFIG_MSM_CAMERA_SENSOR=y
# CONFIG_MSM_CPP is not set
CONFIG_MSM_CCI=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 72392f3..cfd346e 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -71,6 +71,7 @@
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_XPU_ERR_FATAL=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -276,6 +277,7 @@
CONFIG_OV8825=y
CONFIG_s5k4e1=y
CONFIG_HI256=y
+CONFIG_OV12830=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CCI=y
CONFIG_MSM_CSIPHY=y
@@ -287,6 +289,7 @@
CONFIG_OV9724=y
CONFIG_SP1628=y
CONFIG_GC0339=y
+CONFIG_OV5648=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_WFD=y
@@ -419,6 +422,7 @@
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_KEYS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 8447dd55..0c28cc4 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -499,6 +499,7 @@
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_CPU_FREQ_SWITCH_PROFILER=y
CONFIG_DYNAMIC_DEBUG=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_LL=y
CONFIG_EARLY_PRINTK=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index 6471673..9a5aaf0 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -115,6 +115,7 @@
CONFIG_NETFILTER_XT_MATCH_ESP=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_IP_SET=y
CONFIG_NF_CONNTRACK_IPV4=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 863e14f..3f34690 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -119,6 +119,7 @@
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_IP_SET=y
CONFIG_NF_CONNTRACK_IPV4=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
index 6609c32..b04acb5 100644
--- a/arch/arm/configs/msmkrypton_defconfig
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -38,7 +38,12 @@
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
CONFIG_MSM_IPC_LOGGING=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_UARTDM_Core_v14=y
CONFIG_NO_HZ=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 03fb936..5c8b3bf4 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -320,4 +320,12 @@
.size \name , . - \name
.endm
+ .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
+#ifndef CONFIG_CPU_USE_DOMAINS
+ adds \tmp, \addr, #\size - 1
+ sbcccs \tmp, \tmp, \limit
+ bcs \bad
+#endif
+ .endm
+
#endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/include/asm/smcmod.h b/arch/arm/include/asm/smcmod.h
index 06918c4..6225c1e 100644
--- a/arch/arm/include/asm/smcmod.h
+++ b/arch/arm/include/asm/smcmod.h
@@ -108,6 +108,45 @@
uint32_t return_val; /* out */
} __packed;
+/**
+ * struct smcmod_decrypt_req - used to decrypt image fragments.
+ * @service_id - requested service.
+ * @command_id - requested command.
+ * @operation - specifies metadata parsing or image fragment decrypting.
+ * @request - describes request parameters depending on operation.
+ * @response - this is the response of the request.
+ */
+struct smcmod_decrypt_req {
+ uint32_t service_id;
+ uint32_t command_id;
+#define SMCMOD_DECRYPT_REQ_OP_METADATA 1
+#define SMCMOD_DECRYPT_REQ_OP_IMG_FRAG 2
+ uint32_t operation;
+ union {
+ struct {
+ uint32_t len;
+ uint32_t ion_fd;
+ } metadata;
+ struct {
+ uint32_t ctx_id;
+ uint32_t last_frag;
+ uint32_t frag_len;
+ uint32_t ion_fd;
+ uint32_t offset;
+ } img_frag;
+ } request;
+ union {
+ struct {
+ uint32_t status;
+ uint32_t ctx_id;
+ uint32_t end_offset;
+ } metadata;
+ struct {
+ uint32_t status;
+ } img_frag;
+ } response;
+};
+
#define SMCMOD_IOC_MAGIC 0x97
/* Number chosen to avoid any conflicts */
@@ -120,4 +159,7 @@
#define SMCMOD_IOCTL_SEND_MSG_DIGEST_CMD \
_IOWR(SMCMOD_IOC_MAGIC, 35, struct smcmod_msg_digest_req)
#define SMCMOD_IOCTL_GET_VERSION _IOWR(SMCMOD_IOC_MAGIC, 36, uint32_t)
+#define SMCMOD_IOCTL_SEND_DECRYPT_CMD \
+ _IOWR(SMCMOD_IOC_MAGIC, 37, struct smcmod_decrypt_req)
+
#endif /* __SMCMOD_H_ */
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 71f6536..0a070e9 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -101,28 +101,39 @@
extern int __get_user_2(void *);
extern int __get_user_4(void *);
-#define __get_user_x(__r2,__p,__e,__s,__i...) \
+#define __GUP_CLOBBER_1 "lr", "cc"
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define __GUP_CLOBBER_2 "ip", "lr", "cc"
+#else
+#define __GUP_CLOBBER_2 "lr", "cc"
+#endif
+#define __GUP_CLOBBER_4 "lr", "cc"
+
+#define __get_user_x(__r2,__p,__e,__l,__s) \
__asm__ __volatile__ ( \
__asmeq("%0", "r0") __asmeq("%1", "r2") \
+ __asmeq("%3", "r1") \
"bl __get_user_" #__s \
: "=&r" (__e), "=r" (__r2) \
- : "0" (__p) \
- : __i, "cc")
+ : "0" (__p), "r" (__l) \
+ : __GUP_CLOBBER_##__s)
#define get_user(x,p) \
({ \
+ unsigned long __limit = current_thread_info()->addr_limit - 1; \
register const typeof(*(p)) __user *__p asm("r0") = (p);\
register unsigned long __r2 asm("r2"); \
+ register unsigned long __l asm("r1") = __limit; \
register int __e asm("r0"); \
switch (sizeof(*(__p))) { \
case 1: \
- __get_user_x(__r2, __p, __e, 1, "lr"); \
- break; \
+ __get_user_x(__r2, __p, __e, __l, 1); \
+ break; \
case 2: \
- __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \
+ __get_user_x(__r2, __p, __e, __l, 2); \
break; \
case 4: \
- __get_user_x(__r2, __p, __e, 4, "lr"); \
+ __get_user_x(__r2, __p, __e, __l, 4); \
break; \
default: __e = __get_user_bad(); break; \
} \
@@ -135,31 +146,34 @@
extern int __put_user_4(void *, unsigned int);
extern int __put_user_8(void *, unsigned long long);
-#define __put_user_x(__r2,__p,__e,__s) \
+#define __put_user_x(__r2,__p,__e,__l,__s) \
__asm__ __volatile__ ( \
__asmeq("%0", "r0") __asmeq("%2", "r2") \
+ __asmeq("%3", "r1") \
"bl __put_user_" #__s \
: "=&r" (__e) \
- : "0" (__p), "r" (__r2) \
+ : "0" (__p), "r" (__r2), "r" (__l) \
: "ip", "lr", "cc")
#define put_user(x,p) \
({ \
+ unsigned long __limit = current_thread_info()->addr_limit - 1; \
register const typeof(*(p)) __r2 asm("r2") = (x); \
register const typeof(*(p)) __user *__p asm("r0") = (p);\
+ register unsigned long __l asm("r1") = __limit; \
register int __e asm("r0"); \
switch (sizeof(*(__p))) { \
case 1: \
- __put_user_x(__r2, __p, __e, 1); \
+ __put_user_x(__r2, __p, __e, __l, 1); \
break; \
case 2: \
- __put_user_x(__r2, __p, __e, 2); \
+ __put_user_x(__r2, __p, __e, __l, 2); \
break; \
case 4: \
- __put_user_x(__r2, __p, __e, 4); \
+ __put_user_x(__r2, __p, __e, __l, 4); \
break; \
case 8: \
- __put_user_x(__r2, __p, __e, 8); \
+ __put_user_x(__r2, __p, __e, __l, 8); \
break; \
default: __e = __put_user_bad(); break; \
} \
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 11093a7..9b06bb4 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -16,8 +16,9 @@
* __get_user_X
*
* Inputs: r0 contains the address
+ * r1 contains the address limit, which must be preserved
* Outputs: r0 is the error code
- * r2, r3 contains the zero-extended value
+ * r2 contains the zero-extended value
* lr corrupted
*
* No other registers must be altered. (see <asm/uaccess.h>
@@ -27,33 +28,39 @@
* Note also that it is intended that __get_user_bad is not global.
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/errno.h>
#include <asm/domain.h>
ENTRY(__get_user_1)
+ check_uaccess r0, 1, r1, r2, __get_user_bad
1: TUSER(ldrb) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__get_user_1)
ENTRY(__get_user_2)
-#ifdef CONFIG_THUMB2_KERNEL
-2: TUSER(ldrb) r2, [r0]
-3: TUSER(ldrb) r3, [r0, #1]
+ check_uaccess r0, 2, r1, r2, __get_user_bad
+#ifdef CONFIG_CPU_USE_DOMAINS
+rb .req ip
+2: ldrbt r2, [r0], #1
+3: ldrbt rb, [r0], #0
#else
-2: TUSER(ldrb) r2, [r0], #1
-3: TUSER(ldrb) r3, [r0]
+rb .req r0
+2: ldrb r2, [r0]
+3: ldrb rb, [r0, #1]
#endif
#ifndef __ARMEB__
- orr r2, r2, r3, lsl #8
+ orr r2, r2, rb, lsl #8
#else
- orr r2, r3, r2, lsl #8
+ orr r2, rb, r2, lsl #8
#endif
mov r0, #0
mov pc, lr
ENDPROC(__get_user_2)
ENTRY(__get_user_4)
+ check_uaccess r0, 4, r1, r2, __get_user_bad
4: TUSER(ldr) r2, [r0]
mov r0, #0
mov pc, lr
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 7db2599..3d73dcb 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -16,6 +16,7 @@
* __put_user_X
*
* Inputs: r0 contains the address
+ * r1 contains the address limit, which must be preserved
* r2, r3 contains the value
* Outputs: r0 is the error code
* lr corrupted
@@ -27,16 +28,19 @@
* Note also that it is intended that __put_user_bad is not global.
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/errno.h>
#include <asm/domain.h>
ENTRY(__put_user_1)
+ check_uaccess r0, 1, r1, ip, __put_user_bad
1: TUSER(strb) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__put_user_1)
ENTRY(__put_user_2)
+ check_uaccess r0, 2, r1, ip, __put_user_bad
mov ip, r2, lsr #8
#ifdef CONFIG_THUMB2_KERNEL
#ifndef __ARMEB__
@@ -60,12 +64,14 @@
ENDPROC(__put_user_2)
ENTRY(__put_user_4)
+ check_uaccess r0, 4, r1, ip, __put_user_bad
4: TUSER(str) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__put_user_4)
ENTRY(__put_user_8)
+ check_uaccess r0, 8, r1, ip, __put_user_bad
#ifdef CONFIG_THUMB2_KERNEL
5: TUSER(str) r2, [r0]
6: TUSER(str) r3, [r0, #4]
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index a8eee29..b80949c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -282,7 +282,6 @@
select QMI_ENCDEC
select DONT_MAP_HOLE_AFTER_MEMBANK0
select MSM_ULTRASOUND_B
- select MSM_LPM_TEST
select MSM_RPM_LOG
select ARCH_WANT_KMAP_ATOMIC_FLUSH
@@ -307,6 +306,10 @@
select MEMORY_HOLE_CARVEOUT
select DONT_MAP_HOLE_AFTER_MEMBANK0
select QMI_ENCDEC
+ select MSM_SPM_V2
+ select MSM_L2_SPM
+ select MSM_PM8X60 if PM
+ select MSM_RPM_SMD
config ARCH_MPQ8092
bool "MPQ8092"
@@ -430,6 +433,7 @@
select MAY_HAVE_SPARSE_IRQ
select SPARSE_IRQ
select MEMORY_HOLE_CARVEOUT
+ select QMI_ENCDEC
config ARCH_MSM8610
bool "MSM8610"
@@ -2173,12 +2177,12 @@
config MSM_SMCMOD
tristate "Secure Monitor Call (SMC) Module"
default n
- depends on (ARCH_FSM9XXX && ION && ION_MSM && MSM_SCM)
+ depends on (ION && ION_MSM && MSM_SCM)
help
Enable support for smcmod driver. This driver provides a mechanism
to execute the Secure Monitor Call (SMC) to switch from non-secure
- to secure execution in the fsm9xxx targets. This module utilizes Ion
- for buffer management.
+ to secure execution in the fsm9xxx and msm8x26 targets. This module
+ utilizes Ion for buffer management.
config MSM_SUBSYSTEM_RESTART
bool "MSM Subsystem Restart"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 56fb625..8c42b8d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -331,7 +331,7 @@
obj-$(CONFIG_MSM_SDIO_SMEM) += sdio_smem.o
obj-$(CONFIG_MSM_RPM) += rpm.o rpm_resources.o
obj-$(CONFIG_MSM_LPM_TEST) += test-lpm.o
-obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o lpm_levels.o lpm_resources.o
+obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o lpm_levels.o
obj-$(CONFIG_MSM_MPM_OF) += mpm-of.o
obj-$(CONFIG_MSM_MPM) += mpm.o
obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o rpm_master_stat.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 8b0acc6..3505afe 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -99,8 +99,10 @@
dtb-$(CONFIG_ARCH_MSM8226) += msm8226-v1-qrd-skuf.dtb
dtb-$(CONFIG_ARCH_MSM8226) += msm8226-v2-qrd-skuf.dtb
dtb-$(CONFIG_ARCH_MSM8226) += apq8026-v1-xpm.dtb
+ dtb-$(CONFIG_ARCH_MSM8226) += apq8026-v1-cdp.dtb
dtb-$(CONFIG_ARCH_MSM8226) += apq8026-v1-mtp.dtb
dtb-$(CONFIG_ARCH_MSM8226) += apq8026-v2-xpm.dtb
+ dtb-$(CONFIG_ARCH_MSM8226) += apq8026-v2-cdp.dtb
dtb-$(CONFIG_ARCH_MSM8226) += apq8026-v2-mtp.dtb
# FSM9XXX
diff --git a/arch/arm/mach-msm/batterydata-lib.c b/arch/arm/mach-msm/batterydata-lib.c
index 2be591c..42a59d1 100644
--- a/arch/arm/mach-msm/batterydata-lib.c
+++ b/arch/arm/mach-msm/batterydata-lib.c
@@ -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
@@ -13,7 +13,7 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/module.h>
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
int linear_interpolate(int y0, int x0, int y1, int x1, int x)
{
diff --git a/arch/arm/mach-msm/bms-batterydata-desay.c b/arch/arm/mach-msm/bms-batterydata-desay.c
index e2b62be..1e168cd 100644
--- a/arch/arm/mach-msm/bms-batterydata-desay.c
+++ b/arch/arm/mach-msm/bms-batterydata-desay.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*/
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
static struct single_row_lut desay_5200_fcc_temp = {
.x = {-20, 0, 25, 40},
diff --git a/arch/arm/mach-msm/bms-batterydata-oem.c b/arch/arm/mach-msm/bms-batterydata-oem.c
index e4c42d7..634b4dd 100644
--- a/arch/arm/mach-msm/bms-batterydata-oem.c
+++ b/arch/arm/mach-msm/bms-batterydata-oem.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*/
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
static struct single_row_lut fcc_temp = {
.x = {-20, 0, 25, 40, 65},
diff --git a/arch/arm/mach-msm/bms-batterydata-qrd-4v2-1300mah.c b/arch/arm/mach-msm/bms-batterydata-qrd-4v2-1300mah.c
index a2c6391..7e4b2fd 100644
--- a/arch/arm/mach-msm/bms-batterydata-qrd-4v2-1300mah.c
+++ b/arch/arm/mach-msm/bms-batterydata-qrd-4v2-1300mah.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*/
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
static struct single_row_lut fcc_temp = {
.x = {-20, 0, 25, 40, 60},
diff --git a/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c b/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
index 8adf8ca..46c1bbe 100644
--- a/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
+++ b/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
@@ -9,7 +9,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
static struct single_row_lut fcc_temp = {
.x = {-20, 0, 25, 40, 60},
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index dc98c57..75bf5a1 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*/
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
static struct single_row_lut fcc_temp = {
.x = {-20, 0, 25, 40, 65},
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index dd6c9ec..094765f 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, 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
@@ -21,6 +21,7 @@
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/gpiomux.h>
+#include <mach/socinfo.h>
#include "devices.h"
#include "board-8064.h"
#include "board-storage-common-a.h"
@@ -238,6 +239,10 @@
400000, 24000000, 48000000, 96000000
};
+static unsigned int sdc1_sup_clk_rates_all[] = {
+ 400000, 24000000, 48000000, 96000000, 192000000
+};
+
static struct mmc_platform_data sdc1_data = {
.ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
#ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
@@ -331,8 +336,16 @@
void __init apq8064_init_mmc(void)
{
- if (apq8064_sdc1_pdata)
+ if (apq8064_sdc1_pdata) {
+ /* 8064 v2 supports upto 200MHz clock on SDC1 slot */
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
+ apq8064_sdc1_pdata->sup_clk_table =
+ sdc1_sup_clk_rates_all;
+ apq8064_sdc1_pdata->sup_clk_cnt =
+ ARRAY_SIZE(sdc1_sup_clk_rates_all);
+ }
apq8064_add_sdcc(1, apq8064_sdc1_pdata);
+ }
if (apq8064_sdc2_pdata)
apq8064_add_sdcc(2, apq8064_sdc2_pdata);
diff --git a/arch/arm/mach-msm/board-8084.c b/arch/arm/mach-msm/board-8084.c
index 2a6bbb7..8f35a29 100644
--- a/arch/arm/mach-msm/board-8084.c
+++ b/arch/arm/mach-msm/board-8084.c
@@ -29,6 +29,8 @@
#include <mach/socinfo.h>
#include <mach/clk-provider.h>
#include <mach/msm_smem.h>
+#include <mach/rpm-smd.h>
+#include "spm.h"
#include "board-dt.h"
#include "clock.h"
#include "devices.h"
@@ -88,6 +90,8 @@
msm_smem_init();
msm_init_modem_notifier_list();
msm_smd_init();
+ msm_rpm_driver_init();
+ msm_spm_device_init();
msm_clock_init(&msm8084_clock_init_data);
tsens_tm_init_driver();
}
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index fd831fc..78a73c4 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -85,12 +85,6 @@
.pull = GPIOMUX_PULL_DOWN,
};
-static struct gpiomux_setting gpio_spi_cs_eth_config = {
- .func = GPIOMUX_FUNC_4,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -205,12 +199,6 @@
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
},
},
- {
- .gpio = 22, /* BLSP1 QUP1 SPI_CS_ETH */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_cs_eth_config,
- },
- },
{ /* NFC */
.gpio = 10, /* BLSP1 QUP3 I2C_DAT */
.settings = {
@@ -394,6 +382,20 @@
},
},
{
+ .gpio = 22, /* CAM1_VDD */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[4],
+ },
+ },
+ {
+ .gpio = 34, /* CAM1 VCM_PWDN */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[4],
+ },
+ },
+ {
.gpio = 35, /* CAM2_STANDBY_N */
.settings = {
[GPIOMUX_ACTIVE] = &cam_settings[3],
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 0d62b7a..aff2d75 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -51,7 +51,6 @@
#include "platsmp.h"
#include "spm.h"
#include "pm.h"
-#include "lpm_resources.h"
#include "modem_notifier.h"
static struct memtype_reserve msm8226_reserve_table[] __initdata = {
@@ -116,7 +115,6 @@
msm_init_modem_notifier_list();
msm_smd_init();
msm_rpm_driver_init();
- msm_lpmrs_module_init();
msm_spm_device_init();
msm_pm_sleep_status_init();
rpm_regulator_smd_driver_init();
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index f8ca143..01f1468 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -531,7 +531,8 @@
}
msm_gpiomux_install(wcnss_5wire_interface,
ARRAY_SIZE(wcnss_5wire_interface));
- msm_gpiomux_install(msm_lcd_configs, ARRAY_SIZE(msm_lcd_configs));
+ msm_gpiomux_install_nowrite(msm_lcd_configs,
+ ARRAY_SIZE(msm_lcd_configs));
msm_gpiomux_install(msm_keypad_configs,
ARRAY_SIZE(msm_keypad_configs));
msm_gpiomux_install(sd_card_det, ARRAY_SIZE(sd_card_det));
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index c6c9d14..d175bb4 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -52,7 +52,6 @@
#include "platsmp.h"
#include "spm.h"
#include "pm.h"
-#include "lpm_resources.h"
#include "modem_notifier.h"
static struct memtype_reserve msm8610_reserve_table[] __initdata = {
@@ -107,7 +106,6 @@
msm_init_modem_notifier_list();
msm_smd_init();
msm_rpm_driver_init();
- msm_lpmrs_module_init();
msm_spm_device_init();
msm_pm_sleep_status_init();
rpm_regulator_smd_driver_init();
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index 4298d96..62e8122 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, 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
@@ -726,6 +726,96 @@
}
};
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+static struct gpiomux_setting sdcc2_clk_actv_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sdcc2_cmd_data_0_3_actv_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sdcc2_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting sdcc2_data_1_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+/**
+ * DAT_0 to DAT_3 lines (gpio 89 - 92) are shared with ethernet
+ * CMD line (gpio 97) is shared with USB
+ * CLK line (gpio 98) is shared with battery alarm in
+ */
+static struct msm_gpiomux_config msm8960_sdcc2_configs[] __initdata = {
+ {
+ /* DATA_3 */
+ .gpio = 92,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdcc2_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+ },
+ },
+ {
+ /* DATA_2 */
+ .gpio = 91,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdcc2_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+ },
+ },
+ {
+ /* DATA_1 */
+ .gpio = 90,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdcc2_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdcc2_data_1_suspend_cfg,
+ },
+ },
+ {
+ /* DATA_0 */
+ .gpio = 89,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdcc2_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+ },
+ },
+ {
+ /* CMD */
+ .gpio = 97,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdcc2_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+ },
+ },
+ {
+ /* CLK */
+ .gpio = 98,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdcc2_clk_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+ },
+ },
+};
+
+static void msm_gpiomux_sdc2_install(void)
+{
+ msm_gpiomux_install(msm8960_sdcc2_configs,
+ ARRAY_SIZE(msm8960_sdcc2_configs));
+}
+#else
+static void msm_gpiomux_sdc2_install(void) {}
+#endif /* CONFIG_MMC_MSM_SDC2_SUPPORT */
+
int __init msm8930_init_gpiomux(void)
{
int rc = msm_gpiomux_init(NR_GPIO_IRQS);
@@ -802,5 +892,7 @@
msm_gpiomux_install(msm_sitar_config, ARRAY_SIZE(msm_sitar_config));
+ msm_gpiomux_sdc2_install();
+
return 0;
}
diff --git a/arch/arm/mach-msm/board-8930-regulator-pm8038.c b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
index 8ed93ea..8e04003 100644
--- a/arch/arm/mach-msm/board-8930-regulator-pm8038.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
@@ -99,6 +99,7 @@
REGULATOR_SUPPLY("mhl_iovcc18", "0-0039"),
REGULATOR_SUPPLY("vdd-io", "spi0.0"),
REGULATOR_SUPPLY("vdd-phy", "spi0.0"),
+ REGULATOR_SUPPLY("sdc_vdd", "msm_sdcc.2"),
};
VREG_CONSUMERS(L12) = {
REGULATOR_SUPPLY("8038_l12", NULL),
diff --git a/arch/arm/mach-msm/board-8930-regulator-pm8917.c b/arch/arm/mach-msm/board-8930-regulator-pm8917.c
index cdc419f..e63fbdd 100644
--- a/arch/arm/mach-msm/board-8930-regulator-pm8917.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8917.c
@@ -81,6 +81,7 @@
REGULATOR_SUPPLY("cam_vana", "4-006c"),
REGULATOR_SUPPLY("cam_vana", "4-0048"),
REGULATOR_SUPPLY("cam_vana", "4-0020"),
+ REGULATOR_SUPPLY("sdc_vdd", "msm_sdcc.2"),
};
VREG_CONSUMERS(L12) = {
REGULATOR_SUPPLY("8917_l12", NULL),
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index d045040..fec87ae 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, 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
@@ -49,6 +49,13 @@
.lpm_uA = 9000,
.hpm_uA = 200000, /* 200mA */
},
+ /* SDCC2 : SDIO slot connected */
+ [SDCC2] = {
+ .name = "sdc_vdd",
+ .high_vol_level = 1800000,
+ .low_vol_level = 1800000,
+ .hpm_uA = 200000, /* 200mA */
+ },
/* SDCC3 : External card slot connected */
[SDCC3] = {
.name = "sdc_vdd",
@@ -94,7 +101,7 @@
* during sleep.
*/
.lpm_uA = 2000,
- }
+ },
};
static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
@@ -103,6 +110,10 @@
.vdd_data = &mmc_vdd_reg_data[SDCC1],
.vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
},
+ /* SDCC2 : SDIO card slot connected */
+ [SDCC2] = {
+ .vdd_data = &mmc_vdd_reg_data[SDCC2],
+ },
/* SDCC3 : External card slot connected */
[SDCC3] = {
.vdd_data = &mmc_vdd_reg_data[SDCC3],
@@ -170,6 +181,15 @@
{TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
};
+static struct msm_mmc_gpio sdc2_gpio[] = {
+ {92, "sdc2_dat_3"},
+ {91, "sdc2_dat_2"},
+ {90, "sdc2_dat_1"},
+ {89, "sdc2_dat_0"},
+ {97, "sdc2_cmd"},
+ {98, "sdc2_clk"}
+};
+
static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
[SDCC1] = {
.on = sdc1_pad_pull_on_cfg,
@@ -207,10 +227,21 @@
},
};
+static struct msm_mmc_gpio_data mmc_gpio_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC2] = {
+ .gpio = sdc2_gpio,
+ .size = ARRAY_SIZE(sdc2_gpio),
+ },
+};
+
static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
[SDCC1] = {
.pad_data = &mmc_pad_data[SDCC1],
},
+ [SDCC2] = {
+ .is_gpio = true,
+ .gpio_data = &mmc_gpio_data[SDCC2],
+ },
[SDCC3] = {
.pad_data = &mmc_pad_data[SDCC3],
},
@@ -248,6 +279,23 @@
};
#endif
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+static unsigned int sdc2_sup_clk_rates[] = {
+ 400000, 24000000, 48000000
+};
+
+static struct mmc_platform_data msm8960_sdc2_data = {
+ .ocr_mask = MMC_VDD_165_195 | MMC_VDD_27_28 | MMC_VDD_28_29,
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+ .sup_clk_table = sdc2_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
+ .vreg_data = &mmc_slot_vreg_data[SDCC2],
+ .pin_data = &mmc_slot_pin_data[SDCC2],
+ .sdiowakeup_irq = MSM_GPIO_TO_INT(90),
+ .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
+};
+#endif
+
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
static struct mmc_platform_data msm8960_sdc3_data = {
.ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
@@ -300,6 +348,10 @@
/* SDC1 : eMMC card connected */
msm_add_sdcc(1, &msm8960_sdc1_data);
#endif
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+ /* SDC2: SDIO slot for WLAN */
+ msm_add_sdcc(2, &msm8960_sdc2_data);
+#endif
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
/*
* All 8930 platform boards using the 1.2 SoC have been reworked so that
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 68af757..80a957f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -45,8 +45,8 @@
#include "clock.h"
#include "devices.h"
#include "spm.h"
+#include "pm.h"
#include "modem_notifier.h"
-#include "lpm_resources.h"
#include "platsmp.h"
@@ -96,7 +96,6 @@
msm_init_modem_notifier_list();
msm_smd_init();
msm_rpm_driver_init();
- msm_lpmrs_module_init();
msm_pm_sleep_status_init();
rpm_regulator_smd_driver_init();
msm_spm_device_init();
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 36ad755..058789a 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -42,7 +42,6 @@
#include <mach/msm_smem.h>
#include "clock.h"
#include "modem_notifier.h"
-#include "lpm_resources.h"
#include "spm.h"
#define MSM_KERNEL_EBI_SIZE 0x51000
@@ -240,7 +239,6 @@
msm_init_modem_notifier_list();
msm_smd_init();
msm_rpm_driver_init();
- msm_lpmrs_module_init();
rpm_regulator_smd_driver_init();
msm_spm_device_init();
msm_clock_init(&msm9625_clock_init_data);
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
index e80244b..13d7e8b 100644
--- a/arch/arm/mach-msm/board-krypton.c
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -27,9 +27,11 @@
#include <mach/restart.h>
#include <mach/socinfo.h>
#include <mach/clk-provider.h>
+#include <mach/msm_smem.h>
#include "board-dt.h"
#include "clock.h"
#include "devices.h"
+#include "modem_notifier.h"
static struct memtype_reserve msmkrypton_reserve_table[] __initdata = {
[MEMTYPE_EBI1] = {
@@ -59,6 +61,8 @@
*/
void __init msmkrypton_add_drivers(void)
{
+ msm_smem_init();
+ msm_init_modem_notifier_list();
msm_smd_init();
msm_clock_init(&msmkrypton_clock_init_data);
}
diff --git a/arch/arm/mach-msm/board-samarium.c b/arch/arm/mach-msm/board-samarium.c
index be09b54..6133983 100644
--- a/arch/arm/mach-msm/board-samarium.c
+++ b/arch/arm/mach-msm/board-samarium.c
@@ -44,6 +44,8 @@
CLK_DUMMY("core_clk", USB_HS_SYSTEM_CLK, "msm_otg", OFF),
CLK_DUMMY("iface_clk", USB_HS_AHB_CLK, "msm_otg", OFF),
CLK_DUMMY("xo", CXO_OTG_CLK, "msm_otg", OFF),
+ CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
+ CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, "msm_sps", OFF),
};
static struct clock_init_data msm_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index f52bc28..97b8448 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/cpu.h>
+#include <linux/seq_file.h>
#include <linux/io.h>
#include <mach/msm-krait-l2-accessors.h>
#include <mach/msm_iomap.h>
@@ -159,25 +160,23 @@
return cesynr;
}
-static int proc_read_status(char *page, char **start, off_t off, int count,
- int *eof, void *data)
+static int cache_erp_show(struct seq_file *m, void *v)
{
struct msm_l1_err_stats *l1_stats;
- char *p = page;
- int len, cpu, ret, bytes_left = PAGE_SIZE;
+ int cpu;
for_each_present_cpu(cpu) {
l1_stats = &per_cpu(msm_l1_erp_stats, cpu);
- ret = snprintf(p, bytes_left,
- "CPU %d:\n" \
- "\tD-cache tag parity errors:\t%u\n" \
- "\tD-cache data parity errors:\t%u\n" \
- "\tI-cache tag parity errors:\t%u\n" \
- "\tI-cache data parity errors:\t%u\n" \
- "\tD-cache timing errors:\t\t%u\n" \
- "\tI-cache timing errors:\t\t%u\n" \
- "\tTLB multi-hit errors:\t\t%u\n\n", \
+ seq_printf(m,
+ "CPU %d:\n"
+ "\tD-cache tag parity errors:\t%u\n"
+ "\tD-cache data parity errors:\t%u\n"
+ "\tI-cache tag parity errors:\t%u\n"
+ "\tI-cache data parity errors:\t%u\n"
+ "\tD-cache timing errors:\t\t%u\n"
+ "\tI-cache timing errors:\t\t%u\n"
+ "\tTLB multi-hit errors:\t\t%u\n\n",
cpu,
l1_stats->dctpe,
l1_stats->dcdpe,
@@ -186,18 +185,16 @@
l1_stats->dcte,
l1_stats->icte,
l1_stats->tlbmh);
- p += ret;
- bytes_left -= ret;
}
- p += snprintf(p, bytes_left,
- "L2 master port decode errors:\t\t%u\n" \
- "L2 master port slave errors:\t\t%u\n" \
- "L2 tag soft errors, single-bit:\t\t%u\n" \
- "L2 tag soft errors, double-bit:\t\t%u\n" \
- "L2 data soft errors, single-bit:\t%u\n" \
- "L2 data soft errors, double-bit:\t%u\n" \
- "L2 modified soft errors:\t\t%u\n" \
+ seq_printf(m,
+ "L2 master port decode errors:\t\t%u\n"
+ "L2 master port slave errors:\t\t%u\n"
+ "L2 tag soft errors, single-bit:\t\t%u\n"
+ "L2 tag soft errors, double-bit:\t\t%u\n"
+ "L2 data soft errors, single-bit:\t%u\n"
+ "L2 data soft errors, double-bit:\t%u\n"
+ "L2 modified soft errors:\t\t%u\n"
"L2 master port LDREX NOK errors:\t%u\n",
msm_l2_erp_stats.mpdcd,
msm_l2_erp_stats.mpslv,
@@ -208,16 +205,21 @@
msm_l2_erp_stats.mse,
msm_l2_erp_stats.mplxrexnok);
- len = (p - page) - off;
- if (len < 0)
- len = 0;
-
- *eof = (len <= count) ? 1 : 0;
- *start = page + off;
-
- return len;
+ return 0;
}
+static int cache_erp_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cache_erp_show, NULL);
+}
+
+static const struct file_operations cache_erp_fops = {
+ .open = cache_erp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int msm_erp_dump_regions(void)
{
int i = 0;
@@ -235,26 +237,30 @@
}
#ifdef CONFIG_MSM_L1_ERR_LOG
-static int proc_read_log(char *page, char **start, off_t off, int count,
- int *eof, void *data)
+static int cache_erp_log_show(struct seq_file *m, void *v)
{
- char *p = page;
- int len, log_value;
+ int log_value;
+
log_value = __raw_readl(MSM_IMEM_BASE + ERP_LOG_MAGIC_ADDR) ==
ERP_LOG_MAGIC ? 1 : 0;
- p += snprintf(p, PAGE_SIZE, "%d\n", log_value);
+ seq_printf(m, "%d\n", log_value);
- len = (p - page) - off;
- if (len < 0)
- len = 0;
-
- *eof = (len <= count) ? 1 : 0;
- *start = page + off;
-
- return len;
+ return 0;
}
+static int cache_erp_log_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cache_erp_log_show, NULL);
+}
+
+static const struct file_operations cache_erp_log_fops = {
+ .open = cache_erp_log_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static void log_cpu_event(void)
{
__raw_writel(ERP_LOG_MAGIC, MSM_IMEM_BASE + ERP_LOG_MAGIC_ADDR);
@@ -263,11 +269,10 @@
static int procfs_event_log_init(void)
{
- procfs_log_entry = create_proc_entry("cpu/msm_erp_log", S_IRUGO, NULL);
-
+ procfs_log_entry = proc_create("cpu/msm_erp_log", S_IRUGO, NULL,
+ &cache_erp_log_fops);
if (!procfs_log_entry)
return -ENODEV;
- procfs_log_entry->read_proc = proc_read_log;
return 0;
}
@@ -561,7 +566,8 @@
goto fail_l1;
}
- procfs_entry = create_proc_entry("cpu/msm_cache_erp", S_IRUGO, NULL);
+ procfs_entry = proc_create("cpu/msm_cache_erp", S_IRUGO, NULL,
+ &cache_erp_fops);
if (!procfs_entry) {
pr_err("Failed to create procfs node for cache error reporting\n");
@@ -580,8 +586,6 @@
smp_call_function_single(cpu, enable_erp_irq_callback, NULL, 1);
put_online_cpus();
- procfs_entry->read_proc = proc_read_status;
-
ret = procfs_event_log_init();
if (ret)
pr_err("Failed to create procfs node for ERP log access\n");
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index 184338e..3c6975f 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -168,7 +168,8 @@
CLK_DUMMY("", gcc_sdcc4_inactivity_timers_clk.c, "", OFF),
CLK_DUMMY("", gcc_spss_ahb_clk.c, "", OFF),
CLK_DUMMY("", gcc_sys_noc_ufs_axi_clk.c, "", OFF),
- CLK_DUMMY("", gcc_sys_noc_usb3_axi_clk.c, "", OFF),
+ CLK_DUMMY("mem_iface_clk", gcc_sys_noc_usb3_axi_clk.c,
+ "f9304000.qcom,usbbam", OFF),
CLK_DUMMY("", gcc_sys_noc_usb3_sec_axi_clk.c, "", OFF),
CLK_DUMMY("", gcc_tsif_ahb_clk.c, "", OFF),
CLK_DUMMY("", gcc_tsif_inactivity_timers_clk.c, "", OFF),
@@ -183,7 +184,8 @@
CLK_DUMMY("", gcc_ufs_tx_symbol_1_clk.c, "", OFF),
CLK_DUMMY("", gcc_usb2a_phy_sleep_clk.c, "", OFF),
CLK_DUMMY("", gcc_usb2b_phy_sleep_clk.c, "", OFF),
- CLK_DUMMY("", gcc_usb30_master_clk.c, "", OFF),
+ CLK_DUMMY("mem_clk", gcc_usb30_master_clk.c, "f9304000.qcom,usbbam",
+ OFF),
CLK_DUMMY("", gcc_usb30_mock_utmi_clk.c, "", OFF),
CLK_DUMMY("", gcc_usb30_sleep_clk.c, "", OFF),
CLK_DUMMY("", gcc_usb30_sec_master_clk.c, "", OFF),
@@ -392,6 +394,7 @@
CLK_DUMMY("core_clk", qdss_clk.c, "fc321000.funnel", OFF),
CLK_DUMMY("core_clk", qdss_clk.c, "fc322000.funnel", OFF),
CLK_DUMMY("core_clk", qdss_clk.c, "fc345000.funnel", OFF),
+ CLK_DUMMY("core_clk", qdss_clk.c, "fc355000.funnel", OFF),
CLK_DUMMY("core_clk", qdss_clk.c, "fc36c000.funnel", OFF),
CLK_DUMMY("core_clk", qdss_clk.c, "fc302000.stm", OFF),
@@ -402,6 +405,7 @@
CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc321000.funnel", OFF),
CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc322000.funnel", OFF),
CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc345000.funnel", OFF),
+ CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc355000.funnel", OFF),
CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc36c000.funnel", OFF),
CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc302000.stm", OFF),
};
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 452bc28..65ad6c2 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -265,6 +265,7 @@
#define MMPLL1_PLL_STATUS (0x005C)
#define MMSS_PLL_VOTE_APCS (0x0100)
#define VCODEC0_CMD_RCGR (0x1000)
+#define VENUS0_BCR (0x1020)
#define VENUS0_VCODEC0_CBCR (0x1028)
#define VENUS0_AHB_CBCR (0x1030)
#define VENUS0_AXI_CBCR (0x1034)
@@ -274,6 +275,7 @@
#define BYTE0_CMD_RCGR (0x2120)
#define ESC0_CMD_RCGR (0x2160)
#define MDSS_AHB_CBCR (0x2308)
+#define MDSS_BCR (0x2300)
#define MDSS_AXI_CBCR (0x2310)
#define MDSS_PCLK0_CBCR (0x2314)
#define MDSS_MDP_CBCR (0x231C)
@@ -312,18 +314,22 @@
#define CAMSS_TOP_AHB_CBCR (0x3484)
#define CAMSS_MICRO_AHB_CBCR (0x3494)
#define JPEG0_CMD_RCGR (0x3500)
+#define CAMSS_JPEG_BCR (0x35A0)
#define CAMSS_JPEG_JPEG0_CBCR (0x35A8)
#define CAMSS_JPEG_JPEG_AHB_CBCR (0x35B4)
#define CAMSS_JPEG_JPEG_AXI_CBCR (0x35B8)
#define VFE0_CMD_RCGR (0x3600)
#define CPP_CMD_RCGR (0x3640)
+#define CAMSS_VFE_BCR (0x36A0)
#define CAMSS_VFE_VFE0_CBCR (0x36A8)
#define CAMSS_VFE_CPP_CBCR (0x36B0)
#define CAMSS_VFE_CPP_AHB_CBCR (0x36B4)
#define CAMSS_VFE_VFE_AHB_CBCR (0x36B8)
#define CAMSS_VFE_VFE_AXI_CBCR (0x36BC)
+#define CAMSS_CSI_VFE0_BCR (0x3700)
#define CAMSS_CSI_VFE0_CBCR (0x3704)
#define OXILI_GFX3D_CBCR (0x4028)
+#define OXILICX_BCR (0x4030)
#define OXILICX_AXI_CBCR (0x4038)
#define OXILICX_AHB_CBCR (0x403C)
#define MMPLL2_PLL_MODE (0x4100)
@@ -2255,6 +2261,7 @@
static struct branch_clk camss_csi_vfe0_clk = {
.cbcr_reg = CAMSS_CSI_VFE0_CBCR,
+ .bcr_reg = CAMSS_CSI_VFE0_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2302,6 +2309,7 @@
static struct branch_clk camss_jpeg_jpeg0_clk = {
.cbcr_reg = CAMSS_JPEG_JPEG0_CBCR,
+ .bcr_reg = CAMSS_JPEG_BCR,
.has_sibling = 0,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2430,6 +2438,7 @@
static struct branch_clk camss_vfe_vfe0_clk = {
.cbcr_reg = CAMSS_VFE_VFE0_CBCR,
+ .bcr_reg = CAMSS_VFE_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2512,6 +2521,7 @@
static struct branch_clk mdss_mdp_clk = {
.cbcr_reg = MDSS_MDP_CBCR,
+ .bcr_reg = MDSS_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2608,6 +2618,7 @@
static struct branch_clk oxili_gfx3d_clk = {
.cbcr_reg = OXILI_GFX3D_CBCR,
+ .bcr_reg = OXILICX_BCR,
.has_sibling = 0,
.max_div = 0,
.base = &virt_bases[MMSS_BASE],
@@ -2667,6 +2678,7 @@
static struct branch_clk venus0_vcodec0_clk = {
.cbcr_reg = VENUS0_VCODEC0_CBCR,
+ .bcr_reg = VENUS0_BCR,
.has_sibling = 0,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3378,9 +3390,13 @@
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6f.qcom,camera"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "90.qcom,camera"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6d.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6a.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6c.qcom,camera"),
CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6f.qcom,camera"),
CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "90.qcom,camera"),
CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6d.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6a.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6c.qcom,camera"),
/* CCI clocks */
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 1514bba..0677525 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1547,7 +1547,7 @@
F_END
};
-static CLK_SDC(sdc1_clk, 1, 6, 52000000, 104000000);
+static CLK_SDC(sdc1_clk, 1, 6, 52000000, 208000000);
static CLK_SDC(sdc2_clk, 2, 5, 52000000, 104000000);
static CLK_SDC(sdc3_clk, 3, 4, 104000000, 208000000);
static CLK_SDC(sdc4_clk, 4, 3, 33000000, 67000000);
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index c91af54..fc32a59 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -161,25 +161,62 @@
DEFINE_SIMPLE_ATTRIBUTE(clock_hwcg_fops, clock_debug_hwcg_get,
NULL, "%llu\n");
+static void clock_print_fmax_by_level(struct seq_file *m, int level)
+{
+ struct clk *clock = m->private;
+ struct clk_vdd_class *vdd_class = clock->vdd_class;
+ int off, i, vdd_level, nregs = vdd_class->num_regulators;
+
+ vdd_level = find_vdd_level(clock, clock->rate);
+
+ seq_printf(m, "%2s%10lu", vdd_level == level ? "[" : "",
+ clock->fmax[level]);
+ for (i = 0; i < nregs; i++) {
+ off = nregs*level + i;
+ if (vdd_class->vdd_uv)
+ seq_printf(m, "%10u", vdd_class->vdd_uv[off]);
+ if (vdd_class->vdd_ua)
+ seq_printf(m, "%10u", vdd_class->vdd_ua[off]);
+ }
+
+ if (vdd_level == level)
+ seq_puts(m, "]");
+ seq_puts(m, "\n");
+}
+
static int fmax_rates_show(struct seq_file *m, void *unused)
{
struct clk *clock = m->private;
- int level = 0;
+ struct clk_vdd_class *vdd_class = clock->vdd_class;
+ int level = 0, i, nregs = vdd_class->num_regulators;
+ char reg_name[10];
int vdd_level = find_vdd_level(clock, clock->rate);
if (vdd_level < 0) {
seq_printf(m, "could not find_vdd_level for %s, %ld\n",
- clock->dbg_name, clock->rate);
+ clock->dbg_name, clock->rate);
return 0;
}
- for (level = 0; level < clock->num_fmax; level++) {
- if (vdd_level == level)
- seq_printf(m, "[%lu] ", clock->fmax[level]);
- else
- seq_printf(m, "%lu ", clock->fmax[level]);
+
+ seq_printf(m, "%12s", "");
+ for (i = 0; i < nregs; i++) {
+ snprintf(reg_name, ARRAY_SIZE(reg_name), "reg %d", i);
+ seq_printf(m, "%10s", reg_name);
+ if (vdd_class->vdd_ua)
+ seq_printf(m, "%10s", "");
+ }
+
+ seq_printf(m, "\n%12s", "freq");
+ for (i = 0; i < nregs; i++) {
+ seq_printf(m, "%10s", "uV");
+ if (vdd_class->vdd_ua)
+ seq_printf(m, "%10s", "uA");
}
seq_printf(m, "\n");
+ for (level = 0; level < clock->num_fmax; level++)
+ clock_print_fmax_by_level(m, level);
+
return 0;
}
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
index 883a5c2..139c756 100644
--- a/arch/arm/mach-msm/clock-dummy.c
+++ b/arch/arm/mach-msm/clock-dummy.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
@@ -19,6 +19,7 @@
static int dummy_clk_set_rate(struct clk *clk, unsigned long rate)
{
+ clk->rate = rate;
return 0;
}
@@ -34,7 +35,7 @@
static unsigned long dummy_clk_get_rate(struct clk *clk)
{
- return 0;
+ return clk->rate;
}
static long dummy_clk_round_rate(struct clk *clk, unsigned long rate)
@@ -42,7 +43,7 @@
return rate;
}
-static struct clk_ops clk_ops_dummy = {
+struct clk_ops clk_ops_dummy = {
.reset = dummy_clk_reset,
.set_rate = dummy_clk_set_rate,
.set_max_rate = dummy_clk_set_max_rate,
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index a2936c2..60a62ec 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -125,6 +125,8 @@
#define CPR_FUSE_RO_SEL_BITS 3
#define CPR_FUSE_RO_SEL_BITS_MASK ((1<<CPR_FUSE_RO_SEL_BITS)-1)
+#define CPR_FUSE_MIN_QUOT_DIFF 100
+
#define BYTES_PER_FUSE_ROW 8
enum voltage_change_dir {
@@ -200,16 +202,26 @@
u32 vdd_apc_step_down_limit;
};
-static int cpr_debug_enable;
+#define CPR_DEBUG_MASK_IRQ BIT(0)
+#define CPR_DEBUG_MASK_API BIT(1)
+
+static int cpr_debug_enable = CPR_DEBUG_MASK_IRQ;
static int cpr_enable;
static struct cpr_regulator *the_cpr;
module_param_named(debug_enable, cpr_debug_enable, int, S_IRUGO | S_IWUSR);
#define cpr_debug(message, ...) \
do { \
- if (cpr_debug_enable) \
+ if (cpr_debug_enable & CPR_DEBUG_MASK_API) \
pr_info(message, ##__VA_ARGS__); \
} while (0)
+#define cpr_debug_irq(message, ...) \
+ do { \
+ if (cpr_debug_enable & CPR_DEBUG_MASK_IRQ) \
+ pr_info(message, ##__VA_ARGS__); \
+ else \
+ pr_debug(message, ##__VA_ARGS__); \
+ } while (0)
static bool cpr_is_allowed(struct cpr_regulator *cpr_vreg)
{
@@ -267,11 +279,12 @@
cpr_masked_write(cpr_vreg, REG_RBCPR_CTL, mask, value);
}
-static void cpr_ctl_enable(struct cpr_regulator *cpr_vreg)
+static void cpr_ctl_enable(struct cpr_regulator *cpr_vreg, int corner)
{
u32 val;
- if (cpr_is_allowed(cpr_vreg))
+ if (cpr_is_allowed(cpr_vreg) &&
+ (cpr_vreg->ceiling_volt[corner] > cpr_vreg->floor_volt[corner]))
val = RBCPR_CTL_LOOP_EN;
else
val = 0;
@@ -369,7 +382,7 @@
cpr_ctl_disable(the_cpr);
cpr_irq_clr(the_cpr);
cpr_corner_restore(the_cpr, the_cpr->corner);
- cpr_ctl_enable(the_cpr);
+ cpr_ctl_enable(the_cpr, the_cpr->corner);
} else {
cpr_ctl_disable(the_cpr);
cpr_irq_set(the_cpr, 0);
@@ -485,16 +498,16 @@
& RBCPR_RESULT0_ERROR_STEPS_MASK;
last_volt = cpr_vreg->last_volt[corner];
- cpr_debug("last_volt[corner:%d] = %d uV\n", corner, last_volt);
+ cpr_debug_irq("last_volt[corner:%d] = %d uV\n", corner, last_volt);
if (dir == UP) {
- cpr_debug("Up: cpr status = 0x%08x (error_steps=%d)\n",
- reg_val, error_steps);
+ cpr_debug_irq("Up: cpr status = 0x%08x (error_steps=%d)\n",
+ reg_val, error_steps);
if (last_volt >= cpr_vreg->ceiling_volt[corner]) {
- cpr_debug("[corn:%d] @ ceiling: %d >= %d: NACK\n",
- corner, last_volt,
- cpr_vreg->ceiling_volt[corner]);
+ cpr_debug_irq("[corn:%d] @ ceiling: %d >= %d: NACK\n",
+ corner, last_volt,
+ cpr_vreg->ceiling_volt[corner]);
cpr_irq_clr_nack(cpr_vreg);
/* Maximize the UP threshold */
@@ -506,17 +519,18 @@
}
if (error_steps > cpr_vreg->vdd_apc_step_up_limit) {
- cpr_debug("%d is over up-limit(%d): Clamp\n",
- error_steps,
- cpr_vreg->vdd_apc_step_up_limit);
+ cpr_debug_irq("%d is over up-limit(%d): Clamp\n",
+ error_steps,
+ cpr_vreg->vdd_apc_step_up_limit);
error_steps = cpr_vreg->vdd_apc_step_up_limit;
}
/* Calculate new voltage */
new_volt = last_volt + (error_steps * cpr_vreg->step_volt);
if (new_volt > cpr_vreg->ceiling_volt[corner]) {
- cpr_debug("new_volt(%d) >= ceiling_volt(%d): Clamp\n",
- new_volt, cpr_vreg->ceiling_volt[corner]);
+ cpr_debug_irq("new_volt(%d) >= ceiling(%d): Clamp\n",
+ new_volt,
+ cpr_vreg->ceiling_volt[corner]);
new_volt = cpr_vreg->ceiling_volt[corner];
}
@@ -542,15 +556,16 @@
/* Ack */
cpr_irq_clr_ack(cpr_vreg);
- cpr_debug("UP: -> new_volt = %d uV\n", new_volt);
+ cpr_debug_irq("UP: -> new_volt[corner:%d] = %d uV\n",
+ corner, new_volt);
} else if (dir == DOWN) {
- cpr_debug("Down: cpr status = 0x%08x (error_steps=%d)\n",
- reg_val, error_steps);
+ cpr_debug_irq("Down: cpr status = 0x%08x (error_steps=%d)\n",
+ reg_val, error_steps);
if (last_volt <= cpr_vreg->floor_volt[corner]) {
- cpr_debug("[corn:%d] @ floor: %d <= %d: NACK\n",
- corner, last_volt,
- cpr_vreg->floor_volt[corner]);
+ cpr_debug_irq("[corn:%d] @ floor: %d <= %d: NACK\n",
+ corner, last_volt,
+ cpr_vreg->floor_volt[corner]);
cpr_irq_clr_nack(cpr_vreg);
/* Maximize the DOWN threshold */
@@ -571,17 +586,18 @@
}
if (error_steps > cpr_vreg->vdd_apc_step_down_limit) {
- cpr_debug("%d is over down-limit(%d): Clamp\n",
- error_steps,
- cpr_vreg->vdd_apc_step_down_limit);
+ cpr_debug_irq("%d is over down-limit(%d): Clamp\n",
+ error_steps,
+ cpr_vreg->vdd_apc_step_down_limit);
error_steps = cpr_vreg->vdd_apc_step_down_limit;
}
/* Calculte new voltage */
new_volt = last_volt - (error_steps * cpr_vreg->step_volt);
if (new_volt < cpr_vreg->floor_volt[corner]) {
- cpr_debug("new_volt(%d) < floor_volt(%d): Clamp\n",
- new_volt, cpr_vreg->floor_volt[corner]);
+ cpr_debug_irq("new_volt(%d) < floor(%d): Clamp\n",
+ new_volt,
+ cpr_vreg->floor_volt[corner]);
new_volt = cpr_vreg->floor_volt[corner];
}
@@ -601,7 +617,8 @@
/* Ack */
cpr_irq_clr_ack(cpr_vreg);
- cpr_debug("DOWN: -> new_volt = %d uV\n", new_volt);
+ cpr_debug_irq("DOWN: -> new_volt[corner:%d] = %d uV\n",
+ corner, new_volt);
}
}
@@ -613,7 +630,7 @@
mutex_lock(&cpr_vreg->cpr_mutex);
reg_val = cpr_read(cpr_vreg, REG_RBIF_IRQ_STATUS);
- cpr_debug("IRQ_STATUS = 0x%02X\n", reg_val);
+ cpr_debug_irq("IRQ_STATUS = 0x%02X\n", reg_val);
if (!cpr_is_allowed(cpr_vreg)) {
reg_val = cpr_read(cpr_vreg, REG_RBCPR_CTL);
@@ -632,7 +649,7 @@
cpr_irq_clr_nack(cpr_vreg);
} else if (reg_val & CPR_INT_MID) {
/* RBCPR_CTL_SW_AUTO_CONT_ACK_EN is enabled */
- cpr_debug("IRQ occured for Mid Flag\n");
+ cpr_debug_irq("IRQ occured for Mid Flag\n");
} else {
pr_err("IRQ occured for unknown flag (0x%08x)\n", reg_val);
}
@@ -678,7 +695,7 @@
if (cpr_is_allowed(cpr_vreg) && cpr_vreg->corner) {
cpr_irq_clr(cpr_vreg);
cpr_corner_switch(cpr_vreg, cpr_vreg->corner);
- cpr_ctl_enable(cpr_vreg);
+ cpr_ctl_enable(cpr_vreg, cpr_vreg->corner);
}
mutex_unlock(&cpr_vreg->cpr_mutex);
@@ -744,7 +761,7 @@
if (cpr_is_allowed(cpr_vreg) && cpr_vreg->vreg_enabled) {
cpr_irq_clr(cpr_vreg);
cpr_corner_switch(cpr_vreg, corner);
- cpr_ctl_enable(cpr_vreg);
+ cpr_ctl_enable(cpr_vreg, corner);
}
cpr_vreg->corner = corner;
@@ -793,7 +810,7 @@
cpr_irq_clr(cpr_vreg);
enable_irq(cpr_vreg->cpr_irq);
- cpr_ctl_enable(cpr_vreg);
+ cpr_ctl_enable(cpr_vreg, cpr_vreg->corner);
return 0;
}
@@ -1194,6 +1211,29 @@
if (!cpr_vreg->cpr_fuse_bits) {
cpr_vreg->cpr_fuse_disable = 1;
pr_err("cpr_fuse_bits = 0: set cpr_fuse_disable = 1\n");
+ } else {
+ /* Check if the target quotients are too close together */
+ int *quot = cpr_vreg->cpr_fuse_target_quot;
+ bool valid_fuse = true;
+
+ if ((quot[CPR_CORNER_TURBO] > quot[CPR_CORNER_NORMAL]) &&
+ (quot[CPR_CORNER_NORMAL] > quot[CPR_CORNER_SVS])) {
+ if ((quot[CPR_CORNER_TURBO] -
+ quot[CPR_CORNER_NORMAL])
+ <= CPR_FUSE_MIN_QUOT_DIFF)
+ valid_fuse = false;
+ else if ((quot[CPR_CORNER_NORMAL] -
+ quot[CPR_CORNER_SVS])
+ <= CPR_FUSE_MIN_QUOT_DIFF)
+ valid_fuse = false;
+ } else {
+ valid_fuse = false;
+ }
+
+ if (!valid_fuse) {
+ cpr_vreg->cpr_fuse_disable = 1;
+ pr_err("invalid quotient values\n");
+ }
}
return 0;
diff --git a/arch/arm/mach-msm/include/mach/camera2.h b/arch/arm/mach-msm/include/mach/camera2.h
index 3e7e5fd..887c594 100644
--- a/arch/arm/mach-msm/include/mach/camera2.h
+++ b/arch/arm/mach-msm/include/mach/camera2.h
@@ -40,6 +40,7 @@
enum cci_i2c_master_t {
MASTER_0,
MASTER_1,
+ MASTER_MAX,
};
struct msm_camera_slave_info {
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 72b5cc1..75dc240 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -168,6 +168,7 @@
int msm_clock_register(struct clk_lookup *table, size_t size);
extern struct clk dummy_clk;
+extern struct clk_ops clk_ops_dummy;
#define CLK_DUMMY(clk_name, clk_id, clk_dev, flags) { \
.con_id = clk_name, \
@@ -175,6 +176,16 @@
.clk = &dummy_clk, \
}
+#define DEFINE_CLK_DUMMY(name, _rate) \
+ static struct fixed_clk name = { \
+ .c = { \
+ .dbg_name = #name, \
+ .rate = _rate, \
+ .ops = &clk_ops_dummy, \
+ CLK_INIT(name.c), \
+ }, \
+ };
+
#define CLK_LOOKUP(con, c, dev) { .con_id = con, .clk = &c, .dev_id = dev }
#endif
diff --git a/arch/arm/mach-msm/include/mach/mpm.h b/arch/arm/mach-msm/include/mach/mpm.h
index b92c039..e76a6a9 100644
--- a/arch/arm/mach-msm/include/mach/mpm.h
+++ b/arch/arm/mach-msm/include/mach/mpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -163,4 +163,23 @@
static inline void msm_mpm_exit_sleep(bool from_idle) {}
static inline void __init of_mpm_init(struct device_node *node) {}
#endif
+#ifdef CONFIG_MSM_MPM_OF
+/** msm_mpm_suspend_prepare() - Called at prepare_late() op during suspend
+ *
+ *
+ * When called the MPM driver checks if the wakeup interrupts can be monitored
+ * by MPM hardware and program them accordingly. If wake up interrupts cannot
+ * be monitored then it disallows system low power modes.
+ */
+void msm_mpm_suspend_prepare(void);
+/** msm_mpm_suspend_wake - Called during wake() op in suspend.
+ *
+ * When called MPM drivers sets the vote for system low power modes depending
+ * on the active interrupts.
+ */
+void msm_mpm_suspend_wake(void);
+#else
+static inline void msm_mpm_suspend_prepare(void){}
+static inline void msm_mpm_suspend_wake(void) {}
+#endif
#endif /* __ARCH_ARM_MACH_MSM_MPM_H */
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
index a8b9da5..1861b48 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
@@ -23,7 +23,7 @@
*
*/
-#define MSMKRYPTON_SHARED_RAM_PHYS 0x00000000
+#define MSMKRYPTON_SHARED_RAM_PHYS 0x02200000
#define MSMKRYPTON_TLMM_PHYS 0xFD510000
#define MSMKRYPTON_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 7b73333..67cf442 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -115,7 +115,8 @@
#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27) \
|| defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM9625) \
- || defined(CONFIG_ARCH_MSM8610) || defined(CONFIG_ARCH_MSM8226)
+ || defined(CONFIG_ARCH_MSM8610) || defined(CONFIG_ARCH_MSM8226) \
+ || defined(CONFIG_ARCH_MSMKRYPTON)
#define MSM_SHARED_RAM_SIZE SZ_1M
#else
#define MSM_SHARED_RAM_SIZE SZ_2M
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 3332701..6cd4a2e 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -17,6 +17,34 @@
#include <linux/types.h> /* u32 */
+#ifdef CONFIG_ARM_LPAE
+
+/* Returns upper 4bits of 36bits physical address */
+#define SPS_GET_UPPER_ADDR(addr) ((addr & 0xF00000000ULL) >> 32)
+
+/* Returns 36bits physical address from 32bit address &
+ * flags word */
+#define DESC_FULL_ADDR(flags, addr) (((flags & 0xF) << 32) | addr)
+
+/* Returns flags word with flags and 4bit upper address
+ * from flags and 36bit physical address */
+#define DESC_FLAG_WORD(flags, addr) (((addr & 0xF00000000ULL) >> 32) | flags)
+
+#else
+
+#define SPS_GET_UPPER_ADDR(addr) (0)
+#define DESC_FULL_ADDR(flags, addr) (addr)
+#define DESC_FLAG_WORD(flags, addr) (flags)
+
+#endif
+
+/* Returns upper 4bits of 36bits physical address from
+ * flags word */
+#define DESC_UPPER_ADDR(flags) ((flags & 0xF))
+
+/* Returns lower 32bits of 36bits physical address */
+#define SPS_GET_LOWER_ADDR(addr) ((u32)(addr & 0xFFFFFFFF))
+
/* SPS device handle indicating use of system memory */
#define SPS_DEV_HANDLE_MEM ((u32)0x7ffffffful)
@@ -56,8 +84,8 @@
#define SPS_IOVEC_FLAG_LOCK 0x0400 /* pipe lock */
#define SPS_IOVEC_FLAG_UNLOCK 0x0200 /* pipe unlock */
#define SPS_IOVEC_FLAG_IMME 0x0100 /* immediate command descriptor */
-#define SPS_IOVEC_FLAG_NO_SUBMIT 0x0002 /* Do not submit descriptor to HW */
-#define SPS_IOVEC_FLAG_DEFAULT 0x0001 /* Use driver default */
+#define SPS_IOVEC_FLAG_NO_SUBMIT 0x0020 /* Do not submit descriptor to HW */
+#define SPS_IOVEC_FLAG_DEFAULT 0x0010 /* Use driver default */
/* Maximum descriptor/iovec size */
#define SPS_IOVEC_MAX_SIZE (32 * 1024 - 1) /* 32K-1 bytes due to HW limit */
@@ -79,6 +107,9 @@
#define SPS_BAM_NO_EXT_P_RST (1UL << 4)
/* Don't enable local clock gating */
#define SPS_BAM_NO_LOCAL_CLK_GATING (1UL << 5)
+/* Don't enable writeback cancel*/
+#define SPS_BAM_CANCEL_WB (1UL << 6)
+
/* BAM device management flags */
@@ -137,6 +168,8 @@
SPS_O_OUT_OF_DESC = 0x00000008,/* Out of descriptors */
SPS_O_ERROR = 0x00000010, /* Error */
SPS_O_EOT = 0x00000020, /* End-of-transfer */
+ SPS_O_RST_ERROR = 0x00000040, /* Pipe reset unsucessful error */
+ SPS_O_HRESP_ERROR = 0x00000080,/* Errorneous Hresponse by AHB MASTER */
/* Options to enable hardware features */
SPS_O_STREAMING = 0x00010000, /* Enable streaming mode (no EOT) */
@@ -200,6 +233,8 @@
SPS_EVENT_FLOWOFF, /* Graceful halt (idle) */
SPS_EVENT_INACTIVE, /* Inactivity timeout */
SPS_EVENT_ERROR, /* Error */
+ SPS_EVENT_RST_ERROR, /* Pipe Reset unsuccessful */
+ SPS_EVENT_HRESP_ERROR, /* Errorneous Hresponse by AHB Master*/
SPS_EVENT_MAX,
};
@@ -429,7 +464,7 @@
*/
struct sps_mem_buffer {
void *base;
- u32 phys_base;
+ phys_addr_t phys_base;
u32 size;
u32 min_size;
};
@@ -646,7 +681,7 @@
*
*/
struct sps_transfer {
- u32 iovec_phys;
+ phys_addr_t iovec_phys;
struct sps_iovec *iovec;
u32 iovec_count;
void *user;
@@ -938,7 +973,7 @@
* @return 0 on success, negative value on error
*
*/
-int sps_transfer_one(struct sps_pipe *h, u32 addr, u32 size,
+int sps_transfer_one(struct sps_pipe *h, phys_addr_t addr, u32 size,
void *user, u32 flags);
/**
@@ -1335,8 +1370,8 @@
return -EPERM;
}
-static inline int sps_transfer_one(struct sps_pipe *h, u32 addr, u32 size,
- void *user, u32 flags)
+static inline int sps_transfer_one(struct sps_pipe *h, phys_addr_t addr,
+ u32 size, void *user, u32 flags)
{
return -EPERM;
}
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index aa33f2c..4d7c3d4 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -16,19 +16,60 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
#include <linux/of.h>
#include <mach/mpm.h>
-#include "lpm_resources.h"
#include "pm.h"
#include "rpm-notifier.h"
-
+#include "spm.h"
+#include "idle.h"
enum {
MSM_LPM_LVL_DBG_SUSPEND_LIMITS = BIT(0),
MSM_LPM_LVL_DBG_IDLE_LIMITS = BIT(1),
};
-#define MAX_STR_LEN 30
+enum {
+ MSM_SCM_L2_ON = 0,
+ MSM_SCM_L2_OFF = 1,
+ MSM_SCM_L2_GDHS = 3,
+};
+
+struct msm_rpmrs_level {
+ enum msm_pm_sleep_mode sleep_mode;
+ uint32_t l2_cache;
+ bool available;
+ uint32_t latency_us;
+ uint32_t steady_state_power;
+ uint32_t energy_overhead;
+ uint32_t time_overhead_us;
+};
+
+struct lpm_lookup_table {
+ uint32_t modes;
+ const char *mode_name;
+};
+
+static void msm_lpm_level_update(void);
+
+static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
+ unsigned long action, void *hcpu);
+
+static struct notifier_block __refdata msm_lpm_cpu_nblk = {
+ .notifier_call = msm_lpm_cpu_callback,
+};
+
+static uint32_t allowed_l2_mode;
+static uint32_t sysfs_dbg_l2_mode = MSM_SPM_L2_MODE_POWER_COLLAPSE;
+static uint32_t default_l2_mode;
+
+static bool no_l2_saw;
+
+static ssize_t msm_lpm_levels_attr_show(
+ struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+static ssize_t msm_lpm_levels_attr_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count);
static int msm_lpm_lvl_dbg_msk;
@@ -39,9 +80,54 @@
static struct msm_rpmrs_level *msm_lpm_levels;
static int msm_lpm_level_count;
-static DEFINE_PER_CPU(uint32_t , msm_lpm_sleep_time);
-static DEFINE_PER_CPU(int , lpm_permitted_level);
-static DEFINE_PER_CPU(struct atomic_notifier_head, lpm_notify_head);
+static struct kobj_attribute lpm_l2_kattr = __ATTR(l2, S_IRUGO|S_IWUSR,\
+ msm_lpm_levels_attr_show, msm_lpm_levels_attr_store);
+
+static struct attribute *lpm_levels_attr[] = {
+ &lpm_l2_kattr.attr,
+ NULL,
+};
+
+static struct attribute_group lpm_levels_attr_grp = {
+ .attrs = lpm_levels_attr,
+};
+
+/* SYSFS */
+static ssize_t msm_lpm_levels_attr_show(
+ struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct kernel_param kp;
+ int rc;
+
+ kp.arg = &sysfs_dbg_l2_mode;
+
+ rc = param_get_uint(buf, &kp);
+
+ if (rc > 0) {
+ strlcat(buf, "\n", PAGE_SIZE);
+ rc++;
+ }
+
+ return rc;
+}
+
+static ssize_t msm_lpm_levels_attr_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct kernel_param kp;
+ unsigned int temp;
+ int rc;
+
+ kp.arg = &temp;
+ rc = param_set_uint(buf, &kp);
+ if (rc)
+ return rc;
+
+ sysfs_dbg_l2_mode = temp;
+ msm_lpm_level_update();
+
+ return count;
+}
static int msm_pm_get_sleep_mode_value(struct device_node *node,
const char *key, uint32_t *sleep_mode_val)
@@ -74,8 +160,7 @@
if (!ret) {
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(pm_sm_lookup); i++) {
- if (!strncmp(mode_name, pm_sm_lookup[i].mode_name,
- MAX_STR_LEN)) {
+ if (!strcmp(mode_name, pm_sm_lookup[i].mode_name)) {
*sleep_mode_val = pm_sm_lookup[i].modes;
ret = 0;
break;
@@ -85,16 +170,61 @@
return ret;
}
+static int msm_lpm_set_l2_mode(int sleep_mode)
+{
+ int lpm = sleep_mode;
+ int rc = 0;
+
+ if (no_l2_saw)
+ goto bail_set_l2_mode;
+
+ msm_pm_set_l2_flush_flag(MSM_SCM_L2_ON);
+
+ switch (sleep_mode) {
+ case MSM_SPM_L2_MODE_POWER_COLLAPSE:
+ msm_pm_set_l2_flush_flag(MSM_SCM_L2_OFF);
+ break;
+ case MSM_SPM_L2_MODE_GDHS:
+ msm_pm_set_l2_flush_flag(MSM_SCM_L2_GDHS);
+ break;
+ case MSM_SPM_L2_MODE_RETENTION:
+ case MSM_SPM_L2_MODE_DISABLED:
+ break;
+ default:
+ lpm = MSM_SPM_L2_MODE_DISABLED;
+ break;
+ }
+
+ rc = msm_spm_l2_set_low_power_mode(lpm, true);
+
+ if (rc) {
+ if (rc == -ENXIO)
+ WARN_ON_ONCE(1);
+ else
+ pr_err("%s: Failed to set L2 low power mode %d, ERR %d",
+ __func__, lpm, rc);
+ }
+
+bail_set_l2_mode:
+ return rc;
+}
+
static void msm_lpm_level_update(void)
{
- unsigned int lpm_level;
+ int lpm_level;
struct msm_rpmrs_level *level = NULL;
+ uint32_t max_l2_mode;
+ static DEFINE_MUTEX(lpm_lock);
+
+ mutex_lock(&lpm_lock);
+
+ max_l2_mode = min(allowed_l2_mode, sysfs_dbg_l2_mode);
for (lpm_level = 0; lpm_level < msm_lpm_level_count; lpm_level++) {
level = &msm_lpm_levels[lpm_level];
- level->available =
- !msm_lpm_level_beyond_limit(&level->rs_limits);
+ level->available = !(level->l2_cache > max_l2_mode);
}
+ mutex_unlock(&lpm_lock);
}
int msm_lpm_enter_sleep(uint32_t sclk_count, void *limits,
@@ -102,13 +232,7 @@
{
int ret = 0;
int debug_mask;
- struct msm_rpmrs_limits *l = (struct msm_rpmrs_limits *)limits;
- struct msm_lpm_sleep_data sleep_data;
-
- sleep_data.limits = limits;
- sleep_data.kernel_sleep = __get_cpu_var(msm_lpm_sleep_time);
- atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
- MSM_LPM_STATE_ENTER, &sleep_data);
+ uint32_t l2 = *(uint32_t *)limits;
if (from_idle)
debug_mask = msm_lpm_lvl_dbg_msk &
@@ -118,19 +242,20 @@
MSM_LPM_LVL_DBG_SUSPEND_LIMITS;
if (debug_mask)
- pr_info("%s(): pxo:%d l2:%d mem:0x%x(0x%x) dig:0x%x(0x%x)\n",
- __func__, l->pxo, l->l2_cache,
- l->vdd_mem_lower_bound,
- l->vdd_mem_upper_bound,
- l->vdd_dig_lower_bound,
- l->vdd_dig_upper_bound);
+ pr_info("%s(): l2:%d", __func__, l2);
- ret = msm_lpmrs_enter_sleep(sclk_count, l, from_idle, notify_rpm);
+ ret = msm_lpm_set_l2_mode(l2);
+
if (ret) {
- pr_warn("%s() LPM resources failed to enter sleep\n",
- __func__);
- goto bail;
+ if (ret == -ENXIO)
+ ret = 0;
+ else {
+ pr_warn("%s(): Failed to set L2 SPM Mode %d",
+ __func__, l2);
+ goto bail;
+ }
}
+
if (notify_rpm) {
ret = msm_rpm_enter_sleep(debug_mask);
if (ret) {
@@ -138,6 +263,8 @@
__func__, ret);
goto bail;
}
+
+ msm_mpm_enter_sleep(sclk_count, from_idle);
}
bail:
return ret;
@@ -147,12 +274,12 @@
bool notify_rpm, bool collapsed)
{
- msm_lpmrs_exit_sleep((struct msm_rpmrs_limits *)limits,
- from_idle, notify_rpm, collapsed);
- if (notify_rpm)
+ msm_lpm_set_l2_mode(default_l2_mode);
+
+ if (notify_rpm) {
+ msm_mpm_exit_sleep(from_idle);
msm_rpm_exit_sleep();
- atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
- MSM_LPM_STATE_EXIT, NULL);
+ }
}
void msm_lpm_show_resources(void)
@@ -161,48 +288,6 @@
return;
}
-uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits)
-{
- return limits->pxo;
-}
-
-uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits)
-{
- return limits->l2_cache;
-}
-
-uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits)
-{
- return limits->vdd_mem_upper_bound;
-}
-
-uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits)
-{
- return limits->vdd_dig_upper_bound;
-}
-
-static bool lpm_level_permitted(int cur_level_count)
-{
- if (__get_cpu_var(lpm_permitted_level) == msm_lpm_level_count + 1)
- return true;
- return (__get_cpu_var(lpm_permitted_level) == cur_level_count);
-}
-
-int msm_lpm_register_notifier(int cpu, int level_iter,
- struct notifier_block *nb, bool is_latency_measure)
-{
- per_cpu(lpm_permitted_level, cpu) = level_iter;
- return atomic_notifier_chain_register(&per_cpu(lpm_notify_head,
- cpu), nb);
-}
-
-int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb)
-{
- per_cpu(lpm_permitted_level, cpu) = msm_lpm_level_count + 1;
- return atomic_notifier_chain_unregister(&per_cpu(lpm_notify_head, cpu),
- nb);
-}
-
s32 msm_cpuidle_get_deep_idle_latency(void)
{
int i;
@@ -225,17 +310,26 @@
}
return best->latency_us - 1;
}
-static bool msm_lpm_irqs_detectable(struct msm_rpmrs_limits *limits,
- bool irqs_detectable, bool gpio_detectable)
+
+static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
+ unsigned long action, void *hcpu)
{
- if (!limits->irqs_detectable)
- return irqs_detectable;
-
- if (!limits->gpio_detectable)
- return gpio_detectable;
-
- return true;
-
+ switch (action) {
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ allowed_l2_mode = default_l2_mode;
+ msm_lpm_level_update();
+ break;
+ case CPU_DEAD_FROZEN:
+ case CPU_DEAD:
+ case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
+ if (num_online_cpus() == 1)
+ allowed_l2_mode = MSM_SPM_L2_MODE_POWER_COLLAPSE;
+ msm_lpm_level_update();
+ break;
+ }
+ return NOTIFY_OK;
}
static void *msm_lpm_lowest_limits(bool from_idle,
@@ -244,24 +338,15 @@
{
unsigned int cpu = smp_processor_id();
struct msm_rpmrs_level *best_level = NULL;
+ uint32_t best_level_pwr = 0;
uint32_t pwr;
int i;
- int best_level_iter = msm_lpm_level_count + 1;
- bool irqs_detect = false;
- bool gpio_detect = false;
bool modify_event_timer;
uint32_t next_wakeup_us = time_param->sleep_us;
if (!msm_lpm_levels)
return NULL;
- msm_lpm_level_update();
-
- if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
- irqs_detect = msm_mpm_irqs_detectable(from_idle);
- gpio_detect = msm_mpm_gpio_irqs_detectable(from_idle);
- }
-
for (i = 0; i < msm_lpm_level_count; i++) {
struct msm_rpmrs_level *level = &msm_lpm_levels[i];
@@ -293,11 +378,6 @@
if (next_wakeup_us <= level->time_overhead_us)
continue;
- if ((sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) &&
- !msm_lpm_irqs_detectable(&level->rs_limits,
- irqs_detect, gpio_detect))
- continue;
-
if ((MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE == sleep_mode)
|| (MSM_PM_SLEEP_MODE_POWER_COLLAPSE == sleep_mode))
if (!cpu && msm_rpm_waiting_for_ack())
@@ -318,12 +398,10 @@
pwr += level->energy_overhead / next_wakeup_us;
}
- if (!best_level || best_level->rs_limits.power[cpu] >= pwr) {
+ if (!best_level || (best_level_pwr >= pwr)) {
- level->rs_limits.latency_us[cpu] = level->latency_us;
- level->rs_limits.power[cpu] = pwr;
best_level = level;
- best_level_iter = i;
+ best_level_pwr = pwr;
if (power)
*power = pwr;
if (modify_event_timer &&
@@ -336,32 +414,78 @@
time_param->modified_time_us = 0;
}
}
- if (best_level && !lpm_level_permitted(best_level_iter))
- best_level = NULL;
- else
- per_cpu(msm_lpm_sleep_time, cpu) =
- time_param->modified_time_us ?
- time_param->modified_time_us : time_param->sleep_us;
- return best_level ? &best_level->rs_limits : NULL;
+ return best_level ? &best_level->l2_cache : NULL;
}
-static struct lpm_test_platform_data lpm_test_pdata;
-
-static struct platform_device msm_lpm_test_device = {
- .name = "lpm_test",
- .id = -1,
- .dev = {
- .platform_data = &lpm_test_pdata,
- },
-};
-
static struct msm_pm_sleep_ops msm_lpm_ops = {
.lowest_limits = msm_lpm_lowest_limits,
.enter_sleep = msm_lpm_enter_sleep,
.exit_sleep = msm_lpm_exit_sleep,
};
+static int msm_lpm_get_l2_cache_value(struct device_node *node,
+ char *key, uint32_t *l2_val)
+{
+ int i;
+ struct lpm_lookup_table l2_mode_lookup[] = {
+ {MSM_SPM_L2_MODE_POWER_COLLAPSE, "l2_cache_pc"},
+ {MSM_SPM_L2_MODE_GDHS, "l2_cache_gdhs"},
+ {MSM_SPM_L2_MODE_RETENTION, "l2_cache_retention"},
+ {MSM_SPM_L2_MODE_DISABLED, "l2_cache_active"}
+ };
+ const char *l2_str;
+ int ret;
+
+ ret = of_property_read_string(node, key, &l2_str);
+ if (!ret) {
+ ret = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(l2_mode_lookup); i++) {
+ if (!strcmp(l2_str, l2_mode_lookup[i].mode_name)) {
+ *l2_val = l2_mode_lookup[i].modes;
+ ret = 0;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+static int __devinit msm_lpm_levels_sysfs_add(void)
+{
+ struct kobject *module_kobj = NULL;
+ struct kobject *low_power_kobj = NULL;
+ int rc = 0;
+
+ module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!module_kobj) {
+ pr_err("%s: cannot find kobject for module %s\n",
+ __func__, KBUILD_MODNAME);
+ rc = -ENOENT;
+ goto resource_sysfs_add_exit;
+ }
+
+ low_power_kobj = kobject_create_and_add(
+ "enable_low_power", module_kobj);
+ if (!low_power_kobj) {
+ pr_err("%s: cannot create kobject\n", __func__);
+ rc = -ENOMEM;
+ goto resource_sysfs_add_exit;
+ }
+
+ rc = sysfs_create_group(low_power_kobj, &lpm_levels_attr_grp);
+resource_sysfs_add_exit:
+ if (rc) {
+ if (low_power_kobj) {
+ sysfs_remove_group(low_power_kobj,
+ &lpm_levels_attr_grp);
+ kobject_del(low_power_kobj);
+ }
+ }
+
+ return rc;
+}
+
static int __devinit msm_lpm_levels_probe(struct platform_device *pdev)
{
struct msm_rpmrs_level *levels = NULL;
@@ -372,7 +496,6 @@
int ret = 0;
uint32_t num_levels = 0;
int idx = 0;
- unsigned int m_cpu = 0;
for_each_child_of_node(pdev->dev.of_node, node)
num_levels++;
@@ -392,49 +515,11 @@
goto fail;
level->sleep_mode = val;
- key = "qcom,xo";
- ret = msm_lpm_get_xo_value(node, key, &val);
- if (ret)
- goto fail;
- level->rs_limits.pxo = val;
-
key = "qcom,l2";
ret = msm_lpm_get_l2_cache_value(node, key, &val);
if (ret)
goto fail;
- level->rs_limits.l2_cache = val;
-
- key = "qcom,vdd-dig-upper-bound";
- ret = of_property_read_u32(node, key, &val);
- if (ret)
- goto fail;
- level->rs_limits.vdd_dig_upper_bound = val;
-
- key = "qcom,vdd-dig-lower-bound";
- ret = of_property_read_u32(node, key, &val);
- if (ret)
- goto fail;
- level->rs_limits.vdd_dig_lower_bound = val;
-
- key = "qcom,vdd-mem-upper-bound";
- ret = of_property_read_u32(node, key, &val);
- if (ret)
- goto fail;
- level->rs_limits.vdd_mem_upper_bound = val;
-
- key = "qcom,vdd-mem-lower-bound";
- ret = of_property_read_u32(node, key, &val);
- if (ret)
- goto fail;
- level->rs_limits.vdd_mem_lower_bound = val;
-
- key = "qcom,gpio-detectable";
- level->rs_limits.gpio_detectable =
- of_property_read_bool(node, key);
-
- key = "qcom,irqs-detectable";
- level->rs_limits.irqs_detectable =
- of_property_read_bool(node, key);
+ level->l2_cache = val;
key = "qcom,latency-us";
ret = of_property_read_u32(node, key, &val);
@@ -463,22 +548,33 @@
level->available = true;
}
+ node = pdev->dev.of_node;
+ key = "qcom,no-l2-saw";
+ no_l2_saw = of_property_read_bool(node, key);
+
msm_lpm_levels = levels;
msm_lpm_level_count = idx;
- lpm_test_pdata.msm_lpm_test_levels = msm_lpm_levels;
- lpm_test_pdata.msm_lpm_test_level_count = msm_lpm_level_count;
- key = "qcom,use-qtimer";
- lpm_test_pdata.use_qtimer =
- of_property_read_bool(pdev->dev.of_node, key);
+ if (num_online_cpus() == 1)
+ allowed_l2_mode = MSM_SPM_L2_MODE_POWER_COLLAPSE;
- for_each_possible_cpu(m_cpu)
- per_cpu(lpm_permitted_level, m_cpu) =
- msm_lpm_level_count + 1;
+ /* Do the following two steps only if L2 SAW is present */
+ if (!no_l2_saw) {
+ key = "qcom,default-l2-state";
+ if (msm_lpm_get_l2_cache_value(node, key, &default_l2_mode))
+ goto fail;
- platform_device_register(&msm_lpm_test_device);
+ if (msm_lpm_levels_sysfs_add())
+ goto fail;
+ register_hotcpu_notifier(&msm_lpm_cpu_nblk);
+ msm_pm_set_l2_flush_flag(0);
+ } else {
+ msm_pm_set_l2_flush_flag(1);
+ default_l2_mode = MSM_SPM_L2_MODE_POWER_COLLAPSE;
+ }
+
+ msm_lpm_level_update();
msm_pm_set_sleep_ops(&msm_lpm_ops);
-
return 0;
fail:
pr_err("%s: Error in name %s key %s\n", __func__, node->full_name, key);
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
deleted file mode 100644
index 1d9c539..0000000
--- a/arch/arm/mach-msm/lpm_resources.c
+++ /dev/null
@@ -1,1009 +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/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/cpu.h>
-#include <linux/notifier.h>
-#include <linux/hrtimer.h>
-#include <linux/tick.h>
-#include <mach/mpm.h>
-#include <mach/rpm-smd.h>
-#include <mach/trace_msm_low_power.h>
-#include "spm.h"
-#include "lpm_resources.h"
-#include "rpm-notifier.h"
-#include "idle.h"
-
-
-/*Debug Definitions*/
-enum {
- MSM_LPMRS_DEBUG_RPM = BIT(0),
- MSM_LPMRS_DEBUG_PXO = BIT(1),
- MSM_LPMRS_DEBUG_VDD_DIG = BIT(2),
- MSM_LPMRS_DEBUG_VDD_MEM = BIT(3),
- MSM_LPMRS_DEBUG_L2 = BIT(4),
- MSM_LPMRS_DEBUG_LVLS = BIT(5),
-};
-
-static int msm_lpm_debug_mask;
-module_param_named(
- debug_mask, msm_lpm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP
-);
-
-static bool msm_lpm_get_rpm_notif = true;
-
-/*Macros*/
-#define MAX_RS_NAME (16)
-#define MAX_RS_SIZE (4)
-#define IS_RPM_CTL(rs) \
- (!strncmp(rs->name, "rpm_ctl", MAX_RS_NAME))
-#define MAX_STR_LEN 30
-
-static bool msm_lpm_beyond_limits_vdd_dig(struct msm_rpmrs_limits *limits);
-static void msm_lpm_aggregate_vdd_dig(struct msm_rpmrs_limits *limits);
-static void msm_lpm_flush_vdd_dig(int notify_rpm);
-static void msm_lpm_notify_vdd_dig(struct msm_rpm_notifier_data
- *rpm_notifier_cb);
-static int msm_lpm_init_value_vdd_dig(struct device_node *node,
- char *key, uint32_t *default_value);
-
-static bool msm_lpm_beyond_limits_vdd_mem(struct msm_rpmrs_limits *limits);
-static void msm_lpm_aggregate_vdd_mem(struct msm_rpmrs_limits *limits);
-static void msm_lpm_flush_vdd_mem(int notify_rpm);
-static void msm_lpm_notify_vdd_mem(struct msm_rpm_notifier_data
- *rpm_notifier_cb);
-static int msm_lpm_init_value_vdd_mem(struct device_node *node,
- char *key, uint32_t *default_value);
-
-
-static bool msm_lpm_beyond_limits_pxo(struct msm_rpmrs_limits *limits);
-static void msm_lpm_aggregate_pxo(struct msm_rpmrs_limits *limits);
-static void msm_lpm_flush_pxo(int notify_rpm);
-static void msm_lpm_notify_pxo(struct msm_rpm_notifier_data
- *rpm_notifier_cb);
-static int msm_lpm_init_value_pxo(struct device_node *node,
- char *key, uint32_t *default_value);
-
-
-static bool msm_lpm_beyond_limits_l2(struct msm_rpmrs_limits *limits);
-static void msm_lpm_flush_l2(int notify_rpm);
-static void msm_lpm_aggregate_l2(struct msm_rpmrs_limits *limits);
-static int msm_lpm_init_value_l2(struct device_node *node,
- char *key, uint32_t *default_value);
-
-static void msm_lpm_flush_rpm_ctl(int notify_rpm);
-
-static int msm_lpm_rpm_callback(struct notifier_block *rpm_nb,
- unsigned long action, void *rpm_notif);
-
-static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
- unsigned long action, void *hcpu);
-
-static ssize_t msm_lpm_resource_attr_show(
- struct kobject *kobj, struct kobj_attribute *attr, char *buf);
-static ssize_t msm_lpm_resource_attr_store(struct kobject *kobj,
- struct kobj_attribute *attr, const char *buf, size_t count);
-
-
-#define RPMRS_ATTR(_name) \
- __ATTR(_name, S_IRUGO|S_IWUSR, \
- msm_lpm_resource_attr_show, msm_lpm_resource_attr_store)
-
-/*Data structures*/
-struct msm_lpm_rs_data {
- uint32_t type;
- uint32_t id;
- uint32_t key;
- uint32_t value;
- uint32_t default_value;
- struct msm_rpm_request *handle;
-};
-
-enum {
- MSM_LPM_RPM_RS_TYPE = 0,
- MSM_LPM_LOCAL_RS_TYPE = 1,
-};
-
-enum {
- MSM_SCM_L2_ON = 0,
- MSM_SCM_L2_OFF = 1,
- MSM_SCM_L2_GDHS = 3,
-};
-
-struct msm_lpm_resource {
- struct msm_lpm_rs_data rs_data;
- uint32_t sleep_value;
- char name[MAX_RS_NAME];
-
- uint32_t enable_low_power;
- bool valid;
-
- bool (*beyond_limits)(struct msm_rpmrs_limits *limits);
- void (*aggregate)(struct msm_rpmrs_limits *limits);
- void (*flush)(int notify_rpm);
- void (*notify)(struct msm_rpm_notifier_data *rpm_notifier_cb);
- struct kobj_attribute ko_attr;
- int (*init_value)(struct device_node *node,
- char *key, uint32_t *default_value);
-};
-
-struct lpm_lookup_table {
- uint32_t modes;
- const char *mode_name;
-};
-
-static struct msm_lpm_resource msm_lpm_l2 = {
- .name = "l2",
- .beyond_limits = msm_lpm_beyond_limits_l2,
- .aggregate = msm_lpm_aggregate_l2,
- .flush = msm_lpm_flush_l2,
- .notify = NULL,
- .valid = false,
- .ko_attr = RPMRS_ATTR(l2),
- .init_value = msm_lpm_init_value_l2,
-};
-
-static struct msm_lpm_resource msm_lpm_vdd_dig = {
- .name = "vdd-dig",
- .beyond_limits = msm_lpm_beyond_limits_vdd_dig,
- .aggregate = msm_lpm_aggregate_vdd_dig,
- .flush = msm_lpm_flush_vdd_dig,
- .notify = msm_lpm_notify_vdd_dig,
- .valid = false,
- .ko_attr = RPMRS_ATTR(vdd_dig),
- .init_value = msm_lpm_init_value_vdd_dig,
-};
-
-static struct msm_lpm_resource msm_lpm_vdd_mem = {
- .name = "vdd-mem",
- .beyond_limits = msm_lpm_beyond_limits_vdd_mem,
- .aggregate = msm_lpm_aggregate_vdd_mem,
- .flush = msm_lpm_flush_vdd_mem,
- .notify = msm_lpm_notify_vdd_mem,
- .valid = false,
- .ko_attr = RPMRS_ATTR(vdd_mem),
- .init_value = msm_lpm_init_value_vdd_mem,
-};
-
-static struct msm_lpm_resource msm_lpm_pxo = {
- .name = "pxo",
- .beyond_limits = msm_lpm_beyond_limits_pxo,
- .aggregate = msm_lpm_aggregate_pxo,
- .flush = msm_lpm_flush_pxo,
- .notify = msm_lpm_notify_pxo,
- .valid = false,
- .ko_attr = RPMRS_ATTR(pxo),
- .init_value = msm_lpm_init_value_pxo,
-};
-
-static struct msm_lpm_resource *msm_lpm_resources[] = {
- &msm_lpm_vdd_dig,
- &msm_lpm_vdd_mem,
- &msm_lpm_pxo,
- &msm_lpm_l2,
-};
-
-static struct msm_lpm_resource msm_lpm_rpm_ctl = {
- .name = "rpm_ctl",
- .beyond_limits = NULL,
- .aggregate = NULL,
- .flush = msm_lpm_flush_rpm_ctl,
- .valid = true,
- .ko_attr = RPMRS_ATTR(rpm_ctl),
-};
-
-static struct notifier_block msm_lpm_rpm_nblk = {
- .notifier_call = msm_lpm_rpm_callback,
-};
-
-static struct notifier_block __refdata msm_lpm_cpu_nblk = {
- .notifier_call = msm_lpm_cpu_callback,
-};
-
-static DEFINE_SPINLOCK(msm_lpm_sysfs_lock);
-
-/* Attribute Definitions */
-static struct attribute *msm_lpm_attributes[] = {
- &msm_lpm_vdd_dig.ko_attr.attr,
- &msm_lpm_vdd_mem.ko_attr.attr,
- &msm_lpm_pxo.ko_attr.attr,
- &msm_lpm_l2.ko_attr.attr,
- NULL,
-};
-
-static struct attribute_group msm_lpm_attribute_group = {
- .attrs = msm_lpm_attributes,
-};
-
-static struct attribute *msm_lpm_rpm_ctl_attribute[] = {
- &msm_lpm_rpm_ctl.ko_attr.attr,
- NULL,
-};
-
-static struct attribute_group msm_lpm_rpm_ctl_attr_group = {
- .attrs = msm_lpm_rpm_ctl_attribute,
-};
-
-#define GET_RS_FROM_ATTR(attr) \
- (container_of(attr, struct msm_lpm_resource, ko_attr))
-
-/* RPM */
-static struct msm_rpm_request *msm_lpm_create_rpm_request
- (uint32_t rsc_type, uint32_t rsc_id)
-{
- struct msm_rpm_request *handle = NULL;
-
- handle = msm_rpm_create_request(MSM_RPM_CTX_SLEEP_SET,
- rsc_type,
- rsc_id, 1);
- return handle;
-}
-
-static int msm_lpm_send_sleep_data(struct msm_rpm_request *handle,
- uint32_t key, uint8_t *value)
-{
- int ret = 0;
- int msg_id;
-
- if (!handle)
- return ret;
-
- ret = msm_rpm_add_kvp_data_noirq(handle, key, value, MAX_RS_SIZE);
-
- if (ret < 0) {
- pr_err("%s: Error adding kvp data key %u, size %d\n",
- __func__, key, MAX_RS_SIZE);
- return ret;
- }
-
- msg_id = msm_rpm_send_request_noirq(handle);
- if (!msg_id) {
- pr_err("%s: Error sending RPM request key %u, handle 0x%x\n",
- __func__, key, (unsigned int)handle);
- ret = -EIO;
- return ret;
- }
-
- ret = msm_rpm_wait_for_ack_noirq(msg_id);
- if (ret < 0) {
- pr_err("%s: Couldn't get ACK from RPM for Msg %d Error %d",
- __func__, msg_id, ret);
- return ret;
- }
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_RPM)
- pr_info("Rs key %u, value %u, size %d\n", key,
- *(unsigned int *)value, MAX_RS_SIZE);
- return ret;
-}
-
-/* RPM Notifier */
-static int msm_lpm_rpm_callback(struct notifier_block *rpm_nb,
- unsigned long action,
- void *rpm_notif)
-{
- int i;
- struct msm_lpm_resource *rs = NULL;
- struct msm_rpm_notifier_data *rpm_notifier_cb =
- (struct msm_rpm_notifier_data *)rpm_notif;
-
- if (!msm_lpm_get_rpm_notif)
- return NOTIFY_DONE;
-
- if (!(rpm_nb && rpm_notif))
- return NOTIFY_BAD;
-
- for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
- rs = msm_lpm_resources[i];
- if (rs && rs->valid && rs->notify)
- rs->notify(rpm_notifier_cb);
- }
-
- return NOTIFY_OK;
-}
-
-/* SYSFS */
-static ssize_t msm_lpm_resource_attr_show(
- struct kobject *kobj, struct kobj_attribute *attr, char *buf)
-{
- struct kernel_param kp;
- unsigned long flags;
- unsigned int temp;
- int rc;
-
- spin_lock_irqsave(&msm_lpm_sysfs_lock, flags);
- temp = GET_RS_FROM_ATTR(attr)->enable_low_power;
- spin_unlock_irqrestore(&msm_lpm_sysfs_lock, flags);
-
- kp.arg = &temp;
- rc = param_get_uint(buf, &kp);
-
- if (rc > 0) {
- strlcat(buf, "\n", PAGE_SIZE);
- rc++;
- }
-
- return rc;
-}
-
-static ssize_t msm_lpm_resource_attr_store(struct kobject *kobj,
- struct kobj_attribute *attr, const char *buf, size_t count)
-{
- struct kernel_param kp;
- unsigned long flags;
- unsigned int temp;
- int rc;
-
- kp.arg = &temp;
- rc = param_set_uint(buf, &kp);
- if (rc)
- return rc;
-
- spin_lock_irqsave(&msm_lpm_sysfs_lock, flags);
- GET_RS_FROM_ATTR(attr)->enable_low_power = temp;
-
- if (IS_RPM_CTL(GET_RS_FROM_ATTR(attr))) {
- struct msm_lpm_resource *rs = GET_RS_FROM_ATTR(attr);
- rs->flush(false);
- }
-
- spin_unlock_irqrestore(&msm_lpm_sysfs_lock, flags);
-
- return count;
-}
-
-/* lpm resource handling functions */
-/* Common */
-static void msm_lpm_notify_common(struct msm_rpm_notifier_data *cb,
- struct msm_lpm_resource *rs)
-{
- if ((cb->rsc_type == rs->rs_data.type) &&
- (cb->rsc_id == rs->rs_data.id) &&
- (cb->key == rs->rs_data.key)) {
-
- BUG_ON(cb->size > MAX_RS_SIZE);
-
- if (rs->valid) {
- if (cb->value) {
- memcpy(&rs->rs_data.value, cb->value, cb->size);
- msm_rpm_add_kvp_data_noirq(rs->rs_data.handle,
- cb->key, cb->value, cb->size);
- }
- else
- rs->rs_data.value = rs->rs_data.default_value;
-
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_RPM)
- pr_info("Notification received Rs %s value %u\n",
- rs->name, rs->rs_data.value);
- }
- }
-}
-
-/* L2 */
-static bool msm_lpm_beyond_limits_l2(struct msm_rpmrs_limits *limits)
-{
- uint32_t l2;
- bool ret = false;
- struct msm_lpm_resource *rs = &msm_lpm_l2;
-
- if (rs->valid) {
- uint32_t l2_buf = rs->rs_data.value;
-
- if (rs->enable_low_power == 1)
- l2 = MSM_LPM_L2_CACHE_GDHS;
- else if (rs->enable_low_power == 2)
- l2 = MSM_LPM_L2_CACHE_HSFS_OPEN;
- else
- l2 = MSM_LPM_L2_CACHE_ACTIVE ;
-
- if (l2_buf > l2)
- l2 = l2_buf;
- ret = (l2 > limits->l2_cache);
-
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_L2)
- pr_info("%s: l2 buf %u, l2 %u, limits %u\n",
- __func__, l2_buf, l2, limits->l2_cache);
- }
- return ret;
-}
-
-static void msm_lpm_aggregate_l2(struct msm_rpmrs_limits *limits)
-{
- struct msm_lpm_resource *rs = &msm_lpm_l2;
-
- if (rs->valid)
- rs->sleep_value = limits->l2_cache;
- trace_lpm_resources(rs->sleep_value, rs->name);
-}
-
-static void msm_lpm_set_l2_mode(int sleep_mode)
-{
- int lpm, rc;
-
- msm_pm_set_l2_flush_flag(MSM_SCM_L2_ON);
-
- switch (sleep_mode) {
- case MSM_LPM_L2_CACHE_HSFS_OPEN:
- lpm = MSM_SPM_L2_MODE_POWER_COLLAPSE;
- msm_pm_set_l2_flush_flag(MSM_SCM_L2_OFF);
- break;
- case MSM_LPM_L2_CACHE_GDHS:
- lpm = MSM_SPM_L2_MODE_GDHS;
- msm_pm_set_l2_flush_flag(MSM_SCM_L2_GDHS);
- break;
- case MSM_LPM_L2_CACHE_RETENTION:
- lpm = MSM_SPM_L2_MODE_RETENTION;
- break;
- default:
- case MSM_LPM_L2_CACHE_ACTIVE:
- lpm = MSM_SPM_L2_MODE_DISABLED;
- break;
- }
-
- rc = msm_spm_l2_set_low_power_mode(lpm, true);
-
- if (rc < 0)
- pr_err("%s: Failed to set L2 low power mode %d",
- __func__, lpm);
-
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_L2)
- pr_info("%s: Requesting low power mode %d\n",
- __func__, lpm);
-}
-
-static int msm_lpm_init_value_l2(struct device_node *node,
- char *key, uint32_t *default_value)
-{
- return msm_lpm_get_l2_cache_value(node, key, default_value);
-}
-
-static void msm_lpm_flush_l2(int notify_rpm)
-{
- struct msm_lpm_resource *rs = &msm_lpm_l2;
-
- msm_lpm_set_l2_mode(rs->sleep_value);
-}
-
-int msm_lpm_get_l2_cache_value(struct device_node *node,
- char *key, uint32_t *l2_val)
-{
- int i;
- struct lpm_lookup_table l2_mode_lookup[] = {
- {MSM_LPM_L2_CACHE_HSFS_OPEN, "l2_cache_pc"},
- {MSM_LPM_L2_CACHE_GDHS, "l2_cache_gdhs"},
- {MSM_LPM_L2_CACHE_RETENTION, "l2_cache_retention"},
- {MSM_LPM_L2_CACHE_ACTIVE, "l2_cache_active"}
- };
- const char *l2_str;
- int ret;
-
- ret = of_property_read_string(node, key, &l2_str);
- if (!ret) {
- ret = -EINVAL;
- for (i = 0; i < ARRAY_SIZE(l2_mode_lookup); i++) {
- if (!strncmp(l2_str, l2_mode_lookup[i].mode_name,
- MAX_STR_LEN)) {
- *l2_val = l2_mode_lookup[i].modes;
- ret = 0;
- break;
- }
- }
- }
- return ret;
-}
-
-/* RPM CTL */
-static void msm_lpm_flush_rpm_ctl(int notify_rpm)
-{
- struct msm_lpm_resource *rs = &msm_lpm_rpm_ctl;
- msm_lpm_send_sleep_data(rs->rs_data.handle,
- rs->rs_data.key,
- (uint8_t *)&rs->sleep_value);
-}
-
-/*VDD Dig*/
-static bool msm_lpm_beyond_limits_vdd_dig(struct msm_rpmrs_limits *limits)
-{
- bool ret = true;
- struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
-
- if (rs->valid) {
- uint32_t vdd_buf = rs->rs_data.value;
- uint32_t vdd_dig = rs->enable_low_power ? rs->enable_low_power :
- rs->rs_data.default_value;
-
- if (vdd_buf > vdd_dig)
- vdd_dig = vdd_buf;
-
- ret = (vdd_dig > limits->vdd_dig_upper_bound);
-
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_VDD_DIG)
- pr_info("%s:buf %d vdd dig %d limits%d\n",
- __func__, vdd_buf, vdd_dig,
- limits->vdd_dig_upper_bound);
- }
- return ret;
-}
-
-static int msm_lpm_init_value_vdd_dig(struct device_node *node,
- char *key, uint32_t *default_value)
-{
- return of_property_read_u32(node, key, default_value);
-}
-
-static void msm_lpm_aggregate_vdd_dig(struct msm_rpmrs_limits *limits)
-{
- struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
-
- if (rs->valid) {
- uint32_t vdd_buf = rs->rs_data.value;
- if (limits->vdd_dig_lower_bound > vdd_buf)
- rs->sleep_value = limits->vdd_dig_lower_bound;
- else
- rs->sleep_value = vdd_buf;
- }
- trace_lpm_resources(rs->sleep_value, rs->name);
-}
-
-static void msm_lpm_flush_vdd_dig(int notify_rpm)
-{
- if (notify_rpm) {
- struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
- msm_lpm_send_sleep_data(rs->rs_data.handle,
- rs->rs_data.key,
- (uint8_t *)&rs->sleep_value);
- }
-}
-
-static void msm_lpm_notify_vdd_dig(struct msm_rpm_notifier_data
- *rpm_notifier_cb)
-{
- struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
- msm_lpm_notify_common(rpm_notifier_cb, rs);
-}
-
-/*VDD Mem*/
-static bool msm_lpm_beyond_limits_vdd_mem(struct msm_rpmrs_limits *limits)
-{
- bool ret = true;
- struct msm_lpm_resource *rs = &msm_lpm_vdd_mem;
-
- if (rs->valid) {
- uint32_t vdd_buf = rs->rs_data.value;
- uint32_t vdd_mem = rs->enable_low_power ? rs->enable_low_power :
- rs->rs_data.default_value;
-
- if (vdd_buf > vdd_mem)
- vdd_mem = vdd_buf;
-
- ret = (vdd_mem > limits->vdd_mem_upper_bound);
-
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_VDD_MEM)
- pr_info("%s:buf %d vdd mem %d limits%d\n",
- __func__, vdd_buf, vdd_mem,
- limits->vdd_mem_upper_bound);
- }
- return ret;
-}
-
-static void msm_lpm_aggregate_vdd_mem(struct msm_rpmrs_limits *limits)
-{
- struct msm_lpm_resource *rs = &msm_lpm_vdd_mem;
-
- if (rs->valid) {
- uint32_t vdd_buf = rs->rs_data.value;
- if (limits->vdd_mem_lower_bound > vdd_buf)
- rs->sleep_value = limits->vdd_mem_lower_bound;
- else
- rs->sleep_value = vdd_buf;
- }
- trace_lpm_resources(rs->sleep_value, rs->name);
-}
-
-static void msm_lpm_flush_vdd_mem(int notify_rpm)
-{
- if (notify_rpm) {
- struct msm_lpm_resource *rs = &msm_lpm_vdd_mem;
- msm_lpm_send_sleep_data(rs->rs_data.handle,
- rs->rs_data.key,
- (uint8_t *)&rs->sleep_value);
- }
-}
-
-static void msm_lpm_notify_vdd_mem(struct msm_rpm_notifier_data
- *rpm_notifier_cb)
-{
- struct msm_lpm_resource *rs = &msm_lpm_vdd_mem;
- msm_lpm_notify_common(rpm_notifier_cb, rs);
-}
-
-static int msm_lpm_init_value_vdd_mem(struct device_node *node,
- char *key, uint32_t *default_value)
-{
- return of_property_read_u32(node, key, default_value);
-}
-
-/*PXO*/
-static bool msm_lpm_beyond_limits_pxo(struct msm_rpmrs_limits *limits)
-{
- bool ret = true;
- struct msm_lpm_resource *rs = &msm_lpm_pxo;
-
- if (rs->valid) {
- uint32_t pxo_buf = rs->rs_data.value;
- uint32_t pxo = rs->enable_low_power ? MSM_LPM_PXO_OFF :
- rs->rs_data.default_value;
-
- if (pxo_buf > pxo)
- pxo = pxo_buf;
-
- ret = (pxo > limits->pxo);
-
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_PXO)
- pr_info("%s:pxo buf %d pxo %d limits pxo %d\n",
- __func__, pxo_buf, pxo, limits->pxo);
- }
- return ret;
-}
-
-static void msm_lpm_aggregate_pxo(struct msm_rpmrs_limits *limits)
-{
- struct msm_lpm_resource *rs = &msm_lpm_pxo;
-
- if (rs->valid) {
- uint32_t pxo_buf = rs->rs_data.value;
- if (limits->pxo > pxo_buf)
- rs->sleep_value = limits->pxo;
- else
- rs->sleep_value = pxo_buf;
-
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_PXO)
- pr_info("%s: pxo buf %d sleep value %d\n",
- __func__, pxo_buf, rs->sleep_value);
- }
- trace_lpm_resources(rs->sleep_value, rs->name);
-}
-
-static void msm_lpm_flush_pxo(int notify_rpm)
-{
- if (notify_rpm) {
- struct msm_lpm_resource *rs = &msm_lpm_pxo;
- msm_lpm_send_sleep_data(rs->rs_data.handle,
- rs->rs_data.key,
- (uint8_t *)&rs->sleep_value);
- }
-}
-
-static void msm_lpm_notify_pxo(struct msm_rpm_notifier_data
- *rpm_notifier_cb)
-{
- struct msm_lpm_resource *rs = &msm_lpm_pxo;
- msm_lpm_notify_common(rpm_notifier_cb, rs);
-}
-
-static int msm_lpm_init_value_pxo(struct device_node *node,
- char *key, uint32_t *default_value)
-{
- return msm_lpm_get_xo_value(node, key, default_value);
-}
-
-static inline bool msm_lpm_use_mpm(struct msm_rpmrs_limits *limits)
-{
- return (limits->pxo == MSM_LPM_PXO_OFF);
-}
-
-int msm_lpm_get_xo_value(struct device_node *node,
- char *key, uint32_t *xo_val)
-{
- int i;
- struct lpm_lookup_table pxo_mode_lookup[] = {
- {MSM_LPM_PXO_OFF, "xo_off"},
- {MSM_LPM_PXO_ON, "xo_on"}
- };
- const char *xo_str;
- int ret;
-
- ret = of_property_read_string(node, key, &xo_str);
- if (!ret) {
- ret = -EINVAL;
- for (i = 0; i < ARRAY_SIZE(pxo_mode_lookup); i++) {
- if (!strncmp(xo_str, pxo_mode_lookup[i].mode_name,
- MAX_STR_LEN)) {
- *xo_val = pxo_mode_lookup[i].modes;
- ret = 0;
- break;
- }
- }
- }
- return ret;
-}
-
-/* LPM levels interface */
-bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits)
-{
- int i;
- struct msm_lpm_resource *rs;
- bool beyond_limit = false;
-
- for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
- rs = msm_lpm_resources[i];
- if (rs->beyond_limits && rs->beyond_limits(limits)) {
- beyond_limit = true;
- if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_LVLS)
- pr_info("%s: %s beyond limit", __func__,
- rs->name);
- break;
- }
- }
-
- return beyond_limit;
-}
-
-int msm_lpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm)
-{
- int ret = 0;
- int i;
- struct msm_lpm_resource *rs = NULL;
-
- for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
- rs = msm_lpm_resources[i];
- if (rs->aggregate)
- rs->aggregate(limits);
- }
-
- msm_lpm_get_rpm_notif = false;
- for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
- rs = msm_lpm_resources[i];
- if (rs->valid && rs->flush)
- rs->flush(notify_rpm);
- }
- msm_lpm_get_rpm_notif = true;
-
- if (notify_rpm)
- msm_mpm_enter_sleep(sclk_count, from_idle);
-
- return ret;
-}
-
-void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm, bool collapsed)
-{
- if (msm_lpm_use_mpm(limits))
- msm_mpm_exit_sleep(from_idle);
-
- if (msm_lpm_l2.valid)
- msm_lpm_set_l2_mode(msm_lpm_l2.rs_data.default_value);
-}
-
-static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
- unsigned long action, void *hcpu)
-{
- struct msm_lpm_resource *rs = &msm_lpm_l2;
- switch (action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- rs->rs_data.value = rs->rs_data.default_value;
- break;
- case CPU_ONLINE_FROZEN:
- case CPU_ONLINE:
- if (num_online_cpus() > 1)
- rs->rs_data.value = rs->rs_data.default_value;
- break;
- case CPU_DEAD_FROZEN:
- case CPU_DEAD:
- if (num_online_cpus() == 1)
- rs->rs_data.value = MSM_LPM_L2_CACHE_HSFS_OPEN;
- break;
- }
- return NOTIFY_OK;
-}
-
-/* RPM CTL */
-static int __devinit msm_lpm_init_rpm_ctl(void)
-{
- struct msm_lpm_resource *rs = &msm_lpm_rpm_ctl;
-
- rs->rs_data.handle = msm_rpm_create_request(
- MSM_RPM_CTX_ACTIVE_SET,
- rs->rs_data.type,
- rs->rs_data.id, 1);
- if (!rs->rs_data.handle)
- return -EIO;
-
- rs->valid = true;
- return 0;
-}
-
-static int __devinit msm_lpm_resource_sysfs_add(void)
-{
- struct kobject *module_kobj = NULL;
- struct kobject *low_power_kobj = NULL;
- struct kobject *mode_kobj = NULL;
- int rc = 0;
-
- module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
- if (!module_kobj) {
- pr_err("%s: cannot find kobject for module %s\n",
- __func__, KBUILD_MODNAME);
- rc = -ENOENT;
- goto resource_sysfs_add_exit;
- }
-
- low_power_kobj = kobject_create_and_add(
- "enable_low_power", module_kobj);
- if (!low_power_kobj) {
- pr_err("%s: cannot create kobject\n", __func__);
- rc = -ENOMEM;
- goto resource_sysfs_add_exit;
- }
-
- mode_kobj = kobject_create_and_add(
- "mode", module_kobj);
- if (!mode_kobj) {
- pr_err("%s: cannot create kobject\n", __func__);
- rc = -ENOMEM;
- goto resource_sysfs_add_exit;
- }
-
- rc = sysfs_create_group(low_power_kobj, &msm_lpm_attribute_group);
- if (rc) {
- pr_err("%s: cannot create kobject attribute group\n", __func__);
- goto resource_sysfs_add_exit;
- }
-
- rc = sysfs_create_group(mode_kobj, &msm_lpm_rpm_ctl_attr_group);
- if (rc) {
- pr_err("%s: cannot create kobject attribute group\n", __func__);
- goto resource_sysfs_add_exit;
- }
-
-resource_sysfs_add_exit:
- if (rc) {
- if (low_power_kobj)
- sysfs_remove_group(low_power_kobj,
- &msm_lpm_attribute_group);
- kobject_del(low_power_kobj);
- kobject_del(mode_kobj);
- }
-
- return rc;
-}
-
-late_initcall(msm_lpm_resource_sysfs_add);
-
-static int __devinit msm_lpmrs_probe(struct platform_device *pdev)
-{
- struct device_node *node = NULL;
- char *key = NULL;
- int ret = 0;
-
- for_each_child_of_node(pdev->dev.of_node, node) {
- struct msm_lpm_resource *rs = NULL;
- const char *val;
- int i;
- bool local_resource;
-
- key = "qcom,name";
- ret = of_property_read_string(node, key, &val);
- if (ret) {
- pr_err("Cannot read string\n");
- goto fail;
- }
-
- for (i = 0; i < ARRAY_SIZE(msm_lpm_resources); i++) {
- char *lpmrs_name = msm_lpm_resources[i]->name;
- if (!msm_lpm_resources[i]->valid &&
- !strncmp(val, lpmrs_name, strnlen(lpmrs_name,
- MAX_RS_NAME))) {
- rs = msm_lpm_resources[i];
- break;
- }
- }
-
- if (!rs) {
- pr_err("LPM resource not found\n");
- continue;
- }
-
- key = "qcom,init-value";
- ret = rs->init_value(node, key, &rs->rs_data.default_value);
- if (ret) {
- pr_err("%s():Failed to read %s\n", __func__, key);
- goto fail;
- }
-
- rs->rs_data.value = rs->rs_data.default_value;
-
- key = "qcom,local-resource-type";
- local_resource = of_property_read_bool(node, key);
-
- if (!local_resource) {
- key = "qcom,type";
- ret = of_property_read_u32(node, key,
- &rs->rs_data.type);
- if (ret) {
- pr_err("Failed to read type\n");
- goto fail;
- }
-
- key = "qcom,id";
- ret = of_property_read_u32(node, key, &rs->rs_data.id);
- if (ret) {
- pr_err("Failed to read id\n");
- goto fail;
- }
-
- key = "qcom,key";
- ret = of_property_read_u32(node, key, &rs->rs_data.key);
- if (ret) {
- pr_err("Failed to read key\n");
- goto fail;
- }
-
- rs->rs_data.handle = msm_lpm_create_rpm_request(
- rs->rs_data.type,
- rs->rs_data.id);
-
- if (!rs->rs_data.handle) {
- pr_err("%s: Failed to allocate handle for %s\n",
- __func__, rs->name);
- ret = -1;
- goto fail;
- }
- /* fall through */
- }
-
- rs->valid = true;
- }
- msm_rpm_register_notifier(&msm_lpm_rpm_nblk);
- msm_lpm_init_rpm_ctl();
-
- if (msm_lpm_l2.valid) {
- register_hotcpu_notifier(&msm_lpm_cpu_nblk);
- /* For UP mode, set the default to HSFS OPEN*/
- if (num_possible_cpus() == 1) {
- msm_lpm_l2.rs_data.default_value =
- MSM_LPM_L2_CACHE_HSFS_OPEN;
- msm_lpm_l2.rs_data.value = MSM_LPM_L2_CACHE_HSFS_OPEN;
- }
- msm_pm_set_l2_flush_flag(0);
- } else
- msm_pm_set_l2_flush_flag(1);
-
-fail:
- return ret;
-}
-
-static struct of_device_id msm_lpmrs_match_table[] = {
- {.compatible = "qcom,lpm-resources"},
- {},
-};
-
-static struct platform_driver msm_lpmrs_driver = {
- .probe = msm_lpmrs_probe,
- .driver = {
- .name = "lpm-resources",
- .owner = THIS_MODULE,
- .of_match_table = msm_lpmrs_match_table,
- },
-};
-
-int __init msm_lpmrs_module_init(void)
-{
- return platform_driver_register(&msm_lpmrs_driver);
-}
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
deleted file mode 100644
index 105cfe6..0000000
--- a/arch/arm/mach-msm/lpm_resources.h
+++ /dev/null
@@ -1,235 +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.
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_LPM_RESOURCES_H
-#define __ARCH_ARM_MACH_MSM_LPM_RESOURCES_H
-
-#include "pm.h"
-#include "test-lpm.h"
-
-enum {
- MSM_LPM_PXO_OFF,
- MSM_LPM_PXO_ON
-};
-
-enum {
- MSM_LPM_L2_CACHE_HSFS_OPEN,
- MSM_LPM_L2_CACHE_GDHS,
- MSM_LPM_L2_CACHE_RETENTION,
- MSM_LPM_L2_CACHE_ACTIVE,
-};
-
-struct msm_rpmrs_limits {
- uint32_t pxo;
- uint32_t l2_cache;
- uint32_t vdd_mem_upper_bound;
- uint32_t vdd_mem_lower_bound;
- uint32_t vdd_dig_upper_bound;
- uint32_t vdd_dig_lower_bound;
- bool irqs_detectable;
- bool gpio_detectable;
-
- uint32_t latency_us[NR_CPUS];
- uint32_t power[NR_CPUS];
-};
-
-struct msm_rpmrs_level {
- enum msm_pm_sleep_mode sleep_mode;
- struct msm_rpmrs_limits rs_limits;
- bool available;
- uint32_t latency_us;
- uint32_t steady_state_power;
- uint32_t energy_overhead;
- uint32_t time_overhead_us;
-};
-
-enum {
- MSM_LPM_STATE_ENTER = 0,
- MSM_LPM_STATE_EXIT = 1,
-};
-
-#define MSM_PM(field) MSM_LPM_##field
-
-/**
- * msm_pm_get_pxo() - get the limits for pxo
- * @limits: pointer to the msm_rpmrs_limits structure
- *
- * This function gets the limits to the resource pxo on
- * 8974
- */
-
-uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_pm_get_l2_cache() - get the limits for l2 cache
- * @limits: pointer to the msm_rpmrs_limits structure
- *
- * This function gets the limits to the resource l2 cache
- * on 8974
- */
-
-uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_pm_get_vdd_mem() - get the limits for pxo
- * @limits: pointer to the msm_rpmrs_limits structure
- *
- * This function gets the limits to the resource vdd mem
- * on 8974
- */
-
-uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_pm_get_vdd_dig() - get the limits for vdd dig
- * @limits: pointer to the msm_rpmrs_limits structure
- *
- * This function gets the limits to the resource on 8974
- */
-
-uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_lpm_get_xo_value() - get the enum value for xo
- * @node pointer to the device node
- * @key pxo property key
- * @xo_val xo enum value
- */
-int msm_lpm_get_xo_value(struct device_node *node,
- char *key, uint32_t *xo_val);
-
-/**
- * msm_lpm_get_l2_cache_value() - get the enum value for l2 cache
- * @node pointer to the device node
- * @key l2 cache property key
- * @l2_val l2 mode enum value
- */
-int msm_lpm_get_l2_cache_value(struct device_node *node,
- char *key, uint32_t *l2_val);
-
-/**
- * struct msm_lpm_sleep_data - abstraction to get sleep data
- * @limits: pointer to the msm_rpmrs_limits structure
- * @kernel_sleep: kernel sleep time as decided by the power calculation
- * algorithm
- *
- * This structure is an abstraction to get the limits and kernel sleep time
- * during enter sleep.
- */
-
-struct msm_lpm_sleep_data {
- struct msm_rpmrs_limits *limits;
- uint32_t kernel_sleep;
-};
-
-/**
- * msm_lpm_register_notifier() - register for notifications
- * @cpu: cpu to debug
- * @level_iter: low power level index to debug
- * @nb: notifier block to callback on notifications
- * @is_latency_measure: is it latency measure
- *
- * This function sets the permitted level to the index of the
- * level under test and registers notifier for callback.
- */
-
-int msm_lpm_register_notifier(int cpu, int level_iter,
- struct notifier_block *nb, bool is_latency_measure);
-
-/**
- * msm_lpm_unregister_notifier() - unregister from notifications
- * @cpu: cpu to debug
- * @nb: notifier block to callback on notifications
- *
- * This function sets the permitted level to a value one more than
- * available levels count which indicates that all levels are
- * permitted and it also unregisters notifier for callback.
- */
-
-int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb);
-
-#ifdef CONFIG_MSM_RPM_SMD
-
-/**
- * msm_lpm_level_beyond_limit() - Check if the resources in a low power level
- * is beyond the limits of the driver votes received for those resources.This
- * function is used by lpm_levels to eliminate any low power level that cannot
- * be entered.
- *
- * @limits: pointer to the resource limits of a low power level.
- *
- * returns true if the resource limits are beyond driver resource votes.
- * false otherwise.
- */
-bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits);
-
-/**
- * msm_lpmrs_enter_sleep() - Enter sleep flushes the sleep votes of low power
- * resources to the RPM driver, also configure the MPM if needed depending
- * on the low power mode being entered. L2 low power mode is also set in
- * this function.
-
- * @sclk_count: wakeup counter for RPM.
- * @limits: pointer to the resource limits of the low power mode being entered.
- * @from_idle: bool to determine if this call being made as a part of
- * idle power collapse.
- * @notify_rpm: bool that informs if this is an RPM notified power collapse.
- *
- * returns 0 on success.
- */
-int msm_lpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm);
-
-/**
- * msm_lpmrs_exit_sleep() - Exit sleep, reset the MPM and L2 mode.
- * @ limits: pointer to resource limits of the most recent low power mode.
- * @from_idle: bool to determine if this call being made as a part of
- * idle power collapse.
- * @notify_rpm: bool that informs if this is an RPM notified power collapse.
- * @collapsed: bool that informs if the Krait was power collapsed.
- */
-void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm, bool collapsed);
-/**
- * msm_lpmrs_module_init() - Init function that parses the device tree to
- * get the low power resource attributes and registers with RPM driver for
- * callback notification.
- *
- * returns 0 on success.
- */
-int __init msm_lpmrs_module_init(void);
-
-#else
-static inline bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits)
-{
- return true;
-}
-
-static inline int msm_lpmrs_enter_sleep(uint32_t sclk_count,
- struct msm_rpmrs_limits *limits, bool from_idle, bool notify_rpm)
-{
- return 0;
-}
-
-static inline void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm, bool collapsed)
-{
- return;
-}
-
-static inline int __init msm_lpmrs_module_init(void)
-{
- return 0;
-}
-#endif /* CONFIG_MSM_RPM_SMD */
-
-#endif
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 2ce4fa0..a974018 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -308,6 +308,8 @@
unsigned long memory_reserve_prop_length;
unsigned int memory_size;
unsigned int memory_start;
+ unsigned int num_holes = 0;
+ int i;
int ret;
memory_name_prop = of_get_flat_dt_prop(node,
@@ -358,21 +360,27 @@
mem_remove:
if (memory_remove_prop) {
- if (memory_remove_prop_length != (2*sizeof(unsigned int))) {
+ if (!memory_remove_prop_length || (memory_remove_prop_length %
+ (2 * sizeof(unsigned int)) != 0)) {
WARN(1, "Memory remove malformed\n");
goto mem_reserve;
}
- memory_start = be32_to_cpu(memory_remove_prop[0]);
- memory_size = be32_to_cpu(memory_remove_prop[1]);
+ num_holes = memory_remove_prop_length /
+ (2 * sizeof(unsigned int));
- ret = memblock_remove(memory_start, memory_size);
- if (ret)
- WARN(1, "Failed to remove memory %x-%x\n",
+ for (i = 0; i < (num_holes * 2); i += 2) {
+ memory_start = be32_to_cpu(memory_remove_prop[i]);
+ memory_size = be32_to_cpu(memory_remove_prop[i+1]);
+
+ ret = memblock_remove(memory_start, memory_size);
+ if (ret)
+ WARN(1, "Failed to remove memory %x-%x\n",
memory_start, memory_start+memory_size);
- else
- pr_info("Node %s removed memory %x-%x\n", uname,
+ else
+ pr_info("Node %s removed memory %x-%x\n", uname,
memory_start, memory_start+memory_size);
+ }
}
mem_reserve:
@@ -428,6 +436,8 @@
unsigned long memory_remove_prop_length;
unsigned long hole_start;
unsigned long hole_size;
+ unsigned int num_holes = 0;
+ int i = 0;
memory_remove_prop = of_get_flat_dt_prop(node,
"qcom,memblock-remove",
@@ -441,15 +451,21 @@
}
if (memory_remove_prop) {
- if (memory_remove_prop_length != (2*sizeof(unsigned int))) {
+ if (!memory_remove_prop_length || (memory_remove_prop_length %
+ (2 * sizeof(unsigned int)) != 0)) {
WARN(1, "Memory remove malformed\n");
goto out;
}
- hole_start = be32_to_cpu(memory_remove_prop[0]);
- hole_size = be32_to_cpu(memory_remove_prop[1]);
+ num_holes = memory_remove_prop_length /
+ (2 * sizeof(unsigned int));
- adjust_meminfo(hole_start, hole_size);
+ for (i = 0; i < (num_holes * 2); i += 2) {
+ hole_start = be32_to_cpu(memory_remove_prop[i]);
+ hole_size = be32_to_cpu(memory_remove_prop[i+1]);
+
+ adjust_meminfo(hole_start, hole_size);
+ }
}
out:
diff --git a/arch/arm/mach-msm/mpm-of.c b/arch/arm/mach-msm/mpm-of.c
index dbd5d67..a0746f9 100644
--- a/arch/arm/mach-msm/mpm-of.c
+++ b/arch/arm/mach-msm/mpm-of.c
@@ -27,10 +27,17 @@
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
#include <asm/hardware/gic.h>
#include <asm/arch_timer.h>
#include <mach/gpio.h>
#include <mach/mpm.h>
+#include <mach/clk.h>
+#include <mach/rpm-regulator-smd.h>
enum {
MSM_MPM_GIC_IRQ_DOMAIN,
@@ -75,6 +82,12 @@
#define ARCH_TIMER_HZ (19200000)
static struct msm_mpm_device_data msm_mpm_dev_data;
+static struct clk *xo_clk;
+static bool xo_enabled;
+static struct workqueue_struct *msm_mpm_wq;
+static struct work_struct msm_mpm_work;
+static struct completion wake_wq;
+
enum mpm_reg_offsets {
MSM_MPM_REG_WAKEUP,
MSM_MPM_REG_ENABLE,
@@ -257,6 +270,8 @@
else
__clear_bit(d->hwirq, irq_apps);
+ if (!wakeset && (msm_mpm_initialized & MSM_MPM_DEVICE_PROBED))
+ complete(&wake_wq);
}
return 0;
@@ -543,6 +558,54 @@
}
}
}
+static void msm_mpm_sys_low_power_modes(bool allow)
+{
+ if (allow) {
+ if (xo_enabled) {
+ clk_disable_unprepare(xo_clk);
+ xo_enabled = false;
+ }
+ } else {
+ if (!xo_enabled) {
+ /* If we cannot enable XO clock then we want to flag it,
+ * than having to deal with not being able to wakeup
+ * from a non-monitorable interrupt
+ */
+ BUG_ON(clk_prepare_enable(xo_clk));
+ xo_enabled = true;
+ }
+ }
+}
+
+void msm_mpm_suspend_prepare(void)
+{
+ bool allow = msm_mpm_irqs_detectable(false) &&
+ msm_mpm_gpio_irqs_detectable(false);
+ msm_mpm_sys_low_power_modes(allow);
+}
+EXPORT_SYMBOL(msm_mpm_suspend_prepare);
+
+void msm_mpm_suspend_wake(void)
+{
+ bool allow = msm_mpm_irqs_detectable(true) &&
+ msm_mpm_gpio_irqs_detectable(true);
+ msm_mpm_sys_low_power_modes(allow);
+}
+EXPORT_SYMBOL(msm_mpm_suspend_wake);
+
+static void msm_mpm_work_fn(struct work_struct *work)
+{
+ unsigned long flags;
+ while (1) {
+ bool allow;
+ wait_for_completion(&wake_wq);
+ spin_lock_irqsave(&msm_mpm_lock, flags);
+ allow = msm_mpm_irqs_detectable(true) &&
+ msm_mpm_gpio_irqs_detectable(true);
+ spin_unlock_irqrestore(&msm_mpm_lock, flags);
+ msm_mpm_sys_low_power_modes(allow);
+ }
+}
static int __devinit msm_mpm_dev_probe(struct platform_device *pdev)
{
@@ -555,6 +618,13 @@
return 0;
}
+ xo_clk = devm_clk_get(&pdev->dev, "xo");
+
+ if (IS_ERR(xo_clk)) {
+ pr_err("%s(): Cannot get clk resource for XO\n", __func__);
+ return PTR_ERR(xo_clk);
+ }
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vmpm");
if (!res) {
pr_err("%s(): Missing RPM memory resource\n", __func__);
@@ -610,10 +680,27 @@
return ret;
}
+
+ init_completion(&wake_wq);
+
+ INIT_WORK(&msm_mpm_work, msm_mpm_work_fn);
+ msm_mpm_wq = create_singlethread_workqueue("mpm");
+
+ if (msm_mpm_wq)
+ queue_work(msm_mpm_wq, &msm_mpm_work);
+ else {
+ pr_warn("%s(): Failed to create wq. So voting against XO off",
+ __func__);
+ /* Throw a BUG. Otherwise, its possible that system allows
+ * XO shutdown when there are non-monitored interrupts are
+ * pending and cause errors at a later point in time.
+ */
+ BUG_ON(clk_prepare_enable(xo_clk));
+ xo_enabled = true;
+ }
+
msm_mpm_initialized |= MSM_MPM_DEVICE_PROBED;
-
return 0;
-
}
static inline int __init mpm_irq_domain_linear_size(struct irq_domain *d)
diff --git a/arch/arm/mach-msm/pcie.c b/arch/arm/mach-msm/pcie.c
index c09b759..7695b2d 100644
--- a/arch/arm/mach-msm/pcie.c
+++ b/arch/arm/mach-msm/pcie.c
@@ -484,22 +484,19 @@
static void msm_pcie_adjust_tlp_size(struct msm_pcie_dev_t *dev)
{
/*
- * Apply this fix only for device such as APQ8064 version 1.
* Set the Max TLP size to 2K, instead of using default of 4K
* to avoid a RAM problem in PCIE20 core of that version.
*/
- if (readl_relaxed(dev->elbi + PCIE20_ELBI_VERSION) == 0x01002107) {
- /*
- * CFG_REMOTE_RD_REQ_BRIDGE_SIZE:
- * 5=4KB/4=2KB/3=1KB/2=512B/1=256B/0=128B
- */
- writel_relaxed(4, dev->pcie20 +
- PCIE20_PLR_AXI_MSTR_RESP_COMP_CTRL0);
+ /*
+ * CFG_REMOTE_RD_REQ_BRIDGE_SIZE:
+ * 5=4KB/4=2KB/3=1KB/2=512B/1=256B/0=128B
+ */
+ writel_relaxed(4, dev->pcie20 +
+ PCIE20_PLR_AXI_MSTR_RESP_COMP_CTRL0);
- writel_relaxed(1, dev->pcie20 +
- PCIE20_PLR_AXI_MSTR_RESP_COMP_CTRL1);
- }
+ writel_relaxed(1, dev->pcie20 +
+ PCIE20_PLR_AXI_MSTR_RESP_COMP_CTRL1);
};
static int __init msm_pcie_setup(int nr, struct pci_sys_data *sys)
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 0a799aa..28d8e42 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -34,6 +34,7 @@
"9 ARM: dts: msm: add perf-events support for msm8226\n"
"10 Perf: Fix counts across power collapse\n"
"11 ARM: dts: msm: add perf-events support for msm8x10, msm8x12\n"
+ "12 Perf: Make per-process counters configurable\n"
;
static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_trace_counters.c b/arch/arm/mach-msm/perf_trace_counters.c
index d961994..65b0d28 100644
--- a/arch/arm/mach-msm/perf_trace_counters.c
+++ b/arch/arm/mach-msm/perf_trace_counters.c
@@ -10,9 +10,13 @@
* GNU General Public License for more details.
*/
#include <asm/thread_notify.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
#define CREATE_TRACE_POINTS
#include "perf_trace_counters.h"
+static unsigned int tp_pid_state;
+
static int tracectr_notifier(struct notifier_block *self, unsigned long cmd,
void *v)
{
@@ -34,9 +38,80 @@
.notifier_call = tracectr_notifier,
};
+static void enable_tp_pid(void)
+{
+ if (tp_pid_state == 0) {
+ tp_pid_state = 1;
+ thread_register_notifier(&tracectr_notifier_block);
+ }
+}
+
+static void disable_tp_pid(void)
+{
+ if (tp_pid_state == 1) {
+ tp_pid_state = 0;
+ thread_unregister_notifier(&tracectr_notifier_block);
+ }
+}
+
+static ssize_t read_enabled_perftp_file_bool(struct file *file,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buf[2];
+ buf[1] = '\n';
+ if (tp_pid_state == 0)
+ buf[0] = '0';
+ else
+ buf[0] = '1';
+ return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t write_enabled_perftp_file_bool(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buf[32];
+ size_t buf_size;
+
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ switch (buf[0]) {
+ case 'y':
+ case 'Y':
+ case '1':
+ enable_tp_pid();
+ break;
+ case 'n':
+ case 'N':
+ case '0':
+ disable_tp_pid();
+ break;
+ }
+
+ return count;
+}
+
+static const struct file_operations fops_perftp = {
+ .read = read_enabled_perftp_file_bool,
+ .write = write_enabled_perftp_file_bool,
+ .llseek = default_llseek,
+};
+
int __init init_tracecounters(void)
{
- thread_register_notifier(&tracectr_notifier_block);
+ struct dentry *dir;
+ struct dentry *file;
+ unsigned int value = 1;
+
+ dir = debugfs_create_dir("perf_debug_tp", NULL);
+ if (!dir)
+ return -ENOMEM;
+ file = debugfs_create_file("enabled", 0777, dir,
+ &value, &fops_perftp);
+ if (!file) {
+ debugfs_remove(dir);
+ return -ENOMEM;
+ }
return 0;
}
late_initcall(init_tracecounters);
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index ff1fd4f..4adbdc0 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -30,6 +30,7 @@
#include <linux/list_sort.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
+#include <linux/of_gpio.h>
#include <asm/uaccess.h>
#include <asm/setup.h>
@@ -251,6 +252,7 @@
struct pil_desc *desc = dev_id;
struct pil_priv *priv = desc->priv;
+ pil_info(desc, "Power/Clock ready interrupt received\n");
if (!desc->priv->unvoted_flag) {
desc->priv->unvoted_flag = 1;
__pil_proxy_unvote(priv);
@@ -586,6 +588,34 @@
return ret;
}
+static void pil_parse_devicetree(struct pil_desc *desc)
+{
+ int clk_ready = 0;
+
+ if (of_find_property(desc->dev->of_node,
+ "qcom,gpio-proxy-unvote",
+ NULL)) {
+ clk_ready = of_get_named_gpio(desc->dev->of_node,
+ "qcom,gpio-proxy-unvote", 0);
+
+ if (clk_ready < 0) {
+ dev_err(desc->dev,
+ "[%s]: Error getting proxy unvoting gpio\n",
+ desc->name);
+ return;
+ }
+
+ clk_ready = gpio_to_irq(clk_ready);
+ if (clk_ready < 0) {
+ dev_err(desc->dev,
+ "[%s]: Error getting proxy unvote IRQ\n",
+ desc->name);
+ return;
+ }
+ }
+ desc->proxy_unvote_irq = clk_ready;
+}
+
/* Synchronize request_firmware() with suspend */
static DECLARE_RWSEM(pil_pm_rwsem);
@@ -741,12 +771,6 @@
void __iomem *addr;
char buf[sizeof(priv->info->name)];
- /* Ignore users who don't make any sense */
- WARN(desc->ops->proxy_unvote && desc->proxy_unvote_irq == 0
- && !desc->proxy_timeout,
- "Invalid proxy unvote callback or a proxy timeout of 0"
- " was specified or no proxy unvote IRQ was specified.\n");
-
if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote,
"Invalid proxy voting. Ignoring\n"))
((struct pil_reset_ops *)desc->ops)->proxy_unvote = NULL;
@@ -767,7 +791,15 @@
strncpy(buf, desc->name, sizeof(buf));
__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
- if (desc->proxy_unvote_irq > 0) {
+ pil_parse_devicetree(desc);
+
+ /* Ignore users who don't make any sense */
+ WARN(desc->ops->proxy_unvote && desc->proxy_unvote_irq == 0
+ && !desc->proxy_timeout,
+ "Invalid proxy unvote callback or a proxy timeout of 0"
+ " was specified or no proxy unvote IRQ was specified.\n");
+
+ if (desc->proxy_unvote_irq > 0 && desc->ops->proxy_unvote) {
ret = request_threaded_irq(desc->proxy_unvote_irq,
NULL,
proxy_unvote_intr_handler,
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 4b14efb..620ab5c 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -411,15 +411,6 @@
int ret;
uint32_t regval;
- int clk_ready = of_get_named_gpio(pdev->dev.of_node,
- "qcom,gpio-proxy-unvote", 0);
- if (clk_ready < 0)
- return clk_ready;
-
- clk_ready = gpio_to_irq(clk_ready);
- if (clk_ready < 0)
- return clk_ready;
-
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
@@ -449,7 +440,6 @@
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
desc->proxy_timeout = 10000;
- desc->proxy_unvote_irq = clk_ready;
if (pas_supported(PAS_WCNSS) > 0) {
desc->ops = &pil_pronto_ops_trusted;
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index f8e1759..a9a6942 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -403,18 +403,13 @@
struct q6v5_data *q6;
struct pil_desc *desc;
struct resource *res;
- int ret, gpio_clk_ready;
+ int ret;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
platform_set_drvdata(pdev, drv);
- ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
- "qcom,gpio-proxy-unvote", 0));
- if (ret < 0)
- return ret;
- gpio_clk_ready = ret;
q6 = pil_q6v5_init(pdev);
if (IS_ERR(q6))
return PTR_ERR(q6);
@@ -423,7 +418,6 @@
desc = &q6->desc;
desc->owner = THIS_MODULE;
desc->proxy_timeout = PROXY_TIMEOUT_MS;
- desc->proxy_unvote_irq = gpio_clk_ready;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
q6->restart_reg = devm_request_and_ioremap(&pdev->dev, res);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 5833db9..c267541 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -298,18 +298,9 @@
struct property *prop;
int ret;
- int clk_ready = of_get_named_gpio(pdev->dev.of_node,
- "qcom,gpio-proxy-unvote", 0);
- if (clk_ready < 0)
- return clk_ready;
-
- clk_ready = gpio_to_irq(clk_ready);
- if (clk_ready < 0)
- return clk_ready;
-
mba = devm_kzalloc(&pdev->dev, sizeof(*mba), GFP_KERNEL);
- if (IS_ERR(mba))
- return PTR_ERR(mba);
+ if (!mba)
+ return -ENOMEM;
drv->mba = mba;
q6 = pil_q6v5_init(pdev);
@@ -322,7 +313,6 @@
q6_desc->ops = &pil_msa_pbl_ops;
q6_desc->owner = THIS_MODULE;
q6_desc->proxy_timeout = PROXY_TIMEOUT_MS;
- q6_desc->proxy_unvote_irq = clk_ready;
q6->self_auth = of_property_read_bool(pdev->dev.of_node,
"qcom,pil-self-auth");
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index dd0599b..da5e67a 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -40,6 +40,7 @@
#include <mach/trace_msm_low_power.h>
#include <mach/msm-krait-l2-accessors.h>
#include <mach/msm_bus.h>
+#include <mach/mpm.h>
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
#include <asm/pgtable.h>
@@ -1132,9 +1133,22 @@
pm_sleep_ops = *ops;
}
+static int msm_suspend_prepare(void)
+{
+ msm_mpm_suspend_prepare();
+ return 0;
+}
+
+static void msm_suspend_wake(void)
+{
+ msm_mpm_suspend_wake();
+}
+
static const struct platform_suspend_ops msm_pm_ops = {
.enter = msm_pm_enter,
.valid = suspend_valid_only_mem,
+ .prepare_late = msm_suspend_prepare,
+ .wake = msm_suspend_wake,
};
static int __devinit msm_pm_snoc_client_probe(struct platform_device *pdev)
@@ -1367,7 +1381,7 @@
end = exit_phys + SECTION_SIZE;
ret = msm_pm_add_idmap(pc_pgd, exit_phys, end,
- PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
+ PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF);
if (ret)
return ret;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 64ee880..8baac01 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -250,7 +250,11 @@
return;
spin_lock_irqsave(&audio->dsp_lock, flags);
- BUG_ON(list_empty(&audio->out_queue));
+ if (list_empty(&audio->out_queue)) {
+ pr_warning("%s: ingore unexpected event from dsp\n", __func__);
+ spin_unlock_irqrestore(&audio->dsp_lock, flags);
+ return;
+ }
used_buf = list_first_entry(&audio->out_queue,
struct audio_aio_buffer_node, list);
if (token == used_buf->token) {
diff --git a/arch/arm/mach-msm/smcmod.c b/arch/arm/mach-msm/smcmod.c
index 221a522..683fb32 100644
--- a/arch/arm/mach-msm/smcmod.c
+++ b/arch/arm/mach-msm/smcmod.c
@@ -29,6 +29,7 @@
#include <linux/msm_ion.h>
#include <asm/smcmod.h>
#include <mach/scm.h>
+#include <mach/socinfo.h>
static DEFINE_MUTEX(ioctl_lock);
@@ -513,6 +514,110 @@
return ret;
}
+static int smcmod_send_dec_cmd(struct smcmod_decrypt_req *reqp)
+{
+ struct ion_client *ion_clientp;
+ struct ion_handle *ion_handlep = NULL;
+ int ion_fd;
+ int ret;
+ u32 pa;
+ size_t size;
+ struct {
+ u32 args[4];
+ } req;
+ struct {
+ u32 args[3];
+ } rsp;
+
+ ion_clientp = msm_ion_client_create(UINT_MAX, "smcmod");
+ if (IS_ERR_OR_NULL(ion_clientp))
+ return PTR_ERR(ion_clientp);
+
+ switch (reqp->operation) {
+ case SMCMOD_DECRYPT_REQ_OP_METADATA: {
+ ion_fd = reqp->request.metadata.ion_fd;
+ ret = smcmod_ion_fd_to_phys(ion_fd, ion_clientp,
+ &ion_handlep, &pa, &size);
+ if (ret)
+ goto error;
+
+ req.args[0] = reqp->request.metadata.len;
+ req.args[1] = pa;
+ break;
+ }
+ case SMCMOD_DECRYPT_REQ_OP_IMG_FRAG: {
+ ion_fd = reqp->request.img_frag.ion_fd;
+ ret = smcmod_ion_fd_to_phys(ion_fd, ion_clientp,
+ &ion_handlep, &pa, &size);
+ if (ret)
+ goto error;
+
+ req.args[0] = reqp->request.img_frag.ctx_id;
+ req.args[1] = reqp->request.img_frag.last_frag;
+ req.args[2] = reqp->request.img_frag.frag_len;
+ req.args[3] = pa + reqp->request.img_frag.offset;
+ break;
+ }
+ default:
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /*
+ * scm_call does cache maintenance over request and response buffers.
+ * The userspace must flush/invalidate ion input/output buffers itself.
+ */
+
+ ret = scm_call(reqp->service_id, reqp->command_id,
+ &req, sizeof(req), &rsp, sizeof(rsp));
+ if (ret)
+ goto error;
+
+ switch (reqp->operation) {
+ case SMCMOD_DECRYPT_REQ_OP_METADATA:
+ reqp->response.metadata.status = rsp.args[0];
+ reqp->response.metadata.ctx_id = rsp.args[1];
+ reqp->response.metadata.end_offset = rsp.args[2] - pa;
+ break;
+ case SMCMOD_DECRYPT_REQ_OP_IMG_FRAG: {
+ reqp->response.img_frag.status = rsp.args[0];
+ break;
+ }
+ default:
+ break;
+ }
+
+error:
+ if (!IS_ERR_OR_NULL(ion_clientp)) {
+ if (!IS_ERR_OR_NULL(ion_handlep))
+ ion_free(ion_clientp, ion_handlep);
+ ion_client_destroy(ion_clientp);
+ }
+ return ret;
+}
+
+static int smcmod_ioctl_check(unsigned cmd)
+{
+ switch (cmd) {
+ case SMCMOD_IOCTL_SEND_REG_CMD:
+ case SMCMOD_IOCTL_SEND_BUF_CMD:
+ case SMCMOD_IOCTL_SEND_CIPHER_CMD:
+ case SMCMOD_IOCTL_SEND_MSG_DIGEST_CMD:
+ case SMCMOD_IOCTL_GET_VERSION:
+ if (!cpu_is_fsm9xxx())
+ return -EINVAL;
+ break;
+ case SMCMOD_IOCTL_SEND_DECRYPT_CMD:
+ if (!cpu_is_msm8226())
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static long smcmod_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
@@ -531,6 +636,10 @@
*/
mutex_lock(&ioctl_lock);
+ ret = smcmod_ioctl_check(cmd);
+ if (ret)
+ goto cleanup;
+
switch (cmd) {
case SMCMOD_IOCTL_SEND_REG_CMD:
{
@@ -652,6 +761,26 @@
}
break;
+ case SMCMOD_IOCTL_SEND_DECRYPT_CMD:
+ {
+ struct smcmod_decrypt_req req;
+
+ if (copy_from_user((void *)&req, argp, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ ret = smcmod_send_dec_cmd(&req);
+ if (ret < 0)
+ goto cleanup;
+
+ if (copy_to_user(argp, (void *)&req, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ }
+ break;
+
default:
ret = -EINVAL;
}
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index ffa00c9..01e0985 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -503,8 +503,10 @@
if (ret)
return ret;
- if (subsys->desc->is_not_loadable)
+ if (subsys->desc->is_not_loadable) {
+ subsys_set_state(subsys, SUBSYS_ONLINE);
return 0;
+ }
ret = wait_for_err_ready(subsys);
if (ret)
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index e62af21..1d12b07 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -21,6 +21,7 @@
#include <linux/uaccess.h>
#include <linux/user.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/cp15.h>
#include <asm/cputype.h>
@@ -656,23 +657,23 @@
}
#ifdef CONFIG_PROC_FS
-static int proc_read_status(char *page, char **start, off_t off, int count,
- int *eof, void *data)
+static int vfp_bounce_show(struct seq_file *m, void *v)
{
- char *p = page;
- int len;
-
- p += snprintf(p, PAGE_SIZE, "%llu\n", atomic64_read(&vfp_bounce_count));
-
- len = (p - page) - off;
- if (len < 0)
- len = 0;
-
- *eof = (len <= count) ? 1 : 0;
- *start = page + off;
-
- return len;
+ seq_printf(m, "%llu\n", atomic64_read(&vfp_bounce_count));
+ return 0;
}
+
+static int vfp_bounce_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, vfp_bounce_show, NULL);
+}
+
+static const struct file_operations vfp_bounce_fops = {
+ .open = vfp_bounce_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif
/*
@@ -755,11 +756,9 @@
}
#ifdef CONFIG_PROC_FS
- procfs_entry = create_proc_entry("cpu/vfp_bounce", S_IRUGO, NULL);
-
- if (procfs_entry)
- procfs_entry->read_proc = proc_read_status;
- else
+ procfs_entry = proc_create("cpu/vfp_bounce", S_IRUGO, NULL,
+ &vfp_bounce_fops);
+ if (!procfs_entry)
pr_err("Failed to create procfs node for VFP bounce reporting\n");
#endif
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 7f7b4d7..a740be6 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -401,7 +401,7 @@
struct smq_invoke_buf *list;
struct fastrpc_buf *pbuf = ibuf, *obufs = 0;
struct smq_phy_page *pages;
- struct ion_handle **handles;
+ struct ion_handle **handles = NULL;
void *args;
int i, rlen, size, used, inh, bufs = 0, err = 0;
int inbufs = REMOTE_SCALARS_INBUFS(sc);
@@ -798,7 +798,7 @@
struct fastrpc_device *dev = 0;
struct smq_invoke_ctx *ctx = 0;
struct fastrpc_buf obuf, *abufs = 0, *b;
- struct ion_handle **handles;
+ struct ion_handle **handles = NULL;
int interrupted = 0;
uint32_t sc;
int i, bufs, nbufs = 0, err = 0;
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 3ae56c5..7154942 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -27,7 +27,7 @@
/* Size of the USB buffers used for read and write*/
#define USB_MAX_OUT_BUF 4096
-#define APPS_BUF_SIZE 2000
+#define APPS_BUF_SIZE 4096
#define IN_BUF_SIZE 16384
#define MAX_IN_BUF_SIZE 32768
#define MAX_SYNC_OBJ_NAME_SIZE 32
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index de4433b..379dc4d 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -69,6 +69,13 @@
void encode_rsp_and_send(int buf_length)
{
struct diag_smd_info *data = &(driver->smd_data[MODEM_DATA]);
+
+ if (buf_length > APPS_BUF_SIZE) {
+ pr_err("diag: In %s, invalid len %d, permissible len %d\n",
+ __func__, buf_length, APPS_BUF_SIZE);
+ return;
+ }
+
send.state = DIAG_STATE_START;
send.pkt = driver->apps_rsp_buf;
send.last = (void *)(driver->apps_rsp_buf + buf_length);
@@ -1315,10 +1322,12 @@
{
int i;
- if (index > 490) {
- pr_err("diag: error response too huge, aborting\n");
+ /* -1 to accomodate the first byte 0x13 */
+ if (index > APPS_BUF_SIZE-1) {
+ pr_err("diag: cannot send err rsp, huge length: %d\n", index);
return;
}
+
driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
for (i = 0; i < index; i++)
driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 132df90..6efab5b 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -65,6 +65,7 @@
#define CSR_QDSSPWRREQIGNORE (0x060)
#define CSR_QDSSSPARE (0x064)
#define CSR_IPCAT (0x068)
+#define CSR_BYTECNTVAL (0x06C)
#define BLKSIZE_256 0
#define BLKSIZE_512 1
@@ -159,6 +160,19 @@
}
EXPORT_SYMBOL(coresight_csr_hwctrl_set);
+void coresight_csr_set_byte_cntr(uint32_t count)
+{
+ struct csr_drvdata *drvdata = csrdrvdata;
+
+ CSR_UNLOCK(drvdata);
+
+ csr_writel(drvdata, count, CSR_BYTECNTVAL);
+ mb();
+
+ CSR_LOCK(drvdata);
+}
+EXPORT_SYMBOL(coresight_csr_set_byte_cntr);
+
static int __devinit csr_probe(struct platform_device *pdev)
{
int ret;
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index b570252..3ad1f34 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -48,12 +48,14 @@
extern void msm_qdss_csr_disable_bam_to_usb(void);
extern void msm_qdss_csr_disable_flush(void);
extern int coresight_csr_hwctrl_set(phys_addr_t addr, uint32_t val);
+extern void coresight_csr_set_byte_cntr(uint32_t);
#else
static inline void msm_qdss_csr_enable_bam_to_usb(void) {}
static inline void msm_qdss_csr_disable_bam_to_usb(void) {}
static inline void msm_qdss_csr_disable_flush(void) {}
static inline int coresight_csr_hwctrl_set(phys_addr_t addr,
uint32_t val) { return -ENOSYS; }
+static inline void coresight_csr_set_byte_cntr(uint32_t val) {}
#endif
#ifdef CONFIG_CORESIGHT_ETM
extern unsigned int etm_readl_cp14(uint32_t off);
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 4186abe..c501700 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -30,6 +30,10 @@
#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include <linux/coresight-cti.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
#include <linux/usb/usb_qdss.h>
#include <mach/memory.h>
#include <mach/sps.h>
@@ -135,6 +139,8 @@
struct device *dev;
struct coresight_device *csdev;
struct miscdevice miscdev;
+ struct cdev byte_cntr_dev;
+ struct class *byte_cntr_class;
struct clk *clk;
spinlock_t spinlock;
bool reset_flush_race;
@@ -157,6 +163,19 @@
bool enable;
enum tmc_config_type config_type;
uint32_t trigger_cntr;
+ int byte_cntr_irq;
+ atomic_t byte_cntr_irq_cnt;
+ uint32_t byte_cntr_value;
+ struct mutex byte_cntr_read_lock;
+ struct mutex byte_cntr_lock;
+ uint32_t byte_cntr_block_size;
+ bool byte_cntr_overflow;
+ bool byte_cntr_present;
+ bool byte_cntr_enable;
+ uint32_t byte_cntr_overflow_cnt;
+ bool byte_cntr_read_active;
+ wait_queue_head_t wq;
+ char *byte_cntr_node;
};
static void tmc_wait_for_flush(struct tmc_drvdata *drvdata)
@@ -368,6 +387,52 @@
mutex_unlock(&drvdata->usb_lock);
}
+static uint32_t tmc_etr_get_write_ptr(struct tmc_drvdata *drvdata)
+{
+ uint32_t rwp = 0;
+
+ TMC_UNLOCK(drvdata);
+
+ rwp = tmc_readl(drvdata, TMC_RWP);
+
+ TMC_LOCK(drvdata);
+
+ return rwp;
+}
+
+static void tmc_etr_byte_cntr_start(struct tmc_drvdata *drvdata)
+{
+ if (!drvdata->byte_cntr_present)
+ return;
+
+ mutex_lock(&drvdata->byte_cntr_lock);
+ atomic_set(&drvdata->byte_cntr_irq_cnt, 0);
+ drvdata->byte_cntr_overflow = false;
+ drvdata->byte_cntr_read_active = false;
+ drvdata->byte_cntr_enable = true;
+ if (drvdata->byte_cntr_value != 0)
+ drvdata->byte_cntr_overflow_cnt = drvdata->size /
+ (drvdata->byte_cntr_value * 8);
+ else
+ drvdata->byte_cntr_overflow_cnt = 0;
+ coresight_csr_set_byte_cntr(drvdata->byte_cntr_value);
+ mutex_unlock(&drvdata->byte_cntr_lock);
+}
+
+static void tmc_etr_byte_cntr_stop(struct tmc_drvdata *drvdata)
+{
+ if (!drvdata->byte_cntr_present)
+ return;
+
+ mutex_lock(&drvdata->byte_cntr_lock);
+ coresight_csr_set_byte_cntr(0);
+ drvdata->byte_cntr_value = 0;
+ drvdata->byte_cntr_enable = false;
+ mutex_unlock(&drvdata->byte_cntr_lock);
+
+ wake_up(&drvdata->wq);
+}
+
static void __tmc_etb_enable(struct tmc_drvdata *drvdata)
{
/* Zero out the memory to help with debug */
@@ -438,10 +503,14 @@
coresight_cti_map_trigout(drvdata->cti_flush, 1, 0);
coresight_cti_map_trigin(drvdata->cti_reset, 0, 0);
} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM &&
- !drvdata->reset_flush_race) {
- coresight_cti_map_trigout(drvdata->cti_flush, 3, 0);
- coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
+ if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
+ tmc_etr_byte_cntr_start(drvdata);
+ if (!drvdata->reset_flush_race) {
+ coresight_cti_map_trigout(drvdata->cti_flush,
+ 3, 0);
+ coresight_cti_map_trigin(drvdata->cti_reset,
+ 2, 0);
+ }
} else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
drvdata->usbch = usb_qdss_open("qdss", drvdata,
usb_notifier);
@@ -674,10 +743,14 @@
coresight_cti_unmap_trigin(drvdata->cti_reset, 0, 0);
coresight_cti_unmap_trigout(drvdata->cti_flush, 1, 0);
} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM &&
- !drvdata->reset_flush_race) {
- coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0);
- coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0);
+ if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
+ tmc_etr_byte_cntr_stop(drvdata);
+ if (!drvdata->reset_flush_race) {
+ coresight_cti_unmap_trigin(drvdata->cti_reset,
+ 2, 0);
+ coresight_cti_unmap_trigout(drvdata->cti_flush,
+ 3, 0);
+ }
} else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
tmc_etr_bam_disable(drvdata);
usb_qdss_close(drvdata->usbch);
@@ -929,6 +1002,161 @@
.llseek = no_llseek,
};
+static int tmc_etr_byte_cntr_open(struct inode *inode, struct file *file)
+{
+ struct tmc_drvdata *drvdata = container_of(inode->i_cdev,
+ struct tmc_drvdata,
+ byte_cntr_dev);
+
+ if (drvdata->out_mode != TMC_ETR_OUT_MODE_MEM ||
+ !drvdata->byte_cntr_enable)
+ return -EPERM;
+
+ if (!mutex_trylock(&drvdata->byte_cntr_read_lock))
+ return -EPERM;
+
+ file->private_data = drvdata;
+ nonseekable_open(inode, file);
+ drvdata->byte_cntr_block_size = drvdata->byte_cntr_value * 8;
+ drvdata->byte_cntr_read_active = true;
+ dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
+ return 0;
+}
+
+static void tmc_etr_read_bytes(struct tmc_drvdata *drvdata, loff_t *ppos,
+ size_t bytes, size_t *len)
+{
+ if (*len >= bytes) {
+ atomic_dec(&drvdata->byte_cntr_irq_cnt);
+ *len = bytes;
+ } else {
+ if (((uint32_t)*ppos % bytes) + *len > bytes)
+ *len = bytes - ((uint32_t)*ppos % bytes);
+ if ((*len + (uint32_t)*ppos) % bytes == 0)
+ atomic_dec(&drvdata->byte_cntr_irq_cnt);
+ }
+}
+
+static size_t tmc_etr_flush_bytes(struct tmc_drvdata *drvdata, loff_t *ppos,
+ size_t bytes)
+{
+ uint32_t rwp = 0;
+ size_t len = bytes;
+
+ rwp = tmc_etr_get_write_ptr(drvdata);
+ if (rwp >= (drvdata->paddr + *ppos)) {
+ if (len > (rwp - drvdata->paddr - *ppos))
+ len = rwp - drvdata->paddr - *ppos;
+ }
+ return len;
+}
+
+static ssize_t tmc_etr_byte_cntr_read(struct file *file, char __user *data,
+ size_t len, loff_t *ppos)
+{
+ struct tmc_drvdata *drvdata = file->private_data;
+ char *bufp = drvdata->vaddr + *ppos;
+ size_t bytes = drvdata->byte_cntr_block_size;
+ int ret = 0;
+
+ if (!data)
+ return -EINVAL;
+ if (drvdata->byte_cntr_overflow)
+ return -EIO;
+
+ mutex_lock(&drvdata->byte_cntr_lock);
+ /* In case the byte counter is enabled and disabled multiple times
+ * prevent unexpected data from being given to the user
+ */
+ if (!drvdata->byte_cntr_read_active)
+ goto read_err0;
+
+ if (!drvdata->byte_cntr_enable) {
+ if (!atomic_read(&drvdata->byte_cntr_irq_cnt)) {
+ /* Read the last 'block' of data which might be needed
+ * to be read partially. If already read, return 0
+ */
+ len = tmc_etr_flush_bytes(drvdata, ppos, bytes);
+ if (!len)
+ goto read_err0;
+ } else {
+ /* Keep reading until you reach the last block of data
+ */
+ tmc_etr_read_bytes(drvdata, ppos, bytes, &len);
+ }
+ } else {
+ if (!atomic_read(&drvdata->byte_cntr_irq_cnt)) {
+ mutex_unlock(&drvdata->byte_cntr_lock);
+ if (wait_event_interruptible(drvdata->wq,
+ (atomic_read(&drvdata->byte_cntr_irq_cnt) > 0) ||
+ !drvdata->byte_cntr_enable)) {
+ ret = -ERESTARTSYS;
+ goto read_err1;
+ }
+ mutex_lock(&drvdata->byte_cntr_lock);
+ if (!drvdata->byte_cntr_read_active) {
+ ret = 0;
+ goto read_err0;
+ }
+ }
+ if (drvdata->byte_cntr_overflow) {
+ ret = -EIO;
+ goto read_err0;
+ }
+ if (!drvdata->byte_cntr_enable &&
+ !atomic_read(&drvdata->byte_cntr_irq_cnt)) {
+ len = tmc_etr_flush_bytes(drvdata, ppos, bytes);
+ if (!len) {
+ ret = 0;
+ goto read_err0;
+ }
+ } else {
+ tmc_etr_read_bytes(drvdata, ppos, bytes, &len);
+ }
+ }
+ if (copy_to_user(data, bufp, len)) {
+ mutex_unlock(&drvdata->byte_cntr_lock);
+ dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+ ret = -EFAULT;
+ goto read_err1;
+ }
+ mutex_unlock(&drvdata->byte_cntr_lock);
+
+ if (*ppos + len >= drvdata->size)
+ *ppos = 0;
+ else
+ *ppos += len;
+
+ dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
+ __func__, len, (int) (drvdata->size - *ppos));
+ return len;
+
+read_err0:
+ mutex_unlock(&drvdata->byte_cntr_lock);
+read_err1:
+ return ret;
+}
+
+static int tmc_etr_byte_cntr_release(struct inode *inode, struct file *file)
+{
+ struct tmc_drvdata *drvdata = file->private_data;
+
+ mutex_lock(&drvdata->byte_cntr_lock);
+ drvdata->byte_cntr_read_active = false;
+ mutex_unlock(&drvdata->byte_cntr_lock);
+ mutex_unlock(&drvdata->byte_cntr_read_lock);
+ dev_dbg(drvdata->dev, "%s: released\n", __func__);
+ return 0;
+}
+
+static const struct file_operations byte_cntr_fops = {
+ .owner = THIS_MODULE,
+ .open = tmc_etr_byte_cntr_open,
+ .read = tmc_etr_byte_cntr_read,
+ .release = tmc_etr_byte_cntr_release,
+ .llseek = no_llseek,
+};
+
static ssize_t tmc_show_trigger_cntr(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1044,6 +1272,41 @@
static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tmc_etr_show_out_mode,
tmc_etr_store_out_mode);
+static ssize_t tmc_etr_show_byte_cntr_value(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val = drvdata->byte_cntr_value;
+
+ if (!drvdata->byte_cntr_present)
+ return -EPERM;
+
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t tmc_etr_store_byte_cntr_value(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+
+ if (!drvdata->byte_cntr_present || drvdata->byte_cntr_enable)
+ return -EPERM;
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+ if ((drvdata->size / 8) < val)
+ return -EINVAL;
+ if (drvdata->size % (val * 8) != 0)
+ return -EINVAL;
+
+ drvdata->byte_cntr_value = val;
+ return size;
+}
+static DEVICE_ATTR(byte_cntr_value, S_IRUGO | S_IWUSR,
+ tmc_etr_show_byte_cntr_value, tmc_etr_store_byte_cntr_value);
+
static struct attribute *tmc_attrs[] = {
&dev_attr_trigger_cntr.attr,
NULL,
@@ -1055,6 +1318,7 @@
static struct attribute *tmc_etr_attrs[] = {
&dev_attr_out_mode.attr,
+ &dev_attr_byte_cntr_value.attr,
NULL,
};
@@ -1118,6 +1382,113 @@
sps_deregister_bam_device(bamdata->handle);
}
+static irqreturn_t tmc_etr_byte_cntr_irq(int irq, void *data)
+{
+ struct tmc_drvdata *drvdata = data;
+
+ atomic_inc(&drvdata->byte_cntr_irq_cnt);
+ if (atomic_read(&drvdata->byte_cntr_irq_cnt) >
+ drvdata->byte_cntr_overflow_cnt) {
+ dev_err(drvdata->dev, "Byte counter overflow\n");
+ drvdata->byte_cntr_overflow = true;
+ }
+ wake_up(&drvdata->wq);
+ return IRQ_HANDLED;
+}
+
+static int tmc_etr_byte_cntr_dev_register(struct tmc_drvdata *drvdata)
+{
+ int ret;
+ struct device *device;
+ dev_t dev;
+
+ ret = alloc_chrdev_region(&dev, 0, 1, drvdata->byte_cntr_node);
+ if (ret)
+ goto dev_err0;
+ cdev_init(&drvdata->byte_cntr_dev, &byte_cntr_fops);
+ drvdata->byte_cntr_dev.owner = THIS_MODULE;
+ drvdata->byte_cntr_dev.ops = &byte_cntr_fops;
+ ret = cdev_add(&drvdata->byte_cntr_dev, dev, 1);
+ if (ret)
+ goto dev_err1;
+ drvdata->byte_cntr_class = class_create(THIS_MODULE,
+ drvdata->byte_cntr_node);
+ if (!drvdata->byte_cntr_class)
+ goto dev_err2;
+ device = device_create(drvdata->byte_cntr_class, NULL,
+ drvdata->byte_cntr_dev.dev, drvdata,
+ drvdata->byte_cntr_node);
+ if (IS_ERR(device)) {
+ ret = PTR_ERR(device);
+ goto dev_err3;
+ }
+ return 0;
+dev_err3:
+ class_destroy(drvdata->byte_cntr_class);
+dev_err2:
+ cdev_del(&drvdata->byte_cntr_dev);
+dev_err1:
+ unregister_chrdev_region(drvdata->byte_cntr_dev.dev, 1);
+dev_err0:
+ return ret;
+}
+
+static void tmc_etr_byte_cntr_dev_deregister(struct tmc_drvdata *drvdata)
+{
+ device_destroy(drvdata->byte_cntr_class, drvdata->byte_cntr_dev.dev);
+ class_destroy(drvdata->byte_cntr_class);
+ cdev_del(&drvdata->byte_cntr_dev);
+ unregister_chrdev_region(drvdata->byte_cntr_dev.dev, 1);
+}
+
+static int tmc_etr_byte_cntr_init(struct platform_device *pdev,
+ struct tmc_drvdata *drvdata)
+{
+ int ret = 0;
+ size_t node_size = strlen("-stream") + 1;
+ char *node_name = (char *)((struct coresight_platform_data *)
+ (pdev->dev.platform_data))->name;
+
+ if (!drvdata->byte_cntr_present) {
+ dev_info(&pdev->dev, "Byte Counter feature absent\n");
+ return 0;
+ }
+
+ drvdata->byte_cntr_irq = platform_get_irq_byname(pdev,
+ "byte-cntr-irq");
+ if (drvdata->byte_cntr_irq < 0) {
+ dev_err(&pdev->dev, "Byte-cntr-irq not specified\n");
+ return 0;
+ }
+ ret = devm_request_irq(&pdev->dev, drvdata->byte_cntr_irq,
+ tmc_etr_byte_cntr_irq,
+ IRQF_TRIGGER_RISING | IRQF_SHARED,
+ node_name, drvdata);
+ if (ret) {
+ dev_err(&pdev->dev, "Request irq failed\n");
+ return ret;
+ }
+ init_waitqueue_head(&drvdata->wq);
+ node_size += strlen(node_name);
+ drvdata->byte_cntr_node = devm_kzalloc(&pdev->dev,
+ node_size, GFP_KERNEL);
+ strlcpy(drvdata->byte_cntr_node, node_name, node_size);
+ strlcat(drvdata->byte_cntr_node, "-stream", node_size);
+ ret = tmc_etr_byte_cntr_dev_register(drvdata);
+ if (ret) {
+ dev_err(&pdev->dev, "Byte cntr node not registered\n");
+ return ret;
+ }
+ dev_info(&pdev->dev, "Byte Counter feature enabled\n");
+ return 0;
+}
+
+static void tmc_etr_byte_cntr_exit(struct tmc_drvdata *drvdata)
+{
+ if (drvdata->byte_cntr_present)
+ tmc_etr_byte_cntr_dev_deregister(drvdata);
+}
+
static int __devinit tmc_probe(struct platform_device *pdev)
{
int ret;
@@ -1162,6 +1533,9 @@
spin_lock_init(&drvdata->spinlock);
mutex_init(&drvdata->read_lock);
mutex_init(&drvdata->usb_lock);
+ mutex_init(&drvdata->byte_cntr_lock);
+ mutex_init(&drvdata->byte_cntr_read_lock);
+ atomic_set(&drvdata->byte_cntr_irq_cnt, 0);
drvdata->clk = devm_clk_get(dev, "core_clk");
if (IS_ERR(drvdata->clk))
@@ -1207,10 +1581,16 @@
memset(drvdata->vaddr, 0, drvdata->size);
drvdata->buf = drvdata->vaddr;
drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
-
- ret = tmc_etr_bam_init(pdev, drvdata);
+ if (pdev->dev.of_node)
+ drvdata->byte_cntr_present = !of_property_read_bool
+ (pdev->dev.of_node,
+ "qcom,byte-cntr-absent");
+ ret = tmc_etr_byte_cntr_init(pdev, drvdata);
if (ret)
goto err0;
+ ret = tmc_etr_bam_init(pdev, drvdata);
+ if (ret)
+ goto err1;
} else {
baddr = devm_kzalloc(dev, PAGE_SIZE + drvdata->size,
GFP_KERNEL);
@@ -1277,7 +1657,7 @@
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc) {
ret = -ENOMEM;
- goto err1;
+ goto err2;
}
if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
desc->type = CORESIGHT_DEV_TYPE_SINK;
@@ -1290,7 +1670,7 @@
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
- goto err1;
+ goto err2;
}
} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
desc->type = CORESIGHT_DEV_TYPE_SINK;
@@ -1303,7 +1683,7 @@
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
- goto err1;
+ goto err2;
}
} else {
desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
@@ -1317,7 +1697,7 @@
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
- goto err1;
+ goto err2;
}
}
@@ -1327,14 +1707,16 @@
drvdata->miscdev.fops = &tmc_fops;
ret = misc_register(&drvdata->miscdev);
if (ret)
- goto err2;
+ goto err3;
dev_info(dev, "TMC initialized\n");
return 0;
-err2:
+err3:
coresight_unregister(drvdata->csdev);
-err1:
+err2:
tmc_etr_bam_exit(drvdata);
+err1:
+ tmc_etr_byte_cntr_exit(drvdata);
err0:
free_contiguous_memory_by_paddr(drvdata->paddr);
return ret;
@@ -1344,6 +1726,7 @@
{
struct tmc_drvdata *drvdata = platform_get_drvdata(pdev);
+ tmc_etr_byte_cntr_exit(drvdata);
misc_deregister(&drvdata->miscdev);
coresight_unregister(drvdata->csdev);
tmc_etr_bam_exit(drvdata);
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 76c6350..4c05978 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -188,12 +188,7 @@
min_rev = (rev & CRYPTO_CORE_MINOR_REV_MASK) >> CRYPTO_CORE_MINOR_REV;
step_rev = (rev & CRYPTO_CORE_STEP_REV_MASK) >> CRYPTO_CORE_STEP_REV;
- if ((maj_rev != 0x05) || (min_rev > 0x02) || (step_rev > 0x02)) {
- pr_err("Unknown Qualcomm crypto device at 0x%x, rev %d.%d.%d\n",
- pce_dev->phy_iobase, maj_rev, min_rev, step_rev);
- return -EIO;
- };
- if ((min_rev > 0) && (step_rev != 0)) {
+ if (maj_rev != 0x05) {
pr_err("Unknown Qualcomm crypto device at 0x%x, rev %d.%d.%d\n",
pce_dev->phy_iobase, maj_rev, min_rev, step_rev);
return -EIO;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 966e035..1ff989c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -498,7 +498,7 @@
kref_init(&context->refcount);
context->device = dev_priv->device;
context->pagetable = dev_priv->process_priv->pagetable;
-
+ context->dev_priv = dev_priv;
context->pid = dev_priv->process_priv->pid;
ret = kgsl_sync_timeline_create(context);
@@ -564,7 +564,7 @@
* detached, to avoid possibly freeing memory while
* it is still in use by the GPU.
*/
- kgsl_cancel_events_ctxt(device, context);
+ kgsl_context_cancel_events(device, context);
kgsl_context_put(context);
}
@@ -708,21 +708,22 @@
KGSL_PWR_WARN(device, "resume start\n");
mutex_lock(&device->mutex);
if (device->state == KGSL_STATE_SUSPEND) {
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
complete_all(&device->hwaccess_gate);
- } else {
+ } else if (device->state != KGSL_STATE_INIT) {
/*
* This is an error situation,so wait for the device
* to idle and then put the device to SLUMBER state.
* This will put the device to the right state when
* we resume.
*/
- device->ftbl->idle(device);
+ if (device->state == KGSL_STATE_ACTIVE)
+ device->ftbl->idle(device);
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
kgsl_pwrctrl_sleep(device);
KGSL_PWR_ERR(device,
"resume invoked without a suspend\n");
}
- kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
mutex_unlock(&device->mutex);
@@ -817,9 +818,9 @@
debugfs_remove_recursive(private->debug_root);
while (1) {
- rcu_read_lock();
+ spin_lock(&private->mem_lock);
entry = idr_get_next(&private->mem_idr, &next);
- rcu_read_unlock();
+ spin_unlock(&private->mem_lock);
if (entry == NULL)
break;
kgsl_mem_entry_put(entry);
@@ -830,8 +831,8 @@
*/
next = 0;
}
- kgsl_mmu_putpagetable(private->pagetable);
idr_destroy(&private->mem_idr);
+ kgsl_mmu_putpagetable(private->pagetable);
kfree(private);
return;
@@ -985,7 +986,7 @@
if (context == NULL)
break;
- if (context->pid == private->pid)
+ if (context->dev_priv == dev_priv)
kgsl_context_detach(context);
next = next + 1;
@@ -1253,11 +1254,11 @@
{
struct kgsl_mem_entry *entry;
- rcu_read_lock();
+ spin_lock(&process->mem_lock);
entry = idr_find(&process->mem_idr, id);
if (entry)
kgsl_mem_entry_get(entry);
- rcu_read_unlock();
+ spin_unlock(&process->mem_lock);
return entry;
}
@@ -1275,10 +1276,12 @@
static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry)
{
bool ret = false;
+
+ if (entry == NULL)
+ return false;
+
spin_lock(&entry->priv->mem_lock);
- if (entry && entry->pending_free) {
- ret = false;
- } else if (entry) {
+ if (!entry->pending_free) {
entry->pending_free = 1;
ret = true;
}
@@ -1560,9 +1563,11 @@
}
static void kgsl_freemem_event_cb(struct kgsl_device *device,
- void *priv, u32 id, u32 timestamp)
+ void *priv, u32 id, u32 timestamp, u32 type)
{
struct kgsl_mem_entry *entry = priv;
+
+ /* Free the memory for all event types */
trace_kgsl_mem_timestamp_free(device, entry, id, timestamp, 0);
kgsl_mem_entry_put(entry);
}
@@ -2626,21 +2631,23 @@
};
/**
- * kgsl_genlock_event_cb - Event callback for a genlock timestamp event
- * @device - The KGSL device that expired the timestamp
- * @priv - private data for the event
- * @context_id - the context id that goes with the timestamp
- * @timestamp - the timestamp that triggered the event
+ * kgsl_genlock_event_cb() - Event callback for a genlock timestamp event
+ * @device: The KGSL device that expired the timestamp
+ * @priv: private data for the event
+ * @context_id: the context id that goes with the timestamp
+ * @timestamp: the timestamp that triggered the event
+ * @type: Type of event that signaled the callback
*
* Release a genlock lock following the expiration of a timestamp
*/
static void kgsl_genlock_event_cb(struct kgsl_device *device,
- void *priv, u32 context_id, u32 timestamp)
+ void *priv, u32 context_id, u32 timestamp, u32 type)
{
struct kgsl_genlock_event_priv *ev = priv;
int ret;
+ /* Signal the lock for every event type */
ret = genlock_lock(ev->handle, GENLOCK_UNLOCK, 0, 0);
if (ret)
KGSL_CORE_ERR("Error while unlocking genlock: %d\n", ret);
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index d05d391..8d390a9 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -218,16 +218,16 @@
void kgsl_get_memory_usage(char *str, size_t len, unsigned int memflags);
-int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
- void (*cb)(struct kgsl_device *, void *, u32, u32), void *priv,
- void *owner);
+void kgsl_signal_event(struct kgsl_device *device,
+ struct kgsl_context *context, unsigned int timestamp,
+ unsigned int type);
+
+void kgsl_signal_events(struct kgsl_device *device,
+ struct kgsl_context *context, unsigned int type);
void kgsl_cancel_events(struct kgsl_device *device,
void *owner);
-void kgsl_cancel_events_ctxt(struct kgsl_device *device,
- struct kgsl_context *context);
-
extern const struct dev_pm_ops kgsl_pm_ops;
int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state);
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 9dfda32..2a77632 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -296,20 +296,17 @@
print_mem_entry(s, entry);
}
- spin_unlock(&private->mem_lock);
/* now print all the unbound entries */
while (1) {
- rcu_read_lock();
entry = idr_get_next(&private->mem_idr, &next);
- rcu_read_unlock();
-
if (entry == NULL)
break;
if (entry->memdesc.gpuaddr == 0)
print_mem_entry(s, entry);
next++;
}
+ spin_unlock(&private->mem_lock);
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 1f8bcbe..9629d3f 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -54,6 +54,22 @@
#define KGSL_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
+/*
+ * KGSL event types - these are passed to the event callback when the event
+ * expires or is cancelled
+ */
+
+#define KGSL_EVENT_TIMESTAMP_RETIRED 0
+#define KGSL_EVENT_CANCELLED 1
+
+/*
+ * "list" of event types for ftrace symbolic magic
+ */
+
+#define KGSL_EVENT_TYPES \
+ { KGSL_EVENT_TIMESTAMP_RETIRED, "retired" }, \
+ { KGSL_EVENT_CANCELLED, "cancelled" }
+
struct kgsl_device;
struct platform_device;
struct kgsl_device_private;
@@ -127,10 +143,12 @@
int mpu_range;
};
+typedef void (*kgsl_event_func)(struct kgsl_device *, void *, u32, u32, u32);
+
struct kgsl_event {
struct kgsl_context *context;
uint32_t timestamp;
- void (*func)(struct kgsl_device *, void *, u32, u32);
+ kgsl_event_func func;
void *priv;
struct list_head list;
void *owner;
@@ -283,6 +301,7 @@
struct kref refcount;
uint32_t id;
pid_t pid;
+ struct kgsl_device_private *dev_priv;
unsigned long priv;
struct kgsl_device *device;
struct kgsl_pagetable *pagetable;
@@ -329,6 +348,9 @@
struct kgsl_device *kgsl_get_device(int dev_idx);
+int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
+ kgsl_event_func func, void *priv, void *owner);
+
static inline void kgsl_process_add_stats(struct kgsl_process_private *priv,
unsigned int type, size_t size)
{
@@ -547,4 +569,30 @@
return context;
}
+/**
+ * kgsl_context_cancel_events() - Cancel all events for a context
+ * @device: Pointer to the KGSL device structure for the GPU
+ * @context: Pointer to the KGSL context
+ *
+ * Signal all pending events on the context with KGSL_EVENT_CANCELLED
+ */
+static inline void kgsl_context_cancel_events(struct kgsl_device *device,
+ struct kgsl_context *context)
+{
+ kgsl_signal_events(device, context, KGSL_EVENT_CANCELLED);
+}
+
+/**
+ * kgsl_context_cancel_events_timestamp() - cancel events for a given timestamp
+ * @device: Pointer to the KGSL device that owns the context
+ * @context: Pointer to the context that owns the event or NULL for global
+ * @timestamp: Timestamp to cancel events for
+ *
+ * Cancel events pending for a specific timestamp
+ */
+static inline void kgsl_cancel_events_timestamp(struct kgsl_device *device,
+ struct kgsl_context *context, unsigned int timestamp)
+{
+ kgsl_signal_event(device, context, timestamp, KGSL_EVENT_CANCELLED);
+}
#endif /* __KGSL_DEVICE_H */
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 1fc7467..c221c4a 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -385,6 +385,7 @@
kgsl_gem_free_memory(obj);
drm_gem_object_release(obj);
kfree(obj->driver_private);
+ kfree(obj);
}
int
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 40974b0..e4f502a 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -18,6 +18,12 @@
#include "kgsl_trace.h"
+static inline struct list_head *_get_list_head(struct kgsl_device *device,
+ struct kgsl_context *context)
+{
+ return (context) ? &context->events : &device->events;
+}
+
static void _add_event_to_list(struct list_head *head, struct kgsl_event *event)
{
struct list_head *n;
@@ -36,27 +42,182 @@
list_add_tail(&event->list, head);
}
+static inline void _do_signal_event(struct kgsl_device *device,
+ struct kgsl_event *event, unsigned int timestamp,
+ unsigned int type)
+{
+ int id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL;
+
+ trace_kgsl_fire_event(id, timestamp, type, jiffies - event->created);
+
+ if (event->func)
+ event->func(device, event->priv, id, timestamp, type);
+
+ list_del(&event->list);
+ kgsl_context_put(event->context);
+ kfree(event);
+
+ kgsl_active_count_put(device);
+}
+
+static void _retire_events(struct kgsl_device *device,
+ struct list_head *head, unsigned int timestamp)
+{
+ struct kgsl_event *event, *tmp;
+
+ list_for_each_entry_safe(event, tmp, head, list) {
+ if (timestamp_cmp(timestamp, event->timestamp) < 0)
+ break;
+
+ _do_signal_event(device, event, event->timestamp,
+ KGSL_EVENT_TIMESTAMP_RETIRED);
+ }
+}
+
+static struct kgsl_event *_find_event(struct kgsl_device *device,
+ struct list_head *head, unsigned int timestamp,
+ kgsl_event_func func, void *priv)
+{
+ struct kgsl_event *event, *tmp;
+
+ list_for_each_entry_safe(event, tmp, head, list) {
+ if (timestamp == event->timestamp && func == event->func &&
+ event->priv == priv)
+ return event;
+ }
+
+ return NULL;
+}
+
+/**
+ * _signal_event() - send a signal to a specific event in the list
+ * @device: Pointer to the KGSL device struct
+ * @head: Pointer to the event list to process
+ * @timestamp: timestamp of the event to signal
+ * @cur: timestamp value to send to the callback
+ * @type: Signal ID to send to the callback
+ *
+ * Send the specified signal to the events in the list with the specified
+ * timestamp. The timestamp 'cur' is sent to the callback so it knows
+ * when the signal was delivered
+ */
+static void _signal_event(struct kgsl_device *device,
+ struct list_head *head, unsigned int timestamp,
+ unsigned int cur, unsigned int type)
+{
+ struct kgsl_event *event, *tmp;
+
+ list_for_each_entry_safe(event, tmp, head, list) {
+ if (timestamp_cmp(timestamp, event->timestamp) == 0)
+ _do_signal_event(device, event, cur, type);
+ }
+}
+
+/**
+ * _signal_events() - send a signal to all the events in a list
+ * @device: Pointer to the KGSL device struct
+ * @head: Pointer to the event list to process
+ * @timestamp: Timestamp to pass to the events (this should be the current
+ * timestamp when the signal is sent)
+ * @type: Signal ID to send to the callback
+ *
+ * Send the specified signal to all the events in the list and destroy them
+ */
+static void _signal_events(struct kgsl_device *device,
+ struct list_head *head, uint32_t timestamp,
+ unsigned int type)
+{
+ struct kgsl_event *event, *tmp;
+
+ list_for_each_entry_safe(event, tmp, head, list)
+ _do_signal_event(device, event, timestamp, type);
+
+}
+
+/**
+ * kgsl_signal_event() - send a signal to a specific event in the context
+ * @device: Pointer to the KGSL device struct
+ * @context: Pointer to the KGSL context
+ * @timestamp: Timestamp of the event to signal
+ * @type: Signal ID to send to the callback
+ *
+ * Send the specified signal to all the events in the context with the given
+ * timestamp
+ */
+void kgsl_signal_event(struct kgsl_device *device,
+ struct kgsl_context *context, unsigned int timestamp,
+ unsigned int type)
+{
+ struct list_head *head = _get_list_head(device, context);
+ uint32_t cur;
+
+ BUG_ON(!mutex_is_locked(&device->mutex));
+
+ cur = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED);
+ _signal_event(device, head, timestamp, cur, type);
+
+ if (context && list_empty(&context->events))
+ list_del_init(&context->events_list);
+}
+EXPORT_SYMBOL(kgsl_signal_event);
+
+/**
+ * kgsl_signal_events() - send a signal to all events in the context
+ * @device: Pointer to the KGSL device struct
+ * @context: Pointer to the KGSL context
+ * @type: Signal ID to send to the callback function
+ *
+ * Send the specified signal to all the events in the context
+ */
+void kgsl_signal_events(struct kgsl_device *device,
+ struct kgsl_context *context, unsigned int type)
+{
+ struct list_head *head = _get_list_head(device, context);
+ uint32_t cur;
+
+ BUG_ON(!mutex_is_locked(&device->mutex));
+
+ /*
+ * Send the current timestamp to the callback so it knows when the
+ * signal occured
+ */
+
+ cur = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED);
+
+ _signal_events(device, head, cur, type);
+
+ /*
+ * Remove the context from the master list since we know everything on
+ * it has been removed
+ */
+
+ if (context)
+ list_del_init(&context->events_list);
+}
+EXPORT_SYMBOL(kgsl_signal_events);
+
/**
* kgsl_add_event - Add a new timstamp event for the KGSL device
* @device - KGSL device for the new event
* @id - the context ID that the event should be added to
* @ts - the timestamp to trigger the event on
- * @cb - callback function to call when the timestamp expires
+ * @func - callback function to call when the timestamp expires
* @priv - private data for the specific event type
* @owner - driver instance that owns this event
*
* @returns - 0 on success or error code on failure
*/
int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
- void (*cb)(struct kgsl_device *, void *, u32, u32), void *priv,
- void *owner)
+ kgsl_event_func func, void *priv, void *owner)
{
int ret;
struct kgsl_event *event;
unsigned int cur_ts;
struct kgsl_context *context = NULL;
- if (cb == NULL)
+ BUG_ON(!mutex_is_locked(&device->mutex));
+
+ if (func == NULL)
return -EINVAL;
if (id != KGSL_MEMSTORE_GLOBAL) {
@@ -74,8 +235,9 @@
*/
if (timestamp_cmp(cur_ts, ts) >= 0) {
- trace_kgsl_fire_event(id, ts, 0);
- cb(device, priv, id, ts);
+ trace_kgsl_fire_event(id, cur_ts, ts, 0);
+
+ func(device, priv, id, ts, KGSL_EVENT_TIMESTAMP_RETIRED);
kgsl_context_put(context);
return 0;
}
@@ -100,7 +262,7 @@
event->context = context;
event->timestamp = ts;
event->priv = priv;
- event->func = cb;
+ event->func = func;
event->owner = owner;
event->created = jiffies;
@@ -129,131 +291,60 @@
EXPORT_SYMBOL(kgsl_add_event);
/**
- * kgsl_cancel_events_ctxt - Cancel all events for a context
- * @device - KGSL device for the events to cancel
- * @context - context whose events we want to cancel
+ * kgsl_cancel_events() - Cancel all global events owned by a process
+ * @device: Pointer to the KGSL device struct
+ * @owner: driver instance that owns the events to cancel
*
+ * Cancel all global events that match the owner pointer
*/
-void kgsl_cancel_events_ctxt(struct kgsl_device *device,
- struct kgsl_context *context)
-{
- struct kgsl_event *event, *event_tmp;
- unsigned int id, cur;
-
- cur = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED);
- id = context->id;
-
- /*
- * Increment the refcount to avoid freeing the context while
- * cancelling its events
- */
- _kgsl_context_get(context);
-
- /* Remove ourselves from the master pending list */
- list_del_init(&context->events_list);
-
- list_for_each_entry_safe(event, event_tmp, &context->events, list) {
- /*
- * "cancel" the events by calling their callback.
- * Currently, events are used for lock and memory
- * management, so if the process is dying the right
- * thing to do is release or free.
- *
- * Send the current timestamp so the event knows how far the
- * system got before the event was canceled
- */
- list_del(&event->list);
-
- trace_kgsl_fire_event(id, cur, jiffies - event->created);
-
- if (event->func)
- event->func(device, event->priv, id, cur);
-
- kgsl_context_put(context);
- kfree(event);
-
- kgsl_active_count_put(device);
- }
- kgsl_context_put(context);
-}
-
-/**
- * kgsl_cancel_events - Cancel all generic events for a process
- * @device - KGSL device for the events to cancel
- * @owner - driver instance that owns the events to cancel
- *
- */
-void kgsl_cancel_events(struct kgsl_device *device,
- void *owner)
+void kgsl_cancel_events(struct kgsl_device *device, void *owner)
{
struct kgsl_event *event, *event_tmp;
unsigned int cur;
+ BUG_ON(!mutex_is_locked(&device->mutex));
+
cur = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED);
list_for_each_entry_safe(event, event_tmp, &device->events, list) {
if (event->owner != owner)
continue;
- /*
- * "cancel" the events by calling their callback.
- * Currently, events are used for lock and memory
- * management, so if the process is dying the right
- * thing to do is release or free. Send the current timestamp so
- * the callback knows how far the GPU made it before things went
- * explosion
- */
- list_del(&event->list);
-
- trace_kgsl_fire_event(KGSL_MEMSTORE_GLOBAL, cur,
- jiffies - event->created);
-
- if (event->func)
- event->func(device, event->priv, KGSL_MEMSTORE_GLOBAL,
- cur);
-
- if (event->context)
- kgsl_context_put(event->context);
- kfree(event);
-
- kgsl_active_count_put(device);
+ _do_signal_event(device, event, cur, KGSL_EVENT_CANCELLED);
}
}
EXPORT_SYMBOL(kgsl_cancel_events);
-static void _process_event_list(struct kgsl_device *device,
- struct list_head *head, unsigned int timestamp)
+/**
+ * kgsl_cancel_event() - send a cancel signal to a specific event
+ * @device: Pointer to the KGSL device struct
+ * @context: Pointer to the KGSL context
+ * @timestamp: Timestamp of the event to cancel
+ * @func: Callback function of the event - this is used to match the actual
+ * event
+ * @priv: Private data for the callback function - this is used to match to the
+ * actual event
+ *
+ * Send the a cancel signal to a specific event that matches all the parameters
+ */
+
+void kgsl_cancel_event(struct kgsl_device *device, struct kgsl_context *context,
+ unsigned int timestamp, kgsl_event_func func,
+ void *priv)
{
- struct kgsl_event *event, *tmp;
- unsigned int id;
+ struct kgsl_event *event;
+ struct list_head *head = _get_list_head(device, context);
- list_for_each_entry_safe(event, tmp, head, list) {
- if (timestamp_cmp(timestamp, event->timestamp) < 0)
- break;
+ event = _find_event(device, head, timestamp, func, priv);
- id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL;
+ if (event) {
+ unsigned int cur = kgsl_readtimestamp(device, context,
+ KGSL_TIMESTAMP_RETIRED);
- /*
- * Send the timestamp of the expired event, not the current
- * timestamp. This prevents the event handlers from getting
- * confused if they don't bother comparing the current timetamp
- * to the timestamp they wanted
- */
- list_del(&event->list);
-
- trace_kgsl_fire_event(id, event->timestamp,
- jiffies - event->created);
-
- if (event->func)
- event->func(device, event->priv, id, event->timestamp);
-
- if (event->context)
- kgsl_context_put(event->context);
- kfree(event);
-
- kgsl_active_count_put(device);
+ _do_signal_event(device, event, cur, KGSL_EVENT_CANCELLED);
}
}
+EXPORT_SYMBOL(kgsl_cancel_event);
static inline int _mark_next_event(struct kgsl_device *device,
struct list_head *head)
@@ -282,7 +373,7 @@
unsigned int timestamp = kgsl_readtimestamp(device, context,
KGSL_TIMESTAMP_RETIRED);
- _process_event_list(device, &context->events, timestamp);
+ _retire_events(device, &context->events, timestamp);
/*
* _mark_next event will return 1 as long as the next event
@@ -313,7 +404,7 @@
/* Process expired global events */
timestamp = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED);
- _process_event_list(device, &device->events, timestamp);
+ _retire_events(device, &device->events, timestamp);
_mark_next_event(device, &device->events);
/* Now process all of the pending contexts */
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index a7c9347..ecda5a7 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -472,7 +472,8 @@
* Return - void
*/
static void kgsl_iommu_clk_disable_event(struct kgsl_device *device, void *data,
- unsigned int id, unsigned int ts)
+ unsigned int id, unsigned int ts,
+ u32 type)
{
struct kgsl_mmu *mmu = data;
struct kgsl_iommu *iommu = mmu->priv;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 20391be..5479ae9 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -79,6 +79,7 @@
static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
int requested_state);
static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state);
+static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state);
/* Update the elapsed time at a particular clock level
* if the device is active(on_time = true).Otherwise
@@ -643,6 +644,9 @@
case KGSL_PWRFLAGS_AXI_ON:
kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
break;
+ case KGSL_PWRFLAGS_POWER_ON:
+ kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON);
+ break;
}
set_bit(flag, &device->pwrctrl.ctrl_flags);
} else {
@@ -713,6 +717,20 @@
return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_AXI_ON);
}
+static int kgsl_pwrctrl_force_rail_on_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_POWER_ON);
+}
+
+static int kgsl_pwrctrl_force_rail_on_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_POWER_ON);
+}
+
DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store);
DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
kgsl_pwrctrl_max_gpuclk_store);
@@ -749,6 +767,9 @@
DEVICE_ATTR(force_bus_on, 0644,
kgsl_pwrctrl_force_bus_on_show,
kgsl_pwrctrl_force_bus_on_store);
+DEVICE_ATTR(force_rail_on, 0644,
+ kgsl_pwrctrl_force_rail_on_show,
+ kgsl_pwrctrl_force_rail_on_store);
static const struct device_attribute *pwrctrl_attr_list[] = {
&dev_attr_gpuclk,
@@ -765,6 +786,7 @@
&dev_attr_reset_count,
&dev_attr_force_clk_on,
&dev_attr_force_bus_on,
+ &dev_attr_force_rail_on,
NULL
};
@@ -917,6 +939,9 @@
{
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ if (test_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->ctrl_flags))
+ return;
+
if (state == KGSL_PWRFLAGS_OFF) {
if (test_and_clear_bit(KGSL_PWRFLAGS_POWER_ON,
&pwr->power_flags)) {
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 6094e04..333089a 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -544,6 +544,16 @@
int remain = device->snapshot_maxsize - sizeof(*header);
void *snapshot;
struct timespec boot;
+ int ret = 0;
+
+ /*
+ * Bail if failed to get active count for GPU,
+ * try again
+ */
+ if (kgsl_active_count_get(device)) {
+ KGSL_DRV_ERR(device, "Failed to get GPU active count");
+ return -EINVAL;
+ }
/* increment the hang count (on hang) for good book keeping */
if (hang)
@@ -558,19 +568,23 @@
* of the state and never frozen.
*/
- if (hang && device->snapshot_frozen == 1)
- return 0;
+ if (hang && device->snapshot_frozen == 1) {
+ ret = 0;
+ goto done;
+ }
if (device->snapshot == NULL) {
KGSL_DRV_ERR(device,
"snapshot: No snapshot memory available\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto done;
}
if (remain < sizeof(*header)) {
KGSL_DRV_ERR(device,
"snapshot: Not enough memory for the header\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto done;
}
header->magic = SNAPSHOT_MAGIC;
@@ -606,7 +620,10 @@
__pa(device->snapshot), device->snapshot_size);
if (hang)
sysfs_notify(&device->snapshot_kobj, NULL, "timestamp");
- return 0;
+
+done:
+ kgsl_active_count_put(device);
+ return ret;
}
EXPORT_SYMBOL(kgsl_device_snapshot);
@@ -715,7 +732,10 @@
{
if (device && count > 0) {
mutex_lock(&device->mutex);
- kgsl_device_snapshot(device, 0);
+ if (!kgsl_active_count_get(device)) {
+ kgsl_device_snapshot(device, 0);
+ kgsl_active_count_put(device);
+ }
mutex_unlock(&device->mutex);
}
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 62ecdeb..5379670 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -86,7 +86,7 @@
*/
static inline void kgsl_fence_event_cb(struct kgsl_device *device,
- void *priv, u32 context_id, u32 timestamp)
+ void *priv, u32 context_id, u32 timestamp, u32 type)
{
struct kgsl_fence_event_priv *ev = priv;
kgsl_sync_timeline_signal(ev->context->timeline, ev->timestamp);
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 5981163..831b13f 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -771,21 +771,25 @@
TRACE_EVENT(kgsl_fire_event,
TP_PROTO(unsigned int id, unsigned int ts,
- unsigned int age),
- TP_ARGS(id, ts, age),
+ unsigned int type, unsigned int age),
+ TP_ARGS(id, ts, type, age),
TP_STRUCT__entry(
__field(unsigned int, id)
__field(unsigned int, ts)
+ __field(unsigned int, type)
__field(unsigned int, age)
),
TP_fast_assign(
__entry->id = id;
__entry->ts = ts;
+ __entry->type = type;
__entry->age = age;
),
TP_printk(
- "ctx=%u ts=%u age=%u",
- __entry->id, __entry->ts, __entry->age)
+ "ctx=%u ts=%u type=%s age=%u",
+ __entry->id, __entry->ts,
+ __print_symbolic(__entry->type, KGSL_EVENT_TYPES),
+ __entry->age)
);
TRACE_EVENT(kgsl_active_count,
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 27818b4..f0793b2 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -499,10 +499,13 @@
return 0;
}
+#define IADC_CENTER 0xC000
+#define IADC_READING_RESOLUTION_N 542535
+#define IADC_READING_RESOLUTION_D 100000
static int32_t qpnp_convert_raw_offset_voltage(void)
{
struct qpnp_iadc_drv *iadc = qpnp_iadc;
- uint32_t num = 0;
+ s64 numerator;
if ((iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw) == 0) {
pr_err("raw offset errors! raw_gain:0x%x and raw_offset:0x%x\n",
@@ -510,19 +513,23 @@
return -EINVAL;
}
- iadc->adc->calib.offset_uv = 0;
+ numerator = iadc->adc->calib.offset_raw - IADC_CENTER;
+ numerator *= IADC_READING_RESOLUTION_N;
+ iadc->adc->calib.offset_uv = div_s64(numerator,
+ IADC_READING_RESOLUTION_D);
- num = iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw;
+ numerator = iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw;
+ numerator *= IADC_READING_RESOLUTION_N;
- iadc->adc->calib.gain_uv = (num * QPNP_ADC_GAIN_NV)/
- (iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
+ iadc->adc->calib.gain_uv = div_s64(numerator,
+ IADC_READING_RESOLUTION_D);
pr_debug("gain_uv:%d offset_uv:%d\n",
iadc->adc->calib.gain_uv, iadc->adc->calib.offset_uv);
return 0;
}
-int32_t qpnp_iadc_calibrate_for_trim(void)
+int32_t qpnp_iadc_calibrate_for_trim(bool batfet_closed)
{
struct qpnp_iadc_drv *iadc = qpnp_iadc;
uint8_t rslt_lsb, rslt_msb;
@@ -544,7 +551,14 @@
iadc->adc->calib.gain_raw = raw_data;
- if (iadc->external_rsense) {
+ /*
+ * there is a features in the BMS where if the batfet is opened
+ * the BMS reads from INTERNAL_RSENSE (channel 0) actually go to
+ * OFFSET_CALIBRATION_CSP_CSN (channel 5). Hence if batfet is opened
+ * we have to calibrate based on OFFSET_CALIBRATION_CSP_CSN even for
+ * internal rsense.
+ */
+ if (!batfet_closed || iadc->external_rsense) {
/* external offset calculation */
rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP_CSN,
&raw_data, mode_sel);
@@ -621,7 +635,7 @@
struct qpnp_iadc_drv *iadc = qpnp_iadc;
int rc = 0;
- rc = qpnp_iadc_calibrate_for_trim();
+ rc = qpnp_iadc_calibrate_for_trim(true);
if (rc)
pr_debug("periodic IADC calibration failed\n");
else
@@ -716,9 +730,8 @@
die_temp_offset = -die_temp_offset;
if (die_temp_offset > QPNP_IADC_DIE_TEMP_CALIB_OFFSET) {
- iadc->die_temp =
- result_pmic_therm.physical;
- rc = qpnp_iadc_calibrate_for_trim();
+ iadc->die_temp = result_pmic_therm.physical;
+ rc = qpnp_iadc_calibrate_for_trim(true);
if (rc)
pr_err("periodic IADC calibration failed\n");
}
@@ -1008,7 +1021,7 @@
}
iadc->iadc_initialized = true;
- rc = qpnp_iadc_calibrate_for_trim();
+ rc = qpnp_iadc_calibrate_for_trim(true);
if (rc)
dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
schedule_delayed_work(&iadc->iadc_work,
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 5415f4e..b725200 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1996,7 +1996,7 @@
if (atomic_read(&data->st_enabled) == 0)
break;
- pm_runtime_put(&data->client->adapter->dev);
+ pm_runtime_put(data->client->adapter->dev.parent);
atomic_set(&data->st_enabled, 0);
complete(&data->st_completion);
mxt_interrupt(data->client->irq, data);
@@ -2015,8 +2015,9 @@
}
INIT_COMPLETION(data->st_completion);
INIT_COMPLETION(data->st_powerdown);
- atomic_set(&data->st_pending_irqs, 0);
atomic_set(&data->st_enabled, 1);
+ synchronize_irq(data->client->irq);
+ atomic_set(&data->st_pending_irqs, 0);
break;
default:
dev_err(&data->client->dev, "unsupported value: %lu\n", value);
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index ba0be2b..908d0d7 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -1056,6 +1056,8 @@
rmi4_pdata->i2c_pull_up = of_property_read_bool(np,
"synaptics,i2c-pull-up");
+ rmi4_pdata->power_down_enable = of_property_read_bool(np,
+ "synaptics,power-down");
rmi4_pdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
rmi4_pdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
@@ -2003,7 +2005,7 @@
error_reg_en_vcc_i2c:
if (rmi4_data->board->i2c_pull_up)
- reg_set_optimum_mode_check(rmi4_data->vdd, 0);
+ reg_set_optimum_mode_check(rmi4_data->vcc_i2c, 0);
error_reg_opt_i2c:
regulator_disable(rmi4_data->vdd);
error_reg_en_vdd:
@@ -2592,29 +2594,53 @@
bool on)
{
int retval;
+ int load_ua;
if (on == false)
goto regulator_hpm;
- retval = reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_LPM_LOAD_UA);
+ load_ua = rmi4_data->board->power_down_enable ? 0 : RMI4_LPM_LOAD_UA;
+ retval = reg_set_optimum_mode_check(rmi4_data->vdd, load_ua);
if (retval < 0) {
dev_err(&rmi4_data->i2c_client->dev,
- "Regulator vcc_ana set_opt failed rc=%d\n",
+ "Regulator vdd_ana set_opt failed rc=%d\n",
retval);
goto fail_regulator_lpm;
}
- if (rmi4_data->board->i2c_pull_up) {
- retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
- RMI4_I2C_LPM_LOAD_UA);
- if (retval < 0) {
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_disable(rmi4_data->vdd);
+ if (retval) {
dev_err(&rmi4_data->i2c_client->dev,
- "Regulator vcc_i2c set_opt failed rc=%d\n",
+ "Regulator vdd disable failed rc=%d\n",
retval);
goto fail_regulator_lpm;
}
}
+ if (rmi4_data->board->i2c_pull_up) {
+ load_ua = rmi4_data->board->power_down_enable ?
+ 0 : RMI4_I2C_LPM_LOAD_UA;
+ retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
+ load_ua);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c set_opt failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_lpm;
+ }
+
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_disable(rmi4_data->vcc_i2c);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c disable failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_lpm;
+ }
+ }
+ }
+
return 0;
regulator_hpm:
@@ -2628,6 +2654,16 @@
goto fail_regulator_hpm;
}
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_enable(rmi4_data->vdd);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vdd enable failed rc=%d\n",
+ retval);
+ goto fail_regulator_hpm;
+ }
+ }
+
if (rmi4_data->board->i2c_pull_up) {
retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
RMI4_I2C_LOAD_UA);
@@ -2637,6 +2673,26 @@
retval);
goto fail_regulator_hpm;
}
+
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_enable(rmi4_data->vcc_i2c);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c enable failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_hpm;
+ }
+ }
+ }
+
+ if (rmi4_data->board->power_down_enable) {
+ retval = synaptics_rmi4_reset_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to issue reset command, rc = %d\n",
+ __func__, retval);
+ return retval;
+ }
}
return 0;
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index e84b477..3c2be38 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -403,15 +403,22 @@
/**
* kpdbl_config_data - kpdbl configuration data
* @pwm_cfg - device pwm configuration
- * @row_src_sel_val - select source, 0 for vph_pwr and 1 for vbst
- * @row_scan_en - enable row scan
- * @row_scan_val - map to enable needed rows
+ * @mode - running mode: pwm or lut
+ * @row_id - row id of the led
+ * @row_src_vbst - 0 for vph_pwr and 1 for vbst
+ * @row_src_en - enable row source
+ * @always_on - always on row
+ * @lut_params - lut parameters to be used by pwm driver
+ * @duty_cycles - duty cycles for lut
*/
struct kpdbl_config_data {
struct pwm_config_data *pwm_cfg;
- u32 row_src_sel_val;
- u32 row_scan_en;
- u32 row_scan_val;
+ u32 row_id;
+ bool row_src_vbst;
+ bool row_src_en;
+ bool always_on;
+ struct pwm_duty_cycles *duty_cycles;
+ struct lut_params lut_params;
};
/**
@@ -458,6 +465,8 @@
int turn_off_delay_ms;
};
+static int num_kpbl_leds_on;
+
static int
qpnp_led_masked_write(struct qpnp_led_data *led, u16 addr, u8 mask, u8 val)
{
@@ -906,35 +915,73 @@
if (!led->kpdbl_cfg->pwm_cfg->blinking)
led->kpdbl_cfg->pwm_cfg->mode =
led->kpdbl_cfg->pwm_cfg->default_mode;
- rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
- KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
- duty_us = (led->kpdbl_cfg->pwm_cfg->pwm_period_us *
- led->cdev.brightness) / KPDBL_MAX_LEVEL;
- rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev, duty_us,
- led->kpdbl_cfg->pwm_cfg->pwm_period_us);
- if (rc < 0) {
- dev_err(&led->spmi_dev->dev, "pwm config failed\n");
- return rc;
+ if (!num_kpbl_leds_on) {
+ rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
+ KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n", rc);
+ return rc;
+ }
}
+
+ if (led->kpdbl_cfg->pwm_cfg->mode == PWM_MODE) {
+ duty_us = (led->kpdbl_cfg->pwm_cfg->pwm_period_us *
+ led->cdev.brightness) / KPDBL_MAX_LEVEL;
+ rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev,
+ duty_us,
+ led->kpdbl_cfg->pwm_cfg->pwm_period_us);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev, "pwm config failed\n");
+ return rc;
+ }
+ }
+
rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
if (rc < 0) {
dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
return rc;
}
+
+ num_kpbl_leds_on++;
+
} else {
led->kpdbl_cfg->pwm_cfg->mode =
led->kpdbl_cfg->pwm_cfg->default_mode;
- pwm_disable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
- rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
- KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Failed to write led enable reg\n");
- return rc;
+
+ if (led->kpdbl_cfg->always_on) {
+ rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev, 0,
+ led->kpdbl_cfg->pwm_cfg->pwm_period_us);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "pwm config failed\n");
+ return rc;
+ }
+
+ rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
+ return rc;
+ }
+ } else
+ pwm_disable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
+
+ if (num_kpbl_leds_on > 0)
+ num_kpbl_leds_on--;
+
+ if (!num_kpbl_leds_on) {
+ rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
+ KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led enable reg\n");
+ return rc;
+ }
}
}
led->kpdbl_cfg->pwm_cfg->blinking = false;
+
qpnp_dump_regs(led, kpdbl_debug_regs, ARRAY_SIZE(kpdbl_debug_regs));
return 0;
@@ -1000,11 +1047,14 @@
struct qpnp_led_data *led;
led = container_of(led_cdev, struct qpnp_led_data, cdev);
- if (value < LED_OFF || value > led->cdev.max_brightness) {
+ if (value < LED_OFF) {
dev_err(&led->spmi_dev->dev, "Invalid brightness value\n");
return;
}
+ if (value > led->cdev.max_brightness)
+ value = led->cdev.max_brightness;
+
led->cdev.brightness = value;
schedule_work(&led->work);
}
@@ -2013,16 +2063,31 @@
int rc;
u8 val;
- /* enable row source selct */
- rc = qpnp_led_masked_write(led, KPDBL_ROW_SRC_SEL(led->base),
- KPDBL_ROW_SRC_SEL_VAL_MASK, led->kpdbl_cfg->row_src_sel_val);
+ /* select row source - vbst or vph */
+ rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ KPDBL_ROW_SRC_SEL(led->base), &val, 1);
if (rc) {
dev_err(&led->spmi_dev->dev,
- "Enable row src sel write failed(%d)\n", rc);
+ "Unable to read from addr=%x, rc(%d)\n",
+ KPDBL_ROW_SRC_SEL(led->base), rc);
return rc;
}
- /* row source */
+ if (led->kpdbl_cfg->row_src_vbst)
+ val |= 1 << led->kpdbl_cfg->row_id;
+ else
+ val &= ~(1 << led->kpdbl_cfg->row_id);
+
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ KPDBL_ROW_SRC_SEL(led->base), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to read from addr=%x, rc(%d)\n",
+ KPDBL_ROW_SRC_SEL(led->base), rc);
+ return rc;
+ }
+
+ /* row source enable */
rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
KPDBL_ROW_SRC(led->base), &val, 1);
if (rc) {
@@ -2032,12 +2097,10 @@
return rc;
}
- val &= ~KPDBL_ROW_SCAN_VAL_MASK;
- val |= led->kpdbl_cfg->row_scan_val;
-
- led->kpdbl_cfg->row_scan_en <<= KPDBL_ROW_SCAN_EN_SHIFT;
- val &= ~KPDBL_ROW_SCAN_EN_MASK;
- val |= led->kpdbl_cfg->row_scan_en;
+ if (led->kpdbl_cfg->row_src_en)
+ val |= KPDBL_ROW_SCAN_EN_MASK | (1 << led->kpdbl_cfg->row_id);
+ else
+ val &= ~(1 << led->kpdbl_cfg->row_id);
rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
KPDBL_ROW_SRC(led->base), &val, 1);
@@ -2565,6 +2628,7 @@
dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
return -ENOMEM;
}
+
rc = of_property_read_string(node, "qcom,mode", &mode);
if (!rc) {
led_mode = qpnp_led_get_mode(mode);
@@ -2590,23 +2654,20 @@
if (rc < 0)
return rc;
- rc = of_property_read_u32(node, "qcom,row-src-sel-val", &val);
+ rc = of_property_read_u32(node, "qcom,row-id", &val);
if (!rc)
- led->kpdbl_cfg->row_src_sel_val = val;
+ led->kpdbl_cfg->row_id = val;
else
return rc;
- rc = of_property_read_u32(node, "qcom,row-scan-val", &val);
- if (!rc)
- led->kpdbl_cfg->row_scan_val = val;
- else
- return rc;
+ led->kpdbl_cfg->row_src_vbst =
+ of_property_read_bool(node, "qcom,row-src-vbst");
- rc = of_property_read_u32(node, "qcom,row-scan-en", &val);
- if (!rc)
- led->kpdbl_cfg->row_scan_en = val;
- else
- return rc;
+ led->kpdbl_cfg->row_src_en =
+ of_property_read_bool(node, "qcom,row-src-en");
+
+ led->kpdbl_cfg->always_on =
+ of_property_read_bool(node, "qcom,always-on");
return 0;
}
@@ -2856,6 +2917,7 @@
goto fail_id_check;
}
} else if (strncmp(led_label, "kpdbl", sizeof("kpdbl")) == 0) {
+ num_kpbl_leds_on = 0;
rc = qpnp_get_config_kpdbl(led, temp);
if (rc < 0) {
dev_err(&led->spmi_dev->dev,
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 74ec99a..4668d02 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -146,6 +146,15 @@
snapshot config = 3264 * 2448 at 18 fps.
2 lanes max fps is 18, 4 lanes max fps is 24.
+config OV5648
+ bool "Sensor OV5648 (BAYER 5M)"
+ depends on MSMB_CAMERA
+ ---help---
+ OmniVision 5 MP Bayer Sensor, only use 1 mipi lane,
+ preview set to 1296*972 at 30 fps,
+ snapshot set to 2592*1944 at 12 fps,
+ This sensor driver does not support auto focus.
+
config MT9M114
bool "Sensor MT9M114 (YUV 1.26MP)"
depends on MSMB_CAMERA
@@ -191,6 +200,15 @@
and QSXGA snapshot at 15 fps.
This sensor driver does not support auto focus.
+config OV12830
+ bool "OmniVision OV12830 (BAYER 12MP)"
+ depends on MSMB_CAMERA
+ ---help---
+ OmniVision 12.8 MP Bayer Sensor with auto focus.uses
+ 4 mipi lanes, preview config = 2112 * 1500 at 30 fps,
+ snapshot config = 4224 * 3000 at 15 fps.
+ 2 lanes max fps is 18, 4 lanes max fps is 24.
+
config MSM_V4L2_VIDEO_OVERLAY_DEVICE
tristate "Qualcomm MSM V4l2 video overlay device"
---help---
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 4c5f258..07a66e6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -22,7 +22,7 @@
#include "msm.h"
#include "msm_camera_io_util.h"
-#define VFE32_BURST_LEN 1
+#define VFE32_BURST_LEN 2
#define VFE32_UB_SIZE 1024
#define VFE32_EQUAL_SLICE_UB 204
#define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx)
@@ -146,7 +146,7 @@
/* BUS_CFG */
msm_camera_io_w(0x00000001, vfe_dev->vfe_base + 0x3C);
msm_camera_io_w(0x01000025, vfe_dev->vfe_base + 0x1C);
- msm_camera_io_w_mb(0x1DFFFFFF, vfe_dev->vfe_base + 0x20);
+ msm_camera_io_w_mb(0x1CFFFFFF, vfe_dev->vfe_base + 0x20);
msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24);
msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28);
}
@@ -161,8 +161,6 @@
static void msm_vfe32_process_halt_irq(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1)
{
- if (irq_status1 & BIT(24))
- complete(&vfe_dev->halt_complete);
}
static void msm_vfe32_process_camif_irq(struct vfe_device *vfe_dev,
@@ -304,7 +302,7 @@
*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
*irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x30);
msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x24);
- msm_camera_io_w(*irq_status1, vfe_dev->vfe_base + 0x28);
+ msm_camera_io_w_mb(*irq_status1, vfe_dev->vfe_base + 0x28);
msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x18);
if (*irq_status1 & BIT(0))
@@ -750,14 +748,20 @@
static long msm_vfe32_axi_halt(struct vfe_device *vfe_dev)
{
uint32_t halt_mask;
+ uint32_t axi_busy_flag = true;
+
+ msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8);
+ while (axi_busy_flag) {
+ if (msm_camera_io_r(
+ vfe_dev->vfe_base + 0x1DC) & 0x1)
+ axi_busy_flag = false;
+ }
+ msm_camera_io_w_mb(0, vfe_dev->vfe_base + 0x1D8);
halt_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x20);
- halt_mask |= BIT(24);
+ halt_mask &= 0xFEFFFFFF;
+ /* Disable AXI IRQ */
msm_camera_io_w_mb(halt_mask, vfe_dev->vfe_base + 0x20);
- init_completion(&vfe_dev->halt_complete);
- /*TD: Need to fix crashes with this*/
- /*msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8);*/
- return wait_for_completion_interruptible_timeout(
- &vfe_dev->halt_complete, msecs_to_jiffies(500));
+ return 0;
}
static uint32_t msm_vfe32_get_wm_mask(
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 908d3c6..3806213 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -527,9 +527,11 @@
int i;
uint32_t *data_ptr = cfg_data +
reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
- for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++)
+ for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++) {
*data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base +
- reg_cfg_cmd->u.rw_info.reg_offset++);
+ reg_cfg_cmd->u.rw_info.reg_offset);
+ reg_cfg_cmd->u.rw_info.reg_offset += 4;
+ }
break;
}
}
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index b85527d..a4eb274 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -34,8 +34,8 @@
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/msmb_camera.h>
-#include <media/msmb_pproc.h>
#include <media/msmb_generic_buf_mgr.h>
+#include <media/msmb_pproc.h>
#include "msm_cpp.h"
#include "msm_isp_util.h"
#include "msm_camera_io_util.h"
@@ -1036,7 +1036,7 @@
}
#endif
-void msm_cpp_do_timeout_work(struct work_struct *work)
+static void msm_cpp_do_timeout_work(struct work_struct *work)
{
int ret;
uint32_t i = 0;
@@ -1046,6 +1046,11 @@
pr_err("cpp_timer_callback called idx:%d. (jiffies=%lu)\n",
del_timer_idx, jiffies);
+ if (!work || !this_frame) {
+ pr_err("Invalid work:%p, this_frame:%p, del_idx:%d\n",
+ work, this_frame, del_timer_idx);
+ return;
+ }
pr_err("fatal: cpp_timer expired for identity=0x%x, frame_id=%03d",
this_frame->identity, this_frame->frame_id);
cpp_timers[del_timer_idx].used = 0;
@@ -1304,7 +1309,8 @@
(cpp_frame_msg[12] & 0x3FF);
fw_version_1_2_x = 0;
- if (cpp_dev->hw_info.cpp_hw_version == 0x10010000)
+ if ((cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_1_1_0) ||
+ (cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_1_1_1))
fw_version_1_2_x = 2;
for (i = 0; i < num_stripes; i++) {
@@ -1465,6 +1471,13 @@
return -EINVAL;
}
+ if (u_stream_buff_info->num_buffs == 0) {
+ pr_err("%s:%d: Invalid number of buffers\n", __func__,
+ __LINE__);
+ kfree(u_stream_buff_info);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
k_stream_buff_info.num_buffs = u_stream_buff_info->num_buffs;
k_stream_buff_info.identity = u_stream_buff_info->identity;
@@ -1478,7 +1491,7 @@
k_stream_buff_info.buffer_info =
kzalloc(k_stream_buff_info.num_buffs *
sizeof(struct msm_cpp_buffer_info_t), GFP_KERNEL);
- if (!k_stream_buff_info.buffer_info) {
+ if (ZERO_OR_NULL_PTR(k_stream_buff_info.buffer_info)) {
pr_err("%s:%d: malloc error\n", __func__, __LINE__);
kfree(u_stream_buff_info);
mutex_unlock(&cpp_dev->mutex);
@@ -1563,20 +1576,26 @@
rc = 0;
break;
}
- case VIDIOC_MSM_CPP_SEND_BUF_DONE: {
- struct msm_buf_mngr_info buff_mgr_info;
- rc = (copy_from_user(&buff_mgr_info,
+ case VIDIOC_MSM_CPP_QUEUE_BUF: {
+ struct msm_pproc_queue_buf_info queue_buf_info;
+ rc = (copy_from_user(&queue_buf_info,
(void __user *)ioctl_ptr->ioctl_ptr,
- sizeof(struct msm_buf_mngr_info)) ?
+ sizeof(struct msm_pproc_queue_buf_info)) ?
-EFAULT : 0);
if (rc) {
ERR_COPY_FROM_USER();
break;
}
- rc = msm_cpp_buffer_ops(cpp_dev,
- VIDIOC_MSM_BUF_MNGR_BUF_DONE,
- &buff_mgr_info);
+ if (queue_buf_info.is_buf_dirty) {
+ rc = msm_cpp_buffer_ops(cpp_dev,
+ VIDIOC_MSM_BUF_MNGR_PUT_BUF,
+ &queue_buf_info.buff_mgr_info);
+ } else {
+ rc = msm_cpp_buffer_ops(cpp_dev,
+ VIDIOC_MSM_BUF_MNGR_BUF_DONE,
+ &queue_buf_info.buff_mgr_info);
+ }
if (rc < 0) {
pr_err("error in buf done\n");
rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index 0a70d37..796bede 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -21,6 +21,14 @@
#include <media/v4l2-subdev.h>
#include "msm_sd.h"
+/* hw version info:
+ 31:28 Major version
+ 27:16 Minor version
+ 15:0 Revision bits
+**/
+#define CPP_HW_VERSION_1_1_0 0x10010000
+#define CPP_HW_VERSION_1_1_1 0x10010001
+
#define MAX_ACTIVE_CPP_INSTANCE 8
#define MAX_CPP_PROCESSING_FRAME 2
#define MAX_CPP_V4l2_EVENTS 30
diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
index d53d766..d302131 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
@@ -25,8 +25,8 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-subdev.h>
#include <media/media-entity.h>
-#include <media/msmb_pproc.h>
#include <media/msmb_generic_buf_mgr.h>
+#include <media/msmb_pproc.h>
#include "msm_vpe.h"
#include "msm_camera_io_util.h"
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index 18ac623..bd1b10b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -9,9 +9,11 @@
obj-$(CONFIG_IMX135) += imx135.o
obj-$(CONFIG_OV8825) += ov8825.o
obj-$(CONFIG_s5k4e1) += s5k4e1.o
+obj-$(CONFIG_OV12830) += ov12830.o
obj-$(CONFIG_OV2720) += ov2720.o
obj-$(CONFIG_OV9724) += ov9724.o
obj-$(CONFIG_HI256) += hi256.o
+obj-$(CONFIG_OV5648) += ov5648.o
obj-$(CONFIG_MT9M114) += mt9m114.o
obj-$(CONFIG_SP1628) += sp1628.o
obj-$(CONFIG_GC0339) += gc0339.o
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 a27ca99..4fa3085 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
@@ -46,30 +46,44 @@
static void msm_cci_set_clk_param(struct cci_device *cci_dev)
{
- struct msm_cci_clk_params_t *clk_params = &cci_dev->cci_clk_params;
+ struct msm_cci_clk_params_t *clk_params = NULL;
+ uint8_t count = 0;
- msm_camera_io_w(clk_params->hw_thigh << 16 | clk_params->hw_tlow,
- cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR);
- msm_camera_io_w(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta,
- cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR);
- msm_camera_io_w(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta,
- cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR);
- msm_camera_io_w(clk_params->hw_tbuf,
- cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR);
- msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
- clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
- cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR);
- msm_camera_io_w(clk_params->hw_thigh << 16 | clk_params->hw_tlow,
- cci_dev->base + CCI_I2C_M1_SCL_CTL_ADDR);
- msm_camera_io_w(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta,
- cci_dev->base + CCI_I2C_M1_SDA_CTL_0_ADDR);
- msm_camera_io_w(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta,
- cci_dev->base + CCI_I2C_M1_SDA_CTL_1_ADDR);
- msm_camera_io_w(clk_params->hw_tbuf,
- cci_dev->base + CCI_I2C_M1_SDA_CTL_2_ADDR);
- msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
- clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
- cci_dev->base + CCI_I2C_M1_MISC_CTL_ADDR);
+ for (count = 0; count < MASTER_MAX; count++) {
+ if (MASTER_0 == count) {
+ clk_params = &cci_dev->cci_clk_params[count];
+ msm_camera_io_w(clk_params->hw_thigh << 16 |
+ clk_params->hw_tlow,
+ cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR);
+ msm_camera_io_w(clk_params->hw_tsu_sto << 16 |
+ clk_params->hw_tsu_sta,
+ cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR);
+ msm_camera_io_w(clk_params->hw_thd_dat << 16 |
+ clk_params->hw_thd_sta,
+ cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR);
+ msm_camera_io_w(clk_params->hw_tbuf,
+ cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR);
+ msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
+ clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
+ cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR);
+ } else if (MASTER_1 == count) {
+ clk_params = &cci_dev->cci_clk_params[count];
+ msm_camera_io_w(clk_params->hw_thigh << 16 |
+ clk_params->hw_tlow,
+ cci_dev->base + CCI_I2C_M1_SCL_CTL_ADDR);
+ msm_camera_io_w(clk_params->hw_tsu_sto << 16 |
+ clk_params->hw_tsu_sta,
+ cci_dev->base + CCI_I2C_M1_SDA_CTL_0_ADDR);
+ msm_camera_io_w(clk_params->hw_thd_dat << 16 |
+ clk_params->hw_thd_sta,
+ cci_dev->base + CCI_I2C_M1_SDA_CTL_1_ADDR);
+ msm_camera_io_w(clk_params->hw_tbuf,
+ cci_dev->base + CCI_I2C_M1_SDA_CTL_2_ADDR);
+ msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
+ clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
+ cci_dev->base + CCI_I2C_M1_MISC_CTL_ADDR);
+ }
+ }
return;
}
@@ -910,58 +924,96 @@
{
int32_t rc = 0;
uint32_t val = 0;
+ uint8_t count = 0;
struct device_node *of_node = cci_dev->pdev->dev.of_node;
+ struct device_node *src_node = NULL;
- rc = of_property_read_u32(of_node, "qcom,hw-thigh", &val);
- CDBG("%s qcom,hw-thigh %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_thigh = val;
+ for (count = 0; count < MASTER_MAX; count++) {
- rc = of_property_read_u32(of_node, "qcom,hw-tlow", &val);
- CDBG("%s qcom,hw-tlow %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_tlow = val;
+ if (MASTER_0 == count)
+ src_node = of_find_node_by_name(of_node,
+ "qcom,cci-master0");
+ else if (MASTER_1 == count)
+ src_node = of_find_node_by_name(of_node,
+ "qcom,cci-master1");
+ else
+ return;
- rc = of_property_read_u32(of_node, "qcom,hw-tsu-sto", &val);
- CDBG("%s qcom,hw-tsu-sto %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_tsu_sto = val;
+ rc = of_property_read_u32(src_node, "qcom,hw-thigh", &val);
+ CDBG("%s qcom,hw-thigh %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_thigh = val;
+ else
+ cci_dev->cci_clk_params[count].hw_thigh = 78;
- rc = of_property_read_u32(of_node, "qcom,hw-tsu-sta", &val);
- CDBG("%s qcom,hw-tsu-sta %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_tsu_sta = val;
+ rc = of_property_read_u32(src_node, "qcom,hw-tlow", &val);
+ CDBG("%s qcom,hw-tlow %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_tlow = val;
+ else
+ cci_dev->cci_clk_params[count].hw_tlow = 114;
- rc = of_property_read_u32(of_node, "qcom,hw-thd-dat", &val);
- CDBG("%s qcom,hw-thd-dat %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_thd_dat = val;
+ rc = of_property_read_u32(src_node, "qcom,hw-tsu-sto", &val);
+ CDBG("%s qcom,hw-tsu-sto %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_tsu_sto = val;
+ else
+ cci_dev->cci_clk_params[count].hw_tsu_sto = 28;
- rc = of_property_read_u32(of_node, "qcom,hw-thd-sta", &val);
- CDBG("%s qcom,hwthd-sta %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_thd_sta = val;
+ rc = of_property_read_u32(src_node, "qcom,hw-tsu-sta", &val);
+ CDBG("%s qcom,hw-tsu-sta %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_tsu_sta = val;
+ else
+ cci_dev->cci_clk_params[count].hw_tsu_sta = 28;
- rc = of_property_read_u32(of_node, "qcom,hw-tbuf", &val);
- CDBG("%s qcom,hw-tbuf %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_tbuf = val;
+ rc = of_property_read_u32(src_node, "qcom,hw-thd-dat", &val);
+ CDBG("%s qcom,hw-thd-dat %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_thd_dat = val;
+ else
+ cci_dev->cci_clk_params[count].hw_thd_dat = 10;
- rc = of_property_read_u32(of_node, "qcom,hw-scl-stretch-en", &val);
- CDBG("%s qcom,hw-scl-stretch-en %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_scl_stretch_en = val;
+ rc = of_property_read_u32(src_node, "qcom,hw-thd-sta", &val);
+ CDBG("%s qcom,hwthd-sta %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_thd_sta = val;
+ else
+ cci_dev->cci_clk_params[count].hw_thd_sta = 77;
- rc = of_property_read_u32(of_node, "qcom,hw-trdhld", &val);
- CDBG("%s qcom,hw-trdhld %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_trdhld = val;
+ rc = of_property_read_u32(src_node, "qcom,hw-tbuf", &val);
+ CDBG("%s qcom,hw-tbuf %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_tbuf = val;
+ else
+ cci_dev->cci_clk_params[count].hw_tbuf = 118;
- rc = of_property_read_u32(of_node, "qcom,hw-tsp", &val);
- CDBG("%s qcom,hw-tsp %d, rc %d\n", __func__, val, rc);
- if (!rc)
- cci_dev->cci_clk_params.hw_tsp = val;
+ rc = of_property_read_u32(src_node,
+ "qcom,hw-scl-stretch-en", &val);
+ CDBG("%s qcom,hw-scl-stretch-en %d, rc %d\n",
+ __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_scl_stretch_en = val;
+ else
+ cci_dev->cci_clk_params[count].hw_scl_stretch_en = 0;
+ rc = of_property_read_u32(src_node, "qcom,hw-trdhld", &val);
+ CDBG("%s qcom,hw-trdhld %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_trdhld = val;
+ else
+ cci_dev->cci_clk_params[count].hw_trdhld = 6;
+
+ rc = of_property_read_u32(src_node, "qcom,hw-tsp", &val);
+ CDBG("%s qcom,hw-tsp %d, rc %d\n", __func__, val, rc);
+ if (!rc)
+ cci_dev->cci_clk_params[count].hw_tsp = val;
+ else
+ cci_dev->cci_clk_params[count].hw_tsp = 1;
+
+ of_node_put(src_node);
+ src_node = NULL;
+ }
return;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
index f9e40f1..16edaae 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
@@ -139,7 +139,7 @@
struct msm_camera_cci_i2c_queue_info
cci_i2c_queue_info[NUM_MASTERS][NUM_QUEUES];
struct msm_camera_cci_master_info cci_master_info[NUM_MASTERS];
- struct msm_cci_clk_params_t cci_clk_params;
+ struct msm_cci_clk_params_t cci_clk_params[MASTER_MAX];
struct gpio *cci_gpio_tbl;
uint8_t cci_gpio_tbl_size;
};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov12830.c b/drivers/media/platform/msm/camera_v2/sensor/ov12830.c
new file mode 100644
index 0000000..593892e
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov12830.c
@@ -0,0 +1,197 @@
+/* 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 "msm_sensor.h"
+#define OV12830_SENSOR_NAME "ov12830"
+DEFINE_MSM_MUTEX(ov12830_mut);
+
+static struct msm_sensor_ctrl_t ov12830_s_ctrl;
+
+static struct msm_sensor_power_setting ov12830_power_setting[] = {
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VIO,
+ .config_val = 0,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VANA,
+ .config_val = 0,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_VDIG,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_VDIG,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VAF,
+ .config_val = 0,
+ .delay = 15,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 15,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_AF_PWDM,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_AF_PWDM,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_CLK,
+ .seq_val = SENSOR_CAM_MCLK,
+ .config_val = 24000000,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_I2C_MUX,
+ .seq_val = 0,
+ .config_val = 0,
+ .delay = 0,
+ },
+};
+
+static struct v4l2_subdev_info ov12830_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+};
+
+static const struct i2c_device_id ov12830_i2c_id[] = {
+ {OV12830_SENSOR_NAME,
+ (kernel_ulong_t)&ov12830_s_ctrl},
+ { }
+};
+
+static int msm_ov12830_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return msm_sensor_i2c_probe(client, id, &ov12830_s_ctrl);
+}
+
+static struct i2c_driver ov12830_i2c_driver = {
+ .id_table = ov12830_i2c_id,
+ .probe = msm_ov12830_i2c_probe,
+ .driver = {
+ .name = OV12830_SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client ov12830_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id ov12830_dt_match[] = {
+ {.compatible = "qcom,ov12830",
+ .data = &ov12830_s_ctrl},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, ov12830_dt_match);
+
+static struct platform_driver ov12830_platform_driver = {
+ .driver = {
+ .name = "qcom,ov12830",
+ .owner = THIS_MODULE,
+ .of_match_table = ov12830_dt_match,
+ },
+};
+
+static int32_t ov12830_platform_probe
+ (struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ const struct of_device_id *match;
+ match = of_match_device(ov12830_dt_match, &pdev->dev);
+ rc = msm_sensor_platform_probe(pdev, match->data);
+ return rc;
+}
+
+static int __init ov12830_init_module(void)
+{
+ int32_t rc = 0;
+ pr_debug("%s:%d\n", __func__, __LINE__);
+ rc = platform_driver_probe(&ov12830_platform_driver,
+ ov12830_platform_probe);
+ if (!rc)
+ return rc;
+ pr_debug("%s:%d rc %d\n", __func__, __LINE__, rc);
+ return i2c_add_driver(&ov12830_i2c_driver);
+}
+
+static void __exit ov12830_exit_module(void)
+{
+ pr_info("%s:%d\n", __func__, __LINE__);
+ if (ov12830_s_ctrl.pdev) {
+ msm_sensor_free_sensor_data(&ov12830_s_ctrl);
+ platform_driver_unregister
+ (&ov12830_platform_driver);
+ } else {
+ i2c_del_driver(&ov12830_i2c_driver);
+ }
+}
+
+static struct msm_sensor_ctrl_t ov12830_s_ctrl = {
+ .sensor_i2c_client = &ov12830_sensor_i2c_client,
+ .power_setting_array.power_setting = ov12830_power_setting,
+ .power_setting_array.size =
+ ARRAY_SIZE(ov12830_power_setting),
+ .msm_sensor_mutex = &ov12830_mut,
+ .sensor_v4l2_subdev_info = ov12830_subdev_info,
+ .sensor_v4l2_subdev_info_size =
+ ARRAY_SIZE(ov12830_subdev_info),
+};
+
+module_init(ov12830_init_module);
+module_exit(ov12830_exit_module);
+MODULE_DESCRIPTION("ov12830");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov5648.c b/drivers/media/platform/msm/camera_v2/sensor/ov5648.c
new file mode 100644
index 0000000..7877fcb
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov5648.c
@@ -0,0 +1,179 @@
+/* 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 "msm_sensor.h"
+
+#define OV5648_SENSOR_NAME "ov5648"
+DEFINE_MSM_MUTEX(ov5648_mut);
+
+static struct msm_sensor_ctrl_t ov5648_s_ctrl;
+
+static struct msm_sensor_power_setting ov5648_power_setting[] = {
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VIO,
+ .config_val = 0,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_VDIG,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 10,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_VDIG,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 10,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VANA,
+ .config_val = 0,
+ .delay = 10,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 30,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 30,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 30,
+ },
+ {
+ .seq_type = SENSOR_CLK,
+ .seq_val = SENSOR_CAM_MCLK,
+ .config_val = 24000000,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_I2C_MUX,
+ .seq_val = 0,
+ .config_val = 0,
+ .delay = 0,
+ },
+};
+
+static struct v4l2_subdev_info ov5648_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+};
+
+static const struct i2c_device_id ov5648_i2c_id[] = {
+ {OV5648_SENSOR_NAME,
+ (kernel_ulong_t)&ov5648_s_ctrl},
+ { }
+};
+
+static int32_t msm_ov5648_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return msm_sensor_i2c_probe(client, id, &ov5648_s_ctrl);
+}
+
+static struct i2c_driver ov5648_i2c_driver = {
+ .id_table = ov5648_i2c_id,
+ .probe = msm_ov5648_i2c_probe,
+ .driver = {
+ .name = OV5648_SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client ov5648_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static struct msm_sensor_ctrl_t ov5648_s_ctrl = {
+ .sensor_i2c_client = &ov5648_sensor_i2c_client,
+ .power_setting_array.power_setting = ov5648_power_setting,
+ .power_setting_array.size =
+ ARRAY_SIZE(ov5648_power_setting),
+ .msm_sensor_mutex = &ov5648_mut,
+ .sensor_v4l2_subdev_info = ov5648_subdev_info,
+ .sensor_v4l2_subdev_info_size =
+ ARRAY_SIZE(ov5648_subdev_info),
+};
+
+static const struct of_device_id ov5648_dt_match[] = {
+ {
+ .compatible = "qcom,ov5648",
+ .data = &ov5648_s_ctrl
+ },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, ov5648_dt_match);
+
+static struct platform_driver ov5648_platform_driver = {
+ .driver = {
+ .name = "qcom,ov5648",
+ .owner = THIS_MODULE,
+ .of_match_table = ov5648_dt_match,
+ },
+};
+
+static int32_t ov5648_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ const struct of_device_id *match;
+
+ match = of_match_device(ov5648_dt_match, &pdev->dev);
+ rc = msm_sensor_platform_probe(pdev, match->data);
+ return rc;
+}
+
+static int __init ov5648_init_module(void)
+{
+ int32_t rc = 0;
+
+ rc = platform_driver_probe(&ov5648_platform_driver,
+ ov5648_platform_probe);
+ if (!rc)
+ return rc;
+ return i2c_add_driver(&ov5648_i2c_driver);
+}
+
+static void __exit ov5648_exit_module(void)
+{
+ if (ov5648_s_ctrl.pdev) {
+ msm_sensor_free_sensor_data(&ov5648_s_ctrl);
+ platform_driver_unregister(&ov5648_platform_driver);
+ } else
+ i2c_del_driver(&ov5648_i2c_driver);
+ return;
+}
+
+module_init(ov5648_init_module);
+module_exit(ov5648_exit_module);
+MODULE_DESCRIPTION("ov5648");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index a3d6dd8..e263911 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -466,6 +466,12 @@
&mpq_demux->decoder_ts_errors);
debugfs_create_u32(
+ "decoder_cc_errors",
+ S_IRUGO | S_IWUSR | S_IWGRP,
+ mpq_demux->demux.dmx.debugfs_demux_dir,
+ &mpq_demux->decoder_cc_errors);
+
+ debugfs_create_u32(
"sdmx_process_count",
S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
@@ -1457,6 +1463,7 @@
mpq_demux->decoder_out_interval_sum = 0;
mpq_demux->decoder_out_interval_max = 0;
mpq_demux->decoder_ts_errors = 0;
+ mpq_demux->decoder_cc_errors = 0;
return 0;
@@ -2346,6 +2353,14 @@
meta_data.info.framing.pattern_type =
feed_data->last_framing_match_type;
meta_data.info.framing.stc = feed_data->last_framing_match_stc;
+ meta_data.info.framing.continuity_error_counter =
+ feed_data->continuity_errs;
+ meta_data.info.framing.transport_error_indicator_counter =
+ feed_data->tei_errs;
+ meta_data.info.framing.ts_dropped_bytes =
+ feed_data->ts_dropped_bytes;
+ meta_data.info.framing.ts_packets_num =
+ feed_data->ts_packets_num;
mpq_streambuffer_get_buffer_handle(stream_buffer,
0, /* current write buffer handle */
@@ -2644,6 +2659,7 @@
mpq_dmx_check_continuity(feed_data,
ts_header->continuity_counter,
discontinuity_indicator);
+ mpq_demux->decoder_cc_errors += feed_data->continuity_errs;
/* Need to back-up the PTS information of the very first frame */
if (feed_data->first_pts_dts_copy) {
@@ -2788,6 +2804,15 @@
feed_data->last_framing_match_type;
meta_data.info.framing.stc =
feed_data->last_framing_match_stc;
+ meta_data.info.framing.continuity_error_counter =
+ feed_data->continuity_errs;
+ meta_data.info.framing.
+ transport_error_indicator_counter =
+ feed_data->tei_errs;
+ meta_data.info.framing.ts_dropped_bytes =
+ feed_data->ts_dropped_bytes;
+ meta_data.info.framing.ts_packets_num =
+ feed_data->ts_packets_num;
mpq_streambuffer_get_buffer_handle(
stream_buffer,
@@ -3052,6 +3077,7 @@
mpq_dmx_check_continuity(feed_data,
ts_header->continuity_counter,
discontinuity_indicator);
+ mpq_demux->decoder_cc_errors += feed_data->continuity_errs;
if (mpq_streambuffer_data_write(
stream_buffer,
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index f095e00..adc4261 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -388,6 +388,8 @@
* successive video frames output, exposed in debugfs.
* @decoder_ts_errors: Counter for number of decoder packets with TEI bit
* set, exposed in debugfs.
+ * @decoder_cc_errors: Counter for number of decoder packets with continuity
+ * counter errors, exposed in debugfs.
* @sdmx_process_count: Total number of times sdmx_process is called.
* @sdmx_process_time_sum: Total time sdmx_process takes.
* @sdmx_process_time_average: Average time sdmx_process takes.
@@ -445,6 +447,7 @@
u32 decoder_out_interval_average;
u32 decoder_out_interval_max;
u32 decoder_ts_errors;
+ u32 decoder_cc_errors;
u32 sdmx_process_count;
u32 sdmx_process_time_sum;
u32 sdmx_process_time_average;
diff --git a/drivers/media/platform/msm/dvb/include/mpq_adapter.h b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
index a2ade18..86f36a4 100644
--- a/drivers/media/platform/msm/dvb/include/mpq_adapter.h
+++ b/drivers/media/platform/msm/dvb/include/mpq_adapter.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
@@ -67,6 +67,24 @@
/** STC value attached to first TS packet holding the pattern */
u64 stc;
+
+ /*
+ * Number of TS packets with Transport Error Indicator (TEI)
+ * found while constructing the frame.
+ */
+ __u32 transport_error_indicator_counter;
+
+ /* Number of continuity errors found while constructing the frame */
+ __u32 continuity_error_counter;
+
+ /*
+ * Number of dropped bytes due to insufficient buffer space,
+ * since last reported frame.
+ */
+ __u32 ts_dropped_bytes;
+
+ /* Total number of TS packets holding the frame */
+ __u32 ts_packets_num;
};
struct dmx_pes_packet_info {
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 44105ad..a63ee61 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1230,7 +1230,7 @@
hfi_msg_sys_session_abort_done_packet*) msg_hdr);
break;
default:
- dprintk(VIDC_ERR, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
+ dprintk(VIDC_DBG, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
break;
}
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 96d95989..cf96ca2 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -387,7 +387,6 @@
goto exit;
}
for (i = 0; i < b->length; ++i) {
- buffer_type = HAL_BUFFER_OUTPUT;
if (EXTRADATA_IDX(b->length) &&
(i == EXTRADATA_IDX(b->length)) &&
!b->m.planes[i].length) {
@@ -404,8 +403,20 @@
kfree(binfo);
goto exit;
}
- if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
- buffer_type = HAL_BUFFER_INPUT;
+
+ if (vidc_inst->session_type == MSM_VIDC_DECODER) {
+ if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ buffer_type = HAL_BUFFER_INPUT;
+ else /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
+ buffer_type = HAL_BUFFER_OUTPUT;
+ } else {
+ /* FIXME in the future. See comment in msm_comm_get_\
+ * domain_partition. Same problem here. */
+ if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ buffer_type = HAL_BUFFER_OUTPUT;
+ else /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
+ buffer_type = HAL_BUFFER_INPUT;
+ }
temp = get_same_fd_buffer(&v4l2_inst->registered_bufs,
b->m.planes[i].reserved[0], &plane);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 1c43f1e..b6d031a 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -477,14 +477,14 @@
if (rc) {
dprintk(VIDC_ERR,
"Failed to initialize vb2 queue on capture port\n");
- goto fail_init;
+ goto fail_bufq_capture;
}
rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
session_type);
if (rc) {
dprintk(VIDC_ERR,
"Failed to initialize vb2 queue on capture port\n");
- goto fail_init;
+ goto fail_bufq_output;
}
rc = msm_comm_try_state(inst, MSM_VIDC_CORE_INIT);
if (rc) {
@@ -502,6 +502,14 @@
mutex_unlock(&core->lock);
return inst;
fail_init:
+ vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
+fail_bufq_output:
+ vb2_queue_release(&inst->bufq[CAPTURE_PORT].vb2_bufq);
+fail_bufq_capture:
+ if (session_type == MSM_VIDC_DECODER)
+ msm_vdec_ctrl_deinit(inst);
+ else if (session_type == MSM_VIDC_ENCODER)
+ msm_venc_ctrl_deinit(inst);
msm_smem_delete_client(inst->mem_client);
fail_mem_client:
kfree(inst);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 5f0ec4e..57b98dc 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -805,6 +805,8 @@
vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
vb->v4l2_buf.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME)
+ vb->v4l2_buf.flags |= V4L2_QCOM_BUF_DROP_FRAME;
switch (fill_buf_done->picture_type) {
case HAL_PICTURE_IDR:
vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
@@ -1942,6 +1944,12 @@
"Received CODECCONFIG on output cap\n");
}
if (vb->v4l2_buf.flags &
+ V4L2_QCOM_BUF_FLAG_DECODEONLY) {
+ frame_data.flags |= HAL_BUFFERFLAG_DECODEONLY;
+ dprintk(VIDC_DBG,
+ "Received DECODEONLY on output cap\n");
+ }
+ if (vb->v4l2_buf.flags &
V4L2_QCOM_BUF_TIMESTAMP_INVALID)
frame_data.timestamp = LLONG_MAX;
dprintk(VIDC_DBG,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index ac6cb02..874738b 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -39,6 +39,8 @@
#define HFI_BUFFERFLAG_EOSEQ 0x00200000
#define HFI_BUFFERFLAG_DISCONTINUITY 0x80000000
#define HFI_BUFFERFLAG_TEI 0x40000000
+#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000
+
#define HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING \
(HFI_OX_BASE + 0x1001)
@@ -407,7 +409,7 @@
u32 input_tag;
u8 *packet_buffer;
u8 *extra_data_buffer;
- u32 rgData[0];
+ u32 rgData[1];
};
struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet {
@@ -426,7 +428,7 @@
u32 input_tag;
u8 *packet_buffer;
u8 *extra_data_buffer;
- u32 rgData[0];
+ u32 rgData[1];
};
struct hfi_cmd_session_empty_buffer_uncompressed_plane1_packet {
@@ -435,7 +437,7 @@
u32 filled_len;
u32 offset;
u8 *packet_buffer2;
- u32 rgData[0];
+ u32 rgData[1];
};
struct hfi_cmd_session_empty_buffer_uncompressed_plane2_packet {
@@ -444,7 +446,7 @@
u32 filled_len;
u32 offset;
u8 *packet_buffer3;
- u32 rgData[0];
+ u32 rgData[1];
};
struct hfi_cmd_session_fill_buffer_packet {
@@ -458,7 +460,7 @@
u32 output_tag;
u8 *packet_buffer;
u8 *extra_data_buffer;
- u32 rgData[0];
+ u32 rgData[1];
};
struct hfi_cmd_session_flush_packet {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 288b386..5c22552 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -44,6 +44,8 @@
#define HAL_BUFFERFLAG_READONLY 0x00000200
#define HAL_BUFFERFLAG_ENDOFSUBFRAME 0x00000400
#define HAL_BUFFERFLAG_EOSEQ 0x00200000
+#define HAL_BUFFERFLAG_DROP_FRAME 0x20000000
+
#define HAL_DEBUG_MSG_LOW 0x00000001
#define HAL_DEBUG_MSG_MEDIUM 0x00000002
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 8121471..9cd199b 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -296,24 +296,13 @@
static long set_default_properties(struct venc_inst *inst)
{
struct v4l2_control ctrl = {0};
- int rc;
/* Set the IDR period as 1. The venus core doesn't give
* the sps/pps for I-frames, only IDR. */
ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD;
ctrl.value = 1;
- rc = msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
- if (rc)
- WFD_MSG_WARN("Failed to set IDR period\n");
- /* Set the default rc mode to VBR/VFR, client can change later */
- ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL;
- ctrl.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR;
- rc = msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
- if (rc)
- WFD_MSG_WARN("Failed to set rc mode\n");
-
- return 0;
+ return msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
}
static int subscribe_events(struct venc_inst *inst)
diff --git a/drivers/media/platform/msm/wfd/vsg-subdev.c b/drivers/media/platform/msm/wfd/vsg-subdev.c
index e0a46cc..6ffaffa 100644
--- a/drivers/media/platform/msm/wfd/vsg-subdev.c
+++ b/drivers/media/platform/msm/wfd/vsg-subdev.c
@@ -462,8 +462,16 @@
static long vsg_return_ip_buffer(struct v4l2_subdev *sd, void *arg)
{
struct vsg_context *context = NULL;
- struct vsg_buf_info *buf_info = NULL, *last_buffer = NULL,
- *expected_buffer = NULL;
+ struct vsg_buf_info *buf_info = NULL, *temp = NULL,
+ /* last buffer sent for encoding */
+ *last_buffer = NULL,
+ /* buffer we expected to get back, ideally ==
+ * last_buffer, but might not be if sequence is
+ * encode, encode, return */
+ *expected_buffer = NULL,
+ /* buffer that we've sent for encoding at some point */
+ *known_buffer = NULL;
+ bool is_last_buffer = false;
int rc = 0;
if (!arg || !sd) {
@@ -477,41 +485,47 @@
buf_info = (struct vsg_buf_info *)arg;
last_buffer = context->last_buffer;
+ WFD_MSG_DBG("Return frame with paddr %p\n",
+ (void *)buf_info->mdp_buf_info.paddr);
+
if (!list_empty(&context->busy_queue.node)) {
expected_buffer = list_first_entry(&context->busy_queue.node,
struct vsg_buf_info, node);
}
- WFD_MSG_DBG("Return frame with paddr %p\n",
- (void *)buf_info->mdp_buf_info.paddr);
-
- if (!expected_buffer) {
- WFD_MSG_ERR("Unexpectedly received buffer from enc with "
- "paddr %p\n", (void *)buf_info->mdp_buf_info.paddr);
- goto return_ip_buf_bad_buf;
+ list_for_each_entry(temp, &context->busy_queue.node, node) {
+ if (mdp_buf_info_equals(&temp->mdp_buf_info,
+ &buf_info->mdp_buf_info)) {
+ known_buffer = temp;
+ break;
+ }
}
- expected_buffer->flags &= ~VSG_BUF_BEING_ENCODED;
- if (mdp_buf_info_equals(&expected_buffer->mdp_buf_info,
- &buf_info->mdp_buf_info)) {
- bool is_same_buffer = context->last_buffer &&
- mdp_buf_info_equals(
- &context->last_buffer->mdp_buf_info,
- &expected_buffer->mdp_buf_info);
-
- list_del(&expected_buffer->node);
- if (!is_same_buffer &&
- !(expected_buffer->flags & VSG_NEVER_RELEASE)) {
- vsg_release_input_buffer(context, expected_buffer);
- kfree(expected_buffer);
- }
- } else {
- WFD_MSG_ERR("Returned buffer %p is not latest buffer, "
- "expected %p\n",
- (void *)buf_info->mdp_buf_info.paddr,
- (void *)expected_buffer->mdp_buf_info.paddr);
- rc = -EINVAL;
+ if (!expected_buffer || !known_buffer) {
+ WFD_MSG_ERR("Unexpectedly received buffer from enc with "
+ "paddr %p\n", (void *)buf_info->mdp_buf_info.paddr);
+ rc = -EBADHANDLE;
goto return_ip_buf_bad_buf;
+ } else if (known_buffer != expected_buffer) {
+ /* Buffers can come back out of order if encoder decides to drop
+ * a frame */
+ WFD_MSG_DBG(
+ "Got a buffer (%p) out of order. Preferred to get %p\n",
+ (void *)known_buffer->mdp_buf_info.paddr,
+ (void *)expected_buffer->mdp_buf_info.paddr);
+ }
+
+ known_buffer->flags &= ~VSG_BUF_BEING_ENCODED;
+ is_last_buffer = context->last_buffer &&
+ mdp_buf_info_equals(
+ &context->last_buffer->mdp_buf_info,
+ &known_buffer->mdp_buf_info);
+
+ list_del(&known_buffer->node);
+ if (!is_last_buffer &&
+ !(known_buffer->flags & VSG_NEVER_RELEASE)) {
+ vsg_release_input_buffer(context, known_buffer);
+ kfree(known_buffer);
}
return_ip_buf_bad_buf:
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 50a1ea1..7934234 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -2416,9 +2416,15 @@
ev.tune_freq = *((int *) &skb->data[0]);
ev.pi_code = *((__le16 *) &skb->data[PI_CODE_OFFSET]);
ev.af_size = skb->data[AF_SIZE_OFFSET];
- memcpy(&ev.af_list[0], &skb->data[AF_LIST_OFFSET], ev.af_size);
+ if (ev.af_size > AF_LIST_MAX) {
+ FMDERR("AF list size received more than available size");
+ return;
+ }
+ memcpy(&ev.af_list[0], &skb->data[AF_LIST_OFFSET],
+ ev.af_size * sizeof(int));
iris_q_event(radio, IRIS_EVT_NEW_AF_LIST);
- iris_q_evt_data(radio, (char *)&ev, sizeof(ev), IRIS_BUF_AF_LIST);
+ iris_q_evt_data(radio, (char *)&ev, (7 + ev.af_size * sizeof(int)),
+ IRIS_BUF_AF_LIST);
}
static void hci_ev_rds_lock_status(struct radio_hci_dev *hdev,
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index ea7032b..e0a99e2 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -1932,6 +1932,7 @@
if (bahama_present == -ENODEV)
return -ENODEV;
+ marimba_set_fm_status(radio->marimba, true);
if (bahama_present)
radio->marimba->mod_id = SLAVE_ID_BAHAMA;
else
@@ -2066,7 +2067,6 @@
radio->handle_irq = 0;
radio->marimba->mod_id = SLAVE_ID_BAHAMA;
- marimba_set_fm_status(radio->marimba, true);
return 0;
@@ -2082,6 +2082,7 @@
config_i2s_err:
radio->pdata->fm_shutdown(radio->pdata);
open_err_setup:
+ marimba_set_fm_status(radio->marimba, false);
radio->handle_irq = 1;
atomic_inc(&radio->users);
return retval;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 495fbb1..bd838fc 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -69,6 +69,8 @@
/* Check if enterprise security is activate */
#define SCM_IS_ACTIVATED_ID 0x02
+#define RPMB_SERVICE 0x2000
+
enum qseecom_clk_definitions {
CLK_DFAB = 0,
CLK_SFPB,
@@ -212,6 +214,8 @@
/* Function proto types */
static int qsee_vote_for_clock(struct qseecom_dev_handle *, int32_t);
static void qsee_disable_clock_vote(struct qseecom_dev_handle *, int32_t);
+static int __qseecom_enable_clk(enum qseecom_ce_hw_instance ce);
+static void __qseecom_disable_clk(enum qseecom_ce_hw_instance ce);
static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
struct qseecom_register_listener_req *svc)
@@ -520,6 +524,10 @@
msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle,
ptr_svc->sb_virt, ptr_svc->sb_length,
ION_IOC_CLEAN_INV_CACHES);
+
+ if (lstnr == RPMB_SERVICE)
+ __qseecom_enable_clk(CLK_QSEE);
+
ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
(const void *)&send_data_rsp,
sizeof(send_data_rsp), resp,
@@ -527,6 +535,8 @@
if (ret) {
pr_err("scm_call() failed with err: %d (app_id = %d)\n",
ret, data->client.app_id);
+ if (lstnr == RPMB_SERVICE)
+ __qseecom_disable_clk(CLK_QSEE);
return ret;
}
if ((resp->result != QSEOS_RESULT_SUCCESS) &&
@@ -535,6 +545,9 @@
resp->result, data->client.app_id, lstnr);
ret = -EINVAL;
}
+ if (lstnr == RPMB_SERVICE)
+ __qseecom_disable_clk(CLK_QSEE);
+
}
if (rc)
return rc;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9527249..654dbcb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1496,9 +1496,11 @@
int vdd_bit = -1;
u8 ctrl;
+ mutex_lock(&host->ios_mutex);
if (host->flags & SDHCI_DEVICE_DEAD) {
if (host->vmmc && ios->power_mode == MMC_POWER_OFF)
mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
+ mutex_unlock(&host->ios_mutex);
return;
}
@@ -1508,6 +1510,7 @@
spin_lock_irqsave(&host->lock, flags);
if (!host->clock) {
spin_unlock_irqrestore(&host->lock, flags);
+ mutex_unlock(&host->ios_mutex);
return;
}
spin_unlock_irqrestore(&host->lock, flags);
@@ -1664,6 +1667,7 @@
sdhci_set_clock(host, ios->clock);
mmiowb();
+ mutex_unlock(&host->ios_mutex);
}
static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -2900,6 +2904,7 @@
host->mmc = mmc;
spin_lock_init(&host->lock);
+ mutex_init(&host->ios_mutex);
return host;
}
diff --git a/drivers/nfc/nfc-nci.c b/drivers/nfc/nfc-nci.c
index 9e9a4ea..e832716 100644
--- a/drivers/nfc/nfc-nci.c
+++ b/drivers/nfc/nfc-nci.c
@@ -27,7 +27,6 @@
#include <linux/regulator/consumer.h>
#include "nfc-nci.h"
-
struct qca199x_platform_data {
unsigned int irq_gpio;
unsigned int dis_gpio;
@@ -62,6 +61,7 @@
bool irq_enabled;
spinlock_t irq_enabled_lock;
unsigned int count_irq;
+ enum nfcc_state state;
};
/*
@@ -69,6 +69,12 @@
* IOCTL NFC_KERNEL_LOGGING_MODE.
*/
static int logging_level;
+/*
+ * FTM-RAW-I2C RD/WR MODE
+ */
+static struct devicemode device_mode;
+static int ftm_raw_write_mode;
+static int ftm_werr_code;
static void qca199x_init_stat(struct qca199x_dev *qca199x_dev)
{
@@ -104,7 +110,6 @@
struct qca199x_dev *qca199x_dev = dev_id;
unsigned long flags;
-
spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
qca199x_dev->count_irq++;
spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
@@ -119,7 +124,6 @@
unsigned int mask = 0;
unsigned long flags;
-
poll_wait(filp, &qca199x_dev->read_wq, wait);
spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
@@ -129,17 +133,33 @@
}
spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
-
return mask;
}
+/*
+ * ONLY for FTM-RAW-I2C Mode
+ * Required to instigate a read, which comes from DT layer. This means we need
+ * to spoof an interrupt and send a wake up event.
+ */
+void ftm_raw_trigger_read(struct qca199x_dev *qca199x_dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
+ qca199x_dev->count_irq++;
+ spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
+ wake_up(&qca199x_dev->read_wq);
+}
+
static ssize_t nfc_read(struct file *filp, char __user *buf,
size_t count, loff_t *offset)
{
struct qca199x_dev *qca199x_dev = filp->private_data;
- unsigned char tmp[MAX_BUFFER_SIZE];
+ unsigned char tmp[MAX_BUFFER_SIZE], rd_byte;
unsigned char len[PAYLOAD_HEADER_LENGTH];
int total, length, ret;
+ int ftm_rerr_code;
+ enum ehandler_mode dmode;
total = 0;
length = 0;
@@ -147,6 +167,36 @@
count = MAX_BUFFER_SIZE;
mutex_lock(&qca199x_dev->read_mutex);
+ dmode = device_mode.handle_flavour;
+ /* FTM-RAW-I2C RD/WR MODE - Special Case */
+ if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
+ (dmode == SOLICITED_FTM_RAW_MODE)) {
+ /* READ */
+ if ((ftm_raw_write_mode == 0) && (ftm_werr_code == 0)) {
+ ftm_rerr_code = i2c_master_recv(qca199x_dev->client,
+ &rd_byte, 1);
+ if (ftm_rerr_code == 0x1)
+ ftm_rerr_code = 0;
+ tmp[0] = (unsigned char)ftm_rerr_code;
+ tmp[1] = rd_byte;
+ total = 2;
+ ret = copy_to_user(buf, tmp, total);
+ }
+ /* WRITE */
+ else if ((ftm_raw_write_mode == 1) || (ftm_werr_code != 0)) {
+ tmp[0] = (unsigned char)ftm_werr_code;
+ total = 1;
+ ret = copy_to_user(buf, tmp, total);
+ } else {
+ /* Invalid case */
+ total = 0;
+ ret = copy_to_user(buf, tmp, total);
+ }
+ mutex_unlock(&qca199x_dev->read_mutex);
+ goto done;
+ }
+
+ /* NORMAL NCI Behaviour */
/* Read the header */
ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
if (ret != PAYLOAD_HEADER_LENGTH)
@@ -174,7 +224,7 @@
err:
if (ret < 0)
mutex_unlock(&qca199x_dev->read_mutex);
-
+done:
return total;
}
@@ -183,7 +233,8 @@
{
struct qca199x_dev *qca199x_dev = filp->private_data;
char tmp[MAX_BUFFER_SIZE];
- int ret;
+ int ret = 0;
+ enum ehandler_mode dmode;
if (count > MAX_BUFFER_SIZE) {
dev_err(&qca199x_dev->client->dev, "out of memory\n");
@@ -195,10 +246,39 @@
return -EFAULT;
}
mutex_lock(&qca199x_dev->read_mutex);
- ret = i2c_master_send(qca199x_dev->client, tmp, count);
+ dmode = device_mode.handle_flavour;
+ /* FTM-DIRECT-I2C RD/WR MODE */
+ /* This is a special FTM-i2c mode case,where tester is not using NCI */
+ if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
+ (dmode == SOLICITED_FTM_RAW_MODE)) {
+ /* Read From Register */
+ if (count == 1) {
+ ftm_raw_write_mode = 0;
+ ret = i2c_master_send(qca199x_dev->client, tmp, count);
+ if (ret == 1)
+ ftm_werr_code = 0;
+ else
+ ftm_werr_code = ret;
+ ftm_raw_trigger_read(qca199x_dev);
+ }
+ /* Write to Register */
+ if (count == 2) {
+ ftm_raw_write_mode = 1;
+ ret = i2c_master_send(qca199x_dev->client, tmp, count);
+ if (ret == 2)
+ ftm_werr_code = 0;
+ else
+ ftm_werr_code = ret;
+ ftm_raw_trigger_read(qca199x_dev);
+ }
+ } else {
+ /* NORMAL NCI behaviour - NB :
+ We can be in FTM mode here also */
+ ret = i2c_master_send(qca199x_dev->client, tmp, count);
+ }
if (ret != count) {
dev_err(&qca199x_dev->client->dev,
- "NFC: failed to write %d\n", ret);
+ "NFC: failed to write %d\n", ret);
ret = -EIO;
}
mutex_unlock(&qca199x_dev->read_mutex);
@@ -225,7 +305,7 @@
/*
* Wake/Sleep Mode
*/
-int nfcc_wake(int level, struct nfc_info *info)
+int nfcc_wake(int level, struct file *filp)
{
int r = 0;
unsigned char raw_nci_sleep[] = {0x2F, 0x03, 0x00};
@@ -233,32 +313,32 @@
unsigned char raw_nci_wake[] = {0x10, 0x0F};
unsigned short slave_addr = 0xE;
unsigned short curr_addr;
+ struct qca199x_dev *qca199x_dev = filp->private_data;
- struct i2c_client *client = info->i2c_dev;
-
- dev_dbg(&client->dev, "nfcc_wake: %s: info: %p\n", __func__, info);
+ dev_dbg(&qca199x_dev->client->dev, "nfcc_wake: %s: info: %p\n",
+ __func__, qca199x_dev);
if (level == NFCC_SLEEP) {
- r = nfc_i2c_write(client, &raw_nci_sleep[0],
+ r = i2c_master_send(qca199x_dev->client, &raw_nci_sleep[0],
sizeof(raw_nci_sleep));
+ r = sizeof(raw_nci_sleep);
if (r != sizeof(raw_nci_sleep))
return -EMSGSIZE;
- info->state = NFCC_STATE_NORMAL_SLEEP;
+ qca199x_dev->state = NFCC_STATE_NORMAL_SLEEP;
} else {
- curr_addr = client->addr;
- client->addr = slave_addr;
- r = nfc_i2c_write(client, &raw_nci_wake[0],
+ curr_addr = qca199x_dev->client->addr;
+ qca199x_dev->client->addr = slave_addr;
+ r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
sizeof(raw_nci_wake));
/* Restore original NFCC slave I2C address */
- client->addr = curr_addr;
-
- if (r != sizeof(raw_nci_sleep))
+ qca199x_dev->client->addr = curr_addr;
+ r = sizeof(raw_nci_wake);
+ if (r != sizeof(raw_nci_wake))
return -EMSGSIZE;
-
- info->state = NFCC_STATE_NORMAL_WAKE;
+ qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
}
- msleep(20);
+
return r;
}
@@ -284,41 +364,35 @@
{
int r = 0;
struct qca199x_dev *qca199x_dev = filp->private_data;
- struct nfc_info *info = container_of(filp->private_data,
- struct nfc_info, miscdev);
-
- struct i2c_client *client = info->i2c_dev;
-
- r = gpio_request(qca199x_dev->dis_gpio, "nfc_reset_gpio");
- if (r) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
- qca199x_dev->dis_gpio);
- goto err_req;
- }
- gpio_set_value(qca199x_dev->dis_gpio, 0);
- r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
- if (r) {
- dev_err(&client->dev, "unable to set direction for gpio [%d]\n",
- qca199x_dev->irq_gpio);
- goto err_req;
- }
if (arg == 0) {
gpio_set_value(qca199x_dev->dis_gpio, 0);
- msleep(20);
+ r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
+ if (r) {
+ dev_err(&qca199x_dev->client->dev,
+ "unable to set direction for gpio [%d]\n",
+ qca199x_dev->dis_gpio);
+ goto err_req;
+ }
+ gpio_set_value(qca199x_dev->dis_gpio, 0);
} else if (arg == 1) {
+ gpio_set_value(qca199x_dev->dis_gpio, 0);
+ r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
+ if (r) {
+ dev_err(&qca199x_dev->client->dev,
+ "unable to set direction for gpio [%d]\n",
+ qca199x_dev->dis_gpio);
+ goto err_req;
+ }
gpio_set_value(qca199x_dev->dis_gpio, 1);
- msleep(20);
} else if (arg == 2) {
msleep(20);
} else if (arg == 3) {
msleep(20);
} else if (arg == 4) {
- nfcc_wake(NFCC_WAKE, info);
- msleep(20);
+ nfcc_wake(NFCC_WAKE, filp);
} else if (arg == 5) {
- nfcc_wake(NFCC_SLEEP, info);
- msleep(20);
+ nfcc_wake(NFCC_SLEEP, filp);
} else {
r = -ENOIOCTLCMD;
}
@@ -327,6 +401,63 @@
return r;
}
+
+/*
+ * Inside nfc_ioctl_nfcc_mode
+ *
+ * @brief nfc_ioctl_nfcc_mode
+ *
+ * (arg = 0) ; NORMAL_MODE - Standard mode, unsolicited read behaviour
+ * (arg = 1) ; SOLICITED_MODE - As above but reads are solicited from User Land
+ * (arg = 2) ; UNSOLICITED_FTM_RAW MODE - NORMAL_MODE but messages from FTM and
+ * not NCI Host.
+ * (arg = 2) ; SOLICITED_FTM_RAW_MODE - As SOLICITED_MODE but messages from FTM
+ * and not NCI Host.
+ *
+ *
+ *
+ */
+int nfc_ioctl_nfcc_mode(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+
+ static unsigned short nci_addr;
+ struct qca199x_dev *qca199x_dev = filp->private_data;
+ struct qca199x_platform_data *platform_data;
+
+ platform_data = qca199x_dev->client->dev.platform_data;
+
+ if (arg == 0) {
+ device_mode.handle_flavour = UNSOLICITED_MODE;
+ qca199x_dev->client->addr = NCI_I2C_SLAVE;
+ /* enable interrupts again */
+ qca199x_enable_irq(qca199x_dev);
+ } else if (arg == 1) {
+ device_mode.handle_flavour = SOLICITED_MODE;
+ qca199x_dev->client->addr = qca199x_dev->client->addr;
+ /* enable interrupts again */
+ qca199x_enable_irq(qca199x_dev);
+ } else if (arg == 2) {
+ device_mode.handle_flavour = UNSOLICITED_FTM_RAW_MODE;
+ nci_addr = qca199x_dev->client->addr;
+ /* replace with new client slave address*/
+ qca199x_dev->client->addr = 0xE;
+ /* We also need to disable interrupts */
+ qca199x_disable_irq(qca199x_dev);
+ } else if (arg == 3) {
+ device_mode.handle_flavour = SOLICITED_FTM_RAW_MODE;
+ nci_addr = qca199x_dev->client->addr;
+ /* replace with new client slave address*/
+ qca199x_dev->client->addr = 0xE;
+ /* We also need to disable interrupts */
+ qca199x_disable_irq(qca199x_dev);
+ } else {
+ device_mode.handle_flavour = UNSOLICITED_MODE;
+ qca199x_dev->client->addr = NCI_I2C_SLAVE;
+ }
+ return retval;
+}
+
/*
* Inside nfc_ioctl_kernel_logging
*
@@ -371,6 +502,7 @@
nfc_ioctl_power_states(pfile, cmd, arg);
break;
case NFCC_MODE:
+ nfc_ioctl_nfcc_mode(pfile, cmd, arg);
break;
case NFC_KERNEL_LOGGING_MODE:
nfc_ioctl_kernel_logging(arg, pfile);
@@ -447,66 +579,75 @@
unsigned char raw_s73[] = {0x73, 0x02};
unsigned char raw_slave1_rd = {0x0};
unsigned char raw_1P8_PAD_CFG_CLK_REQ[] = {0xA5, 0x1};
- unsigned char buf[4];
+ unsigned char raw_1P8_PAD_CFG_PWR_REQ[] = {0xA7, 0x1};
+ unsigned char buf = 0;
- /* Set I2C address to enable configuration of QCA1990 */
client->addr = curr_addr;
- RAW(s73, 0x02);
+ r = i2c_master_send(client, &buf, 1);
+ buf = 0;
+ r = i2c_master_recv(client, &buf, 1);
+ if (0x10 != (0x10 & buf)) {
+ RAW(s73, 0x02);
- r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
- usleep(1000);
- RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
+ r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
+ usleep(1000);
+ RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
- r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
+ r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
sizeof(raw_1p8_CONTROL_011));
- usleep(1000);
- RAW(1P8_CONTROL_010, (0x8));
- r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
- sizeof(raw_1P8_CONTROL_010));
-
- usleep(10000); /* 10ms wait */
- RAW(1P8_CONTROL_010, (0xC));
- r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
- sizeof(raw_1P8_CONTROL_010));
- usleep(100); /* 100uS wait */
- RAW(1P8_X0_0B0, (FREQ_SEL_19));
- r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0], sizeof(raw_1P8_X0_0B0));
- usleep(1000);
-
- /* PWR_EN = 1 */
- RAW(1P8_CONTROL_010, (0xd));
- r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
+ usleep(1000);
+ RAW(1P8_CONTROL_010, (0x8));
+ r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
sizeof(raw_1P8_CONTROL_010));
- usleep(20000); /* 20ms wait */
- /* LS_EN = 1 */
- RAW(1P8_CONTROL_010, 0xF);
- r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
- sizeof(raw_1P8_CONTROL_010));
- usleep(20000); /* 20ms wait */
- /* Enable the PMIC clock */
- RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
- r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
+ usleep(10000); /* 10ms wait */
+ RAW(1P8_CONTROL_010, (0xC));
+ r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
+ sizeof(raw_1P8_CONTROL_010));
+ usleep(100); /* 100uS wait */
+ RAW(1P8_X0_0B0, (FREQ_SEL_19));
+ r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
+ sizeof(raw_1P8_X0_0B0));
+ usleep(1000);
+
+ /* PWR_EN = 1 */
+ RAW(1P8_CONTROL_010, (0xd));
+ r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
+ sizeof(raw_1P8_CONTROL_010));
+ usleep(20000); /* 20ms wait */
+ /* LS_EN = 1 */
+ RAW(1P8_CONTROL_010, 0xF);
+ r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
+ sizeof(raw_1P8_CONTROL_010));
+ usleep(20000); /* 20ms wait */
+
+ /* Enable the PMIC clock */
+ RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
+ r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
sizeof(raw_1P8_PAD_CFG_CLK_REQ));
- usleep(1000);
+ usleep(1000);
- RAW(slave2, 0x10);
- r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
- usleep(1000);
- {
- r = i2c_master_send(client, buf, 1);
- memset(buf, 0xAA, sizeof(buf));
- r = i2c_master_recv(client, buf, 1);
+ RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
+ r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
+ sizeof(raw_1P8_PAD_CFG_PWR_REQ));
+ usleep(1000);
+
+ RAW(slave2, 0x10);
+ r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
+ usleep(1000);
+
+ RAW(slave1, NCI_I2C_SLAVE);
+ r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
+ usleep(1000);
+
+ /* QCA199x NFCC CPU should now boot... */
+ r = i2c_master_recv(client, &raw_slave1_rd, 1);
+ /* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
+ client->addr = NCI_I2C_SLAVE;
+ r = 0;
+ } else {
+ r = 1;
}
- RAW(slave1, NCI_I2C_SLAVE);
- r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
- usleep(1000);
-
- /* QCA199x NFCC CPU should now boot... */
- r = i2c_master_recv(client, &raw_slave1_rd, 1);
- /* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
- client->addr = NCI_I2C_SLAVE;
-
return r;
}
@@ -623,6 +764,9 @@
dev_err(&client->dev, "dis gpio not provided\n");
goto err_irq;
}
+ gpio_set_value(qca199x_dev->dis_gpio, 1);
+ msleep(20);
+ gpio_set_value(qca199x_dev->dis_gpio, 0);
nfc_clk = clk_get(&client->dev, "ref_clk");
@@ -640,7 +784,7 @@
r = gpio_request(platform_data->ven_gpio, "nfc_ven_gpio");
if (r) {
dev_err(&client->dev, "unable to request gpio [%d]\n",
- platform_data->irq_gpio);
+ platform_data->ven_gpio);
goto err_ven_gpio;
}
r = gpio_direction_input(platform_data->ven_gpio);
@@ -648,7 +792,7 @@
dev_err(&client->dev,
"unable to set direction for gpio [%d]\n",
- platform_data->irq_gpio);
+ platform_data->ven_gpio);
goto err_ven_gpio;
}
@@ -681,7 +825,12 @@
/* request irq. The irq is set whenever the chip has data available
* for reading. It is cleared when all data has been read.
*/
- nfcc_initialise(client, platform_data->reg);
+ device_mode.handle_flavour = UNSOLICITED_MODE;
+ r = nfcc_initialise(client, platform_data->reg);
+ if (r) {
+ dev_err(&client->dev, "nfc-nci probe: request nfcc initialise failed\n");
+ goto err_nfcc_init_failed;
+ }
qca199x_dev->irq_enabled = true;
r = request_irq(client->irq, qca199x_dev_irq_handler,
@@ -697,6 +846,7 @@
__func__);
return 0;
+err_nfcc_init_failed:
err_request_irq_failed:
misc_deregister(&qca199x_dev->qca199x_device);
err_misc_register:
diff --git a/drivers/nfc/nfc-nci.h b/drivers/nfc/nfc-nci.h
index 4398df7..c3cabc2 100644
--- a/drivers/nfc/nfc-nci.h
+++ b/drivers/nfc/nfc-nci.h
@@ -30,8 +30,10 @@
};
enum ehandler_mode {
- UNSOLICITED_READ_MODE = 0,
- SOLICITED_READ_MODE
+ UNSOLICITED_MODE = 0,
+ SOLICITED_MODE,
+ UNSOLICITED_FTM_RAW_MODE,
+ SOLICITED_FTM_RAW_MODE
};
enum ekernel_logging_mode {
@@ -43,9 +45,9 @@
LEVEL_5
};
-struct DeviceMode {
+struct devicemode {
enum ehandler_mode handle_flavour;
-} tDeviceMode;
+} tdevicemode;
#define NFC_DRIVER_NAME "nfc-nci"
#define NFC_I2C_DRIVER_NAME "NCI NFC I2C Interface",
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index acd42ae3..a3f8ec9 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -113,4 +113,9 @@
help
OpenFirmware CoreSight accessors
+config OF_BATTERYDATA
+ def_bool y
+ help
+ OpenFirmware BatteryData accessors
+
endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 61a99f2..8b52306 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -16,3 +16,4 @@
obj-$(CONFIG_OF_MTD) += of_mtd.o
obj-$(CONFIG_OF_SLIMBUS) += of_slimbus.o
obj-$(CONFIG_OF_CORESIGHT) += of_coresight.o
+obj-$(CONFIG_OF_BATTERYDATA) += of_batterydata.o
diff --git a/drivers/of/of_batterydata.c b/drivers/of/of_batterydata.c
new file mode 100644
index 0000000..c2585a7
--- /dev/null
+++ b/drivers/of/of_batterydata.c
@@ -0,0 +1,265 @@
+/* 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: " fmt, __func__
+
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/batterydata-lib.h>
+
+static int of_batterydata_read_lut(const struct device_node *np,
+ int max_cols, int max_rows, int *ncols, int *nrows,
+ int *col_legend_data, int *row_legend_data,
+ int *lut_data)
+{
+ struct property *prop;
+ const __be32 *data;
+ int cols, rows, size, i, j, *out_values;
+
+ prop = of_find_property(np, "qcom,lut-col-legend", NULL);
+ if (!prop) {
+ pr_err("%s: No col legend found\n", np->name);
+ return -EINVAL;
+ } else if (!prop->value) {
+ pr_err("%s: No col legend value found, np->name\n", np->name);
+ return -ENODATA;
+ } else if (prop->length > max_cols * sizeof(int)) {
+ pr_err("%s: Too many columns\n", np->name);
+ return -EINVAL;
+ }
+
+ cols = prop->length/sizeof(int);
+ *ncols = cols;
+ data = prop->value;
+ for (i = 0; i < cols; i++)
+ *col_legend_data++ = be32_to_cpup(data++);
+
+ prop = of_find_property(np, "qcom,lut-row-legend", NULL);
+ if (!prop || row_legend_data == NULL) {
+ /* single row lut */
+ rows = 1;
+ } else if (!prop->value) {
+ pr_err("%s: No row legend value found\n", np->name);
+ return -ENODATA;
+ } else if (prop->length > max_rows * sizeof(int)) {
+ pr_err("%s: Too many rows\n", np->name);
+ return -EINVAL;
+ } else {
+ rows = prop->length/sizeof(int);
+ *nrows = rows;
+ data = prop->value;
+ for (i = 0; i < rows; i++)
+ *row_legend_data++ = be32_to_cpup(data++);
+ }
+
+ prop = of_find_property(np, "qcom,lut-data", NULL);
+ data = prop->value;
+ size = prop->length/sizeof(int);
+ if (!prop || size != cols * rows) {
+ pr_err("%s: data size mismatch, %dx%d != %d\n",
+ np->name, cols, rows, size);
+ return -EINVAL;
+ }
+ for (i = 0; i < rows; i++) {
+ out_values = lut_data + (max_cols * i);
+ for (j = 0; j < cols; j++) {
+ *out_values++ = be32_to_cpup(data++);
+ pr_debug("Value = %d\n", *(out_values-1));
+ }
+ }
+
+ return 0;
+}
+
+static int of_batterydata_read_sf_lut(struct device_node *data_node,
+ const char *name, struct sf_lut *lut)
+{
+ struct device_node *node = of_find_node_by_name(data_node, name);
+ int rc;
+
+ if (!lut) {
+ pr_debug("No lut provided, skipping\n");
+ return 0;
+ } else if (!node) {
+ pr_err("Couldn't find %s node.\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_batterydata_read_lut(node, PC_CC_COLS, PC_CC_ROWS,
+ &lut->cols, &lut->rows, lut->row_entries,
+ lut->percent, *lut->sf);
+ if (rc) {
+ pr_err("Failed to read %s node.\n", name);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int of_batterydata_read_pc_temp_ocv_lut(struct device_node *data_node,
+ const char *name, struct pc_temp_ocv_lut *lut)
+{
+ struct device_node *node = of_find_node_by_name(data_node, name);
+ int rc;
+
+ if (!lut) {
+ pr_debug("No lut provided, skipping\n");
+ return 0;
+ } else if (!node) {
+ pr_err("Couldn't find %s node.\n", name);
+ return -EINVAL;
+ }
+ rc = of_batterydata_read_lut(node, PC_TEMP_COLS, PC_TEMP_ROWS,
+ &lut->cols, &lut->rows, lut->temp, lut->percent,
+ *lut->ocv);
+ if (rc) {
+ pr_err("Failed to read %s node.\n", name);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int of_batterydata_read_single_row_lut(struct device_node *data_node,
+ const char *name, struct single_row_lut *lut)
+{
+ struct device_node *node = of_find_node_by_name(data_node, name);
+ int rc;
+
+ if (!lut) {
+ pr_debug("No lut provided, skipping\n");
+ return 0;
+ } else if (!node) {
+ pr_err("Couldn't find %s node.\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_batterydata_read_lut(node, MAX_SINGLE_LUT_COLS, 1,
+ &lut->cols, NULL, lut->x, NULL, lut->y);
+ if (rc) {
+ pr_err("Failed to read %s node.\n", name);
+ return rc;
+ }
+
+ return 0;
+}
+
+#define OF_PROP_READ(property, qpnp_dt_property, node, rc, optional) \
+do { \
+ rc = of_property_read_u32(node, "qcom," qpnp_dt_property, \
+ &property); \
+ \
+ if ((rc == -EINVAL) && optional) { \
+ property = -EINVAL; \
+ rc = 0; \
+ } else if (rc) { \
+ pr_err("Error reading " #qpnp_dt_property \
+ " property rc = %d\n", rc); \
+ return rc; \
+ } \
+} while (0)
+
+static int of_batterydata_load_battery_data(struct device_node *node,
+ struct bms_battery_data *batt_data)
+{
+ int rc;
+
+ rc = of_batterydata_read_single_row_lut(node, "qcom,fcc-temp-lut",
+ batt_data->fcc_temp_lut);
+ if (rc)
+ return rc;
+
+ rc = of_batterydata_read_pc_temp_ocv_lut(node,
+ "qcom,pc-temp-ocv-lut",
+ batt_data->pc_temp_ocv_lut);
+ if (rc)
+ return rc;
+
+ rc = of_batterydata_read_sf_lut(node, "qcom,rbatt-sf-lut",
+ batt_data->rbatt_sf_lut);
+ if (rc)
+ return rc;
+
+ OF_PROP_READ(batt_data->fcc, "fcc-mah", node, rc, false);
+ OF_PROP_READ(batt_data->default_rbatt_mohm,
+ "default-rbatt-mohm", node, rc, false);
+ OF_PROP_READ(batt_data->rbatt_capacitive_mohm,
+ "rbatt-capacitive-mohm", node, rc, false);
+ OF_PROP_READ(batt_data->batt_id_kohm, "batt-id-kohm", node, rc, false);
+ OF_PROP_READ(batt_data->flat_ocv_threshold_uv,
+ "flat-ocv-threshold", node, rc, true);
+ OF_PROP_READ(batt_data->max_voltage_uv,
+ "max-voltage-uv", node, rc, true);
+ OF_PROP_READ(batt_data->cutoff_uv, "v-cutoff-uv", node, rc, true);
+ OF_PROP_READ(batt_data->iterm_ua, "chg-term-ua", node, rc, true);
+
+ return rc;
+}
+
+static int64_t of_batterydata_convert_battery_id_kohm(int batt_id_uv,
+ int rpull_up, int vadc_vdd)
+{
+ int64_t resistor_value_kohm, denom;
+
+ /* calculate the battery id resistance reported via ADC */
+ denom = div64_s64(vadc_vdd * 1000000LL, batt_id_uv) - 1000000LL;
+
+ resistor_value_kohm = div64_s64(rpull_up * 1000000LL + denom/2, denom);
+
+ pr_debug("batt id voltage = %d, resistor value = %lld\n",
+ batt_id_uv, resistor_value_kohm);
+
+ return resistor_value_kohm;
+}
+
+int of_batterydata_read_data(struct device_node *batterydata_container_node,
+ struct bms_battery_data *batt_data,
+ int batt_id_uv)
+{
+ struct device_node *node, *best_node;
+ uint32_t id_kohm;
+ int delta, best_delta, batt_id_kohm, rpull_up_kohm, vadc_vdd_uv, rc = 0;
+
+ node = batterydata_container_node;
+ OF_PROP_READ(rpull_up_kohm, "rpull-up-kohm", node, rc, false);
+ OF_PROP_READ(vadc_vdd_uv, "vref-batt-therm", node, rc, false);
+
+ batt_id_kohm = of_batterydata_convert_battery_id_kohm(batt_id_uv,
+ rpull_up_kohm, vadc_vdd_uv);
+ best_node = NULL;
+ best_delta = 0;
+
+ /*
+ * Find the battery data with a battery id resistor closest to this one
+ */
+ for_each_child_of_node(batterydata_container_node, node) {
+ rc = of_property_read_u32(node, "qcom,batt-id-kohm", &id_kohm);
+ if (rc)
+ continue;
+ delta = abs((int)id_kohm - batt_id_kohm);
+ if (delta < best_delta || !best_node) {
+ best_node = node;
+ best_delta = delta;
+ }
+ }
+
+ if (best_node == NULL) {
+ pr_err("No battery data found\n");
+ return -ENODATA;
+ }
+
+ return of_batterydata_load_battery_data(best_node, batt_data);
+}
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 8c0adbd..8d6d5e6 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -74,23 +74,6 @@
rule_hdr->u.hdr.hdr_offset = 0;
}
buf += sizeof(struct ipa_rt_rule_hw_hdr);
- if ((ip == IPA_IP_v4) &&
- (entry->rule.attrib.attrib_mask & IPA_FLT_TOS)) {
- entry->rule.attrib.tos_value =
- (entry->rule.attrib.u.v4.tos << 5);
- entry->rule.attrib.tos_mask = 0xe0;
- entry->rule.attrib.attrib_mask &= ~IPA_FLT_TOS;
- entry->rule.attrib.attrib_mask |= IPA_FLT_TOS_MASKED;
- }
-
- if ((ip == IPA_IP_v6) &&
- (entry->rule.attrib.attrib_mask & IPA_FLT_TC)) {
- entry->rule.attrib.tos_value =
- (entry->rule.attrib.u.v6.tc << 5);
- entry->rule.attrib.tos_mask = 0xe0;
- entry->rule.attrib.attrib_mask &= ~IPA_FLT_TC;
- entry->rule.attrib.attrib_mask |= IPA_FLT_TOS_MASKED;
- }
if (ipa_generate_hw_rule(ip, &rule->attrib, &buf, &en_rule)) {
IPAERR("fail to generate hw rule\n");
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index 93f2366..b3a6b17 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -373,8 +373,8 @@
/* Add a header entry for USB */
res = add_eth_hdrs(USB_ETH_HDR_NAME_IPV4,
USB_ETH_HDR_NAME_IPV6,
- teth_ctx->mac_addresses.host_pc_mac_addr,
- teth_ctx->mac_addresses.device_mac_addr);
+ teth_ctx->mac_addresses.device_mac_addr,
+ teth_ctx->mac_addresses.host_pc_mac_addr);
if (res) {
TETH_ERR("Failed adding USB Ethernet header\n");
goto bail;
@@ -384,8 +384,8 @@
/* Add a header entry for A2 */
res = add_eth_hdrs(A2_ETH_HDR_NAME_IPV4,
A2_ETH_HDR_NAME_IPV6,
- teth_ctx->mac_addresses.device_mac_addr,
- teth_ctx->mac_addresses.host_pc_mac_addr);
+ teth_ctx->mac_addresses.host_pc_mac_addr,
+ teth_ctx->mac_addresses.device_mac_addr);
if (res) {
TETH_ERR("Failed adding A2 Ethernet header\n");
goto bail;
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index fe8b5ec..b4edce8 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -33,6 +33,7 @@
#define QPNP_PON_DBC_CTL(base) (base + 0x71)
/* PON/RESET sources register addresses */
+#define QPNP_PON_REASON1(base) (base + 0x8)
#define QPNP_PON_WARM_RESET_REASON1(base) (base + 0xA)
#define QPNP_PON_WARM_RESET_REASON2(base) (base + 0xB)
#define QPNP_PON_KPDPWR_S1_TIMER(base) (base + 0x40)
@@ -82,6 +83,7 @@
#define QPNP_PON_S3_DBC_DELAY_MASK 0x07
#define QPNP_PON_RESET_TYPE_MAX 0xF
#define PON_S1_COUNT_MAX 0xF
+#define PON_REASON_MAX 8
#define QPNP_KEY_STATUS_DELAY msecs_to_jiffies(250)
#define QPNP_PON_REV_B 0x01
@@ -123,6 +125,17 @@
3072, 4480, 6720, 10256
};
+static const char * const qpnp_pon_reason[] = {
+ [0] = "Triggered from Hard Reset",
+ [1] = "Triggered from SMPL (sudden momentary power loss)",
+ [2] = "Triggered from RTC (RTC alarm expiry)",
+ [3] = "Triggered from DC (DC charger insertion)",
+ [4] = "Triggered from USB (USB charger insertion)",
+ [5] = "Triggered from PON1 (secondary PMIC)",
+ [6] = "Triggered from CBL (external power supply)",
+ [7] = "Triggered from KPD (power key press)",
+};
+
static int
qpnp_pon_masked_write(struct qpnp_pon *pon, u16 addr, u8 mask, u8 val)
{
@@ -966,7 +979,8 @@
struct resource *pon_resource;
struct device_node *itr = NULL;
u32 delay = 0, s3_debounce = 0;
- int rc, sys_reset;
+ int rc, sys_reset, index;
+ u8 pon_sts = 0;
pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
GFP_KERNEL);
@@ -1007,6 +1021,19 @@
}
pon->base = pon_resource->start;
+ /* PON reason */
+ rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
+ QPNP_PON_REASON1(pon->base), &pon_sts, 1);
+ if (rc) {
+ dev_err(&pon->spmi->dev, "Unable to read PON_RESASON1 reg\n");
+ return rc;
+ }
+ index = ffs(pon_sts);
+ if ((index > PON_REASON_MAX) || (index < 0))
+ index = 0;
+ pr_info("PMIC@SID%d Power-on reason: %s\n", pon->spmi->sid,
+ index ? qpnp_pon_reason[index - 1] : "Unknown");
+
rc = of_property_read_u32(pon->spmi->dev.of_node,
"qcom,pon-dbc-delay", &delay);
if (rc) {
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 4e94b90..2fdc427 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -43,21 +43,32 @@
#define QPNP_EN_PAUSE_LO_MASK 0x01
/* LPG Control for LPG_PWM_SIZE_CLK */
+#define QPNP_PWM_SIZE_SHIFT_SUB_TYPE 2
+#define QPNP_PWM_SIZE_MASK_SUB_TYPE 0x4
+#define QPNP_PWM_FREQ_CLK_SELECT_MASK_SUB_TYPE 0x03
+#define QPNP_PWM_SIZE_9_BIT_SUB_TYPE 0x01
+
+#define QPNP_SET_PWM_CLK_SUB_TYPE(val, clk, pwm_size) \
+do { \
+ val = (clk + 1) & QPNP_PWM_FREQ_CLK_SELECT_MASK_SUB_TYPE; \
+ val |= ((pwm_size > 6 ? QPNP_PWM_SIZE_9_BIT_SUB_TYPE : 0) << \
+ QPNP_PWM_SIZE_SHIFT_SUB_TYPE) & QPNP_PWM_SIZE_MASK_SUB_TYPE; \
+} while (0)
+
#define QPNP_PWM_SIZE_SHIFT 4
#define QPNP_PWM_SIZE_MASK 0x30
-#define QPNP_PWM_FREQ_CLK_SELECT_SHIFT 0
#define QPNP_PWM_FREQ_CLK_SELECT_MASK 0x03
-#define QPNP_PWM_SIZE_9_BIT 0x03
-
+#define QPNP_MIN_PWM_BIT_SIZE 6
+#define QPNP_MAX_PWM_BIT_SIZE 9
#define QPNP_SET_PWM_CLK(val, clk, pwm_size) \
do { \
val = (clk + 1) & QPNP_PWM_FREQ_CLK_SELECT_MASK; \
- val |= ((pwm_size > 6 ? QPNP_PWM_SIZE_9_BIT : 0) << \
- QPNP_PWM_SIZE_SHIFT) & QPNP_PWM_SIZE_MASK; \
+ val |= (((pwm_size - QPNP_MIN_PWM_BIT_SIZE) << \
+ QPNP_PWM_SIZE_SHIFT) & QPNP_PWM_SIZE_MASK); \
} while (0)
#define QPNP_GET_PWM_SIZE(reg) ((reg & QPNP_PWM_SIZE_MASK) \
- >> QPNP_PWM_SIZE_SHIFT)
+ >> QPNP_PWM_SIZE_SHIFT)
/* LPG Control for LPG_PWM_FREQ_PREDIV_CLK */
#define QPNP_PWM_FREQ_PRE_DIVIDE_SHIFT 5
@@ -68,7 +79,7 @@
do { \
val = (pre_div << QPNP_PWM_FREQ_PRE_DIVIDE_SHIFT) & \
QPNP_PWM_FREQ_PRE_DIVIDE_MASK; \
- val |= pre_div_exp & QPNP_PWM_FREQ_EXP_MASK; \
+ val |= (pre_div_exp & QPNP_PWM_FREQ_EXP_MASK); \
} while (0)
/* LPG Control for LPG_PWM_TYPE_CONFIG */
@@ -104,13 +115,27 @@
#define QPNP_DISABLE_PWM(value) (value &= ~QPNP_EN_PWM_OUTPUT_MASK)
+/* LPG Control for PWM_SYNC */
+#define QPNP_PWM_SYNC_VALUE 0x01
+#define QPNP_PWM_SYNC_MASK 0x01
+
/* LPG Control for RAMP_CONTROL */
#define QPNP_RAMP_START_MASK 0x01
+#define QPNP_RAMP_CONTROL_SHIFT 8
#define QPNP_ENABLE_LUT_V0(value) (value |= QPNP_RAMP_START_MASK)
#define QPNP_DISABLE_LUT_V0(value) (value &= ~QPNP_RAMP_START_MASK)
-#define QPNP_ENABLE_LUT_V1(value, id) (value |= BIT(id))
-#define QPNP_DISABLE_LUT_V1(value, id) (value &= ~BIT(id))
+#define QPNP_ENABLE_LUT_V1(value, id) \
+do { \
+ (id < 8) ? (value |= BIT(id)) : \
+ (value |= (BIT(id) >> QPNP_RAMP_CONTROL_SHIFT)); \
+} while (0)
+
+#define QPNP_DISABLE_LUT_V1(value, id) \
+do { \
+ (id < 8) ? (value &= ~BIT(id)) : \
+ (value &= (~BIT(id) >> QPNP_RAMP_CONTROL_SHIFT)); \
+} while (0)
/* LPG Control for RAMP_STEP_DURATION_LSB */
#define QPNP_RAMP_STEP_DURATION_LSB_MASK 0xFF
@@ -159,9 +184,18 @@
#define SPMI_LPG_REG_BASE_OFFSET 0x40
#define SPMI_LPG_REVISION2_OFFSET 0x1
#define SPMI_LPG_REV1_RAMP_CONTROL_OFFSET 0x86
+#define SPMI_LPG_SUB_TYPE_OFFSET 0x5
+#define SPMI_LPG_PWM_SYNC 0x7
#define SPMI_LPG_REG_ADDR(b, n) (b + SPMI_LPG_REG_BASE_OFFSET + (n))
#define SPMI_MAX_BUF_LEN 8
+#define QPNP_GPLED_LPG_CHANNEL_RANGE_START 8
+#define QPNP_GPLED_LPG_CHANNEL_RANGE_END 11
+#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
+
/* LPG revisions */
enum qpnp_lpg_revision {
QPNP_LPG_REVISION_0 = 0x0,
@@ -277,6 +311,8 @@
struct qpnp_lpg_config lpg_config;
u8 qpnp_lpg_registers[QPNP_TOTAL_LPG_SPMI_REGISTERS];
enum qpnp_lpg_revision revision;
+ u8 sub_type;
+ u32 flags;
};
/* Internal functions */
@@ -374,20 +410,29 @@
* (PWM Period / N) = (Pre-divide * Clock Period) * 2^m
*/
static void qpnp_lpg_calc_period(unsigned int period_us,
- struct pwm_period_config *period)
+ struct qpnp_pwm_config *pwm_conf)
{
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;
/* PWM Period / N */
- if (period_us < ((unsigned)(-1) / NSEC_PER_USEC)) {
- period_n = (period_us * NSEC_PER_USEC) >> 6;
+ if (qpnp_check_gpled_lpg_channel(id))
+ n = 7;
+ else
n = 6;
+
+ if (period_us < ((unsigned)(-1) / NSEC_PER_USEC)) {
+ period_n = (period_us * NSEC_PER_USEC) >> n;
} else {
- period_n = (period_us >> 9) * NSEC_PER_USEC;
- n = 9;
+ if (qpnp_check_gpled_lpg_channel(id))
+ n = 8;
+ else
+ n = 9;
+ period_n = (period_us >> n) * NSEC_PER_USEC;
}
min_err = last_err = (unsigned)(-1);
@@ -422,10 +467,22 @@
}
}
- /* Use higher resolution */
- if (best_m >= 3 && n == 6) {
- n += 3;
- best_m -= 3;
+ /* 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;
+ }
+ }
}
period->pwm_size = n;
@@ -467,8 +524,8 @@
int offset = (lut->lo_index << 1) - 2;
pwm_size = QPNP_GET_PWM_SIZE(
- chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) &
- QPNP_PWM_SIZE_9_BIT ? 9 : 6;
+ chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) +
+ QPNP_MIN_PWM_BIT_SIZE;
max_pwm_value = (1 << pwm_size) - 1;
@@ -489,20 +546,30 @@
if (pwm_value > max_pwm_value)
pwm_value = max_pwm_value;
- lut->duty_pct_list[i*2] = pwm_value;
- lut->duty_pct_list[(i*2)+1] = (pwm_value >>
+ if (qpnp_check_gpled_lpg_channel(pwm->pwm_config.channel_id)) {
+ lut->duty_pct_list[i] = pwm_value;
+ } else {
+ lut->duty_pct_list[i*2] = pwm_value;
+ lut->duty_pct_list[(i*2)+1] = (pwm_value >>
QPNP_PWM_VALUE_MSB_SHIFT) & QPNP_PWM_VALUE_MSB_MASK;
+ }
}
+ /*
+ * For the Keypad Backlight Lookup Table (KPDBL_LUT),
+ * offset is lo_index.
+ */
+ if (qpnp_check_gpled_lpg_channel(pwm->pwm_config.channel_id))
+ offset = lut->lo_index;
+
/* Write with max allowable burst mode, each entry is of two bytes */
- for (i = 0; i < list_len;) {
+ for (i = 0; i < list_len; i += burst_size) {
if (i + burst_size >= list_len)
burst_size = list_len - i;
rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
chip->spmi_dev->sid,
chip->lpg_config.lut_base_addr + offset + i,
lut->duty_pct_list + i, burst_size);
- i += burst_size;
}
return rc;
@@ -514,7 +581,11 @@
struct qpnp_lpg_chip *chip = pwm->chip;
struct qpnp_pwm_config *pwm_config = &pwm->pwm_config;
- QPNP_SET_PWM_CLK(val, pwm_config->period.clk,
+ if (chip->sub_type == 0x0B)
+ QPNP_SET_PWM_CLK_SUB_TYPE(val, pwm_config->period.clk,
+ pwm_config->period.pwm_size);
+ else
+ QPNP_SET_PWM_CLK(val, pwm_config->period.clk,
pwm_config->period.pwm_size);
mask = QPNP_PWM_SIZE_MASK | QPNP_PWM_FREQ_CLK_SELECT_MASK;
@@ -542,8 +613,8 @@
int rc;
pwm_size = QPNP_GET_PWM_SIZE(
- chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) &
- QPNP_PWM_SIZE_9_BIT ? 9 : 6;
+ chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) +
+ QPNP_MIN_PWM_BIT_SIZE;
max_pwm_value = (1 << pwm_size) - 1;
@@ -565,10 +636,21 @@
mask = QPNP_PWM_VALUE_MSB_MASK;
- return qpnp_lpg_save_and_write(value, mask,
+ rc = qpnp_lpg_save_and_write(value, mask,
&pwm->chip->qpnp_lpg_registers[QPNP_PWM_VALUE_MSB],
SPMI_LPG_REG_ADDR(lpg_config->base_addr,
QPNP_PWM_VALUE_MSB), 1, chip);
+ if (rc)
+ return rc;
+
+ if (chip->sub_type == 0x0B) {
+ value = QPNP_PWM_SYNC_VALUE & QPNP_PWM_SYNC_MASK;
+ rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
+ chip->spmi_dev->sid,
+ SPMI_LPG_REG_ADDR(lpg_config->base_addr,
+ SPMI_LPG_PWM_SYNC), &value, 1);
+ }
+ return rc;
}
static int qpnp_lpg_configure_pattern(struct pwm_device *pwm)
@@ -910,13 +992,9 @@
addr1, 1, chip);
}
-#define QPNP_GPLED_LPG_CHANNEL_RANGE_START 8
-#define QPNP_GPLED_LPG_CHANNEL_RANGE_END 11
-
static inline int qpnp_enable_pwm_mode(struct qpnp_pwm_config *pwm_conf)
{
- if (pwm_conf->channel_id >= QPNP_GPLED_LPG_CHANNEL_RANGE_START &&
- pwm_conf->channel_id <= QPNP_GPLED_LPG_CHANNEL_RANGE_END)
+ if (qpnp_check_gpled_lpg_channel(pwm_conf->channel_id))
return QPNP_ENABLE_PWM_MODE_GPLED_CHANNEL;
return QPNP_ENABLE_PWM_MODE;
}
@@ -968,7 +1046,7 @@
period = &pwm_config->period;
if (pwm_config->pwm_period != period_us) {
- qpnp_lpg_calc_period(period_us, period);
+ qpnp_lpg_calc_period(period_us, pwm_config);
qpnp_lpg_save_period(pwm);
pwm_config->pwm_period = period_us;
}
@@ -1024,7 +1102,7 @@
period = &pwm_config->period;
if (pwm_config->pwm_period != period_us) {
- qpnp_lpg_calc_period(period_us, period);
+ qpnp_lpg_calc_period(period_us, pwm_config);
qpnp_lpg_save_period(pwm);
pwm_config->pwm_period = period_us;
}
@@ -1077,7 +1155,7 @@
static int _pwm_enable(struct pwm_device *pwm)
{
- int rc;
+ int rc = 0;
struct qpnp_lpg_chip *chip;
unsigned long flags;
@@ -1086,10 +1164,11 @@
spin_lock_irqsave(&pwm->chip->lpg_lock, flags);
if (QPNP_IS_PWM_CONFIG_SELECTED(
- chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL]))
+ chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL])) {
rc = qpnp_lpg_configure_pwm_state(pwm, QPNP_PWM_ENABLE);
- else
- rc = qpnp_lpg_configure_lut_state(pwm, QPNP_LUT_ENABLE);
+ } else if (!(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) {
+ rc = qpnp_lpg_configure_lut_state(pwm, QPNP_LUT_ENABLE);
+ }
spin_unlock_irqrestore(&pwm->chip->lpg_lock, flags);
@@ -1160,7 +1239,8 @@
if (pwm_config->in_use) {
qpnp_lpg_configure_pwm_state(pwm, QPNP_PWM_DISABLE);
- qpnp_lpg_configure_lut_state(pwm, QPNP_LUT_DISABLE);
+ if (!(pwm->chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED))
+ qpnp_lpg_configure_lut_state(pwm, QPNP_LUT_DISABLE);
pwm_config->in_use = 0;
pwm_config->lable = NULL;
}
@@ -1249,12 +1329,13 @@
if (pwm_config->in_use) {
if (QPNP_IS_PWM_CONFIG_SELECTED(
- chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL]))
+ chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL])) {
rc = qpnp_lpg_configure_pwm_state(pwm,
QPNP_PWM_DISABLE);
- else
- rc = qpnp_lpg_configure_lut_state(pwm,
- QPNP_LUT_DISABLE);
+ } else if (!(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) {
+ rc = qpnp_lpg_configure_lut_state(pwm,
+ QPNP_LUT_DISABLE);
+ }
}
spin_unlock_irqrestore(&pwm->chip->lpg_lock, flags);
@@ -1435,6 +1516,11 @@
if (pwm->chip == NULL)
return -ENODEV;
+ if (pwm->chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED) {
+ pr_err("LUT mode isn't supported\n");
+ return -EINVAL;
+ }
+
if (!pwm->pwm_config.in_use) {
pr_err("channel_id: %d: stale handle?\n",
pwm->pwm_config.channel_id);
@@ -1588,7 +1674,7 @@
static int qpnp_parse_dt_config(struct spmi_device *spmi,
struct qpnp_lpg_chip *chip)
{
- int rc, enable;
+ int rc, enable, lut_entry_size;
const char *lable;
struct resource *res;
struct device_node *node;
@@ -1599,6 +1685,14 @@
struct qpnp_lpg_config *lpg_config = &chip->lpg_config;
struct qpnp_lut_config *lut_config = &lpg_config->lut_config;
+ rc = of_property_read_u32(of_node, "qcom,channel-id",
+ &pwm_dev->pwm_config.channel_id);
+ if (rc) {
+ dev_err(&spmi->dev, "%s: node is missing LPG channel id\n",
+ __func__);
+ goto out;
+ }
+
res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
QPNP_LPG_CHANNEL_BASE);
if (!res) {
@@ -1612,28 +1706,27 @@
res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
QPNP_LPG_LUT_BASE);
if (!res) {
- dev_err(&spmi->dev, "%s: node is missing LUT base address\n",
- __func__);
- return -EINVAL;
- }
+ chip->flags |= QPNP_PWM_LUT_NOT_SUPPORTED;
+ } else {
+ lpg_config->lut_base_addr = res->start;
+ /* Each entry of LUT is of 2 bytes for generic LUT and of 1 byte
+ * for KPDBL/GLED LUT.
+ */
+ lpg_config->lut_size = resource_size(res) >> 1;
+ lut_entry_size = sizeof(u16);
- lpg_config->lut_base_addr = res->start;
- /* Each entry of LUT is of 2 bytes */
- lpg_config->lut_size = resource_size(res) >> 1;
+ if (qpnp_check_gpled_lpg_channel(
+ pwm_dev->pwm_config.channel_id)) {
+ lpg_config->lut_size = resource_size(res);
+ lut_entry_size = sizeof(u8);
+ }
- lut_config->duty_pct_list = kzalloc(lpg_config->lut_size *
- sizeof(u16), GFP_KERNEL);
- if (!lut_config->duty_pct_list) {
- pr_err("can not allocate duty pct list\n");
- return -ENOMEM;
- }
-
- rc = of_property_read_u32(of_node, "qcom,channel-id",
- &pwm_dev->pwm_config.channel_id);
- if (rc) {
- dev_err(&spmi->dev, "%s: node is missing LPG channel id\n",
- __func__);
- goto out;
+ lut_config->duty_pct_list = kzalloc(lpg_config->lut_size *
+ lut_entry_size, GFP_KERNEL);
+ if (!lut_config->duty_pct_list) {
+ pr_err("can not allocate duty pct list\n");
+ return -ENOMEM;
+ }
}
for_each_child_of_node(of_node, node) {
@@ -1648,7 +1741,8 @@
if (rc)
goto out;
found_pwm_subnode = 1;
- } else if (!strncmp(lable, "lpg", 3)) {
+ } else if (!strncmp(lable, "lpg", 3) &&
+ !(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) {
qpnp_parse_lpg_dt_config(node, of_node, chip);
if (rc)
goto out;
@@ -1722,6 +1816,11 @@
goto failed_insert;
}
+ spmi_ext_register_readl(chip->spmi_dev->ctrl,
+ chip->spmi_dev->sid,
+ chip->lpg_config.base_addr + SPMI_LPG_SUB_TYPE_OFFSET,
+ &chip->sub_type, 1);
+
rc = radix_tree_insert(&lpg_dev_tree, id, chip);
if (rc) {
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 6412fc0..d6af279 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -53,6 +53,7 @@
#define IRQ_EN (0x1c)
#define AHB_MASTER_ERR_CTRLS (0x24)
#define AHB_MASTER_ERR_ADDR (0x28)
+#define AHB_MASTER_ERR_ADDR_MSB (0x104)
#define AHB_MASTER_ERR_DATA (0x2c)
#define TRUST_REG (0x70)
#define TEST_BUS_SEL (0x74)
@@ -61,6 +62,7 @@
#define IRQ_SRCS_EE(n) (0x800 + 128 * (n))
#define IRQ_SRCS_MSK_EE(n) (0x804 + 128 * (n))
#define IRQ_SRCS_UNMASKED_EE(n) (0x808 + 128 * (n))
+#define PIPE_ATTR_EE(n) (0x80c + 128 * (n))
#define P_CTRL(n) (0x1000 + 4096 * (n))
#define P_RST(n) (0x1004 + 4096 * (n))
@@ -74,10 +76,13 @@
#define P_CNSMR_SDBND(n) (0x1028 + 4096 * (n))
#define P_TRUST_REG(n) (0x1030 + 4096 * (n))
#define P_EVNT_DEST_ADDR(n) (0x182c + 4096 * (n))
+#define P_EVNT_DEST_ADDR_MSB(n) (0x1934 + 4096 * (n))
#define P_EVNT_REG(n) (0x1818 + 4096 * (n))
#define P_SW_OFSTS(n) (0x1800 + 4096 * (n))
#define P_DATA_FIFO_ADDR(n) (0x1824 + 4096 * (n))
+#define P_DATA_FIFO_ADDR_MSB(n) (0x1924 + 4096 * (n))
#define P_DESC_FIFO_ADDR(n) (0x181c + 4096 * (n))
+#define P_DESC_FIFO_ADDR_MSB(n) (0x1914 + 4096 * (n))
#define P_EVNT_GEN_TRSHLD(n) (0x1828 + 4096 * (n))
#define P_FIFO_SIZES(n) (0x1820 + 4096 * (n))
#define P_RETR_CNTXT(n) (0x1834 + 4096 * (n))
@@ -86,6 +91,7 @@
#define P_AU_PSM_CNTXT_1(n) (0x1804 + 4096 * (n))
#define P_PSM_CNTXT_2(n) (0x1808 + 4096 * (n))
#define P_PSM_CNTXT_3(n) (0x180c + 4096 * (n))
+#define P_PSM_CNTXT_3_MSB(n) (0x1904 + 4096 * (n))
#define P_PSM_CNTXT_4(n) (0x1810 + 4096 * (n))
#define P_PSM_CNTXT_5(n) (0x1814 + 4096 * (n))
@@ -95,6 +101,7 @@
*
*/
/* CTRL */
+#define BAM_MESS_ONLY_CANCEL_WB 0x100000
#define CACHE_MISS_ERR_RESP_EN 0x80000
#define LOCAL_CLK_GATING 0x60000
#define IBC_DISABLE 0x10000
@@ -115,7 +122,7 @@
#define BAM_SECURED 0x10000
#define BAM_USE_VMIDMT 0x8000
#define BAM_AXI_ACTIVE 0x4000
-#define BAM_CE_BUFFER_SIZE 0x2000
+#define BAM_CE_BUFFER_SIZE 0x3000
#define BAM_NUM_EES 0xf00
#define BAM_REVISION 0xff
@@ -127,6 +134,7 @@
/* NUM_PIPES */
#define BAM_NON_PIPE_GRP 0xff000000
#define BAM_PERIPH_NON_PIPE_GRP 0xff0000
+#define BAM_DATA_ADDR_BUS_WIDTH 0xC000
#define BAM_NUM_PIPES 0xff
/* TIMER */
@@ -188,6 +196,7 @@
#define BAM_TESTBUS_SEL 0x7f
/* CNFG_BITS */
+#define CNFG_BITS_AOS_OVERFLOW_PRVNT 0x80000000
#define CNFG_BITS_MULTIPLE_EVENTS_DESC_AVAIL_EN 0x40000000
#define CNFG_BITS_MULTIPLE_EVENTS_SIZE_EN 0x20000000
#define CNFG_BITS_BAM_ZLT_W_CD_SUPPORT 0x10000000
@@ -210,6 +219,10 @@
#define CNFG_BITS_BAM_FULL_PIPE 0x800
#define CNFG_BITS_BAM_PIPE_CNFG 0x4
+/* PIPE_ATTR_EEn*/
+#define BAM_ENABLED 0x80000000
+#define P_ATTR 0x7fffffff
+
/* P_ctrln */
#define P_LOCK_GROUP 0x1f0000
#define P_WRITE_NWD 0x800
@@ -234,6 +247,8 @@
#define BAM_P_EE 0x7
/* P_IRQ_STTSn */
+#define P_IRQ_STTS_P_HRESP_ERR_IRQ 0x80
+#define P_IRQ_STTS_P_PIPE_RST_ERR_IRQ 0x40
#define P_IRQ_STTS_P_TRNSFR_END_IRQ 0x20
#define P_IRQ_STTS_P_ERR_IRQ 0x10
#define P_IRQ_STTS_P_OUT_OF_DESC_IRQ 0x8
@@ -242,6 +257,8 @@
#define P_IRQ_STTS_P_PRCSD_DESC_IRQ 0x1
/* P_IRQ_CLRn */
+#define P_IRQ_CLR_P_HRESP_ERR_CLR 0x80
+#define P_IRQ_CLR_P_PIPE_RST_ERR_CLR 0x40
#define P_IRQ_CLR_P_TRNSFR_END_CLR 0x20
#define P_IRQ_CLR_P_ERR_CLR 0x10
#define P_IRQ_CLR_P_OUT_OF_DESC_CLR 0x8
@@ -250,6 +267,8 @@
#define P_IRQ_CLR_P_PRCSD_DESC_CLR 0x1
/* P_IRQ_ENn */
+#define P_IRQ_EN_P_HRESP_ERR_EN 0x80
+#define P_IRQ_EN_P_PIPE_RST_ERR_EN 0x40
#define P_IRQ_EN_P_TRNSFR_END_EN 0x20
#define P_IRQ_EN_P_ERR_EN 0x10
#define P_IRQ_EN_P_OUT_OF_DESC_EN 0x8
@@ -404,6 +423,7 @@
/* NUM_PIPES */
#define BAM_NON_PIPE_GRP 0xff000000
#define BAM_PERIPH_NON_PIPE_GRP 0xff0000
+#define BAM_DATA_ADDR_BUS_WIDTH 0xC000
#define BAM_NUM_PIPES 0xff
/* DESC_CNT_TRSHLD */
@@ -686,8 +706,16 @@
bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 0);
else
bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 1);
-#endif
+ if (enhd_pipe) {
+ if (options & SPS_BAM_CANCEL_WB)
+ bam_write_reg_field(base, CTRL,
+ BAM_MESS_ONLY_CANCEL_WB, 1);
+ else
+ bam_write_reg_field(base, CTRL,
+ BAM_MESS_ONLY_CANCEL_WB, 0);
+ }
+#endif
bam_write_reg(base, DESC_CNT_TRSHLD, summing_threshold);
bam_write_reg(base, CNFG_BITS, cfg_bits);
@@ -786,18 +814,43 @@
return 0;
}
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+static inline u32 bam_get_pipe_attr(void *base, u32 ee, bool global)
+{
+ u32 val;
+
+ if (global)
+ val = bam_read_reg_field(base, PIPE_ATTR_EE(ee), BAM_ENABLED);
+ else
+ val = bam_read_reg_field(base, PIPE_ATTR_EE(ee), P_ATTR);
+
+ return val;
+}
+#else
+static inline u32 bam_get_pipe_attr(void *base, u32 ee, bool global)
+{
+ return 0;
+}
+#endif
+
/**
* Verify that a BAM device is enabled and gathers the hardware
* configuration.
*
*/
-int bam_check(void *base, u32 *version, u32 *num_pipes)
+int bam_check(void *base, u32 *version, u32 ee, u32 *num_pipes)
{
u32 ver = 0;
+ u32 enabled = 0;
SPS_DBG2("sps:%s:bam=0x%x(va).", __func__, (u32) base);
- if (!bam_read_reg_field(base, CTRL, BAM_EN)) {
+ if (!enhd_pipe)
+ enabled = bam_read_reg_field(base, CTRL, BAM_EN);
+ else
+ enabled = bam_get_pipe_attr(base, ee, true);
+
+ if (!enabled) {
SPS_ERR("sps:%s:bam 0x%x(va) is not enabled.\n",
__func__, (u32) base);
return -ENODEV;
@@ -843,10 +896,11 @@
* including the TEST_BUS register content under
* different TEST_BUS_SEL values.
*/
-static void bam_output_register_content(void *base)
+void bam_output_register_content(void *base, u32 ee)
{
u32 num_pipes;
u32 i;
+ u32 pipe_attr = 0;
print_bam_test_bus_reg(base, 0);
@@ -857,8 +911,18 @@
SPS_INFO("sps:bam 0x%x(va) has %d pipes.",
(u32) base, num_pipes);
- for (i = 0; i < num_pipes; i++)
- print_bam_pipe_selected_reg(base, i);
+ pipe_attr = enhd_pipe ?
+ bam_get_pipe_attr(base, ee, false) : 0x0;
+
+ if (!enhd_pipe || !pipe_attr)
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_selected_reg(base, i);
+ else {
+ for (i = 0; i < num_pipes; i++) {
+ if (pipe_attr & (1UL << i))
+ print_bam_pipe_selected_reg(base, i);
+ }
+ }
}
/**
@@ -878,13 +942,13 @@
SPS_ERR("sps:bam 0x%x(va);bam irq status="
"0x%x.\nsps: BAM_ERROR_IRQ\n",
(u32) base, status);
- bam_output_register_content(base);
+ bam_output_register_content(base, ee);
*cb_case = SPS_CALLBACK_BAM_ERROR_IRQ;
} else if (status & IRQ_STTS_BAM_HRESP_ERR_IRQ) {
SPS_ERR("sps:bam 0x%x(va);bam irq status="
"0x%x.\nsps: BAM_HRESP_ERR_IRQ\n",
(u32) base, status);
- bam_output_register_content(base);
+ bam_output_register_content(base, ee);
*cb_case = SPS_CALLBACK_BAM_HRESP_ERR_IRQ;
#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
} else if (status & IRQ_STTS_BAM_TIMER_IRQ) {
@@ -926,7 +990,8 @@
bam_write_reg(base, P_EVNT_GEN_TRSHLD(pipe), param->event_threshold);
- bam_write_reg(base, P_DESC_FIFO_ADDR(pipe), param->desc_base);
+ bam_write_reg(base, P_DESC_FIFO_ADDR(pipe),
+ SPS_GET_LOWER_ADDR(param->desc_base));
bam_write_reg_field(base, P_FIFO_SIZES(pipe), P_DESC_FIFO_SIZE,
param->desc_size);
@@ -934,6 +999,10 @@
param->stream_mode);
#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ if (SPS_LPAE)
+ bam_write_reg(base, P_DESC_FIFO_ADDR_MSB(pipe),
+ SPS_GET_UPPER_ADDR(param->desc_base));
+
bam_write_reg_field(base, P_CTRL(pipe), P_LOCK_GROUP,
param->lock_group);
@@ -946,7 +1015,7 @@
P_EVNT_REG(param->peer_pipe);
bam_write_reg(base, P_DATA_FIFO_ADDR(pipe),
- param->data_base);
+ SPS_GET_LOWER_ADDR(param->data_base));
bam_write_reg_field(base, P_FIFO_SIZES(pipe),
P_DATA_FIFO_SIZE, param->data_size);
@@ -959,6 +1028,12 @@
param->peer_pipe);
#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ if (SPS_LPAE) {
+ bam_write_reg(base, P_EVNT_DEST_ADDR_MSB(pipe), 0x0);
+ bam_write_reg(base, P_DATA_FIFO_ADDR_MSB(pipe),
+ SPS_GET_UPPER_ADDR(param->data_base));
+ }
+
bam_write_reg_field(base, P_CTRL(pipe), P_WRITE_NWD,
param->write_nwd);
@@ -1033,6 +1108,24 @@
u32 src_mask, u32 ee)
{
SPS_DBG2("sps:%s:bam=0x%x(va).pipe=%d.", __func__, (u32) base, pipe);
+ if (src_mask & BAM_PIPE_IRQ_RST_ERROR) {
+ if (enhd_pipe)
+ bam_write_reg_field(base, IRQ_EN,
+ IRQ_EN_BAM_ERROR_EN, 0);
+ else {
+ src_mask &= ~BAM_PIPE_IRQ_RST_ERROR;
+ SPS_DBG2("sps: SPS_O_RST_ERROR is not supported\n");
+ }
+ }
+ if (src_mask & BAM_PIPE_IRQ_HRESP_ERROR) {
+ if (enhd_pipe)
+ bam_write_reg_field(base, IRQ_EN,
+ IRQ_EN_BAM_HRESP_ERR_EN, 0);
+ else {
+ src_mask &= ~BAM_PIPE_IRQ_HRESP_ERROR;
+ SPS_DBG2("sps: SPS_O_HRESP_ERROR is not supported\n");
+ }
+ }
bam_write_reg(base, P_IRQ_EN(pipe), src_mask);
bam_write_reg_field(base, IRQ_SRCS_MSK_EE(ee), (1 << pipe), irq_en);
@@ -1294,6 +1387,7 @@
u32 bam_num_pipes;
u32 bam_pipe_num;
+ u32 bam_data_addr_bus_width;
u32 bam_desc_cnt_trshld;
u32 bam_desc_cnt_trd_val;
@@ -1304,6 +1398,7 @@
u32 bam_irq_src_ee = 0;
u32 bam_irq_msk_ee = 0;
u32 bam_irq_unmsk_ee = 0;
+ u32 bam_pipe_attr_ee = 0;
u32 bam_ahb_err_ctrl;
u32 bam_ahb_err_addr;
@@ -1313,6 +1408,7 @@
u32 bam_sw_rev = 0;
u32 bam_timer = 0;
u32 bam_timer_ctrl = 0;
+ u32 bam_ahb_err_addr_msb = 0;
if (base == NULL)
return;
@@ -1324,6 +1420,8 @@
bam_num_pipes = bam_read_reg(base, NUM_PIPES);
bam_pipe_num = bam_read_reg_field(base, NUM_PIPES, BAM_NUM_PIPES);
+ bam_data_addr_bus_width = bam_read_reg_field(base, NUM_PIPES,
+ BAM_DATA_ADDR_BUS_WIDTH);
bam_desc_cnt_trshld = bam_read_reg(base, DESC_CNT_TRSHLD);
bam_desc_cnt_trd_val = bam_read_reg_field(base, DESC_CNT_TRSHLD,
@@ -1347,6 +1445,11 @@
bam_sw_rev = bam_read_reg(base, SW_REVISION);
bam_timer = bam_read_reg(base, TIMER);
bam_timer_ctrl = bam_read_reg(base, TIMER_CTRL);
+ bam_ahb_err_addr_msb = SPS_LPAE ?
+ bam_read_reg(base, AHB_MASTER_ERR_ADDR_MSB) : 0;
+ if (ee < BAM_MAX_EES)
+ bam_pipe_attr_ee = enhd_pipe ?
+ bam_read_reg(base, PIPE_ATTR_EE(ee)) : 0x0;
#endif
@@ -1358,6 +1461,8 @@
SPS_INFO(" NUM_EES: %d\n", bam_rev_ee_num);
SPS_INFO("BAM_SW_REVISION: 0x%x\n", bam_sw_rev);
SPS_INFO("BAM_NUM_PIPES: %d\n", bam_num_pipes);
+ SPS_INFO("BAM_DATA_ADDR_BUS_WIDTH: %d\n",
+ ((bam_data_addr_bus_width == 0x0) ? 32 : 36));
SPS_INFO(" NUM_PIPES: %d\n", bam_pipe_num);
SPS_INFO("BAM_DESC_CNT_TRSHLD: 0x%x\n", bam_desc_cnt_trshld);
SPS_INFO(" DESC_CNT_TRSHLD: 0x%x (%d)\n", bam_desc_cnt_trd_val,
@@ -1371,10 +1476,12 @@
SPS_INFO("BAM_IRQ_SRCS_MSK_EE(%d): 0x%x\n", ee, bam_irq_msk_ee);
SPS_INFO("BAM_IRQ_SRCS_UNMASKED_EE(%d): 0x%x\n", ee,
bam_irq_unmsk_ee);
+ SPS_INFO("BAM_PIPE_ATTR_EE(%d): 0x%x\n", ee, bam_pipe_attr_ee);
}
SPS_INFO("BAM_AHB_MASTER_ERR_CTRLS: 0x%x\n", bam_ahb_err_ctrl);
SPS_INFO("BAM_AHB_MASTER_ERR_ADDR: 0x%x\n", bam_ahb_err_addr);
+ SPS_INFO("BAM_AHB_MASTER_ERR_ADDR_MSB: 0x%x\n", bam_ahb_err_addr_msb);
SPS_INFO("BAM_AHB_MASTER_ERR_DATA: 0x%x\n", bam_ahb_err_data);
SPS_INFO("BAM_CNFG_BITS: 0x%x\n", bam_cnfg_bits);
@@ -1421,9 +1528,12 @@
u32 p_write_pointer;
u32 p_evnt_dest;
+ u32 p_evnt_dest_msb = 0;
u32 p_desc_fifo_addr;
+ u32 p_desc_fifo_addr_msb = 0;
u32 p_desc_fifo_size;
u32 p_data_fifo_addr;
+ u32 p_data_fifo_addr_msb = 0;
u32 p_data_fifo_size;
u32 p_fifo_sizes;
@@ -1439,6 +1549,7 @@
u32 p_au_ct1;
u32 p_psm_ct2;
u32 p_psm_ct3;
+ u32 p_psm_ct3_msb = 0;
u32 p_psm_ct4;
u32 p_psm_ct5;
@@ -1520,6 +1631,15 @@
p_timer_ctrl = bam_read_reg(base, P_TIMER_CTRL(pipe));
#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ p_evnt_dest_msb = SPS_LPAE ?
+ bam_read_reg(base, P_EVNT_DEST_ADDR_MSB(pipe)) : 0;
+
+ p_desc_fifo_addr_msb = SPS_LPAE ?
+ bam_read_reg(base, P_DESC_FIFO_ADDR_MSB(pipe)) : 0;
+ p_data_fifo_addr_msb = SPS_LPAE ?
+ bam_read_reg(base, P_DATA_FIFO_ADDR_MSB(pipe)) : 0;
+
+ p_psm_ct3_msb = SPS_LPAE ? bam_read_reg(base, P_PSM_CNTXT_3(pipe)) : 0;
p_lock_group = bam_read_reg_field(base, P_CTRL(pipe), P_LOCK_GROUP);
p_df_ct = bam_read_reg(base, P_DF_CNTXT(pipe));
p_df_offset = bam_read_reg_field(base, P_DF_CNTXT(pipe),
@@ -1568,7 +1688,9 @@
SPS_INFO(" DF_OFFSET: 0x%x\n", p_df_offset);
SPS_INFO("BAM_P_DESC_FIFO_ADDR: 0x%x\n", p_desc_fifo_addr);
+ SPS_INFO("BAM_P_DESC_FIFO_ADDR_MSB: 0x%x\n", p_desc_fifo_addr_msb);
SPS_INFO("BAM_P_DATA_FIFO_ADDR: 0x%x\n", p_data_fifo_addr);
+ SPS_INFO("BAM_P_DATA_FIFO_ADDR_MSB: 0x%x\n", p_data_fifo_addr_msb);
SPS_INFO("BAM_P_FIFO_SIZES: 0x%x\n", p_fifo_sizes);
SPS_INFO(" DESC_FIFO_SIZE: 0x%x (%d)\n", p_desc_fifo_size,
p_desc_fifo_size);
@@ -1576,6 +1698,7 @@
p_data_fifo_size);
SPS_INFO("BAM_P_EVNT_DEST_ADDR: 0x%x\n", p_evnt_dest);
+ SPS_INFO("BAM_P_EVNT_DEST_ADDR_MSB: 0x%x\n", p_evnt_dest_msb);
SPS_INFO("BAM_P_EVNT_GEN_TRSHLD: 0x%x\n", p_evnt_trd);
SPS_INFO(" EVNT_GEN_TRSHLD: 0x%x (%d)\n", p_evnt_trd_val,
p_evnt_trd_val);
@@ -1583,6 +1706,7 @@
SPS_INFO("BAM_P_AU_PSM_CNTXT_1: 0x%x\n", p_au_ct1);
SPS_INFO("BAM_P_PSM_CNTXT_2: 0x%x\n", p_psm_ct2);
SPS_INFO("BAM_P_PSM_CNTXT_3: 0x%x\n", p_psm_ct3);
+ SPS_INFO("BAM_P_PSM_CNTXT_3_MSB: 0x%x\n", p_psm_ct3_msb);
SPS_INFO("BAM_P_PSM_CNTXT_4: 0x%x\n", p_psm_ct4);
SPS_INFO("BAM_P_PSM_CNTXT_5: 0x%x\n", p_psm_ct5);
SPS_INFO("BAM_P_TIMER: 0x%x\n", p_timer);
diff --git a/drivers/platform/msm/sps/bam.h b/drivers/platform/msm/sps/bam.h
index 2a7f05b..d34a7d3 100644
--- a/drivers/platform/msm/sps/bam.h
+++ b/drivers/platform/msm/sps/bam.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, 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
@@ -72,7 +72,7 @@
enum bam_pipe_dir dir;
enum bam_pipe_mode mode;
enum bam_write_nwd write_nwd;
- u32 desc_base; /* Physical address of descriptor FIFO */
+ phys_addr_t desc_base; /* Physical address of descriptor FIFO */
u32 desc_size; /* Size (bytes) of descriptor FIFO */
u32 lock_group; /* The lock group this pipe belongs to */
enum bam_stream_mode stream_mode;
@@ -81,7 +81,7 @@
/* The following are only valid if mode is BAM2BAM */
u32 peer_phys_addr;
u32 peer_pipe;
- u32 data_base; /* Physical address of data FIFO */
+ phys_addr_t data_base; /* Physical address of data FIFO */
u32 data_size; /* Size (bytes) of data FIFO */
};
@@ -139,12 +139,14 @@
*
* @version - return BAM hardware version
*
+ * @ee - BAM execution environment index
+ *
* @num_pipes - return number of pipes
*
* @return 0 on success, negative value on error
*
*/
-int bam_check(void *base, u32 *version, u32 *num_pipes);
+int bam_check(void *base, u32 *version, u32 ee, u32 *num_pipes);
/**
* Disable a BAM device
@@ -159,6 +161,17 @@
void bam_exit(void *base, u32 ee);
/**
+ * This function prints BAM register content
+ * including TEST_BUS and PIPE register content.
+ *
+ * @base - BAM virtual base address.
+ *
+ * @ee - BAM execution environment index
+ */
+void bam_output_register_content(void *base, u32 ee);
+
+
+/**
* Get BAM IRQ source and clear global IRQ status
*
* This function gets BAM IRQ source.
@@ -178,6 +191,7 @@
u32 bam_check_irq_source(void *base, u32 ee, u32 mask,
enum sps_callback_case *cb_case);
+
/**
* Initialize a BAM pipe
*
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 2e77114..6ccfd29 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -80,6 +80,7 @@
static struct sps_drv *sps;
u32 d_type;
+bool enhd_pipe;
static void sps_device_de_init(void);
@@ -1610,7 +1611,7 @@
* Perform a single DMA transfer on an SPS connection end point
*
*/
-int sps_transfer_one(struct sps_pipe *h, u32 addr, u32 size,
+int sps_transfer_one(struct sps_pipe *h, phys_addr_t addr, u32 size,
void *user, u32 flags)
{
struct sps_pipe *pipe = h;
@@ -1632,7 +1633,8 @@
return SPS_ERROR;
result = sps_bam_pipe_transfer_one(bam, pipe->pipe_index,
- addr, size, user, flags);
+ SPS_GET_LOWER_ADDR(addr), size, user,
+ DESC_FLAG_WORD(flags, addr));
sps_bam_unlock(bam);
@@ -2454,6 +2456,11 @@
} else
SPS_DBG("sps:device type is %d.", d_type);
+ enhd_pipe = of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,pipe-attr-ee");
+ SPS_DBG2("sps:PIPE_ATTR_EE is %s supported.\n",
+ (enhd_pipe ? "" : "not"));
+
return 0;
}
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 80056f5..d972e7b 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -76,7 +76,9 @@
{SPS_EVENT_INACTIVE, SPS_O_INACTIVE, BAM_PIPE_IRQ_TIMER},
{SPS_EVENT_OUT_OF_DESC, SPS_O_OUT_OF_DESC,
BAM_PIPE_IRQ_OUT_OF_DESC},
- {SPS_EVENT_ERROR, SPS_O_ERROR, BAM_PIPE_IRQ_ERROR}
+ {SPS_EVENT_ERROR, SPS_O_ERROR, BAM_PIPE_IRQ_ERROR},
+ {SPS_EVENT_RST_ERROR, SPS_O_RST_ERROR, BAM_PIPE_IRQ_RST_ERROR},
+ {SPS_EVENT_HRESP_ERROR, SPS_O_HRESP_ERROR, BAM_PIPE_IRQ_HRESP_ERROR}
};
/* Pipe event source handler */
@@ -260,7 +262,8 @@
dev->props.options);
else
/* No, so just verify that it is enabled */
- rc = bam_check(dev->base, &dev->version, &num_pipes);
+ rc = bam_check(dev->base, &dev->version,
+ dev->props.ee, &num_pipes);
if (rc) {
SPS_ERR("sps:Fail to init BAM 0x%x IRQ %d\n",
@@ -1283,14 +1286,19 @@
desc->addr = addr;
desc->size = size;
+
if ((flags & SPS_IOVEC_FLAG_DEFAULT) == 0) {
- desc->flags = flags & BAM_IOVEC_FLAG_MASK;
+ desc->flags = (flags & BAM_IOVEC_FLAG_MASK)
+ | DESC_UPPER_ADDR(flags);
} else {
if (pipe->mode == SPS_MODE_SRC)
- desc->flags = SPS_IOVEC_FLAG_INT;
+ desc->flags = SPS_IOVEC_FLAG_INT
+ | DESC_UPPER_ADDR(flags);
else
- desc->flags = SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT;
+ desc->flags = (SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT)
+ | DESC_UPPER_ADDR(flags);
}
+
#ifdef SPS_BAM_STATISTICS
if ((flags & SPS_IOVEC_FLAG_INT))
pipe->sys.int_flags++;
@@ -1763,6 +1771,30 @@
return;
}
+ if ((status & SPS_O_RST_ERROR) && enhd_pipe) {
+ SPS_ERR("sps:bam 0x%x ;pipe 0x%x irq status=0x%x.\n"
+ "sps: BAM_PIPE_IRQ_RST_ERROR\n",
+ BAM_ID(dev), pipe_index, status);
+ bam_output_register_content(dev->base, dev->props.ee);
+ pipe_handler_generic(dev, pipe,
+ SPS_EVENT_RST_ERROR);
+ status &= ~SPS_O_RST_ERROR;
+ if (status == 0)
+ return;
+ }
+
+ if ((status & SPS_O_HRESP_ERROR) && enhd_pipe) {
+ SPS_ERR("sps:bam 0x%x ;pipe 0x%x irq status=0x%x.\n"
+ "sps: BAM_PIPE_IRQ_HRESP_ERROR\n",
+ BAM_ID(dev), pipe_index, status);
+ bam_output_register_content(dev->base, dev->props.ee);
+ pipe_handler_generic(dev, pipe,
+ SPS_EVENT_HRESP_ERROR);
+ status &= ~SPS_O_HRESP_ERROR;
+ if (status == 0)
+ return;
+ }
+
if ((status & SPS_EVENT_ERROR))
pipe_handler_generic(dev, pipe, SPS_EVENT_ERROR);
}
diff --git a/drivers/platform/msm/sps/sps_bam.h b/drivers/platform/msm/sps/sps_bam.h
index dede487..da5dafd 100644
--- a/drivers/platform/msm/sps/sps_bam.h
+++ b/drivers/platform/msm/sps/sps_bam.h
@@ -50,6 +50,10 @@
BAM_PIPE_IRQ_ERROR = 0x00000010,
/* End-Of-Transfer */
BAM_PIPE_IRQ_EOT = 0x00000020,
+ /* Pipe RESET unsuccessful */
+ BAM_PIPE_IRQ_RST_ERROR = 0x00000040,
+ /* Errorneous Hresponse by AHB MASTER */
+ BAM_PIPE_IRQ_HRESP_ERROR = 0x00000080,
};
/* Halt Type */
diff --git a/drivers/platform/msm/sps/sps_map.c b/drivers/platform/msm/sps/sps_map.c
index d007b31..70735c3 100644
--- a/drivers/platform/msm/sps/sps_map.c
+++ b/drivers/platform/msm/sps/sps_map.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, 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
@@ -96,16 +96,16 @@
*/
desc = spsi_get_mem_ptr(map->desc_base);
if (desc == NULL) {
- SPS_ERR("sps:Cannot get virt addr for I/O buffer: 0x%x",
- map->desc_base);
+ SPS_ERR("sps:Cannot get virt addr for I/O buffer: %pa\n",
+ &map->desc_base);
return SPS_ERROR;
}
if (map->data_size > 0 && map->data_base != SPS_ADDR_INVALID) {
data = spsi_get_mem_ptr(map->data_base);
if (data == NULL) {
- SPS_ERR("sps:Can't get virt addr for I/O buffer: 0x%x",
- map->data_base);
+ SPS_ERR("sps:Can't get virt addr for I/O buffer: %pa",
+ &map->data_base);
return SPS_ERROR;
}
} else {
diff --git a/drivers/platform/msm/sps/sps_map.h b/drivers/platform/msm/sps/sps_map.h
index 7db8043..7ee4713 100644
--- a/drivers/platform/msm/sps/sps_map.h
+++ b/drivers/platform/msm/sps/sps_map.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
@@ -36,9 +36,9 @@
/* Resource parameters */
u32 config; /* Configuration (stream) identifier */
- u32 desc_base; /* Physical address of descriptor FIFO */
+ phys_addr_t desc_base; /* Physical address of descriptor FIFO */
u32 desc_size; /* Size (bytes) of descriptor FIFO */
- u32 data_base; /* Physical address of data FIFO */
+ phys_addr_t data_base; /* Physical address of data FIFO */
u32 data_size; /* Size (bytes) of data FIFO */
};
diff --git a/drivers/platform/msm/sps/sps_mem.c b/drivers/platform/msm/sps/sps_mem.c
index b44e3c4..faa1618 100644
--- a/drivers/platform/msm/sps/sps_mem.c
+++ b/drivers/platform/msm/sps/sps_mem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, 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
@@ -25,7 +25,7 @@
#include "sps_bam.h"
#include "spsi.h"
-static u32 iomem_phys;
+static phys_addr_t iomem_phys;
static void *iomem_virt;
static u32 iomem_size;
static u32 iomem_offset;
@@ -40,7 +40,7 @@
* Translate physical to virtual address
*
*/
-void *spsi_get_mem_ptr(u32 phys_addr)
+void *spsi_get_mem_ptr(phys_addr_t phys_addr)
{
void *virt = NULL;
@@ -49,8 +49,8 @@
virt = (u8 *) iomem_virt + (phys_addr - iomem_phys);
} else {
virt = phys_to_virt(phys_addr);
- SPS_ERR("sps:spsi_get_mem_ptr.invalid phys addr=0x%x.",
- phys_addr);
+ SPS_ERR("sps:spsi_get_mem_ptr.invalid phys addr=0x%pa.",
+ &phys_addr);
}
return virt;
}
@@ -59,9 +59,9 @@
* Allocate I/O (pipe) memory
*
*/
-u32 sps_mem_alloc_io(u32 bytes)
+phys_addr_t sps_mem_alloc_io(u32 bytes)
{
- u32 phys_addr = SPS_ADDR_INVALID;
+ phys_addr_t phys_addr = SPS_ADDR_INVALID;
u32 virt_addr = 0;
virt_addr = gen_pool_alloc(pool, bytes);
@@ -74,8 +74,8 @@
return SPS_ADDR_INVALID;
}
- SPS_DBG2("sps:sps_mem_alloc_io.phys=0x%x.virt=0x%x.size=0x%x.",
- phys_addr, virt_addr, bytes);
+ SPS_DBG2("sps:sps_mem_alloc_io.phys=%pa.virt=0x%x.size=0x%x.",
+ &phys_addr, virt_addr, bytes);
return phys_addr;
}
@@ -84,15 +84,15 @@
* Free I/O memory
*
*/
-void sps_mem_free_io(u32 phys_addr, u32 bytes)
+void sps_mem_free_io(phys_addr_t phys_addr, u32 bytes)
{
u32 virt_addr = 0;
iomem_offset = phys_addr - iomem_phys;
virt_addr = (u32) iomem_virt + iomem_offset;
- SPS_DBG2("sps:sps_mem_free_io.phys=0x%x.virt=0x%x.size=0x%x.",
- phys_addr, virt_addr, bytes);
+ SPS_DBG2("sps:sps_mem_free_io.phys=%pa.virt=0x%x.size=0x%x.",
+ &phys_addr, virt_addr, bytes);
gen_pool_free(pool, virt_addr, bytes);
total_free += bytes;
@@ -102,7 +102,7 @@
* Initialize driver memory module
*
*/
-int sps_mem_init(u32 pipemem_phys_base, u32 pipemem_size)
+int sps_mem_init(phys_addr_t pipemem_phys_base, u32 pipemem_size)
{
int res;
@@ -125,8 +125,8 @@
}
iomem_offset = 0;
- SPS_DBG("sps:sps_mem_init.iomem_phys=0x%x,iomem_virt=0x%x.",
- iomem_phys, (u32) iomem_virt);
+ SPS_DBG("sps:sps_mem_init.iomem_phys=%pa,iomem_virt=0x%x.",
+ &iomem_phys, (u32) iomem_virt);
}
pool = gen_pool_create(min_alloc_order, nid);
diff --git a/drivers/platform/msm/sps/sps_rm.c b/drivers/platform/msm/sps/sps_rm.c
index 2b46203..7d7e1a6 100644
--- a/drivers/platform/msm/sps/sps_rm.c
+++ b/drivers/platform/msm/sps/sps_rm.c
@@ -499,8 +499,8 @@
map->desc.phys_base = map->alloc_desc_base;
map->desc.base = spsi_get_mem_ptr(map->desc.phys_base);
if (map->desc.base == NULL) {
- SPS_ERR("sps:Cannot get virt addr for I/O buffer:0x%x",
- map->desc.phys_base);
+ SPS_ERR("sps:Cannot get virt addr for I/O buffer:%pa",
+ &map->desc.phys_base);
goto exit_err;
}
}
@@ -516,8 +516,8 @@
map->data.phys_base = map->alloc_data_base;
map->data.base = spsi_get_mem_ptr(map->data.phys_base);
if (map->data.base == NULL) {
- SPS_ERR("sps:Cannot get virt addr for I/O buffer:0x%x",
- map->data.phys_base);
+ SPS_ERR("sps:Cannot get virt addr for I/O buffer:%pa",
+ &map->data.phys_base);
goto exit_err;
}
}
diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h
index 8da3b40..f65fef7 100644
--- a/drivers/platform/msm/sps/spsi.h
+++ b/drivers/platform/msm/sps/spsi.h
@@ -27,6 +27,12 @@
#include "sps_map.h"
+#ifdef CONFIG_ARM_LPAE
+#define SPS_LPAE (true)
+#else
+#define SPS_LPAE (false)
+#endif
+
#define BAM_MAX_PIPES 31
#define BAM_MAX_P_LOCK_GROUP_NUM 31
@@ -43,6 +49,7 @@
#define MAX_MSG_LEN 80
extern u32 d_type;
+extern bool enhd_pipe;
#ifdef CONFIG_DEBUG_FS
extern u8 debugfs_record_enabled;
@@ -165,8 +172,9 @@
/* Dynamically allocated resouces, if required */
u32 alloc_src_pipe; /* Source pipe index */
u32 alloc_dest_pipe; /* Destination pipe index */
- u32 alloc_desc_base; /* Physical address of descriptor FIFO */
- u32 alloc_data_base; /* Physical address of data FIFO */
+ /* Physical address of descriptor FIFO */
+ phys_addr_t alloc_desc_base;
+ phys_addr_t alloc_data_base; /* Physical address of data FIFO */
};
/* Event bookkeeping descriptor struct */
@@ -218,7 +226,7 @@
* @return virtual memory pointer
*
*/
-void *spsi_get_mem_ptr(u32 phys_addr);
+void *spsi_get_mem_ptr(phys_addr_t phys_addr);
/**
* Allocate I/O (pipe) memory
@@ -229,7 +237,7 @@
*
* @return physical address of allocated memory, or SPS_ADDR_INVALID on error
*/
-u32 sps_mem_alloc_io(u32 bytes);
+phys_addr_t sps_mem_alloc_io(u32 bytes);
/**
* Free I/O (pipe) memory
@@ -240,7 +248,7 @@
*
* @bytes - number of bytes to free.
*/
-void sps_mem_free_io(u32 phys_addr, u32 bytes);
+void sps_mem_free_io(phys_addr_t phys_addr, u32 bytes);
/**
* Find matching connection mapping
@@ -324,7 +332,7 @@
* @return 0 on success, negative value on error
*
*/
-int sps_mem_init(u32 pipemem_phys_base, u32 pipemem_size);
+int sps_mem_init(phys_addr_t pipemem_phys_base, u32 pipemem_size);
/**
* De-initialize driver memory module
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 4889a79..7c73a82 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -140,6 +140,7 @@
int bus_suspend;
bool disconnected;
bool in_lpm[MAX_BAMS];
+ bool pending_lpm;
int (*wake_cb)(void *);
void *wake_param;
@@ -634,15 +635,25 @@
static void usb_bam_start_lpm(bool disconnect)
{
struct usb_phy *trans = usb_get_transceiver();
+
BUG_ON(trans == NULL);
- pr_debug("%s: Going to LPM\n", __func__);
+
spin_lock(&usb_bam_ipa_handshake_info_lock);
+
info.lpm_wait_handshake[HSUSB_BAM] = false;
info.lpm_wait_pipes = 0;
+
if (disconnect)
pm_runtime_put_noidle(trans->dev);
- spin_unlock(&usb_bam_ipa_handshake_info_lock);
- pm_runtime_suspend(trans->dev);
+
+ if (info.pending_lpm) {
+ info.pending_lpm = 0;
+ spin_unlock(&usb_bam_ipa_handshake_info_lock);
+ pr_debug("%s: Going to LPM\n", __func__);
+ pm_runtime_suspend(trans->dev);
+ } else
+ spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
}
int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
@@ -1438,6 +1449,7 @@
info.lpm_wait_handshake[HSUSB_BAM] = true;
info.connect_complete = 0;
info.disconnected = 0;
+ info.pending_lpm = 0;
info.lpm_wait_pipes = 1;
info.bus_suspend = 0;
info.cons_stopped = 0;
@@ -1998,8 +2010,18 @@
ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
ipa_rm_resource_cons[cur_bam]);
}
- pr_debug("%s Ended disconnect sequence\n", __func__);
- usb_bam_start_lpm(1);
+
+ if (cur_bam == HSUSB_BAM) {
+ /*
+ * Currently we have for HSUSB BAM only one consumer
+ * pipe. Therefore ending disconnect sequence and
+ * starting hsusb lpm. This limitation will be changed
+ * in future patch.
+ */
+ pr_debug("%s Ended disconnect sequence\n", __func__);
+ usb_bam_start_lpm(1);
+ }
+
mutex_unlock(&info.suspend_resume_mutex);
return 0;
}
@@ -2138,6 +2160,7 @@
u8 i = 0;
bool reset_bam;
enum usb_bam bam;
+ u32 addr;
ctx.max_connections = 0;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -2154,9 +2177,11 @@
}
rc = of_property_read_u32(node, "qcom,usb-bam-fifo-baseaddr",
- &pdata->usb_bam_fifo_baseaddr);
+ &addr);
if (rc)
pr_debug("%s: Invalid usb base address property\n", __func__);
+ else
+ pdata->usb_bam_fifo_baseaddr = addr;
pdata->ignore_core_reset_ack = of_property_read_bool(node,
"qcom,ignore-core-reset-ack");
@@ -2629,10 +2654,12 @@
{
spin_lock(&usb_bam_ipa_handshake_info_lock);
if (info.lpm_wait_handshake[HSUSB_BAM] || info.lpm_wait_pipes) {
+ info.pending_lpm = 1;
spin_unlock(&usb_bam_ipa_handshake_info_lock);
pr_err("%s: Scheduling LPM for later\n", __func__);
return 0;
} else {
+ info.pending_lpm = 0;
info.in_lpm[HSUSB_BAM] = true;
spin_unlock(&usb_bam_ipa_handshake_info_lock);
pr_err("%s: Going to LPM now\n", __func__);
@@ -2641,6 +2668,16 @@
}
EXPORT_SYMBOL(msm_bam_lpm_ok);
+void msm_bam_notify_lpm_resume()
+{
+ /*
+ * If core was resumed from lpm, just clear the
+ * pending indication, in case it is set.
+ */
+ info.pending_lpm = 0;
+}
+EXPORT_SYMBOL(msm_bam_notify_lpm_resume);
+
static int usb_bam_remove(struct platform_device *pdev)
{
destroy_workqueue(ctx.usb_bam_wq);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index a9af974..b518f1f 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -22,8 +22,8 @@
#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/mfd/pm8xxx/ccadc.h>
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
#include <linux/mfd/pm8xxx/batt-alarm.h>
+#include <linux/batterydata-lib.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/debugfs.h>
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 11e6cc1..982c30b 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -147,7 +147,9 @@
POWER_SUPPLY_ATTR(voltage_min_design),
POWER_SUPPLY_ATTR(voltage_now),
POWER_SUPPLY_ATTR(voltage_avg),
+ POWER_SUPPLY_ATTR(input_voltage_regulation),
POWER_SUPPLY_ATTR(current_max),
+ POWER_SUPPLY_ATTR(input_current_max),
POWER_SUPPLY_ATTR(current_now),
POWER_SUPPLY_ATTR(current_avg),
POWER_SUPPLY_ATTR(power_now),
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 08995cc..aac0fa2 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -25,11 +25,11 @@
#include <linux/delay.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/qpnp/power-on.h>
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/of_batterydata.h>
/* BMS Register Offsets */
-#define BMS1_REVISION1 0x0
-#define BMS1_REVISION2 0x1
+#define REVISION1 0x0
+#define REVISION2 0x1
#define BMS1_STATUS1 0x8
#define BMS1_MODE_CTL 0X40
/* Coulomb counter clear registers */
@@ -72,6 +72,8 @@
/* IADC Channel Select */
#define IADC1_BMS_ADC_CH_SEL_CTL 0x48
+#define IADC1_BMS_ADC_INT_RSNSN_CTL 0x49
+#define IADC1_BMS_FAST_AVG_EN 0x5B
/* Configuration for saving of shutdown soc/iavg */
#define IGNORE_SOC_TEMP_DECIDEG 50
@@ -144,6 +146,10 @@
u8 revision1;
u8 revision2;
+
+ u8 iadc_bms_revision1;
+ u8 iadc_bms_revision2;
+
int battery_present;
int battery_status;
bool new_battery;
@@ -2327,7 +2333,7 @@
if (chip->use_voltage_soc) {
soc = calculate_soc_from_voltage(chip);
} else {
- qpnp_iadc_calibrate_for_trim();
+ qpnp_iadc_calibrate_for_trim(true);
rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
if (rc) {
pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
@@ -2990,6 +2996,8 @@
}
}
+#define CALIB_WRKARND_DIG_MAJOR_MAX 0x03
+
static void battery_insertion_check(struct qpnp_bms_chip *chip)
{
bool present = is_battery_present(chip);
@@ -3183,11 +3191,7 @@
return IRQ_HANDLED;
}
-#define PALLADIUM_ID_MIN 0x7F40
-#define PALLADIUM_ID_MAX 0x7F5A
-#define DESAY_5200_ID_MIN 0x7F7F
-#define DESAY_5200_ID_MAX 0x802F
-static int32_t read_battery_id(struct qpnp_bms_chip *chip)
+static int64_t read_battery_id(struct qpnp_bms_chip *chip)
{
int rc;
struct qpnp_vadc_result result;
@@ -3198,16 +3202,16 @@
LR_MUX2_BAT_ID, rc);
return rc;
}
- pr_debug("batt_id phy = %lld meas = 0x%llx\n", result.physical,
- result.measurement);
- pr_debug("raw_code = 0x%x\n", result.adc_code);
- return result.adc_code;
+
+ return result.physical;
}
static int set_battery_data(struct qpnp_bms_chip *chip)
{
int64_t battery_id;
+ int rc;
struct bms_battery_data *batt_data;
+ struct device_node *node;
if (chip->batt_type == BATT_DESAY) {
batt_data = &desay_5200_data;
@@ -3227,12 +3231,30 @@
return battery_id;
}
- if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
- battery_id)) {
- batt_data = &palladium_1500_data;
- } else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
- battery_id)) {
- batt_data = &desay_5200_data;
+ node = of_find_node_by_name(chip->spmi->dev.of_node,
+ "qcom,battery-data");
+ if (node) {
+ batt_data = kzalloc(sizeof(struct bms_battery_data),
+ GFP_KERNEL);
+ batt_data->fcc_temp_lut = kzalloc(
+ sizeof(struct single_row_lut),
+ GFP_KERNEL);
+ batt_data->pc_temp_ocv_lut = kzalloc(
+ sizeof(struct pc_temp_ocv_lut),
+ GFP_KERNEL);
+ batt_data->rbatt_sf_lut = kzalloc(
+ sizeof(struct sf_lut), GFP_KERNEL);
+
+ rc = of_batterydata_read_data(node,
+ batt_data, battery_id);
+ if (rc) {
+ pr_err("battery data load failed, using palladium 1500\n");
+ kfree(batt_data->fcc_temp_lut);
+ kfree(batt_data->pc_temp_ocv_lut);
+ kfree(batt_data->rbatt_sf_lut);
+ kfree(batt_data);
+ batt_data = &palladium_1500_data;
+ }
} else {
pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
battery_id);
@@ -3250,6 +3272,14 @@
chip->rbatt_capacitive_mohm = batt_data->rbatt_capacitive_mohm;
chip->flat_ocv_threshold_uv = batt_data->flat_ocv_threshold_uv;
+ /* Override battery properties if specified in the battery profile */
+ if (batt_data->max_voltage_uv >= 0)
+ chip->max_voltage_uv = batt_data->max_voltage_uv;
+ if (batt_data->cutoff_uv >= 0)
+ chip->v_cutoff_uv = batt_data->cutoff_uv;
+ if (batt_data->iterm_ua >= 0)
+ chip->chg_term_ua = batt_data->iterm_ua;
+
if (chip->pc_temp_ocv_lut == NULL) {
pr_err("temp ocv lut table is NULL\n");
return -EINVAL;
@@ -3486,7 +3516,11 @@
return 0;
}
-#define ADC_CH_SEL_MASK 0x7
+#define ADC_CH_SEL_MASK 0x7
+#define ADC_INT_RSNSN_CTL_MASK 0x3
+#define ADC_INT_RSNSN_CTL_VALUE_EXT_RENSE 0x2
+#define FAST_AVG_EN_MASK 0x80
+#define FAST_AVG_EN_VALUE_EXT_RSENSE 0x80
static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
{
u8 iadc_channel_select;
@@ -3554,6 +3588,34 @@
pr_debug("rds_rsense = %d nOhm, saved as %d uOhm\n",
rds_rsense_nohm, chip->r_sense_uohm);
}
+ /* prevent shorting of leads by IADC_BMS when external Rsense is used */
+ if (chip->use_external_rsense) {
+ if (chip->iadc_bms_revision2 > CALIB_WRKARND_DIG_MAJOR_MAX) {
+ rc = qpnp_masked_write_iadc(chip,
+ IADC1_BMS_ADC_INT_RSNSN_CTL,
+ ADC_INT_RSNSN_CTL_MASK,
+ ADC_INT_RSNSN_CTL_VALUE_EXT_RENSE);
+ if (rc) {
+ pr_err("Unable to set batfet config %x to %x: %d\n",
+ IADC1_BMS_ADC_INT_RSNSN_CTL,
+ ADC_INT_RSNSN_CTL_VALUE_EXT_RENSE, rc);
+ return rc;
+ }
+ } else {
+ /* In older PMICS use FAST_AVG_EN register bit 7 */
+ rc = qpnp_masked_write_iadc(chip,
+ IADC1_BMS_FAST_AVG_EN,
+ FAST_AVG_EN_MASK,
+ FAST_AVG_EN_VALUE_EXT_RSENSE);
+ if (rc) {
+ pr_err("Unable to set batfet config %x to %x: %d\n",
+ IADC1_BMS_FAST_AVG_EN,
+ FAST_AVG_EN_VALUE_EXT_RSENSE, rc);
+ return rc;
+ }
+ }
+ }
+
return 0;
}
@@ -3660,20 +3722,36 @@
}
rc = qpnp_read_wrapper(chip, &chip->revision1,
- chip->base + BMS1_REVISION1, 1);
+ chip->base + REVISION1, 1);
if (rc) {
pr_err("error reading version register %d\n", rc);
goto error_read;
}
rc = qpnp_read_wrapper(chip, &chip->revision2,
- chip->base + BMS1_REVISION2, 1);
+ chip->base + REVISION2, 1);
if (rc) {
pr_err("Error reading version register %d\n", rc);
goto error_read;
}
pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
+ rc = qpnp_read_wrapper(chip, &chip->iadc_bms_revision2,
+ chip->iadc_base + REVISION2, 1);
+ if (rc) {
+ pr_err("Error reading version register %d\n", rc);
+ goto error_read;
+ }
+
+ rc = qpnp_read_wrapper(chip, &chip->iadc_bms_revision1,
+ chip->iadc_base + REVISION1, 1);
+ if (rc) {
+ pr_err("Error reading version register %d\n", rc);
+ goto error_read;
+ }
+ pr_debug("IADC_BMS version: %hhu.%hhu\n",
+ chip->iadc_bms_revision2, chip->iadc_bms_revision1);
+
rc = bms_read_properties(chip);
if (rc) {
pr_err("Unable to read all bms properties, rc = %d\n", rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 3679aa9..954bff8 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -28,6 +28,7 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
+#include <linux/of_batterydata.h>
/* Interrupt offsets */
#define INT_RT_STS(base) (base + 0x10)
@@ -273,6 +274,7 @@
struct qpnp_chg_irq chg_failed;
struct qpnp_chg_irq chg_vbatdet_lo;
struct qpnp_chg_irq batt_pres;
+ struct qpnp_chg_irq vchg_loop;
bool bat_is_cool;
bool bat_is_warm;
bool chg_done;
@@ -650,6 +652,92 @@
return rc;
}
+#define QPNP_CHG_VINMIN_MIN_MV 4200
+#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
+#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
+#define QPNP_CHG_VINMIN_MAX_MV 9600
+#define QPNP_CHG_VINMIN_STEP_MV 50
+#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
+#define QPNP_CHG_VINMIN_MASK 0x1F
+#define QPNP_CHG_VINMIN_MIN_VAL 0x10
+static int
+qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
+{
+ u8 temp;
+
+ if (voltage < QPNP_CHG_VINMIN_MIN_MV
+ || voltage > QPNP_CHG_VINMIN_MAX_MV) {
+ pr_err("bad mV=%d asked to set\n", voltage);
+ return -EINVAL;
+ }
+ if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
+ temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
+ temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
+ / QPNP_CHG_VINMIN_STEP_HIGH_MV;
+ } else {
+ temp = QPNP_CHG_VINMIN_MIN_VAL;
+ temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
+ / QPNP_CHG_VINMIN_STEP_MV;
+ }
+
+ pr_debug("voltage=%d setting %02x\n", voltage, temp);
+ return qpnp_chg_masked_write(chip,
+ chip->chgr_base + CHGR_VIN_MIN,
+ QPNP_CHG_VINMIN_MASK, temp, 1);
+}
+
+static int
+qpnp_chg_vinmin_get(struct qpnp_chg_chip *chip)
+{
+ int rc, vin_min_mv;
+ u8 vin_min;
+
+ rc = qpnp_chg_read(chip, &vin_min, chip->chgr_base + CHGR_VIN_MIN, 1);
+ if (rc) {
+ pr_err("failed to read VIN_MIN rc=%d\n", rc);
+ return 0;
+ }
+
+ if (vin_min == 0)
+ vin_min_mv = QPNP_CHG_I_MAX_MIN_100;
+ else if (vin_min > QPNP_CHG_VINMIN_HIGH_MIN_VAL)
+ vin_min_mv = QPNP_CHG_VINMIN_HIGH_MIN_MV +
+ (vin_min - QPNP_CHG_VINMIN_HIGH_MIN_VAL)
+ * QPNP_CHG_VINMIN_STEP_HIGH_MV;
+ else
+ vin_min_mv = QPNP_CHG_VINMIN_MIN_MV +
+ (vin_min - QPNP_CHG_VINMIN_MIN_VAL)
+ * QPNP_CHG_VINMIN_STEP_MV;
+ pr_debug("vin_min= 0x%02x, ma = %d\n", vin_min, vin_min_mv);
+
+ return vin_min_mv;
+}
+
+static int
+qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
+{
+ int rc, iusbmax_ma;
+ u8 iusbmax;
+
+ rc = qpnp_chg_read(chip, &iusbmax,
+ chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
+ if (rc) {
+ pr_err("failed to read IUSB_MAX rc=%d\n", rc);
+ return 0;
+ }
+
+ if (iusbmax == 0)
+ iusbmax_ma = QPNP_CHG_I_MAX_MIN_100;
+ else if (iusbmax == 0x01)
+ iusbmax_ma = QPNP_CHG_I_MAX_MIN_150;
+ else
+ iusbmax_ma = iusbmax * QPNP_CHG_I_MAXSTEP_MA;
+
+ pr_debug("iusbmax = 0x%02x, ma = %d\n", iusbmax, iusbmax_ma);
+
+ return iusbmax_ma;
+}
+
#define USB_SUSPEND_BIT BIT(0)
static int
qpnp_chg_usb_suspend_enable(struct qpnp_chg_chip *chip, int enable)
@@ -797,6 +885,17 @@
pr_err("request ADC error\n");
}
+static irqreturn_t
+qpnp_chg_buck_vchg_loop_irq_handler(int irq, void *_chip)
+{
+ struct qpnp_chg_chip *chip = _chip;
+
+ if (chip->bat_if_base)
+ power_supply_changed(&chip->batt_psy);
+
+ return IRQ_HANDLED;
+}
+
#define EOC_CHECK_PERIOD_MS 10000
static irqreturn_t
qpnp_chg_vbatdet_lo_irq_handler(int irq, void *_chip)
@@ -966,6 +1065,12 @@
qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
{
struct qpnp_chg_chip *chip = _chip;
+ u8 chgr_sts;
+ int rc;
+
+ rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
+ if (rc)
+ pr_err("failed to read interrupt sts %d\n", rc);
pr_debug("FAST_CHG IRQ triggered\n");
chip->chg_done = false;
@@ -978,7 +1083,12 @@
chip->resuming_charging = false;
qpnp_chg_set_appropriate_vbatdet(chip);
}
+
qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
+ if (chgr_sts & FAST_CHG_ON_IRQ)
+ qpnp_chg_enable_irq(&chip->vchg_loop);
+ else
+ qpnp_chg_disable_irq(&chip->vchg_loop);
return IRQ_HANDLED;
}
@@ -1004,6 +1114,8 @@
switch (psp) {
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return 1;
default:
break;
@@ -1109,6 +1221,9 @@
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
@@ -1124,6 +1239,9 @@
"bms",
};
+static int charger_monitor;
+module_param(charger_monitor, int, 0644);
+
#define USB_WALL_THRESHOLD_MA 500
static int
qpnp_power_get_property_mains(struct power_supply *psy,
@@ -1375,6 +1493,23 @@
return ret.intval;
}
+static int get_prop_vchg_loop(struct qpnp_chg_chip *chip)
+{
+ u8 buck_sts;
+ int rc;
+
+ rc = qpnp_chg_read(chip, &buck_sts, INT_RT_STS(chip->buck_base), 1);
+
+ if (rc) {
+ pr_err("spmi read failed: addr=%03X, rc=%d\n",
+ INT_RT_STS(chip->buck_base), rc);
+ return rc;
+ }
+ pr_debug("buck usb sts 0x%x\n", buck_sts);
+
+ return (buck_sts & VCHG_LOOP_IRQ) ? 1 : 0;
+}
+
static void
qpnp_batt_external_power_changed(struct power_supply *psy)
{
@@ -1398,7 +1533,13 @@
qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
} else {
qpnp_chg_usb_suspend_enable(chip, 0);
- qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
+ if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
+ && (charger_monitor)) {
+ qpnp_chg_iusbmax_set(chip,
+ USB_WALL_THRESHOLD_MA);
+ } else {
+ qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
+ }
}
}
@@ -1463,6 +1604,15 @@
case POWER_SUPPLY_PROP_CYCLE_COUNT:
val->intval = get_prop_cycle_count(chip);
break;
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
+ val->intval = get_prop_vchg_loop(chip);
+ break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
+ val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ val->intval = qpnp_chg_vinmin_get(chip) * 1000;
+ break;
default:
return -EINVAL;
}
@@ -1502,38 +1652,6 @@
mask, btc_cfg, 1);
}
-#define QPNP_CHG_VINMIN_MIN_MV 4200
-#define QPNP_CHG_VINMIN_HIGH_MIN_MV 5600
-#define QPNP_CHG_VINMIN_HIGH_MIN_VAL 0x2B
-#define QPNP_CHG_VINMIN_MAX_MV 9600
-#define QPNP_CHG_VINMIN_STEP_MV 50
-#define QPNP_CHG_VINMIN_STEP_HIGH_MV 200
-#define QPNP_CHG_VINMIN_MASK 0x1F
-static int
-qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
-{
- u8 temp;
-
- if (voltage < QPNP_CHG_VINMIN_MIN_MV
- || voltage > QPNP_CHG_VINMIN_MAX_MV) {
- pr_err("bad mV=%d asked to set\n", voltage);
- return -EINVAL;
- }
- if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
- temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
- temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
- / QPNP_CHG_VINMIN_STEP_HIGH_MV;
- } else {
- temp = (voltage - QPNP_CHG_VINMIN_MIN_MV)
- / QPNP_CHG_VINMIN_STEP_MV;
- }
-
- pr_debug("voltage=%d setting %02x\n", voltage, temp);
- return qpnp_chg_masked_write(chip,
- chip->chgr_base + CHGR_VIN_MIN,
- QPNP_CHG_VINMIN_MASK, temp, 1);
-}
-
#define QPNP_CHG_IBATSAFE_MIN_MA 100
#define QPNP_CHG_IBATSAFE_MAX_MA 3250
#define QPNP_CHG_I_STEP_MA 50
@@ -2214,6 +2332,12 @@
case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
qpnp_batt_system_temp_level_set(chip, val->intval);
break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
+ qpnp_chg_iusbmax_set(chip, val->intval / 1000);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ qpnp_chg_vinmin_set(chip, val->intval / 1000);
+ break;
default:
return -EINVAL;
}
@@ -2363,6 +2487,29 @@
enable_irq_wake(chip->batt_pres.irq);
break;
+ case SMBB_BUCK_SUBTYPE:
+ case SMBBP_BUCK_SUBTYPE:
+ case SMBCL_BUCK_SUBTYPE:
+ chip->vchg_loop.irq = spmi_get_irq_byname(spmi,
+ spmi_resource, "vchg-loop");
+ if (chip->vchg_loop.irq < 0) {
+ pr_err("Unable to get vchg-loop irq\n");
+ return rc;
+ }
+ rc = devm_request_irq(chip->dev, chip->vchg_loop.irq,
+ qpnp_chg_buck_vchg_loop_irq_handler,
+ IRQF_TRIGGER_RISING,
+ "vchg-loop", chip);
+ if (rc < 0) {
+ pr_err("Can't request %d vchg-loop irq: %d\n",
+ chip->vchg_loop.irq, rc);
+ return rc;
+ }
+
+ enable_irq_wake(chip->vchg_loop.irq);
+ qpnp_chg_disable_irq(&chip->vchg_loop);
+ break;
+
case SMBB_USB_CHGPTH_SUBTYPE:
case SMBBP_USB_CHGPTH_SUBTYPE:
case SMBCL_USB_CHGPTH_SUBTYPE:
@@ -2426,6 +2573,41 @@
return rc;
}
+static int
+qpnp_chg_load_battery_data(struct qpnp_chg_chip *chip)
+{
+ struct bms_battery_data batt_data;
+ struct device_node *node;
+ struct qpnp_vadc_result result;
+ int rc;
+
+ node = of_find_node_by_name(chip->spmi->dev.of_node,
+ "qcom,battery-data");
+ if (node) {
+ memset(&batt_data, 0, sizeof(struct bms_battery_data));
+ rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &result);
+ if (rc) {
+ pr_err("error reading batt id channel = %d, rc = %d\n",
+ LR_MUX2_BAT_ID, rc);
+ return rc;
+ }
+
+ rc = of_batterydata_read_data(node,
+ &batt_data, result.physical);
+ if (rc) {
+ pr_err("failed to read battery data: %d\n", rc);
+ return rc;
+ }
+
+ if (batt_data.max_voltage_uv >= 0)
+ chip->max_voltage_mv = batt_data.max_voltage_uv / 1000;
+ if (batt_data.iterm_ua >= 0)
+ chip->term_current = batt_data.iterm_ua / 1000;
+ }
+
+ return 0;
+}
+
#define WDOG_EN_BIT BIT(7)
static int
qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
@@ -2833,7 +3015,10 @@
if (rc)
goto fail_chg_enable;
- /* Check if bat_if is set in DT and make sure VADC is present */
+ /*
+ * Check if bat_if is set in DT and make sure VADC is present
+ * Also try loading the battery data profile if bat_if exists
+ */
spmi_for_each_container_dev(spmi_resource, spmi) {
if (!spmi_resource) {
pr_err("qpnp_chg: spmi resource absent\n");
@@ -2863,6 +3048,10 @@
rc = qpnp_vadc_is_ready();
if (rc)
goto fail_chg_enable;
+
+ rc = qpnp_chg_load_battery_data(chip);
+ if (rc)
+ goto fail_chg_enable;
}
}
@@ -3186,6 +3375,66 @@
return rc;
}
+static int
+qpnp_chg_ops_set(const char *val, const struct kernel_param *kp)
+{
+ return -EINVAL;
+}
+
+#define MAX_LEN_VADC 10
+static int
+qpnp_chg_usb_in_get(char *val, const struct kernel_param *kp)
+{
+ int rc;
+ struct qpnp_vadc_result results;
+
+ rc = qpnp_vadc_is_ready();
+ if (rc)
+ return rc;
+
+ rc = qpnp_vadc_read(USBIN, &results);
+ if (rc) {
+ pr_err("Unable to read vchg rc=%d\n", rc);
+ return 0;
+ }
+ rc = snprintf(val, MAX_LEN_VADC, "%lld\n", results.physical);
+
+ return rc;
+}
+
+static int
+qpnp_chg_vchg_get(char *val, const struct kernel_param *kp)
+{
+ int rc;
+ struct qpnp_vadc_result results;
+
+ rc = qpnp_vadc_is_ready();
+ if (rc)
+ return rc;
+
+ rc = qpnp_vadc_read(VCHG_SNS, &results);
+ if (rc) {
+ pr_err("Unable to read vchg rc=%d\n", rc);
+ return 0;
+ }
+ rc = snprintf(val, MAX_LEN_VADC, "%lld\n", results.physical);
+
+ return rc;
+}
+
+static struct kernel_param_ops usb_in_uv_param_ops = {
+ .set = qpnp_chg_ops_set,
+ .get = qpnp_chg_usb_in_get,
+};
+
+static struct kernel_param_ops vchg_uv_param_ops = {
+ .set = qpnp_chg_ops_set,
+ .get = qpnp_chg_vchg_get,
+};
+
+module_param_cb(usb_in_uv, &usb_in_uv_param_ops, NULL, 0644);
+module_param_cb(vchg_uv, &vchg_uv_param_ops, NULL, 0644);
+
static const struct dev_pm_ops qpnp_chg_pm_ops = {
.resume = qpnp_chg_resume,
.suspend = qpnp_chg_suspend,
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index f3b29c9..3b0ef8c 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1315,7 +1315,7 @@
return -ENODEV;
if (param->threshold_notification == NULL) {
- pr_err("No notification for high/low temp??\n");
+ pr_debug("No notification for high/low temp??\n");
return -EINVAL;
}
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index c8e5163..e36806f 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -1186,6 +1186,7 @@
int ret;
struct smux_lch_t *ch;
int enable_powerdown = 0;
+ int tx_ready = 0;
lcid = pkt->hdr.lcid;
ch = &smux_lch[lcid];
@@ -1203,7 +1204,7 @@
if (ch->remote_state == SMUX_LCH_REMOTE_OPENED) {
schedule_notify(lcid, SMUX_CONNECTED, NULL);
if (!(list_empty(&ch->tx_queue)))
- list_channel(ch);
+ tx_ready = 1;
}
ret = 0;
} else if (ch->remote_mode == SMUX_LCH_MODE_REMOTE_LOOPBACK) {
@@ -1226,6 +1227,9 @@
spin_unlock(&smux.tx_lock_lha2);
}
+ if (tx_ready)
+ list_channel(ch);
+
return ret;
}
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index bb2879b..db6fec9 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -264,7 +264,7 @@
*
* Returns 0 on success otherwise negative errno.
*/
-static int dwc3_event_buffers_setup(struct dwc3 *dwc)
+int dwc3_event_buffers_setup(struct dwc3 *dwc)
{
struct dwc3_event_buffer *evt;
int n;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 5db7420..2064c13 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -920,6 +920,7 @@
void dwc3_gadget_restart(struct dwc3 *dwc);
void dwc3_post_host_reset_core_init(struct dwc3 *dwc);
+int dwc3_event_buffers_setup(struct dwc3 *dwc);
extern int dwc3_get_device_id(void);
extern void dwc3_put_device_id(int id);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 0f8a7f0..c89f6d8 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -213,6 +213,7 @@
struct power_supply *ext_vbus_psy;
unsigned int online;
unsigned int host_mode;
+ unsigned int voltage_max;
unsigned int current_max;
unsigned int vdd_no_vol_level;
unsigned int vdd_low_vol_level;
@@ -2119,6 +2120,9 @@
case POWER_SUPPLY_PROP_SCOPE:
val->intval = mdwc->host_mode;
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ val->intval = mdwc->voltage_max;
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
val->intval = mdwc->current_max;
break;
@@ -2166,6 +2170,9 @@
case POWER_SUPPLY_PROP_ONLINE:
mdwc->online = val->intval;
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ mdwc->voltage_max = val->intval;
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
mdwc->current_max = val->intval;
break;
@@ -2206,6 +2213,20 @@
power_supply_changed(&mdwc->usb_psy);
}
+static int
+dwc3_msm_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static char *dwc3_msm_pm_power_supplied_to[] = {
"battery",
@@ -2214,6 +2235,7 @@
static enum power_supply_property dwc3_msm_pm_power_props_usb[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_TYPE,
POWER_SUPPLY_PROP_SCOPE,
@@ -2878,6 +2900,8 @@
mdwc->usb_psy.set_property = dwc3_msm_power_set_property_usb;
mdwc->usb_psy.external_power_changed =
dwc3_msm_external_power_changed;
+ mdwc->usb_psy.property_is_writeable =
+ dwc3_msm_property_is_writeable;
ret = power_supply_register(&pdev->dev, &mdwc->usb_psy);
if (ret < 0) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 63698de..acda980 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -43,6 +43,7 @@
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/ratelimit.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/list.h>
@@ -1487,10 +1488,12 @@
return 0;
}
+#define DWC3_SOFT_RESET_TIMEOUT 10 /* 10 msec */
static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
{
u32 reg;
u32 timeout = 500;
+ ktime_t start, diff;
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
if (is_on) {
@@ -1501,6 +1504,29 @@
if (dwc->revision >= DWC3_REVISION_194A)
reg &= ~DWC3_DCTL_KEEP_CONNECT;
+
+ start = ktime_get();
+ /* issue device SoftReset */
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg | DWC3_DCTL_CSFTRST);
+ do {
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (!(reg & DWC3_DCTL_CSFTRST))
+ break;
+
+ diff = ktime_sub(ktime_get(), start);
+ /* poll for max. 10ms */
+ if (ktime_to_ms(diff) > DWC3_SOFT_RESET_TIMEOUT) {
+ printk_ratelimited(KERN_ERR
+ "%s:core Reset Timed Out\n", __func__);
+ break;
+ }
+ cpu_relax();
+ } while (true);
+
+
+ dwc3_event_buffers_setup(dwc);
+ dwc3_gadget_restart(dwc);
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg |= DWC3_DCTL_RUN_STOP;
} else {
reg &= ~DWC3_DCTL_RUN_STOP;
@@ -1754,6 +1780,7 @@
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
dep = dwc->eps[0];
+ dep->endpoint.maxburst = 1;
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
if (ret) {
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
@@ -1761,6 +1788,7 @@
}
dep = dwc->eps[1];
+ dep->endpoint.maxburst = 1;
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
if (ret) {
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
diff --git a/drivers/usb/gadget/u_ctrl_hsuart.c b/drivers/usb/gadget/u_ctrl_hsuart.c
index a9bd53e..3443d12 100644
--- a/drivers/usb/gadget/u_ctrl_hsuart.c
+++ b/drivers/usb/gadget/u_ctrl_hsuart.c
@@ -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
@@ -18,11 +18,13 @@
#include <linux/termios.h>
#include <linux/debugfs.h>
#include <linux/smux.h>
+#include <linux/completion.h>
#include <mach/usb_gadget_xport.h>
#define CH_OPENED 0
#define CH_READY 1
+#define CH_CONNECTED 2
static unsigned int num_ctrl_ports;
@@ -37,6 +39,7 @@
enum gadget_type gtype;
spinlock_t port_lock;
void *port_usb;
+ struct completion close_complete;
/* work queue*/
struct workqueue_struct *wq;
struct work_struct connect_w;
@@ -74,6 +77,10 @@
size_t len;
switch (event_type) {
+ case SMUX_LOCAL_CLOSED:
+ clear_bit(CH_OPENED, &port->channel_sts);
+ complete(&port->close_complete);
+ break;
case SMUX_CONNECTED:
spin_lock_irqsave(&port->port_lock, flags);
if (!port->port_usb) {
@@ -81,7 +88,7 @@
return;
}
spin_unlock_irqrestore(&port->port_lock, flags);
- set_bit(CH_OPENED, &port->channel_sts);
+ set_bit(CH_CONNECTED, &port->channel_sts);
if (port->gtype == USB_GADGET_RMNET) {
gr = port->port_usb;
if (gr && gr->connect)
@@ -89,7 +96,7 @@
}
break;
case SMUX_DISCONNECTED:
- clear_bit(CH_OPENED, &port->channel_sts);
+ clear_bit(CH_CONNECTED, &port->channel_sts);
break;
case SMUX_READ_DONE:
len = ((struct smux_meta_read *)metadata)->len;
@@ -163,7 +170,7 @@
return -ENODEV;
}
/* drop cpkt if ch is not open */
- if (!test_bit(CH_OPENED, &port->channel_sts)) {
+ if (!test_bit(CH_CONNECTED, &port->channel_sts)) {
port->drp_cpkt_cnt++;
return 0;
}
@@ -209,7 +216,7 @@
port->cbits_tomodem = cbits;
- if (!test_bit(CH_OPENED, &port->channel_sts))
+ if (!test_bit(CH_CONNECTED, &port->channel_sts))
return;
pr_debug("%s: ctrl_tomodem:%d\n", __func__, cbits);
@@ -228,12 +235,21 @@
pr_debug("%s: port:%p\n", __func__, port);
+ if (test_bit(CH_OPENED, &port->channel_sts)) {
+ retval = wait_for_completion_timeout(
+ &port->close_complete, 3 * HZ);
+ if (retval == 0) {
+ pr_err("%s: smux close timedout\n", __func__);
+ return;
+ }
+ }
retval = msm_smux_open(port->ch_id, port->ctxt, smux_control_event,
rx_control_buffer);
if (retval < 0) {
pr_err(" %s smux_open failed\n", __func__);
return;
}
+ set_bit(CH_OPENED, &port->channel_sts);
}
@@ -283,8 +299,9 @@
if (!test_bit(CH_OPENED, &port->channel_sts))
return;
+ INIT_COMPLETION(port->close_complete);
msm_smux_close(port->ch_id);
- clear_bit(CH_OPENED, &port->channel_sts);
+ clear_bit(CH_CONNECTED, &port->channel_sts);
}
void ghsuart_ctrl_disconnect(void *gptr, int port_num)
@@ -363,6 +380,7 @@
gr->disconnect(gr);
clear_bit(CH_OPENED, &port->channel_sts);
+ clear_bit(CH_CONNECTED, &port->channel_sts);
not_ready:
clear_bit(CH_READY, &port->channel_sts);
@@ -403,6 +421,7 @@
spin_lock_init(&port->port_lock);
+ init_completion(&port->close_complete);
INIT_WORK(&port->connect_w, ghsuart_ctrl_connect_w);
INIT_WORK(&port->disconnect_w, ghsuart_ctrl_disconnect_w);
diff --git a/drivers/usb/gadget/u_data_hsuart.c b/drivers/usb/gadget/u_data_hsuart.c
index 8005a4a..c342437 100644
--- a/drivers/usb/gadget/u_data_hsuart.c
+++ b/drivers/usb/gadget/u_data_hsuart.c
@@ -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
@@ -20,6 +20,7 @@
#include <linux/debugfs.h>
#include <linux/bitops.h>
#include <linux/smux.h>
+#include <linux/completion.h>
#include <mach/usb_gadget_xport.h>
@@ -72,6 +73,7 @@
#define CH_OPENED 0
#define CH_READY 1
+#define CH_CONNECTED 2
struct ghsuart_data_port {
/* port */
@@ -86,6 +88,7 @@
spinlock_t port_lock;
void *port_usb;
+ struct completion close_complete;
/* data transfer queues */
unsigned int tx_q_size;
struct list_head tx_idle;
@@ -502,8 +505,12 @@
pr_debug("%s: event type: %s ", __func__, event_string(event_type));
switch (event_type) {
+ case SMUX_LOCAL_CLOSED:
+ clear_bit(CH_OPENED, &port->channel_sts);
+ complete(&port->close_complete);
+ break;
case SMUX_CONNECTED:
- set_bit(CH_OPENED, &port->channel_sts);
+ set_bit(CH_CONNECTED, &port->channel_sts);
if (port->gtype == USB_GADGET_SERIAL) {
cbits = msm_smux_tiocm_get(port->ch_id);
if (cbits & ACM_CTRL_DCD) {
@@ -515,7 +522,7 @@
ghsuart_data_start_io(port);
break;
case SMUX_DISCONNECTED:
- clear_bit(CH_OPENED, &port->channel_sts);
+ clear_bit(CH_CONNECTED, &port->channel_sts);
break;
case SMUX_READ_DONE:
skb = meta_read->pkt_priv;
@@ -589,6 +596,14 @@
pr_debug("%s: port:%p\n", __func__, port);
+ if (test_bit(CH_OPENED, &port->channel_sts)) {
+ ret = wait_for_completion_timeout(
+ &port->close_complete, 3 * HZ);
+ if (ret == 0) {
+ pr_err("%s: smux close timedout\n", __func__);
+ return;
+ }
+ }
ret = msm_smux_open(port->ch_id, port, &ghsuart_notify_event,
&ghsuart_get_rx_buffer);
if (ret) {
@@ -596,6 +611,7 @@
__func__, port->ch_id, ret);
return;
}
+ set_bit(CH_OPENED, &port->channel_sts);
}
static void ghsuart_data_disconnect_w(struct work_struct *w)
@@ -606,8 +622,9 @@
if (!test_bit(CH_OPENED, &port->channel_sts))
return;
+ INIT_COMPLETION(port->close_complete);
msm_smux_close(port->ch_id);
- clear_bit(CH_OPENED, &port->channel_sts);
+ clear_bit(CH_CONNECTED, &port->channel_sts);
}
static void ghsuart_data_free_buffers(struct ghsuart_data_port *port)
@@ -710,6 +727,7 @@
clear_bit(CH_READY, &port->channel_sts);
clear_bit(CH_OPENED, &port->channel_sts);
+ clear_bit(CH_CONNECTED, &port->channel_sts);
return 0;
}
@@ -747,7 +765,7 @@
port->cbits_tomodem = cbits;
- if (!test_bit(CH_OPENED, &port->channel_sts))
+ if (!test_bit(CH_CONNECTED, &port->channel_sts))
return;
/* if DTR is high, update latest modem info to Host */
@@ -786,6 +804,7 @@
spin_lock_init(&port->rx_lock);
spin_lock_init(&port->tx_lock);
+ init_completion(&port->close_complete);
INIT_WORK(&port->connect_w, ghsuart_data_connect_w);
INIT_WORK(&port->disconnect_w, ghsuart_data_disconnect_w);
INIT_WORK(&port->write_tohost_w, ghsuart_data_write_tohost);
@@ -994,6 +1013,7 @@
"#PORT:%d port#: %p\n"
"data_ch_open: %d\n"
"data_ch_ready: %d\n"
+ "data_ch_connected: %d\n"
"\n******UL INFO*****\n\n"
"dpkts_to_modem: %lu\n"
"tomodem_drp_cnt: %u\n"
@@ -1003,6 +1023,7 @@
i, port,
test_bit(CH_OPENED, &port->channel_sts),
test_bit(CH_READY, &port->channel_sts),
+ test_bit(CH_CONNECTED, &port->channel_sts),
port->to_modem,
port->tomodem_drp_cnt,
port->rx_skb_q.qlen,
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 1b6d15e..bec0356 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -541,7 +541,7 @@
*/
static int xhci_ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
{
- int retval;
+ int retval = -ENOMEM;
struct usb_ctrlrequest *dr;
struct urb *urb;
struct usb_device *udev;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index fa1932b..de7fc02 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1005,7 +1005,8 @@
* PHY retention and collapse can not happen with VDP_SRC enabled.
*/
if (motg->caps & ALLOW_PHY_RETENTION && !device_bus_suspend && !dcp &&
- (!host_bus_suspend || motg->caps & ALLOW_HOST_PHY_RETENTION)) {
+ (!host_bus_suspend || ((motg->caps & ALLOW_HOST_PHY_RETENTION)
+ && (pdata->dpdm_pulldown_added || !(portsc & PORTSC_CCS))))) {
phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
if (motg->pdata->otg_control == OTG_PHY_CONTROL) {
/* Enable PHY HV interrupts to wake MPM/Link */
@@ -1034,7 +1035,8 @@
}
/* usb phy no more require TCXO clock, hence vote for TCXO disable */
- if (!host_bus_suspend || (motg->caps & ALLOW_HOST_PHY_RETENTION)) {
+ if (!host_bus_suspend || ((motg->caps & ALLOW_HOST_PHY_RETENTION) &&
+ (pdata->dpdm_pulldown_added || !(portsc & PORTSC_CCS)))) {
if (!IS_ERR(motg->xo_clk)) {
clk_disable_unprepare(motg->xo_clk);
motg->lpm_flags |= XO_SHUTDOWN;
@@ -1111,6 +1113,9 @@
if (!atomic_read(&motg->in_lpm))
return 0;
+ if (motg->pdata->delay_lpm_hndshk_on_disconnect)
+ msm_bam_notify_lpm_resume();
+
disable_irq(motg->irq);
wake_lock(&motg->wlock);
@@ -3600,8 +3605,11 @@
else
val->intval = POWER_SUPPLY_SCOPE_DEVICE;
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ val->intval = motg->voltage_max;
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- val->intval = motg->current_max;
+ val->intval = motg->current_max;
break;
/* Reflect USB enumeration */
case POWER_SUPPLY_PROP_PRESENT:
@@ -3632,6 +3640,9 @@
case POWER_SUPPLY_PROP_ONLINE:
motg->online = val->intval;
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ motg->voltage_max = val->intval;
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
motg->current_max = val->intval;
break;
@@ -3652,6 +3663,7 @@
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_ONLINE:
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
case POWER_SUPPLY_PROP_CURRENT_MAX:
return 1;
default:
@@ -3668,6 +3680,7 @@
static enum power_supply_property otg_pm_power_props_usb[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_SCOPE,
POWER_SUPPLY_PROP_TYPE,
@@ -4053,6 +4066,37 @@
return ret;
}
+static ssize_t dpdm_pulldown_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct msm_otg *motg = the_msm_otg;
+ struct msm_otg_platform_data *pdata = motg->pdata;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", pdata->dpdm_pulldown_added ?
+ "enabled" : "disabled");
+}
+
+static ssize_t dpdm_pulldown_enable_store(struct device *dev,
+ struct device_attribute *attr, const char
+ *buf, size_t size)
+{
+ struct msm_otg *motg = the_msm_otg;
+ struct msm_otg_platform_data *pdata = motg->pdata;
+
+ if (!strnicmp(buf, "enable", 6)) {
+ pdata->dpdm_pulldown_added = true;
+ return size;
+ } else if (!strnicmp(buf, "disable", 7)) {
+ pdata->dpdm_pulldown_added = false;
+ return size;
+ }
+
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(dpdm_pulldown_enable, S_IRUGO | S_IWUSR,
+ dpdm_pulldown_enable_show, dpdm_pulldown_enable_store);
+
struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -4479,6 +4523,8 @@
if (motg->pdata->mpm_dpshv_int || motg->pdata->mpm_dmshv_int)
motg->caps |= ALLOW_HOST_PHY_RETENTION;
+ device_create_file(&pdev->dev,
+ &dev_attr_dpdm_pulldown_enable);
}
if (motg->pdata->enable_lpm_on_dev_suspend)
@@ -4613,6 +4659,10 @@
usb_set_transceiver(NULL);
free_irq(motg->irq, motg);
+ if ((motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) &&
+ (motg->pdata->mpm_dpshv_int || motg->pdata->mpm_dmshv_int))
+ device_remove_file(&pdev->dev,
+ &dev_attr_dpdm_pulldown_enable);
if (motg->pdata->otg_control == OTG_PHY_CONTROL &&
motg->pdata->mpm_otgsessvld_int)
msm_mpm_enable_pin(motg->pdata->mpm_otgsessvld_int, 0);
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 43eda51..017fa8e 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -24,6 +24,7 @@
mdss-dsi-objs += msm_mdss_io_8974.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_edp.o
+obj-$(CONFIG_FB_MSM_MDSS) += mdss_edp_aux.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_io_util.o
obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_tx.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 96f0f8c..f2de17d 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -857,6 +857,26 @@
return ret;
}
+static int msm_dsi_cont_on(struct mdss_panel_data *pdata)
+{
+ struct mdss_panel_info *pinfo;
+ int ret = 0;
+
+ pr_debug("%s:\n", __func__);
+
+ pinfo = &pdata->panel_info;
+ ret = msm_dsi_regulator_enable();
+ if (ret) {
+ pr_err("%s: DSI power on failed\n", __func__);
+ return ret;
+ }
+
+ msm_dsi_ahb_ctrl(1);
+ msm_dsi_prepare_clocks();
+ msm_dsi_clk_enable();
+ return 0;
+}
+
static int __devinit msm_dsi_probe(struct platform_device *pdev)
{
struct dsi_interface intf;
@@ -925,6 +945,7 @@
dsi_host_private->dis_dev = pdev->dev;
intf.on = msm_dsi_on;
intf.off = msm_dsi_off;
+ intf.cont_on = msm_dsi_cont_on;
intf.op_mode_config = msm_dsi_op_mode_config;
intf.tx = msm_dsi_cmds_tx;
intf.rx = msm_dsi_cmds_rx;
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
index 5c164e4..022d911 100644
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -163,7 +163,20 @@
pr_debug("%s: enable = %d\n", __func__, enable);
- if (enable) {
+ if (enable == 2) {
+ dsi_panel_power(1);
+ gpio_request(panel_private->rst_gpio, "panel_reset");
+ if (gpio_is_valid(panel_private->disp_en_gpio)) {
+ gpio_request(panel_private->disp_en_gpio,
+ "panel_enable");
+ }
+ if (gpio_is_valid(panel_private->video_mode_gpio)) {
+ gpio_request(panel_private->video_mode_gpio,
+ "panel_video_mdoe");
+ }
+ 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);
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 1a9059c..686ec01 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -82,6 +82,25 @@
return rc;
}
+static int dsi_splash_on(struct mdss_panel_data *pdata)
+{
+ int rc = 0;
+
+ 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);
+
+ if (rc) {
+ pr_err("mdss_dsi_on DSI failed %d\n", rc);
+ return rc;
+ }
+ return rc;
+}
+
static int dsi_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -105,6 +124,9 @@
case MDSS_EVENT_PANEL_OFF:
rc = dsi_panel_handler(pdata, 0);
break;
+ case MDSS_EVENT_CONT_SPLASH_BEGIN:
+ rc = dsi_splash_on(pdata);
+ break;
default:
pr_debug("%s: unhandled event=%d\n", __func__, event);
break;
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index 54b772b..96dd390 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -198,6 +198,7 @@
struct dsi_interface {
int (*on)(struct mdss_panel_data *pdata);
int (*off)(struct mdss_panel_data *pdata);
+ int (*cont_on)(struct mdss_panel_data *pdata);
void (*op_mode_config)(int mode, struct mdss_panel_data *pdata);
int (*tx)(struct mdss_panel_data *pdata,
struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt);
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 66418db..f6f722e 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -959,6 +959,21 @@
return rc;
}
+int mdp3_iommu_is_attached(int client)
+{
+ struct mdp3_iommu_ctx_map *context_map;
+ int context = MDP3_IOMMU_CTX_DMA_0;
+
+ if (!mdp3_res->iommu_contexts)
+ return 0;
+
+ if (client == MDP3_CLIENT_PPP)
+ context = MDP3_IOMMU_CTX_PPP_0;
+
+ context_map = mdp3_res->iommu_contexts + context;
+ return context_map->attached;
+}
+
static int mdp3_init(struct msm_fb_data_type *mfd)
{
int rc;
@@ -982,6 +997,66 @@
return xres * bpp;
}
+void mdp3_fbmem_clear(void)
+{
+ if (mdp3_res->ion_handle && mdp3_res->virt) {
+ pr_debug("mdp3_fbmem_clear\n");
+ memset(mdp3_res->virt, 0, mdp3_res->size);
+ }
+}
+
+static int mdp3_alloc(size_t size, void **virt, unsigned long *phys)
+{
+ int ret = 0;
+
+ if (mdp3_res->ion_handle) {
+ pr_debug("memory already alloc\n");
+ *virt = mdp3_res->virt;
+ *phys = mdp3_res->phys;
+ return 0;
+ }
+
+ mdp3_res->ion_handle = ion_alloc(mdp3_res->ion_client, size,
+ SZ_1M,
+ ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+
+ if (!IS_ERR_OR_NULL(mdp3_res->ion_handle)) {
+ *virt = ion_map_kernel(mdp3_res->ion_client,
+ mdp3_res->ion_handle);
+ if (IS_ERR(*virt)) {
+ pr_err("map kernel error\n");
+ goto ion_map_kernel_err;
+ }
+
+ ret = ion_phys(mdp3_res->ion_client, mdp3_res->ion_handle,
+ phys, &size);
+ if (ret) {
+ pr_err("%s ion_phys error\n", __func__);
+ goto ion_map_phys_err;
+ }
+
+ mdp3_res->virt = *virt;
+ mdp3_res->phys = *phys;
+ mdp3_res->size = size;
+ } else {
+ pr_err("%s ion alloc fail\n", __func__);
+ mdp3_res->ion_handle = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+
+ion_map_phys_err:
+ ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
+ion_map_kernel_err:
+ ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
+ mdp3_res->ion_handle = NULL;
+ mdp3_res->virt = NULL;
+ mdp3_res->phys = 0;
+ mdp3_res->size = 0;
+ return -ENOMEM;
+}
+
static int mdp3_fbmem_alloc(struct msm_fb_data_type *mfd)
{
int ret = -ENOMEM, dom;
@@ -999,28 +1074,10 @@
return 0;
}
- mdp3_res->ion_handle = ion_alloc(mdp3_res->ion_client, size,
- SZ_1M,
- ION_HEAP(ION_QSECOM_HEAP_ID), 0);
-
- if (!IS_ERR_OR_NULL(mdp3_res->ion_handle)) {
- virt = ion_map_kernel(mdp3_res->ion_client,
- mdp3_res->ion_handle);
- if (IS_ERR(virt)) {
- pr_err("%s map kernel error\n", __func__);
- goto ion_map_kernel_err;
- }
-
- ret = ion_phys(mdp3_res->ion_client, mdp3_res->ion_handle,
- &phys, &size);
- if (ret) {
- pr_err("%s ion_phys error\n", __func__);
- goto ion_map_phys_err;
- }
- } else {
- pr_err("%s ion alloc fail\n", __func__);
- mdp3_res->ion_handle = NULL;
- return -ENOMEM;
+ ret = mdp3_alloc(size, &virt, &phys);
+ if (ret) {
+ pr_err("fail to allocate fb memory\n");
+ return ret;
}
dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
@@ -1031,10 +1088,10 @@
if (ret) {
pr_err("%s map IOMMU error\n", __func__);
- goto ion_map_phys_err;
+ goto ion_map_iommu_err;
}
- pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
+ pr_debug("allocating %u bytes at %p (%lx phys) for fb %d\n",
size, virt, phys, mfd->index);
mfd->fbi->screen_base = virt;
@@ -1042,17 +1099,19 @@
mfd->fbi->fix.smem_len = size;
return 0;
-ion_map_phys_err:
+ion_map_iommu_err:
ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
-ion_map_kernel_err:
ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
mdp3_res->ion_handle = NULL;
+ mdp3_res->virt = NULL;
+ mdp3_res->phys = 0;
+ mdp3_res->size = 0;
return -ENOMEM;
}
void mdp3_fbmem_free(struct msm_fb_data_type *mfd)
{
- pr_info("mdp3_fbmem_free\n");
+ pr_debug("mdp3_fbmem_free\n");
if (mdp3_res->ion_handle) {
int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
@@ -1061,6 +1120,9 @@
dom, 0);
ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
mdp3_res->ion_handle = NULL;
+ mdp3_res->virt = NULL;
+ mdp3_res->phys = 0;
+ mdp3_res->size = 0;
mfd->fbi->screen_base = 0;
mfd->fbi->fix.smem_start = 0;
mfd->fbi->fix.smem_len = 0;
@@ -1103,6 +1165,130 @@
return mdp3_res->domains[MDP3_IOMMU_DOMAIN].domain_idx;
}
+int mdp3_continuous_splash_copy(struct mdss_panel_data *pdata)
+{
+ unsigned long splash_phys, phys;
+ void *splash_virt, *virt;
+ u32 height, width, rgb_size, stride;
+ size_t size;
+ int rc;
+
+ rgb_size = MDP3_REG_READ(MDP3_REG_DMA_P_SIZE);
+ stride = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_Y_STRIDE);
+ stride = stride & 0x3FFF;
+ splash_phys = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_ADDR);
+
+ height = (rgb_size >> 16) & 0xffff;
+ width = rgb_size & 0xffff;
+ size = PAGE_ALIGN(height * stride * 2);
+ pr_debug("splash_height=%d splash_width=%d Buffer size=%d\n",
+ height, width, size);
+
+ rc = mdp3_alloc(size, &virt, &phys);
+ if (rc) {
+ pr_err("fail to allocate memory for continuous splash image\n");
+ return rc;
+ }
+
+ splash_virt = ioremap(splash_phys, stride * height);
+ memcpy(virt, splash_virt, stride * height);
+ iounmap(splash_virt);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, phys);
+
+ return 0;
+}
+
+static int mdp3_is_display_on(struct mdss_panel_data *pdata)
+{
+ int rc = 0;
+ u32 status;
+
+ mdp3_clk_update(MDP3_CLK_AHB, 1);
+ mdp3_clk_update(MDP3_CLK_CORE, 1);
+
+ if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
+ status = MDP3_REG_READ(MDP3_REG_DSI_VIDEO_EN);
+ rc = status & 0x1;
+ } else {
+ status = MDP3_REG_READ(MDP3_REG_DMA_P_START);
+ rc = status & 01;
+ }
+
+ mdp3_clk_update(MDP3_CLK_AHB, 0);
+ mdp3_clk_update(MDP3_CLK_CORE, 0);
+ return rc;
+}
+
+static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata)
+{
+ struct mdss_panel_info *panel_info = &pdata->panel_info;
+ int ab, ib, rc;
+
+ pr_debug("mdp3__continuous_splash_on\n");
+
+ rc = mdp3_clk_enable(1);
+ if (rc) {
+ pr_err("fail to enable clk\n");
+ return rc;
+ }
+
+ ab = panel_info->xres * panel_info->yres * 4;
+ ab *= panel_info->mipi.frame_rate;
+ ib = (ab * 3) / 2;
+ rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
+ if (rc) {
+ pr_err("fail to request bus bandwidth\n");
+ goto splash_on_err;
+ }
+
+ rc = mdp3_ppp_init();
+ if (rc) {
+ pr_err("ppp init failed\n");
+ goto splash_on_err;
+ }
+
+ rc = mdp3_continuous_splash_copy(pdata);
+ if (rc) {
+ pr_err("fail to copy continuous splash image\n");
+ goto splash_on_err;
+ }
+
+ mdp3_irq_register();
+
+ if (pdata->event_handler) {
+ rc = pdata->event_handler(pdata, MDSS_EVENT_CONT_SPLASH_BEGIN,
+ NULL);
+ if (rc) {
+ pr_err("MDSS_EVENT_CONT_SPLASH_BEGIN event fail\n");
+ goto splash_on_err;
+ }
+ }
+
+ if (panel_info->type == MIPI_VIDEO_PANEL)
+ mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_VIDEO].active = 1;
+ else
+ mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_CMD].active = 1;
+ return 0;
+
+splash_on_err:
+ mdp3_clk_enable(0);
+ return rc;
+}
+
+static int mdp3_panel_register_done(struct mdss_panel_data *pdata)
+{
+ int rc = 0;
+
+ if (pdata->panel_info.cont_splash_enabled) {
+ if (!mdp3_is_display_on(pdata)) {
+ pr_err("continuous splash, but bootloader is not\n");
+ return 0;
+ }
+ rc = mdp3_continuous_splash_on(pdata);
+ }
+ return rc;
+}
+
static int mdp3_probe(struct platform_device *pdev)
{
int rc;
@@ -1110,6 +1296,7 @@
.init_fnc = mdp3_init,
.fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain,
.fb_mem_alloc_fnc = mdp3_fbmem_alloc,
+ .panel_register_done = mdp3_panel_register_done,
.fb_stride = mdp3_fb_stride,
};
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index d29e5b6..03416c7 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -111,6 +111,9 @@
struct mdp3_iommu_domain_map *domains;
struct mdp3_iommu_ctx_map *iommu_contexts;
struct ion_handle *ion_handle;
+ void *virt;
+ unsigned long phys;
+ size_t size;
struct mdp3_dma dma[MDP3_DMA_MAX];
struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
@@ -151,7 +154,10 @@
int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
int mdp3_iommu_enable(int client);
int mdp3_iommu_disable(int client);
+int mdp3_iommu_is_attached(int client);
void mdp3_fbmem_free(struct msm_fb_data_type *mfd);
+void mdp3_fbmem_clear(void);
+
#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 7edf3d2..f77a2b3 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -351,7 +351,11 @@
cfg.dsi_cmd.dsi_cmd_tg_intf_sel = 0;
} else
return -EINVAL;
- rc = mdp3_intf_init(intf, &cfg);
+
+ if (intf->config)
+ rc = intf->config(intf, &cfg);
+ else
+ rc = -EINVAL;
return rc;
}
@@ -390,7 +394,10 @@
(MDP3_DMA_OUTPUT_COMP_BITS_8 << 2)|
MDP3_DMA_OUTPUT_COMP_BITS_8;
- rc = mdp3_dma_init(dma, &sourceConfig, &outputConfig);
+ if (dma->dma_config)
+ rc = dma->dma_config(dma, &sourceConfig, &outputConfig);
+ else
+ rc = -EINVAL;
return rc;
}
@@ -413,6 +420,11 @@
goto on_error;
}
+ if (mdp3_session->intf->active) {
+ pr_debug("continuous splash screen, initialized already\n");
+ goto on_error;
+ }
+
rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
if (rc) {
pr_err("fail to attach MDP DMA SMMU\n");
@@ -461,6 +473,8 @@
goto on_error;
}
+ mdp3_fbmem_clear();
+
if (panel->set_backlight)
panel->set_backlight(panel, panel->panel_info.bl_max);
@@ -671,6 +685,12 @@
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);
+ }
+
mutex_lock(&mdp3_session->lock);
data = mdp3_bufq_pop(&mdp3_session->bufq_in);
@@ -715,6 +735,12 @@
return;
}
+ 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);
+ }
+
mutex_lock(&mdp3_session->lock);
fbi = mfd->fbi;
@@ -1217,12 +1243,23 @@
goto init_done;
}
+ rc = mdp3_dma_init(mdp3_session->dma);
+ if (rc) {
+ pr_err("fail to init dma\n");
+ goto init_done;
+ }
+
intf_type = mdp3_ctrl_get_intf_type(mfd);
mdp3_session->intf = mdp3_get_display_intf(intf_type);
if (!mdp3_session->intf) {
rc = -ENODEV;
goto init_done;
}
+ rc = mdp3_intf_init(mdp3_session->intf);
+ if (rc) {
+ pr_err("fail to init interface\n");
+ goto init_done;
+ }
mdp3_session->mfd = mfd;
mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 2e9c787..88eedb9 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -829,19 +829,14 @@
return ret;
}
-int mdp3_dma_init(struct mdp3_dma *dma,
- struct mdp3_dma_source *source_config,
- struct mdp3_dma_output_config *output_config)
+int mdp3_dma_init(struct mdp3_dma *dma)
{
int ret = 0;
pr_debug("mdp3_dma_init\n");
switch (dma->dma_sel) {
case MDP3_DMA_P:
- ret = mdp3_dmap_config(dma, source_config, output_config);
- if (ret < 0)
- return ret;
-
+ dma->dma_config = mdp3_dmap_config;
dma->config_cursor = mdp3_dmap_cursor_config;
dma->config_ccs = mdp3_dmap_ccs_config;
dma->config_histo = mdp3_dmap_histo_config;
@@ -855,10 +850,7 @@
dma->stop = mdp3_dma_stop;
break;
case MDP3_DMA_S:
- ret = mdp3_dmas_config(dma, source_config, output_config);
- if (ret < 0)
- return ret;
-
+ dma->dma_config = mdp3_dmas_config;
dma->config_cursor = NULL;
dma->config_ccs = NULL;
dma->config_histo = NULL;
@@ -1029,10 +1021,9 @@
return 0;
}
-int mdp3_intf_init(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+int mdp3_intf_init(struct mdp3_intf *intf)
{
- int ret = 0;
- switch (cfg->type) {
+ switch (intf->cfg.type) {
case MDP3_DMA_OUTPUT_SEL_LCDC:
intf->config = lcdc_config;
intf->start = lcdc_start;
@@ -1052,16 +1043,5 @@
default:
return -EINVAL;
}
-
- intf->active = false;
- if (intf->config)
- ret = intf->config(intf, cfg);
-
- if (ret) {
- pr_err("MDP interface initialization failed\n");
- return ret;
- }
-
- intf->cfg = *cfg;
return 0;
}
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index c652818..e4a28dc 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -250,6 +250,10 @@
int histo_state;
struct mdp3_dma_histogram_data histo_data;
+ int (*dma_config)(struct mdp3_dma *dma,
+ struct mdp3_dma_source *source_config,
+ struct mdp3_dma_output_config *output_config);
+
int (*start)(struct mdp3_dma *dma, struct mdp3_intf *intf);
int (*stop)(struct mdp3_dma *dma, struct mdp3_intf *intf);
@@ -323,11 +327,9 @@
int (*stop)(struct mdp3_intf *intf);
};
-int mdp3_dma_init(struct mdp3_dma *dma,
- struct mdp3_dma_source *source_config,
- struct mdp3_dma_output_config *output_config);
+int mdp3_dma_init(struct mdp3_dma *dma);
-int mdp3_intf_init(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg);
+int mdp3_intf_init(struct mdp3_intf *intf);
void mdp3_dma_callback_enable(struct mdp3_dma *dma, int type);
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 44a5e62..3b0cd20 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -31,9 +31,7 @@
static int mdss_dsi_regulator_init(struct platform_device *pdev)
{
- int ret = 0;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- struct dsi_drv_cm_data *dsi_drv = NULL;
if (!pdev) {
pr_err("%s: invalid input\n", __func__);
@@ -46,59 +44,9 @@
return -EINVAL;
}
- dsi_drv = &(ctrl_pdata->shared_pdata);
- if (ctrl_pdata->power_data.num_vreg > 0) {
- ret = msm_dss_config_vreg(&pdev->dev,
- ctrl_pdata->power_data.vreg_config,
- ctrl_pdata->power_data.num_vreg, 1);
- } else {
- dsi_drv->vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
- if (IS_ERR(dsi_drv->vdd_vreg)) {
- pr_err("%s: could not get vdda vreg, rc=%ld\n",
- __func__, PTR_ERR(dsi_drv->vdd_vreg));
- return PTR_ERR(dsi_drv->vdd_vreg);
- }
-
- ret = regulator_set_voltage(dsi_drv->vdd_vreg, 3000000,
- 3000000);
- if (ret) {
- pr_err("%s: set voltage failed on vdda vreg, rc=%d\n",
- __func__, ret);
- return ret;
- }
-
- dsi_drv->vdd_io_vreg = devm_regulator_get(&pdev->dev, "vddio");
- if (IS_ERR(dsi_drv->vdd_io_vreg)) {
- pr_err("%s: could not get vddio reg, rc=%ld\n",
- __func__, PTR_ERR(dsi_drv->vdd_io_vreg));
- return PTR_ERR(dsi_drv->vdd_io_vreg);
- }
-
- ret = regulator_set_voltage(dsi_drv->vdd_io_vreg, 1800000,
- 1800000);
- if (ret) {
- pr_err("%s: set voltage failed on vddio vreg, rc=%d\n",
- __func__, ret);
- return ret;
- }
-
- dsi_drv->vdda_vreg = devm_regulator_get(&pdev->dev, "vdda");
- if (IS_ERR(dsi_drv->vdda_vreg)) {
- pr_err("%s: could not get vdda vreg, rc=%ld\n",
- __func__, PTR_ERR(dsi_drv->vdda_vreg));
- return PTR_ERR(dsi_drv->vdda_vreg);
- }
-
- ret = regulator_set_voltage(dsi_drv->vdda_vreg, 1200000,
- 1200000);
- if (ret) {
- pr_err("%s: set voltage failed on vdda vreg, rc=%d\n",
- __func__, ret);
- return ret;
- }
- }
-
- return 0;
+ return msm_dss_config_vreg(&pdev->dev,
+ ctrl_pdata->power_data.vreg_config,
+ ctrl_pdata->power_data.num_vreg, 1);
}
static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata, int enable)
@@ -108,7 +56,8 @@
if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto error;
}
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
@@ -116,71 +65,13 @@
pr_debug("%s: enable=%d\n", __func__, enable);
if (enable) {
- if (ctrl_pdata->power_data.num_vreg > 0) {
- ret = msm_dss_enable_vreg(
- ctrl_pdata->power_data.vreg_config,
- ctrl_pdata->power_data.num_vreg, 1);
- if (ret) {
- pr_err("%s:Failed to enable regulators.rc=%d\n",
- __func__, ret);
- return ret;
- }
-
- /*
- * A small delay is needed here after enabling
- * all regulators and before issuing panel reset
- */
- msleep(20);
- } else {
- ret = regulator_set_optimum_mode(
- (ctrl_pdata->shared_pdata).vdd_vreg, 100000);
- if (ret < 0) {
- pr_err("%s: vdd_vreg set opt mode failed.\n",
- __func__);
- return ret;
- }
-
- ret = regulator_set_optimum_mode(
- (ctrl_pdata->shared_pdata).vdd_io_vreg, 100000);
- if (ret < 0) {
- pr_err("%s: vdd_io_vreg set opt mode failed.\n",
- __func__);
- return ret;
- }
-
- ret = regulator_set_optimum_mode
- ((ctrl_pdata->shared_pdata).vdda_vreg, 100000);
- if (ret < 0) {
- pr_err("%s: vdda_vreg set opt mode failed.\n",
- __func__);
- return ret;
- }
-
- ret = regulator_enable(
- (ctrl_pdata->shared_pdata).vdd_io_vreg);
- if (ret) {
- pr_err("%s: Failed to enable regulator.\n",
- __func__);
- return ret;
- }
- msleep(20);
-
- ret = regulator_enable(
- (ctrl_pdata->shared_pdata).vdd_vreg);
- if (ret) {
- pr_err("%s: Failed to enable regulator.\n",
- __func__);
- return ret;
- }
- msleep(20);
-
- ret = regulator_enable(
- (ctrl_pdata->shared_pdata).vdda_vreg);
- if (ret) {
- pr_err("%s: Failed to enable regulator.\n",
- __func__);
- return ret;
- }
+ ret = msm_dss_enable_vreg(
+ ctrl_pdata->power_data.vreg_config,
+ ctrl_pdata->power_data.num_vreg, 1);
+ if (ret) {
+ pr_err("%s:Failed to enable vregs.rc=%d\n",
+ __func__, ret);
+ goto error;
}
if (pdata->panel_info.panel_power_on == 0)
@@ -190,65 +81,16 @@
mdss_dsi_panel_reset(pdata, 0);
- if (ctrl_pdata->power_data.num_vreg > 0) {
- ret = msm_dss_enable_vreg(
- ctrl_pdata->power_data.vreg_config,
- ctrl_pdata->power_data.num_vreg, 0);
- if (ret) {
- pr_err("%s: Failed to disable regs.rc=%d\n",
- __func__, ret);
- return ret;
- }
- } else {
- ret = regulator_disable(
- (ctrl_pdata->shared_pdata).vdd_vreg);
- if (ret) {
- pr_err("%s: Failed to disable regulator.\n",
- __func__);
- return ret;
- }
-
- ret = regulator_disable(
- (ctrl_pdata->shared_pdata).vdda_vreg);
- if (ret) {
- pr_err("%s: Failed to disable regulator.\n",
- __func__);
- return ret;
- }
-
- ret = regulator_disable(
- (ctrl_pdata->shared_pdata).vdd_io_vreg);
- if (ret) {
- pr_err("%s: Failed to disable regulator.\n",
- __func__);
- return ret;
- }
-
- ret = regulator_set_optimum_mode(
- (ctrl_pdata->shared_pdata).vdd_vreg, 100);
- if (ret < 0) {
- pr_err("%s: vdd_vreg set opt mode failed.\n",
- __func__);
- return ret;
- }
-
- ret = regulator_set_optimum_mode(
- (ctrl_pdata->shared_pdata).vdd_io_vreg, 100);
- if (ret < 0) {
- pr_err("%s: vdd_io_vreg set opt mode failed.\n",
- __func__);
- return ret;
- }
- ret = regulator_set_optimum_mode(
- (ctrl_pdata->shared_pdata).vdda_vreg, 100);
- if (ret < 0) {
- pr_err("%s: vdda_vreg set opt mode failed.\n",
- __func__);
- return ret;
- }
+ ret = msm_dss_enable_vreg(
+ ctrl_pdata->power_data.vreg_config,
+ ctrl_pdata->power_data.num_vreg, 0);
+ if (ret) {
+ pr_err("%s: Failed to disable vregs.rc=%d\n",
+ __func__, ret);
}
}
- return 0;
+error:
+ return ret;
}
static void mdss_dsi_put_dt_vreg_data(struct device *dev,
@@ -269,10 +111,9 @@
static int mdss_dsi_get_dt_vreg_data(struct device *dev,
struct dss_module_power *mp)
{
- int i, rc = 0;
- int dt_vreg_total = 0;
- u32 *val_array = NULL;
- struct device_node *of_node = NULL;
+ int i = 0, rc = 0;
+ u32 tmp = 0;
+ struct device_node *of_node = NULL, *supply_node = NULL;
if (!dev || !mp) {
pr_err("%s: invalid input\n", __func__);
@@ -283,94 +124,131 @@
of_node = dev->of_node;
mp->num_vreg = 0;
- dt_vreg_total = of_property_count_strings(of_node, "qcom,supply-names");
- if (dt_vreg_total < 0) {
- pr_debug("%s: vreg not found. rc=%d\n", __func__,
- dt_vreg_total);
- rc = 0;
- goto error;
- } else {
- pr_debug("%s: vreg found. count=%d\n", __func__, dt_vreg_total);
+ for_each_child_of_node(of_node, supply_node) {
+ if (!strncmp(supply_node->name, "qcom,platform-supply-entry",
+ 26))
+ ++mp->num_vreg;
}
-
- if (dt_vreg_total > 0) {
- mp->num_vreg = dt_vreg_total;
- mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) *
- dt_vreg_total, GFP_KERNEL);
- if (!mp->vreg_config) {
- pr_err("%s: can't alloc vreg mem\n", __func__);
- goto error;
- }
- } else {
+ if (mp->num_vreg == 0) {
pr_debug("%s: no vreg\n", __func__);
- return 0;
+ goto novreg;
+ } else {
+ pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg);
}
- val_array = devm_kzalloc(dev, sizeof(u32) * dt_vreg_total, GFP_KERNEL);
- if (!val_array) {
- pr_err("%s: can't allocate vreg scratch mem\n", __func__);
+ 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 (i = 0; i < dt_vreg_total; i++) {
- const char *st = NULL;
- /* vreg-name */
- rc = of_property_read_string_index(of_node, "qcom,supply-names",
- i, &st);
- if (rc) {
- pr_err("%s: error reading name. i=%d, rc=%d\n",
- __func__, i, rc);
- goto error;
- }
- snprintf(mp->vreg_config[i].vreg_name,
- ARRAY_SIZE((mp->vreg_config[i].vreg_name)), "%s", st);
+ for_each_child_of_node(of_node, supply_node) {
+ if (!strncmp(supply_node->name, "qcom,platform-supply-entry",
+ 26)) {
+ 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;
+ }
+ snprintf(mp->vreg_config[i].vreg_name,
+ ARRAY_SIZE((mp->vreg_config[i].vreg_name)),
+ "%s", st);
+ /* 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-min-voltage */
- memset(val_array, 0, sizeof(u32) * dt_vreg_total);
- rc = of_property_read_u32_array(of_node,
- "qcom,supply-min-voltage-level", val_array,
- dt_vreg_total);
- if (rc) {
- pr_err("%s: error reading min volt. rc=%d\n",
- __func__, rc);
- goto error;
- }
- mp->vreg_config[i].min_voltage = val_array[i];
+ /* 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;
- /* vreg-max-voltage */
- memset(val_array, 0, sizeof(u32) * dt_vreg_total);
- rc = of_property_read_u32_array(of_node,
- "qcom,supply-max-voltage-level", val_array,
- dt_vreg_total);
- if (rc) {
- pr_err("%s: error reading max volt. rc=%d\n",
- __func__, rc);
- goto error;
- }
- mp->vreg_config[i].max_voltage = val_array[i];
+ /* 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;
- /* vreg-peak-current*/
- memset(val_array, 0, sizeof(u32) * dt_vreg_total);
- rc = of_property_read_u32_array(of_node,
- "qcom,supply-peak-current", val_array,
- dt_vreg_total);
- if (rc) {
- pr_err("%s: error reading peak current. rc=%d\n",
- __func__, rc);
- goto error;
- }
- mp->vreg_config[i].enable_load = val_array[i];
+ /* 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;
- pr_debug("%s: %s min=%d, max=%d, pc=%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);
+ /* 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;
+ }
}
- devm_kfree(dev, val_array);
-
return rc;
error:
@@ -378,10 +256,9 @@
devm_kfree(dev, mp->vreg_config);
mp->vreg_config = NULL;
}
+novreg:
mp->num_vreg = 0;
- if (val_array)
- devm_kfree(dev, val_array);
return rc;
}
@@ -937,14 +814,14 @@
struct mdss_panel_common_pdata *panel_data)
{
struct mipi_panel_info *mipi;
- int rc;
+ int rc, i, len;
u8 lanes = 0, bpp;
- u32 h_period, v_period, dsi_pclk_rate;
+ 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 broadcast;
bool cont_splash_enabled = false;
+ const char *data;
h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
+ (panel_data->panel_info.lcdc.h_back_porch)
@@ -1010,7 +887,7 @@
mipi->dsi_pclk_rate = dsi_pclk_rate;
dsi_ctrl_np = of_parse_phandle(pdev->dev.of_node,
- "qcom,dsi-ctrl-phandle", 0);
+ "qcom,mdss-dsi-panel-controller", 0);
if (!dsi_ctrl_np) {
pr_err("%s: Dsi controller node not initialized\n", __func__);
return -EPROBE_DEFER;
@@ -1031,13 +908,57 @@
return rc;
}
- broadcast = of_property_read_bool(pdev->dev.of_node,
- "qcom,mdss-pan-broadcast-mode");
- if (broadcast)
- ctrl_pdata->shared_pdata.broadcast_enable = 1;
+ data = of_get_property(ctrl_pdev->dev.of_node,
+ "qcom,platform-strength-ctrl", &len);
+ if ((!data) || (len != 2)) {
+ pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
+ __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];
- ctrl_pdata->disp_en_gpio = of_get_named_gpio(pdev->dev.of_node,
- "qcom,enable-gpio", 0);
+ data = of_get_property(ctrl_pdev->dev.of_node,
+ "qcom,platform-regulator-settings", &len);
+ if ((!data) || (len != 7)) {
+ pr_err("%s:%d, Unable to read Phy regulator settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++) {
+ (panel_data->panel_info.mipi.dsi_phy_db)->regulator[i]
+ = data[i];
+ }
+
+ data = of_get_property(ctrl_pdev->dev.of_node,
+ "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++) {
+ (panel_data->panel_info.mipi.dsi_phy_db)->bistCtrl[i]
+ = data[i];
+ }
+
+ data = of_get_property(ctrl_pdev->dev.of_node,
+ "qcom,platform-lane-config", &len);
+ if ((!data) || (len != 45)) {
+ pr_err("%s:%d, Unable to read Phy lane configure settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++) {
+ (panel_data->panel_info.mipi.dsi_phy_db)->laneCfg[i] =
+ data[i];
+ }
+
+ ctrl_pdata->shared_pdata.broadcast_enable = of_property_read_bool(
+ pdev->dev.of_node, "qcom,mdss-dsi-panel-broadcast-mode");
+
+ ctrl_pdata->disp_en_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+ "qcom,platform-enable-gpio", 0);
if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
pr_err("%s:%d, Disp_en gpio not specified\n",
__func__, __LINE__);
@@ -1051,8 +972,8 @@
}
}
- ctrl_pdata->disp_te_gpio = of_get_named_gpio(pdev->dev.of_node,
- "qcom,te-gpio", 0);
+ 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",
__func__, __LINE__);
@@ -1089,9 +1010,17 @@
ctrl_pdata->disp_te_gpio);
}
+ rc = of_property_read_u32_array(ctrl_pdev->dev.of_node,
+ "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(pdev->dev.of_node,
- "qcom,rst-gpio", 0);
+ ctrl_pdata->rst_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+ "qcom,platform-reset-gpio", 0);
if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
pr_err("%s:%d, reset gpio not specified\n",
__func__, __LINE__);
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 8a8e4ca..2603648 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -194,6 +194,8 @@
#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
+#define MDSS_DSI_RST_SEQ_LEN 6
+
struct dsi_buf {
u32 *hdr; /* dsi host header */
char *start; /* buffer start addr */
@@ -346,6 +348,7 @@
u32 pclk_rate;
u32 byte_clk_rate;
struct dss_module_power power_data;
+ int rst_seq[MDSS_DSI_RST_SEQ_LEN];
u32 dsi_irq_mask;
struct mdss_hw *dsi_hw;
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index e682e69..5f5084d 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -44,6 +44,14 @@
void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
{
+ if (ctrl->shared_pdata.broadcast_enable)
+ if (ctrl->panel_data.panel_info.pdest
+ == DISPLAY_1) {
+ pr_debug("%s: Broadcast mode enabled.\n",
+ __func__);
+ left_ctrl_pdata = ctrl;
+ }
+
if (ctrl->panel_data.panel_info.pdest == DISPLAY_1) {
mdss_dsi0_hw.ptr = (void *)(ctrl);
ctrl->dsi_hw = &mdss_dsi0_hw;
@@ -861,13 +869,6 @@
else
MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x14000000);
- if (ctrl_pdata->shared_pdata.broadcast_enable)
- if (pdata->panel_info.pdest == DISPLAY_1) {
- pr_debug("%s: Broadcast mode enabled.\n",
- __func__);
- left_ctrl_pdata = ctrl_pdata;
- }
-
data = 0;
if (pinfo->te_sel)
data |= BIT(31);
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 05a84e3..9a019f9 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -158,6 +158,7 @@
void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ int i;
if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
@@ -181,12 +182,11 @@
pr_debug("%s: enable = %d\n", __func__, enable);
if (enable) {
- gpio_set_value((ctrl_pdata->rst_gpio), 1);
- msleep(20);
- gpio_set_value((ctrl_pdata->rst_gpio), 0);
- udelay(200);
- gpio_set_value((ctrl_pdata->rst_gpio), 1);
- msleep(20);
+ for (i = 0; i < MDSS_DSI_RST_SEQ_LEN; ++i) {
+ gpio_set_value((ctrl_pdata->rst_gpio),
+ ctrl_pdata->rst_seq[i]);
+ msleep(ctrl_pdata->rst_seq[++i]);
+ }
if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
gpio_set_value((ctrl_pdata->disp_en_gpio), 1);
if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
@@ -348,11 +348,11 @@
len -= dchdr->dlen;
}
- pcmds->link_state = DSI_LP_MODE; /* default */
-
data = of_get_property(np, link_key, NULL);
- if (!strncmp(data, "DSI_HS_MODE", 11))
+ if (!strncmp(data, "dsi_hs_mode", 11))
pcmds->link_state = DSI_HS_MODE;
+ else
+ pcmds->link_state = DSI_LP_MODE;
pr_debug("%s: dcs_cmd=%x len=%d, cmd_cnt=%d link_state=%d\n", __func__,
pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt, pcmds->link_state);
@@ -361,44 +361,188 @@
}
+static int mdss_panel_dt_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing,
+ char *dst_format)
+{
+ int rc = 0;
+ switch (bpp) {
+ case 3:
+ *dst_format = DSI_CMD_DST_FORMAT_RGB111;
+ break;
+ case 8:
+ *dst_format = DSI_CMD_DST_FORMAT_RGB332;
+ break;
+ case 12:
+ *dst_format = DSI_CMD_DST_FORMAT_RGB444;
+ break;
+ case 16:
+ switch (mipi_mode) {
+ case DSI_VIDEO_MODE:
+ *dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
+ break;
+ case DSI_CMD_MODE:
+ *dst_format = DSI_CMD_DST_FORMAT_RGB565;
+ break;
+ default:
+ *dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
+ break;
+ }
+ break;
+ case 18:
+ switch (mipi_mode) {
+ case DSI_VIDEO_MODE:
+ if (pixel_packing == 0)
+ *dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
+ else
+ *dst_format = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE;
+ break;
+ case DSI_CMD_MODE:
+ *dst_format = DSI_CMD_DST_FORMAT_RGB666;
+ break;
+ default:
+ if (pixel_packing == 0)
+ *dst_format = DSI_VIDEO_DST_FORMAT_RGB666;
+ else
+ *dst_format = DSI_VIDEO_DST_FORMAT_RGB666_LOOSE;
+ break;
+ }
+ break;
+ case 24:
+ switch (mipi_mode) {
+ case DSI_VIDEO_MODE:
+ *dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ break;
+ case DSI_CMD_MODE:
+ *dst_format = DSI_CMD_DST_FORMAT_RGB888;
+ break;
+ default:
+ *dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ break;
+ }
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
+
+static int mdss_dsi_parse_fbc_params(struct device_node *np,
+ struct mdss_panel_info *panel_info)
+{
+ int rc, fbc_enabled = 0;
+ u32 tmp;
+
+ fbc_enabled = of_property_read_bool(np, "qcom,mdss-dsi-fbc-enable");
+ if (fbc_enabled) {
+ pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__);
+ panel_info->fbc.enabled = 1;
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bpp", &tmp);
+ panel_info->fbc.target_bpp = (!rc ? tmp : panel_info->bpp);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-packing",
+ &tmp);
+ panel_info->fbc.comp_mode = (!rc ? tmp : 0);
+ panel_info->fbc.qerr_enable = of_property_read_bool(np,
+ "qcom,mdss-dsi-fbc-quant-error");
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-bias", &tmp);
+ panel_info->fbc.cd_bias = (!rc ? tmp : 0);
+ panel_info->fbc.pat_enable = of_property_read_bool(np,
+ "qcom,mdss-dsi-fbc-pat-mode");
+ panel_info->fbc.vlc_enable = of_property_read_bool(np,
+ "qcom,mdss-dsi-fbc-vlc-mode");
+ panel_info->fbc.bflc_enable = of_property_read_bool(np,
+ "qcom,mdss-dsi-fbc-bflc-mode");
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-h-line-budget",
+ &tmp);
+ panel_info->fbc.line_x_budget = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-budget-ctrl",
+ &tmp);
+ panel_info->fbc.block_x_budget = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-block-budget",
+ &tmp);
+ panel_info->fbc.block_budget = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np,
+ "qcom,mdss-dsi-fbc-lossless-threshold", &tmp);
+ panel_info->fbc.lossless_mode_thd = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np,
+ "qcom,mdss-dsi-fbc-lossy-threshold", &tmp);
+ panel_info->fbc.lossy_mode_thd = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-fbc-rgb-threshold",
+ &tmp);
+ panel_info->fbc.lossy_rgb_thd = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np,
+ "qcom,mdss-dsi-fbc-lossy-mode-idx", &tmp);
+ panel_info->fbc.lossy_mode_idx = (!rc ? tmp : 0);
+ } else {
+ pr_debug("%s:%d Panel does not support FBC.\n",
+ __func__, __LINE__);
+ panel_info->fbc.enabled = 0;
+ panel_info->fbc.target_bpp =
+ panel_info->bpp;
+ }
+ return 0;
+}
+
+
static int mdss_panel_parse_dt(struct platform_device *pdev,
- struct mdss_panel_common_pdata *panel_data)
+ struct mdss_panel_common_pdata *panel_data)
{
struct device_node *np = pdev->dev.of_node;
- u32 res[6], tmp;
- u32 fbc_res[7];
+ u32 tmp;
int rc, i, len;
const char *data;
- static const char *bl_ctrl_type, *pdest;
- bool fbc_enabled = false;
+ static const char *pdest;
- rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-width", &tmp);
if (rc) {
- pr_err("%s:%d, panel resolution not specified\n",
+ pr_err("%s:%d, panel width not specified\n",
__func__, __LINE__);
return -EINVAL;
}
- panel_data->panel_info.xres = (!rc ? res[0] : 640);
- panel_data->panel_info.yres = (!rc ? res[1] : 480);
+ panel_data->panel_info.xres = (!rc ? tmp : 640);
- 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);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-height", &tmp);
if (rc) {
- pr_err("%s:%d, panel bpp not specified\n",
+ pr_err("%s:%d, panel height not specified\n",
__func__, __LINE__);
return -EINVAL;
}
+ panel_data->panel_info.yres = (!rc ? tmp : 480);
+
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp);
+ panel_data->panel_info.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;
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-v-top-border", &tmp);
+ panel_data->panel_info.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;
+ 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;
+ 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;
+ 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));
+ if (rc) {
+ pr_debug("%s: problem determining dst format. Set Default\n",
+ __func__);
+ panel_data->panel_info.mipi.dst_format =
+ DSI_VIDEO_DST_FORMAT_RGB888;
+ }
pdest = of_get_property(pdev->dev.of_node,
- "qcom,mdss-pan-dest", NULL);
+ "qcom,mdss-dsi-panel-destination", NULL);
if (strlen(pdest) != 9) {
pr_err("%s: Unknown pdest specified\n", __func__);
return -EINVAL;
@@ -412,141 +556,132 @@
__func__);
panel_data->panel_info.pdest = DISPLAY_1;
}
-
- rc = of_property_read_u32_array(np,
- "qcom,mdss-pan-porch-values", res, 6);
- 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);
-
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-h-front-porch", &tmp);
+ panel_data->panel_info.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);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-h-pulse-width", &tmp);
+ panel_data->panel_info.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);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-v-back-porch", &tmp);
+ panel_data->panel_info.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);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-v-pulse-width", &tmp);
+ panel_data->panel_info.lcdc.v_pulse_width = (!rc ? tmp : 2);
rc = of_property_read_u32(np,
- "qcom,mdss-pan-underflow-clr", &tmp);
+ "qcom,mdss-dsi-underflow-color", &tmp);
panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
-
- 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__);
-
- panel_data->panel_info.bklt_ctrl = BL_WLED;
- } else if (!strncmp(bl_ctrl_type, "bl_ctrl_pwm", 11)) {
- panel_data->panel_info.bklt_ctrl = BL_PWM;
-
- rc = of_property_read_u32(np, "qcom,pwm-period", &tmp);
- if (rc) {
- pr_err("%s:%d, Error, panel pwm_period\n",
+ 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;
+ data = of_get_property(np, "qcom,mdss-dsi-bl-pmic-control-type", NULL);
+ if (data) {
+ if (!strncmp(data, "bl_ctrl_wled", 12)) {
+ led_trigger_register_simple("bkl-trigger",
+ &bl_led_trigger);
+ pr_debug("%s: SUCCESS-> WLED TRIGGER register\n",
+ __func__);
+ panel_data->panel_info.bklt_ctrl = BL_WLED;
+ } else if (!strncmp(data, "bl_ctrl_pwm", 11)) {
+ panel_data->panel_info.bklt_ctrl = BL_PWM;
+ rc = of_property_read_u32(np,
+ "qcom,mdss-dsi-bl-pmic-pwm-frequency", &tmp);
+ if (rc) {
+ pr_err("%s:%d, Error, panel pwm_period\n",
__func__, __LINE__);
- return -EINVAL;
- }
- panel_data->panel_info.pwm_period = tmp;
-
- rc = of_property_read_u32(np, "qcom,pwm-lpg-channel", &tmp);
- if (rc) {
- pr_err("%s:%d, Error, dsi lpg channel\n",
+ return -EINVAL;
+ }
+ panel_data->panel_info.pwm_period = tmp;
+ rc = of_property_read_u32(np,
+ "qcom,mdss-dsi-bl-pmic-bank-select", &tmp);
+ if (rc) {
+ pr_err("%s:%d, Error, dsi lpg channel\n",
__func__, __LINE__);
- return -EINVAL;
+ return -EINVAL;
+ }
+ panel_data->panel_info.pwm_lpg_chan = tmp;
+ tmp = of_get_named_gpio(np,
+ "qcom,mdss-dsi-pwm-gpio", 0);
+ panel_data->panel_info.pwm_pmic_gpio = tmp;
+ } else if (!strncmp(data, "bl_ctrl_dcs", 11)) {
+ panel_data->panel_info.bklt_ctrl = BL_DCS_CMD;
}
- panel_data->panel_info.pwm_lpg_chan = tmp;
-
- tmp = of_get_named_gpio(np, "qcom,pwm-pmic-gpio", 0);
- panel_data->panel_info.pwm_pmic_gpio = tmp;
- } else if (!strncmp(bl_ctrl_type, "bl_ctrl_dcs", 11)) {
- panel_data->panel_info.bklt_ctrl = BL_DCS_CMD;
- } else {
- pr_debug("%s: Unknown backlight control\n", __func__);
- panel_data->panel_info.bklt_ctrl = UNKNOWN_CTRL;
}
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp);
+ panel_data->panel_info.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);
- rc = of_property_read_u32_array(np,
- "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);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-interleave-mode", &tmp);
+ panel_data->panel_info.mipi.interleave_mode = (!rc ? tmp : 0);
- 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-vsync-enable", &tmp);
- panel_data->panel_info.mipi.vsync_enable = (!rc ? tmp : 0);
-
- rc = of_property_read_u32(np, "qcom,mdss-hw-vsync-mode", &tmp);
- panel_data->panel_info.mipi.hw_vsync_mode = (!rc ? tmp : 0);
-
+ panel_data->panel_info.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,
+ "qcom,mdss-dsi-te-using-te-pin");
rc = of_property_read_u32(np,
- "qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
+ "qcom,mdss-dsi-h-sync-pulse", &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);
-
+ panel_data->panel_info.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,
+ "qcom,mdss-dsi-hsa-power-mode");
+ panel_data->panel_info.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,
+ "qcom,mdss-dsi-bllp-power-mode");
+ panel_data->panel_info.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-pan-dsi-traffic-mode", &tmp);
+ "qcom,mdss-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-insert-dcs-cmd", &tmp);
+ "qcom,mdss-dsi-te-dcs-command", &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);
+ "qcom,mdss-dsi-te-v-sync-continue-lines", &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);
+ "qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line", &tmp);
panel_data->panel_info.mipi.wr_mem_start =
(!rc ? tmp : 0x2c);
-
rc = of_property_read_u32(np,
- "qcom,mdss-pan-te-sel", &tmp);
+ "qcom,mdss-dsi-te-pin-select", &tmp);
panel_data->panel_info.mipi.te_sel =
(!rc ? tmp : 1);
-
- 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);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-virtual-channel-id", &tmp);
panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
+ 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,
+ "qcom,mdss-dsi-lane-0-state");
+ panel_data->panel_info.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,
+ "qcom,mdss-dsi-lane-2-state");
+ panel_data->panel_info.mipi.data_lane3 = of_property_read_bool(np,
+ "qcom,mdss-dsi-lane-3-state");
- 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);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-lane-map", &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-dsi-t-clk-pre", &tmp);
+ panel_data->panel_info.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);
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-stream", &tmp);
panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-mdp-trigger", &tmp);
panel_data->panel_info.mipi.mdp_trigger =
(!rc ? tmp : DSI_CMD_TRIGGER_SW);
if (panel_data->panel_info.mipi.mdp_trigger > 6) {
@@ -556,7 +691,7 @@
DSI_CMD_TRIGGER_SW;
}
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-dma-trigger", &tmp);
panel_data->panel_info.mipi.dma_trigger =
(!rc ? tmp : DSI_CMD_TRIGGER_SW);
if (panel_data->panel_info.mipi.dma_trigger > 6) {
@@ -565,23 +700,11 @@
panel_data->panel_info.mipi.dma_trigger =
DSI_CMD_TRIGGER_SW;
}
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-frame-rate", &tmp);
panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
-
- rc = of_property_read_u32(np, "qcom,mdss-pan-clk-rate", &tmp);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-clock-rate", &tmp);
panel_data->panel_info.clk_rate = (!rc ? tmp : 0);
-
- data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
- if ((!data) || (len != 7)) {
- pr_err("%s:%d, Unable to read Phy regulator settings",
- __func__, __LINE__);
- goto error;
- }
- for (i = 0; i < len; i++)
- phy_params.regulator[i] = data[i];
-
- data = of_get_property(np, "qcom,panel-phy-timingSettings", &len);
+ 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",
__func__, __LINE__);
@@ -590,87 +713,15 @@
for (i = 0; i < len; i++)
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__);
- goto error;
- }
- phy_params.strength[0] = data[0];
- 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__);
- goto error;
- }
- for (i = 0; i < len; i++)
- phy_params.bistCtrl[i] = data[i];
-
- data = of_get_property(np, "qcom,panel-phy-laneConfig", &len);
- if ((!data) || (len != 45)) {
- pr_err("%s:%d, Unable to read Phy lane configure settings",
- __func__, __LINE__);
- goto error;
- }
- for (i = 0; i < len; i++)
- phy_params.laneCfg[i] = data[i];
-
panel_data->panel_info.mipi.dsi_phy_db = &phy_params;
- fbc_enabled = of_property_read_bool(np,
- "qcom,fbc-enabled");
- if (fbc_enabled) {
- pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__);
- panel_data->panel_info.fbc.enabled = 1;
-
- rc = of_property_read_u32_array(np,
- "qcom,fbc-mode", fbc_res, 7);
- panel_data->panel_info.fbc.target_bpp =
- (!rc ? fbc_res[0] : panel_data->panel_info.bpp);
- panel_data->panel_info.fbc.comp_mode = (!rc ? fbc_res[1] : 0);
- panel_data->panel_info.fbc.qerr_enable =
- (!rc ? fbc_res[2] : 0);
- panel_data->panel_info.fbc.cd_bias = (!rc ? fbc_res[3] : 0);
- panel_data->panel_info.fbc.pat_enable = (!rc ? fbc_res[4] : 0);
- panel_data->panel_info.fbc.vlc_enable = (!rc ? fbc_res[5] : 0);
- panel_data->panel_info.fbc.bflc_enable =
- (!rc ? fbc_res[6] : 0);
-
- rc = of_property_read_u32_array(np,
- "qcom,fbc-budget-ctl", fbc_res, 3);
- panel_data->panel_info.fbc.line_x_budget =
- (!rc ? fbc_res[0] : 0);
- panel_data->panel_info.fbc.block_x_budget =
- (!rc ? fbc_res[1] : 0);
- panel_data->panel_info.fbc.block_budget =
- (!rc ? fbc_res[2] : 0);
-
- rc = of_property_read_u32_array(np,
- "qcom,fbc-lossy-mode", fbc_res, 4);
- panel_data->panel_info.fbc.lossless_mode_thd =
- (!rc ? fbc_res[0] : 0);
- panel_data->panel_info.fbc.lossy_mode_thd =
- (!rc ? fbc_res[1] : 0);
- panel_data->panel_info.fbc.lossy_rgb_thd =
- (!rc ? fbc_res[2] : 0);
- panel_data->panel_info.fbc.lossy_mode_idx =
- (!rc ? fbc_res[3] : 0);
-
- } else {
- pr_debug("%s:%d Panel does not support FBC.\n",
- __func__, __LINE__);
- panel_data->panel_info.fbc.enabled = 0;
- panel_data->panel_info.fbc.target_bpp =
- panel_data->panel_info.bpp;
- }
+ mdss_dsi_parse_fbc_params(np, &panel_data->panel_info);
mdss_dsi_parse_dcs_cmds(np, &panel_data->on_cmds,
- "qcom,panel-on-cmds", "qcom,on-cmds-dsi-state");
+ "qcom,mdss-dsi-on-command", "qcom,mdss-dsi-on-command-state");
mdss_dsi_parse_dcs_cmds(np, &panel_data->off_cmds,
- "qcom,panel-off-cmds", "qcom,off-cmds-dsi-state");
+ "qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state");
return 0;
@@ -683,12 +734,12 @@
int rc = 0;
static struct mdss_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);
+ panel_name = of_get_property(pdev->dev.of_node,
+ "qcom,mdss-dsi-panel-name", NULL);
if (!panel_name)
pr_info("%s:%d, panel name not specified\n",
__func__, __LINE__);
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index aea2de0..3e0bc6d 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -24,14 +24,19 @@
#include <linux/err.h>
#include <linux/regulator/consumer.h>
#include <linux/pwm.h>
-
+#include <linux/clk.h>
+#include <linux/spinlock_types.h>
+#include <linux/kthread.h>
#include <asm/system.h>
#include <asm/mach-types.h>
-
#include <mach/hardware.h>
#include <mach/dma.h>
+#include "mdss.h"
+#include "mdss_panel.h"
+#include "mdss_mdp.h"
#include "mdss_edp.h"
+#include "mdss_debug.h"
#define RGB_COMPONENTS 3
#define VDDA_MIN_UV 1800000 /* uV units */
@@ -39,26 +44,7 @@
#define VDDA_UA_ON_LOAD 100000 /* uA units */
#define VDDA_UA_OFF_LOAD 100 /* uA units */
-static int mdss_edp_get_base_address(struct mdss_edp_drv_pdata *edp_drv);
-static int mdss_edp_get_mmss_cc_base_address(struct mdss_edp_drv_pdata
- *edp_drv);
-static int mdss_edp_regulator_init(struct mdss_edp_drv_pdata *edp_drv);
static int mdss_edp_regulator_on(struct mdss_edp_drv_pdata *edp_drv);
-static int mdss_edp_regulator_off(struct mdss_edp_drv_pdata *edp_drv);
-static int mdss_edp_gpio_panel_en(struct mdss_edp_drv_pdata *edp_drv);
-static int mdss_edp_pwm_config(struct mdss_edp_drv_pdata *edp_drv);
-
-static void mdss_edp_edid2pinfo(struct mdss_edp_drv_pdata *edp_drv);
-static void mdss_edp_fill_edid_data(struct mdss_edp_drv_pdata *edp_drv);
-static void mdss_edp_fill_dpcd_data(struct mdss_edp_drv_pdata *edp_drv);
-
-static int mdss_edp_device_register(struct mdss_edp_drv_pdata *edp_drv);
-
-static void mdss_edp_config_sync(unsigned char *edp_base);
-static void mdss_edp_config_sw_div(unsigned char *edp_base);
-static void mdss_edp_config_static_mdiv(unsigned char *edp_base);
-static void mdss_edp_enable(unsigned char *edp_base, int enable);
-
/*
* Init regulator needed for edp, 8974_l12
*/
@@ -256,79 +242,130 @@
}
}
-void mdss_edp_config_sync(unsigned char *edp_base)
+void mdss_edp_config_sync(unsigned char *base)
{
int ret = 0;
- ret = edp_read(edp_base + 0xc); /* EDP_CONFIGURATION_CTRL */
+ ret = edp_read(base + 0xc); /* EDP_CONFIGURATION_CTRL */
ret &= ~0x733;
ret |= (0x55 & 0x733);
- edp_write(edp_base + 0xc, ret);
- edp_write(edp_base + 0xc, 0x55); /* EDP_CONFIGURATION_CTRL */
+ edp_write(base + 0xc, ret);
+ edp_write(base + 0xc, 0x55); /* EDP_CONFIGURATION_CTRL */
}
-static void mdss_edp_config_sw_div(unsigned char *edp_base)
+static void mdss_edp_config_sw_div(unsigned char *base)
{
- edp_write(edp_base + 0x14, 0x13b); /* EDP_SOFTWARE_MVID */
- edp_write(edp_base + 0x18, 0x266); /* EDP_SOFTWARE_NVID */
+ edp_write(base + 0x14, 0x13b); /* EDP_SOFTWARE_MVID */
+ edp_write(base + 0x18, 0x266); /* EDP_SOFTWARE_NVID */
}
-static void mdss_edp_config_static_mdiv(unsigned char *edp_base)
+static void mdss_edp_config_static_mdiv(unsigned char *base)
{
int ret = 0;
- ret = edp_read(edp_base + 0xc); /* EDP_CONFIGURATION_CTRL */
- edp_write(edp_base + 0xc, ret | 0x2); /* EDP_CONFIGURATION_CTRL */
- edp_write(edp_base + 0xc, 0x57); /* EDP_CONFIGURATION_CTRL */
+ ret = edp_read(base + 0xc); /* EDP_CONFIGURATION_CTRL */
+ edp_write(base + 0xc, ret | 0x2); /* EDP_CONFIGURATION_CTRL */
+ edp_write(base + 0xc, 0x57); /* EDP_CONFIGURATION_CTRL */
}
-static void mdss_edp_enable(unsigned char *edp_base, int enable)
+static void mdss_edp_enable(unsigned char *base, int enable)
{
- edp_write(edp_base + 0x8, 0x0); /* EDP_STATE_CTRL */
- edp_write(edp_base + 0x8, 0x40); /* EDP_STATE_CTRL */
- edp_write(edp_base + 0x94, enable); /* EDP_TIMING_ENGINE_EN */
- edp_write(edp_base + 0x4, enable); /* EDP_MAINLINK_CTRL */
+ edp_write(base + 0x8, 0x0); /* EDP_STATE_CTRL */
+ edp_write(base + 0x8, 0x40); /* EDP_STATE_CTRL */
+ edp_write(base + 0x94, enable); /* EDP_TIMING_ENGINE_EN */
+ edp_write(base + 0x4, enable); /* EDP_MAINLINK_CTRL */
}
+static void mdss_edp_irq_enable(struct mdss_edp_drv_pdata *edp_drv);
+static void mdss_edp_irq_disable(struct mdss_edp_drv_pdata *edp_drv);
+
int mdss_edp_on(struct mdss_panel_data *pdata)
{
struct mdss_edp_drv_pdata *edp_drv = NULL;
- int i;
+ int ret = 0;
- edp_drv = container_of(pdata, struct mdss_edp_drv_pdata,
- panel_data);
- if (!edp_drv) {
+ if (!pdata) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
- mdss_edp_prepare_clocks(edp_drv);
- mdss_edp_phy_sw_reset(edp_drv->edp_base);
- mdss_edp_hw_powerup(edp_drv->edp_base, 1);
- mdss_edp_pll_configure(edp_drv->edp_base, edp_drv->edid.timing[0].pclk);
- mdss_edp_clk_enable(edp_drv);
+ edp_drv = container_of(pdata, struct mdss_edp_drv_pdata,
+ panel_data);
- for (i = 0; i < edp_drv->dpcd.max_lane_count; ++i)
- mdss_edp_enable_lane_bist(edp_drv->edp_base, i, 1);
+ pr_debug("%s:+\n", __func__);
+ if (edp_drv->train_start == 0)
+ edp_drv->train_start++;
- mdss_edp_enable_mainlink(edp_drv->edp_base, 1);
- mdss_edp_config_clk(edp_drv->edp_base, edp_drv->mmss_cc_base);
+ mdss_edp_phy_pll_reset(edp_drv->base);
+ mdss_edp_aux_reset(edp_drv->base);
+ mdss_edp_mainlink_reset(edp_drv->base);
- mdss_edp_phy_misc_cfg(edp_drv->edp_base);
- mdss_edp_config_sync(edp_drv->edp_base);
- mdss_edp_config_sw_div(edp_drv->edp_base);
- mdss_edp_config_static_mdiv(edp_drv->edp_base);
- mdss_edp_enable(edp_drv->edp_base, 1);
+ ret = mdss_edp_prepare_clocks(edp_drv);
+ if (ret)
+ return ret;
+ mdss_edp_phy_powerup(edp_drv->base, 1);
+
+ mdss_edp_pll_configure(edp_drv->base, edp_drv->edid.timing[0].pclk);
+ mdss_edp_phy_pll_ready(edp_drv->base);
+
+ ret = mdss_edp_clk_enable(edp_drv);
+ if (ret) {
+ mdss_edp_unprepare_clocks(edp_drv);
+ return ret;
+ }
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+ mdss_edp_aux_ctrl(edp_drv->base, 1);
+
+ mdss_edp_lane_power_ctrl(edp_drv->base,
+ edp_drv->dpcd.max_lane_count, 1);
+ mdss_edp_enable_mainlink(edp_drv->base, 1);
+ mdss_edp_config_clk(edp_drv->base, edp_drv->mmss_cc_base);
+
+ mdss_edp_clock_synchrous(edp_drv->base, 1);
+ mdss_edp_phy_vm_pe_init(edp_drv->base);
+ mdss_edp_config_sync(edp_drv->base);
+ mdss_edp_config_sw_div(edp_drv->base);
+ mdss_edp_config_static_mdiv(edp_drv->base);
gpio_set_value(edp_drv->gpio_panel_en, 1);
+ mdss_edp_irq_enable(edp_drv);
+ pr_debug("%s:-\n", __func__);
return 0;
}
+int mdss_edp_wait4train(struct mdss_panel_data *pdata)
+{
+ struct mdss_edp_drv_pdata *edp_drv = NULL;
+ int ret = 0;
+
+ if (!pdata) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ edp_drv = container_of(pdata, struct mdss_edp_drv_pdata,
+ panel_data);
+
+ ret = wait_for_completion_timeout(&edp_drv->train_comp, 100);
+ if (ret <= 0) {
+ pr_err("%s: Link Train timedout\n", __func__);
+ ret = -EINVAL;
+ } else {
+ ret = 0;
+ }
+
+ mdss_edp_enable(edp_drv->base, 1);
+
+ pr_debug("%s:\n", __func__);
+
+ return ret;
+}
+
int mdss_edp_off(struct mdss_panel_data *pdata)
{
struct mdss_edp_drv_pdata *edp_drv = NULL;
int ret = 0;
- int i;
edp_drv = container_of(pdata, struct mdss_edp_drv_pdata,
panel_data);
@@ -336,20 +373,26 @@
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
+ pr_debug("%s:+\n", __func__);
+
+ mdss_edp_irq_disable(edp_drv);
gpio_set_value(edp_drv->gpio_panel_en, 0);
pwm_disable(edp_drv->bl_pwm);
- mdss_edp_enable(edp_drv->edp_base, 0);
- mdss_edp_unconfig_clk(edp_drv->edp_base, edp_drv->mmss_cc_base);
- mdss_edp_enable_mainlink(edp_drv->edp_base, 0);
+ mdss_edp_enable(edp_drv->base, 0);
+ mdss_edp_unconfig_clk(edp_drv->base, edp_drv->mmss_cc_base);
+ mdss_edp_enable_mainlink(edp_drv->base, 0);
- for (i = 0; i < edp_drv->dpcd.max_lane_count; ++i)
- mdss_edp_enable_lane_bist(edp_drv->edp_base, i, 0);
-
+ mdss_edp_lane_power_ctrl(edp_drv->base,
+ edp_drv->dpcd.max_lane_count, 0);
mdss_edp_clk_disable(edp_drv);
- mdss_edp_hw_powerup(edp_drv->edp_base, 0);
+ mdss_edp_phy_powerup(edp_drv->base, 0);
mdss_edp_unprepare_clocks(edp_drv);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ mdss_edp_aux_ctrl(edp_drv->base, 0);
+
+ pr_debug("%s:-\n", __func__);
return ret;
}
@@ -363,6 +406,9 @@
case MDSS_EVENT_UNBLANK:
rc = mdss_edp_on(pdata);
break;
+ case MDSS_EVENT_PANEL_ON:
+ rc = mdss_edp_wait4train(pdata);
+ break;
case MDSS_EVENT_PANEL_OFF:
rc = mdss_edp_off(pdata);
break;
@@ -382,20 +428,31 @@
pinfo = &edp_drv->panel_data.panel_info;
pinfo->clk_rate = dp->pclk;
+ pr_debug("%s: pclk=%d\n", __func__, pinfo->clk_rate);
pinfo->xres = dp->h_addressable + dp->h_border * 2;
pinfo->yres = dp->v_addressable + dp->v_border * 2;
+ pr_debug("%s: x=%d y=%d\n", __func__, pinfo->xres, pinfo->yres);
+
pinfo->lcdc.h_back_porch = dp->h_blank - dp->h_fporch \
- dp->h_sync_pulse;
pinfo->lcdc.h_front_porch = dp->h_fporch;
pinfo->lcdc.h_pulse_width = dp->h_sync_pulse;
+ pr_debug("%s: hporch= %d %d %d\n", __func__,
+ pinfo->lcdc.h_back_porch, pinfo->lcdc.h_front_porch,
+ pinfo->lcdc.h_pulse_width);
+
pinfo->lcdc.v_back_porch = dp->v_blank - dp->v_fporch \
- dp->v_sync_pulse;
pinfo->lcdc.v_front_porch = dp->v_fporch;
pinfo->lcdc.v_pulse_width = dp->v_sync_pulse;
+ pr_debug("%s: vporch= %d %d %d\n", __func__,
+ pinfo->lcdc.v_back_porch, pinfo->lcdc.v_front_porch,
+ pinfo->lcdc.v_pulse_width);
+
pinfo->type = EDP_PANEL;
pinfo->pdest = DISPLAY_1;
pinfo->wait_cycle = 0;
@@ -415,9 +472,9 @@
gpio_free(edp_drv->gpio_panel_en);
mdss_edp_regulator_off(edp_drv);
- iounmap(edp_drv->edp_base);
+ iounmap(edp_drv->base);
iounmap(edp_drv->mmss_cc_base);
- edp_drv->edp_base = NULL;
+ edp_drv->base = NULL;
return 0;
}
@@ -458,12 +515,19 @@
return -ENOMEM;
}
- edp_drv->edp_base = ioremap(res->start, resource_size(res));
- if (!edp_drv->edp_base) {
+ edp_drv->base_size = resource_size(res);
+ edp_drv->base = ioremap(res->start, resource_size(res));
+ if (!edp_drv->base) {
pr_err("%s: Unable to remap EDP resources", __func__);
return -ENOMEM;
}
+ pr_debug("%s: drv=%x base=%x size=%x\n", __func__,
+ (int)edp_drv, (int)edp_drv->base, edp_drv->base_size);
+
+ mdss_debug_register_base("edp",
+ edp_drv->base, edp_drv->base_size);
+
return 0;
}
@@ -488,52 +552,202 @@
return 0;
}
-static void mdss_edp_fill_edid_data(struct mdss_edp_drv_pdata *edp_drv)
+static void mdss_edp_video_ready(struct mdss_edp_drv_pdata *edp_drv)
{
- struct edp_edid *edid = &edp_drv->edid;
-
- edid->id_name[0] = 'A';
- edid->id_name[0] = 'U';
- edid->id_name[0] = 'O';
- edid->id_name[0] = 0;
- edid->id_product = 0x305D;
- edid->version = 1;
- edid->revision = 4;
- edid->ext_block_cnt = 0;
- edid->video_digital = 0x5;
- edid->color_depth = 6;
- edid->dpm = 0;
- edid->color_format = 0;
- edid->timing[0].pclk = 138500000;
- edid->timing[0].h_addressable = 1920;
- edid->timing[0].h_blank = 160;
- edid->timing[0].v_addressable = 1080;
- edid->timing[0].v_blank = 30;
- edid->timing[0].h_fporch = 48;
- edid->timing[0].h_sync_pulse = 32;
- edid->timing[0].v_sync_pulse = 14;
- edid->timing[0].v_fporch = 8;
- edid->timing[0].width_mm = 256;
- edid->timing[0].height_mm = 144;
- edid->timing[0].h_border = 0;
- edid->timing[0].v_border = 0;
- edid->timing[0].interlaced = 0;
- edid->timing[0].stereo = 0;
- edid->timing[0].sync_type = 1;
- edid->timing[0].sync_separate = 1;
- edid->timing[0].vsync_pol = 0;
- edid->timing[0].hsync_pol = 0;
+ pr_debug("%s: edp_video_ready\n", __func__);
}
-static void mdss_edp_fill_dpcd_data(struct mdss_edp_drv_pdata *edp_drv)
+static int edp_event_thread(void *data)
{
- struct dpcd_cap *cap = &edp_drv->dpcd;
+ struct mdss_edp_drv_pdata *ep;
+ unsigned long flag;
+ u32 todo = 0;
- cap->max_lane_count = 2;
- cap->max_link_clk = 270;
+ ep = (struct mdss_edp_drv_pdata *)data;
+
+ while (1) {
+ wait_event(ep->event_q, (ep->event_pndx != ep->event_gndx));
+ spin_lock_irqsave(&ep->event_lock, flag);
+ if (ep->event_pndx == ep->event_gndx) {
+ spin_unlock_irqrestore(&ep->event_lock, flag);
+ break;
+ }
+ todo = ep->event_todo_list[ep->event_gndx];
+ ep->event_todo_list[ep->event_gndx++] = 0;
+ ep->event_gndx %= HPD_EVENT_MAX;
+ spin_unlock_irqrestore(&ep->event_lock, flag);
+
+ pr_debug("%s: todo=%x\n", __func__, todo);
+
+ if (todo == 0)
+ continue;
+
+ if (todo & EV_EDID_READ)
+ mdss_edp_edid_read(ep, 0);
+
+ if (todo & EV_DPCD_CAP_READ)
+ mdss_edp_dpcd_cap_read(ep);
+
+ if (todo & EV_DPCD_STATUS_READ)
+ mdss_edp_dpcd_status_read(ep);
+
+ if (todo & EV_LINK_TRAIN) {
+ INIT_COMPLETION(ep->train_comp);
+ mdss_edp_link_train(ep);
+ }
+
+ if (todo & EV_VIDEO_READY)
+ mdss_edp_video_ready(ep);
+ }
+
+ return 0;
}
+static void edp_send_events(struct mdss_edp_drv_pdata *ep, u32 events)
+{
+ spin_lock(&ep->event_lock);
+ ep->event_todo_list[ep->event_pndx++] = events;
+ ep->event_pndx %= HPD_EVENT_MAX;
+ wake_up(&ep->event_q);
+ spin_unlock(&ep->event_lock);
+}
+
+irqreturn_t edp_isr(int irq, void *ptr)
+{
+ struct mdss_edp_drv_pdata *ep = (struct mdss_edp_drv_pdata *)ptr;
+ unsigned char *base = ep->base;
+ u32 isr1, isr2, mask1, mask2;
+ u32 ack;
+
+ isr1 = edp_read(base + 0x308);
+ isr2 = edp_read(base + 0x30c);
+
+ mask1 = isr1 & EDP_INTR_MASK1;
+ mask2 = isr2 & EDP_INTR_MASK2;
+
+ isr1 &= ~mask1; /* remove masks bit */
+ isr2 &= ~mask2;
+
+ pr_debug("%s: isr=%x mask=%x isr2=%x mask2=%x\n",
+ __func__, isr1, mask1, isr2, mask2);
+
+ ack = isr1 & EDP_INTR_STATUS1;
+ ack <<= 1; /* ack bits */
+ ack |= mask1;
+ edp_write(base + 0x308, ack);
+
+ ack = isr2 & EDP_INTR_STATUS2;
+ ack <<= 1; /* ack bits */
+ ack |= mask2;
+ edp_write(base + 0x30c, ack);
+
+ if (isr1 & EDP_INTR_HPD) {
+ isr1 &= ~EDP_INTR_HPD; /* clear */
+ if (ep->train_start)
+ edp_send_events(ep, EV_LINK_TRAIN);
+ }
+
+ if (isr2 & EDP_INTR_READY_FOR_VIDEO)
+ edp_send_events(ep, EV_VIDEO_READY);
+
+ if (isr1 && ep->aux_cmd_busy) {
+ /* clear EDP_AUX_TRANS_CTRL */
+ edp_write(base + 0x318, 0);
+ /* read EDP_INTERRUPT_TRANS_NUM */
+ ep->aux_trans_num = edp_read(base + 0x310);
+
+ if (ep->aux_cmd_i2c)
+ edp_aux_i2c_handler(ep, isr1);
+ else
+ edp_aux_native_handler(ep, isr1);
+ }
+
+ return IRQ_HANDLED;
+}
+
+struct mdss_hw mdss_edp_hw = {
+ .hw_ndx = MDSS_HW_EDP,
+ .ptr = NULL,
+ .irq_handler = edp_isr,
+};
+
+static void mdss_edp_irq_enable(struct mdss_edp_drv_pdata *edp_drv)
+{
+ edp_write(edp_drv->base + 0x308, EDP_INTR_MASK1);
+ edp_write(edp_drv->base + 0x30c, EDP_INTR_MASK2);
+
+ mdss_enable_irq(&mdss_edp_hw);
+}
+
+static void mdss_edp_irq_disable(struct mdss_edp_drv_pdata *edp_drv)
+{
+ edp_write(edp_drv->base + 0x308, 0x0);
+ edp_write(edp_drv->base + 0x30c, 0x0);
+
+ mdss_disable_irq(&mdss_edp_hw);
+}
+
+static int mdss_edp_irq_setup(struct mdss_edp_drv_pdata *edp_drv)
+{
+ int ret = 0;
+
+
+ edp_drv->gpio_panel_hpd = of_get_named_gpio_flags(
+ edp_drv->pdev->dev.of_node, "gpio-panel-hpd", 0,
+ &edp_drv->hpd_flags);
+
+ if (!gpio_is_valid(edp_drv->gpio_panel_hpd)) {
+ pr_err("%s gpio_panel_hpd %d is not valid ", __func__,
+ edp_drv->gpio_panel_hpd);
+ return -ENODEV;
+ }
+
+ ret = gpio_request(edp_drv->gpio_panel_hpd, "edp_hpd_irq_gpio");
+ if (ret) {
+ pr_err("%s unable to request gpio_panel_hpd %d", __func__,
+ edp_drv->gpio_panel_hpd);
+ return -ENODEV;
+ }
+
+ ret = gpio_tlmm_config(GPIO_CFG(
+ edp_drv->gpio_panel_hpd,
+ 1,
+ GPIO_CFG_INPUT,
+ GPIO_CFG_NO_PULL,
+ GPIO_CFG_2MA),
+ GPIO_CFG_ENABLE);
+ if (ret) {
+ pr_err("%s: unable to config tlmm = %d\n", __func__,
+ edp_drv->gpio_panel_hpd);
+ gpio_free(edp_drv->gpio_panel_hpd);
+ return -ENODEV;
+ }
+
+ ret = gpio_direction_input(edp_drv->gpio_panel_hpd);
+ if (ret) {
+ pr_err("%s unable to set direction for gpio_panel_hpd %d",
+ __func__, edp_drv->gpio_panel_hpd);
+ return -ENODEV;
+ }
+
+ mdss_edp_hw.ptr = (void *)(edp_drv);
+
+ if (mdss_register_irq(&mdss_edp_hw))
+ pr_err("%s: mdss_register_irq failed.\n", __func__);
+
+
+ return 0;
+}
+
+
+static void mdss_edp_event_setup(struct mdss_edp_drv_pdata *ep)
+{
+ init_waitqueue_head(&ep->event_q);
+ spin_lock_init(&ep->event_lock);
+
+ kthread_run(edp_event_thread, (void *)ep, "mdss_edp_hpd");
+}
static int __devinit mdss_edp_probe(struct platform_device *pdev)
{
@@ -554,6 +768,7 @@
edp_drv->pdev = pdev;
edp_drv->pdev->id = 1;
edp_drv->clk_on = 0;
+ edp_drv->train_start = 0; /* no link train yet */
ret = mdss_edp_get_base_address(edp_drv);
if (ret)
@@ -579,8 +794,38 @@
if (ret)
goto edp_free_gpio_panel_en;
- mdss_edp_fill_edid_data(edp_drv);
- mdss_edp_fill_dpcd_data(edp_drv);
+ mdss_edp_irq_setup(edp_drv);
+
+ mdss_edp_aux_init(edp_drv);
+
+ mdss_edp_event_setup(edp_drv);
+
+ /* need mdss clock to receive irq */
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+ /* only need aux and ahb clock for aux channel */
+ mdss_edp_prepare_aux_clocks(edp_drv);
+ mdss_edp_aux_clk_enable(edp_drv);
+ mdss_edp_phy_pll_reset(edp_drv->base);
+ mdss_edp_aux_reset(edp_drv->base);
+ mdss_edp_mainlink_reset(edp_drv->base);
+ mdss_edp_phy_powerup(edp_drv->base, 1);
+ mdss_edp_aux_ctrl(edp_drv->base, 1);
+
+ mdss_edp_irq_enable(edp_drv);
+
+ mdss_edp_edid_read(edp_drv, 0);
+ mdss_edp_dpcd_cap_read(edp_drv);
+
+ mdss_edp_irq_disable(edp_drv);
+
+ mdss_edp_aux_ctrl(edp_drv->base, 0);
+ mdss_edp_aux_clk_disable(edp_drv);
+ mdss_edp_phy_powerup(edp_drv->base, 0);
+ mdss_edp_unprepare_aux_clocks(edp_drv);
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
mdss_edp_device_register(edp_drv);
return 0;
@@ -594,7 +839,7 @@
mmss_cc_base_unmap:
iounmap(edp_drv->mmss_cc_base);
edp_base_unmap:
- iounmap(edp_drv->edp_base);
+ iounmap(edp_drv->base);
probe_err:
return ret;
diff --git a/drivers/video/msm/mdss/mdss_edp.h b/drivers/video/msm/mdss/mdss_edp.h
index 00ef206..c3f7d0d 100644
--- a/drivers/video/msm/mdss/mdss_edp.h
+++ b/drivers/video/msm/mdss/mdss_edp.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,15 +14,157 @@
#ifndef MDSS_EDP_H
#define MDSS_EDP_H
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/clk.h>
-
-#include "mdss_panel.h"
+#include <linux/of_gpio.h>
#define edp_read(offset) readl_relaxed((offset))
#define edp_write(offset, data) writel_relaxed((data), (offset))
+#define AUX_CMD_FIFO_LEN 144
+#define AUX_CMD_MAX 16
+#define AUX_CMD_I2C_MAX 128
+
+#define EDP_PORT_MAX 1
+#define EDP_SINK_CAP_LEN 16
+
+#define EDP_AUX_ERR_NONE 0
+#define EDP_AUX_ERR_ADDR -1
+#define EDP_AUX_ERR_TOUT -2
+#define EDP_AUX_ERR_NACK -3
+
+/* 4 bits of aux command */
+#define EDP_CMD_AUX_WRITE 0x8
+#define EDP_CMD_AUX_READ 0x9
+
+/* 4 bits of i2c command */
+#define EDP_CMD_I2C_MOT 0x4 /* i2c middle of transaction */
+#define EDP_CMD_I2C_WRITE 0x0
+#define EDP_CMD_I2C_READ 0x1
+#define EDP_CMD_I2C_STATUS 0x2 /* i2c write status request */
+
+/* cmd reply: bit 0, 1 for aux */
+#define EDP_AUX_ACK 0x0
+#define EDP_AUX_NACK 0x1
+#define EDP_AUX_DEFER 0x2
+
+/* cmd reply: bit 2, 3 for i2c */
+#define EDP_I2C_ACK 0x0
+#define EDP_I2C_NACK 0x4
+#define EDP_I2C_DEFER 0x8
+
+#define EDP_CMD_TIMEOUT 400 /* us */
+#define EDP_CMD_LEN 16
+
+#define EDP_INTR_ACK_SHIFT 1
+#define EDP_INTR_MASK_SHIFT 2
+
+/* isr */
+#define EDP_INTR_HPD BIT(0)
+#define EDP_INTR_AUX_I2C_DONE BIT(3)
+#define EDP_INTR_WRONG_ADDR BIT(6)
+#define EDP_INTR_TIMEOUT BIT(9)
+#define EDP_INTR_NACK_DEFER BIT(12)
+#define EDP_INTR_WRONG_DATA_CNT BIT(15)
+#define EDP_INTR_I2C_NACK BIT(18)
+#define EDP_INTR_I2C_DEFER BIT(21)
+#define EDP_INTR_PLL_UNLOCKED BIT(24)
+#define EDP_INTR_AUX_ERROR BIT(27)
+
+
+#define EDP_INTR_STATUS1 \
+ (EDP_INTR_HPD | EDP_INTR_AUX_I2C_DONE| \
+ EDP_INTR_WRONG_ADDR | EDP_INTR_TIMEOUT | \
+ EDP_INTR_NACK_DEFER | EDP_INTR_WRONG_DATA_CNT | \
+ EDP_INTR_I2C_NACK | EDP_INTR_I2C_DEFER | \
+ EDP_INTR_PLL_UNLOCKED | EDP_INTR_AUX_ERROR)
+
+#define EDP_INTR_MASK1 (EDP_INTR_STATUS1 << 2)
+
+
+#define EDP_INTR_READY_FOR_VIDEO BIT(0)
+#define EDP_INTR_IDLE_PATTERNs_SENT BIT(3)
+#define EDP_INTR_FRAME_END BIT(6)
+#define EDP_INTR_CRC_UPDATED BIT(9)
+
+#define EDP_INTR_STATUS2 \
+ (EDP_INTR_READY_FOR_VIDEO | EDP_INTR_IDLE_PATTERNs_SENT | \
+ EDP_INTR_FRAME_END | EDP_INTR_CRC_UPDATED)
+
+#define EDP_INTR_MASK2 (EDP_INTR_STATUS2 << 2)
+
+
+#define EDP_MAINLINK_CTRL 0x004
+#define EDP_STATE_CTRL 0x008
+#define EDP_MAINLINK_READY 0x084
+
+#define EDP_AUX_CTRL 0x300
+#define EDP_INTERRUPT_STATUS 0x308
+#define EDP_INTERRUPT_STATUS_2 0x30c
+#define EDP_AUX_DATA 0x314
+#define EDP_AUX_TRANS_CTRL 0x318
+#define EDP_AUX_STATUS 0x324
+
+#define EDP_PHY_EDPPHY_GLB_VM_CFG0 0x510
+#define EDP_PHY_EDPPHY_GLB_VM_CFG1 0x514
+
+struct edp_cmd {
+ char read; /* 1 == read, 0 == write */
+ char i2c; /* 1 == i2c cmd, 0 == native cmd */
+ u32 addr; /* 20 bits */
+ char *datap;
+ int len; /* len to be tx OR len to be rx for read */
+ char next; /* next command */
+};
+
+struct edp_buf {
+ char *start; /* buffer start addr */
+ char *end; /* buffer end addr */
+ int size; /* size of buffer */
+ char *data; /* data pointer */
+ int len; /* dara length */
+ char trans_num; /* transaction number */
+ char i2c; /* 1 == i2c cmd, 0 == native cmd */
+};
+
+#define DPCD_ENHANCED_FRAME BIT(0)
+#define DPCD_TPS3 BIT(1)
+#define DPCD_MAX_DOWNSPREAD_0_5 BIT(2)
+#define DPCD_NO_AUX_HANDSHAKE BIT(3)
+#define DPCD_PORT_0_EDID_PRESENTED BIT(4)
+
+/* event */
+#define EV_EDP_AUX_SETUP BIT(0)
+#define EV_EDID_READ BIT(1)
+#define EV_DPCD_CAP_READ BIT(2)
+#define EV_DPCD_STATUS_READ BIT(3)
+#define EV_LINK_TRAIN BIT(4)
+#define EV_VIDEO_READY BIT(31)
+
+struct dpcd_cap {
+ char major;
+ char minor;
+ char max_lane_count;
+ char num_rx_port;
+ char i2c_speed_ctrl;
+ char scrambler_reset;
+ char enhanced_frame;
+ u32 max_link_rate; /* 162, 270 and 540 Mb, divided by 10 */
+ u32 flags;
+ u32 rx_port0_buf_size;
+ u32 training_read_interval;/* us */
+};
+
+struct dpcd_link_status {
+ char lane_01_status;
+ char lane_23_status;
+ char interlane_align_done;
+ char downstream_port_status_changed;
+ char link_status_updated;
+ char port_0_in_sync;
+ char port_1_in_sync;
+ char req_voltage_swing[4];
+ char req_pre_emphasis[4];
+};
+
struct display_timing_desc {
u32 pclk;
u32 h_addressable; /* addressable + boder = active */
@@ -45,12 +187,14 @@
u32 hsync_pol;
};
+#define EDID_DISPLAY_PORT_SUPPORT 0x05
+
struct edp_edid {
char id_name[4];
short id_product;
char version;
char revision;
- char video_digital;
+ char video_intf; /* edp == 0x5 */
char color_depth; /* 6, 8, 10, 12 and 14 bits */
char color_format; /* RGB 4:4:4, YCrCb 4:4:4, Ycrcb 4:2:2 */
char dpm; /* display power management */
@@ -62,11 +206,32 @@
struct display_timing_desc timing[4];
};
-struct dpcd_cap {
- char max_lane_count;
- u32 max_link_clk; /* 162, 270 and 540 Mb, divided by 10 */
+struct edp_statistic {
+ u32 intr_hpd;
+ u32 intr_aux_i2c_done;
+ u32 intr_wrong_addr;
+ u32 intr_tout;
+ u32 intr_nack_defer;
+ u32 intr_wrong_data_cnt;
+ u32 intr_i2c_nack;
+ u32 intr_i2c_defer;
+ u32 intr_pll_unlock;
+ u32 intr_crc_update;
+ u32 intr_frame_end;
+ u32 intr_idle_pattern_sent;
+ u32 intr_ready_for_video;
+ u32 aux_i2c_tx;
+ u32 aux_i2c_rx;
+ u32 aux_native_tx;
+ u32 aux_native_rx;
};
+
+#define DPCD_LINK_VOLTAGE_MAX 4
+#define DPCD_LINK_PRE_EMPHASIS_MAX 4
+
+#define HPD_EVENT_MAX 8
+
struct mdss_edp_drv_pdata {
/* device driver */
int (*on) (struct mdss_panel_data *pdata);
@@ -74,11 +239,15 @@
struct platform_device *pdev;
/* edp specific */
- struct mdss_panel_data panel_data;
- unsigned char *edp_base;
+ unsigned char *base;
+ int base_size;
unsigned char *mmss_cc_base;
+
+ struct mdss_panel_data panel_data;
+
struct edp_edid edid;
struct dpcd_cap dpcd;
+ int train_start;
/* regulators */
struct regulator *vdda_vreg;
@@ -98,22 +267,82 @@
struct pwm_device *bl_pwm;
int lpg_channel;
int pwm_period;
+
+ /* hpd */
+ int gpio_panel_hpd;
+ enum of_gpio_flags hpd_flags;
+ int hpd_irq;
+
+ /* aux */
+ struct completion aux_comp;
+ struct completion train_comp;
+ struct mutex aux_mutex;
+ u32 aux_cmd_busy;
+ u32 aux_cmd_i2c;
+ int aux_trans_num;
+ int aux_error_num;
+ u32 aux_ctrl_reg;
+ struct edp_buf txp;
+ struct edp_buf rxp;
+ char txbuf[256];
+ char rxbuf[256];
+ struct dpcd_link_status link_status;
+ char link_rate;
+ char lane_cnt;
+ char v_level;
+ char p_level;
+ /* transfer unit */
+ char tu_desired;
+ char valid_boundary;
+ char delay_start;
+ u32 bpp;
+ struct edp_statistic edp_stat;
+
+ /* event */
+ wait_queue_head_t event_q;
+ u32 event_pndx;
+ u32 event_gndx;
+ u32 event_todo_list[HPD_EVENT_MAX];
+ spinlock_t event_lock;
};
-void mdss_edp_phy_sw_reset(unsigned char *edp_base);
-void mdss_edp_pll_configure(unsigned char *edp_base, int rate);
-void mdss_edp_enable_lane_bist(unsigned char *edp_base, int lane, int enable);
-void mdss_edp_enable_mainlink(unsigned char *edp_base, int enable);
-void mdss_edp_hw_powerup(unsigned char *edp_base, int enable);
-void mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv);
+void mdss_edp_phy_sw_reset(unsigned char *base);
+void mdss_edp_pll_configure(unsigned char *base, int rate);
+void mdss_edp_enable_mainlink(unsigned char *base, int enable);
+void mdss_edp_phy_powerup(unsigned char *base, int enable);
+int mdss_edp_aux_clk_enable(struct mdss_edp_drv_pdata *edp_drv);
+void mdss_edp_aux_clk_disable(struct mdss_edp_drv_pdata *edp_drv);
+int mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv);
void mdss_edp_clk_disable(struct mdss_edp_drv_pdata *edp_drv);
int mdss_edp_clk_init(struct mdss_edp_drv_pdata *edp_drv);
void mdss_edp_clk_deinit(struct mdss_edp_drv_pdata *edp_drv);
-void mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv);
+int mdss_edp_prepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv);
+void mdss_edp_unprepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv);
+int mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv);
void mdss_edp_unprepare_clocks(struct mdss_edp_drv_pdata *edp_drv);
-void mdss_edp_config_clk(unsigned char *edp_base, unsigned char *mmss_cc_base);
-void mdss_edp_unconfig_clk(unsigned char *edp_base,
+void mdss_edp_config_clk(unsigned char *base, unsigned char *mmss_cc_base);
+void mdss_edp_unconfig_clk(unsigned char *base,
unsigned char *mmss_cc_base);
-void mdss_edp_phy_misc_cfg(unsigned char *edp_base);
+
+void mdss_edp_dpcd_cap_read(struct mdss_edp_drv_pdata *edp);
+void mdss_edp_dpcd_status_read(struct mdss_edp_drv_pdata *edp);
+void mdss_edp_edid_read(struct mdss_edp_drv_pdata *edp, int block);
+int mdss_edp_link_train(struct mdss_edp_drv_pdata *edp);
+void edp_aux_i2c_handler(struct mdss_edp_drv_pdata *edp, u32 isr);
+void edp_aux_native_handler(struct mdss_edp_drv_pdata *edp, u32 isr);
+void mdss_edp_aux_init(struct mdss_edp_drv_pdata *ep);
+void mdss_edp_enable_aux(unsigned char *edp_base, int enable);
+
+void mdss_edp_timing_engine_ctrl(unsigned char *edp_base, int enable);
+void mdss_edp_mainlink_ctrl(unsigned char *edp_base, int enable);
+void mdss_edp_mainlink_reset(unsigned char *edp_base);
+void mdss_edp_aux_reset(unsigned char *edp_base);
+void mdss_edp_aux_ctrl(unsigned char *edp_base, int enable);
+void mdss_edp_phy_pll_reset(unsigned char *edp_base);
+int mdss_edp_phy_pll_ready(unsigned char *edp_base);
+int mdss_edp_phy_ready(unsigned char *edp_base);
+void mdss_edp_lane_power_ctrl(unsigned char *edp_base, int max_lane, int up);
+void mdss_edp_phy_vm_pe_init(unsigned char *edp_base);
+void mdss_edp_clock_synchrous(unsigned char *edp_base, int sync);
#endif /* MDSS_EDP_H */
diff --git a/drivers/video/msm/mdss/mdss_edp_aux.c b/drivers/video/msm/mdss/mdss_edp_aux.c
new file mode 100644
index 0000000..6d8e2c2
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_edp_aux.c
@@ -0,0 +1,1260 @@
+/* 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/bug.h>
+#include <linux/of_gpio.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/clk.h>
+#include <mach/dma.h>
+
+#include "mdss_panel.h"
+#include "mdss_edp.h"
+
+/*
+ * edp buffer operation
+ */
+static char *edp_buf_init(struct edp_buf *eb, char *buf, int size)
+{
+ eb->start = buf;
+ eb->size = size;
+ eb->data = eb->start;
+ eb->end = eb->start + eb->size;
+ eb->len = 0;
+ eb->trans_num = 0;
+ eb->i2c = 0;
+ return eb->data;
+}
+
+static char *edp_buf_reset(struct edp_buf *eb)
+{
+ eb->data = eb->start;
+ eb->len = 0;
+ eb->trans_num = 0;
+ eb->i2c = 0;
+ return eb->data;
+}
+
+static char *edp_buf_push(struct edp_buf *eb, int len)
+{
+ eb->data += len;
+ eb->len += len;
+ return eb->data;
+}
+
+static int edp_buf_trailing(struct edp_buf *eb)
+{
+ return (int)(eb->end - eb->data);
+}
+
+/*
+ * edp aux edp_buf_add_cmd:
+ * NO native and i2c command mix allowed
+ */
+static int edp_buf_add_cmd(struct edp_buf *eb, struct edp_cmd *cmd)
+{
+ char data;
+ char *bp, *cp;
+ int i, len;
+
+ if (cmd->read) /* read */
+ len = 4;
+ else
+ len = cmd->len + 4;
+
+ if (edp_buf_trailing(eb) < len)
+ return 0;
+
+ /*
+ * cmd fifo only has depth of 144 bytes
+ * limit buf length to 128 bytes here
+ */
+ if ((eb->len + len) > 128)
+ return 0;
+
+ bp = eb->data;
+ data = cmd->addr >> 16;
+ data &= 0x0f; /* 4 addr bits */
+ if (cmd->read)
+ data |= BIT(4);
+ *bp++ = data;
+ *bp++ = cmd->addr >> 8;
+ *bp++ = cmd->addr;
+ *bp++ = cmd->len - 1;
+
+ if (!cmd->read) { /* write */
+ cp = cmd->datap;
+ for (i = 0; i < cmd->len; i++)
+ *bp++ = *cp++;
+ }
+ edp_buf_push(eb, len);
+
+ if (cmd->i2c)
+ eb->i2c++;
+
+ eb->trans_num++; /* Increase transaction number */
+
+ return cmd->len - 1;
+}
+
+static int edp_cmd_fifo_tx(struct edp_buf *tp, unsigned char *base)
+{
+ u32 data;
+ char *dp;
+ int len, cnt;
+
+ len = tp->len; /* total byte to cmd fifo */
+ if (len == 0)
+ return 0;
+
+ cnt = 0;
+ dp = tp->start;
+
+ while (cnt < len) {
+ data = *dp; /* data byte */
+ data <<= 8;
+ data &= 0x00ff00; /* index = 0, write */
+ if (cnt == 0)
+ data |= BIT(31); /* INDEX_WRITE */
+ pr_debug("%s: data=%x\n", __func__, data);
+ edp_write(base + EDP_AUX_DATA, data);
+ cnt++;
+ dp++;
+ }
+
+ data = (tp->trans_num - 1);
+ if (tp->i2c)
+ data |= BIT(8); /* I2C */
+
+ data |= BIT(9); /* GO */
+ pr_debug("%s: data=%x\n", __func__, data);
+ edp_write(base + EDP_AUX_TRANS_CTRL, data);
+
+ return tp->len;
+}
+
+static int edp_cmd_fifo_rx(struct edp_buf *rp, int len, unsigned char *base)
+{
+ u32 data;
+ char *dp;
+ int i;
+
+ data = 0; /* index = 0 */
+ data |= BIT(31); /* INDEX_WRITE */
+ data |= BIT(0); /* read */
+ edp_write(base + EDP_AUX_DATA, data);
+
+ dp = rp->data;
+
+ /* discard first byte */
+ data = edp_read(base + EDP_AUX_DATA);
+ for (i = 0; i < len; i++) {
+ data = edp_read(base + EDP_AUX_DATA);
+ pr_debug("%s: data=%x\n", __func__, data);
+ *dp++ = (char)((data >> 8) & 0xff);
+ }
+
+ rp->len = len;
+ return len;
+}
+
+static int edp_aux_write_cmds(struct mdss_edp_drv_pdata *ep,
+ struct edp_cmd *cmd)
+{
+ struct edp_cmd *cm;
+ struct edp_buf *tp;
+ int len, ret;
+
+ mutex_lock(&ep->aux_mutex);
+ ep->aux_cmd_busy = 1;
+
+ tp = &ep->txp;
+ edp_buf_reset(tp);
+
+ cm = cmd;
+ while (cm) {
+ pr_debug("%s: i2c=%d read=%d addr=%x len=%d next=%d\n",
+ __func__, cm->i2c, cm->read, cm->addr, cm->len,
+ cm->next);
+ ret = edp_buf_add_cmd(tp, cm);
+ if (ret <= 0)
+ break;
+ if (cm->next == 0)
+ break;
+ cm++;
+ }
+
+ if (tp->i2c)
+ ep->aux_cmd_i2c = 1;
+ else
+ ep->aux_cmd_i2c = 0;
+
+ INIT_COMPLETION(ep->aux_comp);
+
+ len = edp_cmd_fifo_tx(&ep->txp, ep->base);
+
+ wait_for_completion(&ep->aux_comp);
+
+ if (ep->aux_error_num == EDP_AUX_ERR_NONE)
+ ret = len;
+ else
+ ret = ep->aux_error_num;
+
+ ep->aux_cmd_busy = 0;
+ mutex_unlock(&ep->aux_mutex);
+ return ret;
+}
+
+static int edp_aux_read_cmds(struct mdss_edp_drv_pdata *ep,
+ struct edp_cmd *cmds)
+{
+ struct edp_cmd *cm;
+ struct edp_buf *tp;
+ struct edp_buf *rp;
+ int len, ret;
+
+ mutex_lock(&ep->aux_mutex);
+ ep->aux_cmd_busy = 1;
+
+ tp = &ep->txp;
+ rp = &ep->rxp;
+ edp_buf_reset(tp);
+ edp_buf_reset(rp);
+
+ cm = cmds;
+ len = 0;
+ while (cm) {
+ pr_debug("%s: i2c=%d read=%d addr=%x len=%d next=%d\n",
+ __func__, cm->i2c, cm->read, cm->addr, cm->len,
+ cm->next);
+ ret = edp_buf_add_cmd(tp, cm);
+ len += cm->len;
+ if (ret <= 0)
+ break;
+ if (cm->next == 0)
+ break;
+ cm++;
+ }
+
+ if (tp->i2c)
+ ep->aux_cmd_i2c = 1;
+ else
+ ep->aux_cmd_i2c = 0;
+
+ INIT_COMPLETION(ep->aux_comp);
+
+ edp_cmd_fifo_tx(tp, ep->base);
+
+ wait_for_completion(&ep->aux_comp);
+
+ if (ep->aux_error_num == EDP_AUX_ERR_NONE)
+ ret = edp_cmd_fifo_rx(rp, len, ep->base);
+ else
+ ret = ep->aux_error_num;
+
+ ep->aux_cmd_busy = 0;
+ mutex_unlock(&ep->aux_mutex);
+
+ return ret;
+}
+
+void edp_aux_native_handler(struct mdss_edp_drv_pdata *ep, u32 isr)
+{
+
+ pr_debug("%s: isr=%x\n", __func__, isr);
+
+ if (isr & EDP_INTR_AUX_I2C_DONE)
+ ep->aux_error_num = EDP_AUX_ERR_NONE;
+ else if (isr & EDP_INTR_WRONG_ADDR)
+ ep->aux_error_num = EDP_AUX_ERR_ADDR;
+ else if (isr & EDP_INTR_TIMEOUT)
+ ep->aux_error_num = EDP_AUX_ERR_TOUT;
+ if (isr & EDP_INTR_NACK_DEFER)
+ ep->aux_error_num = EDP_AUX_ERR_NACK;
+
+ complete(&ep->aux_comp);
+}
+
+void edp_aux_i2c_handler(struct mdss_edp_drv_pdata *ep, u32 isr)
+{
+
+ pr_debug("%s: isr=%x\n", __func__, isr);
+
+ if (isr & EDP_INTR_AUX_I2C_DONE) {
+ if (isr & (EDP_INTR_I2C_NACK | EDP_INTR_I2C_DEFER))
+ ep->aux_error_num = EDP_AUX_ERR_NACK;
+ else
+ ep->aux_error_num = EDP_AUX_ERR_NONE;
+ } else {
+ if (isr & EDP_INTR_WRONG_ADDR)
+ ep->aux_error_num = EDP_AUX_ERR_ADDR;
+ else if (isr & EDP_INTR_TIMEOUT)
+ ep->aux_error_num = EDP_AUX_ERR_TOUT;
+ if (isr & EDP_INTR_NACK_DEFER)
+ ep->aux_error_num = EDP_AUX_ERR_NACK;
+ if (isr & EDP_INTR_I2C_NACK)
+ ep->aux_error_num = EDP_AUX_ERR_NACK;
+ if (isr & EDP_INTR_I2C_DEFER)
+ ep->aux_error_num = EDP_AUX_ERR_NACK;
+ }
+
+ complete(&ep->aux_comp);
+}
+
+static int edp_aux_write_buf(struct mdss_edp_drv_pdata *ep, u32 addr,
+ char *buf, int len, int i2c)
+{
+ struct edp_cmd cmd;
+
+ cmd.read = 0;
+ cmd.i2c = i2c;
+ cmd.addr = addr;
+ cmd.datap = buf;
+ cmd.len = len & 0x0ff;
+ cmd.next = 0;
+
+ return edp_aux_write_cmds(ep, &cmd);
+}
+
+static int edp_aux_read_buf(struct mdss_edp_drv_pdata *ep, u32 addr,
+ int len, int i2c)
+{
+ struct edp_cmd cmd;
+
+ cmd.read = 1;
+ cmd.i2c = i2c;
+ cmd.addr = addr;
+ cmd.datap = NULL;
+ cmd.len = len & 0x0ff;
+ cmd.next = 0;
+
+ return edp_aux_read_cmds(ep, &cmd);
+}
+
+/*
+ * edid standard header bytes
+ */
+static char edid_hdr[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
+
+int edp_edid_buf_error(char *buf, int len)
+{
+ char *bp;
+ int i;
+ char csum = 0;
+ int ret = 0;
+
+ bp = buf;
+ if (len < 128) {
+ pr_err("%s: Error: len=%x\n", __func__, len);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < 128; i++)
+ csum += *bp++;
+
+ if (csum != 0) {
+ pr_err("%s: Error: csum=%x\n", __func__, csum);
+ return -EINVAL;
+ }
+
+ if (strncmp(buf, edid_hdr, strlen(edid_hdr))) {
+ pr_err("%s: Error: header\n", __func__);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+
+void edp_extract_edid_manufacturer(struct edp_edid *edid, char *buf)
+{
+ char *bp;
+ char data;
+
+ bp = &buf[8];
+ data = *bp & 0x7f;
+ data >>= 2;
+ edid->id_name[0] = 'A' + data - 1;
+ data = *bp & 0x03;
+ data <<= 3;
+ bp++;
+ data |= (*bp >> 5);
+ edid->id_name[1] = 'A' + data - 1;
+ data = *bp & 0x1f;
+ edid->id_name[2] = 'A' + data - 1;
+ edid->id_name[3] = 0;
+
+ pr_debug("%s: edid manufacturer = %s", __func__, edid->id_name);
+}
+
+void edp_extract_edid_product(struct edp_edid *edid, char *buf)
+{
+ char *bp;
+ u32 data;
+
+ bp = &buf[0x0a];
+ data = *bp;
+ edid->id_product = *bp++;
+ edid->id_product &= 0x0ff;
+ data = *bp & 0x0ff;
+ data <<= 8;
+ edid->id_product |= data;
+
+ pr_debug("%s: edid product = 0x%x", __func__, edid->id_product);
+};
+
+void edp_extract_edid_version(struct edp_edid *edid, char *buf)
+{
+ edid->version = buf[0x12];
+ edid->revision = buf[0x13];
+ pr_debug("%s: edid version = %d.%d", __func__, edid->version,
+ edid->revision);
+};
+
+void edp_extract_edid_ext_block_cnt(struct edp_edid *edid, char *buf)
+{
+ edid->ext_block_cnt = buf[0x7e];
+ pr_debug("%s: edid extension = %d", __func__,
+ edid->ext_block_cnt);
+};
+
+void edp_extract_edid_video_support(struct edp_edid *edid, char *buf)
+{
+ char *bp;
+
+ bp = &buf[0x14];
+ if (*bp & 0x80) {
+ edid->video_intf = *bp & 0x0f;
+ /* 6, 8, 10, 12, 14 and 16 bit per component */
+ edid->color_depth = ((*bp & 0x70) >> 4); /* color bit depth */
+ if (edid->color_depth) {
+ edid->color_depth *= 2;
+ edid->color_depth += 4;
+ }
+ pr_debug("%s: Digital Video intf=%d color_depth=%d\n",
+ __func__, edid->video_intf, edid->color_depth);
+ } else {
+ pr_err("%s: Error, Analog video interface", __func__);
+ }
+};
+
+void edp_extract_edid_feature(struct edp_edid *edid, char *buf)
+{
+ char *bp;
+ char data;
+
+ bp = &buf[0x18];
+ data = *bp;
+ data &= 0xe0;
+ data >>= 5;
+ if (data == 0x01)
+ edid->dpm = 1; /* display power management */
+
+ if (edid->video_intf) {
+ if (*bp & 0x80) {
+ /* RGB 4:4:4, YcrCb 4:4:4 and YCrCb 4:2:2 */
+ edid->color_format = *bp & 0x18;
+ edid->color_format >>= 3;
+ }
+ }
+
+ pr_debug("%s: edid dpm=%d color_format=%d", __func__,
+ edid->dpm, edid->color_format);
+};
+
+void edp_extract_edid_detailed_timing_description(struct edp_edid *edid,
+ char *buf)
+{
+ char *bp;
+ u32 data;
+ struct display_timing_desc *dp;
+
+ dp = &edid->timing[0];
+
+ bp = &buf[0x36];
+ dp->pclk = 0;
+ dp->pclk = *bp++; /* byte 0x36 */
+ dp->pclk |= (*bp++ << 8); /* byte 0x37 */
+
+ dp->h_addressable = *bp++; /* byte 0x38 */
+
+ if (dp->pclk == 0 && dp->h_addressable == 0)
+ return; /* Not detailed timing definition */
+
+ dp->pclk *= 10000;
+
+ dp->h_blank = *bp++;/* byte 0x39 */
+ data = *bp & 0xf0; /* byte 0x3A */
+ data <<= 4;
+ dp->h_addressable |= data;
+
+ data = *bp++ & 0x0f;
+ data <<= 8;
+ dp->h_blank |= data;
+
+ dp->v_addressable = *bp++; /* byte 0x3B */
+ dp->v_blank = *bp++; /* byte 0x3C */
+ data = *bp & 0xf0; /* byte 0x3D */
+ data <<= 4;
+ dp->v_addressable |= data;
+
+ data = *bp++ & 0x0f;
+ data <<= 8;
+ dp->v_blank |= data;
+
+ dp->h_fporch = *bp++; /* byte 0x3E */
+ dp->h_sync_pulse = *bp++; /* byte 0x3F */
+
+ dp->v_fporch = *bp & 0x0f0; /* byte 0x40 */
+ dp->v_fporch >>= 4;
+ dp->v_sync_pulse = *bp & 0x0f;
+
+ bp++;
+ data = *bp & 0xc0; /* byte 0x41 */
+ data <<= 2;
+ dp->h_fporch |= data;
+
+ data = *bp & 0x30;
+ data <<= 4;
+ dp->h_sync_pulse |= data;
+
+ data = *bp & 0x0c;
+ data <<= 2;
+ dp->v_fporch |= data;
+
+ data = *bp & 0x03;
+ data <<= 4;
+ dp->v_sync_pulse |= data;
+
+ bp++;
+ dp->width_mm = *bp++; /* byte 0x42 */
+ dp->height_mm = *bp++; /* byte 0x43 */
+ data = *bp & 0x0f0; /* byte 0x44 */
+ data <<= 4;
+ dp->width_mm |= data;
+ data = *bp & 0x0f;
+ data <<= 8;
+ dp->height_mm |= data;
+
+ bp++;
+ dp->h_border = *bp++; /* byte 0x45 */
+ dp->v_border = *bp++; /* byte 0x46 */
+
+ dp->interlaced = *bp & 0x80; /* byte 0x47 */
+
+ dp->stereo = *bp & 0x60;
+ dp->stereo >>= 5;
+
+ data = *bp & 0x1e; /* bit 4,3,2 1*/
+ data >>= 1;
+ dp->sync_type = data & 0x08;
+ dp->sync_type >>= 3; /* analog or digital */
+ if (dp->sync_type) {
+ dp->sync_separate = data & 0x04;
+ dp->sync_separate >>= 2;
+ if (dp->sync_separate) {
+ if (data & 0x02)
+ dp->vsync_pol = 1; /* positive */
+ else
+ dp->vsync_pol = 0;/* negative */
+
+ if (data & 0x01)
+ dp->hsync_pol = 1; /* positive */
+ else
+ dp->hsync_pol = 0; /* negative */
+ }
+ }
+
+ pr_debug("%s: pixel_clock = %d\n", __func__, dp->pclk);
+
+ pr_debug("%s: horizontal=%d, blank=%d, porch=%d, sync=%d\n"
+ , __func__, dp->h_addressable, dp->h_blank,
+ dp->h_fporch, dp->h_sync_pulse);
+ pr_debug("%s: vertical=%d, blank=%d, porch=%d, vsync=%d\n"
+ , __func__, dp->v_addressable, dp->v_blank,
+ dp->v_fporch, dp->v_sync_pulse);
+ pr_debug("%s: panel size in mm, width=%d height=%d\n", __func__,
+ dp->width_mm, dp->height_mm);
+ pr_debug("%s: panel border horizontal=%d vertical=%d\n", __func__,
+ dp->h_border, dp->v_border);
+ pr_debug("%s: flags: interlaced=%d stereo=%d sync_type=%d sync_sep=%d\n"
+ , __func__, dp->interlaced, dp->stereo,
+ dp->sync_type, dp->sync_separate);
+ pr_debug("%s: polarity vsync=%d, hsync=%d", __func__,
+ dp->vsync_pol, dp->hsync_pol);
+}
+
+
+/*
+ * EDID structure can be found in VESA standart here:
+ * http://read.pudn.com/downloads110/ebook/456020/E-EDID%20Standard.pdf
+ *
+ * following table contains default edid
+ * static char edid_raw_data[128] = {
+ * 0, 255, 255, 255, 255, 255, 255, 0,
+ * 6, 175, 93, 48, 0, 0, 0, 0, 0, 22,
+ * 1, 4,
+ * 149, 26, 14, 120, 2,
+ * 164, 21,158, 85, 78, 155, 38, 15, 80, 84,
+ * 0, 0, 0,
+ * 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ * 29, 54, 128, 160, 112, 56, 30, 64, 48, 32, 142, 0, 0, 144, 16,0,0,24,
+ * 19, 36, 128, 160, 112, 56, 30, 64, 48, 32, 142, 0, 0, 144, 16,0,0,24,
+ * 0, 0, 0, 254, 0, 65, 85, 79, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ * 0, 0, 0, 254, 0, 66, 49, 49, 54, 72, 65, 78, 48, 51, 46, 48, 32, 10,
+ * 0, 75 };
+ */
+
+static int edp_aux_chan_ready(struct mdss_edp_drv_pdata *ep)
+{
+ int cnt, ret;
+ char data = 0;
+
+ for (cnt = 5; cnt; cnt--) {
+ ret = edp_aux_write_buf(ep, 0x50, &data, 1, 1);
+ pr_debug("%s: ret=%d\n", __func__, ret);
+ if (ret >= 0)
+ break;
+ pr_debug("%s: failed in write\n", __func__);
+ msleep(100);
+ }
+
+ if (cnt == 0)
+ return 0;
+
+ return 1;
+}
+
+static int edp_sink_edid_read(struct mdss_edp_drv_pdata *ep, int block)
+{
+ struct edp_buf *rp;
+ int cnt, rlen;
+ int ret = 0;
+
+ ret = edp_aux_chan_ready(ep);
+ if (ret == 0) {
+ pr_err("%s: aux chan NOT ready\n", __func__);
+ return ret;
+ }
+
+ for (cnt = 5; cnt; cnt--) {
+ rlen = edp_aux_read_buf(ep, 0x50, 128, 1);
+ if (rlen > 0) {
+ pr_debug("%s: rlen=%d\n", __func__, rlen);
+
+ rp = &ep->rxp;
+ if (!edp_edid_buf_error(rp->data, rp->len))
+ break;
+ }
+ }
+
+ if (cnt <= 0) {
+ pr_err("%s: Failed\n", __func__);
+ return -EINVAL;
+ }
+
+ edp_extract_edid_manufacturer(&ep->edid, rp->data);
+ edp_extract_edid_product(&ep->edid, rp->data);
+ edp_extract_edid_version(&ep->edid, rp->data);
+ edp_extract_edid_ext_block_cnt(&ep->edid, rp->data);
+ edp_extract_edid_video_support(&ep->edid, rp->data);
+ edp_extract_edid_feature(&ep->edid, rp->data);
+ edp_extract_edid_detailed_timing_description(&ep->edid, rp->data);
+
+ return 128;
+}
+
+static void edp_sink_capability_read(struct mdss_edp_drv_pdata *ep,
+ int len)
+{
+ char *bp;
+ char data;
+ struct dpcd_cap *cap;
+ struct edp_buf *rp;
+ int rlen;
+
+ rlen = edp_aux_read_buf(ep, 0, len, 0);
+ if (rlen <= 0) {
+ pr_err("%s: edp aux read failed\n", __func__);
+ return;
+ }
+ rp = &ep->rxp;
+ cap = &ep->dpcd;
+ bp = rp->data;
+
+ data = *bp++; /* byte 0 */
+ cap->major = (data >> 4) & 0x0f;
+ cap->minor = data & 0x0f;
+ if (--rlen <= 0)
+ return;
+ pr_debug("%s: version: %d.%d\n", __func__, cap->major, cap->minor);
+
+ data = *bp++; /* byte 1 */
+ /* 162, 270 and 540 MB, symbol rate, NOT bit rate */
+ cap->max_link_rate = data * 27;
+ if (--rlen <= 0)
+ return;
+ pr_debug("%s: link_rate=%d\n", __func__, cap->max_link_rate);
+
+ data = *bp++; /* byte 2 */
+ if (data & BIT(7))
+ cap->flags |= DPCD_ENHANCED_FRAME;
+ if (data & 0x40)
+ cap->flags |= DPCD_TPS3;
+ data &= 0x0f;
+ cap->max_lane_count = data;
+ if (--rlen <= 0)
+ return;
+ pr_debug("%s: lane_count=%d\n", __func__, cap->max_lane_count);
+
+ data = *bp++; /* byte 3 */
+ if (data & BIT(0)) {
+ cap->flags |= DPCD_MAX_DOWNSPREAD_0_5;
+ pr_debug("%s: max_downspread\n", __func__);
+ }
+
+ if (data & BIT(6)) {
+ cap->flags |= DPCD_NO_AUX_HANDSHAKE;
+ pr_debug("%s: NO Link Training\n", __func__);
+ }
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 4 */
+ cap->num_rx_port = (data & BIT(0)) + 1;
+ pr_debug("%s: rx_ports=%d", __func__, cap->num_rx_port);
+ if (--rlen <= 0)
+ return;
+
+ bp += 3; /* skip 5, 6 and 7 */
+ rlen -= 3;
+ if (rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 8 */
+ if (data & BIT(1)) {
+ cap->flags |= DPCD_PORT_0_EDID_PRESENTED;
+ pr_debug("%s: edid presented\n", __func__);
+ }
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 9 */
+ cap->rx_port0_buf_size = (data + 1) * 32;
+ pr_debug("%s: lane_buf_size=%d", __func__, cap->rx_port0_buf_size);
+ if (--rlen <= 0)
+ return;
+
+ bp += 2; /* skip 10, 11 port1 capability */
+ rlen -= 2;
+ if (rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 12 */
+ cap->i2c_speed_ctrl = data;
+ if (cap->i2c_speed_ctrl > 0)
+ pr_debug("%s: i2c_rate=%d", __func__, cap->i2c_speed_ctrl);
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 13 */
+ cap->scrambler_reset = data & BIT(0);
+ pr_debug("%s: scrambler_reset=%d\n", __func__,
+ cap->scrambler_reset);
+
+ cap->enhanced_frame = data & BIT(1);
+ pr_debug("%s: enhanced_framing=%d\n", __func__,
+ cap->enhanced_frame);
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 14 */
+ if (data == 0)
+ cap->training_read_interval = 4000; /* us */
+ else
+ cap->training_read_interval = 4000 * data; /* us */
+ pr_debug("%s: training_interval=%d\n", __func__,
+ cap->training_read_interval);
+}
+
+static void edp_link_status_read(struct mdss_edp_drv_pdata *ep, int len)
+{
+ char *bp;
+ char data;
+ struct dpcd_link_status *sp;
+ struct edp_buf *rp;
+ int rlen;
+
+ pr_debug("%s: len=%d", __func__, len);
+ /* skip byte 0x200 and 0x201 */
+ rlen = edp_aux_read_buf(ep, 0x202, len, 0);
+ if (rlen <= 0) {
+ pr_err("%s: edp aux read failed\n", __func__);
+ return;
+ }
+ rp = &ep->rxp;
+ bp = rp->data;
+ sp = &ep->link_status;
+
+ data = *bp++; /* byte 0x202 */
+ sp->lane_01_status = data; /* lane 0, 1 */
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 0x203 */
+ sp->lane_23_status = data; /* lane 2, 3 */
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 0x204 */
+ sp->interlane_align_done = (data & BIT(0));
+ sp->downstream_port_status_changed = (data & BIT(6));
+ sp->link_status_updated = (data & BIT(7));
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 0x205 */
+ sp->port_0_in_sync = (data & BIT(0));
+ sp->port_1_in_sync = (data & BIT(1));
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 0x206 */
+ sp->req_voltage_swing[0] = data & 0x03;
+ data >>= 2;
+ sp->req_pre_emphasis[0] = data & 0x03;
+ data >>= 2;
+ sp->req_voltage_swing[1] = data & 0x03;
+ data >>= 2;
+ sp->req_pre_emphasis[1] = data & 0x03;
+ if (--rlen <= 0)
+ return;
+
+ data = *bp++; /* byte 0x207 */
+ sp->req_voltage_swing[2] = data & 0x03;
+ data >>= 2;
+ sp->req_pre_emphasis[2] = data & 0x03;
+ data >>= 2;
+ sp->req_voltage_swing[3] = data & 0x03;
+ data >>= 2;
+ sp->req_pre_emphasis[3] = data & 0x03;
+}
+
+static int edp_cap_lane_rate_set(struct mdss_edp_drv_pdata *ep)
+{
+ char buf[4];
+ int len = 0;
+
+ pr_debug("%s: bw=%x lane=%d\n", __func__, ep->link_rate, ep->lane_cnt);
+ buf[0] = ep->link_rate;
+ buf[1] = ep->lane_cnt;
+ len = edp_aux_write_buf(ep, 0x100, buf, 2, 0);
+
+ return len;
+}
+
+static int edp_lane_set_write(struct mdss_edp_drv_pdata *ep, int voltage_level,
+ int pre_emphasis_level)
+{
+ int i;
+ char buf[4];
+
+ if (voltage_level >= DPCD_LINK_VOLTAGE_MAX)
+ voltage_level |= 0x04;
+
+ if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX)
+ pre_emphasis_level |= 0x04;
+
+ pre_emphasis_level <<= 3;
+
+ for (i = 0; i < 4; i++)
+ buf[i] = voltage_level | pre_emphasis_level;
+
+ pr_debug("%s: p|v=0x%x", __func__, voltage_level | pre_emphasis_level);
+ return edp_aux_write_buf(ep, 0x103, buf, 4, 0);
+}
+
+static int edp_powerstate_write(struct mdss_edp_drv_pdata *ep,
+ char powerstate)
+{
+ pr_debug("%s: state=%d\n", __func__, powerstate);
+ return edp_aux_write_buf(ep, 0x600, &powerstate, 1, 0);
+}
+
+static int edp_train_pattern_set_write(struct mdss_edp_drv_pdata *ep,
+ int pattern)
+{
+ char buf[4];
+
+ pr_debug("%s: pattern=%x\n", __func__, pattern);
+ buf[0] = pattern;
+ return edp_aux_write_buf(ep, 0x102, buf, 1, 0);
+}
+
+static int edp_sink_clock_recovery_done(struct mdss_edp_drv_pdata *ep)
+{
+ u32 mask;
+ u32 data;
+
+ pr_debug("%s:\n", __func__);
+
+ if (ep->lane_cnt == 1) {
+ mask = 0x01; /* lane 0 */
+ data = ep->link_status.lane_01_status;
+ } else if (ep->lane_cnt == 2) {
+ mask = 0x011; /*B lane 0, 1 */
+ data = ep->link_status.lane_01_status;
+ } else {
+ mask = 0x01111; /*B lane 0, 1 */
+ data = ep->link_status.lane_23_status;
+ data <<= 8;
+ data |= ep->link_status.lane_01_status;
+ }
+
+ pr_debug("%s: data=%x mask=%x\n", __func__, data, mask);
+ data &= mask;
+ if (data == mask) /* all done */
+ return 1;
+
+ return 0;
+}
+
+static int edp_sink_channel_eq_done(struct mdss_edp_drv_pdata *ep)
+{
+ u32 mask;
+ u32 data;
+
+ pr_debug("%s:\n", __func__);
+
+ if (!ep->link_status.interlane_align_done) /* not align */
+ return 0;
+
+ if (ep->lane_cnt == 1) {
+ mask = 0x7;
+ data = ep->link_status.lane_01_status;
+ } else if (ep->lane_cnt == 2) {
+ mask = 0x77;
+ data = ep->link_status.lane_01_status;
+ } else {
+ mask = 0x7777;
+ data = ep->link_status.lane_23_status;
+ data <<= 8;
+ data |= ep->link_status.lane_01_status;
+ }
+
+ pr_debug("%s: data=%x mask=%x\n", __func__, data, mask);
+
+ data &= mask;
+ if (data == mask)/* all done */
+ return 1;
+
+ return 0;
+}
+
+void edp_sink_train_set_adjust(struct mdss_edp_drv_pdata *ep)
+{
+ int i;
+ int max = 0;
+
+
+ /* use the max level across lanes */
+ for (i = 0; i < ep->lane_cnt; i++) {
+ pr_debug("%s: lane=%d req_voltage_swing=%d",
+ __func__, i, ep->link_status.req_voltage_swing[i]);
+ if (max < ep->link_status.req_voltage_swing[i])
+ max = ep->link_status.req_voltage_swing[i];
+ }
+
+ ep->v_level = max;
+
+ /* use the max level across lanes */
+ max = 0;
+ for (i = 0; i < ep->lane_cnt; i++) {
+ pr_debug(" %s: lane=%d req_pre_emphasis=%d",
+ __func__, i, ep->link_status.req_pre_emphasis[i]);
+ if (max < ep->link_status.req_pre_emphasis[i])
+ max = ep->link_status.req_pre_emphasis[i];
+ }
+
+ ep->p_level = max;
+ pr_debug("%s: v_level=%d, p_level=%d", __func__,
+ ep->v_level, ep->p_level);
+}
+
+static void edp_host_train_set(struct mdss_edp_drv_pdata *ep, int train)
+{
+ int bit, cnt;
+ u32 data;
+
+
+ bit = 1;
+ bit <<= (train - 1);
+ pr_debug("%s: bit=%d train=%d\n", __func__, bit, train);
+ edp_write(ep->base + EDP_STATE_CTRL, bit);
+
+ bit = 8;
+ bit <<= (train - 1);
+ cnt = 10;
+ while (cnt--) {
+ data = edp_read(ep->base + EDP_MAINLINK_READY);
+ if (data & bit)
+ break;
+ }
+
+ if (cnt == 0)
+ pr_err("%s: set link_train=%d failed\n", __func__, train);
+}
+
+char vm_pre_emphasis[4][4] = {
+ {0x03, 0x06, 0x09, 0x0C}, /* pe0, 0 db */
+ {0x03, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */
+ {0x03, 0x06, 0xFF, 0xFF}, /* pe2, 6.0 db */
+ {0x03, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
+};
+
+/* voltage swing, 0.2v and 1.0v are not support */
+char vm_voltage_swing[4][4] = {
+ {0x14, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */
+ {0x18, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */
+ {0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */
+ {0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
+};
+
+static void edp_voltage_pre_emphasise_set(struct mdss_edp_drv_pdata *ep)
+{
+ u32 value0 = 0;
+ u32 value1 = 0;
+
+ pr_debug("%s: v=%d p=%d\n", __func__, ep->v_level, ep->p_level);
+
+ value0 = vm_pre_emphasis[(int)(ep->v_level)][(int)(ep->p_level)];
+ value1 = vm_voltage_swing[(int)(ep->v_level)][(int)(ep->p_level)];
+
+ /* Configure host and panel only if both values are allowed */
+ if (value0 != 0xFF && value1 != 0xFF) {
+ edp_write(ep->base + EDP_PHY_EDPPHY_GLB_VM_CFG0, value0);
+ edp_write(ep->base + EDP_PHY_EDPPHY_GLB_VM_CFG1, value1);
+ pr_debug("%s: value0=0x%x value1=0x%x", __func__,
+ value0, value1);
+ edp_lane_set_write(ep, ep->v_level, ep->p_level);
+ }
+
+}
+
+static int edp_start_link_train_1(struct mdss_edp_drv_pdata *ep)
+{
+ int tries, old_v_level;
+ int ret = 0;
+
+ pr_debug("%s:", __func__);
+
+ edp_host_train_set(ep, 0x01); /* train_1 */
+ edp_voltage_pre_emphasise_set(ep);
+ edp_train_pattern_set_write(ep, 0x21); /* train_1 */
+
+ tries = 0;
+ old_v_level = ep->v_level;
+ while (1) {
+ usleep(ep->dpcd.training_read_interval);
+
+ edp_link_status_read(ep, 6);
+ if (edp_sink_clock_recovery_done(ep)) {
+ ret = 0;
+ break;
+ }
+
+ if (ep->v_level == DPCD_LINK_VOLTAGE_MAX) {
+ ret = -1;
+ break; /* quit */
+ }
+
+ if (old_v_level == ep->v_level) {
+ tries++;
+ if (tries >= 5) {
+ ret = -1;
+ break; /* quit */
+ }
+ } else {
+ tries = 0;
+ old_v_level = ep->v_level;
+ }
+
+ edp_sink_train_set_adjust(ep);
+ edp_voltage_pre_emphasise_set(ep);
+ }
+
+ return ret;
+}
+
+static int edp_start_link_train_2(struct mdss_edp_drv_pdata *ep)
+{
+ int tries;
+ int ret = 0;
+ char pattern;
+
+ pr_debug("%s:", __func__);
+
+ if (ep->dpcd.flags & DPCD_TPS3)
+ pattern = 0x03;
+ else
+ pattern = 0x02;
+
+ edp_host_train_set(ep, pattern); /* train_2 */
+ edp_voltage_pre_emphasise_set(ep);
+ edp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */
+
+ tries = 0;
+ while (1) {
+ usleep(ep->dpcd.training_read_interval);
+
+ edp_link_status_read(ep, 6);
+
+ if (edp_sink_channel_eq_done(ep)) {
+ ret = 0;
+ break;
+ }
+
+ tries++;
+ if (tries > 5) {
+ ret = -1;
+ break;
+ }
+
+ edp_sink_train_set_adjust(ep);
+ edp_voltage_pre_emphasise_set(ep);
+ }
+
+ return ret;
+}
+
+static int edp_link_rate_shift(struct mdss_edp_drv_pdata *ep)
+{
+ /* add calculation later */
+ return -EINVAL;
+}
+
+static void edp_clear_training_pattern(struct mdss_edp_drv_pdata *ep)
+{
+ pr_debug("%s:\n", __func__);
+ edp_write(ep->base + EDP_STATE_CTRL, 0);
+ edp_train_pattern_set_write(ep, 0);
+ usleep(ep->dpcd.training_read_interval);
+}
+
+static int edp_aux_link_train(struct mdss_edp_drv_pdata *ep)
+{
+ int ret = 0;
+
+ pr_debug("%s", __func__);
+ ret = edp_aux_chan_ready(ep);
+ if (ret == 0) {
+ pr_err("%s: LINK Train failed: aux chan NOT ready\n", __func__);
+ complete(&ep->train_comp);
+ return ret;
+ }
+
+ /* start with max rate and lane */
+ ep->lane_cnt = ep->dpcd.max_lane_count;
+ ep->link_rate = ep->dpcd.max_link_rate;
+ edp_write(ep->base + EDP_MAINLINK_CTRL, 0x1);
+
+train_start:
+ ep->v_level = 0; /* start from default level */
+ ep->p_level = 0;
+ edp_cap_lane_rate_set(ep);
+
+ edp_clear_training_pattern(ep);
+ usleep(ep->dpcd.training_read_interval);
+ edp_powerstate_write(ep, 1);
+
+ ret = edp_start_link_train_1(ep);
+ if (ret < 0) {
+ if (edp_link_rate_shift(ep) == 0) {
+ goto train_start;
+ } else {
+ pr_err("%s: Training 1 failed", __func__);
+ ret = -1;
+ goto clear;
+ }
+ }
+
+ pr_debug("%s: Training 1 completed successfully", __func__);
+
+ edp_clear_training_pattern(ep);
+ ret = edp_start_link_train_2(ep);
+ if (ret < 0) {
+ if (edp_link_rate_shift(ep) == 0) {
+ goto train_start;
+ } else {
+ pr_err("%s: Training 2 failed", __func__);
+ ret = -1;
+ goto clear;
+ }
+ }
+
+ pr_debug("%s: Training 2 completed successfully", __func__);
+
+clear:
+ edp_clear_training_pattern(ep);
+
+ complete(&ep->train_comp);
+ return ret;
+}
+
+void mdss_edp_dpcd_cap_read(struct mdss_edp_drv_pdata *ep)
+{
+ edp_sink_capability_read(ep, 16);
+}
+
+void mdss_edp_dpcd_status_read(struct mdss_edp_drv_pdata *ep)
+{
+ edp_link_status_read(ep, 6);
+}
+
+void mdss_edp_edid_read(struct mdss_edp_drv_pdata *ep, int block)
+{
+ edp_sink_edid_read(ep, block);
+}
+
+int mdss_edp_link_train(struct mdss_edp_drv_pdata *ep)
+{
+ return edp_aux_link_train(ep);
+}
+
+void mdss_edp_aux_init(struct mdss_edp_drv_pdata *ep)
+{
+ mutex_init(&ep->aux_mutex);
+ init_completion(&ep->aux_comp);
+ init_completion(&ep->train_comp);
+ complete(&ep->train_comp); /* make non block at first time */
+
+ edp_buf_init(&ep->txp, ep->txbuf, sizeof(ep->txbuf));
+ edp_buf_init(&ep->rxp, ep->rxbuf, sizeof(ep->rxbuf));
+}
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index ce6b805..ac87cbd 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -111,7 +111,7 @@
return ret;
}
- if (notify > NOTIFY_UPDATE_STOP)
+ if (notify > NOTIFY_UPDATE_POWER_OFF)
return -EINVAL;
if (notify == NOTIFY_UPDATE_START) {
@@ -119,12 +119,19 @@
ret = wait_for_completion_interruptible_timeout(
&mfd->update.comp, 4 * HZ);
to_user = mfd->update.value;
- } else {
+ } else if (notify == NOTIFY_UPDATE_STOP) {
INIT_COMPLETION(mfd->no_update.comp);
ret = wait_for_completion_interruptible_timeout(
&mfd->no_update.comp, 4 * HZ);
to_user = mfd->no_update.value;
+ } else {
+ if (mfd->panel_power_on) {
+ INIT_COMPLETION(mfd->power_off_comp);
+ ret = wait_for_completion_interruptible_timeout(
+ &mfd->power_off_comp, 1 * HZ);
+ }
}
+
if (ret == 0)
ret = -ETIMEDOUT;
else if (ret > 0)
@@ -649,6 +656,9 @@
if (!op_enable)
return -EPERM;
+ if (mfd->dcm_state == DCM_ENTER)
+ return -EPERM;
+
switch (blank_mode) {
case FB_BLANK_UNBLANK:
if (!mfd->panel_power_on && mfd->mdp.on_fnc) {
@@ -690,6 +700,7 @@
else
mdss_fb_release_fences(mfd);
mfd->op_enable = true;
+ complete(&mfd->power_off_comp);
}
break;
}
@@ -1019,6 +1030,7 @@
mfd->ref_cnt = 0;
mfd->panel_power_on = false;
+ mfd->dcm_state = DCM_UNINIT;
mdss_fb_parse_dt_split(mfd);
@@ -1037,6 +1049,7 @@
mfd->no_update.timer.data = (unsigned long)mfd;
init_completion(&mfd->update.comp);
init_completion(&mfd->no_update.comp);
+ init_completion(&mfd->power_off_comp);
init_completion(&mfd->commit_comp);
init_completion(&mfd->power_set_comp);
INIT_WORK(&mfd->commit_work, mdss_fb_commit_wq_handler);
@@ -1522,6 +1535,58 @@
return 0;
}
+int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
+{
+ int ret = -EINVAL;
+
+ if (req_state == mfd->dcm_state) {
+ pr_warn("Already in correct DCM state");
+ ret = 0;
+ }
+
+ switch (req_state) {
+ case DCM_UNBLANK:
+ if (mfd->dcm_state == DCM_UNINIT &&
+ !mfd->panel_power_on && mfd->mdp.on_fnc) {
+ ret = mfd->mdp.on_fnc(mfd);
+ if (ret == 0) {
+ mfd->panel_power_on = true;
+ mfd->dcm_state = DCM_UNBLANK;
+ }
+ }
+ break;
+ case DCM_ENTER:
+ if (mfd->dcm_state == DCM_UNBLANK) {
+ /* Keep unblank path available for only
+ DCM operation */
+ mfd->panel_power_on = false;
+ mfd->dcm_state = DCM_ENTER;
+ ret = 0;
+ }
+ break;
+ case DCM_EXIT:
+ if (mfd->dcm_state == DCM_ENTER) {
+ /* Release the unblank path for exit */
+ mfd->panel_power_on = true;
+ mfd->dcm_state = DCM_EXIT;
+ ret = 0;
+ }
+ break;
+ case DCM_BLANK:
+ if ((mfd->dcm_state == DCM_EXIT ||
+ mfd->dcm_state == DCM_UNBLANK) &&
+ mfd->panel_power_on && mfd->mdp.off_fnc) {
+ ret = mfd->mdp.off_fnc(mfd);
+ if (ret == 0) {
+ mfd->panel_power_on = false;
+ mfd->dcm_state = DCM_UNINIT;
+ }
+ }
+ break;
+ }
+ return ret;
+}
+
static int mdss_fb_cursor(struct fb_info *info, void __user *p)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 12f3d68..030fd67 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -124,6 +124,7 @@
struct disp_info_notify update;
struct disp_info_notify no_update;
+ struct completion power_off_comp;
struct msm_mdp_interface mdp;
@@ -145,6 +146,8 @@
void *msm_fb_backup;
struct completion power_set_comp;
u32 is_power_setting;
+
+ u32 dcm_state;
};
struct msm_fb_backup_type {
@@ -177,4 +180,5 @@
void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd);
void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd);
int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp);
+int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state);
#endif /* MDSS_FB_H */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index 1f0efd3..bcd5f28 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -140,6 +140,48 @@
__func__, HDCP_STATE_NAME, hdcp_ddc_status, failure, nack0);
} /* reset_hdcp_ddc_failures */
+static void hdmi_hdcp_hw_ddc_clean(struct hdmi_hdcp_ctrl *hdcp_ctrl)
+{
+ struct dss_io_data *io = NULL;
+ u32 hdcp_ddc_status, ddc_hw_status;
+ u32 ddc_xfer_done, ddc_xfer_req, ddc_hw_done;
+ u32 ddc_hw_not_ready;
+ u32 timeout_count;
+
+ if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ io = hdcp_ctrl->init_data.core_io;
+ if (!io->base) {
+ DEV_ERR("%s: core io not inititalized\n", __func__);
+ return;
+ }
+
+ if (DSS_REG_R(io, HDMI_DDC_HW_STATUS) != 0) {
+ /* Wait to be clean on DDC HW engine */
+ timeout_count = 100;
+ do {
+ hdcp_ddc_status = DSS_REG_R(io, HDMI_HDCP_DDC_STATUS);
+ ddc_hw_status = DSS_REG_R(io, HDMI_DDC_HW_STATUS);
+ ddc_xfer_done = (hdcp_ddc_status & BIT(10)) ;
+ ddc_xfer_req = (hdcp_ddc_status & BIT(4)) ;
+ ddc_hw_done = (ddc_hw_status & BIT(3)) ;
+ ddc_hw_not_ready = ((ddc_xfer_done != 1) ||
+ (ddc_xfer_req != 0) || (ddc_hw_done != 1));
+
+ DEV_DBG("%s: %s: timeout count(%d):ddc hw%sready\n",
+ __func__, HDCP_STATE_NAME, timeout_count,
+ ddc_hw_not_ready ? " not " : " ");
+ DEV_DBG("hdcp_ddc_status[0x%x], ddc_hw_status[0x%x]\n",
+ hdcp_ddc_status, ddc_hw_status);
+ if (ddc_hw_not_ready)
+ msleep(20);
+ } while (ddc_hw_not_ready && --timeout_count);
+ }
+} /* hdmi_hdcp_hw_ddc_clean */
+
static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
{
int rc;
@@ -853,6 +895,7 @@
struct delayed_work *dw = to_delayed_work(work);
struct hdmi_hdcp_ctrl *hdcp_ctrl = container_of(dw,
struct hdmi_hdcp_ctrl, hdcp_auth_work);
+ struct dss_io_data *io;
if (!hdcp_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -865,6 +908,11 @@
return;
}
+ io = hdcp_ctrl->init_data.core_io;
+ /* Enabling Software DDC */
+ DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION , DSS_REG_R(io,
+ HDMI_DDC_ARBITRATION) & ~(BIT(4)));
+
rc = hdmi_hdcp_authentication_part1(hdcp_ctrl);
if (rc) {
DEV_DBG("%s: %s: HDCP Auth Part I failed\n", __func__,
@@ -878,6 +926,10 @@
HDCP_STATE_NAME);
goto error;
}
+ /* Disabling software DDC before going into part3 to make sure
+ * there is no Arbitratioon between software and hardware for DDC */
+ DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION , DSS_REG_R(io,
+ HDMI_DDC_ARBITRATION) | (BIT(4)));
error:
/*
@@ -969,6 +1021,9 @@
DSS_REG_W(io, HDMI_HDCP_RESET, BIT(0));
+ /* Wait to be clean on DDC HW engine */
+ hdmi_hdcp_hw_ddc_clean(hdcp_ctrl);
+
/* Disable encryption and disable the HDCP block */
DSS_REG_W(io, HDMI_HDCP_CTRL, 0);
@@ -1036,6 +1091,9 @@
DSS_REG_W(io, HDMI_HDCP_RESET, BIT(0));
+ /* Wait to be clean on DDC HW engine */
+ hdmi_hdcp_hw_ddc_clean(hdcp_ctrl);
+
/* Disable encryption and disable the HDCP block */
DSS_REG_W(io, HDMI_HDCP_CTRL, 0);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index e4a6b86..1fef395 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -866,13 +866,14 @@
static void hdmi_tx_hpd_int_work(struct work_struct *work)
{
struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+ struct dss_io_data *io;
hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, hpd_int_work);
if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
DEV_DBG("%s: invalid input\n", __func__);
return;
}
-
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
DEV_DBG("%s: Got HPD interrupt\n", __func__);
if (hdmi_ctrl->hpd_state) {
@@ -880,6 +881,9 @@
DEV_ERR("%s: Failed to enable ddc power\n", __func__);
return;
}
+ /* Enable SW DDC before EDID read */
+ DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION ,
+ DSS_REG_R(io, HDMI_DDC_ARBITRATION) & ~(BIT(4)));
hdmi_tx_read_sink_info(hdmi_ctrl);
hdmi_tx_send_cable_notification(hdmi_ctrl, 1);
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 950fd27..aba77e3 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -579,6 +579,10 @@
struct mdss_mdp_ctl *mdss_mdp_ctl_mixer_switch(struct mdss_mdp_ctl *ctl,
u32 return_type);
+int mdss_mdp_wb_set_format(struct msm_fb_data_type *mfd, int dst_format);
+int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd,
+ struct mdp_mixer_cfg *mixer_cfg);
+
#define mfd_to_mdp5_data(mfd) (mfd->mdp.private1)
#define mfd_to_mdata(mfd) (((struct mdss_overlay_private *)\
(mfd->mdp.private1))->mdata)
diff --git a/drivers/video/msm/mdss/mdss_mdp_formats.h b/drivers/video/msm/mdss/mdss_mdp_formats.h
index acb8dc2..f5da8e6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_formats.h
+++ b/drivers/video/msm/mdss/mdss_mdp_formats.h
@@ -124,6 +124,7 @@
FMT_RGB_8888(MDP_RGBA_8888, 1, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA),
FMT_RGB_8888(MDP_RGBX_8888, 0, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA),
FMT_RGB_8888(MDP_BGRA_8888, 1, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
+ FMT_RGB_8888(MDP_BGRX_8888, 0, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
FMT_YUV_PSEUDO(MDP_Y_CRCB_H1V1, MDSS_MDP_CHROMA_RGB, C2_R_Cr, C1_B_Cb),
FMT_YUV_PSEUDO(MDP_Y_CBCR_H1V1, MDSS_MDP_CHROMA_RGB, C1_B_Cb, C2_R_Cr),
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index d0c1818..cb4c1f2 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -224,7 +224,6 @@
mdss_mdp_ctl_intf_event
(ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
- complete(&ctx->stop_comp);
}
mutex_unlock(&ctx->clk_mtx);
}
@@ -255,6 +254,7 @@
if (ctx->rdptr_enabled == 0) {
mdss_mdp_irq_disable_nosync
(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num);
+ complete(&ctx->stop_comp);
schedule_work(&ctx->clk_work);
}
@@ -456,7 +456,7 @@
struct mdss_mdp_cmd_ctx *ctx;
unsigned long flags;
int need_wait = 0;
- int ret;
+ int ret = 0;
ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
if (!ctx) {
@@ -474,13 +474,15 @@
}
spin_unlock_irqrestore(&ctx->clk_lock, flags);
- if (need_wait) {
+ if (need_wait)
if (wait_for_completion_timeout(&ctx->stop_comp, STOP_TIMEOUT)
- <= 0) {
+ <= 0)
WARN(1, "stop cmd time out\n");
- mdss_mdp_cmd_clk_off(ctx);
- }
- }
+
+ if (cancel_work_sync(&ctx->clk_work))
+ pr_debug("no pending clk work\n");
+
+ mdss_mdp_cmd_clk_off(ctx);
ctx->panel_on = 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 24b27b4..4032b91 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -823,7 +823,7 @@
}
if (pipe->back_buf.num_planes) {
buf = &pipe->back_buf;
- } else if (ctl->play_cnt == 0) {
+ } else if (ctl->play_cnt == 0 && pipe->front_buf.num_planes) {
pipe->params_changed++;
buf = &pipe->front_buf;
} else if (!pipe->params_changed) {
@@ -1601,6 +1601,13 @@
if (ret)
return ret;
+ /* Supprt only MDP register read/write and
+ exit_dcm in DCM state*/
+ if (mfd->dcm_state == DCM_ENTER &&
+ (mdp_pp.op != mdp_op_calib_buffer &&
+ mdp_pp.op != mdp_op_calib_dcm_state))
+ return -EPERM;
+
switch (mdp_pp.op) {
case mdp_op_pa_cfg:
ret = mdss_mdp_pa_config(mdp5_data->ctl,
@@ -1681,6 +1688,9 @@
(struct mdp_calib_config_buffer *)
&mdp_pp.data.calib_buffer, ©back);
break;
+ case mdp_op_calib_dcm_state:
+ ret = mdss_fb_dcm(mfd, mdp_pp.data.calib_dcm.dcm_state);
+ break;
default:
pr_err("Unsupported request to MDP_PP IOCTL. %d = op\n",
mdp_pp.op);
@@ -1757,6 +1767,10 @@
return -EPERM;
ret = mdss_misr_crc_set(mdata, &metadata->data.misr_request);
break;
+ case metadata_op_wb_format:
+ ret = mdss_mdp_wb_set_format(mfd,
+ metadata->data.mixer_cfg.writeback_format);
+ break;
default:
pr_warn("unsupported request to MDP META IOCTL\n");
ret = -EINVAL;
@@ -1798,6 +1812,9 @@
return -EPERM;
ret = mdss_misr_crc_get(mdata, &metadata->data.misr_request);
break;
+ case metadata_op_wb_format:
+ ret = mdss_mdp_wb_get_format(mfd, &metadata->data.mixer_cfg);
+ break;
default:
pr_warn("Unsupported request to MDP META IOCTL.\n");
ret = -EINVAL;
@@ -1859,6 +1876,7 @@
case MSMFB_OVERLAY_PLAY_ENABLE:
if (!copy_from_user(&val, argp, sizeof(val))) {
mdp5_data->overlay_play_enable = val;
+ ret = 0;
} else {
pr_err("OVERLAY_PLAY_ENABLE failed (%d)\n", ret);
ret = -EFAULT;
@@ -1978,7 +1996,8 @@
if (!mfd->panel_info->cont_splash_enabled) {
rc = mdss_mdp_overlay_start(mfd);
- if (!IS_ERR_VALUE(rc) && (mfd->panel_info->type != DTV_PANEL))
+ if (!IS_ERR_VALUE(rc) && (mfd->panel_info->type != DTV_PANEL) &&
+ (mfd->panel_info->type != WRITEBACK_PANEL))
rc = mdss_mdp_overlay_kickoff(mfd);
} else {
rc = mdss_mdp_ctl_setup(mdp5_data->ctl);
@@ -2001,6 +2020,8 @@
{
int rc;
struct mdss_overlay_private *mdp5_data;
+ struct mdss_mdp_mixer *mixer;
+
if (!mfd)
return -ENODEV;
@@ -2018,6 +2039,15 @@
return 0;
mdss_mdp_overlay_free_fb_pipe(mfd);
+
+ mixer = mdss_mdp_mixer_get(mdp5_data->ctl, MDSS_MDP_MIXER_MUX_LEFT);
+ if (mixer)
+ mixer->cursor_enabled = 0;
+
+ mixer = mdss_mdp_mixer_get(mdp5_data->ctl, MDSS_MDP_MIXER_MUX_RIGHT);
+ if (mixer)
+ mixer->cursor_enabled = 0;
+
if (!mfd->ref_cnt) {
mdss_mdp_overlay_release_all(mfd);
} else {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index eaef12b..3f75053 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -162,6 +162,9 @@
int i;
int rc = 0, rot_mode = 0;
u32 nlines;
+ u16 width;
+
+ width = pipe->src.w >> pipe->horz_deci;
if (pipe->bwc_mode) {
rc = mdss_mdp_get_rau_strides(pipe->src.w, pipe->src.h,
@@ -172,11 +175,11 @@
ps.ystride[0], ps.ystride[1]);
} else if (mdata->has_decimation && pipe->src_fmt->is_yuv) {
ps.num_planes = 2;
- ps.ystride[0] = pipe->src.w >> pipe->horz_deci;
- ps.ystride[1] = pipe->src.h >> pipe->vert_deci;
+ ps.ystride[0] = width;
+ ps.ystride[1] = ps.ystride[0];
} else {
rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
- pipe->src.w, pipe->src.h, &ps, 0);
+ width, pipe->src.h, &ps, 0);
if (rc)
return rc;
@@ -184,7 +187,7 @@
rot_mode = 1;
else if (ps.num_planes == 1)
ps.ystride[0] = MAX_BPP *
- max(pipe->mixer->width, pipe->src.w);
+ max(pipe->mixer->width, width);
}
nlines = pipe->bwc_mode ? 1 : 2;
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index ff54067..0c74137 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -577,6 +577,86 @@
}
}
+int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd,
+ struct mdp_mixer_cfg *mixer_cfg)
+{
+ int dst_format;
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+
+ if (!ctl) {
+ pr_err("No panel data!\n");
+ return -EINVAL;
+ }
+
+ switch (ctl->dst_format) {
+ case MDP_RGB_888:
+ dst_format = WB_FORMAT_RGB_888;
+ break;
+ case MDP_RGB_565:
+ dst_format = WB_FORMAT_RGB_565;
+ break;
+ case MDP_XRGB_8888:
+ dst_format = WB_FORMAT_xRGB_8888;
+ break;
+ case MDP_ARGB_8888:
+ dst_format = WB_FORMAT_ARGB_8888;
+ break;
+ case MDP_BGRA_8888:
+ dst_format = WB_FORMAT_BGRA_8888;
+ break;
+ case MDP_BGRX_8888:
+ dst_format = WB_FORMAT_BGRX_8888;
+ break;
+ case MDP_Y_CBCR_H2V2_VENUS:
+ dst_format = WB_FORMAT_NV12;
+ break;
+ default:
+ return -EINVAL;
+ }
+ mixer_cfg->writeback_format = dst_format;
+ return 0;
+}
+
+int mdss_mdp_wb_set_format(struct msm_fb_data_type *mfd, int dst_format)
+{
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+
+ if (!ctl) {
+ pr_err("No panel data!\n");
+ return -EINVAL;
+ }
+
+ switch (dst_format) {
+ case WB_FORMAT_RGB_888:
+ ctl->dst_format = MDP_RGB_888;
+ break;
+ case WB_FORMAT_RGB_565:
+ ctl->dst_format = MDP_RGB_565;
+ break;
+ case WB_FORMAT_xRGB_8888:
+ ctl->dst_format = MDP_XRGB_8888;
+ break;
+ case WB_FORMAT_ARGB_8888:
+ ctl->dst_format = MDP_ARGB_8888;
+ break;
+ case WB_FORMAT_BGRA_8888:
+ ctl->dst_format = MDP_BGRA_8888;
+ break;
+ case WB_FORMAT_BGRX_8888:
+ ctl->dst_format = MDP_BGRX_8888;
+ break;
+ case WB_FORMAT_NV12:
+ ctl->dst_format = MDP_Y_CBCR_H2V2_VENUS;
+ break;
+ default:
+ pr_err("wfd format not supported\n");
+ return -EINVAL;
+ }
+
+ pr_debug("wfd format %d\n", ctl->dst_format);
+ return 0;
+}
+
int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd,
void *arg)
{
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 6c70cc4..c24f643 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -457,30 +457,84 @@
}
-/* EDP phy configuration settings */
-void mdss_edp_phy_sw_reset(unsigned char *edp_base)
+void mdss_edp_timing_engine_ctrl(unsigned char *edp_base, int enable)
{
- /* phy sw reset */
- edp_write(edp_base + 0x74, 0x100); /* EDP_PHY_CTRL */
- wmb();
- usleep(1);
- edp_write(edp_base + 0x74, 0x000); /* EDP_PHY_CTRL */
- wmb();
- usleep(1);
-
- /* phy PLL sw reset */
- edp_write(edp_base + 0x74, 0x001); /* EDP_PHY_CTRL */
- wmb();
- usleep(1);
- edp_write(edp_base + 0x74, 0x000); /* EDP_PHY_CTRL */
- wmb();
- usleep(1);
+ /* should eb last reg to program */
+ edp_write(edp_base + 0x94, enable); /* EDP_TIMING_ENGINE_EN */
}
-void mdss_edp_hw_powerup(unsigned char *edp_base, int enable)
+void mdss_edp_mainlink_ctrl(unsigned char *edp_base, int enable)
{
- int ret = 0;
+ edp_write(edp_base + 0x04, enable); /* EDP_MAINLINK_CTRL */
+}
+void mdss_edp_mainlink_reset(unsigned char *edp_base)
+{
+ edp_write(edp_base + 0x04, 0x02); /* EDP_MAINLINK_CTRL */
+ usleep(1000);
+ edp_write(edp_base + 0x04, 0); /* EDP_MAINLINK_CTRL */
+}
+
+void mdss_edp_aux_reset(unsigned char *edp_base)
+{
+ /*reset AUX */
+ edp_write(edp_base + 0x300, BIT(1)); /* EDP_AUX_CTRL */
+ usleep(1000);
+ edp_write(edp_base + 0x300, 0); /* EDP_AUX_CTRL */
+}
+
+void mdss_edp_aux_ctrl(unsigned char *edp_base, int enable)
+{
+ u32 data;
+
+ data = edp_read(edp_base + 0x300);
+ if (enable)
+ data |= 0x01;
+ else
+ data |= ~0x01;
+ edp_write(edp_base + 0x300, data); /* EDP_AUX_CTRL */
+}
+
+void mdss_edp_phy_pll_reset(unsigned char *edp_base)
+{
+ /* EDP_PHY_CTRL */
+ edp_write(edp_base + 0x74, 0x005); /* bit 0, 2 */
+ usleep(1000);
+ edp_write(edp_base + 0x74, 0x000); /* EDP_PHY_CTRL */
+}
+
+int mdss_edp_phy_pll_ready(unsigned char *edp_base)
+{
+ int cnt;
+ u32 status;
+
+ cnt = 10;
+ while (cnt--) {
+ status = edp_read(edp_base + 0x6c0);
+ if (status & 0x01)
+ break;
+ usleep(100);
+ }
+
+ if (cnt == 0) {
+ pr_err("%s: PLL NOT ready\n", __func__);
+ return 0;
+ } else
+ return 1;
+}
+
+int mdss_edp_phy_ready(unsigned char *edp_base)
+{
+ u32 status;
+
+ status = edp_read(edp_base + 0x598);
+ status &= 0x01;
+
+ return status;
+}
+
+void mdss_edp_phy_powerup(unsigned char *edp_base, int enable)
+{
if (enable) {
/* EDP_PHY_EDPPHY_GLB_PD_CTL */
edp_write(edp_base + 0x52c, 0x3f);
@@ -488,9 +542,6 @@
edp_write(edp_base + 0x528, 0x1);
/* EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG */
edp_write(edp_base + 0x620, 0xf);
- /* EDP_AUX_CTRL */
- ret = edp_read(edp_base + 0x300);
- edp_write(edp_base + 0x300, ret | 0x1);
} else {
/* EDP_PHY_EDPPHY_GLB_PD_CTL */
edp_write(edp_base + 0x52c, 0xc0);
@@ -527,7 +578,7 @@
edp_write(edp_base + 0x620, 0x7);
edp_write(edp_base + 0x620, 0xf);
- } else if (rate == 138500000) {
+ } else if (rate == 138530000) {
edp_write(edp_base + 0x664, 0x5); /* UNIPHY_PLL_LKDET_CFG2 */
edp_write(edp_base + 0x600, 0x1); /* UNIPHY_PLL_REFCLK_CFG */
edp_write(edp_base + 0x638, 0x36); /* UNIPHY_PLL_SDM_CFG0 */
@@ -558,7 +609,7 @@
edp_write(edp_base + 0x620, 0x7); /* UNIPHY_PLL_GLB_CFG */
edp_write(edp_base + 0x620, 0xf); /* UNIPHY_PLL_GLB_CFG */
} else {
- pr_err("%s: Unknown configuration rate\n", __func__);
+ pr_err("%s: rate=%d is NOT supported\n", __func__, rate);
}
}
@@ -598,22 +649,20 @@
}
}
-void mdss_edp_enable_lane_bist(unsigned char *edp_base, int lane, int enable)
+void mdss_edp_lane_power_ctrl(unsigned char *edp_base, int max_lane, int up)
{
- unsigned char *addr_ln_bist_cfg, *addr_ln_pd_ctrl;
+ int i, off;
+ u32 data;
+
+ if (up)
+ data = 0; /* power up */
+ else
+ data = 0x7; /* power down */
/* EDP_PHY_EDPPHY_LNn_PD_CTL */
- addr_ln_pd_ctrl = edp_base + 0x404 + (0x40 * lane);
- /* EDP_PHY_EDPPHY_LNn_BIST_CFG0 */
- addr_ln_bist_cfg = edp_base + 0x408 + (0x40 * lane);
-
- if (enable) {
- edp_write(addr_ln_pd_ctrl, 0x0);
- edp_write(addr_ln_bist_cfg, 0x10);
-
- } else {
- edp_write(addr_ln_pd_ctrl, 0xf);
- edp_write(addr_ln_bist_cfg, 0x10);
+ for (i = 0; i < max_lane; i++) {
+ off = 0x40 * i;
+ edp_write(edp_base + 0x404 + off , data);
}
}
@@ -668,12 +717,47 @@
return -EPERM;
}
-
-void mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
+int mdss_edp_aux_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
{
+ int ret;
+
+ if (clk_set_rate(edp_drv->aux_clk, 19200000) < 0)
+ pr_err("%s: aux_clk - clk_set_rate failed\n",
+ __func__);
+
+ ret = clk_enable(edp_drv->aux_clk);
+ if (ret) {
+ pr_err("%s: Failed to enable aux clk\n", __func__);
+ goto c2;
+ }
+
+ ret = clk_enable(edp_drv->ahb_clk);
+ if (ret) {
+ pr_err("%s: Failed to enable ahb clk\n", __func__);
+ goto c1;
+ }
+
+ return 0;
+c1:
+ clk_disable(edp_drv->aux_clk);
+c2:
+ return ret;
+
+}
+
+void mdss_edp_aux_clk_disable(struct mdss_edp_drv_pdata *edp_drv)
+{
+ clk_disable(edp_drv->aux_clk);
+ clk_disable(edp_drv->ahb_clk);
+}
+
+int mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
+{
+ int ret;
+
if (edp_drv->clk_on) {
pr_info("%s: edp clks are already ON\n", __func__);
- return;
+ return 0;
}
if (clk_set_rate(edp_drv->aux_clk, 19200000) < 0)
@@ -688,12 +772,39 @@
pr_err("%s: link_clk - clk_set_rate failed\n",
__func__);
- clk_enable(edp_drv->aux_clk);
- clk_enable(edp_drv->pixel_clk);
- clk_enable(edp_drv->ahb_clk);
- clk_enable(edp_drv->link_clk);
+ ret = clk_enable(edp_drv->aux_clk);
+ if (ret) {
+ pr_err("%s: Failed to enable aux clk\n", __func__);
+ goto c4;
+ }
+ ret = clk_enable(edp_drv->pixel_clk);
+ if (ret) {
+ pr_err("%s: Failed to enable pixel clk\n", __func__);
+ goto c3;
+ }
+ ret = clk_enable(edp_drv->ahb_clk);
+ if (ret) {
+ pr_err("%s: Failed to enable ahb clk\n", __func__);
+ goto c2;
+ }
+ ret = clk_enable(edp_drv->link_clk);
+ if (ret) {
+ pr_err("%s: Failed to enable link clk\n", __func__);
+ goto c1;
+ }
edp_drv->clk_on = 1;
+
+ return 0;
+
+c1:
+ clk_disable(edp_drv->ahb_clk);
+c2:
+ clk_disable(edp_drv->pixel_clk);
+c3:
+ clk_disable(edp_drv->aux_clk);
+c4:
+ return ret;
}
void mdss_edp_clk_disable(struct mdss_edp_drv_pdata *edp_drv)
@@ -711,12 +822,69 @@
edp_drv->clk_on = 0;
}
-void mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
+int mdss_edp_prepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv)
{
- clk_prepare(edp_drv->aux_clk);
- clk_prepare(edp_drv->pixel_clk);
- clk_prepare(edp_drv->ahb_clk);
- clk_prepare(edp_drv->link_clk);
+ int ret;
+
+ ret = clk_prepare(edp_drv->aux_clk);
+ if (ret) {
+ pr_err("%s: Failed to prepare aux clk\n", __func__);
+ goto c2;
+ }
+ ret = clk_prepare(edp_drv->ahb_clk);
+ if (ret) {
+ pr_err("%s: Failed to prepare ahb clk\n", __func__);
+ goto c1;
+ }
+
+ return 0;
+c1:
+ clk_unprepare(edp_drv->aux_clk);
+c2:
+ return ret;
+
+}
+
+void mdss_edp_unprepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv)
+{
+ clk_unprepare(edp_drv->aux_clk);
+ clk_unprepare(edp_drv->ahb_clk);
+}
+
+int mdss_edp_prepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
+{
+ int ret;
+
+ ret = clk_prepare(edp_drv->aux_clk);
+ if (ret) {
+ pr_err("%s: Failed to prepare aux clk\n", __func__);
+ goto c4;
+ }
+ ret = clk_prepare(edp_drv->pixel_clk);
+ if (ret) {
+ pr_err("%s: Failed to prepare pixel clk\n", __func__);
+ goto c3;
+ }
+ ret = clk_prepare(edp_drv->ahb_clk);
+ if (ret) {
+ pr_err("%s: Failed to prepare ahb clk\n", __func__);
+ goto c2;
+ }
+ ret = clk_prepare(edp_drv->link_clk);
+ if (ret) {
+ pr_err("%s: Failed to prepare link clk\n", __func__);
+ goto c1;
+ }
+
+ return 0;
+c1:
+ clk_unprepare(edp_drv->ahb_clk);
+c2:
+ clk_unprepare(edp_drv->pixel_clk);
+c3:
+ clk_unprepare(edp_drv->aux_clk);
+c4:
+ return ret;
}
void mdss_edp_unprepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
@@ -775,14 +943,29 @@
mdss_edp_enable_pixel_clk(edp_base, mmss_cc_base, 0);
}
-void mdss_edp_phy_misc_cfg(unsigned char *edp_base)
+void mdss_edp_clock_synchrous(unsigned char *edp_base, int sync)
+{
+ u32 data;
+
+ /* EDP_MISC1_MISC0 */
+ data = edp_read(edp_base + 0x02c);
+
+ if (sync)
+ data |= 0x01;
+ else
+ data &= ~0x01;
+
+ /* EDP_MISC1_MISC0 */
+ edp_write(edp_base + 0x2c, data);
+}
+
+/* voltage mode and pre emphasis cfg */
+void mdss_edp_phy_vm_pe_init(unsigned char *edp_base)
{
/* EDP_PHY_EDPPHY_GLB_VM_CFG0 */
- edp_write(edp_base + 0x510, 0x3);
+ edp_write(edp_base + 0x510, 0x3); /* vm only */
/* EDP_PHY_EDPPHY_GLB_VM_CFG1 */
edp_write(edp_base + 0x514, 0x64);
/* EDP_PHY_EDPPHY_GLB_MISC9 */
edp_write(edp_base + 0x518, 0x6c);
- /* EDP_MISC1_MISC0 */
- edp_write(edp_base + 0x2c, 0x1);
}
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/batterydata-lib.h
similarity index 93%
rename from include/linux/mfd/pm8xxx/batterydata-lib.h
rename to include/linux/batterydata-lib.h
index 644eede..fe2d86f 100644
--- a/include/linux/mfd/pm8xxx/batterydata-lib.h
+++ b/include/linux/batterydata-lib.h
@@ -10,8 +10,8 @@
* GNU General Public License for more details.
*/
-#ifndef __PM8XXX_BMS_BATTERYDATA_H
-#define __PM8XXX_BMS_BATTERYDATA_H
+#ifndef __BMS_BATTERYDATA_H
+#define __BMS_BATTERYDATA_H
#include <linux/errno.h>
@@ -95,6 +95,11 @@
* battery capacitance
* @flat_ocv_threshold_uv: the voltage where the battery's discharge curve
* starts flattening out.
+ * @max_voltage_uv: max voltage of the battery
+ * @cutoff_uv: cutoff voltage of the battery
+ * @iterm_ua: termination current of the battery when charging
+ * to 100%
+ * @batt_id_kohm: battery id resistor value
*/
struct bms_battery_data {
@@ -108,6 +113,10 @@
int delta_rbatt_mohm;
int rbatt_capacitive_mohm;
int flat_ocv_threshold_uv;
+ int max_voltage_uv;
+ int cutoff_uv;
+ int iterm_ua;
+ int batt_id_kohm;
};
#if defined(CONFIG_PM8921_BMS) || \
diff --git a/include/linux/bug.h b/include/linux/bug.h
index 72961c3..cd141a4 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -96,4 +96,10 @@
}
#endif /* CONFIG_GENERIC_BUG */
+
+#ifdef CONFIG_PANIC_ON_DATA_CORRUPTION
+#define PANIC_CORRUPTION 1
+#else
+#define PANIC_CORRUPTION 0
+#endif /* CONFIG_PANIC_ON_DATA_CORRUPTION */
#endif /* _LINUX_BUG_H */
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 73016d6..d121695 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -35,8 +35,11 @@
* struct synaptics_rmi4_platform_data - rmi4 platform data
* @x_flip: x flip flag
* @y_flip: y flip flag
+ * @i2c_pull_up: pull up i2c bus with regulator
+ * @power_down_enable: enable complete regulator shutdown in suspend
* @irq_gpio: attention interrupt gpio
* @irq_flags: flags used by the irq
+ * @reset_flags: flags used by reset line
* @reset_gpio: reset gpio
* @panel_x: panel maximum values on the x
* @panel_y: panel maximum values on the y
@@ -47,6 +50,7 @@
bool x_flip;
bool y_flip;
bool i2c_pull_up;
+ bool power_down_enable;
unsigned irq_gpio;
u32 irq_flags;
u32 reset_flags;
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index cd70726..85dec85 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -14,7 +14,7 @@
#define __PM8XXX_BMS_H
#include <linux/errno.h>
-#include <linux/mfd/pm8xxx/batterydata-lib.h>
+#include <linux/batterydata-lib.h>
#define PM8921_BMS_DEV_NAME "pm8921-bms"
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 72e31b2..94d8245 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -241,6 +241,7 @@
struct sdhci_next next_data;
ktime_t data_start_time;
+ struct mutex ios_mutex;
unsigned long private[0] ____cacheline_aligned;
};
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index c3ff9de..2455212 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -87,6 +87,7 @@
enum {
NOTIFY_UPDATE_START,
NOTIFY_UPDATE_STOP,
+ NOTIFY_UPDATE_POWER_OFF,
};
enum {
@@ -612,6 +613,19 @@
uint32_t *buffer;
};
+struct mdp_calib_dcm_state {
+ uint32_t ops;
+ uint32_t dcm_state;
+};
+
+enum {
+ DCM_UNINIT,
+ DCM_UNBLANK,
+ DCM_ENTER,
+ DCM_EXIT,
+ DCM_BLANK,
+};
+
#define MDSS_MAX_BL_BRIGHTNESS 255
#define AD_BL_LIN_LEN (MDSS_MAX_BL_BRIGHTNESS + 1)
@@ -704,6 +718,7 @@
mdp_op_ad_input,
mdp_op_calib_mode,
mdp_op_calib_buffer,
+ mdp_op_calib_dcm_state,
mdp_op_max,
};
@@ -713,6 +728,8 @@
WB_FORMAT_RGB_888,
WB_FORMAT_xRGB_8888,
WB_FORMAT_ARGB_8888,
+ WB_FORMAT_BGRA_8888,
+ WB_FORMAT_BGRX_8888,
WB_FORMAT_ARGB_8888_INPUT_ALPHA /* Need to support */
};
@@ -732,6 +749,7 @@
struct mdss_calib_cfg mdss_calib_cfg;
struct mdss_ad_input ad_input;
struct mdp_calib_config_buffer calib_buffer;
+ struct mdp_calib_dcm_state calib_dcm;
} data;
};
diff --git a/include/linux/of_batterydata.h b/include/linux/of_batterydata.h
new file mode 100644
index 0000000..b2ed5a1
--- /dev/null
+++ b/include/linux/of_batterydata.h
@@ -0,0 +1,45 @@
+/* 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 <linux/of.h>
+#include <linux/batterydata-lib.h>
+
+#ifdef CONFIG_OF_BATTERYDATA
+/**
+ * of_batterydata_read_data() - Populate battery data from the device tree
+ * @container_node: pointer to the battery-data container device node
+ * containing the profile nodes.
+ * @batt_data: pointer to an allocated bms_battery_data structure that the
+ * loaded profile will be written to.
+ * @batt_id_uv: ADC voltage of the battery id line used to differentiate
+ * between different battery profiles. If there are multiple
+ * battery data in the device tree, the one with the closest
+ * battery id resistance will be automatically loaded.
+ *
+ * This routine loads the closest match battery data from device tree based on
+ * the battery id reading. Then, it will try to load all the relevant data from
+ * the device tree battery data profile.
+ *
+ * If any of the lookup table pointers are NULL, this routine will skip trying
+ * to read them.
+ */
+int of_batterydata_read_data(struct device_node *container_node,
+ struct bms_battery_data *batt_data,
+ int batt_id_uv);
+#else
+static inline int of_batterydata_read_data(struct device_node *container_node,
+ struct bms_battery_data *batt_data,
+ int batt_id_uv);
+{
+ return -ENXIO;
+}
+#endif /* CONFIG_OF_QPNP */
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 3d7b1c9..5d6cdac 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -98,7 +98,9 @@
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CURRENT_AVG,
POWER_SUPPLY_PROP_POWER_NOW,
@@ -283,6 +285,7 @@
case POWER_SUPPLY_PROP_CHARGE_COUNTER:
case POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW:
case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
case POWER_SUPPLY_PROP_CURRENT_NOW:
case POWER_SUPPLY_PROP_CURRENT_AVG:
return 1;
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index dfb156f..013a778 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -1419,11 +1419,16 @@
enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result);
/**
- * qpnp_iadc_calibrate_for_trim() - Clients can use this API to re-calibrate
- * IADC.
- * @result: 0 on success.
+ * qpnp_iadc_calibrate_for_trim - Clients can use this API to re-calibrate
+ * IADC. The offset and gain values are programmed in the trim
+ * registers. The offset and the gain can be retrieved using
+ * qpnp_iadc_get_gain_and_offset
+ * @batfet_closed: batfet is opened or closed. The IADC chooses proper
+ * channel (internal/external) based on batfet status
+ * for calibration.
+ * RETURNS: 0 on success.
*/
-int32_t qpnp_iadc_calibrate_for_trim(void);
+int32_t qpnp_iadc_calibrate_for_trim(bool batfet_closed);
int32_t qpnp_iadc_comp_result(int64_t *result);
#else
static inline int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
@@ -1440,7 +1445,7 @@
enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result)
{ return -ENXIO; }
-static inline int32_t qpnp_iadc_calibrate_for_trim(void)
+static inline int32_t qpnp_iadc_calibrate_for_trim(bool batfet_closed)
{ return -ENXIO; }
static inline int32_t qpnp_iadc_comp_result(int64_t *result, int32_t sign)
{ return -ENXIO; }
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index f04d2bf..5fd1f22 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -228,6 +228,8 @@
* interrupt threshold (ITC), when log2_itc is
* between 1 to 7.
* @l1_supported: enable link power management support.
+ * @dpdm_pulldown_added: Indicates whether pull down resistors are
+ connected on data lines or not.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -255,6 +257,7 @@
const char *mhl_dev_name;
int log2_itc;
bool l1_supported;
+ bool dpdm_pulldown_added;
};
/* phy related flags */
@@ -435,6 +438,7 @@
struct power_supply usb_psy;
unsigned int online;
unsigned int host_mode;
+ unsigned int voltage_max;
unsigned int current_max;
dev_t ext_chg_dev;
@@ -525,12 +529,14 @@
};
#ifdef CONFIG_USB_BAM
bool msm_bam_lpm_ok(void);
+void msm_bam_notify_lpm_resume(void);
void msm_bam_set_hsic_host_dev(struct device *dev);
void msm_bam_wait_for_hsic_prod_granted(void);
bool msm_bam_hsic_lpm_ok(void);
void msm_bam_hsic_notify_on_resume(void);
#else
static inline bool msm_bam_lpm_ok(void) { return true; }
+static inline void msm_bam_notify_lpm_resume(void) {}
static inline void msm_bam_set_hsic_host_dev(struct device *dev) {}
static inline void msm_bam_wait_for_hsic_prod_granted(void) {}
static inline bool msm_bam_hsic_lpm_ok(void) { return true; }
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 7ad0c16..4404df5 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -703,6 +703,7 @@
#define V4L2_QCOM_BUF_FLAG_IDRFRAME 0x20000 /* Image is a IDR-frame */
#define V4L2_QCOM_BUF_FLAG_DECODEONLY 0x40000
#define V4L2_QCOM_BUF_DATA_CORRUPT 0x80000
+#define V4L2_QCOM_BUF_DROP_FRAME 0x100000
/*
* O V E R L A Y P R E V I E W
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index c47c9da..162729a 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -6,6 +6,7 @@
#endif
#include <linux/videodev2.h>
#include <linux/types.h>
+#include <media/msmb_generic_buf_mgr.h>
/* Should be same as VIDEO_MAX_PLANES in videodev2.h */
#define MAX_PLANES VIDEO_MAX_PLANES
@@ -174,6 +175,10 @@
struct msm_vpe_buffer_info_t output_buffer_info;
};
+struct msm_pproc_queue_buf_info {
+ struct msm_buf_mngr_info buff_mgr_info;
+ uint8_t is_buf_dirty;
+};
#define VIDIOC_MSM_CPP_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE, struct msm_camera_v4l2_ioctl_t)
@@ -218,7 +223,7 @@
#define VIDIOC_MSM_VPE_DEQUEUE_STREAM_BUFF_INFO \
_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct msm_camera_v4l2_ioctl_t)
-#define VIDIOC_MSM_CPP_SEND_BUF_DONE \
+#define VIDIOC_MSM_CPP_QUEUE_BUF \
_IOWR('V', BASE_VIDIOC_PRIVATE + 14, struct msm_camera_v4l2_ioctl_t)
#define V4L2_EVENT_CPP_FRAME_DONE (V4L2_EVENT_PRIVATE_START + 0)
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 887b291..4cbac7b 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -77,6 +77,9 @@
#define RDS_PS0_LEN 6
#define RX_REPEATE_BYTE_OFFSET 5
+#define FM_AF_LIST_MAX_SIZE 200
+#define AF_LIST_MAX (FM_AF_LIST_MAX_SIZE / 4) /* Each AF frequency consist
+ of sizeof(int) bytes */
/* HCI timeouts */
#define RADIO_HCI_TIMEOUT (10000) /* 10 seconds */
@@ -485,7 +488,7 @@
__le32 tune_freq;
__le16 pi_code;
__u8 af_size;
- __u8 af_list[25];
+ __u8 af_list[FM_AF_LIST_MAX_SIZE];
} __packed;
struct hci_ev_cmd_complete {
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index f1a6e9e..90fd57d 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -41,6 +41,7 @@
#include <linux/debug_locks.h>
#include <linux/lockdep.h>
#include <linux/idr.h>
+#include <linux/bug.h>
#include "workqueue_sched.h"
@@ -1878,6 +1879,7 @@
printk(KERN_ERR " last function: ");
print_symbol("%s\n", (unsigned long)f);
debug_show_held_locks(current);
+ BUG_ON(PANIC_CORRUPTION);
dump_stack();
}
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 097d70f..b9060a1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1290,6 +1290,13 @@
If unsure, say N.
+config PANIC_ON_DATA_CORRUPTION
+ bool "Cause a Kernel Panic When Data Corruption is detected"
+ help
+ Select this option to upgrade warnings for potentially
+ recoverable data corruption scenarios to system-halting panics,
+ for easier detection and debug.
+
source "samples/Kconfig"
source "lib/Kconfig.kgdb"
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 982b850..6a039a6 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -10,6 +10,7 @@
#include <linux/list.h>
#include <linux/bug.h>
#include <linux/kernel.h>
+#include <linux/bug.h>
/*
* Insert a new entry between two known consecutive entries.
@@ -30,6 +31,10 @@
"list_add corruption. prev->next should be "
"next (%p), but was %p. (prev=%p).\n",
next, prev->next, prev);
+
+ BUG_ON(((prev->next != next) || (next->prev != prev)) &&
+ PANIC_CORRUPTION);
+
next->prev = new;
new->next = next;
new->prev = prev;
@@ -55,8 +60,10 @@
"but was %p\n", entry, prev->next) ||
WARN(next->prev != entry,
"list_del corruption. next->prev should be %p, "
- "but was %p\n", entry, next->prev))
+ "but was %p\n", entry, next->prev)) {
+ BUG_ON(PANIC_CORRUPTION);
return;
+ }
__list_del(prev, next);
}
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index f2aa5de..ac516f4 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -12,6 +12,7 @@
#include <linux/debug_locks.h>
#include <linux/delay.h>
#include <linux/export.h>
+#include <linux/bug.h>
void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name,
struct lock_class_key *key)
@@ -64,6 +65,7 @@
owner ? owner->comm : "<none>",
owner ? task_pid_nr(owner) : -1,
lock->owner_cpu);
+ BUG_ON(PANIC_CORRUPTION);
dump_stack();
}
diff --git a/net/core/flow.c b/net/core/flow.c
index e318c7e..9a517c6 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -423,6 +423,7 @@
if (!fc->percpu)
return -ENOMEM;
+ get_online_cpus();
for_each_online_cpu(i) {
if (flow_cache_cpu_prepare(fc, i))
goto err;
@@ -431,6 +432,7 @@
.notifier_call = flow_cache_cpu,
};
register_hotcpu_notifier(&fc->hotcpu_notifier);
+ put_online_cpus();
setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd,
(unsigned long) fc);
@@ -440,6 +442,7 @@
return 0;
err:
+ put_online_cpus();
for_each_possible_cpu(i) {
struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, i);
kfree(fcp->hash_table);
diff --git a/scripts/build-all.py b/scripts/build-all.py
index c585e4a..5a109bb 100755
--- a/scripts/build-all.py
+++ b/scripts/build-all.py
@@ -46,8 +46,8 @@
make_env = os.environ
make_env.update({
'ARCH': 'arm',
- 'CROSS_COMPILE': 'arm-none-linux-gnueabi-',
'KCONFIG_NOTIMESTAMP': 'true' })
+make_env.setdefault('CROSS_COMPILE', 'arm-none-linux-gnueabi-')
all_options = {}
def error(msg):
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index de0b4da..46b0a91 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -2891,6 +2891,7 @@
if (client->addr != HELICON_CORE_0_I2C_ADDR)
goto rtn;
+ dev_set_name(&client->dev, "%s", MSM8X10_CODEC_NAME);
dev = &client->dev;
if (client->dev.of_node) {
dev_dbg(&client->dev, "%s:Platform data from device tree\n",
diff --git a/sound/soc/codecs/msm8x10-wcd.h b/sound/soc/codecs/msm8x10-wcd.h
index d8f6ace..8e561cf 100644
--- a/sound/soc/codecs/msm8x10-wcd.h
+++ b/sound/soc/codecs/msm8x10-wcd.h
@@ -32,6 +32,7 @@
#define MSM8X10_DINO_LPASS_DIGCODEC_CBCR 0xFE02C014
#define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR 0xFE02C018
+#define MSM8X10_CODEC_NAME "msm8x10_wcd_codec"
#define MSM8X10_WCD_IS_DINO_REG(reg) \
(((reg >= 0x400) && (reg <= 0x5FF)) ? 1 : 0)
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 7b896c2..a6390dd 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -4554,7 +4554,6 @@
}
}
- wcd9xxx_resmgr_post_ssr(&tapan->resmgr);
if (spkr_drv_wrnd == 1)
snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x80);
@@ -4567,6 +4566,8 @@
tapan_slim_interface_init_reg(codec);
+ wcd9xxx_resmgr_post_ssr(&tapan->resmgr);
+
wcd9xxx_mbhc_deinit(&tapan->mbhc);
if (TAPAN_IS_1_0(wcd9xxx->version))
@@ -4575,7 +4576,7 @@
rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
- &mbhc_cb, rco_clk_rate);
+ &mbhc_cb, rco_clk_rate, false);
if (ret)
pr_err("%s: mbhc init failed %d\n", __func__, ret);
else
@@ -4677,7 +4678,7 @@
rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
- &mbhc_cb, rco_clk_rate);
+ &mbhc_cb, rco_clk_rate, false);
if (ret) {
pr_err("%s: mbhc init failed %d\n", __func__, ret);
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 59354a3..c27e085 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -6230,7 +6230,6 @@
codec->reg_size, GFP_KERNEL);
}
- wcd9xxx_resmgr_post_ssr(&taiko->resmgr);
if (spkr_drv_wrnd == 1)
snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
@@ -6243,6 +6242,8 @@
taiko_init_slim_slave_cfg(codec);
taiko_slim_interface_init_reg(codec);
+ wcd9xxx_resmgr_post_ssr(&taiko->resmgr);
+
if (taiko->mbhc_started) {
wcd9xxx_mbhc_deinit(&taiko->mbhc);
taiko->mbhc_started = false;
@@ -6254,7 +6255,7 @@
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
taiko_enable_mbhc_micbias,
- NULL, rco_clk_rate);
+ NULL, rco_clk_rate, true);
if (ret) {
pr_err("%s: mbhc init failed %d\n", __func__, ret);
} else {
@@ -6436,7 +6437,7 @@
/* init and start mbhc */
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
taiko_enable_mbhc_micbias,
- NULL, rco_clk_rate);
+ NULL, 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-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index d0c00a7..6fdebe6 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -799,8 +799,8 @@
pr_debug("%s: Enabling micbias\n", __func__);
mbhc->micbias_enable_cb(mbhc->codec, true);
}
-
- wcd9xxx_detect_impedance(mbhc, &mbhc->zl, &mbhc->zr);
+ if (mbhc->impedance_detect)
+ wcd9xxx_detect_impedance(mbhc, &mbhc->zl, &mbhc->zr);
pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
jack_type, mbhc->hph_status);
wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
@@ -3938,7 +3938,8 @@
int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
struct snd_soc_codec *codec,
int (*micbias_enable_cb) (struct snd_soc_codec*, bool),
- const struct wcd9xxx_mbhc_cb *mbhc_cb, int rco_clk_rate)
+ const struct wcd9xxx_mbhc_cb *mbhc_cb, int rco_clk_rate,
+ bool impedance_det_en)
{
int ret;
void *core;
@@ -3964,6 +3965,7 @@
mbhc->micbias_enable_cb = micbias_enable_cb;
mbhc->rco_clk_rate = rco_clk_rate;
mbhc->mbhc_cb = mbhc_cb;
+ mbhc->impedance_detect = impedance_det_en;
if (mbhc->headset_jack.jack == NULL) {
ret = snd_soc_jack_new(codec, "Headset Jack", WCD9XXX_JACK_MASK,
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 1f6502f..0599ccb 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -291,6 +291,7 @@
bool micbias_enable;
int (*micbias_enable_cb) (struct snd_soc_codec*, bool);
+ bool impedance_detect;
/* impedance of hphl and hphr */
uint32_t zl, zr;
@@ -363,7 +364,8 @@
struct snd_soc_codec *codec,
int (*micbias_enable_cb) (struct snd_soc_codec*, bool),
const struct wcd9xxx_mbhc_cb *mbhc_cb,
- int rco_clk_rate);
+ int rco_clk_rate,
+ bool impedance_det_en);
void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
void *wcd9xxx_mbhc_cal_btn_det_mp(
const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
diff --git a/sound/soc/msm/apq8074.c b/sound/soc/msm/apq8074.c
index cb101bd..3a055e2 100644
--- a/sound/soc/msm/apq8074.c
+++ b/sound/soc/msm/apq8074.c
@@ -123,7 +123,7 @@
.gpio = 0,
.gpio_irq = 0,
.gpio_level_insert = 1,
- .detect_extn_cable = true,
+ .detect_extn_cable = false,
.insert_detect = true,
.swap_gnd_mic = NULL,
};
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index a0ed887..41fe8aa 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -741,6 +741,30 @@
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia9",
},
+ {
+ .playback = {
+ .stream_name = "QCHAT Playback",
+ .aif_name = "QCHAT_DL",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "QCHAT Capture",
+ .aif_name = "QCHAT_UL",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "QCHAT",
+ },
};
static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index 4d9632c..340d3db 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -587,7 +587,7 @@
.stream_name = "Secondary MI2S Playback",
.cpu_dai_name = "msm-dai-q6-mi2s.1",
.platform_name = "msm-pcm-routing",
- .codec_name = "msm8x10-wcd-i2c-core.5-000d",
+ .codec_name = MSM8X10_CODEC_NAME,
.codec_dai_name = "msm8x10_wcd_i2s_rx1",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
@@ -601,7 +601,7 @@
.stream_name = "Primary MI2S Capture",
.cpu_dai_name = "msm-dai-q6-mi2s.0",
.platform_name = "msm-pcm-routing",
- .codec_name = "msm8x10-wcd-i2c-core.5-000d",
+ .codec_name = MSM8X10_CODEC_NAME,
.codec_dai_name = "msm8x10_wcd_i2s_tx1",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_PRI_MI2S_TX,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index d02713a..0a54869 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -627,6 +627,8 @@
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
else if (val == MSM_FRONTEND_DAI_VOICE2)
session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+ else if (val == MSM_FRONTEND_DAI_QCHAT)
+ session_id = voc_get_session_id(QCHAT_SESSION_NAME);
else
session_id = voc_get_session_id(VOIP_SESSION_NAME);
@@ -1869,6 +1871,9 @@
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new mmul5_mixer_controls[] = {
@@ -1914,6 +1919,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new sec_i2s_rx_voice_mixer_controls[] = {
@@ -1932,6 +1940,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new sec_mi2s_rx_voice_mixer_controls[] = {
@@ -1950,6 +1961,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
@@ -1971,6 +1985,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
@@ -1992,6 +2009,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new mi2s_rx_voice_mixer_controls[] = {
@@ -2013,6 +2033,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_MI2S_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
@@ -2034,6 +2057,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
@@ -2055,6 +2081,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new sec_aux_pcm_rx_voice_mixer_controls[] = {
@@ -2073,6 +2102,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
@@ -2094,6 +2126,9 @@
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
@@ -2243,6 +2278,33 @@
msm_routing_put_voice_stub_mixer),
};
+static const struct snd_kcontrol_new tx_qchat_mixer_controls[] = {
+ SOC_SINGLE_EXT("PRI_TX_QCHAT", MSM_BACKEND_DAI_PRI_I2S_TX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SLIM_0_TX_QCHAT", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_QCHAT",
+ MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_QCHAT, 1, 0,
+ msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX_QCHAT", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("AUX_PCM_TX_QCHAT", MSM_BACKEND_DAI_AUXPCM_TX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX_QCHAT", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("MI2S_TX_QCHAT", MSM_BACKEND_DAI_MI2S_TX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("PRI_MI2S_TX_QCHAT", MSM_BACKEND_DAI_PRI_MI2S_TX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+};
+
static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
@@ -2831,6 +2893,8 @@
/* LSM */
SND_SOC_DAPM_AIF_OUT("LSM_UL_HL", "Listen Audio Service Capture",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("QCHAT_DL", "QCHAT Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("QCHAT_UL", "QCHAT Capture", 0, 0, 0, 0),
/* Backend AIF */
/* Stream name equals to backend dai link stream name
*/
@@ -3065,6 +3129,9 @@
SND_SOC_DAPM_MIXER("PRI_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0,
primary_mi2s_rx_port_mixer_controls,
ARRAY_SIZE(primary_mi2s_rx_port_mixer_controls)),
+ SND_SOC_DAPM_MIXER("QCHAT_Tx Mixer",
+ SND_SOC_NOPM, 0, 0, tx_qchat_mixer_controls,
+ ARRAY_SIZE(tx_qchat_mixer_controls)),
/* Virtual Pins to force backends ON atm */
SND_SOC_DAPM_OUTPUT("BE_OUT"),
SND_SOC_DAPM_INPUT("BE_IN"),
@@ -3136,6 +3203,7 @@
{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
{"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
{"MultiMedia4 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"MultiMedia4 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"MultiMedia5 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -3266,6 +3334,7 @@
{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
{"MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3273,6 +3342,7 @@
{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"PRI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"PRI_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3280,6 +3350,7 @@
{"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SEC_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"SEC_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
{"SEC_MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3287,6 +3358,7 @@
{"SEC_MI2S_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"SEC_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SEC_MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"SEC_MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"SEC_MI2S_RX", NULL, "SEC_MI2S_RX_Voice Mixer"},
{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3295,6 +3367,7 @@
{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SLIM_0_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"SLIM_0_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"SLIM_0_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3302,6 +3375,7 @@
{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"INTERNAL_BT_SCO_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3309,6 +3383,7 @@
{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"AFE_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"AFE_PCM_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3317,6 +3392,7 @@
{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"AUX_PCM_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"AUX_PCM_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
{"SEC_AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3324,6 +3400,7 @@
{"SEC_AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SEC_AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"SEC_AUX_PCM_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX_Voice Mixer"},
{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3331,6 +3408,7 @@
{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"HDMI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"HDMI_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
{"HDMI", NULL, "HDMI_DL_HL"},
@@ -3339,6 +3417,7 @@
{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"MI2S_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
@@ -3398,6 +3477,16 @@
{"LSM1 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"},
{"LSM_UL_HL", NULL, "LSM1 MUX"},
+ {"QCHAT_Tx Mixer", "PRI_TX_QCHAT", "PRI_I2S_TX"},
+ {"QCHAT_Tx Mixer", "SLIM_0_TX_QCHAT", "SLIMBUS_0_TX"},
+ {"QCHAT_Tx Mixer", "INTERNAL_BT_SCO_TX_QCHAT", "INT_BT_SCO_TX"},
+ {"QCHAT_Tx Mixer", "AFE_PCM_TX_QCHAT", "PCM_TX"},
+ {"QCHAT_Tx Mixer", "AUX_PCM_TX_QCHAT", "AUX_PCM_TX"},
+ {"QCHAT_Tx Mixer", "SEC_AUX_PCM_TX_QCHAT", "SEC_AUX_PCM_TX"},
+ {"QCHAT_Tx Mixer", "MI2S_TX_QCHAT", "MI2S_TX"},
+ {"QCHAT_Tx Mixer", "PRI_MI2S_TX_QCHAT", "PRI_MI2S_TX"},
+ {"QCHAT_UL", NULL, "QCHAT_Tx Mixer"},
+
{"INT_FM_RX", NULL, "INTFM_DL_HL"},
{"INTFM_UL_HL", NULL, "INT_FM_TX"},
{"AUX_PCM_RX", NULL, "AUXPCM_DL_HL"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 4ce0db5..10be150 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -81,6 +81,7 @@
MSM_FRONTEND_DAI_DTMF_RX,
MSM_FRONTEND_DAI_LSM1,
MSM_FRONTEND_DAI_VOICE2,
+ MSM_FRONTEND_DAI_QCHAT,
MSM_FRONTEND_DAI_MAX,
};
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index bcaf58f..1074d76 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -51,7 +51,7 @@
.fifo_size = 0,
};
-static int is_volte(struct msm_voice *pvolte)
+static bool is_volte(struct msm_voice *pvolte)
{
if (pvolte == &voice_info[VOLTE_SESSION_INDEX])
return true;
@@ -59,7 +59,7 @@
return false;
}
-static int is_voice2(struct msm_voice *pvoice2)
+static bool is_voice2(struct msm_voice *pvoice2)
{
if (pvoice2 == &voice_info[VOICE2_SESSION_INDEX])
return true;
@@ -67,6 +67,14 @@
return false;
}
+static bool is_qchat(struct msm_voice *pqchat)
+{
+ if (pqchat == &voice_info[QCHAT_SESSION_INDEX])
+ return true;
+ else
+ return false;
+}
+
static uint32_t get_session_id(struct msm_voice *pvoc)
{
uint32_t session_id = 0;
@@ -75,6 +83,8 @@
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
else if (is_voice2(pvoc))
session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+ else if (is_qchat(pvoc))
+ session_id = voc_get_session_id(QCHAT_SESSION_NAME);
else
session_id = voc_get_session_id(VOICE_SESSION_NAME);
@@ -120,6 +130,10 @@
voice = &voice_info[VOICE2_SESSION_INDEX];
pr_debug("%s: Open Voice2 Substream Id=%s\n",
__func__, substream->pcm->id);
+ } else if (!strncmp("QCHAT", substream->pcm->id, 5)) {
+ voice = &voice_info[QCHAT_SESSION_INDEX];
+ pr_debug("%s: Open QCHAT Substream Id=%s\n",
+ __func__, substream->pcm->id);
} else {
voice = &voice_info[VOICE_SESSION_INDEX];
pr_debug("%s: Open VOICE Substream Id=%s\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
index 5425c46..f199be6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
@@ -17,6 +17,7 @@
VOICE_SESSION_INDEX,
VOLTE_SESSION_INDEX,
VOICE2_SESSION_INDEX,
+ QCHAT_SESSION_INDEX,
VOICE_SESSION_INDEX_MAX,
};
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 01eb51c..7243f19 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -208,6 +208,9 @@
} else if (session_id ==
common.voice[VOC_PATH_VOLTE_PASSIVE].session_id) {
session_name = VOLTE_SESSION_NAME;
+ } else if (session_id ==
+ common.voice[VOC_PATH_QCHAT_PASSIVE].session_id) {
+ session_name = QCHAT_SESSION_NAME;
} else if (session_id == common.voice[VOC_PATH_FULL].session_id) {
session_name = VOIP_SESSION_NAME;
}
@@ -227,6 +230,9 @@
else if (!strncmp(name, "VoLTE session", 13))
session_id =
common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
+ else if (!strncmp(name, "QCHAT session", 13))
+ session_id =
+ common.voice[VOC_PATH_QCHAT_PASSIVE].session_id;
else
session_id = common.voice[VOC_PATH_FULL].session_id;
@@ -258,6 +264,10 @@
v = &common.voice[VOC_PATH_FULL];
break;
+ case QCHAT_SESSION_VSID:
+ v = &common.voice[VOC_PATH_QCHAT_PASSIVE];
+ break;
+
case ALL_SESSION_VSID:
break;
@@ -294,6 +304,10 @@
idx = VOC_PATH_FULL;
break;
+ case QCHAT_SESSION_VSID:
+ idx = VOC_PATH_QCHAT_PASSIVE;
+ break;
+
case ALL_SESSION_VSID:
idx = MAX_VOC_SESSIONS - 1;
break;
@@ -313,11 +327,6 @@
NULL : &common.voice[idx]);
}
-static bool is_voice_session(u32 session_id)
-{
- return (session_id == common.voice[VOC_PATH_PASSIVE].session_id);
-}
-
static bool is_voip_session(u32 session_id)
{
return (session_id == common.voice[VOC_PATH_FULL].session_id);
@@ -333,6 +342,11 @@
return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
}
+static bool is_qchat_session(u32 session_id)
+{
+ return (session_id == common.voice[VOC_PATH_QCHAT_PASSIVE].session_id);
+}
+
static bool is_voc_state_active(int voc_state)
{
if ((voc_state == VOC_RUN) ||
@@ -375,6 +389,7 @@
common.voice[VOC_PATH_VOLTE_PASSIVE].session_id = VOLTE_SESSION_VSID;
common.voice[VOC_PATH_VOICE2_PASSIVE].session_id = VOICE2_SESSION_VSID;
common.voice[VOC_PATH_FULL].session_id = VOIP_SESSION_VSID;
+ common.voice[VOC_PATH_QCHAT_PASSIVE].session_id = QCHAT_SESSION_VSID;
}
static int voice_apr_register(void)
@@ -499,10 +514,8 @@
pr_err("%s: apr_mvm is NULL.\n", __func__);
return -EINVAL;
}
- pr_debug("%s: VoLTE command to MVM\n", __func__);
- if (is_volte_session(v->session_id) ||
- is_voice_session(v->session_id) ||
- is_voice2_session(v->session_id)) {
+ pr_debug("%s: Send Dual Control command to MVM\n", __func__);
+ if (!is_voip_session(v->session_id)) {
mvm_handle = voice_get_mvm_handle(v);
mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
APR_MSG_TYPE_SEQ_CMD,
@@ -576,9 +589,7 @@
/* send cmd to create mvm session and wait for response */
if (!mvm_handle) {
- if (is_voice_session(v->session_id) ||
- is_volte_session(v->session_id) ||
- is_voice2_session(v->session_id)) {
+ if (!is_voip_session(v->session_id)) {
mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
@@ -603,6 +614,10 @@
strlcpy(mvm_session_cmd.mvm_session.name,
VOICE2_SESSION_VSID_STR,
sizeof(mvm_session_cmd.mvm_session.name));
+ } else if (is_qchat_session(v->session_id)) {
+ strlcpy(mvm_session_cmd.mvm_session.name,
+ QCHAT_SESSION_VSID_STR,
+ sizeof(mvm_session_cmd.mvm_session.name));
} else {
strlcpy(mvm_session_cmd.mvm_session.name,
"default modem voice",
@@ -665,9 +680,7 @@
}
/* send cmd to create cvs session */
if (!cvs_handle) {
- if (is_voice_session(v->session_id) ||
- is_volte_session(v->session_id) ||
- is_voice2_session(v->session_id)) {
+ if (!is_voip_session(v->session_id)) {
pr_debug("%s: creating CVS passive session\n",
__func__);
@@ -693,6 +706,10 @@
strlcpy(cvs_session_cmd.cvs_session.name,
VOICE2_SESSION_VSID_STR,
sizeof(cvs_session_cmd.cvs_session.name));
+ } else if (is_qchat_session(v->session_id)) {
+ strlcpy(cvs_session_cmd.cvs_session.name,
+ QCHAT_SESSION_VSID_STR,
+ sizeof(cvs_session_cmd.cvs_session.name));
} else {
strlcpy(cvs_session_cmd.cvs_session.name,
"default modem voice",
@@ -881,7 +898,9 @@
}
}
- if (is_voip_session(v->session_id) || v->voc_state == VOC_ERROR) {
+ if (is_voip_session(v->session_id) ||
+ is_qchat_session(v->session_id) ||
+ v->voc_state == VOC_ERROR) {
/* Destroy CVS. */
pr_debug("%s: CVS destroy session\n", __func__);
@@ -4551,6 +4570,11 @@
v = voice_get_session(session_id);
if (v != NULL)
v->voc_state = VOC_ERROR;
+
+ session_id = voc_get_session_id(QCHAT_SESSION_NAME);
+ v = voice_get_session(session_id);
+ if (v != NULL)
+ v->voc_state = VOC_ERROR;
} else {
pr_debug("%s: Reset event received in Voice service\n",
__func__);
@@ -4694,6 +4718,11 @@
v = voice_get_session(session_id);
if (v != NULL)
v->voc_state = VOC_ERROR;
+
+ session_id = voc_get_session_id(QCHAT_SESSION_NAME);
+ v = voice_get_session(session_id);
+ if (v != NULL)
+ v->voc_state = VOC_ERROR;
} else {
pr_debug("%s: Reset event received in Voice service\n",
__func__);
@@ -4966,6 +4995,11 @@
v = voice_get_session(session_id);
if (v != NULL)
v->voc_state = VOC_ERROR;
+
+ session_id = voc_get_session_id(QCHAT_SESSION_NAME);
+ v = voice_get_session(session_id);
+ if (v != NULL)
+ v->voc_state = VOC_ERROR;
} else {
pr_debug("%s: Reset event received in Voice service\n",
__func__);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index d36beda..1e9c813 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1309,7 +1309,7 @@
void *buf;
};
-#define MAX_VOC_SESSIONS 4
+#define MAX_VOC_SESSIONS 5
struct common_data {
/* these default values are for all devices */
@@ -1372,18 +1372,22 @@
#define VOC_PATH_FULL 1
#define VOC_PATH_VOLTE_PASSIVE 2
#define VOC_PATH_VOICE2_PASSIVE 3
+#define VOC_PATH_QCHAT_PASSIVE 4
#define MAX_SESSION_NAME_LEN 32
#define VOICE_SESSION_NAME "Voice session"
#define VOIP_SESSION_NAME "VoIP session"
#define VOLTE_SESSION_NAME "VoLTE session"
#define VOICE2_SESSION_NAME "Voice2 session"
+#define QCHAT_SESSION_NAME "QCHAT session"
#define VOICE2_SESSION_VSID_STR "10DC1000"
+#define QCHAT_SESSION_VSID_STR "10803000"
#define VOICE_SESSION_VSID 0x10C01000
#define VOICE2_SESSION_VSID 0x10DC1000
#define VOLTE_SESSION_VSID 0x10C02000
#define VOIP_SESSION_VSID 0x10004000
+#define QCHAT_SESSION_VSID 0x10803000
#define ALL_SESSION_VSID 0xFFFFFFFF
#define VSID_MAX ALL_SESSION_VSID